@nuvin/session 0.1.1-rc.2 → 0.2.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.
Files changed (51) hide show
  1. package/dist/{chunk-WB4FEWBI.js → chunk-3CVYVANJ.js} +1 -1
  2. package/dist/chunk-7LEIACBZ.js +85 -0
  3. package/dist/{chunk-COVRYM64.js → chunk-KQHHBUVY.js} +137 -47
  4. package/dist/client/daemon-client.d.ts.map +1 -1
  5. package/dist/client/data-client.d.ts +10 -15
  6. package/dist/client/data-client.d.ts.map +1 -1
  7. package/dist/client/directory.d.ts +12 -14
  8. package/dist/client/directory.d.ts.map +1 -1
  9. package/dist/client/http-data-client.d.ts +5 -0
  10. package/dist/client/http-data-client.d.ts.map +1 -1
  11. package/dist/client/index.js +299 -40
  12. package/dist/client/session-client.d.ts +30 -4
  13. package/dist/client/session-client.d.ts.map +1 -1
  14. package/dist/client/websocket.d.ts.map +1 -1
  15. package/dist/controller/agent-channel.d.ts +10 -5
  16. package/dist/controller/agent-channel.d.ts.map +1 -1
  17. package/dist/controller/index.js +323 -48
  18. package/dist/controller/session-controller.d.ts +15 -14
  19. package/dist/controller/session-controller.d.ts.map +1 -1
  20. package/dist/controller/test-utils.d.ts +3 -1
  21. package/dist/controller/test-utils.d.ts.map +1 -1
  22. package/dist/protocol/data-rpc.d.ts +13 -14
  23. package/dist/protocol/data-rpc.d.ts.map +1 -1
  24. package/dist/protocol/history-text.d.ts +4 -0
  25. package/dist/protocol/history-text.d.ts.map +1 -0
  26. package/dist/protocol/index.d.ts +1 -0
  27. package/dist/protocol/index.d.ts.map +1 -1
  28. package/dist/protocol/index.js +12 -4
  29. package/dist/protocol/model-identity.d.ts +7 -0
  30. package/dist/protocol/model-identity.d.ts.map +1 -1
  31. package/dist/protocol/types.d.ts +339 -35
  32. package/dist/protocol/types.d.ts.map +1 -1
  33. package/dist/protocol/version.d.ts +1 -1
  34. package/dist/state/approvals.d.ts +4 -15
  35. package/dist/state/approvals.d.ts.map +1 -1
  36. package/dist/state/index.d.ts +2 -0
  37. package/dist/state/index.d.ts.map +1 -1
  38. package/dist/state/index.js +15 -9
  39. package/dist/state/messages.d.ts +12 -2
  40. package/dist/state/messages.d.ts.map +1 -1
  41. package/dist/state/questions.d.ts +5 -0
  42. package/dist/state/questions.d.ts.map +1 -0
  43. package/dist/state/session.d.ts.map +1 -1
  44. package/dist/state/tool-key.d.ts +2 -0
  45. package/dist/state/tool-key.d.ts.map +1 -0
  46. package/dist/state/tool-preview.d.ts +5 -0
  47. package/dist/state/tool-preview.d.ts.map +1 -1
  48. package/dist/state/tool-preview.js +81 -29
  49. package/dist/test-utils/index.js +2 -2
  50. package/package.json +3 -3
  51. package/dist/chunk-7HGJO7ZX.js +0 -9
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createSessionViewState,
3
3
  reduceSessionEvent
4
- } from "../chunk-COVRYM64.js";
4
+ } from "../chunk-KQHHBUVY.js";
5
5
  import {
6
6
  PROTOCOL_VERSION
7
- } from "../chunk-WB4FEWBI.js";
7
+ } from "../chunk-3CVYVANJ.js";
8
8
 
9
9
  // src/client/endpoint.ts
