- introduce storage domain (IStorageService/IRecordStore/IConfigStore) as the program-side persistence substrate over raw node fs
- add hostFs (local real-filesystem primitives reused by persistence and the local agent backend)
- add agentFs (IAgentFileSystem + IFileSystemBackend) and process (IProcessRunner + IProcessBackend) with local/ssh backends for the Agent execution environment
- add workspaceContext (session workspace root + path access), workspaceRegistry (process-wide catalog) and hostFolderBrowser (host-side folder picker)
- remove kaos/fs/terminal/filestore/workspace domains
- route persistence through storage (sessionMetaStore -> IConfigStore) and hostFs (sessionStore); route plan file IO through agentFs
- collect app paths in IEnvironmentService; register new domains in DOMAIN_LAYER and refresh the dependency map
- remove fictional IModelCatalogService / ILLMService stubs and the unused kosong config section
- add IProtocolHandlerRegistry (Core) to build protocol adapters by provider type, realizing provider != request handler
- promote ProviderManager to IProviderManager (Session, seeded) and move it into the kosong domain
- rewire IProfileService and ILLMRequester to inject IProviderManager (and IProtocolHandlerRegistry) instead of the options.modelProvider side-channel
- update DI scope docs, service-design notes, and tests
- add Session-scoped `interaction` domain, a unified blocking
request/response kernel (pending set + onDidChange) for
human-in-the-loop requests
- rebuild `approval` and `question` as typed facades over the kernel;
their public contracts are unchanged
- derive the full session phase (awaiting_approval / awaiting_question /
running / idle) in `session-activity` from the kernel's pending set and
each agent's active turn; move `SessionStatus` there
- implement `session` facade `archive()` (persist flag, remove agents,
publish event) and brand `ISessionContext` with `_serviceBrand`
- orient: DI x Scope black box and file conventions
- design: domain boundaries, scope, and DI wiring
- implement: service authoring against interfaces
- verify: build and validation checks
- align / test / errors / flags / permission / service-authoring
- ConfigService now reads/writes real config.toml: snake_case↔camelCase
transforms, lossless raw round-trip, KIMI_MODEL_* env overlay, and
lenient load diagnostics.
- Add IConfigRegistry.onDidRegisterSection so late-registered sections are
validated, get defaults applied, and fire onDidChange.
- Move section schemas to their owner domains: providers→provider,
experimental→flag, thinking→profile, loopControl→loop,
McpServerConfig→mcp.
- profile/loop/llmRequester read config through IConfigService instead of
the dangling KimiConfig options.
- Add the agent-core-dev config topic (section ownership + TOML format).
- port IWorkspaceRegistry (Core) backed by <homeDir>/workspaces.json
- port IWorkspaceFsService (Core) host-fs folder-picker backend
- rename IWorkspaceService to ISessionWorkspaceService (Session)
- extend ISessionStore with sessionDir/workspaceIdFor/countActiveSessions
and drop the unused read/write stubs
- add workspace.not_found, fs.path_not_found, fs.permission_denied and
validation.failed to protocol KimiErrorCode
- update the DI scope map and allow the workspace>event layer exception
- rename TelemetryClient to ITelemetryAppender and noopTelemetryClient to nullTelemetryAppender (vscode-style); add addAppender/removeAppender/setAppender/setEnabled/flush/shutdown to ITelemetryService
- TelemetryService fans track out to all appenders with per-appender error isolation via onUnexpectedError; withContext shares appenders and inherits enabled state
- add ConsoleAppender (dev echo) and CloudAppender + CloudTransport: HTTP POST to telemetry-logs.kimi.com with Bearer auth, retry, and on-disk fallback, decoupled from @moonshot-ai/kimi-telemetry
- document telemetry usage (inject/track/context/appenders/bootstrap) in the agent-core-dev skill
- add provider domain with IProviderService CRUD over the providers config section
- refactor OAuthService and AuthSummaryService to read and write providers via provider
- add ConfigService.replace for whole-section writes used by provider delete
- move provider/OAuth schemas from auth/oauthSchemas into the provider domain
- update DI scope diagram and domain layer map; remove the Turn scope
Resolve merge conflicts by keeping the HEAD (kimi-code-v2) architecture
as the base and adopting compatible increments from before-rebase-v2:
- adopt auth OAuth flow, structured log domain, telemetry sinks,
workspace service, and the file-backed config service
- migrate IAgentConfigService to the Session-scoped ISessionConfigService
- keep HEAD's turn/agent-lifecycle/permission domains and the removed
tool/message/records domains, since before-rebase-v2's versions depend
on domains (context/injection/tool/records) that HEAD has removed
- repair auto-merge fallout: dedupe auth vs config schema exports,
restore cwd/chdir on AgentKaos, retarget records imports to
sessionMetaStore, and revert THEIRS test files that no longer match
HEAD's src
Note: agent-core-v2 typecheck already fails on HEAD (138 errors); this
merge introduces no new error types (132, a subset of HEAD).
- add logfmt formatter with redaction, truncation and ANSI coloring
- add rotating file writer plus a Session-scoped file writer service
- add env-driven logging config and ILogOptions seed
- add Session-scoped ISessionLogService and flush on ILogService
- rework createServices around ServiceRegistration groups (base + additionalServices) and add per-domain register*Services stubs
- extract loopRunner, toolCallExecutor and turnEvents out of turnService; switch turn lifecycle to typed events
- add AsyncEmitter / IWaitUntil / handleVetos to _base/event for interceptable onWill and veto events
- document DI x scope (docs/di.md, docs/service-design.md, scope-domain diagram) and refresh di-testing.md
- ignore plan/
Introduce packages/agent-core-v2, the next-generation agent engine built
on a four-level DI Scope architecture (Core/Session/Agent/Turn).
- Port VSCode-style DI primitives into _base/di and add a Scope layer
(LifecycleScope, registerScopedService, Scope tree, IScopeHandle).
- Implement domain services across L1-L7 and cross-cutting domains
(log, telemetry, environment, kaos, kosong, records, config, tool,
skill, permission, approval, question, context, message, turn,
injection, compaction, plan, goal, swarm, usage, tooldedup,
background, cron, mcp, agent-lifecycle, session-context,
session-activity, session, hooks, event, gateway, terminal, fs,
workspace, filestore, auth).
- Establish DI testing conventions: resolve the system under test by
interface through the container, with shared stubs under
test/<domain>/stubs.ts (environment/log/records/turn).
- Add a domain-layer import boundary checker and a service dependency
graph generator.
- Register the package in flake.nix (workspacePaths / workspaceNames).
v1 (packages/agent-core) is left untouched; the server/SDK switchover is
a later step. See plan/ for the design, roadmap, and skeleton spec.
The Write tool previously failed when a parent directory was missing, forcing a manual mkdir round trip. It now creates missing parents recursively before writing.
The model-facing skill listing silently sliced long descriptions to 250 characters with no marker, so neither the user nor the model could tell a description was cut. Truncated entries now end with an ellipsis and the truncation walks whole grapheme clusters so it never splits a surrogate pair or combining sequence.
* feat(tui): redesign /plugins as a tabbed panel
Split the /plugins manager into Installed / Official / Third-party /
Custom tabs. The Official and Third-party marketplace catalogs load
lazily, so /plugins opens instantly and keeps working offline, with
fetch failures shown inline instead of closing the panel. The tab strip
is shared with the /model provider tabs via the new renderTabStrip
helper.
* fix(tui): show untiered marketplace entries and update badges
Address Codex review feedback on the /plugins tab redesign:
- Untiered marketplace entries (no `tier` field) now appear on the
Third-party tab instead of being invisible in both marketplace tabs.
- Installed plugins whose marketplace version is newer than the local
version render an `update <local> → <latest>` badge again, and
up-to-date plugins show `installed · v<version>` — restoring the
update visibility the pre-redesign marketplace UI had.
* fix(tui): decode Space for installed-plugin toggle
In terminals that send printable keys via Kitty/CSI-u sequences (e.g. VS
Code's integrated terminal), the Space key arrives as a printable char
rather than a Key.space match, so the Installed-tab Space toggle silently
stopped working. Check both matchesKey(Key.space) and the decoded
printable char to match the MCP selector and other dialogs.
* fix(tui): open custom marketplaces on the Third-party tab
When `/plugins marketplace <source>` points at a custom catalog whose
entries omit `tier`, those entries are classified into the Third-party
tab. Opening on Official left the visible tab empty and Enter could not
install anything, unlike the old marketplace picker which showed all
entries from the supplied source. Open on Third-party when a custom
source is supplied; the default catalog still lands on Official.
* docs(plugins): drop open-url wording and hyphenate Shift-Tab
Address Codex review feedback:
- The marketplace Enter action is install/update only (open-url rows were
removed), so say "install or update" instead of "open or install" and
drop the leftover changeset sentence about setup URLs.
- Use `Shift-Tab` (hyphen) instead of `Shift+Tab` to match the docs
typography convention.
* fix(tui): keep marketplace selection valid while loading
When the Official/Third-party catalog is still loading, `entries` is empty
and pressing ↓ computed `Math.min(-1, selectedIndex + 1)` = -1. The later
Enter then read `entries[-1]` and the first install silently did nothing.
Clamp the index to 0 while there are no entries.
* fix(tui): count tab separators in tab-strip fit check
renderTabStrip declared a strip to fit whenever the sum of tab cell widths
fit, but the returned string also inserts single spaces between tabs via
`segments.join(' ')`. At widths around 43-45 columns for a four-tab strip
this declared a fit while the joined line was wider, so the trailing tab
got truncated instead of showing the `<`/`>` scroll markers. Count the
inter-tab separators in both the full-fit check and the scrolling window
fit check.
* docs(plugins): fix Kimi Datasource redirect anchor
The datasource.md redirect pointed at ./plugins.html#kimi-datasource, but
plugins.md no longer has a `## Kimi Datasource` heading — it is now
`## Official Plugins`. Update the en/zh redirect targets and fallback
links to #official-plugins / #官方插件 so the link lands on an existing
anchor.
* docs(plugins): restore concise Kimi Datasource section
The `## Official Plugins` section had replaced the original
`## Kimi Datasource` section, leaving the datasource.md redirect pointing
at a missing anchor and the Datasource capabilities/usage unreachable.
Restore a concise `## Kimi Datasource` section (intro + OAuth login +
install steps + usage) in both en and zh so the #kimi-datasource anchor
is valid again and the content is reachable.
* docs(plugins): restore Installing-from-GitHub subheading
The tab-redesign rewrite had dropped the `### Installing from GitHub` /
`### 从 GitHub 安装` subheading and its lead sentence, leaving only the
four URL forms. Restore the heading and lead sentence in both en and zh.
* docs(plugins): expand Kimi Datasource and tidy marketplace docs
- Condense the Official / Third-party / Custom tab overview and trust-badge note
- Trim the custom marketplace JSON section to the minimal id + source shape
- Move and expand the Kimi Datasource section with install, usage, and coverage
* docs(plugins): fix heading style and drop Next steps section
- Use sentence case for the Datasource headings (How to use, What you can do)
- Rename the Datasource caveat heading to Billing and limitations / 计费与限制 to avoid a duplicate Notes / 注意事项 anchor
- Remove the Next steps section, which linked back to the on-page Datasource anchor
* fix(tui): repaint plugins panel from current theme palette
The /plugins panel and MCP selector captured a palette snapshot at construction. In auto theme mode, applyResolvedAutoTheme swaps currentTheme.palette and re-renders without remounting the open panel, so it kept stale colors until closed.
Read currentTheme.palette during render instead, drop the colors opt from both components and their call sites, and add a regression test that switches palettes on a mounted panel.
* fix(tui): repaint model tab strip from current theme palette
TabbedModelSelectorComponent cached a palette snapshot in opts and used it only for the tab strip. In auto theme mode the inner model list repaints from currentTheme but the strip kept the old colors until the dialog was closed.
Read currentTheme.palette on the render path instead, drop the colors opt and its three call sites, and add a regression test that switches palettes on a mounted selector and asserts the strip repaints. This removes the last palette snapshot among editor-replacement dialogs.