Skip to content

feat(server): support restoring and listing archived sessions#1071

Open
sailist wants to merge 92 commits into
MoonshotAI:mainfrom
sailist:feat/web-archive-resume
Open

feat(server): support restoring and listing archived sessions#1071
sailist wants to merge 92 commits into
MoonshotAI:mainfrom
sailist:feat/web-archive-resume

Conversation

@sailist

@sailist sailist commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue; the problem is described below.

Problem

Archived sessions could be included in session listings, but server clients had no API to restore an archived session or to query only archived sessions. That blocks the web archive/resume flow, where the UI needs to bring an archived session back before resuming it.

What changed

1. Restore archived sessions through the server API

Problem: Clients could see archived sessions but could not restore them through the server.

What was done:

  • Added a session restore action that clears the archived flag from the persisted session state.
  • Returned the restored session so callers can immediately continue the resume flow.
  • Added server e2e coverage for restoring archived sessions.

2. List only archived sessions

Problem: The existing list API could include archived sessions, but it could not filter to archived sessions only.

What was done:

  • Added an archived_only list query parameter.
  • Kept it mutually exclusive with include_archive to avoid ambiguous list semantics.
  • Updated the API surface snapshot and e2e tests for the new query behavior.

3. Groundwork carried on this branch

Problem: The archived-session server work sits on top of the in-process core architecture used by the server.

What was done:

  • Carried the domain/runtime/service refactor groundwork for agent-core services.
  • Added lifecycle/event projection pieces used by session and agent flows.
  • Added dependency-direction fence tests and service-design documentation for the new architecture.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

sailist and others added 30 commits June 17, 2026 22:09
- run the supervised server via `server run --foreground` (default `server run` now spawns a detached daemon)
- schtasks: use the absolute exe path and redirect stdout/stderr to the log file via cmd.exe
- systemd: route stdout/stderr to the log file via StandardOutput=append
- systemd: enable loginctl linger on install so the user service survives logout; report linger state in status
- add I...Service interface, createDecorator token, and ...Service subclass for each manager\n- switch Agent and KimiCore to instantiate and reference service interfaces\n- add unwrap() migration bridge for call sites that still need the raw manager\n- update tests to construct service classes and interface types
construct Agent and Session services via InstantiationService child scopes\nregister per-agent services (records, compaction, context, turn, etc.) as SyncDescriptors in a ServiceCollection\nregister session services (hooks, skill registry, MCP connection) the same way\nthread an optional instantiationService through KimiCore, Session, and Agent options\nexport service interfaces as values so they can serve as DI identifiers
- inject IRecordsService through DI instead of reading agent.records\n- accept emitStatusUpdated as a callback instead of the Agent instance
- goal, plan, swarm and replay services take explicit deps instead of Agent\n- inject records/replay/context/config via DI decorators\n- pass telemetry, kaos, homedir and emit callbacks as constructor args\n- update agent service registration and affected tests
- add AgentEventBus pub/sub service and route event emission through it
- add LifecycleService with a beforePrompt hook for system reminders
- move plan-mode reminders from PlanModeInjector onto the lifecycle hook
- fire the beforePrompt hook in the turn loop before each step's prompt
- add onContextMessageRemoved lifecycle hook, fired when context drops a message
- move beforePrompt firing from the turn loop into InjectionManager.inject
- dedup plan-mode reminders into full/sparse/reentry variants by turn distance
- track the injected reminder index and realign it on context message removal
- use reentry reminder when re-entering plan mode with existing plan content
Add a vitest fence that scans packages/agent-core/src/{rpc,session,agent,di}
and forbids runtime modules from importing back into services/ (relative
paths or the @moonshot-ai/agent-core/services bare subpath), pinning the
rule from src/services/AGENTS.md. A pure exported findViolations helper is
driven by both the positive (real src) and negative (planted fixture) cases.

