@nuvin/session 0.1.0-rc.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-7HGJO7ZX.js +9 -0
- package/dist/chunk-HJLRL64D.js +13 -0
- package/dist/{chunk-3IPZO7LP.js → chunk-TUNCGICQ.js} +19 -1
- package/dist/{chunk-FR3R66RD.js → chunk-WAMOWOCO.js} +20 -2
- package/dist/{chunk-3J44LBXZ.js → chunk-WB4FEWBI.js} +1 -1
- package/dist/client/daemon-client.d.ts +50 -0
- package/dist/client/daemon-client.d.ts.map +1 -0
- package/dist/client/data-client.d.ts +21 -3
- package/dist/client/data-client.d.ts.map +1 -1
- package/dist/client/directory.d.ts +7 -12
- package/dist/client/directory.d.ts.map +1 -1
- package/dist/client/http-data-client.d.ts +2 -0
- package/dist/client/http-data-client.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1300 -979
- package/dist/client/session-client.d.ts +19 -6
- package/dist/client/session-client.d.ts.map +1 -1
- package/dist/client/transport.d.ts +18 -2
- package/dist/client/transport.d.ts.map +1 -1
- package/dist/client/websocket.d.ts +5 -0
- package/dist/client/websocket.d.ts.map +1 -1
- package/dist/controller/index.js +129 -40
- package/dist/controller/session-controller.d.ts +18 -5
- package/dist/controller/session-controller.d.ts.map +1 -1
- package/dist/grant/index.d.ts +1 -1
- package/dist/grant/index.d.ts.map +1 -1
- package/dist/grant/index.js +2 -1
- package/dist/protocol/data-rpc.d.ts +70 -3
- package/dist/protocol/data-rpc.d.ts.map +1 -1
- package/dist/protocol/index.d.ts +1 -0
- package/dist/protocol/index.d.ts.map +1 -1
- package/dist/protocol/index.js +12 -3
- package/dist/protocol/model-identity.d.ts +7 -0
- package/dist/protocol/model-identity.d.ts.map +1 -0
- package/dist/protocol/types.d.ts +176 -83
- package/dist/protocol/types.d.ts.map +1 -1
- package/dist/protocol/version.d.ts +1 -1
- package/dist/state/approvals.d.ts +6 -3
- package/dist/state/approvals.d.ts.map +1 -1
- package/dist/state/index.js +5 -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 +50 -1
- package/dist/test-utils/fake-relay.d.ts.map +1 -1
- package/dist/test-utils/index.js +6 -4
- package/package.json +5 -4
- package/dist/chunk-NN43LVAS.js +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { AgentInput, AskUserAnswers } from "@nuvin/agent-core/shared";
|
|
2
|
-
import type { AgentCatalogEntry, AgentDetail, CommandDetail, ConfigPatch, McpServerInfo, ModelCompletion, ServerEvent, SessionViewState, SetConfigResult, SkillCatalogEntry, SkillDetail, SlashCommandDescriptor } from "../protocol/types.ts";
|
|
2
|
+
import type { AgentCatalogEntry, AgentDetail, ChatGptCredentialInput, CommandDetail, ConfigPatch, CustomProviderInput, GrantCapability, McpAction, McpActionResult, McpServerInfo, ModelCompletion, ServerEvent, SessionViewState, SetConfigResult, SkillCatalogEntry, SkillDetail, SlashCommandDescriptor } from "../protocol/types.ts";
|
|
3
3
|
import type { ClientTransport } from "./transport.ts";
|
|
4
4
|
export type ClientSubmitOptions = {
|
|
5
5
|
displayText: string;
|
|
6
6
|
attachmentLabels?: string[];
|
|
7
|
+
turnId?: string;
|
|
7
8
|
};
|
|
8
9
|
/**
|
|
9
10
|
* Client-side mirror of the replicated session state. Applies every incoming
|
|
@@ -29,17 +30,14 @@ export interface SessionClient {
|
|
|
29
30
|
* republishes through a state-reset event; this resolves on the ack.
|
|
30
31
|
*/
|
|
31
32
|
loadHistory(historyId: string): Promise<void>;
|
|
32
|
-
/**
|
|
33
|
-
* Signal the daemon to reload provider keys / config after local onboarding
|
|
34
|
-
* wrote them to the shared config dir (spec §10/§12). Resolves on the ack.
|
|
35
|
-
*/
|
|
36
|
-
reloadConfig(): Promise<void>;
|
|
37
33
|
/**
|
|
38
34
|
* Abort the in-flight MCP OAuth login (spec §10). Sends `cancel-auth-flow`;
|
|
39
35
|
* the daemon invokes its live cancel handle, which publishes a cleared
|
|
40
36
|
* `auth-flow` event. Resolves on the ack.
|
|
41
37
|
*/
|
|
42
38
|
cancelAuthFlow(): Promise<void>;
|
|
39
|
+
/** Execute one authoritative MCP mutation in the attached daemon session. */
|
|
40
|
+
mcpAction(action: McpAction, serverName: string): Promise<McpActionResult>;
|
|
43
41
|
/** Server-executed slash command descriptors from the attach snapshot. */
|
|
44
42
|
serverCommands(): SlashCommandDescriptor[];
|
|
45
43
|
/**
|
|
@@ -73,6 +71,21 @@ export interface SessionClient {
|
|
|
73
71
|
getCommand(name: string): Promise<CommandDetail>;
|
|
74
72
|
/** MCP servers with live status + per-server tools for the MCP tab. */
|
|
75
73
|
listMcpServers(): Promise<McpServerInfo[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Effective grant capabilities from the transport's latest welcome (UI hint).
|
|
76
|
+
* Empty when the transport does not expose capabilities.
|
|
77
|
+
*/
|
|
78
|
+
capabilities(): readonly GrantCapability[];
|
|
79
|
+
/**
|
|
80
|
+
* Complete ChatGPT/Codex device-code login. Provider id is locked to
|
|
81
|
+
* `openai-codex`; callers cannot select another. Resolves on the ack.
|
|
82
|
+
*/
|
|
83
|
+
completeProviderAuth(credential: ChatGptCredentialInput): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Register a custom provider (base URL + API key + surface) on the attached
|
|
86
|
+
* host. Sends `add-custom-provider` and resolves on the ack.
|
|
87
|
+
*/
|
|
88
|
+
addCustomProvider(provider: CustomProviderInput): Promise<void>;
|
|
76
89
|
close(): void;
|
|
77
90
|
}
|
|
78
91
|
export declare function createSessionClient(transport: ClientTransport): SessionClient;
|
|
@@ -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;AAEtF,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,
|
|
1
|
+
{"version":3,"file":"session-client.d.ts","sourceRoot":"","sources":["../../src/client/session-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
import type { ClientCommand, ServerFrame } from "../protocol/types.ts";
|
|
1
|
+
import type { ClientCommand, GrantCapability, ServerFrame } from "../protocol/types.ts";
|
|
2
2
|
/** Client side of a session transport. Implementation: WebSocket over UDS (local) or TCP (remote). */
|
|
3
3
|
export interface ClientTransport {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Send a command frame. Return `false` when the frame was dropped (not attached /
|
|
6
|
+
* not connected) so callers can fail pending promises instead of hanging forever.
|
|
7
|
+
* Returning `true` or `undefined` means the frame was handed to the socket.
|
|
8
|
+
*/
|
|
9
|
+
send(command: ClientCommand): boolean | undefined;
|
|
5
10
|
/** Subscribe to frames. The transport MUST deliver a snapshot frame first (attach semantics). */
|
|
6
11
|
onFrame(listener: (frame: ServerFrame) => void): () => void;
|
|
7
12
|
close(): void;
|
|
13
|
+
/**
|
|
14
|
+
* Effective grant capabilities from the latest welcome (UI hint only). Optional
|
|
15
|
+
* so lightweight fakes and non-daemon transports need not implement it —
|
|
16
|
+
* SessionClient treats a missing reader as an empty capability set.
|
|
17
|
+
*/
|
|
18
|
+
capabilities?(): readonly GrantCapability[];
|
|
19
|
+
/**
|
|
20
|
+
* Optional: notify when in-flight commands can no longer receive acks (socket
|
|
21
|
+
* drop / reconnect). SessionClient rejects pending promises on this signal.
|
|
22
|
+
*/
|
|
23
|
+
onUndeliverable?(listener: () => void): () => void;
|
|
8
24
|
}
|
|
9
25
|
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/client/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/client/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExF,sGAAsG;AACtG,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;IAClD,iGAAiG;IACjG,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5D,KAAK,IAAI,IAAI,CAAC;IACd;;;;OAIG;IACH,YAAY,CAAC,IAAI,SAAS,eAAe,EAAE,CAAC;IAC5C;;;OAGG;IACH,eAAe,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CACpD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { GrantCapability } from "../protocol/types.ts";
|
|
1
2
|
import { type GetEndpoint } from "./endpoint.ts";
|
|
2
3
|
import { type TransportSocket } from "./socket.ts";
|
|
3
4
|
import type { ClientTransport } from "./transport.ts";
|
|
@@ -38,6 +39,10 @@ export type WebSocketTransportOptions = {
|
|
|
38
39
|
export interface WebSocketClientTransport extends ClientTransport {
|
|
39
40
|
connectionState(): WebSocketTransportState;
|
|
40
41
|
onConnectionState(listener: (state: WebSocketTransportState) => void): () => void;
|
|
42
|
+
/** Effective capabilities from the latest welcome; empty while handshake is open or closed. */
|
|
43
|
+
capabilities(): readonly GrantCapability[];
|
|
44
|
+
/** Always present on the WebSocket transport — signals dropped/reconnect undeliverable commands. */
|
|
45
|
+
onUndeliverable(listener: () => void): () => void;
|
|
41
46
|
}
|
|
42
47
|
/**
|
|
43
48
|
* ClientTransport over a WebSocket (spec §4.6): hello/welcome handshake, then
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/client/websocket.ts"],"names":[],"mappings":"
|
|
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,qEAAqE;IACrE,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,CAgR1B"}
|
package/dist/controller/index.js
CHANGED
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
createMessageStateFromMessages,
|
|
7
7
|
createSessionViewState,
|
|
8
8
|
isAutoApprovedTool,
|
|
9
|
+
isToolAutoApprovedForMode,
|
|
9
10
|
reduceSessionEvent
|
|
10
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-WAMOWOCO.js";
|
|
11
12
|
|
|
12
13
|
// src/controller/agent-channel.ts
|
|
13
14
|
import { EventEmitter } from "events";
|
|
@@ -67,15 +68,18 @@ var MAX_AUTO_COMPACTION_CHAIN = 10;
|
|
|
67
68
|
function createSessionController(deps) {
|
|
68
69
|
const now = deps.now ?? Date.now;
|
|
69
70
|
const isAutoApproved = deps.isAutoApproved ?? isAutoApprovedTool;
|
|
70
|
-
const errorDetail = deps.errorDetail ?? ((error) => String(error));
|
|
71
|
+
const errorDetail = deps.errorDetail ?? ((error) => error instanceof Error ? error.message : String(error));
|
|
71
72
|
let serverCommands = deps.serverCommands ?? [];
|
|
72
73
|
let compaction = deps.compaction;
|
|
73
74
|
let guardPrompt = deps.guardPrompt;
|
|
74
75
|
let autoCompactionChain = 0;
|
|
75
76
|
let state = createSessionViewState();
|
|
76
77
|
let seq = 0;
|
|
77
|
-
let
|
|
78
|
+
let approvalMode = deps.approvalMode ?? "ask";
|
|
78
79
|
let abortController = null;
|
|
80
|
+
let activeTurnId;
|
|
81
|
+
let activePolicyDenial;
|
|
82
|
+
let hostBusyCount = 0;
|
|
79
83
|
let questionCounter = 0;
|
|
80
84
|
const listeners = /* @__PURE__ */ new Set();
|
|
81
85
|
const approvalResolvers = /* @__PURE__ */ new Map();
|
|
@@ -85,9 +89,15 @@ function createSessionController(deps) {
|
|
|
85
89
|
let queueCounter = 0;
|
|
86
90
|
const deliveryQueue = [];
|
|
87
91
|
let draining = false;
|
|
88
|
-
const emit = (body) => {
|
|
92
|
+
const emit = (body, explicitTurnId) => {
|
|
89
93
|
seq += 1;
|
|
90
|
-
const
|
|
94
|
+
const turnId = explicitTurnId ?? activeTurnId;
|
|
95
|
+
const event = Object.assign(
|
|
96
|
+
{},
|
|
97
|
+
body,
|
|
98
|
+
{ seq, at: now() },
|
|
99
|
+
turnId !== void 0 ? { turnId } : {}
|
|
100
|
+
);
|
|
91
101
|
state = reduceSessionEvent(state, event);
|
|
92
102
|
deliveryQueue.push(event);
|
|
93
103
|
if (draining) return;
|
|
@@ -106,10 +116,10 @@ function createSessionController(deps) {
|
|
|
106
116
|
draining = false;
|
|
107
117
|
}
|
|
108
118
|
};
|
|
109
|
-
const emitTurnStatus = (
|
|
119
|
+
const emitTurnStatus = () => {
|
|
110
120
|
emit({
|
|
111
121
|
type: "turn-status",
|
|
112
|
-
busy,
|
|
122
|
+
busy: abortController !== null || hostBusyCount > 0,
|
|
113
123
|
queuedCount: queue.length,
|
|
114
124
|
queued: queue.map((q) => ({
|
|
115
125
|
id: q.id,
|
|
@@ -123,6 +133,7 @@ function createSessionController(deps) {
|
|
|
123
133
|
emit({ type: "agent-event", event, ...scope ? { scope } : {} });
|
|
124
134
|
});
|
|
125
135
|
const unsubscribeLoaded = deps.channel.onSessionLoaded((loaded) => {
|
|
136
|
+
queue.length = 0;
|
|
126
137
|
abortController?.abort(new Error("Session loaded; the active turn was cancelled."));
|
|
127
138
|
rejectAllPending("Session loaded; pending interactions were cancelled.");
|
|
128
139
|
emit({
|
|
@@ -133,6 +144,7 @@ function createSessionController(deps) {
|
|
|
133
144
|
// else a resumed session reverts to the empty seed meta (no model name).
|
|
134
145
|
state: {
|
|
135
146
|
...createSessionViewState(),
|
|
147
|
+
busy: hostBusyCount > 0,
|
|
136
148
|
meta: state.meta,
|
|
137
149
|
messages: createMessageStateFromMessages(loaded.messages)
|
|
138
150
|
}
|
|
@@ -142,8 +154,8 @@ function createSessionController(deps) {
|
|
|
142
154
|
const { toolCall, agentId, parentToolCallId, dirAccess } = request;
|
|
143
155
|
const scope = parentToolCallId !== void 0 ? { agentId, parentToolCallId } : void 0;
|
|
144
156
|
const approvalKey = `${agentId}:${toolCall.name}`;
|
|
145
|
-
const auto = !dirAccess && (
|
|
146
|
-
if (dirAccess &&
|
|
157
|
+
const auto = !dirAccess && (alwaysApproved.has(approvalKey) || isToolAutoApprovedForMode(approvalMode, toolCall.name, isAutoApproved));
|
|
158
|
+
if (dirAccess && approvalMode === "sudo") {
|
|
147
159
|
emit({
|
|
148
160
|
type: "agent-event",
|
|
149
161
|
event: { type: "tool_call", toolCall },
|
|
@@ -164,8 +176,13 @@ function createSessionController(deps) {
|
|
|
164
176
|
emit({
|
|
165
177
|
type: "agent-event",
|
|
166
178
|
event: { type: "tool_call", toolCall },
|
|
179
|
+
...deps.headless ? { toolStatus: "rejected" } : {},
|
|
167
180
|
...scope ? { scope } : {}
|
|
168
181
|
});
|
|
182
|
+
if (deps.headless) {
|
|
183
|
+
activePolicyDenial = "Tool approval is unavailable in headless mode.";
|
|
184
|
+
return { action: "reject", reason: activePolicyDenial };
|
|
185
|
+
}
|
|
169
186
|
const nickname = nicknameFor(parentToolCallId);
|
|
170
187
|
const input = asJsonObject(toolCall.input);
|
|
171
188
|
const descriptor = {
|
|
@@ -184,6 +201,10 @@ function createSessionController(deps) {
|
|
|
184
201
|
});
|
|
185
202
|
});
|
|
186
203
|
deps.channel.setQuestionHandler((request) => {
|
|
204
|
+
if (deps.headless) {
|
|
205
|
+
activePolicyDenial = "Questions are unavailable in headless mode.";
|
|
206
|
+
return Promise.reject(new Error(activePolicyDenial));
|
|
207
|
+
}
|
|
187
208
|
questionCounter += 1;
|
|
188
209
|
const questionId = `question-${questionCounter}`;
|
|
189
210
|
return new Promise((resolve, reject) => {
|
|
@@ -221,28 +242,39 @@ function createSessionController(deps) {
|
|
|
221
242
|
}
|
|
222
243
|
questionResolvers.clear();
|
|
223
244
|
}
|
|
224
|
-
function
|
|
225
|
-
if (abortController
|
|
226
|
-
abortController = null;
|
|
227
|
-
rejectAllPending(reason);
|
|
228
|
-
emitTurnStatus(false);
|
|
245
|
+
function startNextQueuedSubmission() {
|
|
246
|
+
if (abortController || hostBusyCount > 0) return;
|
|
229
247
|
const next = queue.shift();
|
|
230
|
-
if (next)
|
|
231
|
-
|
|
232
|
-
|
|
248
|
+
if (!next) return;
|
|
249
|
+
if (!next.opts.silent) {
|
|
250
|
+
emit(
|
|
251
|
+
{
|
|
233
252
|
type: "user-message",
|
|
234
253
|
text: next.opts.displayText,
|
|
235
254
|
...next.opts.attachmentLabels?.length ? { attachmentLabels: next.opts.attachmentLabels } : {}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
255
|
+
},
|
|
256
|
+
next.opts.turnId
|
|
257
|
+
);
|
|
239
258
|
}
|
|
259
|
+
void runTurn(next.input, { turnId: next.opts.turnId });
|
|
260
|
+
}
|
|
261
|
+
function finalizeTurn(controller, reason) {
|
|
262
|
+
if (abortController !== controller) return false;
|
|
263
|
+
abortController = null;
|
|
264
|
+
rejectAllPending(reason);
|
|
265
|
+
emitTurnStatus();
|
|
266
|
+
return true;
|
|
240
267
|
}
|
|
241
268
|
async function runTurn(input, opts) {
|
|
242
269
|
const controller = new AbortController();
|
|
270
|
+
const previousTurnId = activeTurnId;
|
|
271
|
+
if (opts.turnId !== void 0) activeTurnId = opts.turnId;
|
|
272
|
+
if (!opts.systemInitiated) activePolicyDenial = void 0;
|
|
243
273
|
abortController = controller;
|
|
274
|
+
let terminalStatus = "completed";
|
|
275
|
+
let terminalMessage;
|
|
244
276
|
try {
|
|
245
|
-
emitTurnStatus(
|
|
277
|
+
emitTurnStatus();
|
|
246
278
|
if (!opts.systemInitiated) autoCompactionChain = 0;
|
|
247
279
|
compaction?.setEnabled(true);
|
|
248
280
|
let finalInput = input;
|
|
@@ -251,11 +283,15 @@ function createSessionController(deps) {
|
|
|
251
283
|
try {
|
|
252
284
|
guarded = await guardPrompt(input);
|
|
253
285
|
} catch (error) {
|
|
254
|
-
|
|
286
|
+
terminalStatus = "failed";
|
|
287
|
+
terminalMessage = errorDetail(error);
|
|
288
|
+
emit({ type: "error", message: terminalMessage });
|
|
255
289
|
return;
|
|
256
290
|
}
|
|
257
291
|
if ("blocked" in guarded) {
|
|
258
|
-
|
|
292
|
+
terminalStatus = "failed";
|
|
293
|
+
terminalMessage = `Prompt blocked: ${guarded.blocked.reason}`;
|
|
294
|
+
emit({ type: "error", message: terminalMessage });
|
|
259
295
|
return;
|
|
260
296
|
}
|
|
261
297
|
finalInput = guarded.prompt;
|
|
@@ -281,27 +317,61 @@ function createSessionController(deps) {
|
|
|
281
317
|
await compaction.run(compactionIo);
|
|
282
318
|
};
|
|
283
319
|
try {
|
|
284
|
-
await deps.agent.send(finalInput, {
|
|
320
|
+
const result = await deps.agent.send(finalInput, {
|
|
321
|
+
streaming: true,
|
|
322
|
+
signal: controller.signal
|
|
323
|
+
});
|
|
324
|
+
if (typeof result === "object" && result !== null && "status" in result && result.status === "aborted") {
|
|
325
|
+
terminalStatus = "aborted";
|
|
326
|
+
}
|
|
285
327
|
if (compaction && !controller.signal.aborted) {
|
|
286
328
|
if (compaction.consumePendingAction() === "compact") {
|
|
287
329
|
await runCompaction();
|
|
288
330
|
}
|
|
289
331
|
}
|
|
290
332
|
} catch (error) {
|
|
333
|
+
if (controller.signal.aborted || isAbortError(error)) {
|
|
334
|
+
terminalStatus = "aborted";
|
|
335
|
+
}
|
|
291
336
|
try {
|
|
292
337
|
const recovered = compaction ? compaction.messagesFromError(error) : null;
|
|
293
338
|
if (recovered) {
|
|
294
339
|
deps.agent.messages = recovered;
|
|
295
340
|
await runCompaction();
|
|
296
341
|
} else if (!controller.signal.aborted && !isAbortError(error)) {
|
|
297
|
-
|
|
342
|
+
terminalStatus = "failed";
|
|
343
|
+
terminalMessage = errorDetail(error);
|
|
344
|
+
emit({ type: "error", message: terminalMessage });
|
|
298
345
|
}
|
|
299
346
|
} catch (recoveryError) {
|
|
300
|
-
|
|
347
|
+
terminalStatus = "failed";
|
|
348
|
+
terminalMessage = errorDetail(recoveryError);
|
|
349
|
+
emit({ type: "error", message: terminalMessage });
|
|
301
350
|
}
|
|
302
351
|
}
|
|
303
352
|
} finally {
|
|
304
|
-
|
|
353
|
+
const ownedTurn = finalizeTurn(
|
|
354
|
+
controller,
|
|
355
|
+
"Turn ended before pending interactions could be resolved."
|
|
356
|
+
);
|
|
357
|
+
if (activePolicyDenial !== void 0) {
|
|
358
|
+
terminalStatus = "failed";
|
|
359
|
+
terminalMessage = activePolicyDenial;
|
|
360
|
+
}
|
|
361
|
+
if (opts.turnId !== void 0) {
|
|
362
|
+
emit(
|
|
363
|
+
{
|
|
364
|
+
type: "turn-completed",
|
|
365
|
+
status: terminalStatus,
|
|
366
|
+
...activePolicyDenial !== void 0 ? { reason: "policy-denied" } : {},
|
|
367
|
+
...terminalMessage !== void 0 ? { message: terminalMessage } : {}
|
|
368
|
+
},
|
|
369
|
+
opts.turnId
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
if (!opts.systemInitiated) activePolicyDenial = void 0;
|
|
373
|
+
activeTurnId = previousTurnId;
|
|
374
|
+
if (ownedTurn) startNextQueuedSubmission();
|
|
305
375
|
}
|
|
306
376
|
}
|
|
307
377
|
return {
|
|
@@ -340,7 +410,7 @@ function createSessionController(deps) {
|
|
|
340
410
|
const index = queue.findIndex((q) => q.id === queuedId);
|
|
341
411
|
if (index === -1) return false;
|
|
342
412
|
queue.splice(index, 1);
|
|
343
|
-
emitTurnStatus(
|
|
413
|
+
emitTurnStatus();
|
|
344
414
|
return true;
|
|
345
415
|
},
|
|
346
416
|
decideApproval(toolCallId, decision, comment, grantDir) {
|
|
@@ -388,6 +458,9 @@ function createSessionController(deps) {
|
|
|
388
458
|
getSnapshot() {
|
|
389
459
|
return { seq, state, serverCommands };
|
|
390
460
|
},
|
|
461
|
+
isHostBusy() {
|
|
462
|
+
return hostBusyCount > 0;
|
|
463
|
+
},
|
|
391
464
|
onEvent(listener) {
|
|
392
465
|
listeners.add(listener);
|
|
393
466
|
return () => listeners.delete(listener);
|
|
@@ -404,37 +477,53 @@ function createSessionController(deps) {
|
|
|
404
477
|
publishAuthFlow(flow) {
|
|
405
478
|
emit({ type: "auth-flow", flow });
|
|
406
479
|
},
|
|
480
|
+
publishMcpState(mcpState) {
|
|
481
|
+
emit({ type: "mcp-state", state: mcpState });
|
|
482
|
+
},
|
|
407
483
|
publishWorkflowProgress(runId, delta) {
|
|
408
484
|
emit({ type: "workflow-progress", runId, delta });
|
|
409
485
|
},
|
|
410
486
|
reset() {
|
|
411
487
|
queue.length = 0;
|
|
488
|
+
hostBusyCount = 0;
|
|
412
489
|
abortController?.abort(new Error("Session reset."));
|
|
413
490
|
rejectAllPending("Session reset; pending interactions were cancelled.");
|
|
414
491
|
alwaysApproved.clear();
|
|
415
|
-
|
|
492
|
+
approvalMode = "ask";
|
|
416
493
|
emit({
|
|
417
494
|
type: "state-reset",
|
|
418
|
-
state: { ...createSessionViewState(), meta: state.meta }
|
|
495
|
+
state: { ...createSessionViewState(), meta: state.meta, mcp: state.mcp }
|
|
419
496
|
});
|
|
420
497
|
},
|
|
421
|
-
|
|
422
|
-
|
|
498
|
+
setApprovalMode(mode) {
|
|
499
|
+
approvalMode = mode;
|
|
500
|
+
},
|
|
501
|
+
setBusy(busy) {
|
|
502
|
+
if (busy) {
|
|
503
|
+
hostBusyCount += 1;
|
|
504
|
+
} else if (hostBusyCount > 0) {
|
|
505
|
+
hostBusyCount -= 1;
|
|
506
|
+
}
|
|
507
|
+
emitTurnStatus();
|
|
508
|
+
startNextQueuedSubmission();
|
|
423
509
|
},
|
|
424
510
|
async submit(input, opts) {
|
|
425
|
-
if (abortController) {
|
|
511
|
+
if (abortController || hostBusyCount > 0) {
|
|
426
512
|
queue.push({ id: `q-${++queueCounter}`, input, opts });
|
|
427
|
-
emitTurnStatus(
|
|
513
|
+
emitTurnStatus();
|
|
428
514
|
return;
|
|
429
515
|
}
|
|
430
516
|
if (!opts.silent) {
|
|
431
|
-
emit(
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
517
|
+
emit(
|
|
518
|
+
{
|
|
519
|
+
type: "user-message",
|
|
520
|
+
text: opts.displayText,
|
|
521
|
+
...opts.attachmentLabels?.length ? { attachmentLabels: opts.attachmentLabels } : {}
|
|
522
|
+
},
|
|
523
|
+
opts.turnId
|
|
524
|
+
);
|
|
436
525
|
}
|
|
437
|
-
await runTurn(input, {});
|
|
526
|
+
await runTurn(input, { turnId: opts.turnId });
|
|
438
527
|
}
|
|
439
528
|
};
|
|
440
529
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentMetricsSnapshot } from "@nuvin/agent-core/agent";
|
|
2
2
|
import { type AgentInput, type AskUserAnswers, type Message } from "@nuvin/agent-core/shared";
|
|
3
|
-
import type { McpAuthFlowState, ServerEvent, SessionMeta, SessionSnapshot, SlashCommandDescriptor, WorkflowProgressDelta } from "../protocol/types.ts";
|
|
3
|
+
import type { McpAuthFlowState, McpViewState, ServerEvent, SessionMeta, SessionSnapshot, SlashCommandDescriptor, WorkflowProgressDelta } from "../protocol/types.ts";
|
|
4
|
+
import { type SessionApprovalMode } from "../state/approvals.ts";
|
|
4
5
|
import type { AgentChannel } from "./agent-channel.ts";
|
|
5
6
|
/** Subset of Agent the controller needs — structurally satisfied by @nuvin/agent-core Agent. */
|
|
6
7
|
export type AgentLike = {
|
|
@@ -53,6 +54,10 @@ export interface SessionControllerDeps {
|
|
|
53
54
|
* attach snapshot for autocomplete. Defaults to an empty list.
|
|
54
55
|
*/
|
|
55
56
|
serverCommands?: SlashCommandDescriptor[];
|
|
57
|
+
/** Non-interactive sessions never wait for an approval or question response. */
|
|
58
|
+
headless?: boolean;
|
|
59
|
+
/** Existing approval mode to apply when the controller is created. */
|
|
60
|
+
approvalMode?: SessionApprovalMode;
|
|
56
61
|
}
|
|
57
62
|
export type SubmitOptions = {
|
|
58
63
|
displayText: string;
|
|
@@ -62,6 +67,8 @@ export type SubmitOptions = {
|
|
|
62
67
|
* already echoed their text). `displayText` may be `""` in that case.
|
|
63
68
|
*/
|
|
64
69
|
silent?: boolean;
|
|
70
|
+
/** Caller identifier copied onto all events produced by this turn. */
|
|
71
|
+
turnId?: string;
|
|
65
72
|
};
|
|
66
73
|
export interface SessionController {
|
|
67
74
|
abort(): void;
|
|
@@ -106,6 +113,8 @@ export interface SessionController {
|
|
|
106
113
|
* mutated in place. Callers must treat the returned state as read-only.
|
|
107
114
|
*/
|
|
108
115
|
getSnapshot(): SessionSnapshot;
|
|
116
|
+
/** Return whether a host-controlled server operation currently owns busy state. */
|
|
117
|
+
isHostBusy(): boolean;
|
|
109
118
|
onEvent(listener: (event: ServerEvent) => void): () => void;
|
|
110
119
|
/**
|
|
111
120
|
* Replace the server-executed slash-command descriptors surfaced in the attach
|
|
@@ -128,6 +137,8 @@ export interface SessionController {
|
|
|
128
137
|
* reduces it like any other event. `null` clears the client modal.
|
|
129
138
|
*/
|
|
130
139
|
publishAuthFlow(flow: McpAuthFlowState): void;
|
|
140
|
+
/** Publish the authoritative MCP catalog and operation state. */
|
|
141
|
+
publishMcpState(state: McpViewState): void;
|
|
131
142
|
/**
|
|
132
143
|
* Publish a workflow UI progress delta (spec §8.2/§13). The WorkflowManager
|
|
133
144
|
* is the sole caller. emit-only — sequences + reduces into
|
|
@@ -136,13 +147,15 @@ export interface SessionController {
|
|
|
136
147
|
publishWorkflowProgress(runId: string, delta: WorkflowProgressDelta): void;
|
|
137
148
|
/**
|
|
138
149
|
* Reset session state: abort any active turn, clear queued submissions,
|
|
139
|
-
* reject pending approvals/questions, clear alwaysApproved +
|
|
150
|
+
* reject pending approvals/questions, clear alwaysApproved + approvalMode, and emit
|
|
140
151
|
* a state-reset with a fresh view state CARRYING OVER the last published
|
|
141
|
-
* meta. Runtime-side resets
|
|
142
|
-
* prompt, metrics) are the HOST's
|
|
152
|
+
* meta and authoritative MCP state. Runtime-side resets
|
|
153
|
+
* (sessionStore.startNewSession, agent system prompt, metrics) are the HOST's
|
|
154
|
+
* job — it calls those, then this.
|
|
143
155
|
*/
|
|
144
156
|
reset(): void;
|
|
145
|
-
|
|
157
|
+
setApprovalMode(mode: SessionApprovalMode): void;
|
|
158
|
+
setBusy(busy: boolean): void;
|
|
146
159
|
/**
|
|
147
160
|
* Submit user input. If no turn is active, the returned promise resolves
|
|
148
161
|
* when the turn completes. If a turn is already active, the submission is
|
|
@@ -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,cAAc,EAEnB,KAAK,OAAO,
|
|
1
|
+
{"version":3,"file":"session-controller.d.ts","sourceRoot":"","sources":["../../src/controller/session-controller.ts"],"names":[],"mappings":"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"}
|
package/dist/grant/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type GrantPayload } from "../protocol/types.ts";
|
|
2
2
|
/** ±5 min clock-skew tolerance on expiry/issuedAt checks (relay spec §7). */
|
|
3
3
|
export declare const DEFAULT_GRANT_SKEW_MS: number;
|
|
4
4
|
/** base64 DER key pair: `publicKey` SPKI (daemon.yaml), `privateKey` PKCS#8 (server secret). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/grant/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/grant/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE7E,6EAA6E;AAC7E,eAAO,MAAM,qBAAqB,QAAgB,CAAC;AAEnD,gGAAgG;AAChG,MAAM,MAAM,YAAY,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAC1B,iBAAiB,GACjB,SAAS,GACT,WAAW,GACX,eAAe,GACf,WAAW,CAAC;AAEhB,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACnC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAE9C,wBAAgB,oBAAoB,IAAI,YAAY,CAMnD;AAED,mFAAmF;AACnF,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CASjF;AA+BD;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3E,iBAAiB,CAuCnB"}
|
package/dist/grant/index.js
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
import type { HistoryPage, SessionSnapshot,
|
|
1
|
+
import type { ConfigMutationResult, HistoryPage, ProfileSummary, ProviderConfigSummary, ProviderCredentialInput, ProviderSurfaceId, SessionSnapshot, WorkspaceConfigSummary } from "./types.ts";
|
|
2
|
+
export type DataRpcErrorCode = "invalid-input" | "not-found" | "conflict" | "unsupported" | "unauthorized" | "daemon-offline" | "internal";
|
|
3
|
+
export type DataRpcError = {
|
|
4
|
+
code: DataRpcErrorCode;
|
|
5
|
+
message: string;
|
|
6
|
+
};
|
|
7
|
+
export type ProfileScope = {
|
|
8
|
+
profile?: string;
|
|
9
|
+
};
|
|
10
|
+
export type AddProviderInput = ProfileScope & {
|
|
11
|
+
name: string;
|
|
12
|
+
surface: ProviderSurfaceId;
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
defaultModel?: string;
|
|
15
|
+
credential: ProviderCredentialInput;
|
|
16
|
+
activate?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type UpdateWorkspaceInput = ProfileScope & {
|
|
19
|
+
activeProvider?: string;
|
|
20
|
+
toggles?: Record<string, boolean>;
|
|
21
|
+
};
|
|
2
22
|
/**
|
|
3
23
|
* The read/management data plane: ONE schema, two transports into the daemon
|
|
4
24
|
* (local REST via rest-http.ts, relay control RPC via daemons.controller.ts →
|
|
@@ -39,7 +59,7 @@ export type DataRpcSchema = {
|
|
|
39
59
|
params: {
|
|
40
60
|
profile?: string;
|
|
41
61
|
};
|
|
42
|
-
result:
|
|
62
|
+
result: WorkspaceConfigSummary[];
|
|
43
63
|
};
|
|
44
64
|
"create-workspace": {
|
|
45
65
|
params: {
|
|
@@ -47,7 +67,54 @@ export type DataRpcSchema = {
|
|
|
47
67
|
root?: string;
|
|
48
68
|
profile?: string;
|
|
49
69
|
};
|
|
50
|
-
result:
|
|
70
|
+
result: WorkspaceConfigSummary;
|
|
71
|
+
};
|
|
72
|
+
"list-profiles": {
|
|
73
|
+
params: Record<string, never>;
|
|
74
|
+
result: ProfileSummary[];
|
|
75
|
+
};
|
|
76
|
+
"list-providers": {
|
|
77
|
+
params: ProfileScope;
|
|
78
|
+
result: ProviderConfigSummary[];
|
|
79
|
+
};
|
|
80
|
+
"add-provider": {
|
|
81
|
+
params: AddProviderInput;
|
|
82
|
+
result: ConfigMutationResult<ProviderConfigSummary>;
|
|
83
|
+
};
|
|
84
|
+
"remove-provider": {
|
|
85
|
+
params: {
|
|
86
|
+
providerId: string;
|
|
87
|
+
profile?: string;
|
|
88
|
+
};
|
|
89
|
+
result: ConfigMutationResult<null>;
|
|
90
|
+
};
|
|
91
|
+
"set-default-provider": {
|
|
92
|
+
params: {
|
|
93
|
+
providerId: string;
|
|
94
|
+
profile?: string;
|
|
95
|
+
};
|
|
96
|
+
result: ConfigMutationResult<null>;
|
|
97
|
+
};
|
|
98
|
+
"set-provider-auth": {
|
|
99
|
+
params: {
|
|
100
|
+
providerId: string;
|
|
101
|
+
credential: ProviderCredentialInput;
|
|
102
|
+
profile?: string;
|
|
103
|
+
};
|
|
104
|
+
result: ConfigMutationResult<null>;
|
|
105
|
+
};
|
|
106
|
+
"clear-provider-auth": {
|
|
107
|
+
params: {
|
|
108
|
+
providerId: string;
|
|
109
|
+
profile?: string;
|
|
110
|
+
};
|
|
111
|
+
result: ConfigMutationResult<null>;
|
|
112
|
+
};
|
|
113
|
+
"update-workspace": {
|
|
114
|
+
params: UpdateWorkspaceInput & {
|
|
115
|
+
name: string;
|
|
116
|
+
};
|
|
117
|
+
result: ConfigMutationResult<WorkspaceConfigSummary>;
|
|
51
118
|
};
|
|
52
119
|
};
|
|
53
120
|
export type DataRpcMethod = keyof DataRpcSchema;
|