@corenel/term 0.4.0 → 0.5.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/README.md CHANGED
@@ -4,7 +4,7 @@ Corenel's terminal face: a headless chat controller and the [Ink](https://github
4
4
  views that render it. Published so [`@corenel/cli`](https://www.npmjs.com/package/@corenel/cli)
5
5
  can depend on it; usable directly if you are building a terminal agent of your own.
6
6
 
7
- Requires Node 18+.
7
+ Requires Node 22+.
8
8
 
9
9
  ## The split that matters
10
10
 
@@ -0,0 +1,6 @@
1
+ import type { ApprovalSuggestion, SuggestionChoice } from '@corenel/protocol';
2
+ export declare function suggestionLine(s: ApprovalSuggestion): string;
3
+ export declare function suggestionKeys(s: ApprovalSuggestion): string;
4
+ export declare function parseSuggestionChoice(s: ApprovalSuggestion, input: string | null): SuggestionChoice | null;
5
+ export declare function suggestionOutcome(tool: string, choice: SuggestionChoice): string;
6
+ //# sourceMappingURL=approvalText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvalText.d.ts","sourceRoot":"","sources":["../src/approvalText.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAiB9E,wBAAgB,cAAc,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAE5D;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAI5D;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,gBAAgB,GAAG,IAAI,CAO1G;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAQhF"}
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  emptyState,
3
3
  parseTodos
4
- } from "./chunk-2MGDL3I4.js";
4
+ } from "./chunk-MAZLORMD.js";
5
5
  import {
6
6
  formatHelpText,
7
7
  isKnownCommandWord,
8
8
  parseCommand,
9
9
  unknownCommandMessage
10
- } from "./chunk-5RPHYXND.js";
10
+ } from "./chunk-TWFWLEIP.js";
11
11
  import {
12
12
  WRITE_TOOL_NAMES,
13
13
  buildWritePreview
@@ -155,9 +155,44 @@ function stripInline(s) {
155
155
  return s.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1 ($2)").replace(/\*\*(\S(?:[^*]*\S)?)\*\*/g, "$1").replace(/(?<!\*)\*(\S(?:[^*]*\S)?)\*(?!\*)/g, "$1").replace(/`([^`]+)`/g, "$1");
156
156
  }
157
157
 
158
+ // src/approvalText.ts
159
+ function sanitizeToolName(name) {
160
+ return name.replace(/[\u0000-\u001f\u007f-\u009f]/g, "");
161
+ }
162
+ function suggestionLine(s) {
163
+ return `You have allowed ${sanitizeToolName(s.tool)} ${s.count} times${s.scope === "workspace" ? " in this folder" : ""}. Always allow it?`;
164
+ }
165
+ function suggestionKeys(s) {
166
+ return s.scopeChoice ? "[w] this folder [e] everywhere [n] not now [x] never" : "[e] always [n] not now [x] never";
167
+ }
168
+ function parseSuggestionChoice(s, input) {
169
+ const k = (input ?? "").trim().toLowerCase();
170
+ if (k === "w") return s.scopeChoice ? "workspace" : null;
171
+ if (k === "e") return "global";
172
+ if (k === "n") return "not-now";
173
+ if (k === "x") return "never";
174
+ return null;
175
+ }
176
+ function suggestionOutcome(tool, choice) {
177
+ const t = sanitizeToolName(tool);
178
+ switch (choice) {
179
+ case "workspace":
180
+ return `always allowing ${t} in this folder (undo: corenel approvals revoke ${t})`;
181
+ case "global":
182
+ return `always allowing ${t} everywhere (undo: corenel approvals revoke ${t} --global)`;
183
+ case "not-now":
184
+ return `not now: ${t} will be suggested again after more approvals`;
185
+ case "never":
186
+ return `${t} will not be suggested again`;
187
+ }
188
+ }
189
+
158
190
  // src/session.ts
159
191
  var DELTA_FLUSH_MS = 50;
160
192
  var TOOL_DELTA_CAP = 4e3;
193
+ function sameTool(heldKey, askedName) {
194
+ return heldKey === askedName || heldKey.endsWith(`:${askedName}`);
195
+ }
161
196
  var TermSession = class {
162
197
  constructor(deps) {
163
198
  this.deps = deps;
@@ -203,6 +238,12 @@ var TermSession = class {
203
238
  turnId = 0;
204
239
  activeTurn = 0;
205
240
  pending = null;
241
+ /** The tool name a `pending` permission ask is FOR -- set only by
242
+ * `askPermission`, never by `askUser` (a question is not tied to one tool).
243
+ * Consumed once by `resolvePending` to decide whether a denied ask should
244
+ * drop a held suggestion for the same tool (final review M3). */
245
+ pendingAskTool = null;
246
+ heldSuggestion = null;
206
247
  draining = false;
207
248
  /* Bumped whenever the conversation is REPLACED out from under a turn --
208
249
  * `/clear` and `resume()`. A turn captures it when it starts and only adopts
@@ -1016,9 +1057,12 @@ var TermSession = class {
1016
1057
  }
1017
1058
  /** esc, or any other reason the overlay should close -- a no-op unless the
1018
1059
  * manager is actually the modal open right now, so it can never steal a
1019
- * permission or question modal's close. */
1060
+ * permission or question modal's close. Restores a held suggestion (final
1061
+ * review M3) rather than just clearing the modal -- otherwise an offer held
1062
+ * behind this overlay came back only when some LATER, unrelated permission
1063
+ * ask happened to resolve. */
1020
1064
  closeMcpManager() {
1021
- if (this.state.modal?.kind === "mcp") this.set({ modal: null });
1065
+ if (this.state.modal?.kind === "mcp") this.restoreHeldSuggestion(null);
1022
1066
  }
1023
1067
  /* ---- the Ink `/help` overlay -------------------------------------------
1024
1068
  *
@@ -1038,9 +1082,10 @@ var TermSession = class {
1038
1082
  }
1039
1083
  /** esc, or any other reason the overlay should close -- a no-op unless the
1040
1084
  * help overlay is actually the modal open right now, so it can never steal
1041
- * a permission, question, or MCP modal's close. */
1085
+ * a permission, question, or MCP modal's close. Restores a held suggestion
1086
+ * (final review M3) -- see closeMcpManager's doc. */
1042
1087
  closeHelp() {
1043
- if (this.state.modal?.kind === "help") this.set({ modal: null });
1088
+ if (this.state.modal?.kind === "help") this.restoreHeldSuggestion(null);
1044
1089
  }
1045
1090
  /* ---- the Ink `/context` overlay ----------------------------------------
1046
1091
  *
@@ -1079,9 +1124,11 @@ var TermSession = class {
1079
1124
  }
1080
1125
  /** esc, or any other reason the context overlay should close -- a no-op
1081
1126
  * unless the context overlay is actually the modal open right now, so it
1082
- * can never steal a permission, question, help, or MCP modal's close. */
1127
+ * can never steal a permission, question, help, or MCP modal's close.
1128
+ * Restores a held suggestion (final review M3) -- see closeMcpManager's
1129
+ * doc. */
1083
1130
  closeContext() {
1084
- if (this.state.modal?.kind === "context") this.set({ modal: null });
1131
+ if (this.state.modal?.kind === "context") this.restoreHeldSuggestion(null);
1085
1132
  }
1086
1133
  /** Up/down inside the overlay -- wraps, and does nothing with zero rows. */
1087
1134
  moveMcpSelection(delta) {
@@ -1260,6 +1307,7 @@ ${line}` : line;
1260
1307
  this.activeTurn = mine;
1261
1308
  this.beginTurn();
1262
1309
  const system = await this.resolveSystem();
1310
+ const skills = this.deps.skills ? await this.deps.skills().catch(() => []) : [];
1263
1311
  const run = this.deps.runner ?? runAgent;
1264
1312
  try {
1265
1313
  const result = await run({
@@ -1268,6 +1316,7 @@ ${line}` : line;
1268
1316
  ...system ? { system } : {},
1269
1317
  messages: this.history,
1270
1318
  tools: this.deps.tools,
1319
+ ...skills.length ? { skills } : {},
1271
1320
  toolCtx: this.deps.toolCtx(ac.signal, (q) => this.askUser(q), this.permission),
1272
1321
  signal: ac.signal,
1273
1322
  ...this.permission ? { permission: this.permission } : {},
@@ -1344,15 +1393,17 @@ ${line}` : line;
1344
1393
  * fully synchronous, exactly as before this method could show a diff at
1345
1394
  * all. */
1346
1395
  askPermission(req) {
1347
- if (this.deps.approveAll) return Promise.resolve("allow");
1396
+ if (this.deps.approveAll) return Promise.resolve({ decision: "allow", by: "unattended" });
1348
1397
  if (this.pending) throw new Error("a question is already open");
1349
1398
  const detail = req.input;
1350
1399
  const shown = typeof detail?.command === "string" ? detail.command : typeof detail?.path === "string" ? detail.path : "";
1351
1400
  const openModal = (diff) => {
1352
- if (this.state.status === "aborting") return "deny";
1401
+ if (this.state.status === "aborting") return { decision: "deny", by: "timeout" };
1402
+ if (this.state.modal?.kind === "suggestion") this.heldSuggestion = this.state.modal.suggestion;
1353
1403
  this.set({ modal: { kind: "permission", tool: req.tool, detail: shown, ...diff ? { diff } : {} } });
1354
1404
  return new Promise((resolve) => {
1355
1405
  this.pending = { resolve: (v) => resolve(v ?? "deny") };
1406
+ this.pendingAskTool = req.tool;
1356
1407
  });
1357
1408
  };
1358
1409
  if (!this.deps.previewWrite || !WRITE_TOOL_NAMES.has(req.tool)) return Promise.resolve(openModal(null));
@@ -1360,6 +1411,7 @@ ${line}` : line;
1360
1411
  }
1361
1412
  askUser(questions) {
1362
1413
  if (this.pending) throw new Error("a question is already open");
1414
+ if (this.state.modal?.kind === "suggestion") this.heldSuggestion = this.state.modal.suggestion;
1363
1415
  this.set({ modal: { kind: "user", questions } });
1364
1416
  return new Promise((resolve) => {
1365
1417
  this.pending = { resolve: (v) => resolve(v ?? null) };
@@ -1377,15 +1429,65 @@ ${line}` : line;
1377
1429
  * outcome that `askUserTool` (packages/harness/tools/builtins.ts) checks for. */
1378
1430
  forceClosePending() {
1379
1431
  if (!this.pending) return;
1380
- this.resolvePending(this.state.modal?.kind === "user" ? null : "deny");
1432
+ this.resolvePending(this.state.modal?.kind === "user" ? null : { decision: "deny", by: "timeout" });
1381
1433
  }
1382
1434
  resolvePending(value) {
1383
1435
  const p = this.pending;
1384
1436
  if (!p) return;
1385
1437
  this.pending = null;
1386
- this.set({ modal: null });
1438
+ const askTool = this.pendingAskTool;
1439
+ this.pendingAskTool = null;
1440
+ const decision = typeof value === "object" && value !== null && "decision" in value ? value.decision : value;
1441
+ this.restoreHeldSuggestion(decision === "deny" && askTool !== null ? askTool : null);
1387
1442
  p.resolve(value);
1388
1443
  }
1444
+ /** Restore whatever suggestion is held (if any) as the visible modal,
1445
+ * dropping it instead if `dropForTool` names the tool it is for. Shared by
1446
+ * every path that can uncover a held offer: answering a permission/question
1447
+ * ask (`resolvePending`), and closing the help/MCP/context overlays -- all
1448
+ * of which used to just clear the modal, silently losing a held offer until
1449
+ * some LATER, unrelated permission answer happened to surface it (final
1450
+ * review M3). */
1451
+ restoreHeldSuggestion(dropForTool) {
1452
+ let held = this.heldSuggestion;
1453
+ this.heldSuggestion = null;
1454
+ if (held && dropForTool !== null && sameTool(held.tool, dropForTool)) held = null;
1455
+ this.set({ modal: held ? { kind: "suggestion", suggestion: held, openedAt: Date.now(), armedChoice: null } : null });
1456
+ }
1457
+ /** Offer a standing approval. Shown now if nothing is open, otherwise held
1458
+ * until the open prompt is answered; a newer offer replaces a held one. */
1459
+ offerApprovalSuggestion(s) {
1460
+ if (!this.deps.saveApprovalChoice) return;
1461
+ if (this.state.modal === null) {
1462
+ this.set({ modal: { kind: "suggestion", suggestion: s, openedAt: Date.now(), armedChoice: null } });
1463
+ return;
1464
+ }
1465
+ this.heldSuggestion = s;
1466
+ }
1467
+ /** Arm a widening choice (`workspace` / `global`) without granting it yet --
1468
+ * only a following Enter (`respondApprovalSuggestion`) does that. See
1469
+ * ApprovalSuggestionView's doc (final review I1). A no-op if the suggestion
1470
+ * modal is not open. */
1471
+ armApprovalSuggestion(choice) {
1472
+ if (this.state.modal?.kind !== "suggestion") return;
1473
+ this.set({ modal: { ...this.state.modal, armedChoice: choice } });
1474
+ }
1475
+ async respondApprovalSuggestion(choice) {
1476
+ const modal = this.state.modal;
1477
+ const save = this.deps.saveApprovalChoice;
1478
+ if (modal?.kind !== "suggestion" || !save) return;
1479
+ this.set({ modal: null });
1480
+ try {
1481
+ await save(modal.suggestion, choice);
1482
+ this.note("info", suggestionOutcome(modal.suggestion.tool, choice));
1483
+ } catch (e) {
1484
+ this.note("warn", `could not save that choice: ${e instanceof Error ? e.message : String(e)}`);
1485
+ }
1486
+ }
1487
+ /** Escape: ignore the offer. Writes nothing (plan Task 5: ignoring is not a choice). */
1488
+ dismissApprovalSuggestion() {
1489
+ if (this.state.modal?.kind === "suggestion") this.set({ modal: null });
1490
+ }
1389
1491
  };
1390
1492
 
1391
1493
  export {
@@ -1393,6 +1495,10 @@ export {
1393
1495
  ageWord,
1394
1496
  formatContext,
1395
1497
  parseMarkdown,
1498
+ suggestionLine,
1499
+ suggestionKeys,
1500
+ parseSuggestionChoice,
1501
+ suggestionOutcome,
1396
1502
  DELTA_FLUSH_MS,
1397
1503
  TOOL_DELTA_CAP,
1398
1504
  TermSession
@@ -1,4 +1,5 @@
1
1
  // src/state.ts
2
+ var SUGGESTION_ARM_DELAY_MS = 400;
2
3
  function emptyState(model = "") {
3
4
  return {
4
5
  seq: 0,
@@ -45,6 +46,7 @@ function parseTodos(args) {
45
46
  }
46
47
 
47
48
  export {
49
+ SUGGESTION_ARM_DELAY_MS,
48
50
  emptyState,
49
51
  parseTodos
50
52
  };
@@ -1,4 +1,5 @@
1
1
  // src/commands.ts
2
+ import { strategiesRoot } from "@corenel/protocol";
2
3
  var TERM_COMMANDS = [
3
4
  { name: "help", summary: "what you can type here" },
4
5
  { name: "tools", summary: "what the agent can do, and what it can change" },
@@ -15,7 +16,9 @@ var TERM_COMMANDS = [
15
16
  { name: "mode", args: "<id>", summary: "switch the agent mode (takes effect next turn); no id lists what is configured" },
16
17
  { name: "persona", args: "<id>", summary: "switch persona (takes effect next turn); no id lists what is configured" },
17
18
  { name: "skill", args: "<name>", summary: "apply a skill to your NEXT message only, then it clears; no name lists what is installed" },
18
- { name: "strategy", args: "<name>", summary: "run a saved strategy from .prompd/strategies; no name lists what is saved" },
19
+ { name: "strategy", args: "<name>", get summary() {
20
+ return `run a saved strategy from the current project's strategies folder (${strategiesRoot()} in a folder with no project); no name lists what is saved`;
21
+ } },
19
22
  { name: "mcp", args: "[list|add|remove|login|refresh|forget]", summary: "MCP servers -- what is connected, and sign in or add one; no argument opens the manager" }
20
23
  ];
21
24
  function formatHelpText() {
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,EAkBtC,CAAC;AAEF;;;;;;;+DAO+D;AAC/D,wBAAgB,cAAc,IAAI,MAAM,CAiBvC;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GAChB;IAAE,GAAG,EAAE,QAAQ,CAAA;CAAE,GACjB;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAClB;IAAE,GAAG,EAAE,QAAQ,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,GAAG,EAAE,QAAQ,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GAChB;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,GAAG,EAAE,KAAK,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAQxH;;;;;yDAKyD;AACzD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxD;AAkBD;;;;;;;WAOW;AACX,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU1D;AAED;;yBAEyB;AACzB,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAwC/D;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAK3D"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,EAkBtC,CAAC;AAEF;;;;;;;+DAO+D;AAC/D,wBAAgB,cAAc,IAAI,MAAM,CAiBvC;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GAChB;IAAE,GAAG,EAAE,QAAQ,CAAA;CAAE,GACjB;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAClB;IAAE,GAAG,EAAE,QAAQ,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,GAAG,EAAE,QAAQ,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GAChB;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,GAAG,EAAE,KAAK,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAQxH;;;;;yDAKyD;AACzD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxD;AAkBD;;;;;;;WAOW;AACX,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU1D;AAED;;yBAEyB;AACzB,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAwC/D;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAK3D"}
package/dist/commands.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  parseCommand,
7
7
  suggestCommand,
8
8
  unknownCommandMessage
9
- } from "./chunk-5RPHYXND.js";
9
+ } from "./chunk-TWFWLEIP.js";
10
10
  export {
11
11
  TERM_COMMANDS,
12
12
  filterCommands,
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ink/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAoEzC,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB;;;;iDAI6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ;;iBAEa;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;oDAOgD;IAChD,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B;;;;;oDAKgD;IAChD,KAAK,EAAE,OAAO,CAAC;IACf;uDACmD;IACnD,eAAe,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;2EAUuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,4EAA4E;AAC5E,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,KAAK,CAAC,YAAY,CAgIvD"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ink/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAoEzC,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB;;;;iDAI6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ;;iBAEa;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;oDAOgD;IAChD,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B;;;;;oDAKgD;IAChD,KAAK,EAAE,OAAO,CAAC;IACf;uDACmD;IACnD,eAAe,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;2EAUuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,4EAA4E;AAC5E,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,KAAK,CAAC,YAAY,CAuIvD"}
@@ -1,5 +1,11 @@
1
1
  import React from 'react';
2
+ import type { ApprovalSuggestion } from '@corenel/protocol';
2
3
  import type { PermissionAsk, UserAsk } from '../state';
4
+ /** The standing-approval offer (plan 2): one line of question, one of keys.
5
+ * Not part of ModalView -- it pauses nothing -- so App.tsx routes it here. */
6
+ export declare function SuggestionView({ suggestion }: {
7
+ suggestion: ApprovalSuggestion;
8
+ }): React.ReactElement;
3
9
  /** The permission ask and the free-text/choice ask -- the two modals that
4
10
  * pause a turn waiting on the user. `McpManager` and `HelpView` are NOT this
5
11
  * component's job: App.tsx routes those to their own views (McpOverlay.tsx;
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/ink/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AA2GvD;;;;;;iDAMiD;AACjD,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CA2DhH"}
1
+ {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/ink/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAKvD;8EAC8E;AAC9E,wBAAgB,cAAc,CAAC,EAAE,UAAU,EAAE,EAAE;IAAE,UAAU,EAAE,kBAAkB,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAOrG;AAyGD;;;;;;iDAMiD;AACjD,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CA2DhH"}
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
+ import { PermissionService } from '@corenel/harness/guardrail/permission-service';
3
+ import { type ApprovalsService } from '@corenel/harness/approvals';
2
4
  import { TermSession, type TermSessionDeps } from '../session';
3
5
  export interface TuiDeps extends TermSessionDeps {
4
6
  version: string;
@@ -6,6 +8,14 @@ export interface TuiDeps extends TermSessionDeps {
6
8
  resume?: {
7
9
  id?: string;
8
10
  };
11
+ /** The host's approvals service (plan 2). Absent: no standing approvals, no
12
+ * decision log, no suggestions -- the kernel runs exactly as before. */
13
+ approvals?: ApprovalsService;
14
+ /** Stamped on each decision record. The session id is added at decision time. */
15
+ approvalsContext?: {
16
+ runId?: string;
17
+ workspace?: string;
18
+ };
9
19
  }
