@gajae-code/coding-agent 0.4.5 → 0.5.1
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 +62 -0
- package/dist/types/async/job-manager.d.ts +26 -0
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli/list-models.d.ts +6 -0
- package/dist/types/commands/gc.d.ts +26 -0
- package/dist/types/commands/harness.d.ts +3 -0
- package/dist/types/config/file-lock-gc.d.ts +5 -0
- package/dist/types/config/file-lock.d.ts +7 -0
- package/dist/types/config/model-profile-activation.d.ts +11 -2
- package/dist/types/config/model-profiles.d.ts +7 -0
- package/dist/types/config/model-registry.d.ts +3 -0
- package/dist/types/config/model-resolver.d.ts +2 -0
- package/dist/types/config/models-config-schema.d.ts +30 -0
- package/dist/types/config/settings-schema.d.ts +4 -3
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/defaults/gjc/extensions/grok-build/index.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/index.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.d.ts +25 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/payload/sanitize.d.ts +27 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/billing.d.ts +8 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.d.ts +5 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +10 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/usage.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/shared/errors.d.ts +38 -0
- package/dist/types/defaults/gjc-grok-cli.d.ts +5 -0
- package/dist/types/extensibility/extensions/index.d.ts +1 -0
- package/dist/types/extensibility/extensions/prefix-command-bridge.d.ts +35 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +103 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +112 -0
- package/dist/types/gjc-runtime/gc-render.d.ts +6 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +134 -0
- package/dist/types/gjc-runtime/ledger-event-renderer.d.ts +68 -0
- package/dist/types/gjc-runtime/team-gc.d.ts +7 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +5 -1
- package/dist/types/gjc-runtime/tmux-common.d.ts +14 -0
- package/dist/types/gjc-runtime/tmux-gc.d.ts +7 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +13 -0
- package/dist/types/harness-control-plane/gc-adapter.d.ts +3 -0
- package/dist/types/harness-control-plane/owner.d.ts +8 -1
- package/dist/types/harness-control-plane/receipt-spool.d.ts +19 -0
- package/dist/types/harness-control-plane/state-machine.d.ts +6 -1
- package/dist/types/harness-control-plane/storage.d.ts +20 -0
- package/dist/types/harness-control-plane/types.d.ts +4 -0
- package/dist/types/hindsight/mental-models.d.ts +5 -5
- package/dist/types/modes/components/hook-selector.d.ts +7 -1
- package/dist/types/modes/components/model-selector.d.ts +1 -12
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/rpc/rpc-client.d.ts +2 -2
- package/dist/types/modes/rpc/rpc-mode.d.ts +16 -1
- package/dist/types/modes/rpc/rpc-types.d.ts +4 -1
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +13 -0
- package/dist/types/modes/shared/agent-wire/session-registry.d.ts +25 -0
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +2 -0
- package/dist/types/sdk.d.ts +5 -0
- package/dist/types/session/agent-session.d.ts +3 -1
- package/dist/types/session/blob-store.d.ts +59 -4
- package/dist/types/session/session-manager.d.ts +24 -6
- package/dist/types/session/streaming-output.d.ts +3 -2
- package/dist/types/session/tool-choice-queue.d.ts +6 -0
- package/dist/types/skill-state/workflow-hud.d.ts +14 -0
- package/dist/types/task/receipt.d.ts +1 -0
- package/dist/types/task/types.d.ts +7 -0
- package/dist/types/thinking-metadata.d.ts +16 -0
- package/dist/types/thinking.d.ts +3 -12
- package/dist/types/tools/ask.d.ts +15 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/resolve.d.ts +0 -10
- package/dist/types/tools/subagent.d.ts +6 -0
- package/dist/types/utils/tool-choice.d.ts +14 -1
- package/package.json +7 -7
- package/src/async/job-manager.ts +52 -0
- package/src/cli/args.ts +3 -0
- package/src/cli/auth-broker-cli.ts +1 -0
- package/src/cli/list-models.ts +13 -1
- package/src/cli.ts +9 -4
- package/src/commands/gc.ts +22 -0
- package/src/commands/harness.ts +43 -5
- package/src/commands/launch.ts +2 -2
- package/src/commands/session.ts +3 -1
- package/src/config/file-lock-gc.ts +181 -0
- package/src/config/file-lock.ts +14 -0
- package/src/config/model-profile-activation.ts +15 -3
- package/src/config/model-profiles.ts +264 -56
- package/src/config/model-resolver.ts +9 -6
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings-schema.ts +6 -3
- package/src/coordinator/contract.ts +1 -0
- package/src/coordinator-mcp/server.ts +513 -26
- package/src/cursor.ts +16 -2
- package/src/defaults/gjc/agent.models.grok-cli.yml +36 -0
- package/src/defaults/gjc/extensions/grok-build/index.ts +1 -0
- package/src/defaults/gjc/extensions/grok-build/package.json +7 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/biome.json +39 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/package.json +8 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/index.ts +1 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +155 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/payload/sanitize.ts +361 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/billing.ts +57 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +99 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +50 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/usage.ts +56 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +36 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/errors.ts +44 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +131 -113
- package/src/defaults/gjc/skills/deep-interview/lateral-review-panel.md +49 -0
- package/src/defaults/gjc/skills/team/SKILL.md +3 -2
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +8 -2
- package/src/defaults/gjc-defaults.ts +7 -0
- package/src/defaults/gjc-grok-cli.ts +22 -0
- package/src/export/html/index.ts +13 -9
- package/src/extensibility/extensions/index.ts +1 -0
- package/src/extensibility/extensions/prefix-command-bridge.ts +128 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +417 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +18 -26
- package/src/gjc-runtime/deep-interview-state.ts +324 -0
- package/src/gjc-runtime/gc-render.ts +70 -0
- package/src/gjc-runtime/gc-runtime.ts +403 -0
- package/src/gjc-runtime/ledger-event-renderer.ts +164 -0
- package/src/gjc-runtime/ralplan-runtime.ts +58 -7
- package/src/gjc-runtime/state-renderer.ts +12 -3
- package/src/gjc-runtime/state-runtime.ts +46 -29
- package/src/gjc-runtime/team-gc.ts +49 -0
- package/src/gjc-runtime/team-runtime.ts +211 -8
- package/src/gjc-runtime/tmux-common.ts +29 -0
- package/src/gjc-runtime/tmux-gc.ts +176 -0
- package/src/gjc-runtime/tmux-sessions.ts +68 -12
- package/src/gjc-runtime/ultragoal-runtime.ts +517 -41
- package/src/gjc-runtime/workflow-manifest.generated.json +27 -1
- package/src/gjc-runtime/workflow-manifest.ts +16 -1
- package/src/harness-control-plane/gc-adapter.ts +184 -0
- package/src/harness-control-plane/owner.ts +89 -27
- package/src/harness-control-plane/receipt-spool.ts +128 -0
- package/src/harness-control-plane/state-machine.ts +27 -6
- package/src/harness-control-plane/storage.ts +93 -0
- package/src/harness-control-plane/types.ts +4 -0
- package/src/hindsight/mental-models.ts +17 -16
- package/src/internal-urls/docs-index.generated.ts +14 -8
- package/src/main.ts +7 -2
- package/src/modes/components/assistant-message.ts +26 -14
- package/src/modes/components/diff.ts +97 -0
- package/src/modes/components/hook-selector.ts +19 -0
- package/src/modes/components/model-selector.ts +370 -181
- package/src/modes/components/status-line/segments.ts +1 -1
- package/src/modes/components/tool-execution.ts +30 -13
- package/src/modes/controllers/command-controller.ts +25 -6
- package/src/modes/controllers/extension-ui-controller.ts +3 -0
- package/src/modes/controllers/selector-controller.ts +34 -42
- package/src/modes/rpc/rpc-client.ts +3 -2
- package/src/modes/rpc/rpc-mode.ts +187 -39
- package/src/modes/rpc/rpc-types.ts +5 -2
- package/src/modes/shared/agent-wire/command-dispatch.ts +279 -257
- package/src/modes/shared/agent-wire/command-validation.ts +11 -0
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +30 -1
- package/src/modes/shared/agent-wire/session-registry.ts +109 -0
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +24 -0
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +23 -3
- package/src/modes/shared/agent-wire/unattended-session.ts +16 -1
- package/src/sdk.ts +46 -5
- package/src/secrets/obfuscator.ts +102 -27
- package/src/session/agent-session.ts +179 -25
- package/src/session/blob-store.ts +148 -6
- package/src/session/session-manager.ts +311 -60
- package/src/session/streaming-output.ts +185 -122
- package/src/session/tool-choice-queue.ts +23 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +7 -1
- package/src/skill-state/workflow-hud.ts +106 -10
- package/src/slash-commands/builtin-registry.ts +3 -2
- package/src/task/executor.ts +78 -6
- package/src/task/receipt.ts +5 -0
- package/src/task/render.ts +21 -1
- package/src/task/types.ts +8 -0
- package/src/thinking-metadata.ts +51 -0
- package/src/thinking.ts +26 -46
- package/src/tools/ask.ts +56 -1
- package/src/tools/bash.ts +1 -1
- package/src/tools/index.ts +2 -0
- package/src/tools/job.ts +3 -2
- package/src/tools/monitor.ts +36 -1
- package/src/tools/resolve.ts +93 -18
- package/src/tools/subagent-render.ts +9 -0
- package/src/tools/subagent.ts +26 -2
- package/src/utils/edit-mode.ts +1 -1
- package/src/utils/tool-choice.ts +45 -16
|
@@ -12,6 +12,8 @@ import type { ContextUsage } from "../../extensibility/extensions/types";
|
|
|
12
12
|
import type { SessionStats } from "../../session/agent-session";
|
|
13
13
|
import type { TodoPhase } from "../../tools/todo-write";
|
|
14
14
|
|
|
15
|
+
export type RpcGetStateInclude = "tools" | "dumpTools" | "systemPrompt";
|
|
16
|
+
|
|
15
17
|
// ============================================================================
|
|
16
18
|
// RPC Commands (stdin)
|
|
17
19
|
// ============================================================================
|
|
@@ -26,7 +28,7 @@ export type RpcCommand =
|
|
|
26
28
|
| { id?: string; type: "new_session"; parentSession?: string }
|
|
27
29
|
|
|
28
30
|
// State
|
|
29
|
-
| { id?: string; type: "get_state" }
|
|
31
|
+
| { id?: string; type: "get_state"; include?: RpcGetStateInclude[] }
|
|
30
32
|
| { id?: string; type: "set_todos"; phases: TodoPhase[] }
|
|
31
33
|
| { id?: string; type: "set_host_tools"; tools: RpcHostToolDefinition[] }
|
|
32
34
|
| { id?: string; type: "set_host_uri_schemes"; schemes: RpcHostUriSchemeDefinition[] }
|
|
@@ -99,8 +101,9 @@ export interface RpcSessionState {
|
|
|
99
101
|
messageCount: number;
|
|
100
102
|
queuedMessageCount: number;
|
|
101
103
|
todoPhases: TodoPhase[];
|
|
102
|
-
/**
|
|
104
|
+
/** Optional static system prompt blocks. Omitted by default; request with get_state include ["systemPrompt"]. */
|
|
103
105
|
systemPrompt?: string[];
|
|
106
|
+
/** Optional static tool schemas. Omitted by default; request with get_state include ["tools"]. */
|
|
104
107
|
dumpTools?: Array<{ name: string; description: string; parameters: unknown }>;
|
|
105
108
|
/** Current context window usage. Null tokens/percent when unknown (e.g. right after compaction). */
|
|
106
109
|
contextUsage?: ContextUsage;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentTool } from "@gajae-code/agent-core";
|
|
2
|
+
import { ThinkingLevel } from "@gajae-code/agent-core";
|
|
2
3
|
import { getOAuthProviders } from "@gajae-code/ai/utils/oauth";
|
|
3
4
|
import { Snowflake } from "@gajae-code/utils";
|
|
4
5
|
import type { ExtensionUIContext } from "../../../extensibility/extensions";
|
|
@@ -127,308 +128,329 @@ export async function dispatchRpcCommand(
|
|
|
127
128
|
const denied = preflight();
|
|
128
129
|
if (denied) return denied;
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
case "steer": {
|
|
142
|
-
await session.steer(command.message, command.images);
|
|
143
|
-
return rpcSuccess(id, "steer");
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
case "follow_up": {
|
|
147
|
-
await session.followUp(command.message, command.images);
|
|
148
|
-
return rpcSuccess(id, "follow_up");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
case "abort": {
|
|
152
|
-
await session.abort();
|
|
153
|
-
return rpcSuccess(id, "abort");
|
|
154
|
-
}
|
|
131
|
+
try {
|
|
132
|
+
switch (command.type) {
|
|
133
|
+
case "prompt": {
|
|
134
|
+
session
|
|
135
|
+
.prompt(command.message, {
|
|
136
|
+
images: command.images,
|
|
137
|
+
streamingBehavior: command.streamingBehavior,
|
|
138
|
+
})
|
|
139
|
+
.catch(e => output(rpcError(id, "prompt", serializeRpcDispatchError(e))));
|
|
140
|
+
return reconcile() ?? rpcSuccess(id, "prompt");
|
|
141
|
+
}
|
|
155
142
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
.catch(e => output(rpcError(id, "abort_and_prompt", e.message)));
|
|
161
|
-
return rpcSuccess(id, "abort_and_prompt");
|
|
162
|
-
}
|
|
143
|
+
case "steer": {
|
|
144
|
+
await session.steer(command.message, command.images);
|
|
145
|
+
return rpcSuccess(id, "steer");
|
|
146
|
+
}
|
|
163
147
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
148
|
+
case "follow_up": {
|
|
149
|
+
await session.followUp(command.message, command.images);
|
|
150
|
+
return rpcSuccess(id, "follow_up");
|
|
151
|
+
}
|
|
169
152
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
isStreaming: session.isStreaming,
|
|
175
|
-
isCompacting: session.isCompacting,
|
|
176
|
-
steeringMode: session.steeringMode,
|
|
177
|
-
followUpMode: session.followUpMode,
|
|
178
|
-
interruptMode: session.interruptMode,
|
|
179
|
-
sessionFile: session.sessionFile,
|
|
180
|
-
sessionId: session.sessionId,
|
|
181
|
-
sessionName: session.sessionName,
|
|
182
|
-
autoCompactionEnabled: session.autoCompactionEnabled,
|
|
183
|
-
messageCount: session.messages.length,
|
|
184
|
-
queuedMessageCount: session.queuedMessageCount,
|
|
185
|
-
todoPhases: session.getTodoPhases(),
|
|
186
|
-
systemPrompt: session.systemPrompt,
|
|
187
|
-
dumpTools: session.agent.state.tools.map(tool => ({
|
|
188
|
-
name: tool.name,
|
|
189
|
-
description: tool.description,
|
|
190
|
-
parameters: tool.parameters,
|
|
191
|
-
})),
|
|
192
|
-
contextUsage: session.getContextUsage(),
|
|
193
|
-
};
|
|
194
|
-
return rpcSuccess(id, "get_state", state);
|
|
195
|
-
}
|
|
153
|
+
case "abort": {
|
|
154
|
+
await session.abort();
|
|
155
|
+
return rpcSuccess(id, "abort");
|
|
156
|
+
}
|
|
196
157
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
158
|
+
case "abort_and_prompt": {
|
|
159
|
+
await session.abort();
|
|
160
|
+
session
|
|
161
|
+
.prompt(command.message, { images: command.images })
|
|
162
|
+
.catch(e => output(rpcError(id, "abort_and_prompt", e.message)));
|
|
163
|
+
return rpcSuccess(id, "abort_and_prompt");
|
|
164
|
+
}
|
|
201
165
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
166
|
+
case "new_session": {
|
|
167
|
+
const options = command.parentSession ? { parentSession: command.parentSession } : undefined;
|
|
168
|
+
const cancelled = !(await session.newSession(options));
|
|
169
|
+
return rpcSuccess(id, "new_session", { cancelled });
|
|
170
|
+
}
|
|
208
171
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
172
|
+
case "get_state": {
|
|
173
|
+
const state: RpcSessionState = {
|
|
174
|
+
model: session.model,
|
|
175
|
+
thinkingLevel: session.thinkingLevel,
|
|
176
|
+
isStreaming: session.isStreaming,
|
|
177
|
+
isCompacting: session.isCompacting,
|
|
178
|
+
steeringMode: session.steeringMode,
|
|
179
|
+
followUpMode: session.followUpMode,
|
|
180
|
+
interruptMode: session.interruptMode,
|
|
181
|
+
sessionFile: session.sessionFile,
|
|
182
|
+
sessionId: session.sessionId,
|
|
183
|
+
sessionName: session.sessionName,
|
|
184
|
+
autoCompactionEnabled: session.autoCompactionEnabled,
|
|
185
|
+
messageCount: session.messages.length,
|
|
186
|
+
queuedMessageCount: session.queuedMessageCount,
|
|
187
|
+
todoPhases: session.getTodoPhases(),
|
|
188
|
+
contextUsage: session.getContextUsage(),
|
|
189
|
+
};
|
|
190
|
+
const include = new Set(command.include ?? []);
|
|
191
|
+
if (include.has("systemPrompt")) {
|
|
192
|
+
state.systemPrompt = session.systemPrompt;
|
|
193
|
+
}
|
|
194
|
+
if (include.has("tools") || include.has("dumpTools")) {
|
|
195
|
+
state.dumpTools = session.agent.state.tools.map(tool => ({
|
|
196
|
+
name: tool.name,
|
|
197
|
+
description: tool.description,
|
|
198
|
+
parameters: tool.parameters,
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
return rpcSuccess(id, "get_state", state);
|
|
215
202
|
}
|
|
216
|
-
}
|
|
217
203
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (!model) {
|
|
222
|
-
return rpcError(id, "set_model", `Model not found: ${command.provider}/${command.modelId}`);
|
|
204
|
+
case "set_todos": {
|
|
205
|
+
session.setTodoPhases(command.phases);
|
|
206
|
+
return rpcSuccess(id, "set_todos", { todoPhases: session.getTodoPhases() });
|
|
223
207
|
}
|
|
224
|
-
await session.setModel(model);
|
|
225
|
-
return rpcSuccess(id, "set_model", model);
|
|
226
|
-
}
|
|
227
208
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
209
|
+
case "set_host_tools": {
|
|
210
|
+
const tools = normalizeHostToolDefinitions(command.tools);
|
|
211
|
+
const rpcTools = hostToolRegistry.setTools(tools);
|
|
212
|
+
await session.refreshRpcHostTools(rpcTools);
|
|
213
|
+
return rpcSuccess(id, "set_host_tools", { toolNames: tools.map(tool => tool.name) });
|
|
232
214
|
}
|
|
233
|
-
return rpcSuccess(id, "cycle_model", result);
|
|
234
|
-
}
|
|
235
215
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
216
|
+
case "set_host_uri_schemes": {
|
|
217
|
+
try {
|
|
218
|
+
const schemes = hostUriRegistry.setSchemes(command.schemes);
|
|
219
|
+
return rpcSuccess(id, "set_host_uri_schemes", { schemes });
|
|
220
|
+
} catch (err) {
|
|
221
|
+
return rpcError(id, "set_host_uri_schemes", err instanceof Error ? err.message : String(err));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
240
224
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
225
|
+
case "set_model": {
|
|
226
|
+
const models = session.getAvailableModels();
|
|
227
|
+
const model = models.find(m => m.provider === command.provider && m.id === command.modelId);
|
|
228
|
+
if (!model) {
|
|
229
|
+
return rpcError(id, "set_model", `Model not found: ${command.provider}/${command.modelId}`);
|
|
230
|
+
}
|
|
231
|
+
await session.setModel(model);
|
|
232
|
+
return rpcSuccess(id, "set_model", model);
|
|
233
|
+
}
|
|
245
234
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
235
|
+
case "cycle_model": {
|
|
236
|
+
const result = await session.cycleModel();
|
|
237
|
+
if (!result) {
|
|
238
|
+
return rpcSuccess(id, "cycle_model", null);
|
|
239
|
+
}
|
|
240
|
+
return rpcSuccess(id, "cycle_model", result);
|
|
250
241
|
}
|
|
251
|
-
return rpcSuccess(id, "cycle_thinking_level", { level });
|
|
252
|
-
}
|
|
253
242
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
243
|
+
case "get_available_models": {
|
|
244
|
+
const models = session.getAvailableModels();
|
|
245
|
+
return rpcSuccess(id, "get_available_models", { models });
|
|
246
|
+
}
|
|
258
247
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
248
|
+
case "set_thinking_level": {
|
|
249
|
+
if (!(Object.values(ThinkingLevel) as string[]).includes(command.level as string)) {
|
|
250
|
+
return rpcError(id, "set_thinking_level", `Invalid thinking level: ${String(command.level)}`);
|
|
251
|
+
}
|
|
252
|
+
session.setThinkingLevel(command.level);
|
|
253
|
+
return rpcSuccess(id, "set_thinking_level");
|
|
254
|
+
}
|
|
263
255
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
256
|
+
case "cycle_thinking_level": {
|
|
257
|
+
const level = session.cycleThinkingLevel();
|
|
258
|
+
if (!level) {
|
|
259
|
+
return rpcSuccess(id, "cycle_thinking_level", null);
|
|
260
|
+
}
|
|
261
|
+
return rpcSuccess(id, "cycle_thinking_level", { level });
|
|
262
|
+
}
|
|
268
263
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
264
|
+
case "set_steering_mode": {
|
|
265
|
+
if ((command.mode as string) !== "all" && (command.mode as string) !== "one-at-a-time") {
|
|
266
|
+
return rpcError(id, "set_steering_mode", `Invalid steering mode: ${String(command.mode)}`);
|
|
267
|
+
}
|
|
268
|
+
session.setSteeringMode(command.mode);
|
|
269
|
+
return rpcSuccess(id, "set_steering_mode");
|
|
270
|
+
}
|
|
273
271
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
272
|
+
case "set_follow_up_mode": {
|
|
273
|
+
if ((command.mode as string) !== "all" && (command.mode as string) !== "one-at-a-time") {
|
|
274
|
+
return rpcError(id, "set_follow_up_mode", `Invalid follow-up mode: ${String(command.mode)}`);
|
|
275
|
+
}
|
|
276
|
+
session.setFollowUpMode(command.mode);
|
|
277
|
+
return rpcSuccess(id, "set_follow_up_mode");
|
|
278
|
+
}
|
|
278
279
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
280
|
+
case "set_interrupt_mode": {
|
|
281
|
+
if ((command.mode as string) !== "immediate" && (command.mode as string) !== "wait") {
|
|
282
|
+
return rpcError(id, "set_interrupt_mode", `Invalid interrupt mode: ${String(command.mode)}`);
|
|
283
|
+
}
|
|
284
|
+
session.setInterruptMode(command.mode);
|
|
285
|
+
return rpcSuccess(id, "set_interrupt_mode");
|
|
286
|
+
}
|
|
283
287
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
+
case "compact": {
|
|
289
|
+
const result = await session.compact(command.customInstructions);
|
|
290
|
+
return rpcSuccess(id, "compact", result);
|
|
291
|
+
}
|
|
288
292
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
+
case "set_auto_compaction": {
|
|
294
|
+
session.setAutoCompactionEnabled(command.enabled);
|
|
295
|
+
return rpcSuccess(id, "set_auto_compaction");
|
|
296
|
+
}
|
|
293
297
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
+
case "set_auto_retry": {
|
|
299
|
+
session.setAutoRetryEnabled(command.enabled);
|
|
300
|
+
return rpcSuccess(id, "set_auto_retry");
|
|
301
|
+
}
|
|
298
302
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
+
case "abort_retry": {
|
|
304
|
+
session.abortRetry();
|
|
305
|
+
return rpcSuccess(id, "abort_retry");
|
|
306
|
+
}
|
|
303
307
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
+
case "bash": {
|
|
309
|
+
const result = await session.executeBash(command.command);
|
|
310
|
+
return reconcile() ?? rpcSuccess(id, "bash", result);
|
|
311
|
+
}
|
|
308
312
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
+
case "abort_bash": {
|
|
314
|
+
session.abortBash();
|
|
315
|
+
return rpcSuccess(id, "abort_bash");
|
|
316
|
+
}
|
|
313
317
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
+
case "get_session_stats": {
|
|
319
|
+
const stats = session.getSessionStats();
|
|
320
|
+
return rpcSuccess(id, "get_session_stats", stats);
|
|
321
|
+
}
|
|
318
322
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
+
case "export_html": {
|
|
324
|
+
const path = await session.exportToHtml(command.outputPath);
|
|
325
|
+
return rpcSuccess(id, "export_html", { path });
|
|
326
|
+
}
|
|
323
327
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
+
case "switch_session": {
|
|
329
|
+
const cancelled = !(await session.switchSession(command.sessionPath));
|
|
330
|
+
return rpcSuccess(id, "switch_session", { cancelled });
|
|
331
|
+
}
|
|
328
332
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return rpcError(id, "set_session_name", "Session name cannot be empty");
|
|
333
|
+
case "branch": {
|
|
334
|
+
const result = await session.branch(command.entryId);
|
|
335
|
+
return rpcSuccess(id, "branch", { text: result.selectedText, cancelled: result.cancelled });
|
|
333
336
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
+
|
|
338
|
+
case "get_branch_messages": {
|
|
339
|
+
const messages = session.getUserMessagesForBranching();
|
|
340
|
+
return rpcSuccess(id, "get_branch_messages", { messages });
|
|
337
341
|
}
|
|
338
|
-
return rpcSuccess(id, "set_session_name");
|
|
339
|
-
}
|
|
340
342
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
343
|
+
case "get_last_assistant_text": {
|
|
344
|
+
const text = session.getLastAssistantText();
|
|
345
|
+
return rpcSuccess(id, "get_last_assistant_text", { text });
|
|
346
|
+
}
|
|
345
347
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
348
|
+
case "set_session_name": {
|
|
349
|
+
const name = command.name.trim();
|
|
350
|
+
if (!name) {
|
|
351
|
+
return rpcError(id, "set_session_name", "Session name cannot be empty");
|
|
352
|
+
}
|
|
353
|
+
const applied = await session.setSessionName(name, "user");
|
|
354
|
+
if (!applied) {
|
|
355
|
+
return rpcError(id, "set_session_name", "Session name cannot be empty");
|
|
356
|
+
}
|
|
357
|
+
return rpcSuccess(id, "set_session_name");
|
|
358
|
+
}
|
|
349
359
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
id:
|
|
353
|
-
|
|
354
|
-
available: provider.available,
|
|
355
|
-
authenticated: session.modelRegistry.authStorage.hasAuth(provider.id),
|
|
356
|
-
}));
|
|
357
|
-
return rpcSuccess(id, "get_login_providers", { providers });
|
|
358
|
-
}
|
|
360
|
+
case "handoff": {
|
|
361
|
+
const result = await session.handoff(command.customInstructions);
|
|
362
|
+
return rpcSuccess(id, "handoff", result ? { savedPath: result.savedPath } : null);
|
|
363
|
+
}
|
|
359
364
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
if (!knownProvider) {
|
|
363
|
-
return rpcError(id, "login", `Unknown OAuth provider: ${command.providerId}`);
|
|
364
|
-
}
|
|
365
|
-
const uiCtx = createUiContext();
|
|
366
|
-
let authEmitted = false;
|
|
367
|
-
try {
|
|
368
|
-
await session.modelRegistry.authStorage.login(command.providerId, {
|
|
369
|
-
onAuth: info => {
|
|
370
|
-
authEmitted = true;
|
|
371
|
-
output({
|
|
372
|
-
type: "extension_ui_request",
|
|
373
|
-
id: Snowflake.next() as string,
|
|
374
|
-
method: "open_url",
|
|
375
|
-
url: info.url,
|
|
376
|
-
instructions: info.instructions,
|
|
377
|
-
} as RpcExtensionUIRequest);
|
|
378
|
-
},
|
|
379
|
-
onProgress: message => {
|
|
380
|
-
uiCtx.notify(message, "info");
|
|
381
|
-
},
|
|
382
|
-
onPrompt: () => {
|
|
383
|
-
if (!authEmitted) {
|
|
384
|
-
return Promise.reject(
|
|
385
|
-
new Error(
|
|
386
|
-
`Provider '${command.providerId}' requires interactive prompts ` +
|
|
387
|
-
"which are not supported in RPC mode. Use the terminal UI to log in.",
|
|
388
|
-
),
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
return new Promise<string>(() => {});
|
|
392
|
-
},
|
|
393
|
-
});
|
|
394
|
-
await session.modelRegistry.refresh();
|
|
395
|
-
return rpcSuccess(id, "login", { providerId: command.providerId });
|
|
396
|
-
} catch (err: unknown) {
|
|
397
|
-
return rpcError(id, "login", err instanceof Error ? err.message : String(err));
|
|
365
|
+
case "get_messages": {
|
|
366
|
+
return rpcSuccess(id, "get_messages", { messages: session.messages });
|
|
398
367
|
}
|
|
399
|
-
}
|
|
400
368
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
369
|
+
case "get_login_providers": {
|
|
370
|
+
const providers = getOAuthProviders().map(provider => ({
|
|
371
|
+
id: provider.id,
|
|
372
|
+
name: provider.name,
|
|
373
|
+
available: provider.available,
|
|
374
|
+
authenticated: session.modelRegistry.authStorage.hasAuth(provider.id),
|
|
375
|
+
}));
|
|
376
|
+
return rpcSuccess(id, "get_login_providers", { providers });
|
|
404
377
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
378
|
+
|
|
379
|
+
case "login": {
|
|
380
|
+
const knownProvider = getOAuthProviders().find(p => p.id === command.providerId);
|
|
381
|
+
if (!knownProvider) {
|
|
382
|
+
return rpcError(id, "login", `Unknown OAuth provider: ${command.providerId}`);
|
|
383
|
+
}
|
|
384
|
+
const uiCtx = createUiContext();
|
|
385
|
+
let authEmitted = false;
|
|
386
|
+
try {
|
|
387
|
+
await session.modelRegistry.authStorage.login(command.providerId, {
|
|
388
|
+
onAuth: info => {
|
|
389
|
+
authEmitted = true;
|
|
390
|
+
output({
|
|
391
|
+
type: "extension_ui_request",
|
|
392
|
+
id: Snowflake.next() as string,
|
|
393
|
+
method: "open_url",
|
|
394
|
+
url: info.url,
|
|
395
|
+
instructions: info.instructions,
|
|
396
|
+
} as RpcExtensionUIRequest);
|
|
397
|
+
},
|
|
398
|
+
onProgress: message => {
|
|
399
|
+
uiCtx.notify(message, "info");
|
|
400
|
+
},
|
|
401
|
+
onPrompt: () => {
|
|
402
|
+
if (!authEmitted) {
|
|
403
|
+
return Promise.reject(
|
|
404
|
+
new Error(
|
|
405
|
+
`Provider '${command.providerId}' requires interactive prompts ` +
|
|
406
|
+
"which are not supported in RPC mode. Use the terminal UI to log in.",
|
|
407
|
+
),
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
return new Promise<string>(() => {});
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
await session.modelRegistry.refresh();
|
|
414
|
+
return rpcSuccess(id, "login", { providerId: command.providerId });
|
|
415
|
+
} catch (err: unknown) {
|
|
416
|
+
return rpcError(id, "login", err instanceof Error ? err.message : String(err));
|
|
417
|
+
}
|
|
410
418
|
}
|
|
411
|
-
}
|
|
412
419
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
420
|
+
case "negotiate_unattended": {
|
|
421
|
+
if (!unattendedControlPlane) {
|
|
422
|
+
return rpcError(id, "negotiate_unattended", "unattended mode is not available on this session");
|
|
423
|
+
}
|
|
424
|
+
try {
|
|
425
|
+
const accepted = unattendedControlPlane.negotiate(command.declaration);
|
|
426
|
+
return rpcSuccess(id, "negotiate_unattended", accepted);
|
|
427
|
+
} catch (err) {
|
|
428
|
+
return typedError("negotiate_unattended", err);
|
|
429
|
+
}
|
|
416
430
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
431
|
+
|
|
432
|
+
case "workflow_gate_response": {
|
|
433
|
+
if (!unattendedControlPlane) {
|
|
434
|
+
return rpcError(id, "workflow_gate_response", "workflow gates are not available on this session");
|
|
435
|
+
}
|
|
436
|
+
try {
|
|
437
|
+
const resolution = await unattendedControlPlane.resolveGate({
|
|
438
|
+
gate_id: command.gate_id,
|
|
439
|
+
answer: command.answer,
|
|
440
|
+
idempotency_key: command.idempotency_key,
|
|
441
|
+
});
|
|
442
|
+
return rpcSuccess(id, "workflow_gate_response", resolution);
|
|
443
|
+
} catch (err) {
|
|
444
|
+
return typedError("workflow_gate_response", err);
|
|
445
|
+
}
|
|
426
446
|
}
|
|
427
|
-
}
|
|
428
447
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
448
|
+
default: {
|
|
449
|
+
const unknownCommand = command as { type: string };
|
|
450
|
+
return rpcError(undefined, unknownCommand.type, `Unknown command: ${unknownCommand.type}`);
|
|
451
|
+
}
|
|
432
452
|
}
|
|
453
|
+
} catch (err) {
|
|
454
|
+
return rpcError(id, command.type, serializeRpcDispatchError(err));
|
|
433
455
|
}
|
|
434
456
|
}
|
|
@@ -28,6 +28,15 @@ function stringArray(value: unknown): value is string[] {
|
|
|
28
28
|
return Array.isArray(value) && value.every(item => typeof item === "string");
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const GET_STATE_INCLUDES = new Set(["tools", "dumpTools", "systemPrompt"]);
|
|
32
|
+
|
|
33
|
+
function optionalGetStateInclude(value: unknown): boolean {
|
|
34
|
+
return (
|
|
35
|
+
value === undefined ||
|
|
36
|
+
(Array.isArray(value) && value.every(item => typeof item === "string" && GET_STATE_INCLUDES.has(item)))
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
function todoPhase(value: unknown): boolean {
|
|
32
41
|
if (!isRecord(value) || typeof value.name !== "string" || !Array.isArray(value.tasks)) return false;
|
|
33
42
|
return value.tasks.every(
|
|
@@ -96,7 +105,9 @@ export function isRpcCommand(value: unknown): value is RpcCommand {
|
|
|
96
105
|
case "follow_up":
|
|
97
106
|
return stringField(value, "message") && optionalArray(value.images);
|
|
98
107
|
case "abort":
|
|
108
|
+
return true;
|
|
99
109
|
case "get_state":
|
|
110
|
+
return optionalGetStateInclude(value.include);
|
|
100
111
|
case "cycle_model":
|
|
101
112
|
case "get_available_models":
|
|
102
113
|
case "cycle_thinking_level":
|