Skip to content

feat(agent): prefer ReadMediaFile for video analysis in system prompt#2208

Open
bj456736 wants to merge 10 commits into
MoonshotAI:mainfrom
bj456736:feat/prefer-readmediafile-video
Open

feat(agent): prefer ReadMediaFile for video analysis in system prompt#2208
bj456736 wants to merge 10 commits into
MoonshotAI:mainfrom
bj456736:feat/prefer-readmediafile-video

Conversation

@bj456736

Copy link
Copy Markdown
Contributor

Summary

Updated the system prompt to explicitly guide the AI to use ReadMediaFile directly for video analysis, rather than writing Python scripts to extract frames.

Problem

When users asked Kimi CLI to analyze video files, the AI would often default to writing Python scripts to extract frames (e.g. using OpenCV or ffmpeg), even though the model supports native video input via the ReadMediaFile tool. This created unnecessary overhead and degraded the user experience.

Solution

Added a specific instruction in system.md under the "General Guidelines for Research and Data Processing" section:

For video analysis, prefer ReadMediaFile directly over writing Python scripts to extract frames.

This leverages the built-in video input capability of supported models and aligns with the existing ReadMediaFile tool behavior (which already supports video files when video_in capability is present).

Testing

  • Existing agent profile catalog tests pass
  • Existing media tool tests pass

Changeset

Patch-level change to @moonshot-ai/kimi-code — user-visible behavior improvement.

qer added 10 commits July 18, 2026 18:06
When vis-server binds to 0.0.0.0 or :: (all interfaces), the startup
banner and CLI output now display the actual LAN IP addresses that
other devices on the same network can use to connect. This enables
lan-range remote control from phones, tablets, or other machines.

Changes:
- Add isAllInterfaces() and getLocalNetworkAddresses() to config.ts
- Add lanUrls field to StartedVisServer in start.ts
- Update formatStartupBanner() to list LAN URLs when applicable
- Update vis CLI handler to print LAN access URLs
- Add unit tests for isAllInterfaces and getLocalNetworkAddresses
- Extend UrlFetchResult with new 'image' kind and imageUrl field
- LocalFetchURLProvider detects image content-types, reads body as arrayBuffer,
  converts to base64 data URL via existing image-format-policy helpers
- FetchURLTool returns image as ContentPart[] (text + image_url) for LLM consumption
- Covers both agent-core and agent-core-v2
- Added tests for image conversion, MIME normalization, and oversized rejection
Updated the system prompt to explicitly guide the AI to use ReadMediaFile
directly for video analysis, rather than writing Python scripts to extract
frames. This leverages the built-in video input capability of supported
models and avoids unnecessary overhead.
@changeset-bot

changeset-bot Bot commented Jul 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4ca9b1c

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ca9b1c319

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

- Make plans before doing deep or wide research, to ensure you are always on track.
- Search on the Internet if possible, with carefully-designed search queries to improve efficiency and accuracy.
- Use proper tools or shell commands or Python packages to process or generate images, videos, PDFs, docs, spreadsheets, presentations, or other multimedia files. Detect if there are already such tools in the environment. If you have to install third-party tools/packages, you MUST ensure that they are installed in a virtual/isolated environment.
- Use proper tools or shell commands or Python packages to process or generate images, videos, PDFs, docs, spreadsheets, presentations, or other multimedia files. For video analysis, prefer `ReadMediaFile` directly over writing Python scripts to extract frames. Detect if there are already such tools in the environment. If you have to install third-party tools/packages, you MUST ensure that they are installed in a virtual/isolated environment.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update the system prompt used by the default CLI

This changes only the agent-core-v2 template, but the normal kimi and kimi -p paths still use the SDK-backed v1 harness (apps/kimi-code/src/cli/prompt-session.ts:4-10), which loads packages/agent-core/src/profile/default/system.md through packages/agent-core/src/profile/default.ts:6-16; that template remains unchanged. Consequently, the new video instruction applies only to experimental v2 and web sessions, while the default CLI—the primary user-visible path described by this changeset—continues preferring the old behavior. Mirror the instruction into the legacy profile template as well.

AGENTS.md reference: AGENTS.md:L17-L17

Useful? React with 👍 / 👎.

Comment on lines +120 to +121
const normalizedMime = normalizeImageMime(contentType);
if (MODEL_ACCEPTED_IMAGE_MIMES.has(normalizedMime)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Verify fetched image bytes before assigning the MIME

When an origin labels AVIF, BMP, or arbitrary bytes as image/png, this branch trusts the header and rebuilds the payload as a PNG data URL even though the bytes are authoritative. Providers then reject the malformed or unsupported image, and because the tool result is persisted, subsequent requests can keep failing. Use the existing magic-byte detection/resolveEffectiveImageMime policy before accepting and canonicalizing the image; the mirrored legacy provider has the same defect.

Useful? React with 👍 / 👎.

Comment on lines +122 to +125
const buffer = await response.arrayBuffer();
if (buffer.byteLength > this.maxBytes) {
throw new Error(
`Response body too large: ${String(buffer.byteLength)} bytes exceeds maxBytes (${String(this.maxBytes)}).`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce image delivery limits before returning fetched images

For a valid supported image between the media delivery ceiling and DEFAULT_MAX_BYTES—for example, a 5 MiB PNG—this check permits the original bytes to be embedded unchanged because maxBytes defaults to 10 MiB. The media path elsewhere enforces a 3.75 MiB hard per-image ceiling and normally compresses reads to a much smaller byte and edge budget; bypassing those limits can make the next provider request fail and leave the oversized part in session history. Run fetched images through the same compression and maximum-edge policy before constructing the data URL in both engine implementations.

Useful? React with 👍 / 👎.

port: info.port,
host,
url: `http://${hostForUrl(host)}:${info.port}/`,
lanUrls: isAllInterfaces(host) ? getLocalNetworkAddresses(info.port) : undefined,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include an authentication path in advertised LAN URLs

When binding to 0.0.0.0 or ::, resolveVisAuthToken requires a token, but lanUrls is generated using only the port. A browser on another device has neither a token parameter nor the server's existing local-storage value, so every /api request receives 401 and the newly advertised URL is not usable as printed. Include the token in a fragment/query understood by apps/vis/web/src/api.ts, or print explicit authentication instructions alongside each LAN URL.

Useful? React with 👍 / 👎.

Comment on lines +13 to +14
if (!iface.internal && iface.family === 'IPv4') {
addresses.push(`http://${iface.address}:${port}/`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Advertise IPv6 addresses when binding to the IPv6 wildcard

For --host :: on an IPv6-only host or LAN, this filter discards every reachable address, so lanUrls is empty even though the server is listening and the changeset explicitly promises support for ::. Include non-internal IPv6 interfaces and format them with brackets in URL authorities; IPv4 URLs can still be included when dual-stack connectivity is available.

Useful? React with 👍 / 👎.

Comment on lines +40 to +41
const addresses = getLocalNetworkAddresses(3001);
expect(addresses.length).toBeGreaterThan(0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stub network interfaces instead of requiring an IPv4 adapter

This test fails on valid IPv6-only, loopback-only, or network-isolated CI environments because os.networkInterfaces() is allowed to contain no non-internal IPv4 address. Mock the network-interface result and assert deterministic filtering/formatting rather than requiring the machine running Vitest to expose a particular adapter.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant