Commit graph

701 commits

Author SHA1 Message Date
haozhe.yang
ed45cee65d refactor(config): self-register config sections at module load
Move config-section registration out of Service constructors and into
import-time contributions, mirroring the existing registerScopedService
pattern so a section is available as soon as its domain barrel is imported.

- add configSectionContributions collector (module-level, no DI) with
  registerConfigSection / get / _clearForTests
- ConfigRegistry drains the collected contributions on construction
- each owner configSection.ts calls registerConfigSection at top level
  (providers, models, modelCatalog, experimental, thinking/defaultThinking,
  loopControl, permission, hooks, background, microCompaction, cron)
- domain barrels import their configSection to guarantee the side effect
- remove registerSection calls and the now-unused IConfigRegistry injection
  from the 11 owning Services

The KIMI_MODEL_* effective overlay is still registered by modelService and
left for a follow-up.
2026-07-01 22:03:05 +08:00
haozhe.yang
3606488ea2 refactor(agent-core-v2): drop @moonshot-ai/kaos, split IKaos into atoms
Replace the god-object `IKaos` interface and the `@moonshot-ai/kaos`
package dependency with atomic services:

- `IHostEnvironment` (App scope) — memoised OS / shell / path-style /
  home probe; sync fields plus a `ready` promise the composition root
  awaits before seeding Session scopes.
- `IExecContext` (Session scope) — immutable cwd + env-layers seed
  value with `withCwd` / `withEnv` derivations; replaces
  `IKaos.cwd/withCwd/withEnv` and `IKaosFactory`.
- `ISessionAgentFileSystem` / `ISessionProcessRunner` — inline
  `node:fs/promises` and `child_process.spawn` directly; the
  `IKaos.backend` leak that let `profile/context.ts`, `fileTools/glob`
  and `agentFs/runRg` reach around the facades is gone.

Vendor the pure helpers into `src/_base/execEnv/` (`BufferedReadable`,
`decodeTextWithErrors`, `globPatternToRegex`, host-environment probe).
`src/app/kaos/` and `test/kaos/` are deleted; session-lifecycle awaits
`hostEnv.ready` and then seeds `IExecContext` into the child scope.

Rewrites every `@IKaos` consumer:
- `shellTools/bash`, `fileTools/{read,write,edit,glob,grep}`,
  `media/read-media`, `_base/tools/policies/path-access`
- `permissionPolicy/git-cwd-write-approve` and
  `permissionPolicy/git-control-path-access-ask`
- `agent/rpc`, `agent/agentTool`, `agent/profile/{context,profileService}`
- `session/{sessionWarning,workspaceContext}`
- `app/bootstrap` (drops `IBootstrapService.detect()`)
- `fileTools/glob` and `agentFs/runRg` now route rg through
  `ISessionProcessRunner.exec` with per-call `{ cwd }` overrides

`test/tools/fixtures/fake-kaos.ts` is replaced by `fake-exec.ts` with
per-atom factories (`createFakeHostEnvironment`, `createFakeExecContext`,
`createFakeAgentFs`, `createFakeProcessRunner`). Domain-layer registry,
PUML diagram, tsdown externals and `package.json` deps are updated
accordingly.

`packages/kaos/` stays in the workspace — v1, node-sdk and acp-adapter
still depend on it. Only `agent-core-v2` has been detached.
2026-07-01 21:40:46 +08:00
haozhe.yang
e497dd00a4 refactor(agent-core-v2): collapse cron internals into AgentCronService
- Inline SessionCronStore, CronScheduler, and CronPersistence into
  AgentCronService: state lives as private fields, the poll loop uses a
  shared timer, and persistence calls IAtomicDocumentStore directly.
- Drop CronToolManager; the cron tools take IAgentCronService directly,
  matching the background domain.
- Add a generic IntervalTimer to _base/utils and use it for the poll loop.
- Move cron-expr/jitter/clock to the cron root, merge time-format and
  cron-fire-xml into format.ts, and fold the cron types and telemetry
  constants into the contract and service.
2026-07-01 21:35:14 +08:00
haozhe.yang
ea658c26a6 refactor(agent-core-v2): dissolve subagent domain into agentTool + swarm
- remove SubAgentHost / ISessionSubagentHost; a subagent is now a plain
  agent scope created via IAgentLifecycleService and driven through the
  child agent's own turn/loop services
