@gajae-code/coding-agent 0.3.1 → 0.4.0

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.
Files changed (166) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +1 -1
  3. package/dist/types/cli/args.d.ts +2 -0
  4. package/dist/types/commands/launch.d.ts +6 -0
  5. package/dist/types/config/model-profile-activation.d.ts +30 -0
  6. package/dist/types/config/model-profiles.d.ts +19 -0
  7. package/dist/types/config/model-registry.d.ts +25 -10
  8. package/dist/types/config/model-resolver.d.ts +1 -1
  9. package/dist/types/config/models-config-schema.d.ts +84 -0
  10. package/dist/types/config/settings-schema.d.ts +15 -0
  11. package/dist/types/edit/diff.d.ts +16 -0
  12. package/dist/types/edit/modes/replace.d.ts +7 -0
  13. package/dist/types/extensibility/gjc-plugins/activation.d.ts +14 -0
  14. package/dist/types/extensibility/gjc-plugins/index.d.ts +9 -0
  15. package/dist/types/extensibility/gjc-plugins/injection.d.ts +31 -0
  16. package/dist/types/extensibility/gjc-plugins/loader.d.ts +3 -0
  17. package/dist/types/extensibility/gjc-plugins/paths.d.ts +8 -0
  18. package/dist/types/extensibility/gjc-plugins/schema.d.ts +3 -0
  19. package/dist/types/extensibility/gjc-plugins/state.d.ts +9 -0
  20. package/dist/types/extensibility/gjc-plugins/tools.d.ts +8 -0
  21. package/dist/types/extensibility/gjc-plugins/types.d.ts +64 -0
  22. package/dist/types/extensibility/gjc-plugins/validation.d.ts +4 -0
  23. package/dist/types/extensibility/skills.d.ts +9 -1
  24. package/dist/types/gjc-runtime/state-runtime.d.ts +22 -0
  25. package/dist/types/harness-control-plane/storage.d.ts +7 -0
  26. package/dist/types/lsp/client.d.ts +1 -0
  27. package/dist/types/main.d.ts +10 -1
  28. package/dist/types/modes/bridge/bridge-mode.d.ts +2 -0
  29. package/dist/types/modes/components/custom-provider-wizard.d.ts +10 -0
  30. package/dist/types/modes/components/model-selector.d.ts +6 -1
  31. package/dist/types/modes/components/provider-onboarding-selector.d.ts +1 -1
  32. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  33. package/dist/types/modes/prompt-action-autocomplete.d.ts +2 -2
  34. package/dist/types/modes/rpc/rpc-client.d.ts +9 -1
  35. package/dist/types/modes/rpc/rpc-types.d.ts +179 -2
  36. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +57 -0
  37. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +16 -1
  38. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +47 -0
  39. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +7 -0
  40. package/dist/types/modes/shared/agent-wire/handshake.d.ts +11 -1
  41. package/dist/types/modes/shared/agent-wire/protocol.d.ts +3 -1
  42. package/dist/types/modes/shared/agent-wire/responses.d.ts +1 -1
  43. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +27 -0
  44. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +68 -0
  45. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +161 -0
  46. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +61 -0
  47. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +114 -0
  48. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +39 -0
  49. package/dist/types/modes/theme/theme.d.ts +2 -1
  50. package/dist/types/modes/types.d.ts +1 -0
  51. package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
  52. package/dist/types/sdk.d.ts +8 -1
  53. package/dist/types/session/agent-session.d.ts +10 -0
  54. package/dist/types/session/blob-store.d.ts +17 -0
  55. package/dist/types/session/messages.d.ts +3 -0
  56. package/dist/types/session/session-storage.d.ts +6 -0
  57. package/dist/types/skill-state/active-state.d.ts +13 -0
  58. package/dist/types/task/executor.d.ts +1 -0
  59. package/dist/types/thinking.d.ts +3 -2
  60. package/dist/types/tools/hindsight-recall.d.ts +0 -2
  61. package/dist/types/tools/hindsight-reflect.d.ts +0 -2
  62. package/dist/types/tools/hindsight-retain.d.ts +0 -2
  63. package/dist/types/tools/index.d.ts +7 -4
  64. package/package.json +9 -7
  65. package/src/cli/args.ts +10 -0
  66. package/src/cli.ts +14 -0
  67. package/src/commands/harness.ts +192 -7
  68. package/src/commands/launch.ts +8 -0
  69. package/src/commands/ultragoal.ts +1 -21
  70. package/src/config/model-equivalence.ts +1 -1
  71. package/src/config/model-profile-activation.ts +157 -0
  72. package/src/config/model-profiles.ts +155 -0
  73. package/src/config/model-registry.ts +51 -5
  74. package/src/config/model-resolver.ts +3 -2
  75. package/src/config/models-config-schema.ts +42 -1
  76. package/src/config/settings-schema.ts +14 -1
  77. package/src/defaults/gjc/skills/ultragoal/SKILL.md +11 -1
  78. package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +61 -0
  79. package/src/defaults/gjc-defaults.ts +7 -0
  80. package/src/discovery/claude-plugins.ts +25 -5
  81. package/src/edit/diff.ts +64 -1
  82. package/src/edit/modes/replace.ts +60 -2
  83. package/src/extensibility/gjc-plugins/activation.ts +87 -0
  84. package/src/extensibility/gjc-plugins/index.ts +9 -0
  85. package/src/extensibility/gjc-plugins/injection.ts +114 -0
  86. package/src/extensibility/gjc-plugins/loader.ts +131 -0
  87. package/src/extensibility/gjc-plugins/paths.ts +66 -0
  88. package/src/extensibility/gjc-plugins/schema.ts +79 -0
  89. package/src/extensibility/gjc-plugins/state.ts +29 -0
  90. package/src/extensibility/gjc-plugins/tools.ts +47 -0
  91. package/src/extensibility/gjc-plugins/types.ts +97 -0
  92. package/src/extensibility/gjc-plugins/validation.ts +76 -0
  93. package/src/extensibility/skills.ts +39 -7
  94. package/src/gjc-runtime/state-runtime.ts +93 -2
  95. package/src/gjc-runtime/state-writer.ts +17 -1
  96. package/src/gjc-runtime/ultragoal-runtime.ts +62 -2
  97. package/src/gjc-runtime/workflow-manifest.generated.json +5 -0
  98. package/src/gjc-runtime/workflow-manifest.ts +2 -2
  99. package/src/harness-control-plane/storage.ts +144 -2
  100. package/src/hashline/hash.ts +23 -0
  101. package/src/hooks/skill-state.ts +2 -0
  102. package/src/internal-urls/docs-index.generated.ts +8 -11
  103. package/src/lsp/client.ts +7 -0
  104. package/src/main.ts +67 -1
  105. package/src/modes/acp/acp-agent.ts +25 -2
  106. package/src/modes/bridge/bridge-mode.ts +124 -2
  107. package/src/modes/components/custom-provider-wizard.ts +318 -0
  108. package/src/modes/components/model-selector.ts +108 -18
  109. package/src/modes/components/provider-onboarding-selector.ts +6 -1
  110. package/src/modes/controllers/input-controller.ts +14 -2
  111. package/src/modes/controllers/selector-controller.ts +57 -1
  112. package/src/modes/prompt-action-autocomplete.ts +49 -10
  113. package/src/modes/rpc/rpc-client.ts +57 -3
  114. package/src/modes/rpc/rpc-mode.ts +67 -0
  115. package/src/modes/rpc/rpc-types.ts +224 -2
  116. package/src/modes/shared/agent-wire/approval-gate.ts +151 -0
  117. package/src/modes/shared/agent-wire/command-dispatch.ts +97 -4
  118. package/src/modes/shared/agent-wire/command-validation.ts +25 -1
  119. package/src/modes/shared/agent-wire/deep-interview-gate.ts +222 -0
  120. package/src/modes/shared/agent-wire/event-envelope.ts +13 -0
  121. package/src/modes/shared/agent-wire/handshake.ts +43 -3
  122. package/src/modes/shared/agent-wire/protocol.ts +7 -0
  123. package/src/modes/shared/agent-wire/responses.ts +2 -2
  124. package/src/modes/shared/agent-wire/scopes.ts +2 -0
  125. package/src/modes/shared/agent-wire/unattended-action-policy.ts +341 -0
  126. package/src/modes/shared/agent-wire/unattended-audit.ts +175 -0
  127. package/src/modes/shared/agent-wire/unattended-run-controller.ts +406 -0
  128. package/src/modes/shared/agent-wire/unattended-session.ts +180 -0
  129. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +324 -0
  130. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +331 -0
  131. package/src/modes/theme/theme.ts +6 -0
  132. package/src/modes/types.ts +1 -0
  133. package/src/prompts/memories/consolidation.md +1 -1
  134. package/src/prompts/memories/read-path.md +6 -7
  135. package/src/prompts/memories/unavailable.md +2 -2
  136. package/src/prompts/tools/bash.md +1 -1
  137. package/src/prompts/tools/irc.md +1 -1
  138. package/src/prompts/tools/read.md +2 -2
  139. package/src/prompts/tools/recall.md +1 -0
  140. package/src/prompts/tools/reflect.md +1 -0
  141. package/src/prompts/tools/retain.md +1 -0
  142. package/src/runtime-mcp/client.ts +7 -4
  143. package/src/runtime-mcp/manager.ts +45 -13
  144. package/src/runtime-mcp/transports/http.ts +40 -14
  145. package/src/runtime-mcp/transports/stdio.ts +11 -10
  146. package/src/sdk.ts +48 -1
  147. package/src/session/agent-session.ts +211 -2
  148. package/src/session/blob-store.ts +84 -0
  149. package/src/session/messages.ts +3 -0
  150. package/src/session/session-manager.ts +390 -33
  151. package/src/session/session-storage.ts +26 -0
  152. package/src/setup/provider-onboarding.ts +2 -2
  153. package/src/skill-state/active-state.ts +89 -1
  154. package/src/slash-commands/builtin-registry.ts +1 -1
  155. package/src/task/discovery.ts +7 -1
  156. package/src/task/executor.ts +18 -2
  157. package/src/task/index.ts +2 -0
  158. package/src/thinking.ts +8 -2
  159. package/src/tools/ask.ts +39 -9
  160. package/src/tools/hindsight-recall.ts +0 -2
  161. package/src/tools/hindsight-reflect.ts +0 -2
  162. package/src/tools/hindsight-retain.ts +0 -2
  163. package/src/tools/index.ts +7 -18
  164. package/src/tools/read.ts +3 -3
  165. package/src/tools/skill.ts +15 -3
  166. package/src/utils/edit-mode.ts +1 -1