10
20
  /** Exported for `interaction.test.tsx` only: driving real keystrokes through
11
21
  * ink-testing-library's `stdin` requires rendering this directly, since
@@ -14,5 +24,13 @@ export declare function Root({ session, deps }: {
14
24
  session: TermSession;
15
25
  deps: TuiDeps;
16
26
  }): React.ReactElement;
27
+ /** The session's PermissionService: prompts through the session's modal,
28
+ * and -- with an approvals service -- honors standing approvals, records
29
+ * every decision, and offers a suggestion after the answer. Exported for
30
+ * approvalSuggestion.test.tsx. */
31
+ export declare function tuiPermission(session: TermSession, deps: TuiDeps): {
32
+ permission: PermissionService;
33
+ settled: () => Promise<void>;
34
+ };
17
35
  export declare function runTui(deps: TuiDeps): Promise<number>;
18
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ink/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAK3E,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAM/D,MAAM,WAAW,OAAQ,SAAQ,eAAe;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAS1B;AAED;;wEAEwE;AACxE,wBAAgB,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAwPnG;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAyD3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ink/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAE3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnF,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAQ/D,MAAM,WAAW,OAAQ,SAAQ,eAAe;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IASzB;4EACwE;IACxE,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,iFAAiF;IACjF,gBAAgB,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAED;;wEAEwE;AACxE,wBAAgB,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAoSnG;AAED;;;kCAGkC;AAClC,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,GAAG;IAAE,UAAU,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAsBlI;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAwD3D"}
package/dist/ink/index.js CHANGED
@@ -3,14 +3,19 @@ import {
3
3
  ageWord,
4
4
  formatContext,
5
5
  mcpStatusWord,
6
- parseMarkdown
7
- } from "../chunk-HUVRQX53.js";
8
- import "../chunk-2MGDL3I4.js";
6
+ parseMarkdown,
7
+ parseSuggestionChoice,
8
+ suggestionKeys,
9
+ suggestionLine
10
+ } from "../chunk-IF6DCCK2.js";
11
+ import {
12
+ SUGGESTION_ARM_DELAY_MS
13
+ } from "../chunk-MAZLORMD.js";
9
14
  import {
10
15
  TERM_COMMANDS,
11
16
  filterCommands,
12
17
  parseCommand
13
- } from "../chunk-5RPHYXND.js";
18
+ } from "../chunk-TWFWLEIP.js";
14
19
  import "../chunk-M44CET5L.js";