Co-Authored-By: Claude <noreply@anthropic.com>
Extend ILifecycleService/LifecycleService with additive session, agent,
and turn hook pairs (onXxx/fireXxx) mirroring the existing Set<handler> +
IDisposable + sequential-await pattern. onBeforePrompt and
onContextMessageRemoved are unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Append fireXxx calls at session, agent, and turn boundaries. Inject a
session-scoped ILifecycleService into Session via the established DI
accessor pattern; thread the agent id into Agent so it can fire agent
hooks; fire turn hooks in runOneTurn (DidEnd in a finally). All fires
are inert no-ops today (no subscribers); onBeforePrompt /
onContextMessageRemoved call sites are untouched.

Co-Authored-By: Claude <noreply@anthropic.com>
Introduce the per-session repository role for state.json persistence: ISessionRepository (read/write/flush) in services/session/session.ts and a SessionRepository implementation that mirrors Session.writeMetadata/readMetadata/flushMetadata byte-for-byte (same metadataPath, JSON.stringify indent, mkdir options, and serialized write chain). archive/restore/purge are deferred to M1.5 (archive IO lives in session-store.ts; restore/purge have no existing implementation). Adds 7 tests incl. concurrent-write serialization.

Co-Authored-By: Claude <noreply@anthropic.com>
Add a normative note to services/AGENTS.md stating that repositories/indexes consumed directly by a runtime aggregate live in the runtime layer (e.g. src/session/sessionRepository.ts), since runtime must not import from services/. RPC/SDK-facing command/query/runtime facades stay under services/<domain>/ and depend on those runtime repositories (services->runtime allowed). Dependency direction is unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Relocate ISessionRepository + SessionRepository from services/session/ to src/session/ so the runtime Session can depend on it without crossing the M0.1 dependency-direction fence (runtime must not import from services/). The interface now lives beside its implementation in src/session/sessionRepository.ts (no createDecorator - still a per-session plain class). Behavior is byte-for-byte identical: same metadataPath, JSON.stringify indent, mkdir options, and serialized write chain. Move the test to test/session/ and fix imports; remove the interface from services/session/session.ts (ISessionService et al. unchanged).

Co-Authored-By: Claude <noreply@anthropic.com>
Session now constructs a per-session SessionRepository (same homedir + persistenceKaos as before) and delegates writeMetadata/readMetadata/flushMetadata to it. The method names and signatures are unchanged so all call sites (rpc/core-impl.ts, session/rpc.ts, and internal callers) keep compiling and behaving identically; readMetadata still assigns into this.metadata and returns it. Behavior is byte-for-byte identical because SessionRepository.write captures JSON.stringify(this.metadata, null, 2) synchronously and serializes writes through the same chained promise. The now-redundant writeMetadataPromise field and metadataPath getter are removed. Legal now that both Session and SessionRepository live in the runtime layer (no services/ import).

Co-Authored-By: Claude <noreply@anthropic.com>
Split the session query path out of ISessionService into a new
ISessionQueryService that serves list / count / listGlobal /
listByWorkspace / listChildren / search from the SessionIndex read model
(M1.2). Each query re-seeds a fresh index from core.rpc.listSessions so
freshness matches today's per-call reads.

- New sessionQueryService.ts: SessionQueryService facade. Cold path only
  (listSessions + per-row getSessionMetadata); never resumes an agent.
- New sessionStatus.ts: shared, side-effect-free computeSessionStatus,
  applySessionTurnEvent and tryGetSessionMeta used by both SessionService
  and SessionQueryService (no duplicated status logic, no reach into
  SessionService privates).
- session.ts: add ISessionQueryService + SessionSearchQuery.
- sessionService.ts: re-route _computeStatus / _handleBusEvent /
  tryGetMeta through the shared helpers (behavior-preserving).
- New sessionQueryService.test.ts (14 cases), including a no-agent-resume
  assertion.

Byte-for-byte parity with today's SessionService.list is preserved by
re-sorting with a comparator matching core.rpc.listSessions (updatedAt
desc, createdAt desc, id asc) and mirroring the existing cursor pivot,
page-size clamp, and post-hydration status filter.

Co-Authored-By: Claude <noreply@anthropic.com>
…ervice

SessionService.list and listChildren are now thin wrappers that delegate
to the SessionQueryService facade (M1.3a). ISessionService.list and
listChildren are marked @deprecated and point at ISessionQueryService;
they will be removed in M7.1.