@@ -0,0 +1,47 @@
1
+ import type { OpenGateInput } from "./workflow-gate-broker";
2
+ /** "Other (type your own)" sentinel, mirroring the interactive ask tool. */
3
+ export declare const GATE_OTHER_OPTION = "Other (type your own)";
4
+ export interface AskGateQuestion {
5
+ id: string;
6
+ question: string;
7
+ options: Array<{
8
+ label: string;
9
+ }>;
10
+ multi?: boolean;
11
+ recommended?: number;
12
+ }
13
+ export interface AskGateResult {
14
+ id: string;
15
+ question: string;
16
+ options: string[];
17
+ multi: boolean;
18
+ selectedOptions: string[];
19
+ customInput?: string;
20
+ }
21
+ /**
22
+ * The answer shape an agent returns for a deep-interview question gate.
23
+ *
24
+ * `selected` are picked option labels; free text is conveyed by `other: true`
25
+ * plus `custom`, encoded separately from `selected` so a real option whose label
26
+ * happens to equal the display sentinel can never collide with the free-text path.
27
+ */
28
+ export interface DeepInterviewGateAnswer {
29
+ selected: string[];
30
+ other?: boolean;
31
+ custom?: string;
32
+ }
33
+ export declare class DeepInterviewGateError extends Error {
34
+ readonly code: "invalid_answer_shape" | "unknown_option" | "multi_not_allowed" | "missing_custom" | "empty_selection" | "duplicate_selection";
35
+ constructor(code: "invalid_answer_shape" | "unknown_option" | "multi_not_allowed" | "missing_custom" | "empty_selection" | "duplicate_selection", message: string);
36
+ }
37
+ /** Build the `workflow_gate` open-input for one deep-interview question. */
38
+ export declare function questionToGate(question: AskGateQuestion): OpenGateInput;
39
+ /**
40
+ * Decode a gate answer into the QuestionResult the interactive path produces.
41
+ * Selections are de-duplicated (the interactive UI stores them in a Set), and
42
+ * free text is taken from `other`/`custom`. Throws DeepInterviewGateError on a
43
+ * semantically invalid answer.
44
+ */
45
+ export declare function gateAnswerToResult(question: AskGateQuestion, answer: unknown): AskGateResult;
46
+ /** Convenience: map a batch of ask questions to gate open-inputs. */
47
+ export declare function questionsToGates(questions: AskGateQuestion[]): OpenGateInput[];
@@ -22,3 +22,10 @@ export declare class BridgeFrameSequencer {
22
22
  }