15
20
  import {
16
21
  formatEndingChange
@@ -28,6 +33,7 @@ import { useCallback, useState as useState2, useSyncExternalStore } from "react"
28
33
  import { render, useApp, useInput } from "ink";
29
34
  import { PermissionService as PermissionService2 } from "@corenel/harness/guardrail/permission-service";
30
35
  import { STANDARD_POLICY } from "@corenel/harness/guardrail/builtins";
36
+ import { approvalsHooks } from "@corenel/harness/approvals";
31
37
 
32
38
  // src/ink/App.tsx
33
39
  import { useEffect, useState } from "react";
@@ -355,6 +361,15 @@ function contextSnapshotFromState(state, contextWindow, toolCount) {
355
361
  // src/ink/Modal.tsx
356
362
  import { Box as Box5, Text as Text5 } from "ink";
357
363
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
364
+ function SuggestionView({ suggestion }) {
365
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: palette.ember, paddingX: 1, children: [
366
+ /* @__PURE__ */ jsx5(Text5, { wrap: "truncate-end", children: suggestionLine(suggestion) }),
367
+ /* @__PURE__ */ jsxs5(Text5, { color: palette.dim, wrap: "truncate-end", children: [
368
+ suggestionKeys(suggestion),
369
+ " esc ignores"
370
+ ] })
371
+ ] });
372
+ }
358
373
  function capDiffRows(rows, max) {
359
374
  if (rows.length <= max || max <= 0) return max <= 0 ? [] : rows;
360
375
  const kept = rows.slice(0, Math.max(max - 1, 0));
@@ -649,7 +664,8 @@ function App(props) {
649
664
  const roundSeg = state.live ? ` ${glyph.sep} turn ${state.live.turn}` : ` ${glyph.sep} ${props.toolCount} tools`;
650
665
  const turnTokens = tokens(state.turnUsage.promptTokens + state.turnUsage.completionTokens);
651
666
  const totalTokens = tokens(state.usage.promptTokens + state.usage.completionTokens);
652
- const tokenSeg = ` ${glyph.sep} ${turnTokens} turn ${glyph.sep} ${totalTokens} total`;
667
+ const ctxSeg = state.sentTokens ? `${tokens(state.sentTokens)} ctx ${glyph.sep} ` : "";
668
+ const tokenSeg = ` ${glyph.sep} ${ctxSeg}${turnTokens} turn ${glyph.sep} ${totalTokens} total`;
653
669
  const costSeg = state.costUsd > 0 ? ` ${glyph.sep} ${usd(state.costUsd)}` : "";
654
670
  const escSeg = busy ? ` ${glyph.sep} esc stops` : "";
655
671
  const queuedSeg = state.queued.length ? ` ${glyph.sep} ${state.queued.length} queued` : "";
@@ -661,7 +677,7 @@ function App(props) {
661
677
  !modalOpen && state.live?.tools.map((t) => /* @__PURE__ */ jsx8(LiveToolRow, { tool: t }, t.callId)),
662
678
  !modalOpen && state.live?.streaming ? /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.soft, children: state.live.streaming }) }) : null,