SessionService composes a SessionQueryService from its own deps in the
constructor (eager, so the facade's event-bus subscription sees every
event and live status stays in lock-step with SessionService). It is
disposed via this._register. Composition (rather than IInstantiationService
resolution) keeps direct `new SessionService(...)` callers — notably the
existing session-service.test.ts, which is outside this phase's allowlist
— working without an ISessionQueryService stub.

Command / single-entity methods (create, get, update, fork, createChild,
getStatus, compact, undo, archive) stay on SessionService. Behavior is
byte-for-byte identical (the existing 60 session-service cases pass
unchanged). Removed the now-unused ListSessionsPayload import and the
DEFAULT_PAGE_SIZE / MAX_PAGE_SIZE constants.

Co-Authored-By: Claude <noreply@anthropic.com>
Keep a writer-synced SessionIndex read model current after every mutating
SessionService command (create/update/fork/createChild/compact/undo/archive)
by re-reading the affected summary via listSessions({ includeArchive: true })
and upserting it (removing when gone). create/fork/createChild continue to
publish event.session.created via emitCreated; no new protocol event types
are introduced for update/archive/compact/undo (none exist). The index is
exposed as a class-level SessionService.sessionIndex accessor (not on the
ISessionService command interface) for read-model consumers and tests.

Co-Authored-By: Claude <noreply@anthropic.com>
Introduce a unified IWorkspaceService facade that absorbs the workspace
registry + root resolution + recent + browse surfaces previously split
across IWorkspaceRegistry and IWorkspaceFsService. WorkspaceService is a
pure facade: every method delegates to the injected registry / fs
services, so no workspace logic is duplicated.

- registry: list/get/createOrTouch/update/delete
- root resolution: resolveRoot(workspaceId) -> workDir
- recent: listRecent() (derived view over the registry's recency
  ordering, capped at RECENT_ROOTS_LIMIT; no new persistence)
- browse: browse/home

IWorkspaceRegistry / IWorkspaceFsService (and their impls and consumers)
are left in place; consolidating those call sites is a later step. The
new service is registered via registerSingleton and wired into the
services + workspace barrels so the registration fires at runtime.

Co-Authored-By: Claude <noreply@anthropic.com>
SessionHost now owns the agent registry (agents map + agentIdCounter + toolKaos) and the agent lifecycle (createMain/resume/close/closeForReload/instantiateAgent/readyAgents/resumePersistedAgent). Session keeps its identity (id, options, lifecycle, mcp, persistence, metadata) and delegates agent management to an internal SessionHost constructed with the few session-level deps it still needs (scope, logHandle, skillsReady, and a back-reference to the Session for metadata/systemContextKaos/SubagentHostService). M0.4 session lifecycle hooks keep firing at the same points. KimiCore.sessions stays Map<string, Session> and core-impl.ts is untouched (the switch is deferred to M1.7b). Behavior is byte-identical.

Co-Authored-By: Claude <noreply@anthropic.com>
Switch KimiCore.sessions from Map<string, Session> to Map<string, SessionHost>. Construction stores session.host; read sites unwrap the owning Session via the host.session back-ref so SessionAPIImpl, rename/close/reload/fork/export keep operating on the same Session object. SessionHost.session is widened to a documented public accessor (the same deps.session object). Session's public surface is unchanged. Harness tests that reach into core.sessions for session-owned members (experimentalFlags/options/flushMetadata/skills) unwrap .session; host-level getReadyAgent calls and the busy-reload host identity assertion are left operating on hosts. SessionAPIImpl still takes a Session (unwrap at call sites).
sailist and others added 28 commits June 21, 2026 17:30
Introduce the generic ScopeManager base + IManagerService contract for the
di-v3 scope mechanism (per scope-mechanism.md). A manager lives in the parent
scope, is the sole up-going event publisher for its children, attaches to a
child via child.accessor.get(...) and re-emits collection-view events (adding
the child id), and pairs disposeChild with onDidChildDispose + eventBus.publish
in a try/finally. Children never reverse-call the manager's write methods.

