@gajae-code/coding-agent 0.5.0 → 0.5.2
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 +36 -0
- package/README.md +1 -1
- 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/cli/setup-cli.d.ts +8 -1
- package/dist/types/commands/gc.d.ts +26 -0
- package/dist/types/commands/setup.d.ts +7 -0
- package/dist/types/config/file-lock-gc.d.ts +5 -0
- package/dist/types/config/file-lock.d.ts +29 -0
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/models-config-schema.d.ts +5 -0
- package/dist/types/config/settings-schema.d.ts +62 -0
- 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/state-writer.d.ts +64 -2
- package/dist/types/gjc-runtime/team-gc.d.ts +7 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/tmux-common.d.ts +11 -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/gjc-runtime/ultragoal-guard.d.ts +10 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +29 -0
- package/dist/types/harness-control-plane/gc-adapter.d.ts +3 -0
- package/dist/types/harness-control-plane/owner.d.ts +7 -0
- package/dist/types/harness-control-plane/storage.d.ts +20 -0
- package/dist/types/modes/components/hook-selector.d.ts +7 -1
- package/dist/types/modes/components/provider-onboarding-selector.d.ts +1 -1
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +72 -2
- 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/modes/shared/agent-wire/unattended-session.d.ts +10 -0
- package/dist/types/modes/theme/defaults/index.d.ts +302 -0
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/blob-store.d.ts +39 -3
- package/dist/types/session/history-storage.d.ts +2 -2
- package/dist/types/session/session-manager.d.ts +10 -1
- package/dist/types/setup/credential-import.d.ts +79 -0
- package/dist/types/skill-state/workflow-hud.d.ts +14 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/task/render.d.ts +1 -1
- package/dist/types/tools/ask.d.ts +15 -1
- package/dist/types/tools/subagent-render.d.ts +7 -1
- package/dist/types/tools/subagent.d.ts +27 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +5 -0
- package/dist/types/web/search/index.d.ts +4 -4
- package/dist/types/web/search/provider.d.ts +16 -20
- package/dist/types/web/search/providers/base.d.ts +2 -1
- package/dist/types/web/search/providers/openai-compatible.d.ts +9 -0
- package/dist/types/web/search/types.d.ts +14 -2
- package/package.json +7 -7
- package/scripts/build-binary.ts +7 -0
- package/src/async/job-manager.ts +52 -0
- package/src/cli/args.ts +5 -0
- package/src/cli/auth-broker-cli.ts +1 -0
- package/src/cli/fast-help.ts +2 -0
- package/src/cli/list-models.ts +13 -1
- package/src/cli/setup-cli.ts +138 -3
- package/src/cli.ts +1 -0
- package/src/commands/gc.ts +22 -0
- package/src/commands/harness.ts +7 -3
- package/src/commands/setup.ts +5 -1
- package/src/commands/ultragoal.ts +3 -1
- package/src/config/file-lock-gc.ts +193 -0
- package/src/config/file-lock.ts +66 -10
- package/src/config/model-profile-activation.ts +15 -3
- package/src/config/model-profiles.ts +39 -30
- package/src/config/model-registry.ts +21 -1
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings-schema.ts +62 -0
- package/src/coordinator/contract.ts +1 -0
- package/src/coordinator-mcp/server.ts +459 -3
- 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/ultragoal/SKILL.md +30 -8
- package/src/defaults/gjc-defaults.ts +7 -0
- package/src/defaults/gjc-grok-cli.ts +22 -0
- 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 +457 -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/launch-tmux.ts +3 -4
- package/src/gjc-runtime/ledger-event-renderer.ts +164 -0
- package/src/gjc-runtime/ralplan-runtime.ts +232 -19
- package/src/gjc-runtime/state-renderer.ts +12 -3
- package/src/gjc-runtime/state-runtime.ts +48 -30
- package/src/gjc-runtime/state-writer.ts +254 -7
- package/src/gjc-runtime/team-gc.ts +49 -0
- package/src/gjc-runtime/team-runtime.ts +179 -2
- package/src/gjc-runtime/tmux-common.ts +14 -0
- package/src/gjc-runtime/tmux-gc.ts +177 -0
- package/src/gjc-runtime/tmux-sessions.ts +49 -1
- package/src/gjc-runtime/ultragoal-guard.ts +155 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +1239 -31
- package/src/gjc-runtime/workflow-manifest.generated.json +44 -0
- package/src/gjc-runtime/workflow-manifest.ts +12 -0
- package/src/harness-control-plane/gc-adapter.ts +184 -0
- package/src/harness-control-plane/owner.ts +14 -2
- package/src/harness-control-plane/rpc-adapter.ts +1 -1
- package/src/harness-control-plane/storage.ts +70 -0
- package/src/hooks/skill-state.ts +121 -2
- package/src/internal-urls/docs-index.generated.ts +22 -12
- package/src/lsp/defaults.json +1 -0
- package/src/main.ts +18 -3
- package/src/modes/acp/acp-agent.ts +4 -2
- package/src/modes/bridge/bridge-mode.ts +2 -1
- package/src/modes/components/history-search.ts +5 -2
- package/src/modes/components/hook-selector.ts +19 -0
- package/src/modes/components/model-selector.ts +51 -8
- package/src/modes/components/provider-onboarding-selector.ts +6 -1
- package/src/modes/components/status-line/segments.ts +1 -1
- 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 +81 -1
- package/src/modes/interactive-mode.ts +11 -1
- package/src/modes/rpc/rpc-mode.ts +266 -34
- package/src/modes/shared/agent-wire/command-dispatch.ts +281 -261
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +30 -1
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +3 -0
- 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 +32 -2
- package/src/modes/theme/defaults/claude-code.json +100 -0
- package/src/modes/theme/defaults/codex.json +100 -0
- package/src/modes/theme/defaults/index.ts +6 -0
- package/src/modes/theme/defaults/opencode.json +102 -0
- package/src/modes/theme/theme.ts +2 -2
- package/src/modes/types.ts +1 -1
- package/src/prompts/agents/executor.md +5 -2
- package/src/sdk.ts +29 -4
- package/src/session/agent-session.ts +99 -19
- package/src/session/blob-store.ts +59 -3
- package/src/session/history-storage.ts +32 -11
- package/src/session/session-manager.ts +72 -20
- package/src/setup/credential-import.ts +429 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +7 -1
- package/src/skill-state/deep-interview-mutation-guard.ts +2 -1
- package/src/skill-state/workflow-hud.ts +106 -10
- package/src/slash-commands/builtin-registry.ts +3 -2
- package/src/task/executor.ts +16 -1
- package/src/task/render.ts +18 -7
- package/src/tools/ask.ts +59 -2
- package/src/tools/cron.ts +1 -1
- package/src/tools/job.ts +3 -2
- package/src/tools/monitor.ts +36 -1
- package/src/tools/subagent-render.ts +128 -29
- package/src/tools/subagent.ts +173 -9
- package/src/tools/ultragoal-ask-guard.ts +39 -0
- package/src/web/search/index.ts +25 -25
- package/src/web/search/provider.ts +178 -87
- package/src/web/search/providers/base.ts +2 -1
- package/src/web/search/providers/openai-compatible.ts +151 -0
- package/src/web/search/types.ts +47 -22
|
@@ -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,313 +128,332 @@ 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
|
-
thinkingLevel: session.thinkingLevel,
|
|
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
|
-
contextUsage: session.getContextUsage(),
|
|
187
|
-
};
|
|
188
|
-
const include = new Set(command.include ?? []);
|
|
189
|
-
if (include.has("systemPrompt")) {
|
|
190
|
-
state.systemPrompt = session.systemPrompt;
|
|
191
|
-
}
|
|
192
|
-
if (include.has("tools") || include.has("dumpTools")) {
|
|
193
|
-
state.dumpTools = session.agent.state.tools.map(tool => ({
|
|
194
|
-
name: tool.name,
|
|
195
|
-
description: tool.description,
|
|
196
|
-
parameters: tool.parameters,
|
|
197
|
-
}));
|
|
153
|
+
case "abort": {
|
|
154
|
+
await session.abort();
|
|
155
|
+
return rpcSuccess(id, "abort");
|
|
198
156
|
}
|
|
199
|
-
return rpcSuccess(id, "get_state", state);
|
|
200
|
-
}
|
|
201
157
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
+
}
|
|
206
165
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
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
|
+
}
|
|
213
171
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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);
|
|
220
202
|
}
|
|
221
|
-
}
|
|
222
203
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (!model) {
|
|
227
|
-
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() });
|
|
228
207
|
}
|
|
229
|
-
await session.setModel(model);
|
|
230
|
-
return rpcSuccess(id, "set_model", model);
|
|
231
|
-
}
|
|
232
208
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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) });
|
|
237
214
|
}
|
|
238
|
-
return rpcSuccess(id, "cycle_model", result);
|
|
239
|
-
}
|
|
240
215
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
+
}
|
|
245
224
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
+
}
|
|
250
234
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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);
|
|
255
241
|
}
|
|
256
|
-
return rpcSuccess(id, "cycle_thinking_level", { level });
|
|
257
|
-
}
|
|
258
242
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
243
|
+
case "get_available_models": {
|
|
244
|
+
const models = session.getAvailableModels();
|
|
245
|
+
return rpcSuccess(id, "get_available_models", { models });
|
|
246
|
+
}
|
|
263
247
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
+
}
|
|
268
255
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
+
}
|
|
273
263
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
+
}
|
|
278
271
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
+
}
|
|
283
279
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
+
}
|
|
288
287
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
288
|
+
case "compact": {
|
|
289
|
+
const result = await session.compact(command.customInstructions);
|
|
290
|
+
return rpcSuccess(id, "compact", result);
|
|
291
|
+
}
|
|
293
292
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
293
|
+
case "set_auto_compaction": {
|
|
294
|
+
session.setAutoCompactionEnabled(command.enabled);
|
|
295
|
+
return rpcSuccess(id, "set_auto_compaction");
|
|
296
|
+
}
|
|
298
297
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
298
|
+
case "set_auto_retry": {
|
|
299
|
+
session.setAutoRetryEnabled(command.enabled);
|
|
300
|
+
return rpcSuccess(id, "set_auto_retry");
|
|
301
|
+
}
|
|
303
302
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
303
|
+
case "abort_retry": {
|
|
304
|
+
session.abortRetry();
|
|
305
|
+
return rpcSuccess(id, "abort_retry");
|
|
306
|
+
}
|
|
308
307
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
308
|
+
case "bash": {
|
|
309
|
+
const result = await session.executeBash(command.command);
|
|
310
|
+
return reconcile() ?? rpcSuccess(id, "bash", result);
|
|
311
|
+
}
|
|
313
312
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
313
|
+
case "abort_bash": {
|
|
314
|
+
session.abortBash();
|
|
315
|
+
return rpcSuccess(id, "abort_bash");
|
|
316
|
+
}
|
|
318
317
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
318
|
+
case "get_session_stats": {
|
|
319
|
+
const stats = session.getSessionStats();
|
|
320
|
+
return rpcSuccess(id, "get_session_stats", stats);
|
|
321
|
+
}
|
|
323
322
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
323
|
+
case "export_html": {
|
|
324
|
+
const path = await session.exportToHtml(command.outputPath);
|
|
325
|
+
return rpcSuccess(id, "export_html", { path });
|
|
326
|
+
}
|
|
328
327
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
328
|
+
case "switch_session": {
|
|
329
|
+
const cancelled = !(await session.switchSession(command.sessionPath));
|
|
330
|
+
return rpcSuccess(id, "switch_session", { cancelled });
|
|
331
|
+
}
|
|
333
332
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
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 });
|
|
338
336
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
337
|
+
|
|
338
|
+
case "get_branch_messages": {
|
|
339
|
+
const messages = session.getUserMessagesForBranching();
|
|
340
|
+
return rpcSuccess(id, "get_branch_messages", { messages });
|
|
342
341
|
}
|
|
343
|
-
return rpcSuccess(id, "set_session_name");
|
|
344
|
-
}
|
|
345
342
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
343
|
+
case "get_last_assistant_text": {
|
|
344
|
+
const text = session.getLastAssistantText();
|
|
345
|
+
return rpcSuccess(id, "get_last_assistant_text", { text });
|
|
346
|
+
}
|
|
350
347
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
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
|
+
}
|
|
354
359
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
id:
|
|
358
|
-
|
|
359
|
-
available: provider.available,
|
|
360
|
-
authenticated: session.modelRegistry.authStorage.hasAuth(provider.id),
|
|
361
|
-
}));
|
|
362
|
-
return rpcSuccess(id, "get_login_providers", { providers });
|
|
363
|
-
}
|
|
360
|
+
case "handoff": {
|
|
361
|
+
const result = await session.handoff(command.customInstructions);
|
|
362
|
+
return rpcSuccess(id, "handoff", result ? { savedPath: result.savedPath } : null);
|
|
363
|
+
}
|
|
364
364
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const uiCtx = createUiContext();
|
|
371
|
-
let authEmitted = false;
|
|
372
|
-
try {
|
|
373
|
-
await session.modelRegistry.authStorage.login(command.providerId, {
|
|
374
|
-
onAuth: info => {
|
|
375
|
-
authEmitted = true;
|
|
376
|
-
output({
|
|
377
|
-
type: "extension_ui_request",
|
|
378
|
-
id: Snowflake.next() as string,
|
|
379
|
-
method: "open_url",
|
|
380
|
-
url: info.url,
|
|
381
|
-
instructions: info.instructions,
|
|
382
|
-
} as RpcExtensionUIRequest);
|
|
383
|
-
},
|
|
384
|
-
onProgress: message => {
|
|
385
|
-
uiCtx.notify(message, "info");
|
|
386
|
-
},
|
|
387
|
-
onPrompt: () => {
|
|
388
|
-
if (!authEmitted) {
|
|
389
|
-
return Promise.reject(
|
|
390
|
-
new Error(
|
|
391
|
-
`Provider '${command.providerId}' requires interactive prompts ` +
|
|
392
|
-
"which are not supported in RPC mode. Use the terminal UI to log in.",
|
|
393
|
-
),
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
return new Promise<string>(() => {});
|
|
397
|
-
},
|
|
398
|
-
});
|
|
399
|
-
await session.modelRegistry.refresh();
|
|
400
|
-
return rpcSuccess(id, "login", { providerId: command.providerId });
|
|
401
|
-
} catch (err: unknown) {
|
|
402
|
-
return rpcError(id, "login", err instanceof Error ? err.message : String(err));
|
|
365
|
+
case "get_messages": {
|
|
366
|
+
// Fast-lane read: snapshot the live array so a concurrent ordered
|
|
367
|
+
// turn/compaction mutating session.messages in place cannot make this
|
|
368
|
+
// response serialize a half-rewritten array (#606, issue 13).
|
|
369
|
+
return rpcSuccess(id, "get_messages", { messages: [...session.messages] });
|
|
403
370
|
}
|
|
404
|
-
}
|
|
405
371
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
372
|
+
case "get_login_providers": {
|
|
373
|
+
const providers = getOAuthProviders().map(provider => ({
|
|
374
|
+
id: provider.id,
|
|
375
|
+
name: provider.name,
|
|
376
|
+
available: provider.available,
|
|
377
|
+
authenticated: session.modelRegistry.authStorage.hasAuth(provider.id),
|
|
378
|
+
}));
|
|
379
|
+
return rpcSuccess(id, "get_login_providers", { providers });
|
|
409
380
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
381
|
+
|
|
382
|
+
case "login": {
|
|
383
|
+
const knownProvider = getOAuthProviders().find(p => p.id === command.providerId);
|
|
384
|
+
if (!knownProvider) {
|
|
385
|
+
return rpcError(id, "login", `Unknown OAuth provider: ${command.providerId}`);
|
|
386
|
+
}
|
|
387
|
+
const uiCtx = createUiContext();
|
|
388
|
+
let authEmitted = false;
|
|
389
|
+
try {
|
|
390
|
+
await session.modelRegistry.authStorage.login(command.providerId, {
|
|
391
|
+
onAuth: info => {
|
|
392
|
+
authEmitted = true;
|
|
393
|
+
output({
|
|
394
|
+
type: "extension_ui_request",
|
|
395
|
+
id: Snowflake.next() as string,
|
|
396
|
+
method: "open_url",
|
|
397
|
+
url: info.url,
|
|
398
|
+
instructions: info.instructions,
|
|
399
|
+
} as RpcExtensionUIRequest);
|
|
400
|
+
},
|
|
401
|
+
onProgress: message => {
|
|
402
|
+
uiCtx.notify(message, "info");
|
|
403
|
+
},
|
|
404
|
+
onPrompt: () => {
|
|
405
|
+
if (!authEmitted) {
|
|
406
|
+
return Promise.reject(
|
|
407
|
+
new Error(
|
|
408
|
+
`Provider '${command.providerId}' requires interactive prompts ` +
|
|
409
|
+
"which are not supported in RPC mode. Use the terminal UI to log in.",
|
|
410
|
+
),
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
return new Promise<string>(() => {});
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
await session.modelRegistry.refresh();
|
|
417
|
+
return rpcSuccess(id, "login", { providerId: command.providerId });
|
|
418
|
+
} catch (err: unknown) {
|
|
419
|
+
return rpcError(id, "login", err instanceof Error ? err.message : String(err));
|
|
420
|
+
}
|
|
415
421
|
}
|
|
416
|
-
}
|
|
417
422
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
423
|
+
case "negotiate_unattended": {
|
|
424
|
+
if (!unattendedControlPlane) {
|
|
425
|
+
return rpcError(id, "negotiate_unattended", "unattended mode is not available on this session");
|
|
426
|
+
}
|
|
427
|
+
try {
|
|
428
|
+
const accepted = unattendedControlPlane.negotiate(command.declaration);
|
|
429
|
+
return rpcSuccess(id, "negotiate_unattended", accepted);
|
|
430
|
+
} catch (err) {
|
|
431
|
+
return typedError("negotiate_unattended", err);
|
|
432
|
+
}
|
|
421
433
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
434
|
+
|
|
435
|
+
case "workflow_gate_response": {
|
|
436
|
+
if (!unattendedControlPlane) {
|
|
437
|
+
return rpcError(id, "workflow_gate_response", "workflow gates are not available on this session");
|
|
438
|
+
}
|
|
439
|
+
try {
|
|
440
|
+
const resolution = await unattendedControlPlane.resolveGate({
|
|
441
|
+
gate_id: command.gate_id,
|
|
442
|
+
answer: command.answer,
|
|
443
|
+
idempotency_key: command.idempotency_key,
|
|
444
|
+
});
|
|
445
|
+
return rpcSuccess(id, "workflow_gate_response", resolution);
|
|
446
|
+
} catch (err) {
|
|
447
|
+
return typedError("workflow_gate_response", err);
|
|
448
|
+
}
|
|
431
449
|
}
|
|
432
|
-
}
|
|
433
450
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
451
|
+
default: {
|
|
452
|
+
const unknownCommand = command as { type: string };
|
|
453
|
+
return rpcError(id, unknownCommand.type, `Unknown command: ${unknownCommand.type}`);
|
|
454
|
+
}
|
|
437
455
|
}
|
|
456
|
+
} catch (err) {
|
|
457
|
+
return rpcError(id, command.type, serializeRpcDispatchError(err));
|
|
438
458
|
}
|
|
439
459
|
}
|
|
@@ -17,12 +17,26 @@ import type { OpenGateInput } from "./workflow-gate-broker";
|
|
|
17
17
|
/** "Other (type your own)" sentinel, mirroring the interactive ask tool. */
|
|
18
18
|
export const GATE_OTHER_OPTION = "Other (type your own)";
|
|
19
19
|
|
|
20
|
+
/** Optional structured deep-interview round metadata supplied by the agent. */
|
|
21
|
+
export interface AskGateDeepInterviewState {
|
|
22
|
+
round_id?: string;
|
|
23
|
+
round: number;
|
|
24
|
+
component: string;
|
|
25
|
+
dimension: string;
|
|
26
|
+
ambiguity: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
20
29
|
export interface AskGateQuestion {
|
|
21
30
|
id: string;
|
|
22
31
|
question: string;
|
|
23
32
|
options: Array<{ label: string }>;
|
|
24
33
|
multi?: boolean;
|
|
25
34
|
recommended?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Structured round metadata. When present it is the authoritative source for gate
|
|
37
|
+
* `stage_state`; when absent, the question text is regex-parsed as a fallback.
|
|
38
|
+
*/
|
|
39
|
+
deepInterview?: AskGateDeepInterviewState;
|
|
26
40
|
}
|
|
27
41
|
|
|
28
42
|
export interface AskGateResult {
|
|
@@ -130,6 +144,19 @@ function questionAnswerSchema(question: AskGateQuestion, labels: string[]): RpcJ
|
|
|
130
144
|
};
|
|
131
145
|
}
|
|
132
146
|
|
|
147
|
+
/** Build `stage_state` round metadata from the structured param (authoritative when present). */
|
|
148
|
+
function structuredDeepInterviewState(meta: AskGateDeepInterviewState): Record<string, unknown> {
|
|
149
|
+
const state: Record<string, unknown> = {
|
|
150
|
+
deep_interview_metadata: true,
|
|
151
|
+
round: meta.round,
|
|
152
|
+
component: meta.component,
|
|
153
|
+
dimension: meta.dimension,
|
|
154
|
+
ambiguity: meta.ambiguity,
|
|
155
|
+
};
|
|
156
|
+
if (meta.round_id !== undefined) state.round_id = meta.round_id;
|
|
157
|
+
return state;
|
|
158
|
+
}
|
|
159
|
+
|
|
133
160
|
/** Build the `workflow_gate` open-input for one deep-interview question. */
|
|
134
161
|
export function questionToGate(question: AskGateQuestion): OpenGateInput {
|
|
135
162
|
const labels = question.options.map(o => o.label);
|
|
@@ -151,7 +178,9 @@ export function questionToGate(question: AskGateQuestion): OpenGateInput {
|
|
|
151
178
|
multi: question.multi ?? false,
|
|
152
179
|
options: labels,
|
|
153
180
|
other_option: GATE_OTHER_OPTION,
|
|
154
|
-
...
|
|
181
|
+
...(question.deepInterview
|
|
182
|
+
? structuredDeepInterviewState(question.deepInterview)
|
|
183
|
+
: deepInterviewQuestionState(question.question)),
|
|
155
184
|
},
|
|
156
185
|
},
|
|
157
186
|
};
|