663
679
  !modalOpen ? /* @__PURE__ */ jsx8(TodoBlock, { todos: state.todos }) : null,
664
- state.modal ? /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: state.modal.kind === "mcp" ? /* @__PURE__ */ jsx8(McpOverlay, { modal: state.modal, rows }) : state.modal.kind === "help" ? /* @__PURE__ */ jsx8(HelpOverlay, { rows }) : state.modal.kind === "context" ? /* @__PURE__ */ jsx8(ContextOverlay, { snapshot: contextSnapshotFromState(state, props.contextWindow ?? null, props.toolCount), rows }) : state.modal.kind === "permission" || state.modal.kind === "user" ? /* @__PURE__ */ jsx8(ModalView, { modal: state.modal, rows }) : null }) : null,
680
+ state.modal ? /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: state.modal.kind === "mcp" ? /* @__PURE__ */ jsx8(McpOverlay, { modal: state.modal, rows }) : state.modal.kind === "help" ? /* @__PURE__ */ jsx8(HelpOverlay, { rows }) : state.modal.kind === "context" ? /* @__PURE__ */ jsx8(ContextOverlay, { snapshot: contextSnapshotFromState(state, props.contextWindow ?? null, props.toolCount), rows }) : state.modal.kind === "suggestion" ? /* @__PURE__ */ jsx8(SuggestionView, { suggestion: state.modal.suggestion }) : state.modal.kind === "permission" || state.modal.kind === "user" ? /* @__PURE__ */ jsx8(ModalView, { modal: state.modal, rows }) : null }) : null,
665
681
  paletteItems.length && !modalOpen ? /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(PaletteView, { items: paletteItems, selected: paletteSelected }) }) : null,