10
10
  var TerminalEndpointError = class extends Error {
@@ -17,6 +17,13 @@ var TerminalEndpointError = class extends Error {
17
17
  };
18
18
 
19
19
  // src/client/http-data-client.ts
20
+ var DataRpcClientError = class extends Error {
21
+ constructor(code, message) {
22
+ super(message);
23
+ this.code = code;
24
+ this.name = "DataRpcClientError";
25
+ }
26
+ };
20
27
  function httpBaseFromWsUrl(wsUrl) {
21
28
  const u = new URL(wsUrl);
22
29
  const scheme = u.protocol === "wss:" ? "https:" : "http:";
@@ -46,6 +53,9 @@ async function throwFromResponse(response, fallback, terminal, onUnauthorized) {
46
53
  typeof body?.message === "string" ? body.message : mapped.message
47
54
  );
48
55
  }
56
+ if (body?.code === "invalid-history-cursor") {
57
+ throw new DataRpcClientError(body.code, body.message ?? fallback);
58
+ }
49
59
  throw new Error(
50
60
  typeof body?.message === "string" ? body.message : `${fallback} (HTTP ${response.status}).`
51
61
  );
@@ -54,6 +64,21 @@ function createHttpDataClient(options = {}) {
54
64
  const fetchImpl = options.fetchImpl ?? ((...args) => fetch(...args));
55
65
  const baseUrl = (options.baseUrl ?? "").replace(/\/+$/, "");
56
66
  const rows = /* @__PURE__ */ new Map();
67
+ let directoryResolve = null;
68
+ const directoryReady = new Promise((resolve) => {
69
+ directoryResolve = resolve;
70
+ });
71
+ const resolveDirectory = () => {
72
+ if (directoryResolve) {
73
+ directoryResolve();
74
+ directoryResolve = null;
75
+ }
76
+ };
77
+ const ensureDirectoryReady = async (id) => {
78
+ if (rows.has(id)) return;
79
+ if (baseUrl !== "") return;
80
+ await directoryReady;
81
+ };
57
82
  const resolveToken = async (id) => {
58
83
  const endpoint = rows.get(id)?.endpoint;
59
84
  if (endpoint) return endpoint.token;
@@ -64,6 +89,7 @@ function createHttpDataClient(options = {}) {
64
89
  return endpoint ? httpBaseFromWsUrl(endpoint.wsUrl) : baseUrl;
65
90
  };
66
91
  const daemonFetch = async (id, suffix, init = {}) => {
92
+ await ensureDirectoryReady(id);
67
93
  const token = await resolveToken(id);
68
94
  const response = await fetchImpl(
69
95
  `${resolveBase(id)}/api/daemons/${encodeURIComponent(id)}${suffix}`,
@@ -88,23 +114,27 @@ function createHttpDataClient(options = {}) {
88
114
  };
89
115
  return {
90
116
  async listDaemons() {
91
- const token = options.getToken ? await options.getToken() : null;
92
- const response = await fetchImpl(`${baseUrl}/api/daemons`, {
93
- cache: "no-store",
94
- headers: token !== null ? { Authorization: `Bearer ${token}` } : {}
95
- });
96
- if (response.status === 401) {
97
- options.onUnauthorized?.();
98
- throw new TerminalEndpointError("unauthorized", "Signed out \u2014 authentication required.");
117
+ try {
118
+ const token = options.getToken ? await options.getToken() : null;
119
+ const response = await fetchImpl(`${baseUrl}/api/daemons`, {
120
+ cache: "no-store",
121
+ headers: token !== null ? { Authorization: `Bearer ${token}` } : {}
122
+ });
123
+ if (response.status === 401) {
124
+ options.onUnauthorized?.();
125
+ throw new TerminalEndpointError("unauthorized", "Signed out \u2014 authentication required.");
126
+ }
127
+ if (!response.ok) await throwFromResponse(response, "Failed to fetch the daemon list");
128
+ const body = await response.json();
129
+ rows.clear();
130
+ for (const row of body.daemons) rows.set(row.id, row);
131
+ return {
132
+ daemons: body.daemons,
133
+ ...body.defaultSessionId !== void 0 ? { defaultSessionId: body.defaultSessionId } : {}
134
+ };
135
+ } finally {
136
+ resolveDirectory();
99
137
  }
100
- if (!response.ok) await throwFromResponse(response, "Failed to fetch the daemon list");
101
- const body = await response.json();
102
- rows.clear();
103
- for (const row of body.daemons) rows.set(row.id, row);
104
- return {
105
- daemons: body.daemons,
106
- ...body.defaultSessionId !== void 0 ? { defaultSessionId: body.defaultSessionId } : {}
107
- };
108
138
  },
109
139
  async acquireEndpoint(daemonId) {
110
140
  const endpoint = rows.get(daemonId)?.endpoint;
@@ -153,10 +183,10 @@ function createHttpDataClient(options = {}) {
153
183
  const body = await response.json();
154
184
  return { url: body.wsUrl, credential: { grant: body.grant } };
155
185
  },
156
- async fetchTranscript(daemonId, historyId, opts) {
157
- const suffix = `/transcript/${encodeURIComponent(historyId)}${queryString({
158
- workspace: opts?.workspace,
159
- profile: opts?.profile
186
+ async fetchTranscript(daemonId, identity) {
187
+ const suffix = `/transcript/${encodeURIComponent(identity.sessionId)}${queryString({
188
+ workspace: identity.workspace,
189
+ profile: identity.profile
160
190
  })}`;
161
191
  const response = await daemonFetch(daemonId, suffix);
162
192
  if (response.status === 404) {
@@ -173,7 +203,8 @@ function createHttpDataClient(options = {}) {
173
203
  profile: opts?.profile,
174
204
  cwd: opts?.cwd,
175
205
  limit: opts?.limit,
176
- cursor: opts?.cursor
206
+ cursor: opts?.cursor,
207
+ includeExtraction: opts?.includeExtraction === true ? "true" : void 0
177
208
  })}`;
178
209
  const response = await daemonFetch(daemonId, suffix);
179
210
  if (!response.ok)
@@ -182,6 +213,37 @@ function createHttpDataClient(options = {}) {
182
213
  });
183
214
  return await response.json();
184
215
  },
216
+ async listHistoryWorkspaces(daemonId, opts) {
217
+ const suffix = `/history/workspaces${queryString({
218
+ profile: opts?.profile,
219
+ currentCwd: opts?.currentCwd,
220
+ query: opts?.query,
221
+ includeExtraction: opts?.includeExtraction === true ? "true" : void 0
222
+ })}`;
223
+ const response = await daemonFetch(daemonId, suffix, { signal: opts?.signal });
224
+ if (!response.ok)
225
+ await throwFromResponse(response, "Failed to load history workspaces", {
226
+ 404: { reason: "daemon-revoked", message: "This daemon is no longer registered." }
227
+ });
228
+ return await response.json();
229
+ },
230
+ async listWorkspaceHistory(daemonId, opts) {
231
+ const suffix = `/history/workspace${queryString({
232
+ profile: opts?.profile,
233
+ workspace: opts?.workspace,
234
+ cwd: opts?.cwd,
235
+ query: opts?.query,
236
+ limit: opts?.limit,
237
+ cursor: opts?.cursor,
238
+ includeExtraction: opts?.includeExtraction === true ? "true" : void 0
239
+ })}`;
240
+ const response = await daemonFetch(daemonId, suffix, { signal: opts?.signal });
241
+ if (!response.ok)
242
+ await throwFromResponse(response, "Failed to load workspace history", {
243
+ 404: { reason: "daemon-revoked", message: "This daemon is no longer registered." }
244
+ });
245
+ return await response.json();
246
+ },
185
247
  async listWorkspaces(daemonId, opts) {
186
248
  const suffix = `/workspaces${queryString({ profile: opts?.profile })}`;
187
249
  const response = await daemonFetch(daemonId, suffix);
@@ -204,10 +266,10 @@ function createHttpDataClient(options = {}) {
204
266
  if (!response.ok) await throwFromResponse(response, "Failed to create the workspace");
205
267
  return await response.json();
206
268
  },
207
- async deleteSession(daemonId, historyId, opts) {
208
- const suffix = `/sessions/${encodeURIComponent(historyId)}${queryString({
209
- workspace: opts?.workspace,
210
- profile: opts?.profile
269
+ async deleteSession(daemonId, identity) {
270
+ const suffix = `/sessions/${encodeURIComponent(identity.sessionId)}${queryString({
271
+ workspace: identity.workspace,
272
+ profile: identity.profile
211
273
  })}`;
212
274
  const response = await daemonFetch(daemonId, suffix, { method: "DELETE" });
213
275
  if (response.status === 404) {
@@ -306,11 +368,23 @@ function createHttpDataClient(options = {}) {
306
368
  }
307
369
 
308
370
  // src/client/session-client.ts
371
+ var SessionCommandError = class extends Error {
372
+ constructor(code, message) {
373
+ super(message);
374
+ this.code = code;
375
+ this.name = "SessionCommandError";
376
+ }
377
+ };
309
378
  var EMPTY_MODEL_COMPLETION = {
310
379
  providers: [],
311
380
  perProvider: {},
312
381
  recentModels: []
313
382
  };
383
+ var EMPTY_THINKING_COMPLETION = {
384
+ modelIdentity: "",
385
+ canDisable: false,
386
+ options: []
387
+ };
314
388
  function toModelCompletion(result) {
315
389
  if (typeof result !== "object" || result === null || Array.isArray(result)) {
316
390
  return EMPTY_MODEL_COMPLETION;
@@ -340,6 +414,100 @@ function toModelCompletion(result) {
340
414
  }) : [];
341
415
  return { providers, perProvider, recentModels };
342
416
  }
417
+ function optionalString(record, key) {
418
+ const value = record[key];
419
+ return typeof value === "string" ? value : void 0;
420
+ }
421
+ function toThinkingCompletion(result) {
422
+ if (typeof result !== "object" || result === null || Array.isArray(result)) {
423
+ return EMPTY_THINKING_COMPLETION;
424
+ }
425
+ const record = result;
426
+ if (typeof record.modelIdentity !== "string" || typeof record.canDisable !== "boolean" || !Array.isArray(record.options)) {
427
+ return EMPTY_THINKING_COMPLETION;
428
+ }
429
+ const options = record.options.flatMap((entry) => {
430
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return [];
431
+ const option = entry;
432
+ if (typeof option.id !== "string" || option.id.length === 0) return [];
433
+ return [
434
+ typeof option.description === "string" ? { id: option.id, description: option.description } : { id: option.id }
435
+ ];
436
+ });
437
+ const effectiveOption = optionalString(record, "effectiveOption");
438
+ const defaultOption = optionalString(record, "defaultOption");
439
+ const selectedOption = optionalString(record, "selectedOption");
440
+ return {
441
+ modelIdentity: record.modelIdentity,
442
+ ...effectiveOption !== void 0 ? { effectiveOption } : {},
443
+ ...defaultOption !== void 0 ? { defaultOption } : {},
444
+ ...selectedOption !== void 0 ? { selectedOption } : {},
445
+ canDisable: record.canDisable,
446
+ options
447
+ };
448
+ }
449
+ function toPersistBashPermissionResult(result) {
450
+ if (typeof result !== "object" || result === null || Array.isArray(result)) {
451
+ throw new SessionCommandError("invalid-result", "Invalid persistent Bash permission response.");
452
+ }
453
+ const record = result;
454
+ if (record.status === "approved") {
455
+ return { status: "approved" };
456
+ }
457
+ if (record.status !== "validation-error" || typeof record.message !== "string" || typeof record.fieldErrors !== "object" || record.fieldErrors === null || Array.isArray(record.fieldErrors)) {
458
+ throw new SessionCommandError("invalid-result", "Invalid persistent Bash permission response.");
459
+ }
460
+ const fieldErrors = {};
461
+ for (const [key, value] of Object.entries(record.fieldErrors)) {
462
+ if (typeof value !== "string") {
463
+ throw new SessionCommandError(
464
+ "invalid-result",
465
+ "Invalid persistent Bash permission field error."
466
+ );
467
+ }
468
+ fieldErrors[key] = value;
469
+ }
470
+ return {
471
+ status: "validation-error",
472
+ message: record.message,
473
+ fieldErrors
474
+ };
475
+ }
476
+ function toMemoryDecisionOutcome(result) {
477
+ if (typeof result !== "object" || result === null || Array.isArray(result)) {
478
+ throw new SessionCommandError("invalid-result", "Invalid memory decision response.");
479
+ }
480
+ const record = result;
481
+ if (record.status === "approved" || record.status === "rejected") {
482
+ if (typeof record.id !== "string" || typeof record.slug !== "string") {
483
+ throw new SessionCommandError("invalid-result", "Invalid memory decision response.");
484
+ }
485
+ return { status: record.status, id: record.id, slug: record.slug };
486
+ }
487
+ if (record.status === "conflict") {
488
+ if (typeof record.id !== "string" || typeof record.slug !== "string" || typeof record.reason !== "string") {
489
+ throw new SessionCommandError("invalid-result", "Invalid memory decision response.");
490
+ }
491
+ return { status: "conflict", id: record.id, slug: record.slug, reason: record.reason };
492
+ }
493
+ if (record.status === "failed") {
494
+ if (typeof record.id !== "string" || typeof record.reason !== "string") {
495
+ throw new SessionCommandError("invalid-result", "Invalid memory decision response.");
496
+ }
497
+ return typeof record.slug === "string" ? { status: "failed", id: record.id, slug: record.slug, reason: record.reason } : { status: "failed", id: record.id, reason: record.reason };
498
+ }
499
+ throw new SessionCommandError("invalid-result", "Invalid memory decision response.");
500
+ }
501
+ function toMemoryRemovalResult(result) {
502
+ if (typeof result !== "object" || result === null || Array.isArray(result)) {
503
+ throw new SessionCommandError("invalid-result", "Invalid memory removal response.");
504
+ }
505
+ const record = result;
506
+ if (typeof record.removed !== "boolean" || typeof record.slug !== "string") {
507
+ throw new SessionCommandError("invalid-result", "Invalid memory removal response.");
508
+ }
509
+ return { removed: record.removed, slug: record.slug };
510
+ }
343
511
  function createSessionClient(transport) {
344
512
  let state = createSessionViewState();
345
513
  let seq = 0;
@@ -386,7 +554,12 @@ function createSessionClient(transport) {
386
554
  if (frame.ok) {
387
555
  entry.resolve(frame.result);
388
556
  } else {
389
- entry.reject(new Error(frame.error?.message ?? "Command failed."));
557
+ entry.reject(
558
+ new SessionCommandError(
559
+ frame.error?.code ?? "command-failed",
560
+ frame.error?.message ?? "Command failed."
561
+ )
562
+ );
390
563
  }
391
564
  return;
392
565
  }
@@ -444,17 +617,27 @@ function createSessionClient(transport) {
444
617
  })).then(() => {
445
618
  });
446
619
  },
447
- decideApproval(toolCallId, decision, comment, grantDir) {
620
+ decideApproval(toolCallId, decision, comment, grantDir, parentToolCallId) {
448
621
  return sendCommand((id) => ({
449
622
  id,
450
623
  type: "decide-approval",
451
624
  toolCallId,
452
625
  decision,
453
626
  ...comment !== void 0 ? { comment } : {},
454
- ...grantDir !== void 0 ? { grantDir } : {}
627
+ ...grantDir !== void 0 ? { grantDir } : {},
628
+ ...parentToolCallId !== void 0 ? { parentToolCallId } : {}
455
629
  })).then(() => {
456
630
  });
457
631
  },
632
+ persistBashPermission(toolCallId, request, parentToolCallId) {
633
+ return sendCommand((id) => ({
634
+ id,
635
+ type: "persist-bash-permission",
636
+ toolCallId,
637
+ ...parentToolCallId !== void 0 ? { parentToolCallId } : {},
638
+ request
639
+ })).then(toPersistBashPermissionResult);
640
+ },
458
641
  answerQuestion(questionId, answers) {
459
642
  return sendCommand((id) => ({ id, type: "answer-question", questionId, answers })).then(
460
643
  () => {
@@ -497,6 +680,9 @@ function createSessionClient(transport) {
497
680
  completeModels() {
498
681
  return sendCommand((id) => ({ id, type: "complete-models" })).then(toModelCompletion);
499
682
  },
683
+ completeThinking() {
684
+ return sendCommand((id) => ({ id, type: "complete-thinking" })).then(toThinkingCompletion);
685
+ },
500
686
  setConfig(patches) {
501
687
  return sendCommand((id) => ({ id, type: "set-config", patches })).then(
502
688
  (result) => result
@@ -532,6 +718,41 @@ function createSessionClient(transport) {
532
718
  (result) => Array.isArray(result) ? result : []
533
719
  );
534
720
  },
721
+ listPendingMemories() {
722
+ return sendCommand((id) => ({ id, type: "list-pending-memories" })).then(
723
+ (result) => Array.isArray(result) ? result : []
724
+ );
725
+ },
726
+ getPendingMemory(pendingId) {
727
+ return sendCommand((id) => ({ id, type: "get-pending-memory", pendingId })).then(
728
+ (result) => result
729
+ );
730
+ },
731
+ approvePendingMemory(pendingId) {
732
+ return sendCommand((id) => ({ id, type: "approve-pending-memory", pendingId })).then(
733
+ toMemoryDecisionOutcome
734
+ );
735
+ },
736
+ rejectPendingMemory(pendingId) {
737
+ return sendCommand((id) => ({ id, type: "reject-pending-memory", pendingId })).then(
738
+ toMemoryDecisionOutcome
739
+ );
740
+ },
741
+ listWorkspaceMemories() {
742
+ return sendCommand((id) => ({ id, type: "list-workspace-memories" })).then(
743
+ (result) => Array.isArray(result) ? result : []
744
+ );
745
+ },
746
+ getWorkspaceMemory(slug) {
747
+ return sendCommand((id) => ({ id, type: "get-workspace-memory", memorySlug: slug })).then(
748
+ (result) => result
749
+ );
750
+ },
751
+ removeWorkspaceMemory(slug) {
752
+ return sendCommand((id) => ({ id, type: "remove-workspace-memory", memorySlug: slug })).then(
753
+ toMemoryRemovalResult
754
+ );
755
+ },
535
756
  capabilities() {
536
757
  return transport.capabilities?.() ?? [];
537
758
  },
@@ -776,7 +997,7 @@ function createWebSocketTransport(options) {
776
997
  deliver(message);
777
998
  return;
778
999
  }
779
- if (message.type === "welcome" || message.type === "replay" || message.type === "session-list" || message.type === "session-created") {
1000
+ if (message.type === "welcome" || message.type === "replay" || message.type === "session-list" || message.type === "session-list-update" || message.type === "session-created") {
780
1001
  return;
781
1002
  }
782
1003
  lastSeq = message.seq;
@@ -887,11 +1108,13 @@ function throwCollectedErrors(errors, message) {
887
1108
  }
888
1109
  function bindDaemonDataClient(client, daemonId) {
889
1110
  return {
890
- fetchTranscript: (historyId, opts) => client.fetchTranscript(daemonId, historyId, opts),
1111
+ fetchTranscript: (identity) => client.fetchTranscript(daemonId, identity),
891
1112
  fetchHistory: (opts) => client.fetchHistory(daemonId, opts),
1113
+ listHistoryWorkspaces: (opts) => client.listHistoryWorkspaces(daemonId, opts),
1114
+ listWorkspaceHistory: (opts) => client.listWorkspaceHistory(daemonId, opts),
892
1115
  listWorkspaces: (opts) => client.listWorkspaces(daemonId, opts),
893
1116
  createWorkspace: (opts) => client.createWorkspace(daemonId, opts),
894
- deleteSession: (historyId, opts) => client.deleteSession(daemonId, historyId, opts),
1117
+ deleteSession: (identity) => client.deleteSession(daemonId, identity),
895
1118
  listProfiles: () => client.listProfiles(daemonId),
896
1119
  listProviders: (opts) => client.listProviders(daemonId, opts),
897
1120
  addProvider: (input) => client.addProvider(daemonId, input),
@@ -1091,6 +1314,24 @@ function createDaemonClient(target, deps = {}) {
1091
1314
  }
1092
1315
 
1093
1316
  // src/client/directory.ts
1317
+ var DAEMON_REQUEST_ERROR_CODES = /* @__PURE__ */ new Set([
1318
+ "transcript-unavailable",
1319
+ "transcript-corrupt",
1320
+ "history-state-conflict",
1321
+ "ambiguous-session-identity"
1322
+ ]);
1323
+ var DaemonRequestError = class extends Error {
1324
+ code;
1325
+ identity;
1326
+ constructor(message, options) {
1327
+ super(message);
1328
+ this.name = "DaemonRequestError";
1329
+ if (options?.code && DAEMON_REQUEST_ERROR_CODES.has(options.code)) {
1330
+ this.code = options.code;
1331
+ }
1332
+ this.identity = options?.identity;
1333
+ }
1334
+ };
1094
1335
  var toText2 = (data) => {
1095
1336
  if (typeof data === "string") return data;
1096
1337
  if (data instanceof Buffer) return data.toString("utf8");
@@ -1162,6 +1403,13 @@ function createServerDirectory(options) {
1162
1403
  link.pending.set(id, { kind: "list" });
1163
1404
  link.socket.send(JSON.stringify({ id, type: "list-sessions" }));
1164
1405
  };
1406
+ const subscribeToSessionList = (link) => {
1407
+ if (!link.ready || link.socket === null) return;
1408
+ link.commandCounter += 1;
1409
+ link.socket.send(
1410
+ JSON.stringify({ id: `dir-${link.commandCounter}`, type: "subscribe-session-list" })
1411
+ );
1412
+ };
1165
1413
  const handleMessage = (link, message) => {
1166
1414
  if (message.type === "rejected") {
1167
1415
  markOffline(
@@ -1175,6 +1423,13 @@ function createServerDirectory(options) {
1175
1423
  clearTimer(link);
1176
1424
  rebuildView();
1177
1425
  sendList(link);
1426
+ subscribeToSessionList(link);
1427
+ return;
1428
+ }
1429
+ if (message.type === "session-list-update") {
1430
+ if (!link.ready) return;
1431
+ link.status = { state: "online", sessions: message.sessions };
1432
+ rebuildView();
1178
1433
  return;
1179
1434
  }
1180
1435
  if (message.type === "session-list") {
@@ -1202,7 +1457,12 @@ function createServerDirectory(options) {
1202
1457
  if (!entry || entry.kind === "list") return;
1203
1458
  link.pending.delete(message.id);
1204
1459
  if (!message.ok) {
1205
- entry.reject(new Error(message.error?.message ?? "Command failed."));
1460
+ entry.reject(
1461
+ new DaemonRequestError(message.error?.message ?? "Command failed.", {
1462
+ ...message.error?.code ? { code: message.error.code } : {},
1463
+ ...message.error?.identity ? { identity: message.error.identity } : {}
1464
+ })
1465
+ );
1206
1466
  return;
1207
1467
  }
1208
1468
  if (entry.kind === "kill") {
@@ -1403,7 +1663,7 @@ function createServerDirectory(options) {
1403
1663
  );
1404
1664
  });
1405
1665
  },
1406
- resumeSession(server, historyId, resumeOptions) {
1666
+ resumeSession(server, identity) {
1407
1667
  return new Promise((resolve, reject) => {
1408
1668
  const link = linkFor(server);
1409
1669
  if (link instanceof Error) {
@@ -1417,11 +1677,7 @@ function createServerDirectory(options) {
1417
1677
  JSON.stringify({
1418
1678
  id,
1419
1679
  type: "resume-session",
1420
- historyId,
1421
- cwd: resumeOptions.cwd,
1422
- ...resumeOptions.name !== void 0 ? { name: resumeOptions.name } : {},
1423
- ...resumeOptions.workspace !== void 0 ? { workspace: resumeOptions.workspace } : {},
1424
- ...resumeOptions.profile !== void 0 ? { profile: resumeOptions.profile } : {}
1680
+ identity
1425
1681
  })
1426
1682
  );
1427
1683
  });
@@ -1469,6 +1725,9 @@ function createServerDirectory(options) {
1469
1725
  };
1470
1726
  }
1471
1727
  export {
1728
+ DaemonRequestError,
1729
+ DataRpcClientError,
1730
+ SessionCommandError,
1472
1731
  TerminalEndpointError,
1473
1732
  adaptWhatwgSocket,
1474
1733
  bindDaemonDataClient,
@@ -1,5 +1,5 @@
1
1
  import type { AgentInput, AskUserAnswers } from "@nuvin/agent-core/shared";
2
- import type { AgentCatalogEntry, AgentDetail, ChatGptCredentialInput, CommandDetail, ConfigPatch, CustomProviderInput, GrantCapability, McpAction, McpActionResult, 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, MemoryDecisionOutcome, ModelCompletion, PendingMemoryDetail, PendingMemorySummary, PersistBashPermissionRequest, PersistBashPermissionResult, ServerEvent, SessionViewState, SetConfigResult, SkillCatalogEntry, SkillDetail, SlashCommandDescriptor, ThinkingCompletion, WorkspaceMemoryDetail, WorkspaceMemorySummary } from "../protocol/types.ts";
3
3
  import type { ClientTransport } from "./transport.ts";
4
4
  export type ClientSubmitOptions = {
5
5
  displayText: string;
@@ -18,7 +18,8 @@ export interface SessionClient {
18
18
  /** Raw frame hook for UI side-effects (e.g. close modals on state-reset). */
19
19
  onEvent(listener: (event: ServerEvent) => void): () => void;
20
20
  submit(input: AgentInput, opts: ClientSubmitOptions): Promise<void>;
21
- decideApproval(toolCallId: string, decision: "a" | "n" | "y", comment?: string, grantDir?: string): Promise<void>;
21
+ decideApproval(toolCallId: string, decision: "a" | "n" | "y", comment?: string, grantDir?: string, parentToolCallId?: string): Promise<void>;
22
+ persistBashPermission(toolCallId: string, request: PersistBashPermissionRequest, parentToolCallId?: string): Promise<PersistBashPermissionResult>;
22
23
  answerQuestion(questionId: string, answers: AskUserAnswers): Promise<void>;
23
24
  abort(): Promise<void>;
24
25
  /** Cancel a queued (not-yet-running) message by its `turn-status.queued` id. */
@@ -52,11 +53,15 @@ export interface SessionClient {
52
53
  * completion when no host is attached / the daemon is unsupported.
53
54
  */
54
55
  completeModels(): Promise<ModelCompletion>;
56
+ /** Fetch model-specific `/thinking` options from the attached runtime. */
57
+ completeThinking(): Promise<ThinkingCompletion>;
55
58
  /**
56
59
  * Restricted config write (spec: Ctrl+P config panel §Writes). Sends the batch
57
60
  * to the attached host, which allowlists/validates/writes each patch and
58
- * live-applies to this session. Resolves with the {@link SetConfigResult}
59
- * (empty `failures` all applied); rejects when no host is attached.
61
+ * live-applies to this session. Resolves with the {@link SetConfigResult}; empty
62
+ * `failures` means every accepted patch was persisted, and empty
63
+ * `liveApplyFailures` means current-session live apply succeeded. Rejects when no
64
+ * host is attached.
60
65
  */
61
66
  setConfig(patches: ConfigPatch[]): Promise<SetConfigResult>;
62
67
  /** Full skill catalog (incl. disabled) for the Skills tab. */
@@ -71,6 +76,23 @@ export interface SessionClient {
71
76
  getCommand(name: string): Promise<CommandDetail>;
72
77
  /** MCP servers with live status + per-server tools for the MCP tab. */
73
78
  listMcpServers(): Promise<McpServerInfo[]>;
79
+ /** Pending extracted-memory candidates for the Memory tab. */
80
+ listPendingMemories(): Promise<PendingMemorySummary[]>;
81
+ /** Lazy-load one pending candidate's diff detail for the Memory tab. */
82
+ getPendingMemory(pendingId: string): Promise<PendingMemoryDetail>;
83
+ /** Approve one pending candidate (commit it to workspace memory). */
84
+ approvePendingMemory(pendingId: string): Promise<MemoryDecisionOutcome>;
85
+ /** Reject (discard) one pending candidate. */
86
+ rejectPendingMemory(pendingId: string): Promise<MemoryDecisionOutcome>;
87
+ /** Committed workspace memories for the Memory tab. */
88
+ listWorkspaceMemories(): Promise<WorkspaceMemorySummary[]>;
89
+ /** Lazy-load one committed memory's full content for the Memory tab. */
90
+ getWorkspaceMemory(slug: string): Promise<WorkspaceMemoryDetail>;
91
+ /** Delete one committed workspace memory. */
92
+ removeWorkspaceMemory(slug: string): Promise<{
93
+ removed: boolean;
94
+ slug: string;
95
+ }>;
74
96
  /**
75
97
  * Effective grant capabilities from the transport's latest welcome (UI hint).
76
98
  * Empty when the transport does not expose capabilities.
@@ -88,5 +110,9 @@ export interface SessionClient {
88
110
  addCustomProvider(provider: CustomProviderInput): Promise<void>;
89
111
  close(): void;
90
112
  }
113
+ export declare class SessionCommandError extends Error {
114
+ readonly code: string;
115
+ constructor(code: string, message: string);
116
+ }
91
117
  export declare function createSessionClient(transport: ClientTransport): SessionClient;
92
118
  //# sourceMappingURL=session-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-client.d.ts","sourceRoot":"","sources":["../../src/client/session-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-client.d.ts","sourceRoot":"","sources":["../../src/client/session-client.ts"],"names":[],"mappings":"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"}
@@ -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,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"}
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,CAiR1B"}
@@ -1,7 +1,7 @@
1
- import type { AgentEvent, AskUserAnswers, AskUserQuestionRequest, Message, ToolRuntimeDispatchDecision, ToolUseBlock } from "@nuvin/agent-core/shared";
2
- import type { DirAccessRequest } from "../protocol/types.ts";
1
+ import type { AgentEvent, AskUserAnswers, AskUserQuestionRequest, Message, ToolPermissionClass, ToolRuntimeDispatchDecision, ToolUseBlock } from "@nuvin/agent-core/shared";
2
+ import type { BashPolicyApprovalDiagnostics, DirAccessRequest, PersistBashPermissionHandlerResult, PersistBashPermissionRequest, WorkflowBashPolicySummary } from "../protocol/types.ts";
3
3
  import type { TuiMessage } from "../state/messages.ts";
4
- /** Structural mirror of the CLI session store's LoadedSession. */
4
+ /** UI-safe transcript projection of runtime LoadedSession. */
5
5
  export type SessionLoadedPayload = {
6
6
  agentMessages: Message[];
7
7
  id: string;
@@ -23,15 +23,20 @@ export type AgentEventPayload = {
23
23
  };
24
24
  export type ToolCallRequest = {
25
25
  agentId: string;
26
+ approvalKey?: string;
27
+ bashPolicy?: BashPolicyApprovalDiagnostics;
26
28
  /** Set by the runtime pre-check when the call's path is outside allowedDirs. */
27
29
  dirAccess?: DirAccessRequest;
28
30
  parentToolCallId?: string;
31
+ permissionClass?: ToolPermissionClass;
32
+ persistBashPermission?: (request: PersistBashPermissionRequest) => Promise<PersistBashPermissionHandlerResult>;
29
33
  toolCall: ToolUseBlock;
34
+ workflowBashPolicy?: WorkflowBashPolicySummary;
30
35
  };
31
36
  export type AgentEventListener = (payload: AgentEventPayload) => void;
32
37
  export type SessionLoadedListener = (loaded: SessionLoadedPayload) => void;
33
38
  export type ToolCallDecider = (request: ToolCallRequest) => Promise<ToolRuntimeDispatchDecision> | ToolRuntimeDispatchDecision;
34
- export type UserQuestionHandler = (request: AskUserQuestionRequest) => Promise<AskUserAnswers> | AskUserAnswers;
39
+ export type UserQuestionHandler = (request: AskUserQuestionRequest, scope?: DelegationScope) => Promise<AskUserAnswers> | AskUserAnswers;
35
40
  /**
36
41
  * In-process channel between the Agent (constructed in `main()`) and the
37
42
  * React UI (`<App />`). Two distinct shapes:
@@ -49,7 +54,7 @@ export declare class AgentChannel {
49
54
  publishEvent(event: AgentEvent, scope?: DelegationScope): void;
50
55
  publishSessionLoaded(loaded: SessionLoadedPayload): void;
51
56
  requestToolDecision(request: ToolCallRequest): Promise<ToolRuntimeDispatchDecision> | ToolRuntimeDispatchDecision;
52
- requestUserQuestion(request: AskUserQuestionRequest): Promise<AskUserAnswers>;
57
+ requestUserQuestion(request: AskUserQuestionRequest, scope?: DelegationScope): Promise<AskUserAnswers>;
53
58
  onEvent(listener: AgentEventListener): () => void;
54
59
  onSessionLoaded(listener: SessionLoadedListener): () => void;
55
60
  setToolDecider(decider: ToolCallDecider | null): void;