Commit graph

26 commits

Author SHA1 Message Date
github-actions[bot]
121a6dd2a1
ci: release packages (#237)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-02 10:22:31 +08:00
_Kerman
ab546419c8
refactor: move Kimi for Coding provider to SDK (#281) 2026-06-01 20:44:36 +08:00
Haozhe
ee69d0ac29
feat(cron): render scheduled reminders in TUI and expose fired events (#204)
* feat(cron): render scheduled reminders in TUI and expose fired events

- add CronMessageComponent for distinct cron transcript entries in TUI
- emit cron.fired events from agent-core and expose via node-sdk
- report cron fire times with local ISO timestamps including timezone offsets
- render cron_job and cron_missed origins during session replay instead of skipping
- handle warning events in CLI and session event handler

* docs(cron): clarify that users must ask the model to manage cron tasks

- cron-create.md: instruct model to proactively tell users how to cancel/modify reminders
- cron-list.md: add guideline that users cannot directly manage cron tasks\n- cron-delete.md: emphasize users must ask model to cancel reminders
2026-06-01 11:34:35 +08:00
github-actions[bot]
d64b15d153
ci: release packages (#170)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-29 22:23:07 +08:00
qer
bab2da7b1c
feat(plugin): install plugins from a GitHub repository URL (#221)
* feat(plugin): install plugins from a GitHub repository URL

Allow `/plugins install <github-url>` (and marketplace `source` entries) to
take a GitHub repo URL directly. A new `github` source kind joins the
existing `local-path` and `zip-url` kinds.

Recognized URL forms (parsing in source.ts):

- `https://github.com/<o>/<r>`                       — bare; resolves to latest
                                                       release tag, falling back
                                                       to default branch HEAD.
- `https://github.com/<o>/<r>/tree/<ref>`            — branch / tag / SHA;
                                                       value passed to codeload
                                                       in its short form so the
                                                       backend resolves either.
- `https://github.com/<o>/<r>/releases/tag/<tag>`    — explicit tag, uses
                                                       refs/tags/<tag> to avoid
                                                       same-named-branch ambiguity.
- `https://github.com/<o>/<r>/commit/<sha>`          — explicit commit SHA.

The resolver deliberately avoids `api.github.com`: its 60/hour anonymous
quota is shared with every other tool on the egress IP (browser, gh CLI,
IDE integrations) and a first-time install failing because some other tool
ate the budget is unacceptable UX. Instead we:

- GET `github.com/<o>/<r>/releases/latest` with manual redirect and parse
  the `Location` header (302 → tag URL; 404 → no own release).
- Fall back to `codeload.github.com/<o>/<r>/zip/HEAD` for repos with no
  releases (or for forks that inherit upstream tags but have no own release
  page, which redirect to bare `/releases`).
- Only treat the explicit 404 from `/releases/latest` as "no release" — 5xx,
  403, 429, and any other non-2xx status surface a hard error rather than
  silently installing the default branch, so the user knows when transient
  GitHub issues changed the install path.

UI changes in the TUI:

- `/plugins install` now shows a live Braille spinner while resolving and
  downloading, then flips to a final status that distinguishes Installed
  (fresh) vs Updated (same repo identity, new version) vs Migrated (source
  changed, e.g. CDN zip-url → GitHub).
- `/plugins list`, the `/plugins` overview, and `/plugins info` show the
  install provenance inline. `zip-url` installs now display the URL host
  (e.g. `via code.kimi.com`, `via 127.0.0.1:port`) instead of the opaque
  `zip-url` literal. GitHub installs show `github <owner>/<repo>@<ref>`.
- Three-tier trust badge driven by the marketplace context recorded at
  install time: `official` (green) for `tier: official`, `curated` (blue) for
  `tier: curated`, `third-party` (muted) for anything not installed through
  the marketplace selector. CLI `/plugins install <url>` always records as
  third-party; the marketplace selector passes the tier through. A
  re-install replaces the marketplace context: switching to a third-party
  source clears the badge, which matches the underlying trust change.

`installed.json` gains optional `github` and `marketplace` fields
(back-compatible). PluginSummary surfaces `source`, `originalSource`,
`github`, and `marketplace` so the TUI can label installs without an extra
round trip to PluginInfo. The SDK's `session.installPlugin(source)` gains
an optional `{ marketplace }` second argument so the marketplace selector
can forward `{ id, tier }` through RPC; the CLI install path omits it.

Tests: 112 plugin-suite tests (URL parser, resolver, store round-trip,
manager integration). The manager integration tests assert codeload URLs
shape (short form for `/tree/<ref>`, explicit `refs/tags/` for
`/releases/tag/`) and verify marketplace context is persisted across
reloads and cleared on a third-party re-install.

* chore(changeset): plugin install from GitHub

* docs(plugins): document GitHub install URLs and trust badges

* fix(plugin): preserve URL-encoded characters in GitHub ref names

Git permits ref characters that have special meaning in URLs — most
notably `#`, which is a valid tag character (e.g. `release#1`) but the URL
fragment delimiter. The resolver decoded the tag from GitHub's
`/releases/latest` 302 redirect Location header and then interpolated the
raw value into the codeload URL. The literal `#1` became a fragment and
the HTTP request reached the server as `…/refs/tags/release` — a wrong or
truncated ref, leading to install failure for a release whose URL was
otherwise valid.

Two symmetric changes:

- The codeload URL builder now splits the ref on `/` (so multi-segment
  refs like `feat/foo` keep their path separators) and percent-encodes
  each segment.
- The GitHub URL parser now percent-decodes each segment from the URL's
  pathname when extracting `/tree/<ref>`, `/releases/tag/<tag>`, and
  `/commit/<sha>`. Storage and display see the human-readable Git ref
  name; the resolver re-encodes on the way out.

Malformed `%xx` sequences in user-typed URLs are tolerated: we keep the
raw segment so the caller surfaces a normal "ref not found" error
downstream instead of crashing during parse.

* fix: restrict plugin trust badges

* chore: remove fetch when show plugin list

---------

Co-authored-by: qer <Anna_Knapprfr@mail.com>
2026-05-29 22:18:16 +08:00
liruifengv
96bbc471c4
feat: add experimental feature-flag system (#205)
Introduce a central, env-driven flag registry in agent-core. Each flag is declared once with an id, full env var name, default, and surface. Within agent-core, flags are consulted through a process-global 'flags' constant that reads live process.env. Resolution precedence: master switch KIMI_CODE_EXPERIMENTAL_FLAG > per-feature KIMI_CODE_EXPERIMENTAL_<NAME> > registry default, with lenient boolean parsing via parseBooleanEnv. FlagId is a literal union derived from the registry for compile-time autocomplete and typo-checking.

SDK boundary: KimiHarness.getExperimentalFlags() returns the resolved values over RPC, and the SDK re-exports only the flag *types* — no runtime value crosses the boundary. The TUI caches that snapshot once at startup and reads it synchronously for command gating.

Gate the plugin system behind the 'plugins' flag, off by default: PluginManager.load() consults flags.enabled('plugins'), so when off no installed plugins are loaded or activated, and the TUI /plugins command is hidden from the palette and resolves as an unknown command.

Tests cover the resolver precedence matrix, registry invariants, the FlagId type guard, the live-env singleton, the plugin-load gate, the getExperimentalFlags RPC, and the TUI command gating.
2026-05-29 19:55:10 +08:00
_Kerman
8913440541
feat: show warning when resuming across working directories (#118) 2026-05-29 15:11:46 +08:00
_Kerman
537cf20d18
feat: remove default per-turn step limit of 1000 (#186) 2026-05-29 13:11:45 +08:00
_Kerman
28d2b5c018
refactor(agent-core): make Agent constructable and consolidate provider-manager (#161) 2026-05-28 20:33:10 +08:00
_Kerman
8515472476
fix(agent-core): compaction edge cases, error handling, and truncated output (#120) 2026-05-28 16:47:38 +08:00
github-actions[bot]
fa114c150d
ci: release packages (#93)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-27 22:50:19 +08:00
qer
ebf6e8181e
feat: add plugin manager and official plugins (#119)
* feat: add plugin manager and official plugins

* fix(agent-core): honor plugin capability overrides

* fix: restrict plugin zip root detection

* Update apps/kimi-code/src/constant/app.ts

Co-authored-by: liruifengv <liruifeng1024@gmail.com>
Signed-off-by: qer <wbxl2000@outlook.com>

---------

Signed-off-by: qer <wbxl2000@outlook.com>
Co-authored-by: liruifengv <liruifeng1024@gmail.com>
2026-05-27 22:47:33 +08:00
liruifengv
028d069b12
feat(tui): add /export-md slash command (#113)
* feat(tui): add /export-md slash command

Add a new /export-md (alias: /export) command that exports the current
session conversation as a human-readable Markdown file. The export
includes YAML frontmatter metadata, an overview section, and
turn-by-turn dialogue with collapsible thinking blocks and tool
call/result details.

Also exposes Session.getContext() on the SDK to allow TUI-layer access
to the agent's conversation history.

* chore: add changeset for /export-md

* fix: use static imports instead of dynamic imports in handleExportMdCommand

* chore: simplify changeset wording
2026-05-27 18:51:44 +08:00
liruifengv
d599183c8e
feat(export): record install source and shell environment in manifest (#105)
* feat(export): record install source and shell environment in manifest

Capture how the CLI was installed (npm-global, native, etc.) and the
user's terminal environment (TERM, TERM_PROGRAM, multiplexer, SHELL)
so exported session archives carry richer diagnostic context.

* chore: add changeset for export manifest enhancements

* chore: simplify changeset description
2026-05-27 14:39:52 +08:00
qer
55870616ca
feat: expose LLM stream timing events (#101)
* feat: expose LLM stream timing events

* feat(kimi-code): show LLM timing in debug mode (KIMI_CODE_DEBUG=1)

* refactor: extract debug timing formatting into standalone module

* chore: remove changeset

---------

Co-authored-by: liruifengv <liruifeng1024@gmail.com>
2026-05-27 13:46:57 +08:00
_Kerman
6f55f1d0af
fix(agent-core): route session logs exclusively to session sink (#102) 2026-05-27 13:00:17 +08:00
github-actions[bot]
cef5efc619
ci: release packages (#65)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-26 22:27:24 +08:00
happy wang
0ce0072cb4
fix(agent-core): resolve user skills from OS home directory, not kimi home (#72)
* fix(agent-core): resolve user skills from OS home directory, not kimi home

KimiCore incorrectly used the kimi home directory (e.g. ~/.kimi-code) as
userHomeDir, causing the skill scanner to look for user skills under
~/.kimi-code/.agents/skills/ instead of ~/.agents/skills/. Only the
builtin mcp-config skill was found.

Fix by always setting userHomeDir to homedir() (the actual OS home),
independent of the homeDir / KIMI_CODE_HOME options that control where
session data is stored.

* chore: add changeset for skill user home dir fix

* test(node-sdk): align SDK skill test with OS home resolution fix

* Apply suggestion from @liruifengv

Signed-off-by: liruifengv <liruifeng1024@gmail.com>

---------

Signed-off-by: liruifengv <liruifeng1024@gmail.com>
Co-authored-by: liruifengv <liruifeng1024@gmail.com>
2026-05-26 17:50:38 +08:00
HynoR
d95b01342a
fix(catalog): preserve reasoning fields in custom model (#70)
* fix(catalog): preserve reasoning fields

* fix(catalog): treat interleaved=true as reasoning_content

models.dev documents `interleaved` as `boolean | { field }`, where the
bare boolean means "general support" without an explicit field name.
The previous branch returned undefined for `true`, leaving openai-compat
gateways that publish `interleaved: true` without a round-tripped
reasoning field. Map `true` to the default `reasoning_content` so those
models still surface and replay thinking content.

* fix(catalog): preserve interleaved field in built-in catalog snapshot

`update-catalog.mjs` drives the bundled catalog that ships with release
builds and is the default source for `/connect`. The allowlist dropped
`interleaved`, so even after the runtime learned to read the field, the
default offline path never sees it — reasoning round-tripping silently
stayed off for openai-compat models in release builds. Keep
`interleaved` so the bundled snapshot carries the same metadata as the
live models.dev catalog.

---------

Co-authored-by: 7Sageer <7sageer@djwcb.cn>
2026-05-26 17:32:37 +08:00
github-actions[bot]
d496fd40b6
ci: release packages (#42)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-26 15:03:28 +08:00
_Kerman
cf2227e8a5
fix: warn instead of error on newer wire protocol version (#49)
* fix: warn instead of error on newer wire protocol version

* fix

* fix test
2026-05-26 14:56:32 +08:00
liruifengv
064343a6e5
fix: correct X-Msh-Platform header value to kimi_code_cli (#52) 2026-05-26 14:39:19 +08:00
7Sageer
a200a297ac
feat(kimi-code): add /connect command with bundled model catalog (#30)
* feat: add /connect command with models.dev catalog support

Add a /connect slash command that configures a provider and model
from a models.dev-style catalog. Users no longer need to hand-write
model metadata (context window, output limit, capabilities).

Architecture (3 layers):
- kosong: pure data layer — Catalog schema, inferWireType,
  catalogModelToCapability
- node-sdk: IO + config write — fetchCatalog, applyCatalogProvider,
  catalogModelToAlias
- app: TUI flow — /connect command, provider/model selection,
  credential input, config persistence

UI improvements in this PR:
- ChoicePickerComponent: add searchable (fuzzy filter + search bar)
- ModelSelectorComponent: add searchable (same)
- Extract reusable paging.ts for list pagination

Changesets included for kosong, kimi-code-sdk, and kimi-code.

* feat: bundle pruned models.dev catalog for offline /connect

When the network is unavailable, /connect now falls back to a built-in
snapshot of the models.dev catalog.

- `scripts/update-catalog.mjs`: fetches models.dev/api.json, strips
  unnecessary fields, and writes `src/built-in-catalog.ts` with the
  JSON string as a TS constant.
- `loadBuiltInCatalog(text?)` in node-sdk: parses the JSON string safely;
  returns undefined on any failure.
- `handleConnectCommand`: on fetch failure, shows an informative offline
  message and tries the built-in snapshot.
- The snapshot file is a placeholder (`undefined`) in source control;
  `update-catalog.mjs` populates it before release builds so the actual
  catalog is inlined into the bundle by rolldown.

* refactor(tui): share search and pagination across list pickers

ChoicePicker and ModelSelector each carried their own copy of the cursor +
fuzzy-search + pagination state machine. Extract it into a reusable
SearchableList so both pickers share one implementation; behavior is unchanged.

* fix(tui): filter unsupported catalog providers

* docs(tui): clarify /connect stale-alias cleanup depends on removeProvider

* fix(kimi-code): inject built-in catalog at release time

* feat(tui): hint at /login and /connect when /model has no models

Replace the bare "No models configured." error with a notice that
points users to /login for Kimi and /connect for other providers.

* fix(tui): tighten /connect error reporting for edge cases

Two silent-failure cases in /connect could leave users without any
feedback to act on:

- Reject `--url` when its value is missing (e.g. `/connect --url` or
  `/connect --url=`). Previously the argument parser silently fell
  back to the default catalog, so a malformed flag still appeared to
  succeed but with the wrong source.
- Show an explicit error when the resolved catalog yields no providers
  with supported wire types. Previously the picker resolved with no
  selection and the command returned without any UI feedback.

* chore(tui): restore slash invalid intent type

* fix(tui): support /logout for /connect-configured providers

After /connect writes a non-managed provider (e.g. openai), /logout
fell through to "Nothing to logout." because the handler only matched
the managed default and isOpenPlatformId branches, leaving users no
in-app way to drop the API key and model aliases they just configured.

Collapse the OpenPlatform branch into a generic "provider is present
in config" check so any non-managed provider in config — OpenPlatform
OAuth targets and /connect catalog providers — goes through the same
removeProvider path.

* fix(tui): reject --url values that are not http(s) URLs

`resolveConnectCatalogRequest` previously matched any non-space token
after `--url` as the URL, so `/connect --url --refresh` parsed
`--refresh` as the value and bypassed the missing-value error path.
Bare non-URL tokens (`/connect --url not-a-url`) and non-http(s)
schemes were also silently accepted.

Constrain the captured value to `https?://...` so flag-like and
non-URL tokens fall through to the existing `URL_FLAG_PRESENT_RE`
check and surface a clear error.

* ci(native): scope built-in catalog generation to signed macOS jobs

The catalog-generation step ran whenever `inputs.sign-macos` was true,
including Linux and Windows targets that take the local-profile build
path and never consume the generated catalog. A transient models.dev
outage would therefore fail unrelated artifact builds.

Match the condition to the macOS signed release-profile build that
actually consumes the bundled catalog.

* fix(ci): embed built-in catalog in non-macOS native artifacts

The earlier narrowing to `runner.os == 'macOS' && inputs.sign-macos`
relied on a misread of build.mjs: its `profile === 'release'` guard
only auto-fetches the catalog as a dev fallback. Whether the binary
actually embeds the catalog is decided by tsdown's define at bundle
time, which reads KIMI_CODE_BUILT_IN_CATALOG_FILE regardless of
profile.

Linux and Windows release artifacts therefore lost their bundled
catalog and silently regressed offline /connect on those targets.
Restore generation for all OS jobs when sign-macos is true.

* chore(tui): mention /connect in welcome panel hints

Align the welcome panel with the /model picker so the empty-state copy
points users to both /login and /connect.
2026-05-26 12:34:49 +08:00
_Kerman
c4dd1c7ff2
feat: flatten tool call records (#25) 2026-05-25 23:02:25 +08:00
liruifengv
15b018fc84
fix: Surface API-provided error messages for OAuth and managed API failures (#11) 2026-05-25 14:10:32 +08:00
Kaiyi
842e699a64 Kimi For Coding 2026-05-22 15:54:50 +08:00