666
682
  state.pendingSkill && !modalOpen ? /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
667
683
  /* @__PURE__ */ jsxs8(Text8, { color: palette.ember, children: [
@@ -880,6 +896,34 @@ function Root({ session, deps }) {
880
896
  }
881
897
  return;
882
898
  }
899
+ if (state.modal.kind === "suggestion") {
900
+ if (key.ctrl && input === "c") {
901
+ if (state.status !== "idle" && !sawSigint) {
902
+ session.abort();
903
+ setSawSigint(true);
904
+ return;
905
+ }
906
+ exit();
907
+ return;
908
+ }
909
+ if (key.escape) {
910
+ session.dismissApprovalSuggestion();
911
+ if (state.status !== "idle") session.abort();
912
+ return;
913
+ }
914
+ if (Date.now() - state.modal.openedAt < SUGGESTION_ARM_DELAY_MS) return;
915
+ if (key.return) {
916
+ if (state.modal.armedChoice) void session.respondApprovalSuggestion(state.modal.armedChoice);
917
+ return;
918
+ }
919
+ const choice = parseSuggestionChoice(state.modal.suggestion, input);
920
+ if (choice === "workspace" || choice === "global") {
921
+ session.armApprovalSuggestion(choice);
922
+ return;
923
+ }
924
+ if (choice) void session.respondApprovalSuggestion(choice);
925
+ return;
926
+ }
883
927
  if (key.escape) {
884
928
  session.answer(state.modal.kind === "permission" ? "deny" : null);
885
929
  return;
@@ -1003,13 +1047,29 @@ function Root({ session, deps }) {
1003
1047
  }
1004
1048
  );
1005
1049
  }
1006
- async function runTui(deps) {
1007
- const session = new TermSession(deps);
1008
- if (deps.resume) await session.resume(deps.resume.id);
1050
+ function tuiPermission(session, deps) {
1051
+ const approvals = deps.approvals;
1052
+ const hooks = approvals ? approvalsHooks(approvals, {
1053
+ standing: true,
1054
+ context: () => {
1055
+ const id = session.getSnapshot().session?.id;
1056
+ return { host: "tui", surface: "chat", ...deps.approvalsContext ?? {}, ...id ? { sessionId: id } : {} };
1057
+ },
1058
+ onSuggestion: (s) => session.offerApprovalSuggestion(s)
1059
+ }) : null;
1009
1060
  const permission = new PermissionService2({
1010
1061
  policy: deps.policy ?? STANDARD_POLICY,
1011
- prompt: { ask: (req) => session.askPermission(req) }
1062
+ prompt: { ask: (req) => session.askPermission(req) },
1063
+ ...hooks?.standing ? { standing: hooks.standing } : {},
1064
+ ...hooks ? { onDecision: hooks.onDecision } : {}
1012
1065
  });
1066
+ return { permission, settled: hooks ? hooks.settled : async () => void 0 };
1067
+ }
1068
+ async function runTui(deps) {
1069
+ const approvals = deps.approvals;
1070
+ const session = new TermSession(approvals ? { ...deps, saveApprovalChoice: (s, c) => approvals.respond(s, c) } : deps);
1071
+ if (deps.resume) await session.resume(deps.resume.id);
1072
+ const { permission, settled } = tuiPermission(session, deps);
1013
1073
  session.attachPermission(permission);
1014
1074
  const bannerOpts = {
1015
1075
  policy: deps.policy ?? STANDARD_POLICY,
@@ -1038,9 +1098,12 @@ async function runTui(deps) {
1038
1098
  exitOnCtrlC: false
1039
1099
  });
1040
1100
  await app.waitUntilExit();
1101
+ await settled();
1102
+ await approvals?.flush().catch(() => void 0);
1041
1103
  return 0;
1042
1104
  }
1043
1105
  export {
1044
1106
  Root,
1045
- runTui
1107
+ runTui,
1108
+ tuiPermission
1046
1109
  };
package/dist/session.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
2
2
  import type OpenAI from 'openai';
3
- import type { AgentEvent, AgentTool, AskAnswers, AskQuestion, CompressionConfig, PermissionDecision, Policy, ToolContext } from '@corenel/protocol';
3
+ import type { AgentEvent, AgentTool, ApprovalSuggestion, AskAnswers, AskQuestion, CompressionConfig, PermissionDecision, Policy, PromptAnswer, SuggestionChoice, ToolContext } from '@corenel/protocol';
4
4
  import { type RunAgentArgs, type RunAgentResult } from '@corenel/harness/core/loop';
5
+ import type { SkillEntry } from '@corenel/harness/tools/skillTool';
5
6
  import { type ModelRates } from '@corenel/harness/core/pricing';
6
7
  import type { PermissionService } from '@corenel/harness/guardrail/permission-service';
7
8
  import { type CommittedItem, type McpServerView, type PaletteEntry, type TuiState } from './state';
@@ -9,6 +10,7 @@ import { type ContextSnapshot } from './contextText';
9
10
  import { type ReadExisting } from './writePreview';
10
11
  import { type SessionPersistence } from './persist';
11
12
  import type { PolicySource } from './policySource';
13
+ export { parseSuggestionChoice, suggestionKeys, suggestionLine, suggestionOutcome } from './approvalText';
12
14
  /** The system prompt, as something that can be RE-DERIVED rather than fixed at
13
15
  * construction. A bare string is fine for a host that never changes it (`corenel
14
16
  * run`, tests); a thunk is what makes `/mode`/`/persona` real -- each of those
@@ -24,6 +26,10 @@ export interface TermSessionDeps {
24
26
  cwd: string;
25
27
  model: string;
26
28
  system?: SystemSource;
29
+ /** The enabled skills, read fresh each turn so one enabled mid-session is
30
+ * offered on the next. The loop turns them into a system-prompt index plus
31
+ * `use_skill` (harness tools/skillTool.ts). Absent = no skills. */
32
+ skills?: () => Promise<SkillEntry[]>;
27
33
  client: OpenAI;
28
34
  tools: AgentTool[];
29
35
  /** Per-1M-token rates for `model`, or null when nothing prices it -- used to
@@ -162,6 +168,9 @@ export interface TermSessionDeps {
162
168
  * `/mcp login` registers afresh. See the CLI's `McpAdmin.forget` for why
163
169
  * this is always a local write. */
164
170
  forgetMcpServer?: (name: string) => Promise<void>;
171
+ /** Persist the user's answer to an approval suggestion (plan 2). Absent: the
172
+ * session never shows one. Supplied by the host from its approvals service. */
173
+ saveApprovalChoice?: (s: ApprovalSuggestion, choice: SuggestionChoice) => Promise<void>;
165
174
  }
166
175
  /** Deltas arrive per token; re-rendering React that often thrashes for output
167
176
  * no eye can follow. They coalesce on this interval instead. */
@@ -210,6 +219,12 @@ export declare class TermSession {
210
219
  private turnId;
211
220
  private activeTurn;
212
221
  private pending;
222
+ /** The tool name a `pending` permission ask is FOR -- set only by
223
+ * `askPermission`, never by `askUser` (a question is not tied to one tool).
224
+ * Consumed once by `resolvePending` to decide whether a denied ask should
225
+ * drop a held suggestion for the same tool (final review M3). */
226
+ private pendingAskTool;
227
+ private heldSuggestion;
213
228
  private draining;
214
229
  private historyGen;
215
230
  private settling;
@@ -411,14 +426,18 @@ export declare class TermSession {
411
426
  openMcpManager(): Promise<void>;
412
427
  /** esc, or any other reason the overlay should close -- a no-op unless the
413
428
  * manager is actually the modal open right now, so it can never steal a
414
- * permission or question modal's close. */
429
+ * permission or question modal's close. Restores a held suggestion (final
430
+ * review M3) rather than just clearing the modal -- otherwise an offer held
431
+ * behind this overlay came back only when some LATER, unrelated permission
432
+ * ask happened to resolve. */
415
433
  closeMcpManager(): void;
416
434
  /** `/help` with no argument, from the Ink face only -- see the module doc
417
435
  * above. */
418
436
  openHelp(): void;
419
437
  /** esc, or any other reason the overlay should close -- a no-op unless the
420
438
  * help overlay is actually the modal open right now, so it can never steal
421
- * a permission, question, or MCP modal's close. */
439
+ * a permission, question, or MCP modal's close. Restores a held suggestion
440
+ * (final review M3) -- see closeMcpManager's doc. */
422
441
  closeHelp(): void;
423
442
  /** The data `formatContext` (contextText.ts) needs, assembled from
424
443
  * `TuiState`'s own accumulators and the two host-supplied static facts
@@ -433,7 +452,9 @@ export declare class TermSession {
433
452
  openContext(): void;
434
453
  /** esc, or any other reason the context overlay should close -- a no-op
435
454
  * unless the context overlay is actually the modal open right now, so it
436
- * can never steal a permission, question, help, or MCP modal's close. */
455
+ * can never steal a permission, question, help, or MCP modal's close.
456
+ * Restores a held suggestion (final review M3) -- see closeMcpManager's
457
+ * doc. */
437
458
  closeContext(): void;
438
459
  /** Up/down inside the overlay -- wraps, and does nothing with zero rows. */
439
460
  moveMcpSelection(delta: number): void;
@@ -503,7 +524,7 @@ export declare class TermSession {
503
524
  askPermission(req: {
504
525
  tool: string;
505
526
  input: unknown;
506
- }): Promise<PermissionDecision>;
527
+ }): Promise<PermissionDecision | PromptAnswer>;
507
528
  askUser(questions: AskQuestion[]): Promise<AskAnswers | null>;
508
529
  /** The view's answer to whichever modal is open. */
509
530
  answer(value: PermissionDecision | AskAnswers | null): void;
@@ -515,5 +536,24 @@ export declare class TermSession {
515
536
  * outcome that `askUserTool` (packages/harness/tools/builtins.ts) checks for. */
516
537
  private forceClosePending;
517
538
  private resolvePending;
539
+ /** Restore whatever suggestion is held (if any) as the visible modal,
540
+ * dropping it instead if `dropForTool` names the tool it is for. Shared by
541
+ * every path that can uncover a held offer: answering a permission/question
542
+ * ask (`resolvePending`), and closing the help/MCP/context overlays -- all
543
+ * of which used to just clear the modal, silently losing a held offer until
544
+ * some LATER, unrelated permission answer happened to surface it (final
545
+ * review M3). */
546
+ private restoreHeldSuggestion;
547
+ /** Offer a standing approval. Shown now if nothing is open, otherwise held
548
+ * until the open prompt is answered; a newer offer replaces a held one. */
549
+ offerApprovalSuggestion(s: ApprovalSuggestion): void;
550
+ /** Arm a widening choice (`workspace` / `global`) without granting it yet --
551
+ * only a following Enter (`respondApprovalSuggestion`) does that. See
552
+ * ApprovalSuggestionView's doc (final review I1). A no-op if the suggestion
553
+ * modal is not open. */
554
+ armApprovalSuggestion(choice: SuggestionChoice): void;
555
+ respondApprovalSuggestion(choice: SuggestionChoice): Promise<void>;
556
+ /** Escape: ignore the offer. Writes nothing (plan Task 5: ignoring is not a choice). */
557
+ dismissApprovalSuggestion(): void;
518
558
  }
519
559
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/dist/session.js CHANGED
@@ -1,10 +1,14 @@
1
1
  import {
2
2
  DELTA_FLUSH_MS,
3
3
  TOOL_DELTA_CAP,
4
- TermSession
5
- } from "./chunk-HUVRQX53.js";
6
- import "./chunk-2MGDL3I4.js";
7
- import "./chunk-5RPHYXND.js";
4
+ TermSession,
5
+ parseSuggestionChoice,
6
+ suggestionKeys,
7
+ suggestionLine,
8
+ suggestionOutcome
9
+ } from "./chunk-IF6DCCK2.js";
10
+ import "./chunk-MAZLORMD.js";
11
+ import "./chunk-TWFWLEIP.js";
8
12
  import "./chunk-M44CET5L.js";
