@nuvin/session 0.4.0-rc.0 → 0.4.0-rc.10
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/dist/{chunk-DTLHDYZC.js → chunk-U6V6IQJR.js} +184 -45
- package/dist/{chunk-L3QH7Y6S.js → chunk-Y7JPSYTH.js} +8 -1
- package/dist/client/daemon-client.d.ts.map +1 -1
- package/dist/client/data-client.d.ts +7 -1
- package/dist/client/data-client.d.ts.map +1 -1
- package/dist/client/http-data-client.d.ts.map +1 -1
- package/dist/client/index.js +138 -5
- package/dist/client/session-client.d.ts +18 -1
- package/dist/client/session-client.d.ts.map +1 -1
- package/dist/client/websocket.d.ts +1 -1
- package/dist/client/websocket.d.ts.map +1 -1
- package/dist/controller/index.js +80 -22
- package/dist/controller/session-controller.d.ts +12 -4
- package/dist/controller/session-controller.d.ts.map +1 -1
- package/dist/protocol/background-work.d.ts +3 -1
- package/dist/protocol/background-work.d.ts.map +1 -1
- package/dist/protocol/data-rpc.d.ts +8 -1
- package/dist/protocol/data-rpc.d.ts.map +1 -1
- package/dist/protocol/index.js +3 -1
- package/dist/protocol/types.d.ts +183 -12
- package/dist/protocol/types.d.ts.map +1 -1
- package/dist/protocol/version.d.ts +1 -1
- package/dist/state/approvals.d.ts.map +1 -1
- package/dist/state/index.js +7 -3
- package/dist/state/messages.d.ts +29 -2
- package/dist/state/messages.d.ts.map +1 -1
- package/dist/state/session.d.ts.map +1 -1
- package/dist/state/tool-preview.d.ts.map +1 -1
- package/dist/state/tool-preview.js +1 -45
- package/dist/test-utils/index.js +1 -1
- package/package.json +2 -2
package/dist/client/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSessionViewState,
|
|
3
3
|
reduceSessionEvent
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-U6V6IQJR.js";
|
|
5
5
|
import {
|
|
6
6
|
PROTOCOL_VERSION,
|
|
7
|
+
parseBackgroundWorkCancellation,
|
|
7
8
|
parseBackgroundWorkInspection,
|
|
8
9
|
parseBackgroundWorkPage
|
|
9
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-Y7JPSYTH.js";
|
|
10
11
|
|
|
11
12
|
// src/client/endpoint.ts
|
|
12
13
|
var TerminalEndpointError = class extends Error {
|
|
@@ -185,6 +186,27 @@ function createHttpDataClient(options = {}) {
|
|
|
185
186
|
const body = await response.json();
|
|
186
187
|
return { url: body.wsUrl, credential: { grant: body.grant } };
|
|
187
188
|
},
|
|
189
|
+
async removeDaemon(daemonId) {
|
|
190
|
+
const token = options.getToken ? await options.getToken() : null;
|
|
191
|
+
const response = await fetchImpl(`${baseUrl}/api/daemons/${encodeURIComponent(daemonId)}`, {
|
|
192
|
+
method: "DELETE",
|
|
193
|
+
cache: "no-store",
|
|
194
|
+
headers: token !== null ? { Authorization: `Bearer ${token}` } : {}
|
|
195
|
+
});
|
|
196
|
+
if (response.status === 401) {
|
|
197
|
+
options.onUnauthorized?.();
|
|
198
|
+
throw new TerminalEndpointError("unauthorized", "Signed out \u2014 authentication required.");
|
|
199
|
+
}
|
|
200
|
+
if (response.status === 404) {
|
|
201
|
+
rows.delete(daemonId);
|
|
202
|
+
throw new TerminalEndpointError(
|
|
203
|
+
"daemon-revoked",
|
|
204
|
+
`Daemon "${daemonId}" is no longer registered.`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (!response.ok) await throwFromResponse(response, `Failed to remove daemon "${daemonId}"`);
|
|
208
|
+
rows.delete(daemonId);
|
|
209
|
+
},
|
|
188
210
|
async fetchTranscript(daemonId, identity) {
|
|
189
211
|
const suffix = `/transcript/${encodeURIComponent(identity.sessionId)}${queryString({
|
|
190
212
|
workspace: identity.workspace,
|
|
@@ -206,7 +228,8 @@ function createHttpDataClient(options = {}) {
|
|
|
206
228
|
cwd: opts?.cwd,
|
|
207
229
|
limit: opts?.limit,
|
|
208
230
|
cursor: opts?.cursor,
|
|
209
|
-
includeExtraction: opts?.includeExtraction === true ? "true" : void 0
|
|
231
|
+
includeExtraction: opts?.includeExtraction === true ? "true" : void 0,
|
|
232
|
+
includeActive: opts?.includeActive === true ? "true" : void 0
|
|
210
233
|
})}`;
|
|
211
234
|
const response = await daemonFetch(daemonId, suffix);
|
|
212
235
|
if (!response.ok)
|
|
@@ -220,7 +243,8 @@ function createHttpDataClient(options = {}) {
|
|
|
220
243
|
profile: opts?.profile,
|
|
221
244
|
currentCwd: opts?.currentCwd,
|
|
222
245
|
query: opts?.query,
|
|
223
|
-
includeExtraction: opts?.includeExtraction === true ? "true" : void 0
|
|
246
|
+
includeExtraction: opts?.includeExtraction === true ? "true" : void 0,
|
|
247
|
+
includeActive: opts?.includeActive === true ? "true" : void 0
|
|
224
248
|
})}`;
|
|
225
249
|
const response = await daemonFetch(daemonId, suffix, { signal: opts?.signal });
|
|
226
250
|
if (!response.ok)
|
|
@@ -237,7 +261,8 @@ function createHttpDataClient(options = {}) {
|
|
|
237
261
|
query: opts?.query,
|
|
238
262
|
limit: opts?.limit,
|
|
239
263
|
cursor: opts?.cursor,
|
|
240
|
-
includeExtraction: opts?.includeExtraction === true ? "true" : void 0
|
|
264
|
+
includeExtraction: opts?.includeExtraction === true ? "true" : void 0,
|
|
265
|
+
includeActive: opts?.includeActive === true ? "true" : void 0
|
|
241
266
|
})}`;
|
|
242
267
|
const response = await daemonFetch(daemonId, suffix, { signal: opts?.signal });
|
|
243
268
|
if (!response.ok)
|
|
@@ -368,6 +393,19 @@ function createHttpDataClient(options = {}) {
|
|
|
368
393
|
if (!response.ok) await throwFromResponse(response, "Failed to update workspace");
|
|
369
394
|
return await response.json();
|
|
370
395
|
},
|
|
396
|
+
async getModelReasoningCapability(daemonId, input) {
|
|
397
|
+
const suffix = `/model-reasoning-capability${queryString({
|
|
398
|
+
profile: input.profile,
|
|
399
|
+
selector: input.selector
|
|
400
|
+
})}`;
|
|
401
|
+
const response = await daemonFetch(daemonId, suffix);
|
|
402
|
+
if (!response.ok) {
|
|
403
|
+
await throwFromResponse(response, "Failed to load model reasoning capability", {
|
|
404
|
+
404: { reason: "daemon-revoked", message: "This daemon is no longer registered." }
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
return await response.json();
|
|
408
|
+
},
|
|
371
409
|
async listAgentModelSets(daemonId, input) {
|
|
372
410
|
const suffix = `/agent-model-sets${queryString({
|
|
373
411
|
profile: input.profile,
|
|
@@ -545,6 +583,66 @@ function toBackgroundWorkInspection(result) {
|
|
|
545
583
|
throw new SessionCommandError("invalid-result", "Invalid managed work inspection.");
|
|
546
584
|
}
|
|
547
585
|
}
|
|
586
|
+
function toBackgroundWorkCancellation(result) {
|
|
587
|
+
try {
|
|
588
|
+
return parseBackgroundWorkCancellation(result);
|
|
589
|
+
} catch {
|
|
590
|
+
throw new SessionCommandError("invalid-result", "Invalid managed work cancellation.");
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function isRecord(value) {
|
|
594
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
595
|
+
}
|
|
596
|
+
function isStringArray(value) {
|
|
597
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
598
|
+
}
|
|
599
|
+
function isAgentCatalogEntry(value) {
|
|
600
|
+
if (!isRecord(value)) return false;
|
|
601
|
+
return typeof value.id === "string" && typeof value.name === "string" && typeof value.description === "string" && (value.model === void 0 || typeof value.model === "string") && typeof value.source === "string" && typeof value.enabled === "boolean" && isStringArray(value.tools) && isStringArray(value.skills) && typeof value.editableInPlace === "boolean" && typeof value.toggleable === "boolean";
|
|
602
|
+
}
|
|
603
|
+
function isAgentDetail(value) {
|
|
604
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.systemPrompt === "string" && isStringArray(value.tools) && isStringArray(value.skills) && (value.model === void 0 || typeof value.model === "string");
|
|
605
|
+
}
|
|
606
|
+
function isAgentEditorDefinition(value) {
|
|
607
|
+
return isRecord(value) && typeof value.filename === "string" && typeof value.name === "string" && typeof value.description === "string" && (value.model === void 0 || typeof value.model === "string") && typeof value.enabled === "boolean" && typeof value.systemPrompt === "string" && isStringArray(value.tools) && isStringArray(value.skills);
|
|
608
|
+
}
|
|
609
|
+
function isAgentToolCapability(value) {
|
|
610
|
+
if (!isRecord(value) || typeof value.name !== "string" || typeof value.available !== "boolean" || value.source !== "builtin" && value.source !== "mcp" && value.source !== "unavailable" || typeof value.sourceLabel !== "string" || value.status !== "available" && value.status !== "globally-disabled" && value.status !== "disconnected" && value.status !== "unavailable" || value.description !== void 0 && typeof value.description !== "string")
|
|
611
|
+
return false;
|
|
612
|
+
if (value.mcp === void 0) return true;
|
|
613
|
+
return isRecord(value.mcp) && typeof value.mcp.serverId === "string" && typeof value.mcp.toolName === "string" && (value.mcp.serverStatus === "connected" || value.mcp.serverStatus === "disabled" || value.mcp.serverStatus === "authRequired" || value.mcp.serverStatus === "error");
|
|
614
|
+
}
|
|
615
|
+
function isAgentSkillCapability(value) {
|
|
616
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.name === "string" && typeof value.description === "string" && typeof value.source === "string" && typeof value.sourceLabel === "string" && typeof value.available === "boolean" && (value.status === "available" || value.status === "globally-disabled" || value.status === "disconnected" || value.status === "unavailable");
|
|
617
|
+
}
|
|
618
|
+
function isAgentEditorData(value) {
|
|
619
|
+
if (!isRecord(value) || value.mode !== "create" && value.mode !== "edit" || value.sourceKey !== void 0 && typeof value.sourceKey !== "string" || !isAgentEditorDefinition(value.definition) || typeof value.source !== "string" || typeof value.destinationRootLabel !== "string" || typeof value.editableInPlace !== "boolean" || typeof value.cloneOnSave !== "boolean" || typeof value.idLocked !== "boolean" || typeof value.enabledLocked !== "boolean" || typeof value.canonicalRewrite !== "boolean" || value.revision !== void 0 && typeof value.revision !== "string" || !Array.isArray(value.tools) || !value.tools.every(isAgentToolCapability) || !Array.isArray(value.skills) || !value.skills.every(isAgentSkillCapability))
|
|
620
|
+
return false;
|
|
621
|
+
return value.revealOnDelete === void 0 || isRecord(value.revealOnDelete) && typeof value.revealOnDelete.id === "string" && typeof value.revealOnDelete.source === "string";
|
|
622
|
+
}
|
|
623
|
+
function toAgentEditorData(result) {
|
|
624
|
+
if (!isAgentEditorData(result))
|
|
625
|
+
throw new SessionCommandError("invalid-result", "Invalid agent editor response.");
|
|
626
|
+
return result;
|
|
627
|
+
}
|
|
628
|
+
function isAgentMutationResult(result) {
|
|
629
|
+
return isRecord(result) && isAgentCatalogEntry(result.catalogEntry) && isAgentDetail(result.detail) && isAgentEditorData(result.editorData) && typeof result.activePersonaId === "string" && (result.liveApply === "applied" || result.liveApply === "stagedForNextTurn");
|
|
630
|
+
}
|
|
631
|
+
function toAgentMutationResult(result) {
|
|
632
|
+
if (!isAgentMutationResult(result)) {
|
|
633
|
+
throw new SessionCommandError("invalid-result", "Invalid agent mutation response.");
|
|
634
|
+
}
|
|
635
|
+
return result;
|
|
636
|
+
}
|
|
637
|
+
function isDeleteAgentResult(result) {
|
|
638
|
+
return isRecord(result) && typeof result.selectedAgentId === "string" && typeof result.activePersonaId === "string" && (result.liveApply === "applied" || result.liveApply === "stagedForNextTurn") && (result.revealed === void 0 || isRecord(result.revealed) && isAgentCatalogEntry(result.revealed.catalogEntry) && isAgentDetail(result.revealed.detail) && isAgentEditorData(result.revealed.editorData));
|
|
639
|
+
}
|
|
640
|
+
function toDeleteAgentResult(result) {
|
|
641
|
+
if (!isDeleteAgentResult(result)) {
|
|
642
|
+
throw new SessionCommandError("invalid-result", "Invalid agent deletion response.");
|
|
643
|
+
}
|
|
644
|
+
return result;
|
|
645
|
+
}
|
|
548
646
|
function createSessionClient(transport) {
|
|
549
647
|
let state = createSessionViewState();
|
|
550
648
|
let seq = 0;
|
|
@@ -730,6 +828,13 @@ function createSessionClient(transport) {
|
|
|
730
828
|
...input.limit === void 0 ? {} : { limit: input.limit }
|
|
731
829
|
})).then(toBackgroundWorkInspection);
|
|
732
830
|
},
|
|
831
|
+
cancelBackgroundWork(input) {
|
|
832
|
+
return sendCommand((id) => ({
|
|
833
|
+
id,
|
|
834
|
+
type: "cancel-background-work",
|
|
835
|
+
workId: input.workId
|
|
836
|
+
})).then(toBackgroundWorkCancellation);
|
|
837
|
+
},
|
|
733
838
|
serverCommands() {
|
|
734
839
|
return serverCommandList;
|
|
735
840
|
},
|
|
@@ -778,6 +883,28 @@ function createSessionClient(transport) {
|
|
|
778
883
|
(result) => result
|
|
779
884
|
);
|
|
780
885
|
},
|
|
886
|
+
getAgentEditorData(agentId) {
|
|
887
|
+
return sendCommand((id) => ({
|
|
888
|
+
id,
|
|
889
|
+
type: "get-agent-editor-data",
|
|
890
|
+
...agentId === void 0 ? {} : { agentId }
|
|
891
|
+
})).then(toAgentEditorData);
|
|
892
|
+
},
|
|
893
|
+
createAgent(definition) {
|
|
894
|
+
return sendCommand((id) => ({ id, type: "create-agent", definition })).then(
|
|
895
|
+
toAgentMutationResult
|
|
896
|
+
);
|
|
897
|
+
},
|
|
898
|
+
updateAgent(input) {
|
|
899
|
+
return sendCommand((id) => ({ id, type: "update-agent", ...input })).then(
|
|
900
|
+
toAgentMutationResult
|
|
901
|
+
);
|
|
902
|
+
},
|
|
903
|
+
deleteAgent(input) {
|
|
904
|
+
return sendCommand((id) => ({ id, type: "delete-agent", ...input })).then(
|
|
905
|
+
toDeleteAgentResult
|
|
906
|
+
);
|
|
907
|
+
},
|
|
781
908
|
getCommand(name) {
|
|
782
909
|
return sendCommand((id) => ({ id, type: "get-command", name })).then(
|
|
783
910
|
(result) => result
|
|
@@ -1050,6 +1177,11 @@ function createWebSocketTransport(options) {
|
|
|
1050
1177
|
return;
|
|
1051
1178
|
}
|
|
1052
1179
|
if (phase === "awaiting-attach") {
|
|
1180
|
+
if (message.type === "ack" && message.id === `attach-${attachCounter}` && message.ok === false) {
|
|
1181
|
+
terminate();
|
|
1182
|
+
options.onDetached?.(`Attach failed: ${message.error?.message ?? "Session unavailable."}`);
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1053
1185
|
if (message.type === "replay") {
|
|
1054
1186
|
for (const event of message.events) {
|
|
1055
1187
|
lastSeq = event.seq;
|
|
@@ -1200,6 +1332,7 @@ function bindDaemonDataClient(client, daemonId) {
|
|
|
1200
1332
|
setProviderAuth: (providerId, credential, opts) => client.setProviderAuth(daemonId, providerId, credential, opts),
|
|
1201
1333
|
clearProviderAuth: (providerId, opts) => client.clearProviderAuth(daemonId, providerId, opts),
|
|
1202
1334
|
updateWorkspace: (name, patch) => client.updateWorkspace(daemonId, name, patch),
|
|
1335
|
+
getModelReasoningCapability: (input) => client.getModelReasoningCapability(daemonId, input),
|
|
1203
1336
|
listAgentModelSets: (input) => client.listAgentModelSets(daemonId, input),
|
|
1204
1337
|
createAgentModelSet: (input) => client.createAgentModelSet(daemonId, input),
|
|
1205
1338
|
replaceAgentModelSet: (input) => client.replaceAgentModelSet(daemonId, input),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentInput, AskUserAnswers } from "@nuvin/agent-core/shared";
|
|
2
|
-
import type { AgentCatalogEntry, AgentDetail, AgentModelSetSelectionResult, BackgroundWorkInspection, BackgroundWorkPage, CommandDetail, ConfigPatch, ConsolidateProposalDetail, ConsolidateProposalSummary, ConsolidateRunOutcome, CustomProviderInput, GrantCapability, McpAction, McpActionResult, McpServerInfo, MemoryExtractSummary, PersistBashPermissionRequest, PersistBashPermissionResult, ServerEvent, SessionViewState, SetConfigResult, SkillCatalogEntry, SkillDetail, SlashCommandCompletion, SlashCommandDescriptor, WorkspaceMemoryDetail, WorkspaceMemorySummary } from "../protocol/types.ts";
|
|
2
|
+
import type { AgentCatalogEntry, AgentDetail, AgentEditorData, AgentEditorDefinition, AgentModelSetSelectionResult, AgentMutationResult, BackgroundWorkCancellationResult, BackgroundWorkInspection, BackgroundWorkPage, CommandDetail, ConfigPatch, ConsolidateProposalDetail, ConsolidateProposalSummary, ConsolidateRunOutcome, CustomProviderInput, DeleteAgentResult, GrantCapability, McpAction, McpActionResult, McpServerInfo, MemoryExtractSummary, PersistBashPermissionRequest, PersistBashPermissionResult, ServerEvent, SessionViewState, SetConfigResult, SkillCatalogEntry, SkillDetail, SlashCommandCompletion, SlashCommandDescriptor, WorkspaceMemoryDetail, WorkspaceMemorySummary } from "../protocol/types.ts";
|
|
3
3
|
import type { ClientTransport } from "./transport.ts";
|
|
4
4
|
export type ClientSubmitOptions = {
|
|
5
5
|
displayText: string;
|
|
@@ -50,6 +50,10 @@ export interface SessionClient {
|
|
|
50
50
|
offset?: number;
|
|
51
51
|
limit?: number;
|
|
52
52
|
}): Promise<BackgroundWorkInspection>;
|
|
53
|
+
/** Cancel one managed-work item owned by the attached session. */
|
|
54
|
+
cancelBackgroundWork(input: {
|
|
55
|
+
workId: string;
|
|
56
|
+
}): Promise<BackgroundWorkCancellationResult>;
|
|
53
57
|
/** Server-executed slash command descriptors from the attach snapshot. */
|
|
54
58
|
serverCommands(): SlashCommandDescriptor[];
|
|
55
59
|
/**
|
|
@@ -83,6 +87,19 @@ export interface SessionClient {
|
|
|
83
87
|
listAgents(): Promise<AgentCatalogEntry[]>;
|
|
84
88
|
/** Lazy-load one agent's system prompt + tools for the Agents-tab detail pane. */
|
|
85
89
|
getAgent(agentId: string): Promise<AgentDetail>;
|
|
90
|
+
getAgentEditorData(agentId?: string): Promise<AgentEditorData>;
|
|
91
|
+
createAgent(definition: AgentEditorDefinition): Promise<AgentMutationResult>;
|
|
92
|
+
updateAgent(input: {
|
|
93
|
+
sourceKey: string;
|
|
94
|
+
agentId: string;
|
|
95
|
+
expectedRevision: string;
|
|
96
|
+
definition: AgentEditorDefinition;
|
|
97
|
+
}): Promise<AgentMutationResult>;
|
|
98
|
+
deleteAgent(input: {
|
|
99
|
+
sourceKey: string;
|
|
100
|
+
agentId: string;
|
|
101
|
+
expectedRevision: string;
|
|
102
|
+
}): Promise<DeleteAgentResult>;
|
|
86
103
|
/** Lazy-load one custom command's markdown body for the Commands-tab detail pane. */
|
|
87
104
|
getCommand(name: string): Promise<CommandDetail>;
|
|
88
105
|
/** MCP servers with live status + per-server tools for the MCP tab. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-client.d.ts","sourceRoot":"","sources":["../../src/client/session-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAa,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"session-client.d.ts","sourceRoot":"","sources":["../../src/client/session-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,7 +33,7 @@ export type WebSocketTransportOptions = {
|
|
|
33
33
|
backoffFactor?: number;
|
|
34
34
|
/** Handshake refused (bad token / protocol mismatch). Terminal — retrying cannot fix it. */
|
|
35
35
|
onRejected?: (reason: "auth" | "version") => void;
|
|
36
|
-
/** The daemon detached this client (e.g. kill-session). Terminal. */
|
|
36
|
+
/** The daemon refused attachment or detached this client (e.g. kill-session). Terminal. */
|
|
37
37
|
onDetached?: (reason: string) => void;
|
|
38
38
|
};
|
|
39
39
|
export interface WebSocketClientTransport extends ClientTransport {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/client/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,KAAK,WAAW,EAAiD,MAAM,eAAe,CAAC;AAChG,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,GAAG,WAAW,CAAC;AAE5F,MAAM,MAAM,yBAAyB,GAAG;IACtC,iHAAiH;IACjH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0GAA0G;IAC1G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,mGAAmG;IACnG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,eAAe,CAAC;IACjD,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4FAA4F;IAC5F,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAClD,
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/client/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,KAAK,WAAW,EAAiD,MAAM,eAAe,CAAC;AAChG,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,GAAG,WAAW,CAAC;AAE5F,MAAM,MAAM,yBAAyB,GAAG;IACtC,iHAAiH;IACjH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0GAA0G;IAC1G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,mGAAmG;IACnG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,eAAe,CAAC;IACjD,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4FAA4F;IAC5F,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAClD,2FAA2F;IAC3F,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC/D,eAAe,IAAI,uBAAuB,CAAC;IAC3C,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClF,+FAA+F;IAC/F,YAAY,IAAI,SAAS,eAAe,EAAE,CAAC;IAC3C,oGAAoG;IACpG,eAAe,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CACnD;AAyBD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,yBAAyB,GACjC,wBAAwB,CA0R1B"}
|
package/dist/controller/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
sanitizeCoordinatorDeliveryText,
|
|
12
12
|
scopedToolKey,
|
|
13
13
|
summarizeToolCallInput
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-U6V6IQJR.js";
|
|
15
15
|
|
|
16
16
|
// src/controller/agent-channel.ts
|
|
17
17
|
import { EventEmitter } from "events";
|
|
@@ -81,7 +81,8 @@ var AgentChannel = class {
|
|
|
81
81
|
|
|
82
82
|
// src/controller/session-controller.ts
|
|
83
83
|
import {
|
|
84
|
-
isAbortError
|
|
84
|
+
isAbortError,
|
|
85
|
+
isAgentOnlyCoordinatorNotice
|
|
85
86
|
} from "@nuvin/agent-core/shared";
|
|
86
87
|
function formatBashPolicyDenial(diagnostics) {
|
|
87
88
|
const denied = diagnostics.operations.filter((operation) => operation.decision === "deny");
|
|
@@ -94,8 +95,18 @@ function formatBashPolicyDenial(diagnostics) {
|
|
|
94
95
|
});
|
|
95
96
|
return `Bash command rejected by policy: ${details.join("; ")}.`;
|
|
96
97
|
}
|
|
98
|
+
function coordinatorInfoMeta(submission) {
|
|
99
|
+
if (submission.origin !== "coordinator") return {};
|
|
100
|
+
if (isAgentOnlyCoordinatorNotice(submission)) {
|
|
101
|
+
return {
|
|
102
|
+
deliveryKind: submission.deliveryKind,
|
|
103
|
+
transcriptVisibility: "agent-only"
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return submission.subagentReport === void 0 ? {} : { subagentReport: structuredClone(submission.subagentReport) };
|
|
107
|
+
}
|
|
97
108
|
function preservesVerbatimCoordinatorInput(submission) {
|
|
98
|
-
return submission?.origin === "coordinator" && submission.deliveryKind === "subagent-report";
|
|
109
|
+
return submission?.origin === "coordinator" && (submission.deliveryKind === "subagent-report" || isAgentOnlyCoordinatorNotice(submission));
|
|
99
110
|
}
|
|
100
111
|
var MAX_AUTO_COMPACTION_CHAIN = 10;
|
|
101
112
|
function createSessionController(deps) {
|
|
@@ -155,11 +166,12 @@ function createSessionController(deps) {
|
|
|
155
166
|
}
|
|
156
167
|
};
|
|
157
168
|
const emitTurnStatus = () => {
|
|
169
|
+
const visible = queue.filter((q) => !isAgentOnlyCoordinatorNotice(q.opts.submission));
|
|
158
170
|
emit({
|
|
159
171
|
type: "turn-status",
|
|
160
172
|
busy: abortController !== null || hostBusyCount > 0,
|
|
161
|
-
queuedCount:
|
|
162
|
-
queued:
|
|
173
|
+
queuedCount: visible.length,
|
|
174
|
+
queued: visible.map((q) => ({
|
|
163
175
|
id: q.id,
|
|
164
176
|
displayText: q.opts.displayText,
|
|
165
177
|
...q.opts.attachmentLabels?.length ? { attachmentLabels: q.opts.attachmentLabels } : {}
|
|
@@ -408,9 +420,18 @@ function createSessionController(deps) {
|
|
|
408
420
|
return { ok: false, message: errorDetail(error) };
|
|
409
421
|
}
|
|
410
422
|
}
|
|
423
|
+
function allowsSteering(opts) {
|
|
424
|
+
return opts.turnId === void 0 || deps.headless !== true && opts.submission?.origin === "coordinator" && opts.submission.deliveryKind === "subagent-report";
|
|
425
|
+
}
|
|
411
426
|
function startNextQueuedSubmission() {
|
|
412
427
|
if (closing || abortController || hostBusyCount > 0) return;
|
|
413
|
-
|
|
428
|
+
let next = queue.shift();
|
|
429
|
+
let dropped = false;
|
|
430
|
+
while (next?.opts.signal?.aborted) {
|
|
431
|
+
dropped = true;
|
|
432
|
+
next = queue.shift();
|
|
433
|
+
}
|
|
434
|
+
if (dropped) emitTurnStatus();
|
|
414
435
|
if (!next) return;
|
|
415
436
|
const coordinatorOwned = next.opts.submission?.origin === "coordinator";
|
|
416
437
|
if (!coordinatorOwned && !next.opts.silent) {
|
|
@@ -423,13 +444,14 @@ function createSessionController(deps) {
|
|
|
423
444
|
next.opts.turnId
|
|
424
445
|
);
|
|
425
446
|
}
|
|
426
|
-
|
|
447
|
+
const turn = startTrackedTurn(next.input, {
|
|
427
448
|
turnId: next.opts.turnId,
|
|
428
|
-
allowSteering: next.opts
|
|
449
|
+
allowSteering: allowsSteering(next.opts),
|
|
429
450
|
submission: next.opts.submission ?? { origin: "user" },
|
|
430
451
|
...coordinatorOwned ? { coordinatorDisplayText: next.opts.displayText } : {},
|
|
431
452
|
...next.opts.signal === void 0 ? {} : { signal: next.opts.signal }
|
|
432
453
|
});
|
|
454
|
+
if (next.opts.waitFor === "acceptance") observeAcceptedTurn(turn, next.opts.turnId);
|
|
433
455
|
}
|
|
434
456
|
function finalizeTurn(controller, reason) {
|
|
435
457
|
if (abortController !== controller) return false;
|
|
@@ -454,34 +476,46 @@ function createSessionController(deps) {
|
|
|
454
476
|
emitTurnStatus();
|
|
455
477
|
const accepted = [];
|
|
456
478
|
for (const entry of drained) {
|
|
479
|
+
if (entry.opts.signal?.aborted) continue;
|
|
457
480
|
const guarded = await guardQueuedSteering(entry.input);
|
|
481
|
+
if (entry.opts.signal?.aborted) continue;
|
|
458
482
|
if (guarded.ok) {
|
|
459
483
|
accepted.push({
|
|
460
484
|
input: preservesVerbatimCoordinatorInput(entry.opts.submission) ? entry.input : guarded.prompt,
|
|
461
|
-
opts: entry.opts
|
|
485
|
+
opts: entry.opts,
|
|
486
|
+
queuedAt: entry.queuedAt
|
|
462
487
|
});
|
|
463
488
|
} else {
|
|
464
489
|
emit({ type: "error", message: guarded.message });
|
|
465
490
|
}
|
|
466
491
|
}
|
|
467
492
|
if (abortController !== controller || controller.signal.aborted) return [];
|
|
468
|
-
|
|
493
|
+
const current = accepted.filter((entry) => !entry.opts.signal?.aborted);
|
|
494
|
+
for (const entry of current) {
|
|
469
495
|
if (entry.opts.submission?.origin === "coordinator") {
|
|
470
496
|
emit({
|
|
471
497
|
type: "info",
|
|
472
498
|
message: sanitizeCoordinatorDeliveryText(entry.opts.displayText),
|
|
473
|
-
...
|
|
499
|
+
...coordinatorInfoMeta(entry.opts.submission)
|
|
474
500
|
});
|
|
475
501
|
} else if (!entry.opts.silent) {
|
|
476
502
|
emit({
|
|
477
503
|
type: "user-message",
|
|
478
504
|
text: entry.opts.displayText,
|
|
479
|
-
...entry.opts.attachmentLabels?.length ? { attachmentLabels: entry.opts.attachmentLabels } : {}
|
|
505
|
+
...entry.opts.attachmentLabels?.length ? { attachmentLabels: entry.opts.attachmentLabels } : {},
|
|
506
|
+
// The drain stamps event.at at delivery; steeredAt preserves when
|
|
507
|
+
// the client actually queued the input — the HUD's "time since
|
|
508
|
+
// last input" and the persisted steer marker both key off it.
|
|
509
|
+
steeredAt: entry.queuedAt
|
|
480
510
|
});
|
|
481
511
|
}
|
|
482
512
|
}
|
|
483
|
-
return
|
|
484
|
-
(entry) =>
|
|
513
|
+
return current.map(
|
|
514
|
+
(entry) => ({
|
|
515
|
+
input: entry.input,
|
|
516
|
+
submission: entry.opts.submission ?? { origin: "user" },
|
|
517
|
+
steeredAt: entry.queuedAt
|
|
518
|
+
})
|
|
485
519
|
);
|
|
486
520
|
};
|
|
487
521
|
const previousTurnId = activeTurnId;
|
|
@@ -498,7 +532,15 @@ function createSessionController(deps) {
|
|
|
498
532
|
if (!opts.systemInitiated && guardPrompt) {
|
|
499
533
|
let guarded;
|
|
500
534
|
try {
|
|
535
|
+
if (opts.signal?.aborted) {
|
|
536
|
+
terminalStatus = "aborted";
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
501
539
|
guarded = await guardPrompt(input);
|
|
540
|
+
if (opts.signal?.aborted) {
|
|
541
|
+
terminalStatus = "aborted";
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
502
544
|
} catch (error) {
|
|
503
545
|
terminalStatus = "failed";
|
|
504
546
|
terminalMessage = errorDetail(error);
|
|
@@ -513,11 +555,15 @@ function createSessionController(deps) {
|
|
|
513
555
|
}
|
|
514
556
|
finalInput = preservesVerbatimCoordinatorInput(opts.submission) ? input : guarded.prompt;
|
|
515
557
|
}
|
|
558
|
+
if (opts.signal?.aborted) {
|
|
559
|
+
terminalStatus = "aborted";
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
516
562
|
if (opts.coordinatorDisplayText !== void 0) {
|
|
517
563
|
emit({
|
|
518
564
|
type: "info",
|
|
519
565
|
message: sanitizeCoordinatorDeliveryText(opts.coordinatorDisplayText),
|
|
520
|
-
...
|
|
566
|
+
...coordinatorInfoMeta(opts.submission)
|
|
521
567
|
});
|
|
522
568
|
}
|
|
523
569
|
const compactionSend = (text) => runTurn(text, {
|
|
@@ -616,6 +662,11 @@ function createSessionController(deps) {
|
|
|
616
662
|
activeTurnPromise = tracked;
|
|
617
663
|
return tracked;
|
|
618
664
|
}
|
|
665
|
+
function observeAcceptedTurn(turn, turnId) {
|
|
666
|
+
void turn.catch((error) => {
|
|
667
|
+
emit({ type: "error", message: errorDetail(error) }, turnId);
|
|
668
|
+
});
|
|
669
|
+
}
|
|
619
670
|
function detachController() {
|
|
620
671
|
if (detached) return;
|
|
621
672
|
detached = true;
|
|
@@ -627,15 +678,15 @@ function createSessionController(deps) {
|
|
|
627
678
|
abortListeners.clear();
|
|
628
679
|
}
|
|
629
680
|
return {
|
|
630
|
-
abort() {
|
|
631
|
-
queue.length = 0;
|
|
681
|
+
abort(intent = "cancel") {
|
|
632
682
|
const reason = new Error("User aborted the current turn.");
|
|
633
683
|
for (const listener of abortListeners) {
|
|
634
684
|
try {
|
|
635
|
-
listener(reason);
|
|
685
|
+
listener(reason, intent);
|
|
636
686
|
} catch {
|
|
637
687
|
}
|
|
638
688
|
}
|
|
689
|
+
queue.length = 0;
|
|
639
690
|
abortController?.abort(reason);
|
|
640
691
|
rejectAllPending("User aborted the current turn.");
|
|
641
692
|
},
|
|
@@ -825,7 +876,11 @@ function createSessionController(deps) {
|
|
|
825
876
|
emit({
|
|
826
877
|
type: "user-message",
|
|
827
878
|
text,
|
|
828
|
-
...attachmentLabels?.length ? { attachmentLabels } : {}
|
|
879
|
+
...attachmentLabels?.length ? { attachmentLabels } : {},
|
|
880
|
+
// An echo emitted while a turn is in flight is a display-only
|
|
881
|
+
// interjection, never a turn opener — mark it like a drained steer so
|
|
882
|
+
// the WorkingStatusLine anchor and the persisted row both skip it.
|
|
883
|
+
...abortController !== null || hostBusyCount > 0 ? { steeredAt: now() } : {}
|
|
829
884
|
});
|
|
830
885
|
},
|
|
831
886
|
getSnapshot() {
|
|
@@ -912,7 +967,8 @@ function createSessionController(deps) {
|
|
|
912
967
|
id: `q-${++queueCounter}`,
|
|
913
968
|
input,
|
|
914
969
|
opts,
|
|
915
|
-
delivery: abortController !== null && opts
|
|
970
|
+
delivery: abortController !== null && allowsSteering(opts) ? "steering" : "next-turn",
|
|
971
|
+
queuedAt: now()
|
|
916
972
|
});
|
|
917
973
|
emitTurnStatus();
|
|
918
974
|
return;
|
|
@@ -928,13 +984,15 @@ function createSessionController(deps) {
|
|
|
928
984
|
opts.turnId
|
|
929
985
|
);
|
|
930
986
|
}
|
|
931
|
-
|
|
987
|
+
const turn = startTrackedTurn(input, {
|
|
932
988
|
turnId: opts.turnId,
|
|
933
|
-
allowSteering: opts
|
|
989
|
+
allowSteering: allowsSteering(opts),
|
|
934
990
|
submission: opts.submission ?? { origin: "user" },
|
|
935
991
|
...coordinatorOwned ? { coordinatorDisplayText: opts.displayText } : {},
|
|
936
992
|
...opts.signal === void 0 ? {} : { signal: opts.signal }
|
|
937
993
|
});
|
|
994
|
+
if (opts.waitFor === "acceptance") observeAcceptedTurn(turn, opts.turnId);
|
|
995
|
+
else await turn;
|
|
938
996
|
}
|
|
939
997
|
};
|
|
940
998
|
}
|
|
@@ -63,6 +63,12 @@ export interface SessionControllerDeps {
|
|
|
63
63
|
}
|
|
64
64
|
export type SubmitOptions = {
|
|
65
65
|
displayText: string;
|
|
66
|
+
/**
|
|
67
|
+
* Resolve after admission, even when idle. Execution remains controller-owned;
|
|
68
|
+
* failures are reported through events, and close still waits for the turn.
|
|
69
|
+
* Omit to retain the normal idle-turn completion / busy-queue acceptance behavior.
|
|
70
|
+
*/
|
|
71
|
+
waitFor?: "acceptance";
|
|
66
72
|
attachmentLabels?: string[];
|
|
67
73
|
/** Immutable ownership metadata forwarded with this exact agent send. */
|
|
68
74
|
submission?: AgentSubmission;
|
|
@@ -76,10 +82,11 @@ export type SubmitOptions = {
|
|
|
76
82
|
/** Caller identifier copied onto all events produced by this turn. */
|
|
77
83
|
turnId?: string;
|
|
78
84
|
};
|
|
85
|
+
export type SessionStopIntent = "cancel" | "suspend";
|
|
79
86
|
export interface SessionController {
|
|
80
|
-
abort(): void;
|
|
81
|
-
/** Observe
|
|
82
|
-
onAbort(listener: (reason: unknown) => void): () => void;
|
|
87
|
+
abort(intent?: SessionStopIntent): void;
|
|
88
|
+
/** Observe lifecycle intent before signals, queues or approval resolvers stop. */
|
|
89
|
+
onAbort(listener: (reason: unknown, intent: SessionStopIntent) => void): () => void;
|
|
83
90
|
/**
|
|
84
91
|
* Attach runtime-scoped hooks the daemon's session host owns. The host is
|
|
85
92
|
* built after the controller (it needs the controller), so compaction +
|
|
@@ -171,7 +178,8 @@ export interface SessionController {
|
|
|
171
178
|
* Submit user input. If no turn is active, the returned promise resolves
|
|
172
179
|
* when the turn completes. If a turn is already active, the submission is
|
|
173
180
|
* queued and the promise resolves at ENQUEUE time — remote transports should
|
|
174
|
-
* ack on acceptance and observe completion via `turn-status` events.
|
|
181
|
+
* ack on acceptance and observe completion via `turn-status` events. Callers
|
|
182
|
+
* needing acceptance in both cases can opt into `waitFor: "acceptance"`.
|
|
175
183
|
*/
|
|
176
184
|
submit(input: AgentInput, opts: SubmitOptions): Promise<void>;
|
|
177
185
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-controller.d.ts","sourceRoot":"","sources":["../../src/controller/session-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EACL,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"session-controller.d.ts","sourceRoot":"","sources":["../../src/controller/session-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BackgroundWorkInspection, BackgroundWorkPage } from "./types.ts";
|
|
1
|
+
import type { BackgroundWorkCancellationResult, BackgroundWorkInspection, BackgroundWorkPage } from "./types.ts";
|
|
2
2
|
/** Wire-facing managed-work bounds shared by every protocol producer and consumer. */
|
|
3
3
|
export declare const BACKGROUND_WORK_PROTOCOL_LIMITS: Readonly<{
|
|
4
4
|
idChars: 128;
|
|
@@ -23,4 +23,6 @@ export declare class BackgroundWorkResultValidationError extends Error {
|
|
|
23
23
|
export declare function parseBackgroundWorkPage(value: unknown): BackgroundWorkPage;
|
|
24
24
|
/** Validate and clone an untrusted managed-work inspection. */
|
|
25
25
|
export declare function parseBackgroundWorkInspection(value: unknown): BackgroundWorkInspection;
|
|
26
|
+
/** Validate and clone an untrusted managed-work cancellation ack. */
|
|
27
|
+
export declare function parseBackgroundWorkCancellation(value: unknown): BackgroundWorkCancellationResult;
|
|
26
28
|
//# sourceMappingURL=background-work.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"background-work.d.ts","sourceRoot":"","sources":["../../src/protocol/background-work.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,wBAAwB,EACxB,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AAEpB,sFAAsF;AACtF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;EAa1C,CAAC;AAEH,2FAA2F;AAC3F,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAQjF;AAID,qBAAa,mCAAoC,SAAQ,KAAK;;CAK7D;AAoND,yDAAyD;AACzD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAmB1E;AAED,+DAA+D;AAC/D,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAoCtF"}
|
|
1
|
+
{"version":3,"file":"background-work.d.ts","sourceRoot":"","sources":["../../src/protocol/background-work.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,gCAAgC,EAChC,wBAAwB,EACxB,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AAEpB,sFAAsF;AACtF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;EAa1C,CAAC;AAEH,2FAA2F;AAC3F,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAQjF;AAID,qBAAa,mCAAoC,SAAQ,KAAK;;CAK7D;AAoND,yDAAyD;AACzD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAmB1E;AAED,+DAA+D;AAC/D,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAoCtF;AAED,qEAAqE;AACrE,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,gCAAgC,CAShG"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentModelSetsView, AgentModelTierMappings, ConfigMutationResult, HistoryPage, ListHistoryParams, ListHistoryWorkspacesParams, ListHistoryWorkspacesResult, ListWorkspaceHistoryParams, PersistenceIdentity, ProfileSummary, ProviderConfigSummary, ProviderCredentialInput, ProviderSurfaceId, SessionSnapshot, WorkspaceConfigSummary, WorkspaceHistoryPage } from "./types.ts";
|
|
1
|
+
import type { AgentModelSetsView, AgentModelTierMappings, ConfigMutationResult, HistoryPage, ListHistoryParams, ListHistoryWorkspacesParams, ListHistoryWorkspacesResult, ListWorkspaceHistoryParams, ModelReasoningCapabilityView, PersistenceIdentity, ProfileSummary, ProviderConfigSummary, ProviderCredentialInput, ProviderSurfaceId, SessionSnapshot, WorkspaceConfigSummary, WorkspaceHistoryPage } from "./types.ts";
|
|
2
2
|
export type DataRpcErrorCode = "invalid-input" | "not-found" | "conflict" | "unsupported" | "unauthorized" | "daemon-offline" | "transcript-unavailable" | "transcript-corrupt" | "history-state-conflict" | "ambiguous-session-identity" | "invalid-history-cursor" | "internal";
|
|
3
3
|
export type DataRpcError = {
|
|
4
4
|
code: DataRpcErrorCode;
|
|
@@ -123,6 +123,13 @@ export type DataRpcSchema = {
|
|
|
123
123
|
};
|
|
124
124
|
result: ConfigMutationResult<WorkspaceConfigSummary>;
|
|
125
125
|
};
|
|
126
|
+
"get-model-reasoning-capability": {
|
|
127
|
+
params: {
|
|
128
|
+
profile: string;
|
|
129
|
+
selector: string;
|
|
130
|
+
};
|
|
131
|
+
result: ModelReasoningCapabilityView;
|
|
132
|
+
};
|
|
126
133
|
"list-agent-model-sets": {
|
|
127
134
|
params: {
|
|
128
135
|
profile: string;
|