23
23
  /** Serialize a single `AgentSessionEvent` into an `event` wire frame. */
24
24
  export declare function toBridgeEventFrame(event: AgentSessionEvent, sequencer: BridgeFrameSequencer): BridgeEventFrame;
25
+ /**
26
+ * Serialize a `workflow_gate` event into a sequenced wire frame (#321). The
27
+ * gate_id is stamped as the correlation id so the answer (posted to the
28
+ * ui-responses endpoint) can be matched, and the monotonic `seq` gives replay
29
+ * while `frame_id` + gate_id give idempotency.
30
+ */
31
+ export declare function toBridgeWorkflowGateFrame(gate: import("../../rpc/rpc-types").RpcWorkflowGate, sequencer: BridgeFrameSequencer): import("./protocol").BridgeWorkflowGateFrame;
@@ -1,6 +1,7 @@
1
+ import type { RpcUnattendedDeclaration } from "../../rpc/rpc-types";
1
2
  import { BRIDGE_PROTOCOL_VERSION, type BridgeFrameType } from "./protocol";
2
3
  import type { BridgeCommandScope } from "./scopes";
3
- export type BridgeCapability = "events" | "prompt" | "permission" | "elicitation" | "ui.declarative" | "ui.editor" | "ui.terminal_input" | "host_tools" | "host_uri" | "client_bridge.read_text_file" | "client_bridge.write_text_file" | "client_bridge.create_terminal";
4
+ export type BridgeCapability = "events" | "prompt" | "permission" | "elicitation" | "ui.declarative" | "ui.editor" | "ui.terminal_input" | "host_tools" | "host_uri" | "client_bridge.read_text_file" | "client_bridge.write_text_file" | "client_bridge.create_terminal" | "workflow_gate";
4
5
  export interface BridgeProtocolRange {
5
6
  min: number;
6
7
  max: number;
@@ -10,6 +11,8 @@ export interface BridgeHandshakeRequest {
10
11
  capabilities: BridgeCapability[];
11
12
  requested_scopes: BridgeCommandScope[];
12
13
  last_seq?: number;
14
+ /** Optional unattended declaration (budget + scope + action allowlist) for #318/#319. */
15
+ unattended?: RpcUnattendedDeclaration;
13
16
  }
14
17
  export interface BridgeEndpointDescriptor {
15
18
  events: string;
@@ -29,6 +32,10 @@ export interface BridgeHandshakeAccepted {
29
32
  unsupported: BridgeCapability[];
30
33
  endpoints: BridgeEndpointDescriptor;
31
34
  frame_types: BridgeFrameType[];
35
+ /** Echoed unattended declaration when one was supplied and accepted (#321). */
36
+ accepted_unattended?: RpcUnattendedDeclaration;
37
+ /** Server-side accepted unattended mode after live negotiation, not just declaration echo. */
38
+ unattended_active?: boolean;
32
39
  }
33
40
  export interface BridgeHandshakeRejected {
34
41
  status: "rejected";
@@ -36,6 +43,8 @@ export interface BridgeHandshakeRejected {
36
43
  message: string;
37
44
  }
38
45
  export type BridgeHandshakeResponse = BridgeHandshakeAccepted | BridgeHandshakeRejected;
46
+ /** Shape-validate an optional unattended declaration carried on the handshake. */
47
+ export declare function isUnattendedDeclarationShape(value: unknown): value is RpcUnattendedDeclaration;
39
48
  export declare function isBridgeHandshakeRequest(value: unknown): value is BridgeHandshakeRequest;
40
49
  export declare function negotiateBridgeHandshake(request: BridgeHandshakeRequest, server: {
41
50
  sessionId: string;
@@ -43,4 +52,5 @@ export declare function negotiateBridgeHandshake(request: BridgeHandshakeRequest
43
52
  scopes: readonly BridgeCommandScope[];
44
53
  endpoints: BridgeEndpointDescriptor;
45
54
  frameTypes: readonly BridgeFrameType[];
55
+ acceptedUnattended?: RpcUnattendedDeclaration;
46
56
  }): BridgeHandshakeResponse;
@@ -15,7 +15,7 @@ export type AgentSessionEventType = AgentSessionEvent["type"];
15
15
  /** Every agent-session event type, derived from the exhaustive registry. */
16
16
  export declare const AGENT_SESSION_EVENT_TYPES: readonly AgentSessionEventType[];
17
17
  /** Top-level frame categories carried over any bridge transport. */
18
- export type BridgeFrameType = "ready" | "event" | "response" | "ui_request" | "permission_request" | "host_tool_call" | "host_uri_request" | "reset" | "error";
18
+ export type BridgeFrameType = "ready" | "event" | "response" | "ui_request" | "permission_request" | "host_tool_call" | "host_uri_request" | "reset" | "workflow_gate" | "error";
19
19
  /**
20
20
  * Universal frame envelope. Every frame on every transport carries these
21
21
  * fields so clients can order (`seq`), resume (`seq` cursor), and correlate
@@ -42,3 +42,5 @@ export interface BridgeEventPayload {
42
42
  }
43
43
  /** An `AgentSessionEvent` serialized into a versioned wire frame. */
44
44
  export type BridgeEventFrame = BridgeFrameEnvelope<"event", BridgeEventPayload>;
45
+ /** A `workflow_gate` event serialized into a versioned wire frame (#321). */
46
+ export type BridgeWorkflowGateFrame = BridgeFrameEnvelope<"workflow_gate", import("../../rpc/rpc-types").RpcWorkflowGate>;
@@ -1,4 +1,4 @@
1
1
  /** Shared RPC-compatible response helpers for agent-wire consumers. */
2
2
  import type { RpcCommand, RpcResponse } from "../../rpc/rpc-types";
3
3
  export declare function rpcSuccess<T extends RpcCommand["type"]>(id: string | undefined, command: T, data?: object | null): RpcResponse;
4
- export declare function rpcError(id: string | undefined, command: string, message: string): RpcResponse;
4
+ export declare function rpcError(id: string | undefined, command: string, error: string | object): RpcResponse;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Unattended action taxonomy + classifier (#319).
3
+ *
4
+ * Maps coarse command scopes and concrete bash commands onto the v1 action
5
+ * taxonomy so the controller can authorize (default-deny) BEFORE any side effect.
6
+ *
7
+ * The classifier is deliberately FAIL-CLOSED for shell evasion:
8
+ * - nested execution via `$(...)`, backticks, and `<(...)` / `>(...)` is
9
+ * extracted and classified recursively, so a destructive command hidden in a
10
+ * substitution cannot masquerade as the harmless outer command;
11
+ * - statements are split on newlines and `; && || | &`, so a second
12
+ * (destructive) command on another line is classified too;
13
+ * - leading environment assignments and wrappers (`sudo`, `env`, `command`,
14
+ * `xargs`, …) are stripped/followed to the effective command;
15
+ * - anything that is not provably read-only escalates to at least
16
+ * `bash.mutating`, and clearly destructive forms escalate further, so an
17
+ * undeclared destructive action is denied rather than silently allowed.
18
+ */
19
+ import type { RpcUnattendedActionClass } from "../../rpc/rpc-types";
20
+ import type { BridgeCommandScope } from "./scopes";
21
+ /** Coarse command scope -> `command.<scope>` action class. */
22
+ export declare function actionClassForScope(scope: BridgeCommandScope): RpcUnattendedActionClass;
23
+ /**
24
+ * Classify a (possibly compound / nested) bash command into the most severe
25
+ * action class across all statements and nested substitutions. Fail-closed.
26
+ */
27
+ export declare function classifyBashAction(command: string): RpcUnattendedActionClass;
@@ -0,0 +1,68 @@
1
+ import type { RpcBudgetExceeded, RpcWorkflowGateKind, RpcWorkflowStage } from "../../rpc/rpc-types";
2
+ export declare const AUDIT_SCHEMA_VERSION = 1;
3
+ export declare const AUDIT_CATEGORY = "unattended_lifecycle";
4
+ export type AuditOutcome = "accepted" | "rejected" | "denied" | "exceeded" | "aborted" | "info";
5
+ export interface AuditRecord {
6
+ event_id: string;
7
+ schema_version: number;
8
+ category: typeof AUDIT_CATEGORY;
9
+ run_id: string;
10
+ session_id?: string;
11
+ actor?: string;
12
+ timestamp: string;
13
+ event: string;
14
+ outcome: AuditOutcome;
15
+ dedupe_key: string;
16
+ gate_id?: string;
17
+ stage?: RpcWorkflowStage;
18
+ kind?: RpcWorkflowGateKind;
19
+ scope?: string;
20
+ action?: string;
21
+ budget?: RpcBudgetExceeded;
22
+ /** Full answer (omitted when redaction is enabled). */
23
+ answer?: unknown;
24
+ answer_hash?: string;
25
+ error?: unknown;
26
+ }
27
+ export interface AuditQuery {
28
+ run_id?: string;
29
+ session_id?: string;
30
+ actor?: string;
31
+ gate_id?: string;
32
+ outcome?: AuditOutcome;
33
+ event?: string;
34
+ since?: string;
35
+ until?: string;
36
+ }
37
+ export interface AuditLogOptions {
38
+ /** When true, gate answers are stored as hash + summary only. */
39
+ redactAnswers?: boolean;
40
+ /** Injectable id/clock for deterministic tests. */
41
+ now?(): number;
42
+ nextId?(): string;
43
+ }
44
+ export declare function defaultAuditPath(runId: string, root?: string): string;
45
+ /** Append-only audit log writer + reader for one unattended run. */
46
+ export declare class UnattendedAuditLog {
47
+ private readonly filePath;
48
+ private readonly seen;
49
+ private readonly now;
50
+ private readonly nextId;
51
+ private readonly redactAnswers;
52
+ constructor(filePath: string, options?: AuditLogOptions);
53
+ /**
54
+ * Append a record. Returns the written record, or `null` if a record with the
55
+ * same dedupe_key was already written (exactly-once).
56
+ */
57
+ record(input: Omit<AuditRecord, "event_id" | "schema_version" | "category" | "timestamp">): AuditRecord | null;
58
+ /** Append one line and fsync it for crash durability. */
59
+ private appendDurable;
60
+ /** Read every record (fail-closed: a corrupt line throws rather than silently dropping). */
61
+ readAll(): AuditRecord[];
62
+ /** Query records with filters (run/session/actor/gate/outcome/event + time window). */
63
+ query(filter?: AuditQuery): AuditRecord[];
64
+ /** Export the full trail as an array (for `get_unattended_audit`). */
65
+ export(filter?: AuditQuery): AuditRecord[];
66
+ }
67
+ /** SHA-256 of the canonical JSON of an answer (matches the gate broker's hash). */
68
+ export declare function answerHash(answer: unknown): string;
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Unattended run controller (#318).
3
+ *
4
+ * The single required owner of negotiated unattended state. Entering unattended
5
+ * mode is fail-closed: a controller can only be created via {@link
6
+ * UnattendedRunController.negotiate}, which rejects a missing/partial budget, an
7
+ * invalid declaration, or a provider that cannot account for tokens/cost.
8
+ *
9
+ * The controller owns budget accounting across metrics and phases. Scope/action
10
+ * authorization (#319) and the durable audit trail (#320) layer onto the same
11
+ * controller; this slice wires the budget floor and abort coordination.
12
+ *
13
+ * Attended mode never constructs a controller, so by construction the attended
14
+ * path is unaffected by everything here.
15
+ */
16
+ import type { RpcActionDenied, RpcBudgetExceeded, RpcBudgetMetric, RpcScopeDenied, RpcUnattendedActionClass, RpcUnattendedBudget, RpcUnattendedRefusalCode } from "../../rpc/rpc-types";
17
+ import type { BridgeCommandScope } from "./scopes";
18
+ import { actionClassForScope } from "./unattended-action-policy";
19
+ /** Coordinated abort surfaces invoked exactly once on a budget breach / abort. */
20
+ export interface UnattendedAbortHooks {
21
+ abortModelStream?(): void | Promise<void>;
22
+ abortBash?(): void | Promise<void>;
23
+ cancelHostTools?(reason: string): void | Promise<void>;
24
+ cancelHostUris?(reason: string): void | Promise<void>;
25
+ stopWorkflow?(reason: string): void | Promise<void>;
26
+ }
27
+ export type UnattendedAuditEvent = {
28
+ event: "unattended_negotiated";
29
+ run_id: string;
30
+ actor: string;
31
+ } | {
32
+ event: "budget_exceeded";
33
+ payload: RpcBudgetExceeded;
34
+ } | {
35
+ event: "unattended_aborted";
36
+ run_id: string;
37
+ reason: string;
38
+ } | {
39
+ event: "unattended_abort_settled";
40
+ run_id: string;
41
+ status: "aborted" | "abort_failed";
42
+ failures: number;
43
+ } | {
44
+ event: "scope_denied";
45
+ payload: RpcScopeDenied;
46
+ } | {
47
+ event: "action_denied";
48
+ payload: RpcActionDenied;
49
+ };
50
+ export interface NegotiateContext {
51
+ runId: string;
52
+ sessionId?: string;
53
+ audit?(event: UnattendedAuditEvent): void;
54
+ abortHooks?: UnattendedAbortHooks;
55
+ /**
56
+ * Whether the active provider can report token usage and cost. Unattended
57
+ * mode rejects providers without this accounting up front (fail-closed).
58
+ */
59
+ providerSupportsTokenCostMetrics?: boolean;
60
+ /** Injectable clock for deterministic tests. Defaults to Date.now. */
61
+ now?(): number;
62
+ }
63
+ export declare class UnattendedNegotiationError extends Error {
64
+ readonly code: RpcUnattendedRefusalCode;
65
+ constructor(code: RpcUnattendedRefusalCode, message: string);
66
+ }
67
+ export declare class UnattendedBudgetExceededError extends Error {
68
+ readonly payload: RpcBudgetExceeded;
69
+ constructor(payload: RpcBudgetExceeded);
70
+ }
71
+ /** Thrown when a provider/tool reports a non-finite usage value (fail-closed). */
72
+ export declare class UnattendedAccountingError extends Error {
73
+ readonly metric: RpcBudgetMetric;
74
+ readonly phase: string;
75
+ constructor(metric: RpcBudgetMetric, phase: string, value: unknown);
76
+ }
77
+ /** Thrown when a command's coarse scope is outside the declared allowlist (#319). */
78
+ export declare class ScopeDeniedError extends Error {
79
+ readonly payload: RpcScopeDenied;
80
+ constructor(payload: RpcScopeDenied);
81
+ }
82
+ /** Thrown when an action class is outside the declared allowlist (default-deny, #319). */
83
+ export declare class ActionDeniedError extends Error {
84
+ readonly payload: RpcActionDenied;
85
+ constructor(payload: RpcActionDenied);
86
+ }
87
+ interface Usage {
88
+ tokens: number;
89
+ toolCalls: number;
90
+ costUsd: number;
91
+ }
92
+ export declare class UnattendedRunController {
93
+ readonly runId: string;
94
+ readonly sessionId?: string;
95
+ readonly actor: string;
96
+ readonly budget: RpcUnattendedBudget;
97
+ readonly scopes: ReadonlySet<string>;
98
+ readonly actionAllowlist: ReadonlySet<string>;
99
+ private readonly usage;
100
+ private readonly startedAt;
101
+ private readonly now;
102
+ private readonly audit?;
103
+ private readonly abortHooks;
104
+ private aborted;
105
+ private abortPromise?;
106
+ private constructor();
107
+ /** Fail-closed entry: validate the declaration + budget, or throw. */
108
+ static negotiate(declaration: unknown, ctx: NegotiateContext): UnattendedRunController;
109
+ get isAborted(): boolean;
110
+ usageSnapshot(): Readonly<Usage> & {
111
+ wallTimeMs: number;
112
+ };
113
+ remainingWallTimeMs(): number;
114
+ /**
115
+ * Authorize a command's coarse scope against the declared allowlist. Throws
116
+ * ScopeDeniedError (pre-side-effect) when the scope was not declared.
117
+ */
118
+ authorizeScope(scope: BridgeCommandScope, command?: string): void;
119
+ /**
120
+ * Authorize an action class against the declared allowlist. Default-deny: any
121
+ * class not explicitly declared is rejected with ActionDeniedError before the
122
+ * side effect runs.
123
+ */
124
+ authorizeAction(action: RpcUnattendedActionClass, command?: string): void;
125
+ /**
126
+ * Classify a bash command and authorize the resulting action class BEFORE the
127
+ * command is executed. Returns the classified action class on success.
128
+ */
129
+ authorizeBash(command: string): RpcUnattendedActionClass;
130
+ /** Convenience: map a coarse scope to its `command.<scope>` action class. */
131
+ static actionClassForScope: typeof actionClassForScope;
132
+ /** Pre-turn estimate: refuse to start a turn that would obviously breach. */
133
+ preTurnEstimate(estimate: {
134
+ tokens?: number;
135
+ costUsd?: number;
136
+ }): void;
137
+ /** Reserve one tool-call unit BEFORE any side effect; breach if it would exceed. */
138
+ preflightToolCall(phase?: string): void;
139
+ /** Post-turn reconciliation of actual token usage. Fails closed on non-finite. */
140
+ recordTokens(tokens: number, phase?: string): void;
141
+ recordCost(costUsd: number, phase?: string): void;
142
+ /** Combined post-turn reconciliation. */
143
+ reconcile(actual: {
144
+ tokens?: number;
145
+ costUsd?: number;
146
+ }, phase?: string): void;
147
+ /** Wall-time check; call before/inside long operations. */
148
+ checkWallTime(phase?: string): void;
149
+ private breach;
150
+ /**
151
+ * Idempotent abort: runs every abort hook at most once. Safe to call from the
152
+ * synchronous breach path (which does not await) and from callers that do; both
153
+ * share a single abort promise so hook completion can be awaited deterministically.
154
+ */
155
+ abort(reason: string): Promise<void>;
156
+ /** Returns the in-flight/settled abort completion once aborting has begun. */
157
+ get abortCompletion(): Promise<void> | undefined;
158
+ private fireAbort;
159
+ private runAbortHooks;
160
+ }
161
+ export {};
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Session-level unattended control plane (#323 / G011 emission side).
3
+ *
4
+ * Bridges the gate EMISSION side (skill runtimes / ask tool emitting gates) to
5
+ * the gate ANSWER side (the external agent's `workflow_gate_response` over RPC):
6
+ *
7
+ * - `emitGate(input)` opens a gate on the durable broker, emits the gate frame
8
+ * to the transport, and returns a promise that resolves with the agent's
9
+ * answer once it arrives.
10
+ * - `resolveGate(response)` (called from RPC dispatch) validates + resolves the
11
+ * gate on the broker; the broker's `advance` hook resolves the pending
12
+ * `emitGate` promise with the answer.
13
+ *
14
+ * Also implements the dispatch-facing {@link RpcUnattendedControlPlane} so the
15
+ * RPC server can route `negotiate_unattended` + `workflow_gate_response` here.
16
+ */
17
+ import type { RpcCommand, RpcUnattendedAccepted, RpcUnattendedDeclaration, RpcWorkflowGate, RpcWorkflowGateResolution, RpcWorkflowGateResponse } from "../../rpc/rpc-types";
18
+ import type { RpcUnattendedControlPlane } from "./command-dispatch";
19
+ import { type UnattendedAbortHooks, type UnattendedAuditEvent, UnattendedRunController } from "./unattended-run-controller";
20
+ import { type GateStore, type OpenGateInput } from "./workflow-gate-broker";
21
+ /** Minimal surface a skill runtime / ask tool uses to emit a gate and await its answer. */
22
+ export interface WorkflowGateEmitter {
23
+ /** True only when unattended mode has been negotiated. */
24
+ isUnattended(): boolean;
25
+ /** Open + emit a gate; resolves with the agent's answer (from workflow_gate_response). */
26
+ emitGate(input: OpenGateInput): Promise<unknown>;
27
+ }
28
+ export interface UnattendedSessionOptions {
29
+ runId: string;
30
+ sessionId?: string;
31
+ /** Emit a workflow_gate frame to the transport so the agent receives it. */
32
+ emitFrame: (gate: RpcWorkflowGate) => void;
33
+ /** Durable gate store; defaults to in-memory. */
34
+ store?: GateStore;
35
+ /** Audit sink for controller + gate events. */
36
+ audit?: (event: UnattendedAuditEvent | {
37
+ event: string;
38
+ [k: string]: unknown;
39
+ }) => void;
40
+ abortHooks?: UnattendedAbortHooks;
41
+ /** Whether the active provider reports token/cost usage (fail-closed when false/omitted). */
42
+ providerSupportsTokenCostMetrics?: boolean;
43
+ /** Snapshot live cumulative usage after a dispatch or turn, for budget reconciliation. */
44
+ getUsageSnapshot?: () => {
45
+ tokens?: number;
46
+ costUsd?: number;
47
+ };
48
+ }
49
+ export declare class UnattendedSessionControlPlane implements RpcUnattendedControlPlane, WorkflowGateEmitter {
50
+ #private;
51
+ private readonly opts;
52
+ constructor(opts: UnattendedSessionOptions);
53
+ isUnattended(): boolean;
54
+ get controller(): UnattendedRunController | undefined;
55
+ negotiate(declaration: RpcUnattendedDeclaration): RpcUnattendedAccepted;
56
+ preflightCommand(command: RpcCommand): void;
57
+ reconcileUsage(phase?: string): void;
58
+ resolveGate(response: RpcWorkflowGateResponse): Promise<RpcWorkflowGateResolution>;
59
+ emitGate(input: OpenGateInput): Promise<unknown>;
60
+ recover(): Promise<void>;
61
+ }
@@ -0,0 +1,114 @@
1
+ import type { RpcWorkflowGate, RpcWorkflowGateContext, RpcWorkflowGateKind, RpcWorkflowGateOption, RpcWorkflowGateResolution, RpcWorkflowGateResponse, RpcWorkflowStage } from "../../rpc/rpc-types";
2
+ export interface PersistedGate {
3
+ gate: RpcWorkflowGate;
4
+ status: "pending" | "accepted";
5
+ idempotencyKey?: string;
6
+ responseHash?: string;
7
+ /** Raw accepted answer, retained so a crashed advance can be replayed. */
8
+ answer?: unknown;
9
+ resolution?: RpcWorkflowGateResolution;
10
+ advanced: boolean;
11
+ }
12
+ export interface GateStore {
13
+ nextSeq(stage: RpcWorkflowStage): number;
14
+ put(record: PersistedGate): void;
15
+ get(gateId: string): PersistedGate | undefined;
16
+ /** All persisted gate records (used for crash recovery). */
17
+ list(): PersistedGate[];
18
+ }
19
+ export declare class MemoryGateStore implements GateStore {
20
+ private counters;
21
+ private gates;
22
+ nextSeq(stage: RpcWorkflowStage): number;
23
+ put(record: PersistedGate): void;
24
+ get(gateId: string): PersistedGate | undefined;
25
+ list(): PersistedGate[];
26
+ }
27
+ /** Crash-durable JSON-file backed store. Writes the full state on every mutation. */
28
+ export declare class FileGateStore implements GateStore {
29
+ private readonly filePath;
30
+ private state;
31
+ constructor(filePath: string);
32
+ private load;
33
+ private flush;
34
+ nextSeq(stage: RpcWorkflowStage): number;
35
+ put(record: PersistedGate): void;
36
+ get(gateId: string): PersistedGate | undefined;
37
+ list(): PersistedGate[];
38
+ }
39
+ export type GateAuditEvent = {
40
+ event: "gate_emitted";
41
+ gate_id: string;
42
+ stage: RpcWorkflowStage;
43
+ kind: RpcWorkflowGateKind;
44
+ } | {
45
+ event: "gate_response_accepted";
46
+ gate_id: string;
47
+ answer_hash: string;
48
+ } | {
49
+ event: "gate_response_rejected";
50
+ gate_id: string;
51
+ answer_hash: string;
52
+ } | {
53
+ event: "gate_response_idempotent_replay";
54
+ gate_id: string;
55
+ } | {
56
+ event: "gate_response_idempotency_conflict";
57
+ gate_id: string;
58
+ } | {
59
+ event: "gate_response_already_resolved";
60
+ gate_id: string;
61
+ } | {
62
+ event: "gate_response_unknown_gate";
63
+ gate_id: string;
64
+ } | {
65
+ event: "gate_advance_recovered";
66
+ gate_id: string;
67
+ };
68
+ export interface BrokerHooks {
69
+ /** Called once when a pending gate has been persisted and should be emitted. */
70
+ emit?(gate: RpcWorkflowGate): void;
71
+ /**
72
+ * Invoked to advance the workflow after an accepted resolution is durably
73
+ * committed. MUST be idempotent keyed by `gate.gate_id`: `recover()` replays
74
+ * it for any gate left `accepted` but not `advanced` by a crash.
75
+ */
76
+ advance?(gate: RpcWorkflowGate, answer: unknown): void | Promise<void>;
77
+ /** Append-only audit sink. */
78
+ audit?(event: GateAuditEvent): void;
79
+ }
80
+ export interface OpenGateInput {
81
+ stage: RpcWorkflowStage;
82
+ kind: RpcWorkflowGateKind;
83
+ schema: RpcWorkflowGate["schema"];
84
+ options?: RpcWorkflowGateOption[];
85
+ context?: RpcWorkflowGateContext;
86
+ }
87
+ export declare class WorkflowGateBrokerError extends Error {
88
+ readonly code: "unknown_gate" | "already_resolved" | "idempotency_conflict" | "invalid_workflow_stage";
89
+ constructor(code: "unknown_gate" | "already_resolved" | "idempotency_conflict" | "invalid_workflow_stage", message: string);
90
+ }
91
+ export declare class WorkflowGateBroker {
92
+ private readonly runId;
93
+ private readonly store;
94
+ private readonly hooks;
95
+ constructor(runId: string, store: GateStore, hooks?: BrokerHooks);
96
+ private runShort;
97
+ /** Open and emit a gate. The pending record is persisted BEFORE emission. */
98
+ openGate(input: OpenGateInput): RpcWorkflowGate;
99
+ /**
100
+ * Resolve a gate with an answer. Validates against the advertised schema.
101
+ * On success the resolution is persisted BEFORE `advance` is invoked exactly
102
+ * once. Invalid answers leave the gate pending (per #315 acceptance).
103
+ */
104
+ resolve(response: RpcWorkflowGateResponse): Promise<RpcWorkflowGateResolution>;
105
+ /**
106
+ * Recover any gate left `accepted` but not `advanced` by a crash between the
107
+ * durable accept and the advanced commit. Replays `advance` (which must be
108
+ * idempotent) exactly once per gate and marks it advanced. Returns the ids
109
+ * that were recovered.
110
+ */
111
+ recover(): Promise<string[]>;
112
+ /** Canonical serialization helper (exposed for callers/tests). */
113
+ static canonical(value: unknown): string;
114
+ }
@@ -0,0 +1,39 @@
1
+ import type { RpcJsonSchema, RpcWorkflowGateValidationError } from "../../rpc/rpc-types";
2
+ export declare const GATE_SCHEMA_LIMITS: {
3
+ readonly maxSchemaBytes: number;
4
+ readonly maxDepth: 16;
5
+ readonly maxProperties: 256;
6
+ readonly maxEnumValues: 512;
7
+ readonly maxAnswerBytes: number;
8
+ };
9
+ /** Thrown at gate construction when a schema is unsupported or too large. */
10
+ export declare class WorkflowGateSchemaError extends Error {
11
+ readonly code = "invalid_workflow_gate_schema";
12
+ constructor(message: string);
13
+ }
14
+ /** Canonical (stable-key-ordered) JSON serialization used for hashing. */
15
+ export declare function canonicalJson(value: unknown): string;
16
+ export declare function schemaHash(schema: RpcJsonSchema): string;
17
+ declare function answerHashOf(answer: unknown): string;
18
+ /** Validate the schema *shape*. Throws WorkflowGateSchemaError on any problem. */
19
+ export declare function assertSupportedGateSchema(schema: RpcJsonSchema): void;
20
+ type SchemaError = {
21
+ path: string;
22
+ keyword: string;
23
+ message: string;
24
+ expected?: unknown;
25
+ };
26
+ /** A compiled, cached validator for one schema. */
27
+ export interface CompiledGateSchema {
28
+ readonly schema: RpcJsonSchema;
29
+ readonly hash: string;
30
+ validate(answer: unknown): SchemaError[];
31
+ }
32
+ /** Compile (and cache) a validator for a schema. Asserts shape on first compile. */
33
+ export declare function compileGateSchema(schema: RpcJsonSchema): CompiledGateSchema;
34
+ /**
35
+ * Validate an answer against a compiled gate schema. Returns `null` on success
36
+ * or a typed {@link RpcWorkflowGateValidationError} on mismatch.
37
+ */
38
+ export declare function validateGateAnswer(compiled: CompiledGateSchema, gateId: string, answer: unknown): RpcWorkflowGateValidationError | null;
39
+ export { answerHashOf };
@@ -6,7 +6,7 @@ export type SymbolPreset = "unicode" | "nerd" | "ascii";
6
6
  /**
7
7
  * All available symbol keys organized by category.
8
8
  */
9
- export type SymbolKey = "status.success" | "status.error" | "status.warning" | "status.info" | "status.pending" | "status.disabled" | "status.enabled" | "status.running" | "status.shadowed" | "status.aborted" | "nav.cursor" | "nav.selected" | "nav.expand" | "nav.collapse" | "nav.back" | "tree.branch" | "tree.last" | "tree.vertical" | "tree.horizontal" | "tree.hook" | "boxRound.topLeft" | "boxRound.topRight" | "boxRound.bottomLeft" | "boxRound.bottomRight" | "boxRound.horizontal" | "boxRound.vertical" | "boxSharp.topLeft" | "boxSharp.topRight" | "boxSharp.bottomLeft" | "boxSharp.bottomRight" | "boxSharp.horizontal" | "boxSharp.vertical" | "boxSharp.cross" | "boxSharp.teeDown" | "boxSharp.teeUp" | "boxSharp.teeRight" | "boxSharp.teeLeft" | "sep.powerline" | "sep.powerlineThin" | "sep.powerlineLeft" | "sep.powerlineRight" | "sep.powerlineThinLeft" | "sep.powerlineThinRight" | "sep.block" | "sep.space" | "sep.asciiLeft" | "sep.asciiRight" | "sep.dot" | "sep.slash" | "sep.pipe" | "icon.model" | "icon.plan" | "icon.goal" | "icon.pause" | "icon.folder" | "icon.scratchFolder" | "icon.file" | "icon.git" | "icon.branch" | "icon.pr" | "icon.tokens" | "icon.context" | "icon.cost" | "icon.time" | "icon.pi" | "icon.agents" | "icon.cache" | "icon.input" | "icon.output" | "icon.host" | "icon.session" | "icon.package" | "icon.warning" | "icon.rewind" | "icon.auto" | "icon.fast" | "icon.extensionSkill" | "icon.extensionTool" | "icon.extensionSlashCommand" | "icon.extensionMcp" | "icon.extensionRule" | "icon.extensionHook" | "icon.extensionPrompt" | "icon.extensionContextFile" | "icon.extensionInstruction" | "icon.mic" | "thinking.minimal" | "thinking.low" | "thinking.medium" | "thinking.high" | "thinking.xhigh" | "checkbox.checked" | "checkbox.unchecked" | "format.bullet" | "format.dash" | "format.bracketLeft" | "format.bracketRight" | "md.quoteBorder" | "md.hrChar" | "md.bullet" | "lang.default" | "lang.typescript" | "lang.javascript" | "lang.python" | "lang.rust" | "lang.go" | "lang.java" | "lang.c" | "lang.cpp" | "lang.csharp" | "lang.ruby" | "lang.php" | "lang.swift" | "lang.kotlin" | "lang.shell" | "lang.html" | "lang.css" | "lang.json" | "lang.yaml" | "lang.markdown" | "lang.sql" | "lang.docker" | "lang.lua" | "lang.text" | "lang.env" | "lang.toml" | "lang.xml" | "lang.ini" | "lang.conf" | "lang.log" | "lang.csv" | "lang.tsv" | "lang.image" | "lang.pdf" | "lang.archive" | "lang.binary" | "tab.appearance" | "tab.model" | "tab.interaction" | "tab.context" | "tab.editing" | "tab.tools" | "tab.memory" | "tab.tasks" | "tab.providers";
9
+ export type SymbolKey = "status.success" | "status.error" | "status.warning" | "status.info" | "status.pending" | "status.disabled" | "status.enabled" | "status.running" | "status.shadowed" | "status.aborted" | "nav.cursor" | "nav.selected" | "nav.expand" | "nav.collapse" | "nav.back" | "tree.branch" | "tree.last" | "tree.vertical" | "tree.horizontal" | "tree.hook" | "boxRound.topLeft" | "boxRound.topRight" | "boxRound.bottomLeft" | "boxRound.bottomRight" | "boxRound.horizontal" | "boxRound.vertical" | "boxSharp.topLeft" | "boxSharp.topRight" | "boxSharp.bottomLeft" | "boxSharp.bottomRight" | "boxSharp.horizontal" | "boxSharp.vertical" | "boxSharp.cross" | "boxSharp.teeDown" | "boxSharp.teeUp" | "boxSharp.teeRight" | "boxSharp.teeLeft" | "sep.powerline" | "sep.powerlineThin" | "sep.powerlineLeft" | "sep.powerlineRight" | "sep.powerlineThinLeft" | "sep.powerlineThinRight" | "sep.block" | "sep.space" | "sep.asciiLeft" | "sep.asciiRight" | "sep.dot" | "sep.slash" | "sep.pipe" | "icon.model" | "icon.plan" | "icon.goal" | "icon.pause" | "icon.folder" | "icon.scratchFolder" | "icon.file" | "icon.git" | "icon.branch" | "icon.pr" | "icon.tokens" | "icon.context" | "icon.cost" | "icon.time" | "icon.pi" | "icon.agents" | "icon.cache" | "icon.input" | "icon.output" | "icon.host" | "icon.session" | "icon.package" | "icon.warning" | "icon.rewind" | "icon.auto" | "icon.fast" | "icon.extensionSkill" | "icon.extensionTool" | "icon.extensionSlashCommand" | "icon.extensionMcp" | "icon.extensionRule" | "icon.extensionHook" | "icon.extensionPrompt" | "icon.extensionContextFile" | "icon.extensionInstruction" | "icon.mic" | "thinking.minimal" | "thinking.low" | "thinking.medium" | "thinking.high" | "thinking.xhigh" | "thinking.max" | "checkbox.checked" | "checkbox.unchecked" | "format.bullet" | "format.dash" | "format.bracketLeft" | "format.bracketRight" | "md.quoteBorder" | "md.hrChar" | "md.bullet" | "lang.default" | "lang.typescript" | "lang.javascript" | "lang.python" | "lang.rust" | "lang.go" | "lang.java" | "lang.c" | "lang.cpp" | "lang.csharp" | "lang.ruby" | "lang.php" | "lang.swift" | "lang.kotlin" | "lang.shell" | "lang.html" | "lang.css" | "lang.json" | "lang.yaml" | "lang.markdown" | "lang.sql" | "lang.docker" | "lang.lua" | "lang.text" | "lang.env" | "lang.toml" | "lang.xml" | "lang.ini" | "lang.conf" | "lang.log" | "lang.csv" | "lang.tsv" | "lang.image" | "lang.pdf" | "lang.archive" | "lang.binary" | "tab.appearance" | "tab.model" | "tab.interaction" | "tab.context" | "tab.editing" | "tab.tools" | "tab.memory" | "tab.tasks" | "tab.providers";
10
10
  export type SpinnerType = "status" | "activity";
11
11
  export type ThemeColor = "accent" | "border" | "borderAccent" | "borderMuted" | "success" | "error" | "warning" | "muted" | "dim" | "text" | "thinkingText" | "userMessageText" | "customMessageText" | "customMessageLabel" | "toolTitle" | "toolOutput" | "mdHeading" | "mdLink" | "mdLinkUrl" | "mdCode" | "mdCodeBlock" | "mdCodeBlockBorder" | "mdQuote" | "mdQuoteBorder" | "mdHr" | "mdListBullet" | "toolDiffAdded" | "toolDiffRemoved" | "toolDiffContext" | "syntaxComment" | "syntaxKeyword" | "syntaxFunction" | "syntaxVariable" | "syntaxString" | "syntaxNumber" | "syntaxType" | "syntaxOperator" | "syntaxPunctuation" | "thinkingOff" | "thinkingMinimal" | "thinkingLow" | "thinkingMedium" | "thinkingHigh" | "thinkingXhigh" | "bashMode" | "pythonMode" | "statusLineSep" | "statusLineModel" | "statusLinePath" | "statusLineGitClean" | "statusLineGitDirty" | "statusLineContext" | "statusLineSpend" | "statusLineStaged" | "statusLineDirty" | "statusLineUntracked" | "statusLineOutput" | "statusLineCost" | "statusLineSubagents";
12
12
  /** Check if a string is a valid ThemeColor value */
@@ -149,6 +149,7 @@ export declare class Theme {
149
149
  medium: string;
150
150
  high: string;
151
151
  xhigh: string;
152
+ max: string;
152
153
  };
153
154
  get checkbox(): {
154
155
  checked: string;
@@ -123,6 +123,7 @@ export interface InteractiveModeContext {
123
123
  }): void;
124
124
  showError(message: string): void;
125
125
  showWarning(message: string): void;
126
+ notifyConfigChanged?: () => Promise<void> | void;
126
127
  showNewVersionNotification(newVersion: string): void;
127
128
  clearEditor(): void;
128
129
  updatePendingMessagesDisplay(): void;
@@ -5,10 +5,6 @@
5
5
  * Messages are newline-delimited JSON.
6
6
  */
7
7
  import type { MCPRequestOptions, MCPStdioServerConfig, MCPTransport } from "../../runtime-mcp/types";
8
- /**
9
- * Stdio transport for MCP servers.
10
- * Spawns a subprocess and communicates via stdin/stdout.
11
- */
12
8
  export declare class StdioTransport implements MCPTransport {
13
9
  #private;
14
10
  private config;