Publishes through a generic IManagerEventBus<TPublish> port so the scope
mechanism stays decoupled from the rpc-coupled IDomainEventBus. Validated with
a FakeManager/FakeChild test double (7 cases).

Co-Authored-By: Claude <noreply@anthropic.com>
Validate the scope mechanism's Core-registration path with ILogService.

agent-core ships no production ILogService adapter/registration (the server wires PinoLogger via services.set), so there was no registerSingleton(ILogService, ...) to replace. The new test (test/services/logger.test.ts) registers registerScopedService(Core, ILogService, FakeLogService, Delayed) — which aliases to registerSingleton — and asserts: Core-alias routing to the singleton registry, unchanged ILogService behavior (info/warn/error/debug + child bindings), resolution through a ScopeBuilder-built Session scope via the DI parent chain, and lazy (Delayed) construction. Production behavior is unchanged (no src change).

Co-Authored-By: Claude <noreply@anthropic.com>
Add packages/agent-core/src/scope/index.ts as an explicit barrel for the
di-v3 scope mechanism (LifecycleScope, registerScopedService /
getScopedServiceDescriptors / markBuilt / isBuilt, IScopeHandle /
IServiceAccessor, the ScopeBuilder family, the manager pattern base and
contracts, and the I*Context identity decorators), then re-export it from
the top-level index so the surface is reachable from @moonshot-ai/agent-core.

The barrel is explicit (not export *) so internal helpers stay private, and
a wildcard re-export at the top level is safe because none of the scope
names collide with the existing top-level surface.

Co-Authored-By: Claude <noreply@anthropic.com>
Move the DI container from src/di/ into the new infrastructure layer at src/_base/di/. Keep src/di/ as deprecated re-export aliases (removed in P9) so all ~86 consumers keep working unchanged. Fix the one intra-di import that pointed outside di/ (lifecycle.ts → ../../errors/unexpectedError). Zero behavior change.

Co-Authored-By: Claude <noreply@anthropic.com>
…orts

Delete the 13 deprecated re-export shims under src/di/ left by a86e55a
and rewrite every consumer to the #/_base/di barrel (production) or the
#/_base/di/test subpath (test utilities). No deep imports into
_base/di/<submodule> remain except the sanctioned test subpath.

