Port the v1 server's `/sessions/{sid}/tasks*` REST surface onto
agent-core-v2:
- GET /sessions/{sid}/tasks — list with optional `status` filter
- GET /sessions/{sid}/tasks/{tid} — get by id with optional
`with_output` / `output_bytes` preview
- POST /sessions/{sid}/tasks/{tid}:cancel — cancel with the
idempotent 40904 `{cancelled:false}` shape
The routes resolve the main agent's `IBackgroundService` through the
core -> session -> agent scope chain and project `BackgroundTaskInfo`
onto the protocol `BackgroundTask`, matching the v1 wire contract
(schemas, error codes, and messages). The `:cancel` suffix is parsed
via the shared `parseActionSuffix` helper.
Resolved the parallel kosong/tool refactors: kept the modelRuntime+model+chatProvider split and the tool contract domain (L3), adopted upstream's onContextOverflow turn hook and ToolCall unification, and ported prompt_cache_key/kimiRequestHeaders into ModelResolver.
Return turn_id from agent prompt and steer RPC/gateway methods, route
prompt submit/steer/undo/clear/cancel through IAgentRPCService in the
server-v2 action map, and cover prompt submission and missing-agent errors.
Add ReadMediaFile with image/video content handling, shared magic-byte file
type detection, and capability-based registration so the tool only appears
when the active model supports image or video input.
Add a session-scoped IFsService that backs fs search, content grep, git
status, and git diff using AgentFileSystem and IProcessRunner, with gitignore
filtering and protocol-shaped responses.
Add createdAt to parked interactions and keep a bounded recently-resolved
ledger so edge transports can distinguish duplicate resolves from unknown
ids. Cover the server-v2 approval duplicate-resolve path.
Replace the kosong domain with chatProvider, model, and modelRuntime
services, move model alias config and env overlay into model, and update
profile and LLM requester to resolve providers through IModelResolver and
IChatProviderFactory.
Move tool metadata, result, and execution hook contexts into the tool
domain, update callers to import from the new tool contract surface, and
make tool dedupe self-wiring through tool executor hooks.
- GET /tools, GET /mcp/servers, POST /mcp/servers/{id}:restart
- resolve IToolRegistry / IMcpService from the most-recent session's
main agent; empty list / 40408 when no session is live
- project v2 models to the protocol wire shapes, matching
packages/server (source/status mapping, mcp_server_id, null input_schema)
- add GET /sessions/:sid/questions (list pending) and POST
/sessions/:sid/questions/:tail (resolve + :dismiss) on top of
IQuestionService / IInteractionService
- enrich the agent-core-v2 question domain with the rich in-process
model (QuestionItem / QuestionResult) and dismiss() so the v1 wire
can be projected faithfully
- reimplement the protocol <-> in-process adapter at the edge (no v1
agent-core import): synthesized item/option ids, allow_other,
expires_at, and the 5-kind answer flattening
- add GET /sessions/{sid}/messages (paginated, role-filtered) and GET /sessions/{sid}/messages/{message_id}
- thin wrapper over the main agent's IContextMemory, already exposed in the v2 action map
- port v1 id derivation, content mapping, pagination and role-filter semantics
- register the routes under /api/v1 and cover with tests
- add Core-scoped IModelCatalogService in agent-core-v2 covering
listModels, listProviders, getProvider, setDefaultModel, and
refreshOAuthProviderModels
- expose the v1-compatible /api/v1 models and providers catalog routes
in server-v2, mapping provider.not_found / model.not_found to the
numeric protocol error codes
- add IOAuthService.getCachedAccessToken for provider status detection
- register provider.not_found and model.not_found protocol error codes
- add `/sessions/{sid}/approvals` GET (list pending) and POST (resolve)
routes, backed by IApprovalService and IInteractionService; duplicate
resolves return 40902 via the kernel's recently-resolved window
- add `/workspaces` GET / POST / PATCH / DELETE routes, backed by
IWorkspaceRegistry, projecting v2 workspace records onto the v1 wire shape
- register both route groups in registerApiV1Routes
- add an agent-core-v2 interaction example that resolves the Session-scoped
kernel and approval/question facades through the scope tree
- map `workspaces:update` to IWorkspaceRegistry.update in the core actionMap
- cover the rename round-trip in rpc.test.ts
- sync the edge-exposure cheatsheet
- add GET/POST /config backed by agent-core-v2 IConfigService
- reuse protocol configResponseSchema/patchConfigRequestSchema for wire fidelity
- project resolved config generically (camelCase to snake_case); redact provider credentials to has_api_key
- split the flat POST patch into per-domain set calls and publish a config.changed DomainEvent
- wire registerConfigRoutes into /api/v1
- add domain-boundaries.md covering scope vs domain, data-ownership test, and the session/agent/turn split conclusions
- cross-link the topic from SKILL.md, design.md, persistence.md, and service-authoring.md
- warn against I{Scope}EntityService bundles that re-merge domains by lifetime
- regenerate DI x Scope dependency graph from scripts/dep-graph.mjs output:
add storage / bootstrap / session-metadata nodes, drop phantom records /
environment / dynamicInjector / turnRunner nodes, and fix session-index /
background / cron / wireRecord / blobStore / config storage edges
- fix check-domain-layers.mjs layer table (eventBus -> eventSink,
toolDedup -> tooldedup, drop dynamicInjector, add toolExecutor>turn and
permissionMode>contextInjector exceptions) so lint:domain passes again
- remove unused mcpCredentialsDir / defaultMcpCredentialsDir path helpers
from the mcp oauth store (it now persists via IAtomicDocumentStore)
- correct stale persistence comments in fileStorageService and the AGENTS.md
session example
- bootstrap seeds IAppendLogStorage + IAtomicDocumentStorage with
FileStorageService so the Store layer is durable in the CLI
- background task state goes through IAtomicDocumentStore, output.log
through IStorageService byte primitives
- cron task records go through IAtomicDocumentStore; the per-id-json-store
util is deleted
- mcp OAuth credentials move to an async McpOAuthStore over
IAtomicDocumentStore, with the provider caching eagerly so the SDK's
synchronous getters stay non-blocking
- telemetry failed-event spool goes through IStorageService bytes
- session-index enumerates via IStorageService.list and reads state.json
via IAtomicDocumentStore instead of hostFs
- add ITerminalService (create/list/get/attach/write/resize/close) and
ITerminalBackend contract; Session-scoped so per-session sessionId
threading is dropped
- implement TerminalService with per-terminal output buffering, seq replay,
sink fan-out, and dispose-time process cleanup
- register a default NotImplementedTerminalBackend; the real PTY backend is
supplied by the composition root
- add the terminal.not_found error code (protocol + ErrorCodes) and register
the terminal layer in check-domain-layers
- cover the service with unit tests driven by a fake backend
- Add IBlobStorage role token for pluggable blob backends
- Make BlobStoreService depend on IBlobStorage instead of IHostFileSystem
- Remove host filesystem dependency from WireRecordService
- Seed IBlobStorage in local and server-v2 composition roots
- Add BlobStoreService tests
- add non-blocking `enqueue` and `onDidResolve` to the `IInteractionService` kernel
- add typed `enqueue` to `IApprovalService` and `IQuestionService`
- expose `interactions:request`, `approvals:request`, `questions:ask` actions
- stream pending set (`interactions`) and resolutions (`interactions:resolved`) over WS
- tag `serves` consumers with inject / accessor access mechanism
- add cross-scope borrow diagram and update `session` example to use accessor
- sort minidb before migration-legacy in flake.nix workspaceNames
- split session-metadata out of the untyped sessionMetaStore KV bag into a
typed SessionMeta service (title, timestamps, archived, forkedFrom)
- make session-context carry pure seeded facts (sessionId, workspaceId,
sessionDir, metaScope) instead of coupling identity to a persistence store
- slim ISessionService to session-level commands (archive); move fork to
session-lifecycle and drop agent ops (compact/undo) and read views
- seed the session scope and materialize the initial metadata document on
create; archive/close now dispose the scope tree
- add IScopeHandle.dispose so session and agent scopes tear down on close
- drop unused deps from agent-lifecycle and trim session error codes
- rename sessionIndex directory to session-index
Add `packages/server-v2`, a minimal Fastify server bootstrapped through the
`agent-core-v2` DI engine (`bootstrap()` -> Core `Scope`), speaking the same
`/api/v1` interface as the v1 server. Route handlers resolve Core services
via `core.accessor.get(IXxx)`.
- Serve healthz, meta, auth, oauth (login poll/start/cancel/logout) and
shutdown with the standard `{code, msg, data, request_id}` envelope.
- Re-point root `pnpm dev:server` to server-v2 and add a `src/main.ts`
foreground entry.
- Add `build/hash-imports-loader.mjs` so tsx resolves `agent-core-v2`'s `#/`
array-fallback subpath imports.
- `agent-core-v2` Phase 0 fixes so it compiles and boots: add the `event`
domain (`IEventService`), fix `gateway` `event.subscribe` -> `event.on`, fix
the `wireRecord` fallback `BlobStoreService` construction, export the
`provider` barrel, and fix a `tooldedup` test import casing.
- move ExecutableTool contract (ExecutableTool, ToolExecution,
ExecutableToolResult, ExecutableToolContext, ToolUpdate) from loop/types
to a new tool/toolContract domain
- move tool-access into the tool domain and add a tool barrel
- group per-domain tools under tools/ (plan, skill, swarm, todoList, mcp)
- extract createMcpTool from mcpService into mcp/tools/mcp
- update domain-layer exceptions to point at the new tool domain
- add `session-lifecycle` (Core) owning the live session scope tree
(create/get/list/close), extracted from `gateway`
- reshape `sessionIndex` into a backend-neutral query store
(list/get/countActive) keyed by opaque `workspaceId`; drop fs paths
- move `encodeWorkDirKey` to `_base/utils` as the single workspace-id
derivation, and align `workspaceRegistry` to use it
- `gateway` now injects `ISessionLifecycleService`; update dep map and tests