indusagi-coding-agent 0.2.4 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +661 -0
- package/README.md +99 -1
- package/dist/entry.js +13551 -23107
- package/dist/guardrails.js +822 -8248
- package/dist/index.js +12547 -22190
- package/package.json +8 -7
- package/dist/types/addons/addons.test.d.ts +0 -21
- package/dist/types/addons/contract.d.ts +0 -640
- package/dist/types/addons/dispatch/event-dispatcher.d.ts +0 -140
- package/dist/types/addons/dispatch/index.d.ts +0 -23
- package/dist/types/addons/dispatch/tool-interceptor.d.ts +0 -128
- package/dist/types/addons/host.d.ts +0 -246
- package/dist/types/addons/index.d.ts +0 -51
- package/dist/types/addons/manifest.d.ts +0 -56
- package/dist/types/addons/sandbox.d.ts +0 -103
- package/dist/types/addons/surface.d.ts +0 -42
- package/dist/types/boot/auth-vault.d.ts +0 -29
- package/dist/types/boot/boot.d.ts +0 -26
- package/dist/types/boot/boot.test.d.ts +0 -15
- package/dist/types/boot/contract.d.ts +0 -236
- package/dist/types/boot/heap.d.ts +0 -31
- package/dist/types/boot/index.d.ts +0 -20
- package/dist/types/boot/invocation.d.ts +0 -40
- package/dist/types/boot/invocation.test.d.ts +0 -8
- package/dist/types/boot/runners/addon-wiring.d.ts +0 -103
- package/dist/types/boot/runners/addon-wiring.test.d.ts +0 -19
- package/dist/types/boot/runners/checkpoint.d.ts +0 -133
- package/dist/types/boot/runners/checkpoint.test.d.ts +0 -12
- package/dist/types/boot/runners/delegate-runner.d.ts +0 -109
- package/dist/types/boot/runners/delegate-runner.test.d.ts +0 -13
- package/dist/types/boot/runners/index.d.ts +0 -13
- package/dist/types/boot/runners/link-runner.d.ts +0 -20
- package/dist/types/boot/runners/memdir.d.ts +0 -103
- package/dist/types/boot/runners/memdir.test.d.ts +0 -12
- package/dist/types/boot/runners/oneshot-runner.d.ts +0 -19
- package/dist/types/boot/runners/read-state.d.ts +0 -82
- package/dist/types/boot/runners/read-state.test.d.ts +0 -10
- package/dist/types/boot/runners/registry.d.ts +0 -30
- package/dist/types/boot/runners/repl-runner.d.ts +0 -19
- package/dist/types/boot/runners/server-mode.d.ts +0 -71
- package/dist/types/boot/runners/session-persist.test.d.ts +0 -10
- package/dist/types/boot/runners/session.d.ts +0 -88
- package/dist/types/boot/runners/session.test.d.ts +0 -15
- package/dist/types/boot/server-token.d.ts +0 -97
- package/dist/types/boot/stages.d.ts +0 -92
- package/dist/types/boot/upgrade/apply.d.ts +0 -45
- package/dist/types/boot/upgrade/index.d.ts +0 -13
- package/dist/types/boot/upgrade/upgrades.d.ts +0 -126
- package/dist/types/briefing/briefing.test.d.ts +0 -15
- package/dist/types/briefing/compose.d.ts +0 -37
- package/dist/types/briefing/context-docs.d.ts +0 -38
- package/dist/types/briefing/context-docs.test.d.ts +0 -18
- package/dist/types/briefing/contract.d.ts +0 -686
- package/dist/types/briefing/index.d.ts +0 -29
- package/dist/types/briefing/macros.d.ts +0 -206
- package/dist/types/briefing/skills.d.ts +0 -67
- package/dist/types/capability-deck/bridge-ledger/index.d.ts +0 -25
- package/dist/types/capability-deck/bridge-ledger/key.d.ts +0 -65
- package/dist/types/capability-deck/bridge-ledger/ledger.d.ts +0 -129
- package/dist/types/capability-deck/bridge-ledger/network.d.ts +0 -115
- package/dist/types/capability-deck/builtin-bridge.d.ts +0 -114
- package/dist/types/capability-deck/capability-deck.test.d.ts +0 -18
- package/dist/types/capability-deck/cards/bg-process-card.d.ts +0 -99
- package/dist/types/capability-deck/cards/index.d.ts +0 -37
- package/dist/types/capability-deck/cards/memory-card.d.ts +0 -68
- package/dist/types/capability-deck/cards/plan-file.d.ts +0 -56
- package/dist/types/capability-deck/cards/plan-tools.d.ts +0 -97
- package/dist/types/capability-deck/cards/plan-tools.test.d.ts +0 -9
- package/dist/types/capability-deck/cards/saas-card.d.ts +0 -78
- package/dist/types/capability-deck/cards/task-card.d.ts +0 -106
- package/dist/types/capability-deck/cards/todo-card.d.ts +0 -78
- package/dist/types/capability-deck/cards/workflow-card.d.ts +0 -55
- package/dist/types/capability-deck/cards/workflow-card.test.d.ts +0 -12
- package/dist/types/capability-deck/checkpoint.int.test.d.ts +0 -25
- package/dist/types/capability-deck/contract.d.ts +0 -318
- package/dist/types/capability-deck/index.d.ts +0 -46
- package/dist/types/capability-deck/manifest.d.ts +0 -60
- package/dist/types/capability-deck/provision.d.ts +0 -76
- package/dist/types/capability-deck/read-edit-gate.int.test.d.ts +0 -21
- package/dist/types/channels/channels.test.d.ts +0 -15
- package/dist/types/channels/contract.d.ts +0 -489
- package/dist/types/channels/framer.d.ts +0 -49
- package/dist/types/channels/index.d.ts +0 -24
- package/dist/types/channels/link/dialog.d.ts +0 -138
- package/dist/types/channels/link/driver.d.ts +0 -81
- package/dist/types/channels/link/index.d.ts +0 -13
- package/dist/types/channels/link/server.d.ts +0 -70
- package/dist/types/channels/oneshot.d.ts +0 -37
- package/dist/types/channels/ops.d.ts +0 -89
- package/dist/types/channels/session-ops.d.ts +0 -80
- package/dist/types/conductor/bash-guard.d.ts +0 -106
- package/dist/types/conductor/bash-guard.test.d.ts +0 -17
- package/dist/types/conductor/catalog/catalog.d.ts +0 -87
- package/dist/types/conductor/catalog/index.d.ts +0 -14
- package/dist/types/conductor/catalog/matcher.d.ts +0 -47
- package/dist/types/conductor/conductor.d.ts +0 -213
- package/dist/types/conductor/conductor.test.d.ts +0 -10
- package/dist/types/conductor/contract.d.ts +0 -838
- package/dist/types/conductor/diagnostics.d.ts +0 -183
- package/dist/types/conductor/diagnostics.test.d.ts +0 -10
- package/dist/types/conductor/index.d.ts +0 -26
- package/dist/types/conductor/permission-gate.integration.test.d.ts +0 -22
- package/dist/types/conductor/permission-wiring.test.d.ts +0 -14
- package/dist/types/conductor/permissions.d.ts +0 -287
- package/dist/types/conductor/permissions.test.d.ts +0 -12
- package/dist/types/conductor/plan-mode.integration.test.d.ts +0 -23
- package/dist/types/conductor/post-edit-diagnostics.test.d.ts +0 -18
- package/dist/types/conductor/quota-error.d.ts +0 -35
- package/dist/types/conductor/signal-hub/hub.d.ts +0 -83
- package/dist/types/conductor/signal-hub/index.d.ts +0 -19
- package/dist/types/conductor/signal-hub/translate.d.ts +0 -77
- package/dist/types/conductor/skill-parse/index.d.ts +0 -10
- package/dist/types/conductor/skill-parse/parse.d.ts +0 -67
- package/dist/types/conductor/submit.test.d.ts +0 -28
- package/dist/types/conductor/transcript-store/index.d.ts +0 -16
- package/dist/types/conductor/transcript-store/serialize.d.ts +0 -106
- package/dist/types/conductor/transcript-store/serialize.test.d.ts +0 -10
- package/dist/types/conductor/transcript-store/store.d.ts +0 -188
- package/dist/types/console/auth-status.d.ts +0 -28
- package/dist/types/console/components/AgentsView.d.ts +0 -41
- package/dist/types/console/components/BackgroundAgents.d.ts +0 -63
- package/dist/types/console/components/BackgroundAgents.test.d.ts +0 -8
- package/dist/types/console/components/Banner.d.ts +0 -110
- package/dist/types/console/components/Composer.d.ts +0 -37
- package/dist/types/console/components/StatusBar.d.ts +0 -42
- package/dist/types/console/components/TerminalConsole.d.ts +0 -27
- package/dist/types/console/components/WorkingIndicator.d.ts +0 -44
- package/dist/types/console/components/WorkingIndicator.test.d.ts +0 -9
- package/dist/types/console/components/banner-sweep.d.ts +0 -55
- package/dist/types/console/components/banner.test.d.ts +0 -9
- package/dist/types/console/components/welcome.d.ts +0 -115
- package/dist/types/console/components/welcome.test.d.ts +0 -9
- package/dist/types/console/console.test.d.ts +0 -19
- package/dist/types/console/contract.d.ts +0 -611
- package/dist/types/console/index.d.ts +0 -34
- package/dist/types/console/input/complete.d.ts +0 -120
- package/dist/types/console/input/dir-reader.d.ts +0 -28
- package/dist/types/console/input/index.d.ts +0 -24
- package/dist/types/console/input/input.test.d.ts +0 -14
- package/dist/types/console/input/keymap.d.ts +0 -193
- package/dist/types/console/input/paste.d.ts +0 -183
- package/dist/types/console/mount.d.ts +0 -53
- package/dist/types/console/overlays/approval-queue.d.ts +0 -88
- package/dist/types/console/overlays/approval.d.ts +0 -104
- package/dist/types/console/overlays/approval.test.d.ts +0 -17
- package/dist/types/console/overlays/auth.d.ts +0 -31
- package/dist/types/console/overlays/boards.d.ts +0 -55
- package/dist/types/console/overlays/host.d.ts +0 -45
- package/dist/types/console/overlays/index.d.ts +0 -15
- package/dist/types/console/overlays/pickers.d.ts +0 -37
- package/dist/types/console/overlays/sessions.d.ts +0 -29
- package/dist/types/console/reducer.d.ts +0 -51
- package/dist/types/console/slash/builtins.d.ts +0 -33
- package/dist/types/console/slash/commands/dynamic.d.ts +0 -57
- package/dist/types/console/slash/commands/dynamic.test.d.ts +0 -9
- package/dist/types/console/slash/commands/integrations.d.ts +0 -28
- package/dist/types/console/slash/commands/integrations.test.d.ts +0 -18
- package/dist/types/console/slash/commands/shared.d.ts +0 -72
- package/dist/types/console/slash/commands/transcript.d.ts +0 -24
- package/dist/types/console/slash/commands/transcript.test.d.ts +0 -10
- package/dist/types/console/slash/commands/workbench.d.ts +0 -21
- package/dist/types/console/slash/commands/workbench.test.d.ts +0 -10
- package/dist/types/console/slash/index.d.ts +0 -34
- package/dist/types/console/slash/registry.d.ts +0 -90
- package/dist/types/console/slash/resolve.d.ts +0 -109
- package/dist/types/console/slash/slash.test.d.ts +0 -18
- package/dist/types/console/startup.d.ts +0 -119
- package/dist/types/console/theme/adapter.d.ts +0 -79
- package/dist/types/console/theme/index.d.ts +0 -18
- package/dist/types/console/theme/palette.d.ts +0 -77
- package/dist/types/console/theme/resolve.d.ts +0 -45
- package/dist/types/console/theme/theme.test.d.ts +0 -16
- package/dist/types/console/theme/tokens.d.ts +0 -62
- package/dist/types/entry.d.ts +0 -17
- package/dist/types/guardrails.d.ts +0 -33
- package/dist/types/index.d.ts +0 -24
- package/dist/types/insight/channel.d.ts +0 -45
- package/dist/types/insight/contract.d.ts +0 -411
- package/dist/types/insight/index.d.ts +0 -26
- package/dist/types/insight/insight.test.d.ts +0 -17
- package/dist/types/insight/recorder.d.ts +0 -63
- package/dist/types/insight/redaction.d.ts +0 -44
- package/dist/types/insight/replay.d.ts +0 -77
- package/dist/types/insight/sampling.d.ts +0 -84
- package/dist/types/insight/serialize.d.ts +0 -54
- package/dist/types/insight/sinks/console.d.ts +0 -36
- package/dist/types/insight/sinks/file.d.ts +0 -37
- package/dist/types/insight/sinks/index.d.ts +0 -16
- package/dist/types/insight/sinks/stream.d.ts +0 -53
- package/dist/types/kit/clipboard-image.d.ts +0 -40
- package/dist/types/kit/external-editor.d.ts +0 -35
- package/dist/types/kit/image.d.ts +0 -102
- package/dist/types/kit/index.d.ts +0 -29
- package/dist/types/kit/kit.test.d.ts +0 -13
- package/dist/types/kit/shell.d.ts +0 -50
- package/dist/types/kit/tool-fetch.d.ts +0 -165
- package/dist/types/launch/catalog.d.ts +0 -51
- package/dist/types/launch/contract.d.ts +0 -387
- package/dist/types/launch/credentials.d.ts +0 -112
- package/dist/types/launch/index.d.ts +0 -28
- package/dist/types/launch/invocation/attachments.d.ts +0 -72
- package/dist/types/launch/invocation/flags.d.ts +0 -59
- package/dist/types/launch/invocation/index.d.ts +0 -23
- package/dist/types/launch/invocation/read.d.ts +0 -52
- package/dist/types/launch/invocation/usage.d.ts +0 -25
- package/dist/types/launch/launch.test.d.ts +0 -20
- package/dist/types/launch/login.d.ts +0 -68
- package/dist/types/launch/oauth.d.ts +0 -101
- package/dist/types/launch/oauth.test.d.ts +0 -20
- package/dist/types/launch/packages.d.ts +0 -75
- package/dist/types/launch/packages.test.d.ts +0 -15
- package/dist/types/launch/pickers.d.ts +0 -97
- package/dist/types/runtime-bridge/bridges/_drive.d.ts +0 -74
- package/dist/types/runtime-bridge/bridges/builtins.d.ts +0 -77
- package/dist/types/runtime-bridge/bridges/claude-cli.d.ts +0 -37
- package/dist/types/runtime-bridge/bridges/codex-cli.d.ts +0 -27
- package/dist/types/runtime-bridge/bridges/index.d.ts +0 -15
- package/dist/types/runtime-bridge/bridges/indusagi-cli.d.ts +0 -36
- package/dist/types/runtime-bridge/broker.d.ts +0 -182
- package/dist/types/runtime-bridge/contract.d.ts +0 -436
- package/dist/types/runtime-bridge/index.d.ts +0 -21
- package/dist/types/runtime-bridge/runtime-bridge.test.d.ts +0 -17
- package/dist/types/runtime-bridge/sink.d.ts +0 -59
- package/dist/types/sessions/contract.d.ts +0 -79
- package/dist/types/sessions/index.d.ts +0 -11
- package/dist/types/sessions/library.d.ts +0 -95
- package/dist/types/sessions/sessions.test.d.ts +0 -11
- package/dist/types/settings/contract.d.ts +0 -175
- package/dist/types/settings/index.d.ts +0 -13
- package/dist/types/settings/manager.d.ts +0 -109
- package/dist/types/settings/settings.test.d.ts +0 -16
- package/dist/types/transcript-export/index.d.ts +0 -20
- package/dist/types/transcript-export/publish.d.ts +0 -81
- package/dist/types/transcript-export/sgr.d.ts +0 -90
- package/dist/types/transcript-export/template.d.ts +0 -64
- package/dist/types/transcript-export/theme-bridge.d.ts +0 -99
- package/dist/types/transcript-export/transcript-export.test.d.ts +0 -16
- package/dist/types/window-budget/budget/estimate.d.ts +0 -47
- package/dist/types/window-budget/budget/gate.d.ts +0 -37
- package/dist/types/window-budget/budget/index.d.ts +0 -14
- package/dist/types/window-budget/budget/slice.d.ts +0 -38
- package/dist/types/window-budget/condenser.d.ts +0 -73
- package/dist/types/window-budget/contract.d.ts +0 -182
- package/dist/types/window-budget/index.d.ts +0 -17
- package/dist/types/window-budget/microcompact.d.ts +0 -68
- package/dist/types/window-budget/microcompact.test.d.ts +0 -16
- package/dist/types/window-budget/rehydrate.d.ts +0 -56
- package/dist/types/window-budget/summarize/condense.d.ts +0 -76
- package/dist/types/window-budget/summarize/index.d.ts +0 -12
- package/dist/types/window-budget/summarize/prompt.d.ts +0 -56
- package/dist/types/window-budget/window-budget.test.d.ts +0 -18
- package/dist/types/workflow-engine/agent-runner.d.ts +0 -124
- package/dist/types/workflow-engine/agent-runner.test.d.ts +0 -8
- package/dist/types/workflow-engine/display.d.ts +0 -148
- package/dist/types/workflow-engine/display.test.d.ts +0 -1
- package/dist/types/workflow-engine/engine.d.ts +0 -183
- package/dist/types/workflow-engine/engine.test.d.ts +0 -1
- package/dist/types/workflow-engine/index.d.ts +0 -21
- package/dist/types/workflow-engine/parse.d.ts +0 -64
- package/dist/types/workflow-engine/parse.test.d.ts +0 -1
- package/dist/types/workflow-engine/structured-output.d.ts +0 -51
- package/dist/types/workflow-engine/structured-output.test.d.ts +0 -1
- package/dist/types/workspace/brand.d.ts +0 -26
- package/dist/types/workspace/index.d.ts +0 -11
- package/dist/types/workspace/locator.d.ts +0 -50
- package/dist/types/workspace/runtime-detect.d.ts +0 -56
|
@@ -1,838 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conductor contract — the FROZEN type surface of Phase 2 (agent runtime core).
|
|
3
|
-
*
|
|
4
|
-
* This module is the single typed seam between the coding-agent *product* (the
|
|
5
|
-
* UI/channels that drive a session) and the framework `Agent` (the raw LLM
|
|
6
|
-
* conversation loop, published by `indusagi/agent`). It declares *only* shapes
|
|
7
|
-
* plus two tiny inert helpers — no behavior, no I/O, no orchestration. Every
|
|
8
|
-
* later conductor module (the signal hub, the transcript store, the model
|
|
9
|
-
* catalog/matcher, the credential vault, the conductor factory, and the
|
|
10
|
-
* `SessionConductor` itself) is written against the names declared here, so the
|
|
11
|
-
* file is intentionally small, append-mostly, and stable.
|
|
12
|
-
*
|
|
13
|
-
* Design stance:
|
|
14
|
-
* - The conductor *wraps* the framework `Agent`. The framework emits a
|
|
15
|
-
* fine-grained `AgentEvent` stream for its own loop; the conductor consumes
|
|
16
|
-
* that internally and **re-emits a distinct, product-level
|
|
17
|
-
* {@link SessionSignal} stream** to consumers. The two are deliberately not
|
|
18
|
-
* the same union: `SessionSignal` is the stable surface the app renders,
|
|
19
|
-
* free to evolve independently of the framework's loop events.
|
|
20
|
-
* - Faults are **typed discriminated values** ({@link ConductorFault}), never
|
|
21
|
-
* string sentinels. A consumer switches on `fault.kind`, not on substring
|
|
22
|
-
* matching of a message.
|
|
23
|
-
* - Persistence uses a **fresh on-disk vocabulary** ({@link TranscriptEntry},
|
|
24
|
-
* {@link SessionHead}, {@link TRANSCRIPT_SCHEMA}). The node is a `parent`-linked
|
|
25
|
-
* tree, the version is a namespaced string, and the field names are the
|
|
26
|
-
* conductor's own — not the framework's session-manager schema.
|
|
27
|
-
* - State is exposed as an **immutable snapshot** ({@link ConductorState});
|
|
28
|
-
* consumers read it, they never mutate it.
|
|
29
|
-
*
|
|
30
|
-
* Framework anchors (all from the `indusagi` package — the sibling rebuilt
|
|
31
|
-
* framework this app targets):
|
|
32
|
-
* - `AgentMessage`, `ThinkingLevel`, `AgentTool` ← `indusagi/agent`
|
|
33
|
-
* - `Model`, `Usage`, `KnownProvider` ← `indusagi/ai`
|
|
34
|
-
*
|
|
35
|
-
* The conductor never re-declares these; it composes them.
|
|
36
|
-
*/
|
|
37
|
-
import type { AgentMessage, AgentTool, CanUseToolFn, ThinkingLevel } from "indusagi/agent";
|
|
38
|
-
import type { KnownProvider, Model, Usage } from "indusagi/ai";
|
|
39
|
-
import type { PermissionMode } from "../settings";
|
|
40
|
-
import type { ApprovalResolver } from "./permissions";
|
|
41
|
-
/** Re-exported framework vocabulary that conductor consumers routinely need. */
|
|
42
|
-
export type { AgentMessage, AgentTool, CanUseToolFn, ThinkingLevel, Model, Usage, KnownProvider };
|
|
43
|
-
/** Re-exported permission vocabulary, so conductor consumers get it in one import. */
|
|
44
|
-
export type { PermissionMode, ApprovalResolver };
|
|
45
|
-
/**
|
|
46
|
-
* The closed set of failure categories the conductor can surface.
|
|
47
|
-
*
|
|
48
|
-
* Each is a distinct recovery story, so the kind is a discriminant — not a
|
|
49
|
-
* free-form string:
|
|
50
|
-
* - `model` — the LLM call itself failed (transport, provider, decode).
|
|
51
|
-
* - `tool` — a tool invocation threw or returned a hard error.
|
|
52
|
-
* - `persistence` — writing/reading the on-disk transcript failed.
|
|
53
|
-
* - `aborted` — the caller cancelled the in-flight turn via {@link SessionConductor.abort}.
|
|
54
|
-
* - `overflow` — the context window was exceeded and could not be condensed.
|
|
55
|
-
*/
|
|
56
|
-
export type FaultKind = "model" | "tool" | "persistence" | "aborted" | "overflow";
|
|
57
|
-
/**
|
|
58
|
-
* A typed, discriminated failure value emitted on the {@link SessionSignal}
|
|
59
|
-
* stream and attached to faulted states.
|
|
60
|
-
*
|
|
61
|
-
* The `kind` selects the category; `message` is a human-readable summary; the
|
|
62
|
-
* optional `cause` carries the underlying error (or any structured detail) for
|
|
63
|
-
* logging without forcing consumers to parse the message string.
|
|
64
|
-
*/
|
|
65
|
-
export interface ConductorFault {
|
|
66
|
-
/** Failure category — the discriminant consumers switch on. */
|
|
67
|
-
readonly kind: FaultKind;
|
|
68
|
-
/** Human-readable, single-line summary of what went wrong. */
|
|
69
|
-
readonly message: string;
|
|
70
|
-
/** Underlying error or structured detail, if any. */
|
|
71
|
-
readonly cause?: unknown;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Construct a {@link ConductorFault}. The single sanctioned way to mint a fault,
|
|
75
|
-
* so the shape stays uniform across every producer.
|
|
76
|
-
*
|
|
77
|
-
* @param kind the failure category
|
|
78
|
-
* @param message a human-readable, single-line summary
|
|
79
|
-
* @param cause optional underlying error or structured detail
|
|
80
|
-
*/
|
|
81
|
-
export declare function conductorFault(kind: FaultKind, message: string, cause?: unknown): ConductorFault;
|
|
82
|
-
/**
|
|
83
|
-
* The product-level event stream the conductor emits to its consumers (the
|
|
84
|
-
* interactive UI, the print/JSON mode, the JSON-RPC link).
|
|
85
|
-
*
|
|
86
|
-
* This is the conductor's **re-emitted surface** — distinct from the framework
|
|
87
|
-
* `AgentEvent` union. The conductor subscribes to the raw framework loop,
|
|
88
|
-
* layers persistence / auto-condense / fault handling on top, and projects the
|
|
89
|
-
* result down to this small, stable set of discriminated signals. Consumers
|
|
90
|
-
* switch on `kind` and never see a framework loop event directly.
|
|
91
|
-
*
|
|
92
|
-
* - `prompt` — the user's turn was committed to the conversation; `text`
|
|
93
|
-
* is the submitted prompt. Emitted the instant the turn is
|
|
94
|
-
* accepted (before the model replies) so a UI can echo the
|
|
95
|
-
* user message immediately rather than waiting for the first
|
|
96
|
-
* assistant token.
|
|
97
|
-
* - `text` — a chunk of assistant answer text streamed in.
|
|
98
|
-
* - `thinking` — a chunk of reasoning/thinking text streamed in.
|
|
99
|
-
* - `tool_start`— a tool invocation began (correlate by `id`).
|
|
100
|
-
* - `tool_update`— a running tool emitted partial progress (correlate by `id`);
|
|
101
|
-
* `name` is the tool name and `details` is the tool's own typed
|
|
102
|
-
* partial-result detail (e.g. the live `◆ Workflow` snapshot).
|
|
103
|
-
* - `tool_end` — a tool invocation finished (`ok` = no error).
|
|
104
|
-
* - `turn_end` — the assistant turn settled; `usage` reports token spend.
|
|
105
|
-
* - `persisted` — the latest node was committed to the transcript (`entryId`).
|
|
106
|
-
* - `compacted` — the transcript WAS condensed (emitted on completion, not at
|
|
107
|
-
* the start). `manual` marks a user-driven `/compact` — a view may then
|
|
108
|
-
* reset its visible transcript — versus mid-turn auto-compaction, where the
|
|
109
|
-
* display must keep the in-flight exchange on screen.
|
|
110
|
-
* - `fault` — a typed {@link ConductorFault} occurred. `transient` marks a
|
|
111
|
-
* fault surfaced purely as an in-turn notice (e.g. a fallback-model swap on
|
|
112
|
-
* provider overload) — the turn keeps running, so a consumer must NOT treat
|
|
113
|
-
* it as the turn's end (must not clear a busy/in-flight indicator on it).
|
|
114
|
-
* - `queue` — the pending-input queue changed; `count` is its new depth.
|
|
115
|
-
* - `idle` — the conductor has no in-flight work and is ready for input.
|
|
116
|
-
*/
|
|
117
|
-
export type SessionSignal = {
|
|
118
|
-
readonly kind: "prompt";
|
|
119
|
-
readonly text: string;
|
|
120
|
-
} | {
|
|
121
|
-
readonly kind: "text";
|
|
122
|
-
readonly delta: string;
|
|
123
|
-
} | {
|
|
124
|
-
readonly kind: "thinking";
|
|
125
|
-
readonly delta: string;
|
|
126
|
-
} | {
|
|
127
|
-
readonly kind: "tool_start";
|
|
128
|
-
readonly id: string;
|
|
129
|
-
readonly name: string;
|
|
130
|
-
} | {
|
|
131
|
-
readonly kind: "tool_update";
|
|
132
|
-
readonly id: string;
|
|
133
|
-
readonly name: string;
|
|
134
|
-
readonly details: unknown;
|
|
135
|
-
} | {
|
|
136
|
-
readonly kind: "tool_end";
|
|
137
|
-
readonly id: string;
|
|
138
|
-
readonly ok: boolean;
|
|
139
|
-
} | {
|
|
140
|
-
readonly kind: "turn_end";
|
|
141
|
-
readonly usage: Usage;
|
|
142
|
-
} | {
|
|
143
|
-
readonly kind: "persisted";
|
|
144
|
-
readonly entryId: string;
|
|
145
|
-
} | {
|
|
146
|
-
readonly kind: "compacted";
|
|
147
|
-
readonly manual?: boolean;
|
|
148
|
-
} | {
|
|
149
|
-
readonly kind: "fault";
|
|
150
|
-
readonly fault: ConductorFault;
|
|
151
|
-
readonly transient?: boolean;
|
|
152
|
-
} | {
|
|
153
|
-
readonly kind: "queue";
|
|
154
|
-
readonly count: number;
|
|
155
|
-
} | {
|
|
156
|
-
readonly kind: "idle";
|
|
157
|
-
};
|
|
158
|
-
/** The discriminant literals of {@link SessionSignal}, for filtering/logging. */
|
|
159
|
-
export type SignalKind = SessionSignal["kind"];
|
|
160
|
-
/** Extract a single member of {@link SessionSignal} by its `kind`. */
|
|
161
|
-
export type SignalOf<K extends SignalKind> = Extract<SessionSignal, {
|
|
162
|
-
kind: K;
|
|
163
|
-
}>;
|
|
164
|
-
/** A subscriber callback registered with {@link SessionConductor.subscribe}. */
|
|
165
|
-
export type SignalHandler = (signal: SessionSignal) => void;
|
|
166
|
-
/**
|
|
167
|
-
* The on-disk transcript schema namespace + version.
|
|
168
|
-
*
|
|
169
|
-
* A namespaced string (not a bare integer) so the format is self-describing and
|
|
170
|
-
* can evolve without colliding with any other versioned artifact in the app.
|
|
171
|
-
* This is deliberately the conductor's own vocabulary.
|
|
172
|
-
*/
|
|
173
|
-
export declare const TRANSCRIPT_SCHEMA: "indus/transcript@1";
|
|
174
|
-
/** The literal type of {@link TRANSCRIPT_SCHEMA}. */
|
|
175
|
-
export type TranscriptSchema = typeof TRANSCRIPT_SCHEMA;
|
|
176
|
-
/**
|
|
177
|
-
* The conversational role a {@link TranscriptEntry} node carries.
|
|
178
|
-
*
|
|
179
|
-
* Spans both the LLM-facing turns (`user`/`assistant`/`tool`) and the
|
|
180
|
-
* conductor's own bookkeeping nodes (`system` seed, `condense` markers, and
|
|
181
|
-
* `note` for app-injected context). Kept open at the product layer so the
|
|
182
|
-
* transcript can hold more than the framework's message roles.
|
|
183
|
-
*/
|
|
184
|
-
export type TranscriptRole = "user" | "assistant" | "tool" | "system" | "condense" | "note";
|
|
185
|
-
/**
|
|
186
|
-
* A single node in the on-disk transcript tree.
|
|
187
|
-
*
|
|
188
|
-
* The transcript is an append-only **tree**: every node names its `parent`
|
|
189
|
-
* (a root has `parent: null`), and the active leaf is tracked separately in
|
|
190
|
-
* {@link SessionHead}. Branching is moving the head to an earlier node; the next
|
|
191
|
-
* append becomes that node's child. `content` holds the framework
|
|
192
|
-
* {@link AgentMessage} payload so the node round-trips back into the agent loop;
|
|
193
|
-
* `meta` carries optional, non-LLM annotations (labels, condense bookkeeping,
|
|
194
|
-
* model/reasoning markers).
|
|
195
|
-
*
|
|
196
|
-
* Field names are the conductor's own (`parent`, `createdAt`, `meta`) — not the
|
|
197
|
-
* framework's persistence schema.
|
|
198
|
-
*/
|
|
199
|
-
export interface TranscriptEntry {
|
|
200
|
-
/** Stable unique node id (e.g. a ULID). */
|
|
201
|
-
readonly id: string;
|
|
202
|
-
/** Parent node id, or `null` for the transcript root. */
|
|
203
|
-
readonly parent: string | null;
|
|
204
|
-
/** Conversational role of this node. */
|
|
205
|
-
readonly role: TranscriptRole;
|
|
206
|
-
/** The framework message payload this node persists. */
|
|
207
|
-
readonly content: AgentMessage;
|
|
208
|
-
/** ISO-8601 creation timestamp. */
|
|
209
|
-
readonly createdAt: string;
|
|
210
|
-
/** Optional, non-LLM annotations keyed by name. */
|
|
211
|
-
readonly meta?: Readonly<Record<string, unknown>>;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* The head record of a persisted transcript: which session, and where its
|
|
215
|
-
* active leaf currently points.
|
|
216
|
-
*
|
|
217
|
-
* The `leaf` is the id of the most recently appended (or branched-to) node;
|
|
218
|
-
* walking `parent` links from `leaf` to a root reconstructs the active branch.
|
|
219
|
-
* `null` means an empty transcript (no nodes yet).
|
|
220
|
-
*/
|
|
221
|
-
export interface SessionHead {
|
|
222
|
-
/** Stable identifier of the session this transcript belongs to. */
|
|
223
|
-
readonly sessionId: string;
|
|
224
|
-
/** Id of the active leaf node, or `null` for an empty transcript. */
|
|
225
|
-
readonly leaf: string | null;
|
|
226
|
-
/**
|
|
227
|
-
* Cumulative session usage (tokens + cost) persisted alongside the head so
|
|
228
|
-
* resume can restore the running total instead of seeding zero. Optional and
|
|
229
|
-
* absent on legacy transcripts; the store rewrites the head line on every
|
|
230
|
-
* flush, keeping this current with the live tally.
|
|
231
|
-
*/
|
|
232
|
-
readonly usage?: Usage;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* A lightweight, resolved reference to one model card in the catalog.
|
|
236
|
-
*
|
|
237
|
-
* This is the *display/identity* projection of a framework {@link Model} — the
|
|
238
|
-
* minimum a UI needs to list, label, and select a model without holding the
|
|
239
|
-
* full model object. The matcher produces these; the conductor resolves the
|
|
240
|
-
* chosen one back to a full `Model` when it configures the agent.
|
|
241
|
-
*/
|
|
242
|
-
export interface ModelCardRef {
|
|
243
|
-
/** Canonical `"provider/modelId"` identifier (the catalog key). */
|
|
244
|
-
readonly id: string;
|
|
245
|
-
/** Owning provider. */
|
|
246
|
-
readonly provider: KnownProvider | string;
|
|
247
|
-
/** Provider-scoped model id (e.g. `"claude-sonnet-4"`). */
|
|
248
|
-
readonly modelId: string;
|
|
249
|
-
/** Human-readable display name. */
|
|
250
|
-
readonly name: string;
|
|
251
|
-
/** Whether this model exposes a reasoning/thinking budget. */
|
|
252
|
-
readonly reasoning: boolean;
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* A query against the model catalog/matcher.
|
|
256
|
-
*
|
|
257
|
-
* Resolution is a prioritized candidate pipeline: an explicit `provider`+`modelId`
|
|
258
|
-
* pins a single card; otherwise `pattern` is matched (exact id, `provider/`
|
|
259
|
-
* prefix, then glob/fuzzy) and narrowed by the optional capability filters.
|
|
260
|
-
* All fields are optional so an empty query means "the default candidate".
|
|
261
|
-
*/
|
|
262
|
-
export interface MatchQuery {
|
|
263
|
-
/** Free-form selector: an id, an alias, or a glob pattern. */
|
|
264
|
-
readonly pattern?: string;
|
|
265
|
-
/** Restrict candidates to this provider. */
|
|
266
|
-
readonly provider?: KnownProvider | string;
|
|
267
|
-
/** Pin a specific provider-scoped model id (used with {@link provider}). */
|
|
268
|
-
readonly modelId?: string;
|
|
269
|
-
/** Require reasoning/thinking support. */
|
|
270
|
-
readonly reasoning?: boolean;
|
|
271
|
-
/** Require image input support. */
|
|
272
|
-
readonly supportsImageInput?: boolean;
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* The coarse lifecycle phase of the conductor at a point in time.
|
|
276
|
-
*
|
|
277
|
-
* - `idle` — assembled and ready; no turn in flight.
|
|
278
|
-
* - `streaming` — an assistant turn is producing text/thinking.
|
|
279
|
-
* - `tooling` — a tool invocation is executing mid-turn.
|
|
280
|
-
* - `condensing` — the transcript is being condensed to fit the window.
|
|
281
|
-
* - `faulted` — the last turn ended in a {@link ConductorFault}.
|
|
282
|
-
*/
|
|
283
|
-
export type ConductorPhase = "idle" | "streaming" | "tooling" | "condensing" | "faulted";
|
|
284
|
-
/**
|
|
285
|
-
* An immutable snapshot of the conductor's observable state.
|
|
286
|
-
*
|
|
287
|
-
* Returned by {@link SessionConductor.snapshot} and resolved by
|
|
288
|
-
* {@link SessionConductor.submit}. It is a value, not a live view: every field
|
|
289
|
-
* is read-only and the object reflects the instant it was taken. Re-read with a
|
|
290
|
-
* fresh `snapshot()` to observe later changes.
|
|
291
|
-
*/
|
|
292
|
-
export interface ConductorState {
|
|
293
|
-
/** Coarse lifecycle phase at snapshot time. */
|
|
294
|
-
readonly phase: ConductorPhase;
|
|
295
|
-
/** The active transcript head (session id + current leaf). */
|
|
296
|
-
readonly head: SessionHead;
|
|
297
|
-
/** Cumulative token/cost spend across the session so far. */
|
|
298
|
-
readonly usage: Usage;
|
|
299
|
-
/**
|
|
300
|
-
* Tokens occupying the model's context window as of the most recent turn —
|
|
301
|
-
* the last assistant turn's reported usage, NOT the cumulative session spend.
|
|
302
|
-
* This is what the footer's `ctx:%` divides by the context window;
|
|
303
|
-
* {@link usage}.totalTokens grows unbounded across turns and would inflate it.
|
|
304
|
-
*/
|
|
305
|
-
readonly contextTokens: number;
|
|
306
|
-
/** Canonical id of the model currently bound to the session. */
|
|
307
|
-
readonly modelId: string;
|
|
308
|
-
/** The fault from the most recent turn, when {@link phase} is `"faulted"`. */
|
|
309
|
-
readonly fault?: ConductorFault;
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* How a queued input rejoins the conversation once the active turn settles.
|
|
313
|
-
*
|
|
314
|
-
* - `steer` — interrupt-style input meant to redirect the agent; drained
|
|
315
|
-
* ahead of plain follow-ups.
|
|
316
|
-
* - `followUp` — input that simply waits its turn after the current one ends.
|
|
317
|
-
*
|
|
318
|
-
* The conductor enqueues input under one of these modes when {@link SessionConductor.submit}
|
|
319
|
-
* is called while a turn is in flight, then drains the queue in order.
|
|
320
|
-
*/
|
|
321
|
-
export type QueueMode = "steer" | "followUp";
|
|
322
|
-
/**
|
|
323
|
-
* One entry in the conductor's pending-input queue: the {@link QueueMode} it was
|
|
324
|
-
* filed under and the raw user `text`. Surfaced by
|
|
325
|
-
* {@link SessionConductor.pendingInputs} so a UI can render what is waiting.
|
|
326
|
-
*/
|
|
327
|
-
export interface QueuedInput {
|
|
328
|
-
/** How this input will rejoin the conversation when drained. */
|
|
329
|
-
readonly mode: QueueMode;
|
|
330
|
-
/** The raw user message text held for a later turn. */
|
|
331
|
-
readonly text: string;
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* A point-in-time tally of the active session: message counts by role, tool
|
|
335
|
-
* activity, cumulative token spend, and total cost. Computed by
|
|
336
|
-
* {@link SessionConductor.stats} from the live message list plus the running
|
|
337
|
-
* usage carried on {@link ConductorState}.
|
|
338
|
-
*/
|
|
339
|
-
export interface SessionStats {
|
|
340
|
-
/** Identifier of the session these figures describe. */
|
|
341
|
-
readonly sessionId: string;
|
|
342
|
-
/** Number of user-role messages in the active branch. */
|
|
343
|
-
readonly userMessages: number;
|
|
344
|
-
/** Number of assistant-role messages in the active branch. */
|
|
345
|
-
readonly assistantMessages: number;
|
|
346
|
-
/** Number of tool invocations the assistant issued. */
|
|
347
|
-
readonly toolCalls: number;
|
|
348
|
-
/** Number of tool-result messages produced in reply. */
|
|
349
|
-
readonly toolResults: number;
|
|
350
|
-
/** Total message count across all roles. */
|
|
351
|
-
readonly totalMessages: number;
|
|
352
|
-
/** Cumulative token spend, broken out by category and totalled. */
|
|
353
|
-
readonly tokens: {
|
|
354
|
-
readonly input: number;
|
|
355
|
-
readonly output: number;
|
|
356
|
-
readonly cacheRead: number;
|
|
357
|
-
readonly cacheWrite: number;
|
|
358
|
-
readonly total: number;
|
|
359
|
-
};
|
|
360
|
-
/** Cumulative monetary cost of the session so far. */
|
|
361
|
-
readonly cost: number;
|
|
362
|
-
}
|
|
363
|
-
/** Options for {@link SessionConductor.executeBash}. */
|
|
364
|
-
export interface ExecuteBashOptions {
|
|
365
|
-
/**
|
|
366
|
-
* When `true`, the command's output is *not* recorded as a transcript note,
|
|
367
|
-
* so it never re-enters the agent's context. Defaults to `false`.
|
|
368
|
-
*/
|
|
369
|
-
readonly excludeFromContext?: boolean;
|
|
370
|
-
}
|
|
371
|
-
/** The settled result of {@link SessionConductor.executeBash}. */
|
|
372
|
-
export interface BashOutcome {
|
|
373
|
-
/** Combined stdout + stderr of the command. */
|
|
374
|
-
readonly output: string;
|
|
375
|
-
/** Process exit code (`0` on success; non-zero, or `1` on a thrown error). */
|
|
376
|
-
readonly exitCode: number;
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* The minimal file-checkpoint surface the conductor drives for rewind (#24).
|
|
380
|
-
*
|
|
381
|
-
* The product mints a concrete `CheckpointStore` (in `boot/runners/checkpoint.ts`),
|
|
382
|
-
* injects it into the deck's `ctx.framework` bag under the `'checkpoint'` key so
|
|
383
|
-
* the framework's write/edit tools record pre-mutation file content against the
|
|
384
|
-
* active transcript node, and ALSO hands it to the conductor as this port. The
|
|
385
|
-
* conductor pins the active node id as its head advances ({@link setActiveNodeId})
|
|
386
|
-
* so a turn's edits key to the node that was active before the turn, and exposes
|
|
387
|
-
* {@link restore}/{@link hasSnapshot} so the tree picker can roll the working tree
|
|
388
|
-
* back when navigating to an earlier node.
|
|
389
|
-
*
|
|
390
|
-
* Declared as a tiny structural port (not the concrete store) so the conductor
|
|
391
|
-
* stays free of any boot-layer import — the product's store satisfies it by shape.
|
|
392
|
-
*/
|
|
393
|
-
export interface CheckpointPort {
|
|
394
|
-
/**
|
|
395
|
-
* Pin the transcript node subsequent file snapshots are filed under. Called by
|
|
396
|
-
* the conductor as its head advances (at turn start) so a turn's edits key to
|
|
397
|
-
* the node active before the turn ran.
|
|
398
|
-
*
|
|
399
|
-
* @param id the active transcript node id, or `null` to fall back to the root
|
|
400
|
-
*/
|
|
401
|
-
setActiveNodeId(id: string | null): void;
|
|
402
|
-
/** Whether a node has ANY recorded file snapshot (the picker's restore gate). */
|
|
403
|
-
hasSnapshot(nodeId: string): boolean;
|
|
404
|
-
/**
|
|
405
|
-
* Roll the working tree back to a node's recorded state, rewriting each tracked
|
|
406
|
-
* file to its pre-mutation content (deleting files recorded as absent). A safe
|
|
407
|
-
* no-op when the node has no snapshot.
|
|
408
|
-
*
|
|
409
|
-
* @param nodeId the transcript node whose file state to restore to
|
|
410
|
-
* @returns the absolute paths that were written or deleted
|
|
411
|
-
*/
|
|
412
|
-
restore(nodeId: string): string[];
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Options that configure a {@link SessionConductor} at assembly time.
|
|
416
|
-
*
|
|
417
|
-
* Only {@link modelId} is required; everything else has a sensible default
|
|
418
|
-
* resolved by the conductor factory. The shape is intentionally small — richer
|
|
419
|
-
* wiring (MCP, memory, provider routing) is attached by the factory, not passed
|
|
420
|
-
* through this surface.
|
|
421
|
-
*/
|
|
422
|
-
export interface SessionConductorOptions {
|
|
423
|
-
/** Canonical id of the model to bind the session to. */
|
|
424
|
-
readonly modelId: string;
|
|
425
|
-
/** Initial system prompt seeding the conversation. */
|
|
426
|
-
readonly system?: string;
|
|
427
|
-
/** Tools made available to the agent for this session. */
|
|
428
|
-
readonly tools?: AgentTool[];
|
|
429
|
-
/** Initial reasoning effort for models that support it. */
|
|
430
|
-
readonly thinking?: ThinkingLevel;
|
|
431
|
-
/**
|
|
432
|
-
* Canonical id of a model to fall back to when the bound model is overloaded
|
|
433
|
-
* (HTTP 529 / "overloaded") mid-turn (`--fallback-model`). When set, an
|
|
434
|
-
* overload that exhausts the transient-retry budget swaps to this model once
|
|
435
|
-
* per turn and retries instead of surfacing a terminal fault. Absent disables
|
|
436
|
-
* the swap entirely (behavior-preserving default).
|
|
437
|
-
*/
|
|
438
|
-
readonly fallbackModelId?: string;
|
|
439
|
-
/**
|
|
440
|
-
* Per-provider indus-gateway base URLs ("server mode"), keyed by provider slug
|
|
441
|
-
* (e.g. `{ minimax: "http://host/gateway/minimax", sarvam: "…/gateway/sarvam" }`).
|
|
442
|
-
* Set by the session runner for every gateway-eligible provider the user has no
|
|
443
|
-
* local key for but holds a valid server token. At EVERY model bind (including a
|
|
444
|
-
* runtime `/model` switch) the conductor looks up the BOUND model's provider in
|
|
445
|
-
* this map and, when present, binds a CLONE of the framework model with its
|
|
446
|
-
* `baseUrl` swapped to that URL — so any server-tier model routes through the
|
|
447
|
-
* quota-enforcing server while the session token (via {@link getApiKey})
|
|
448
|
-
* authenticates it. A provider absent from the map keeps the direct path.
|
|
449
|
-
*/
|
|
450
|
-
readonly gatewayBaseUrls?: Record<string, string>;
|
|
451
|
-
/** Working directory the session is scoped to (defaults to process cwd). */
|
|
452
|
-
readonly workspace?: string;
|
|
453
|
-
/**
|
|
454
|
-
* Directory to persist the transcript into. When set, the conductor backs its
|
|
455
|
-
* {@link TranscriptStore} with a filesystem backend rooted here (one
|
|
456
|
-
* `<sessionId>.ndjson` per session) so the conversation survives the process
|
|
457
|
-
* and can be resumed. Absent (or when a `store` dep is injected) keeps the
|
|
458
|
-
* default in-memory store — nothing is written to disk.
|
|
459
|
-
*/
|
|
460
|
-
readonly sessionsDir?: string;
|
|
461
|
-
/** Condense the transcript automatically when it nears the window (default on). */
|
|
462
|
-
readonly autoCompact?: boolean;
|
|
463
|
-
/**
|
|
464
|
-
* Resolve the credential for a provider on each call. Threaded to the framework
|
|
465
|
-
* `Agent`, which calls it per request so short-lived OAuth access tokens (e.g.
|
|
466
|
-
* `openai-codex`) can be refreshed and providers with no env-var mapping still
|
|
467
|
-
* authenticate. Returning `undefined` lets the framework fall back to its own
|
|
468
|
-
* environment lookup. May be sync or async.
|
|
469
|
-
*/
|
|
470
|
-
readonly getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;
|
|
471
|
-
/**
|
|
472
|
-
* The hard per-tool permission gate, threaded straight to the framework `Agent`.
|
|
473
|
-
* The framework awaits it on the validated arguments immediately before each
|
|
474
|
-
* tool runs and either proceeds (optionally with substituted input) or
|
|
475
|
-
* short-circuits to an `isError` tool result.
|
|
476
|
-
*
|
|
477
|
-
* Supplied as a **factory** `(currentMode, requestApproval?) => CanUseToolFn`:
|
|
478
|
-
* the conductor calls it once with a getter onto its OWN live permission mode,
|
|
479
|
-
* so the gate it returns reads `permissionMode()` live — a
|
|
480
|
-
* {@link SessionConductor.setPermissionMode} retargets later tool calls with no
|
|
481
|
-
* agent rebuild. (A caller that does not care about the live mode can simply
|
|
482
|
-
* ignore the getter and close over a fixed gate.)
|
|
483
|
-
*
|
|
484
|
-
* The OPTIONAL second argument is a stable {@link ApprovalResolver} delegate the
|
|
485
|
-
* conductor owns: it forwards to whatever resolver was installed via
|
|
486
|
-
* {@link SessionConductor.setApprovalResolver} at call time (and denies when none
|
|
487
|
-
* is installed). An interactive front-end can therefore wire its approval overlay
|
|
488
|
-
* AFTER the conductor (and its gate) are built — the factory just closes over the
|
|
489
|
-
* delegate. A factory that ignores it keeps today's behavior.
|
|
490
|
-
*
|
|
491
|
-
* Optional everywhere: omit it and the framework allows every tool (today's
|
|
492
|
-
* allow-all behavior).
|
|
493
|
-
*/
|
|
494
|
-
readonly canUseTool?: (currentMode: () => PermissionMode, requestApproval?: ApprovalResolver) => CanUseToolFn;
|
|
495
|
-
/**
|
|
496
|
-
* The permission mode the session opens in. Seeds {@link SessionConductor.permissionMode};
|
|
497
|
-
* defaults to `"default"` when absent. The mode is consulted live by the
|
|
498
|
-
* {@link canUseTool} gate, so a later {@link SessionConductor.setPermissionMode}
|
|
499
|
-
* changes subsequent tool calls without rebuilding the gate.
|
|
500
|
-
*/
|
|
501
|
-
readonly permissionMode?: PermissionMode;
|
|
502
|
-
/**
|
|
503
|
-
* Directory the approved plan-mode plan is persisted into. When the model calls
|
|
504
|
-
* `exit_plan_mode` and the user approves leaving plan mode, the conductor writes
|
|
505
|
-
* the plan as a slug-named markdown file under `<plansDir>/plans/`. Absent keeps
|
|
506
|
-
* the handshake (mode flip + context injection) but skips the disk write —
|
|
507
|
-
* tests and headless probes can run the round-trip without a filesystem.
|
|
508
|
-
*/
|
|
509
|
-
readonly plansDir?: string;
|
|
510
|
-
/**
|
|
511
|
-
* The per-session file-checkpoint store for rewind (#24), or `undefined` to run
|
|
512
|
-
* without code checkpointing. When present, the conductor pins the active
|
|
513
|
-
* transcript node on it (the head leaf at turn start) so a turn's file edits key
|
|
514
|
-
* to the node that was active before the turn, and {@link SessionConductor.restoreCode}
|
|
515
|
-
* delegates to it so the tree picker can revert the working tree.
|
|
516
|
-
*/
|
|
517
|
-
readonly checkpoint?: CheckpointPort;
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* What a manual {@link SessionConductor.condense} run amounted to — the honest
|
|
521
|
-
* completion vocabulary `/compact` reports from (see the method doc).
|
|
522
|
-
*/
|
|
523
|
-
export type CondenseOutcome = "condensed" | "nothing" | "cancelled" | "failed" | "busy";
|
|
524
|
-
/**
|
|
525
|
-
* The conductor of a single coding-agent session.
|
|
526
|
-
*
|
|
527
|
-
* It owns the framework `Agent`, threads persistence and auto-condense through
|
|
528
|
-
* the turn loop, and exposes a small product API: submit input, subscribe to
|
|
529
|
-
* the {@link SessionSignal} stream, abort the in-flight turn, read an immutable
|
|
530
|
-
* {@link ConductorState} snapshot, resume a persisted session, and optionally
|
|
531
|
-
* rotate the active model. This is the surface all three run modes drive.
|
|
532
|
-
*/
|
|
533
|
-
export interface SessionConductor {
|
|
534
|
-
/**
|
|
535
|
-
* Submit user input as a new turn and run the agent to settle.
|
|
536
|
-
*
|
|
537
|
-
* Streams {@link SessionSignal}s to subscribers as the turn progresses and
|
|
538
|
-
* resolves to the immutable {@link ConductorState} once the turn settles
|
|
539
|
-
* (success or fault).
|
|
540
|
-
*
|
|
541
|
-
* When a turn is already in flight the input is **not** dropped: it is handed
|
|
542
|
-
* to {@link enqueue} and run automatically as a later turn once the current one
|
|
543
|
-
* settles. In that case `submit` resolves immediately with the current
|
|
544
|
-
* snapshot rather than waiting for the queued turn.
|
|
545
|
-
*
|
|
546
|
-
* @param input the user message text for this turn
|
|
547
|
-
*/
|
|
548
|
-
submit(input: string): Promise<ConductorState>;
|
|
549
|
-
/**
|
|
550
|
-
* Queue an input to run as a future turn. Used directly, or reached via
|
|
551
|
-
* {@link submit} when the conductor is busy. Queued items drain in order after
|
|
552
|
-
* the active turn settles, each running as its own turn. Emits a
|
|
553
|
-
* `{ kind: "queue" }` signal so a UI can reflect the new depth.
|
|
554
|
-
*
|
|
555
|
-
* @param input the user message text to hold for a later turn
|
|
556
|
-
* @param mode how it rejoins the conversation when drained (default `"followUp"`)
|
|
557
|
-
*/
|
|
558
|
-
enqueue(input: string, mode?: QueueMode): void;
|
|
559
|
-
/** How many inputs are currently waiting in the pending-input queue. */
|
|
560
|
-
pendingCount(): number;
|
|
561
|
-
/** A read-only view of the queued inputs, oldest first. */
|
|
562
|
-
pendingInputs(): readonly QueuedInput[];
|
|
563
|
-
/** Discard every queued input. Emits a `{ kind: "queue" }` signal. */
|
|
564
|
-
clearQueue(): void;
|
|
565
|
-
/**
|
|
566
|
-
* Promote the NEWEST queued input to run immediately: the in-flight turn (if
|
|
567
|
-
* any) is aborted — its work stops — while the rest of the queue is kept, and
|
|
568
|
-
* the promoted input runs as the very next turn. The user-facing "run my new
|
|
569
|
-
* message NOW" affordance for a long/stuck turn (issue #19), distinct from
|
|
570
|
-
* {@link abort} (which stops everything and clears the queue). Returns `false`
|
|
571
|
-
* when no input is queued.
|
|
572
|
-
*/
|
|
573
|
-
steerNow(): boolean;
|
|
574
|
-
/**
|
|
575
|
-
* Remove and return the text of the most-recently queued input, or `undefined`
|
|
576
|
-
* when the queue is empty. Lets a UI pop the last entry back into its prompt.
|
|
577
|
-
*/
|
|
578
|
-
dequeueLast(): string | undefined;
|
|
579
|
-
/**
|
|
580
|
-
* The live transcript messages for the active branch.
|
|
581
|
-
*
|
|
582
|
-
* A read-through onto the wrapped agent's running message list — what the
|
|
583
|
-
* interactive UI renders as the conversation. The returned array is the
|
|
584
|
-
* current contents at call time; re-read to observe later turns.
|
|
585
|
-
*/
|
|
586
|
-
messages(): readonly AgentMessage[];
|
|
587
|
-
/**
|
|
588
|
-
* The full framework {@link Model} object currently bound to the session, or
|
|
589
|
-
* `undefined` when none could be resolved. Tracks the active selection across
|
|
590
|
-
* {@link selectModel}/{@link cycleModel} changes.
|
|
591
|
-
*/
|
|
592
|
-
model(): Model<any> | undefined;
|
|
593
|
-
/** Whether a turn is currently in flight (guards re-entrant submit). */
|
|
594
|
-
isBusy(): boolean;
|
|
595
|
-
/**
|
|
596
|
-
* The model catalog entries a picker lists, best-first. Derived from the
|
|
597
|
-
* configured model matcher; returns `[]` when no matcher is wired in.
|
|
598
|
-
*/
|
|
599
|
-
availableModels(): ModelCardRef[];
|
|
600
|
-
/**
|
|
601
|
-
* Bind a model by canonical id for subsequent turns. The companion of
|
|
602
|
-
* {@link cycleModel}; both route through the same selection path.
|
|
603
|
-
*
|
|
604
|
-
* @param id canonical id of the model to switch to
|
|
605
|
-
*/
|
|
606
|
-
selectModel(id: string): void;
|
|
607
|
-
/**
|
|
608
|
-
* Replace the server-tier gateway routing map and immediately re-bind the
|
|
609
|
-
* currently selected model against it (without changing which model is
|
|
610
|
-
* selected). Lets an interactive mid-session sign-in (see `/login` ->
|
|
611
|
-
* "Indus Server") take effect right away: the gateway base-url map is
|
|
612
|
-
* otherwise frozen at conductor construction, so a login that happens after
|
|
613
|
-
* boot would silently never route the bound model through the gateway even
|
|
614
|
-
* though the per-request key resolver already started vending the fresh
|
|
615
|
-
* session token as the provider key.
|
|
616
|
-
*
|
|
617
|
-
* @param map provider id -> gateway base URL, as produced by
|
|
618
|
-
* `resolveServerGatewayUrls` for the current vault/token state
|
|
619
|
-
*/
|
|
620
|
-
updateGatewayBaseUrls(map: Record<string, string>): void;
|
|
621
|
-
/**
|
|
622
|
-
* Replace the agent's tool deck for subsequent turns.
|
|
623
|
-
*
|
|
624
|
-
* Used by `/mcp` to inject the tools of freshly-connected MCP servers into the
|
|
625
|
-
* live session (and to drop them again on disconnect). The conductor merges the
|
|
626
|
-
* passed list with its own seed deck (the built-in tools the session was
|
|
627
|
-
* assembled with), so callers pass only the *extra* tools to add — never the
|
|
628
|
-
* built-ins, which are preserved automatically. Pass `[]` to clear the extras
|
|
629
|
-
* and fall back to the seed deck alone.
|
|
630
|
-
*
|
|
631
|
-
* @param tools the additional tools to layer over the seed deck
|
|
632
|
-
*/
|
|
633
|
-
registerTools(tools: AgentTool[]): void;
|
|
634
|
-
/**
|
|
635
|
-
* Manually run the transcript-condense path (`/compact`) and report what
|
|
636
|
-
* happened, so the caller can give honest feedback instead of announcing
|
|
637
|
-
* "condensed" regardless:
|
|
638
|
-
* - `"condensed"` — the branch shrank and was rebound (emits `compacted`).
|
|
639
|
-
* - `"nothing"` — nothing older to fold (single-turn session, or already
|
|
640
|
-
* compacted); the transcript is untouched.
|
|
641
|
-
* - `"cancelled"` — {@link cancelCondense} fired mid-run; the digest was
|
|
642
|
-
* discarded and the transcript is untouched.
|
|
643
|
-
* - `"failed"` — the condense hook threw; a typed fault was emitted.
|
|
644
|
-
* - `"busy"` — a turn is in flight; compact after it settles (or abort
|
|
645
|
-
* it first).
|
|
646
|
-
* While the condense runs, {@link submit} queues instead of racing it, and the
|
|
647
|
-
* queue drains once the condense settles.
|
|
648
|
-
*/
|
|
649
|
-
condense(): Promise<CondenseOutcome>;
|
|
650
|
-
/**
|
|
651
|
-
* Cancel an in-flight manual {@link condense} (the `/compact` Esc affordance).
|
|
652
|
-
* The summarizer's result is discarded and the transcript stays untouched; a
|
|
653
|
-
* no-op when no manual condense is running.
|
|
654
|
-
*/
|
|
655
|
-
cancelCondense(): void;
|
|
656
|
-
/**
|
|
657
|
-
* Branch the transcript from a prior node. A new branch is opened whose parent
|
|
658
|
-
* is `entryId`; the agent's message list is rebound to that branch's root→leaf
|
|
659
|
-
* path. The conductor's head advances onto the chosen node.
|
|
660
|
-
*
|
|
661
|
-
* @param entryId the transcript node to branch from
|
|
662
|
-
*/
|
|
663
|
-
fork(entryId: string): Promise<void>;
|
|
664
|
-
/**
|
|
665
|
-
* Move the active leaf to `nodeId`, rebuild that branch's root→leaf path, and
|
|
666
|
-
* rebind the agent's message list to it. Used to walk between existing
|
|
667
|
-
* branches without forking a new one.
|
|
668
|
-
*
|
|
669
|
-
* @param nodeId the transcript node to make the active leaf
|
|
670
|
-
*/
|
|
671
|
-
navigateTree(nodeId: string): Promise<void>;
|
|
672
|
-
/**
|
|
673
|
-
* Roll the working tree back to a transcript node's file-checkpoint state
|
|
674
|
-
* (rewind, #24). Reverts every file the node tracked to its pre-mutation content
|
|
675
|
-
* (deleting files that were absent at that point). Additive and code-only: it
|
|
676
|
-
* does NOT move the conversation head — pair it with {@link navigateTree}/{@link fork}
|
|
677
|
-
* for a combined "restore code and conversation". A safe no-op when no checkpoint
|
|
678
|
-
* store is wired or the node has no recorded snapshot.
|
|
679
|
-
*
|
|
680
|
-
* @param nodeId the transcript node whose file state to restore to
|
|
681
|
-
* @returns the absolute paths that were restored (written or deleted)
|
|
682
|
-
*/
|
|
683
|
-
restoreCode(nodeId: string): Promise<string[]>;
|
|
684
|
-
/**
|
|
685
|
-
* Whether the tree picker should offer "restore code" for a node — i.e. whether
|
|
686
|
-
* the node has any recorded file-checkpoint snapshot. `false` when no checkpoint
|
|
687
|
-
* store is wired or the node never mutated files, so the picker's restore option
|
|
688
|
-
* is a safe no-op there.
|
|
689
|
-
*
|
|
690
|
-
* @param nodeId the transcript node to test
|
|
691
|
-
*/
|
|
692
|
-
codeRestoreInfo(nodeId: string): Promise<{
|
|
693
|
-
readonly canRestore: boolean;
|
|
694
|
-
}>;
|
|
695
|
-
/**
|
|
696
|
-
* Run a shell command in the session workspace, returning its combined
|
|
697
|
-
* stdout+stderr and exit code. Unless `opts.excludeFromContext` is set, the
|
|
698
|
-
* output is recorded as a transcript note so it re-enters the agent's context.
|
|
699
|
-
* Never throws: a spawn/exec failure resolves to a non-zero {@link BashOutcome}.
|
|
700
|
-
*
|
|
701
|
-
* @param command the shell command to execute
|
|
702
|
-
* @param opts execution options
|
|
703
|
-
*/
|
|
704
|
-
executeBash(command: string, opts?: ExecuteBashOptions): Promise<BashOutcome>;
|
|
705
|
-
/** A point-in-time {@link SessionStats} tally for the active session. */
|
|
706
|
-
stats(): SessionStats;
|
|
707
|
-
/**
|
|
708
|
-
* Render the session's cumulative cost + token usage as a human-readable,
|
|
709
|
-
* multi-line report. Drives the `/cost` slash command without the caller
|
|
710
|
-
* having to format the {@link SessionStats} figures itself.
|
|
711
|
-
*/
|
|
712
|
-
costReport(): string;
|
|
713
|
-
/** The reasoning effort currently applied to the session. */
|
|
714
|
-
thinkingLevel(): ThinkingLevel;
|
|
715
|
-
/**
|
|
716
|
-
* Set the reasoning effort for subsequent turns. Applied to the agent when it
|
|
717
|
-
* exposes a setter; otherwise stored and applied on the next model bind.
|
|
718
|
-
*
|
|
719
|
-
* @param level the reasoning effort to apply
|
|
720
|
-
*/
|
|
721
|
-
setThinkingLevel(level: ThinkingLevel): void;
|
|
722
|
-
/**
|
|
723
|
-
* Advance the reasoning effort to the next level in the cycle, applying it, and
|
|
724
|
-
* return the newly-selected level.
|
|
725
|
-
*/
|
|
726
|
-
cycleThinkingLevel(): ThinkingLevel;
|
|
727
|
-
/**
|
|
728
|
-
* The permission mode currently in effect. The live `canUseTool` gate reads
|
|
729
|
-
* this on every tool call, so the value reflects the most recent
|
|
730
|
-
* {@link setPermissionMode}.
|
|
731
|
-
*/
|
|
732
|
-
permissionMode(): PermissionMode;
|
|
733
|
-
/**
|
|
734
|
-
* Switch the permission mode for subsequent tool calls. The gate consults the
|
|
735
|
-
* mode live (via a getter), so this takes effect on the next tool call with no
|
|
736
|
-
* agent rebuild. A no-op-equivalent when no gate was wired (the conductor still
|
|
737
|
-
* tracks the mode for the UI).
|
|
738
|
-
*
|
|
739
|
-
* @param mode the permission mode to apply
|
|
740
|
-
*/
|
|
741
|
-
setPermissionMode(mode: PermissionMode): void;
|
|
742
|
-
/**
|
|
743
|
-
* Install (or clear) the host approval resolver an `ask` decision routes to.
|
|
744
|
-
*
|
|
745
|
-
* The `canUseTool` gate consults a STABLE delegate the conductor owns; this
|
|
746
|
-
* method swaps the resolver behind that delegate, so an interactive front-end
|
|
747
|
-
* can wire its approval overlay AFTER the conductor (and its gate) are built —
|
|
748
|
-
* the exact post-mount install the React console needs. Passing `undefined`
|
|
749
|
-
* clears it (an `ask` then deterministically denies, the non-interactive
|
|
750
|
-
* default). A no-op-equivalent when no gate was wired; the resolver is simply
|
|
751
|
-
* never consulted.
|
|
752
|
-
*
|
|
753
|
-
* @param resolver the resolver to consult on an `ask`, or `undefined` to clear
|
|
754
|
-
*/
|
|
755
|
-
setApprovalResolver(resolver: ApprovalResolver | undefined): void;
|
|
756
|
-
/**
|
|
757
|
-
* Toggle plan mode on or off.
|
|
758
|
-
*
|
|
759
|
-
* Entering plan mode (`true`) captures the current mode as the pre-plan mode and
|
|
760
|
-
* switches to `"plan"` (read-only — the gate blocks every mutating tool).
|
|
761
|
-
* Leaving (`false`) restores the captured pre-plan mode (or `"default"` when none
|
|
762
|
-
* was captured). Idempotent: toggling on while already in plan mode is a no-op,
|
|
763
|
-
* and toggling off when not in plan mode restores/keeps `"default"`. Drives the
|
|
764
|
-
* `/plan` command and the Shift+Tab toggle, and is the same path the conductor's
|
|
765
|
-
* own `enter_plan_mode` / approved `exit_plan_mode` handshake uses.
|
|
766
|
-
*
|
|
767
|
-
* @param on `true` to enter plan mode, `false` to leave it
|
|
768
|
-
* @returns the permission mode in effect after the toggle
|
|
769
|
-
*/
|
|
770
|
-
togglePlanMode(on: boolean): PermissionMode;
|
|
771
|
-
/**
|
|
772
|
-
* Advance the permission mode to the NEXT mode in the fixed cycle and return the
|
|
773
|
-
* new mode. The order is `default → acceptEdits → plan → bypass → (wrap)
|
|
774
|
-
* default`; the `"bypassPermissions"` alias is folded to `"bypass"` when reading
|
|
775
|
-
* the current mode so the cycle is stable.
|
|
776
|
-
*
|
|
777
|
-
* Built on top of {@link setPermissionMode}, so the live `canUseTool` gate (which
|
|
778
|
-
* reads {@link permissionMode} on every call) picks the new mode up immediately
|
|
779
|
-
* with no agent rebuild. Plan bookkeeping is preserved: ENTERING `"plan"` captures
|
|
780
|
-
* the pre-plan mode exactly as {@link togglePlanMode} does, so a later round-trip
|
|
781
|
-
* restores the prior mode; LEAVING `"plan"` (cycling `plan → bypass`) is a plain
|
|
782
|
-
* mode change — it does NOT run the `exit_plan_mode` approval handshake, since a
|
|
783
|
-
* manual cycle is not a plan exit. Drives the Shift+Tab cycle; {@link togglePlanMode}
|
|
784
|
-
* remains the path `/plan` uses.
|
|
785
|
-
*
|
|
786
|
-
* @returns the permission mode in effect after the advance
|
|
787
|
-
*/
|
|
788
|
-
cyclePermissionMode(): PermissionMode;
|
|
789
|
-
/**
|
|
790
|
-
* The mode captured when plan mode was last entered, restored on exit — or
|
|
791
|
-
* `undefined` when not currently in (or paused from) plan mode. Exposed so a UI
|
|
792
|
-
* (and the round-trip tests) can observe the Enter/Exit pairing.
|
|
793
|
-
*/
|
|
794
|
-
prePlanMode(): PermissionMode | undefined;
|
|
795
|
-
/** The human-readable session name, or `undefined` when none is set. */
|
|
796
|
-
sessionName(): string | undefined;
|
|
797
|
-
/**
|
|
798
|
-
* Assign a human-readable name to the session.
|
|
799
|
-
*
|
|
800
|
-
* @param name the display name to store
|
|
801
|
-
*/
|
|
802
|
-
setSessionName(name: string): void;
|
|
803
|
-
/**
|
|
804
|
-
* Register a handler for the {@link SessionSignal} stream.
|
|
805
|
-
*
|
|
806
|
-
* @param handler invoked for every emitted signal
|
|
807
|
-
* @returns an unsubscribe function that removes the handler
|
|
808
|
-
*/
|
|
809
|
-
subscribe(handler: SignalHandler): () => void;
|
|
810
|
-
/** Cancel the in-flight turn, if any; emits an `aborted` fault signal. */
|
|
811
|
-
abort(): void;
|
|
812
|
-
/** Read an immutable snapshot of the current {@link ConductorState}. */
|
|
813
|
-
snapshot(): ConductorState;
|
|
814
|
-
/**
|
|
815
|
-
* Restore a previously persisted session, replacing the current transcript
|
|
816
|
-
* and rebinding the agent to the restored model/leaf.
|
|
817
|
-
*
|
|
818
|
-
* @param sessionId the persisted session to resume
|
|
819
|
-
*/
|
|
820
|
-
resume(sessionId: string): Promise<void>;
|
|
821
|
-
/**
|
|
822
|
-
* Abandon the current conversation and start a fresh, empty session.
|
|
823
|
-
*
|
|
824
|
-
* Drops the agent's message history, opens a new session id (so later turns
|
|
825
|
-
* persist separately, leaving the prior transcript intact on disk), zeroes the
|
|
826
|
-
* usage tally, clears the pending-input queue and session name, and settles to
|
|
827
|
-
* `idle`. Emits an `idle` signal so a subscribed UI re-renders the now-empty
|
|
828
|
-
* conversation. This is what `/clear` (and `/new`) drive.
|
|
829
|
-
*/
|
|
830
|
-
newSession(): Promise<void>;
|
|
831
|
-
/**
|
|
832
|
-
* Rotate the active model for subsequent turns. Optional: not every assembly
|
|
833
|
-
* supports mid-session model changes.
|
|
834
|
-
*
|
|
835
|
-
* @param id canonical id of the model to switch to
|
|
836
|
-
*/
|
|
837
|
-
cycleModel?(id: string): void;
|
|
838
|
-
}
|