- add IAgentLifecycleService.fork(parentAgentId); startBtw forks main
- move the Agent collaboration tool into the new agentTool domain
  (stateless runChildAgent helpers, no runner class, no subagent service)
- move SubagentBatch + runChildAgentQueued into the swarm domain
- seed IAgentScopeContext (agentId) per agent so the Agent tool and swarm
  can name themselves as the parent
2026-07-01 20:25:11 +08:00
haozhe.yang
f5bebda7d5 refactor(agent-core-v2): drop unused IWSBroadcastService stub
The v2 `WSBroadcastService` was an empty scaffolding class — its
constructor only registered a no-op `event.on(() => {})` and no other
Service or external caller ever resolved `IWSBroadcastService`. In
server-v2 the WS event fan-out (seq/epoch, journaling, replay,
per-connection dispatch) is done by `SessionEventBroadcaster`, a plain
class in the transport layer that consumes `IEventService`,
`IAgentEventSinkService`, `IAgentLifecycleService`, and
`ISessionLifecycleService` directly.

- Remove `WSBroadcastService` impl and its `registerScopedService`
  binding from `app/gateway/gatewayService.ts`.
- Remove `IWSBroadcastService` interface and decorator from
  `app/gateway/gateway.ts`.
- Update the gateway barrel / header comments to stop advertising it,
  and add a note that WS event fan-out is a transport concern owned by
  the edge package.
- Replace the `docs/di.md` "release resources" example, which used the
  removed stub, with `FlagService` — a real Disposable that registers a
  `config.onDidChangeConfiguration` subscription via `_register`.
- Drop the `IWSBroadcastService` entry and the stub-only
  `gateway ..> event : subscribe` edge from
  `docs/di-scope-domains.puml`. The SVG needs to be re-rendered with
  plantuml; not regenerated here.
2026-07-01 20:09:09 +08:00
haozhe.yang
6e8beccba1 feat(dep-graph): quieter refresh, persistent viewport, public surface, search highlight
- plugin: fingerprint the analyzer output (services/edges/unknownTokens,
  excluding generatedAt) and only invalidate the virtual module on real
  content diffs, so ordinary edits no longer trigger a browser reload.
- web viewer: persist the ReactFlow viewport (x/y/zoom) to sessionStorage
  and restore on mount, so reloads no longer snap back to fitView.
- analyzer: expose each service's public interface surface via a new
  optional ServiceNode.publicMembers (methods + property signatures,
  _serviceBrand filtered out), and register PRODUCTION_OVERRIDES so
  bootstrap-seeded bindings resolve to their real backends.
- web viewer: seed node inPorts from publicMembers so uncalled methods
  still render; dim the handle and label of ports with no incoming edge
  so the connected-vs-declared distinction reads at a glance.
- web viewer: extend search to also match publicMembers, and turn search
  into a highlight/dim treatment (matches + neighbors stay bright, the
  rest dim) instead of filtering — matched nodes get a cyan outline
  distinct from the yellow selection outline.
2026-07-01 20:00:24 +08:00
haozhe.yang
b9259abd3f refactor(agent-core-v2): move thinking helpers from config to profile
- Host resolveThinkingEffort/resolveThinkingLevel in the profile domain,
  the owner of the thinking/defaultThinking config sections, so they use
  the authoritative ThinkingConfig from configSection.ts.
- Drop the local ThinkingConfigDefaults structural duplicate that existed
  only to keep config (L2) from importing upward into profile (L4).
- Update profile/profileService consumers and the config barrel, and move
  the test alongside the helpers.
2026-07-01 18:39:01 +08:00
haozhe.yang
b64539ddd7 feat(dep-graph): attribute edges to source and target methods
- analyzer: record fromMethod/toMethod on each EdgeRef, generalize
  event-bus field detection to all DI-injected ctor fields, and
  attribute this.<field>.<method>() and .get(IX).<method>() call sites
- analyzer: seed IAgentScopeContext framework binding so Agent-scope
  edges resolve instead of showing up as unresolved
- web: render per-method in/out ports on nodes, route each edge to the
  matching method handle, size nodes by port count, and show an
  expandable call list in the edge panel