9
13
  import "./chunk-I44FC7PE.js";
10
14
  import "./chunk-TYP4MMO7.js";
@@ -13,5 +17,9 @@ import "./chunk-CB5RFNB4.js";
13
17
  export {
14
18
  DELTA_FLUSH_MS,
15
19
  TOOL_DELTA_CAP,
16
- TermSession
20
+ TermSession,
21
+ parseSuggestionChoice,
22
+ suggestionKeys,
23
+ suggestionLine,
24
+ suggestionOutcome
17
25
  };
package/dist/state.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AskQuestion, Usage } from '@corenel/protocol';
1
+ import type { ApprovalSuggestion, AskQuestion, SuggestionChoice, Usage } from '@corenel/protocol';
2
2
  import type { WritePreview } from './writePreview';
3
3
  /** One selectable id for a host-supplied capability (`/mode`, `/persona`,
4
4
  * `/skill`, `/strategy`) -- a mode/persona/skill/strategy as DATA, never as a
@@ -129,7 +129,31 @@ export interface HelpView {
129
129
  export interface ContextView {
130
130
  kind: 'context';
131
131
  }
132
- export type Modal = PermissionAsk | UserAsk | McpManager | HelpView | ContextView;
132
+ /** A standing-approval offer (plan 2). NOT a pending ask: nothing waits on it,
133
+ * the turn keeps running, and Escape ignores it without writing anything.
134
+ *
135
+ * `openedAt` and `armedChoice` exist for one reason (final review I1): a
136
+ * standing-approval grant must be a deliberate keystroke, never a keystroke
137
+ * typed for something else. `openedAt` is the timestamp the offer became
138
+ * VISIBLE (set again each time a held offer is restored, not just on the
139
+ * first offer) -- a face ignores every key for a short arm delay after that,
140
+ * so a burst of type-ahead lands on nothing. `armedChoice` holds a choice
141
+ * that WIDENS access (`workspace` / `global`) once its key is pressed, but
142
+ * does not yet grant it -- only a following Enter does. `not-now` and `never`
143
+ * never widen anything, so they still apply on their own keystroke, without
144
+ * arming or Enter. */
145
+ export interface ApprovalSuggestionView {
146
+ kind: 'suggestion';
147
+ suggestion: ApprovalSuggestion;
148
+ openedAt: number;
149
+ armedChoice: SuggestionChoice | null;
150
+ }
151
+ /** How long a face ignores every key after a suggestion becomes visible
152
+ * (final review I1). Long enough to eat a burst of type-ahead landing right
153
+ * as the offer appears, short enough that a deliberate answer never feels
154
+ * delayed. */
155
+ export declare const SUGGESTION_ARM_DELAY_MS = 400;
156
+ export type Modal = PermissionAsk | UserAsk | McpManager | HelpView | ContextView | ApprovalSuggestionView;
133
157
  export type TodoStatus = 'pending' | 'in_progress' | 'completed' | 'blocked';