- src/di/** removed (no re-export alias layer).
- ~178 consumer import specifiers rewritten: 95 bare, 73 deep collapsed
  to the barrel, 10 routed to #/_base/di/test (incl. 2 _util imports).
- _base/di/index.ts: add Trace, Graph (public symbols needed after the
  collapse); stays sinon-free, no test/testInstantiationService re-export.
- _base/di/test.ts: re-export _util (test-only internal) so tests do not
  need to reach into the instantiation submodule.
- package.json imports: add explicit "#/_base/di" -> src/_base/di/index.ts
  so the bare nested barrel resolves under vitest (the #/* wildcard's
  index fallback does not cover a nested "*").
- descriptor.test.ts: drop the obsolete "InstantiationType not re-exported
  from descriptors" guard (the barrel legitimately re-exports it; the
  descriptors submodule is no longer importable).

typecheck + full test (3233 passed) + dependency-direction fence green;
all five verification gates clean (0 hits).

Co-Authored-By: Claude <noreply@anthropic.com>
Codify two architectural rules for the di-v3 refactor:
- barrel-only exports: every layer (_base/<x>, _utils/<x>, <domain>) exposes
  its public surface only via index.ts; consumers import from the barrel,
  never deep-import submodules.
- no re-import / re-export shims: migrations leave no old-path re-export
  aliases; consumers are fully rewritten to the new barrel in the same step,
  and the old path is deleted immediately.

PLAN.md: §0.2 goals, §1.4 rejected alternatives, §2.3 barrel-only note,
§5 acceptance. ROADMAP.md: Global constraints, P2 intro + P2.1/P2.2/P2.4/P2.5
rewritten to the new shape, P9.1 repurposed to a final import audit.

Co-Authored-By: Claude <noreply@anthropic.com>
Move Event/Emitter from src/base/common/event.ts into the _base/
infrastructure layer as a barrel-only module, and delete the now-empty
base/ tree. No re-export shim is left behind (per the amended plan).

- src/_base/event/event.ts: pure move of the implementation (internal
  imports ../../errors/unexpectedError and ../../_base/di resolve
  identically from the new depth, so the file is unchanged).
- src/_base/event/index.ts: new barrel exporting the full public surface
  (Event, Emitter).
- 11 src + 2 test consumers rewritten to the _base/event barrel: src uses
  relative …/_base/event (matching the existing …/_base/di convention),
  tests use #/_base/event. No base/common/event or deep _base/event/<x>
  import remains.
- src/index.ts: top-level Emitter re-export now points at ./_base/event;
  surrounding note updated to the new subpath.
- package.json imports: add explicit "#/_base/event" ->
  src/_base/event/index.ts so the bare nested barrel resolves under
  vitest (the #/* wildcard's index fallback does not cover a nested "*").

typecheck + full test (3233 passed) + dependency-direction fence green;
all three verification gates clean (0 hits, src/base absent).

Co-Authored-By: Claude <noreply@anthropic.com>
Move the non-DI logging core (types/logger/formatter/sinks/resolve-config + barrel) into the _base/ layer. logging/ held no DI (ILogService lives in services/logger/), so the whole dir is sunk and deleted with no re-export shim.

- git mv src/logging/ -> src/_base/logging/ (5 impl files R100; index.ts R075)

- expand _base/logging/index.ts barrel to also export resolveLoggingConfig/ResolveLoggingInput (from resolve-config) and PENDING_MAX/RotatingFileSink (from sinks) so barrel-only consumption typechecks

- rewrite 27 consumer files to the #/_base/logging barrel (or relative …/_base/logging); collapse src/index.ts deep ./logging/<x> re-exports to ./_base/logging (top-level surface unchanged)

- add "#/_base/logging" to package.json imports (nested-barrel resolution)

Gates: typecheck clean; vitest 3233 passed | 1 todo (baseline); dependency-direction fence 14/14. Verification gates literal-0 (no old bare/deep logging imports, no deep #/_base/logging/<x>, src/logging gone).
Move errors/unexpectedError.ts (onUnexpectedError / safelyCallListener / setUnexpectedErrorHandler / resetUnexpectedErrorHandler / UnexpectedErrorHandler) into the _base/ layer under the barrel-only / no-reexport-shim rule.

- git mv src/errors/unexpectedError.ts -> src/_base/errors/unexpectedError.ts (R100); add src/_base/errors/index.ts barrel exporting the 5 symbols

- drop the unexpectedError re-export block from src/errors/index.ts (Kimi codes/classes/serialize barrel intact)

- add export * from './_base/errors' to src/index.ts (next to ./_base/di) so the package root surface is unchanged — setUnexpectedErrorHandler stays importable from @moonshot-ai/agent-core for server

- rewrite 5 consumers to the #/_base/errors barrel (src: _base/di/lifecycle.ts, _base/event/event.ts; test: di/lifecycle.test.ts, errors/unexpectedError.test.ts, base/common/event.test.ts)

- add "#/_base/errors" to package.json imports (nested-barrel resolution)

Gates: agent-core typecheck clean; server typecheck clean (public API preserved); vitest 3233 passed | 1 todo (baseline); dependency-direction fence 14/14. Verification gates literal-0 (no errors/unexpectedError imports, no deep #/_base/errors/<x>, src/errors/unexpectedError.ts gone, root re-exports ./_base/errors).
Sink the pure-function utils/ tree into _utils/<topic>/ subdirs, each
exposed only through an index.ts barrel (barrel-only, no re-export shim,
full consumer rewrite, moved paths deleted). kosong-dependent tokens.ts +
completion-budget.ts stay in utils/ for P3.

Move map (9 files into 8 subdirs):
- abort.ts        → _utils/abort/         (#/_utils/abort)
- fs.ts           → _utils/fs/            (#/_utils/fs)
- hero-slug.ts
  workdir-slug.ts → _utils/slug/          (#/_utils/slug, re-exports both)
- xml-escape.ts   → _utils/xml/           (#/_utils/xml)
- render-prompt.ts→ _utils/template/      (#/_utils/template)
- types.ts        → _utils/types/         (#/_utils/types)
- per-id-json-store.ts → _utils/persistence/ (#/_utils/persistence)
- proxy.ts        → _utils/net/           (#/_utils/net)

Each _utils/<topic>/index.ts re-exports its module's full surface via
export *. Intra-util cross-import (persistence → fs) repointed to the
sibling barrel (../fs). 46 sunk-util import sites across 45 consumer
files rewritten to the #/_utils/<topic> barrels. src/index.ts root
re-export of installGlobalProxyDispatcher repointed to ./_utils/net.

package.json imports: 8 explicit #/_utils/<x> entries added (chosen over
the wildcard form to match the established #/_base/<x> convention; proven
to resolve under both tsc and vitest). exports block untouched.

Gates: agent-core typecheck 0, server typecheck 0, agent-core test
227 files / 3233 passed, dependency-direction fence 14 passed.

Co-Authored-By: Claude <noreply@anthropic.com>
Rename the two stale di-v3 fence it() descriptions: the _utils ← _base ← domains layering rule and the cross-domain impl fence are now active assertions against the real tree (post P2.1-P2.5), not vacuously-clean placeholders. Add a comment noting isDiV3LayoutActive(SRC) is now true. Assertions unchanged; both return [] on the real tree (14/14 green). oxlint cannot express this rule (no import/no-restricted-paths or import/no-restricted-imports); the vitest fence remains the enforcement (deviation documented in STATUS).

Co-Authored-By: Claude <noreply@anthropic.com>
Move the pure approval contract out of services/ into its own domain barrel.

- git mv src/services/approval/approval.ts → src/approval/approval.ts;
  rewrite its infra imports to #/_base/di and #/rpc.
- New src/approval/index.ts barrel exports the contract surface
  (IApprovalService, ApprovalRequest/ApprovalResponse types, and the
  renamed approvalToAgentCoreResponse / approvalToBrokerRequest /
  ApprovalToBrokerRequestParams helpers), mirroring the surface
  services/index.ts used to expose. No register* — approval is a pure
  contract (no impl, no tools).
- Remove the approval re-exports from services/index.ts.
- Repoint all consumers (5 production files, 8 test files) to #/approval.
- Root barrel: add 'export * from "./approval"' (adjacent to the
  _base/errors anchor) so @moonshot-ai/agent-core's public surface is
  byte-for-byte unchanged for consumers like server — the established
  P2.4 precedent and documented P3.8 end state.
- package.json: add explicit '#/approval' imports entry. The '#/'
  array-wildcard resolved for tsc but NOT for vitest, so the explicit
  entry is required for the test runner (recipe §4 ⑥).

Gates: agent-core typecheck + test (3233 passed) + fence (14/14) pass;
server typecheck passes (public surface preserved); services/approval
and #/approval deep-import greps both 0.

Co-Authored-By: Claude <noreply@anthropic.com>
Move the event contract (event.ts, IEventService) and impl (eventService.ts,
EventService) out of services/ into the pre-existing src/event/ module,
co-locating them with event-bus.ts and projection.ts. Add a src/event/index.ts
barrel (IEventService, EventService, IDomainEventBus, DomainEventBus,
shouldProjectToProtocol), repoint every consumer to #/event, and re-export
./event from the root barrel so @moonshot-ai/server keeps seeing
IEventService / EventService. Register the explicit #/event imports entry
(required for vitest).

SyntheticPrompt* types stay in services/index.ts — they are prompt-domain
(defined in prompt.ts, consumed only by prompt), not event. One fragile
singleton-registry index-0 assertion in coreProcessService.test.ts is relaxed
to a by-identifier lookup, since the new event barrel's registerSingleton
shifts registration order.

Gates: agent-core typecheck + test (3233 passed) + fence (14/14) clean;
server typecheck clean; services/event and #/event/<file> greps at 0.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Move the coreProcess contract (coreProcess.ts — ICoreRuntime,
CoreProcessServiceOptions), client (coreProcessClient.ts — BridgeClientAPI,
CoreProcessClientDeps) and impl (coreProcessService.ts — CoreProcessService +
its top-level registerSingleton) out of services/ into a fresh src/coreProcess/
module. Add a src/coreProcess/index.ts barrel mirroring the old
services/index.ts:1-7 surface (BridgeClientAPI, CoreProcessClientDeps,
ICoreRuntime, CoreProcessServiceOptions, CoreProcessService — impl included so
its registerSingleton fires on barrel import, same as event). Repoint every
consumer to #/coreProcess (13 production + 12 test, including multi-line
import blocks), drop the coreProcess re-exports from services/index.ts, and
delete the now-empty services/coreProcess/ dir.

Root barrel src/index.ts gains export * from './coreProcess' (adjacent to the
approval/event/question anchors) and package.json gains an explicit
#/coreProcess imports entry (required for vitest) so @moonshot-ai/server keeps
seeing CoreProcessService / ICoreRuntime / CoreProcessServiceOptions.

Backward edges to the still-unmigrated auth/environment/logger services are
repointed to relative ../services/<x>/<x> (fence-clean: coreProcess is not a
runtime dir and services is in DIV3_RESERVED_DIRS); they will move to
#/auth, #/environment, #/logger in P3.7. The session/provider-manager and rpc
imports stay relative (../session/provider-manager is type-only; ../rpc is
used instead of #/rpc because vitest cannot resolve the #/rpc wildcard for
value imports and adding a #/rpc package.json entry is out of scope).

No production registration-order change; the existing by-identifier
singleton-registry assertion in coreProcessService.test.ts is unchanged, and
the only production consumer (server serviceCollection) feeds an
order-independent ServiceCollection.

coreProcess is not explicitly listed in ROADMAP P3.7 (plan gap); the di-v3
end state empties services/ and P3.1 (session) needs this upstream contract
migrated first, so src/coreProcess/ is the correct home. Proceeded and
documented, not a BLOCKER.

Gates: agent-core typecheck + test (3233 passed) + fence (14/14) clean;
server typecheck clean; services/coreProcess and #/coreProcess/<file> greps
at 0.

Co-Authored-By: Claude <noreply@anthropic.com>
Move services/message/{message.ts,messageService.ts,transcript.ts} to
src/message/ with a barrel mirroring the old services/index.ts surface,
repoint consumers to #/message, add the #/message imports entry, and
re-export from the package root so the server surface is preserved. The
impl's top-level registerSingleton still fires on barrel import (mirrors
coreProcess). The lone backward edge to session (still in services/) stays
relative (../services/session/session) and fence-clean.

Co-Authored-By: Claude <noreply@anthropic.com>
Move services/prompt/{prompt.ts,promptService.ts} to src/prompt/ with a
barrel mirroring the old services/index.ts surface, repoint all consumers
to #/prompt, add the #/prompt imports entry, and re-export from the package
root so the server surface is preserved. The impl's top-level
registerSingleton still fires on barrel import (mirrors message/coreProcess).
Backward edges to the still-unmigrated authSummary/logger/session stay
relative (../services/<x>/<x>) and fence-clean. The SyntheticPrompt* event
types and AgentStateSnapshot/AgentStatePatch (defined in prompt.ts) move
with the domain and are exported from the new barrel; SessionBusyError is
kept on the surface for server's prompts route.

Co-Authored-By: Claude <noreply@anthropic.com>
Move src/services/session/* (6 files: contract + SessionService /
SessionQueryService / SessionRuntimeService / SessionIndex + status
helpers) into the existing runtime module src/session/. Barrel-only, no
alias. Repoint all consumers (incl. the message + prompt backward edges)
to #/session. Remove session re-exports from services/index.ts; add
#/session to package.json imports.

Rule 1 stays clean (fence 14/14): session's impls already import their
6 upstream contracts from #/<domain> barrels, so the move into the
runtime dir introduces no runtime→services violations.

Co-Authored-By: Claude <noreply@anthropic.com>
- add a `:restore` session action that clears the archived flag in state.json and returns the restored session
- add an `archived_only` list query param, mutually exclusive with `include_archive`, that post-filters to archived sessions
- keep the implementation in the server layer as a temporary measure until agent-core exposes restore natively
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@changeset-bot

changeset-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f98edca

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

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Minor

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

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