2026-07-01 18:32:46 +08:00
haozhe.yang
ddb3a7609f feat(agent-core-v2): add session lifecycle events and semanticize onDid events
Rename bare `onDidChange` to semantic `onDidChange<Facet>` following the
VSCode event-naming convention (the event name carries what changed), and
carry a payload so consumers know what changed without re-reading:

- IConfigService.onDidChangeConfiguration
- IProviderService.onDidChangeProviders ({ added, removed, changed })
- IModelService.onDidChangeModels ({ added, removed, changed })
- ISessionMetadata.onDidChangeMetadata ({ changed: (keyof SessionMeta)[] })
- ISessionInteractionService.onDidChangePending ({ pending: string[] })

Add ISessionLifecycleService session-lifecycle events (parity with v1):
onDidCreateSession / onDidCloseSession / onDidArchiveSession /
onDidForkSession, fired from create / close / archive / fork.

Add IEventService.onDidPublish: Event<DomainEvent> so the bus matches the
typed Event<T> convention used elsewhere (publish/subscribe retained).

Update tests, examples, and docs to the new names; add payload and
lifecycle-event assertions.
2026-07-01 18:12:58 +08:00
haozhe.yang
4fc8f136c0 refactor(agent-core-v2): drop unused registerSingleton registry
- remove registerSingleton / getSingletonServiceDescriptors / _clearRegistryForTests and their backing registry from _base/di/extensions.ts
- keep InstantiationType, still imported via #/_base/di/extensions across v2
- drop the stale "legacy exports" note for these helpers from v2 docs and the agent-core-dev skill
2026-07-01 17:51:44 +08:00
haozhe.yang
5bdee931e5 feat(agent-core-v2): dep-graph dev viewer + scope lint
Adds a dev-only tool under `scripts/dep-graph/` that statically analyses the
DI service graph and serves it as an interactive React Flow viewer:

- `analyzer/`: ts-morph pass over `src/**/*.ts` extracts every
  `registerScopedService` binding as a node keyed by `${scope}::${token}`,
  then records ctor / accessor / publish / subscribe / emit / on edges. Each
  edge is resolved to the concrete impl visible from the source's scope
  (walking source scope up to App); if no binding is visible the edge is
  marked `unresolved` — the exact signal for a container-construction
  failure. Framework tokens (`IKaos`, `ISessionContext`, …) are seeded so
  they don't sink into false-positive unresolveds.
- `plugin/virtual-dep-graph.ts`: Vite plugin that exposes the analyzer
  output as a `virtual:dep-graph` module, mirrors it to
  `.local/dep-graph.json`, and re-analyses on any `src/**/*.ts` change via
  chokidar with a 200 ms debounce, then invalidates the virtual module for
  HMR.
- `web/`: React + React Flow frontend with dagre auto-layout in RL mode
  (base primitives on the left, facades on the right). Sidebar filters by
  scope / edge kind / domain / search; toggles for `hide orphans` and
  `group by scope` (horizontal App | Session | Agent bands). Isolated
  nodes are pinned to the sink rank so they sit with the base primitives.
- `cli.ts` (`pnpm dep-graph:analyze`): one-shot JSON dump for CI / offline
  inspection.
- `lint.ts` (`pnpm dep-graph:lint`): treats unresolved ctor edges as
  errors (container will crash) and unresolved accessor edges as warnings
  (only safe under an active inner scope). Auto-runs the analyzer when the
  snapshot is stale.

Isolation from deploy: everything lives under `scripts/dep-graph/` and is
never referenced from `src/index.ts`, so `tsdown` doesn't bundle it into
`dist/`. The added `ts-morph`, `vite`, `react`, `react-dom`,
`@vitejs/plugin-react`, `@xyflow/react`, `@dagrejs/dagre`, `tsx`, and
`@types/react*` all land in `devDependencies` — `pnpm install --prod`
skips them.