134
158
  /** A local mirror of the harness's `todo_write` tool contract (see
135
159
  * packages/harness/tools/todo.ts) — kept local rather than imported so this
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
package/dist/state.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import {
2
+ SUGGESTION_ARM_DELAY_MS,
2
3
  emptyState,
3
4
  parseTodos
4
- } from "./chunk-2MGDL3I4.js";
5
+ } from "./chunk-MAZLORMD.js";
5
6
  export {
7
+ SUGGESTION_ARM_DELAY_MS,
6
8
  emptyState,
7
9
  parseTodos
8
10
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corenel/term",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "description": "Corenel's terminal face — a headless chat controller plus its Ink views. `./session` is ink-free and shared with the CLI's readline fallback; only `./ink` pulls React. dist/ is bundled (see build.mjs), but @corenel/harness and @corenel/protocol stay EXTERNAL to that bundle — they are real runtime dependencies, declared below, so the CLI and term share exactly one harness module instance (see build.mjs for why two instances is a governance hole, not a cosmetic bug).",
6
6
  "exports": {
@@ -46,8 +46,8 @@
46
46
  "ink-text-input": "^6.0.0",
47
47
  "openai": "^4.77.0",
48
48
  "react": "^18.3.1",
49
- "@corenel/harness": "0.9.0",
50
- "@corenel/protocol": "0.8.0"
49
+ "@corenel/harness": "0.11.0",
50
+ "@corenel/protocol": "0.10.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "^24.13.1",
@@ -55,11 +55,11 @@
55
55
  "esbuild": "^0.21.5",
56
56
  "ink-testing-library": "^4.0.0",
57
57
  "typescript": "^5.9.3",
58
- "@corenel/tools-node": "0.5.0"
58
+ "@corenel/tools-node": "0.5.1"
59
59
  },
60
60
  "license": "Elastic-2.0",
61
61
  "engines": {
62
- "node": ">=18"
62
+ "node": ">=22"
63
63
  },
64
64
  "files": [
65
65
  "dist",