Also adds `.vite/` to `.gitignore` so Vite's per-package dep pre-bundling
cache isn't tracked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-01 17:19:18 +08:00
haozhe.yang
5fece98c91 refactor(agent-core-v2): group src domains by lifecycle scope
Move src/{domain}/* to src/{scope}/{domain}/* (app/session/agent) so the
directory layout mirrors the DI LifecycleScope tree. Split the three
multi-scope domains so no domain spans two scopes:

- log      -> app/log + session/sessionLog
- question -> session/question + agent/questionTools
- skill    -> app/globalSkillCatalog + session/sessionSkillCatalog + agent/skill

Rewrite every #/ and relative import, module augmentation, vi.mock, and
source-path read; update the package barrel, registerScopedService domain
labels, the domain-layer checker, the dep-graph script, file headers, and
the di-scope-domains map.
2026-07-01 15:11:49 +08:00
haozhe.yang
314e4ef2df Merge remote-tracking branch 'origin/kimi-code-v2' into kimi-code-v2
# Conflicts:
#	packages/agent-core-v2/src/shellTools/shellToolsService.ts
#	packages/agent-core-v2/src/userTool/userToolService.ts
#	packages/agent-core-v2/test/goal/injection.test.ts
#	packages/agent-core-v2/test/harness/agent.ts
#	packages/agent-core-v2/test/profile/config-state.test.ts
#	packages/agent-core-v2/test/session-lifecycle/sessionLifecycle.test.ts
#	packages/agent-core-v2/test/shellTools/shellToolsService.test.ts
#	packages/agent-core-v2/test/skill/plugin-session-start.test.ts
#	packages/agent-core-v2/test/snapshot/events.ts
#	packages/agent-core-v2/test/subagentHost/agent-tool.test.ts
#	packages/agent-core-v2/test/swarm/swarm.test.ts
#	packages/agent-core-v2/test/toolDedup/tool-dedup.test.ts
#	packages/agent-core-v2/test/turn/stubs.ts
#	packages/agent-core-v2/test/turn/turn.test.ts
2026-07-01 13:58:56 +08:00
haozhe.yang
760808abd9 feat(server-v2): add model catalog auto-refresh and remaining wiring
- add config-driven model catalog refresh scheduler (interval / on-start)
- refresh all providers and add the single-provider refresh endpoint
- broadcast model_catalog.changed to session subscribers
- finish wiring route handlers, middleware, and auth services
- align route and websocket tests with the authenticated server model
2026-07-01 13:02:26 +08:00
haozhe.yang
e0f900803a feat(agent-core-v2): wire remaining v1 migration pieces
- add completion budget with 128k compaction output cap and max-output honor
- add config + /update-config hints to the max-steps-per-turn error
- log malformed tool-call JSON parse failures and cover parseToolCallArguments
- add modelCatalog config section (refresh interval / refresh-on-start)
- wire plugin skills + session-start reminders into skill catalog and prompt flow
- add error serialization helpers and error taxonomy coverage
- route messageLegacy cold-session loading through session-lifecycle resume
- add background task detachTimeoutMs option
2026-07-01 13:00:20 +08:00
haozhe.yang
9b2e66b5db feat(agent-core-v2): add session subagent host and Agent tool
- add DefaultSessionSubagentHost with spawn/resume/retry, runQueued swarm
  with a concurrency cap, startBtw side-question agents, cancelAll and the
  subagent.suspended event, onReady on first turn activity, and telemetry
- add the model-facing Agent collaboration tool (foreground/background,
  resume, gated on task tools) with explore git-context injection and a
  summary-continuation handoff
- fire SubagentStart/SubagentStop external hooks and add a registerable
  deny-all permission policy used by side-question agents
2026-07-01 12:56:09 +08:00
haozhe.yang
bfaa75d320 feat(agent-core-v2): load AGENTS.md hierarchy and surface size warning
- add profile/context.ts to load the user- and project-level AGENTS.md
  hierarchy with a 32KB soft budget
- add AgentProfileService.applyProfile as the production entry point that
  assembles SystemPromptContext and renders the profile
- add SessionWarningService as the getSessionWarnings producer, surfacing
  agents-md-oversized instead of silently truncating
- cover loading, applyProfile, and the warning surface with tests
2026-07-01 12:06:20 +08:00
haozhe.yang
8fbd378277 feat(agent-core-v2): add shared rg locator/runner and explore git context
- add agentFs/rgLocator: shared ripgrep resolution (system PATH, then optional
  cached fallback) driven through a caller-supplied RgProbe
- add agentFs/runRg: shared Glob rg subprocess plumbing on IKaos
  (timeout/abort, capped output, two-phase kill, EAGAIN single-thread retry)
- rewrite GlobTool to use the shared locator/runner and track fallbacks
- make Grep resolve rg through the shared locator and emit
  fs_grep_node_fallback telemetry when rg is missing
- add agentFs/gitContext.collectGitContext and prepend a sanitized
  <git-context> block to fresh explore subagent prompts
- add noopTelemetryService for tools constructed outside DI
- cover gitContext, glob, fsService, and fileToolsService with tests
2026-07-01 11:57:25 +08:00
haozhe.yang
cc3422c77a feat(agent-core-v2): add plugin management and consumption plane
- parse kimi.plugin.json / .kimi-plugin/plugin.json manifests
  (skills, sessionStart, mcpServers, hooks, commands)
- install plugins from local paths, zip URLs, and GitHub refs via
  the manager, store, source, archive, and github-resolver modules
- load plugin slash commands from .md files with $ARGUMENTS expansion
- register IPluginService/PluginService (App scope) exposing management
  plus consumption planes: skill roots, session starts, MCP servers, hooks
- add session-start context injector and RPC prompt metadata
- cover manifest, manager, source, archive, github-resolver, commands,
  and session-start injection with tests
2026-07-01 11:52:35 +08:00
_Kerman
ad782ad94b fix: always register Skill tool 2026-07-01 11:50:34 +08:00
haozhe.yang
97874de529 feat(loop): split llm stream timing into client and server phases
- add requestBuild/serverFirstToken and serverDecode/clientConsume fields to LLMStreamTiming and LoopStepEndEvent
- forward the split timing through AgentLoopService event and streamTiming mapping
- inject ILogService into AgentLoopService and emit a per-step 'llm response' log via logStepTiming to attribute slow turns
2026-07-01 11:47:22 +08:00
haozhe.yang
4d103c5d76 feat(server-v2): add auth and request security hardening
- add persistent bearer-token auth (token store, credentials, password hashing)
- gate HTTP and WebSocket (bearer subprotocol) upgrades behind auth
- classify loopback vs non-loopback binds and validate hostnames/origin
- add rate limiting and security headers middleware
- add GUI store service and routes
- add process file locking
2026-07-01 11:44:20 +08:00
_Kerman
e322d3b3f2 fix(agent-core-v2): fix tests 2026-07-01 11:36:56 +08:00
haozhe.yang
1745ea074a docs(agent-core-dev): rename Core scope to App and drop Turn tier
- replace `Core` with `App` across the skill docs and dep-graph.mjs
- drop the `Turn` scope, collapsing the four-tier tree to three (App/Session/Agent)
- update examples, anti-patterns, banned entity-service names, and createCoreScope -> createAppScope
2026-07-01 11:18:46 +08:00
_Kerman
9fed2af01c fix(agent-core-v2): fix tests 2026-07-01 10:54:13 +08:00
haozhe.yang
cd47ef4aff refactor(agent-core-v2): rename scoped services to encode scope
- rename service interfaces and implementations to carry the Session/Agent
  scope prefix and Service suffix (e.g. IApprovalService ->
  ISessionApprovalService, ApprovalService -> SessionApprovalService)
- rename LifecycleScope.Core to App in the DI base
- update DI createDecorator keys to match the new identifiers
- propagate the renames through server-v2 routes/transport, examples, docs,
  and the agent-core-dev skill
2026-07-01 01:05:53 +08:00
haozhe.yang
075262a49d Merge remote-tracking branch 'origin/main' into kimi-code-v2 2026-06-30 21:25:35 +08:00
haozhe.yang
6219fa6866 feat(agent-core-v2): give ContextMessage a stable id
- stamp `msg_<ulid>` on every message entering IContextMemory and persist it
  in the context.splice wire record, so ids survive restore
- carry the provider response id as `providerMessageId` on assistant messages
- thread `promptMessageId` from prompt -> turn -> turn.started ->
  InFlightTurnTracker, so snapshot `current_prompt_id` comes from the native
  path instead of post-hoc enrichment
- project real ids on the wire and look up messages by id; drop the positional
  parseMessageId
- make the v1 prompt_id equal its user message id
2026-06-30 21:25:01 +08:00
Haozhe
ceb27f5e44
feat(server): add GUI store API mirroring localStorage (#1231)
Some checks are pending
CI / build (push) Waiting to run
CI / test (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Release / Release (push) Waiting to run
* feat(server): add GUI store API mirroring localStorage

- add /api/v1/gui/store/* endpoints (getItem/setItem/removeItem/clear/length) mirroring the browser localStorage interface
- add IGuiStoreService persisting opaque string values to ~/.kimi-code/gui.toml via smol-toml with atomic writes and an in-process write lock
- wire protocol schema, service, routes, and DI registration; add e2e tests and update the API surface snapshot

* chore: add changeset for gui store api

* fix(server): harden GUI store key handling and file permissions

- use a null-prototype record and an own-property check so keys that exist on Object.prototype (toString, constructor, __proto__) behave like ordinary keys
- write gui.toml with 0600 permissions so unsent drafts and input history stay private to the owning user
2026-06-30 21:04:59 +08:00
haozhe.yang
db3a7c4f43 fix(server-v2): serve cold session messages from wire transcript
- add MessageLegacyService (agent-core-v2 L7 edge adapter) implementing the
  v1 GET /sessions/{sid}/messages contract on top of the native services
- cold sessions: load + restore the main agent wire log and read the full
  transcript from IReplayBuilderService; live sessions keep reading
  IContextMemory
- rewrite the messages route as a thin adapter over the legacy service
- register the message.not_found (40403) error code in protocol and
  agent-core-v2
2026-06-30 21:02:23 +08:00
qer
aa6b0d065e
feat(web): always show the usage-data opt-out toggle in settings (#1232)
The telemetry toggle was hidden unless the config explicitly set a value, and its on/off mapping treated the default (unset) state as off even though telemetry is enabled by default. Show it always, treat unset/true as on, and rename it with a description and a restart note.
2026-06-30 20:49:35 +08:00
haozhe.yang
37d3953368 fix(server-v2): align /sessions/:tail actions with v1
- forward undo and archive results from ISessionLegacyService instead of
  re-paginating undo in the route and hardcoding the archive response
- drop the AUTH_TOKEN_MISSING error mapping that v1 does not declare
- move the ContextMessage -> Message projection into agent-core-v2 so
  the session legacy service owns the undo response shape
2026-06-30 20:11:42 +08:00
haozhe.yang
05053ee845 fix(server-v2): align GET /api/v1/auth with v1 readiness summary
The v2 readiness probe returned a simplified snapshot: default_model was
hardcoded to null, providers_count counted only oauth providers, and
managed_provider was synthesized from any authenticated provider. Mirror
v1's AuthSummaryService.get() through a new L7 edge adapter.

- add IAuthLegacyService projecting provider/config/oauth state into the
  v1 AuthSummary wire shape; the native IAuthSummaryService keeps serving
  /api/v2 untouched
- default_model reads the configured defaultModel
- providers_count counts every configured provider
- managed_provider reflects managed:kimi-code cached-token state and is
  null when that provider is absent
- ready matches v1 (providers >= 1, default model set, not revoked)
- register authLegacy at L7 in the domain-layer map
2026-06-30 19:54:43 +08:00
qer
5cb80ce879
feat: support plugin slash commands (#1204)
* feat(agent-core): support plugin slash commands

* feat(node-sdk): expose listPluginCommands

* feat(kimi-code): register and dispatch plugin slash commands

* chore: add changeset for plugin commands

* feat(agent-core): activate plugin commands server-side

* feat(node-sdk): add activatePluginCommand

* feat(kimi-code): render plugin command activations compactly

* feat(agent-core): recurse plugin command directories and preserve namespace

* fix(kimi-code): parse nested plugin command names

* fix(agent-core): update prompt metadata for plugin command turns

* fix(kimi-code): replay plugin command turns as command cards

* fix: treat plugin-command origins as real user prompts in undo

* fix(kimi-code): guard model-empty and clear plugin command render ids

* fix: propagate plugin_command to web and vis turn projectors

* fix(kimi-code): refresh plugin commands through auth flow

* fix(kimi-web): render plugin command cards in chat pane

* fix(kimi-web): render plugin command card in desktop chat view

* fix(kimi-code): treat slash-activation cards as transcript turn boundaries

* fix(kimi-code): count slash-activation entries when trimming transcript turns

* fix(kimi-code): preserve plugin command args in undo selector
2026-06-30 19:38:01 +08:00
haozhe.yang
2fc1fbc648 fix(server-v2): resolve workspace branch from .git/HEAD
- read .git/HEAD and peel ref: refs/heads/<branch> to populate branch
- resolve the real git dir through a .git worktree/submodule file
- keep detached HEAD and unreadable files as branch: null
- add branch-resolution tests for slash branches, detached HEAD, and worktrees
2026-06-30 19:30:17 +08:00
Kai
42e37eb898
feat(timing): split TTFT into api-server and client portions (#1228)
* feat(timing): split TTFT into api-server and client portions

Time-to-first-token previously lumped in-process request building
(message serialization, param assembly) together with network + server
latency, making it impossible to tell whether a slow turn was the client
or the API server.

Add an `onRequestSent` hook to kosong's GenerateOptions, fired by every
provider immediately before it dispatches the network call. The window
from request start to dispatch is attributed to the client; the window
from dispatch to the first streamed token is attributed to the API
server. The split flows through the step.end / turn.step.completed
events (and therefore wire.jsonl) and is surfaced in three places:

- KIMI_CODE_DEBUG=1: `TTFT: 2.5s (api 2.4s + client 100ms)`
- session log: new `llm response` line with the timing breakdown
- vis: firstToken/api + firstToken/client rows and timeline label

The split is omitted (total only) when a provider does not report the
boundary, preserving backward compatibility.

* feat(timing): split the decode window into server vs client time

Time-to-first-token now reports a client/server split, but the slow part
of a long turn is the decode window (inter-token streaming), which was
still a single opaque number. Profiling long sessions showed decode
throughput halving over a session's lifetime independent of context
size, which the synchronous per-chunk stream pipeline can cause: kosong
awaits the host callback for every streamed part, so a loaded main
thread throttles how fast tokens are pulled off the wire.

Account for this directly in the stream loop: the time awaiting the next
part (server + network) versus the time spent processing each part
in-process (deep copy, host callback, part merge). The split is reported
through onStreamEnd and flows through the step.end / turn.step.completed
events (and wire.jsonl) into the same three surfaces as the TTFT split:

- KIMI_CODE_DEBUG=1: `TPS: 40.0 tok/s (200 tokens in 5.0s; server 4.6s + client 400ms)`
- session log: serverDecodeMs / clientConsumeMs on the `llm response` line
- vis: streamDuration/server + streamDuration/client rows and timeline label

A large, growing client share confirms host-side throttling; a dominant
server share points at the server/connection. The per-chunk accounting is
wrapped in try/finally so it stays correct across `continue` and aborts,
and is omitted when the stream reports nothing.
2026-06-30 19:15:02 +08:00
haozhe.yang
73a419ff29 feat(agent-core-v2): implement and register remaining builtin tools
- background: add TaskList / TaskOutput / TaskStop and register them in BackgroundService
- goal: add CreateGoal / GetGoal / SetGoalBudget / UpdateGoal; extend IGoalService with markComplete, markBlocked, setBudgetLimits
- skill: register the Skill tool in AgentSkillService
- question: add AskUserQuestion (foreground + background) via a new Agent-scoped QuestionToolsService
- web: add FetchURL / WebSearch with LocalFetchURL and Moonshot fetch/search providers; add @mozilla/readability and linkedom deps
- move ToolResultBuilder into the tool domain so it can be shared across tool domains
- wire IQuestionToolsService and IWebService into AgentRPCService so the new registration services are instantiated
2026-06-30 18:47:01 +08:00
haozhe.yang
c43177019c feat(server-v2): add session children and warnings endpoints
- surface custom metadata in session index summaries so child sessions can be filtered without per-session document reads
- add ISessionLegacyService.createChild/listChildren: children are forks tagged with parent_session_id + child_session_kind, listed by those markers
- wire GET/POST /sessions/{id}/children and GET /sessions/{id}/warnings, reusing the protocol schemas and mapping session.not_found / session.fork_active_turn
- register the sessionLegacy domain at L7 in the domain-layer check
2026-06-30 18:47:01 +08:00
haozhe.yang
78fa333c98 refactor(agent-core-v2): switch FileStorageService.watch to chokidar
- replace node:fs fs.watch with a chokidar FSWatcher on the parent
  directory (depth 0), filtering events by normalized path so the
  match is correct on Windows as well as POSIX
- keep the existing Event<void> contract, 150ms debounce, and
  ref-counted arm/disarm lifecycle
- add chokidar ^4.0.3 and refresh the lockfile
- settle the watcher in storage watch tests to account for
  chokidar's asynchronous OS-watcher attachment
2026-06-30 18:47:01 +08:00
haozhe.yang
b94c60d50a feat(server-v2): add /api/v1/ws with seq/epoch watermark and resync
Bring the v1 WebSocket protocol to server-v2 so web clients get gap-free
sync across reconnects instead of silently losing events.

- per-session durable event journal with monotonic seq + epoch, recovered
  across restarts
- SessionEventBroadcaster: single per-session fan-out, durable/volatile
  classification, and cursor-based replay (buffer_overflow / epoch_changed)
- WsConnectionV1: client_hello / subscribe with cursors, replay or
  resync_required, and ack carrying authoritative server cursors
- GET /sessions/:id/snapshot: atomic-at-a-watermark state and in-flight turn
- IAgentLifecycleService: onDidCreate / onDidDispose for agent discovery
- GET /connections: list live WebSocket clients
2026-06-30 18:47:01 +08:00
haozhe.yang
858e0f8db7 feat(agent-core-v2): persist workspace registry and rebuild from session index
- add IWorkspaceStore + FileWorkspaceStore persisting the catalog to <homeDir>/workspaces.json in the v1-compatible schema
- WorkspaceRegistryService loads from the store, caches in memory, and writes through on create/update/delete
- when workspaces.json is absent or malformed, rebuild from the legacy session_index.jsonl (one workspace per distinct workDir)
- add tests for cross-instance persistence, rebuild, and write-through
2026-06-30 18:47:01 +08:00
haozhe.yang
d210009877 feat(server-v2): port v1 /sessions/{tail} action routes
- implement SessionLifecycleService.fork (active-turn guard, per-agent
  wire-log copy, metadata rewrite, forked marker, closed-session fork)
- add SessionLegacyService edge adapter for compact/undo/abort/btw over
  the native v2 services
- persist agent transcripts via per-agent homedir and extend SessionMeta
  (isCustomTitle/lastPrompt/agents/custom) for fork parity
- add aborted session status and IWireRecord.getRecords()
- register session.undo_unavailable error code
- dispatch all six /sessions/{tail} actions with v1 error mapping and
  emit session.created on create/fork
2026-06-30 18:47:01 +08:00
haozhe.yang
ce0e4f2589 feat(server-v2): expose /openapi.json via @fastify/swagger
- register @fastify/swagger before routes and serve GET /openapi.json
- add v2-specific openapi transform for multipart upload, binary downloads, and the fs-action/question oneOf dispatchers
- project the session-action dispatcher into archive only (v2 registers a subset of v1 routes)
- reuse protocol wire schemas, no inline re-declaration
2026-06-30 18:47:01 +08:00
haozhe.yang
299e6d6bd8 test(agent-core-v2): expand config slice example to all section owners
- resolve every config-section owner against one shared IConfigRegistry
- add register+inspect scenario asserting all expected sections
- add write+round-trip scenario persisting every persistable section
- stub non-config collaborators to construct owners in isolation
2026-06-30 18:47:01 +08:00
_Kerman
03b513afc0 fix(agent-core-v2): fix tests 2026-06-30 18:44:35 +08:00
liruifengv
659062d11c
fix(tui): enable file path completion for / in shell mode (#1225)
Typing `/\' in shell mode (`!\') now triggers file path completion instead of the slash command menu, for both a bare leading `/\' and inline paths like `ls /\'. Hidden entries are skipped to match `/add-dir\', and accepting a completion no longer produces a double leading slash.
2026-06-30 17:54:24 +08:00
_Kerman
56574a4c1f fix(agent-core-v2): tests 2026-06-30 17:35:58 +08:00
qer
a3f9cec8a9
fix(web): deduplicate workspaces shown in the sidebar (#1221)
Collapse registered workspaces that share a root in the daemon registry (preferring the canonical id) and in the web sidebar merge, so the same folder no longer renders as two identical, synchronously-selected entries.
2026-06-30 17:25:24 +08:00
_Kerman
8d4e702c16 fix(agent-core-v2): reduce service constructor args 2026-06-30 17:03:55 +08:00
_Kerman
567c384840 refactor(agent-core-v2): rename permissionGate 2026-06-30 16:44:17 +08:00