@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 +1 -1
- package/dist/approvalText.d.ts +6 -0
- package/dist/approvalText.d.ts.map +1 -0
- package/dist/{chunk-HUVRQX53.js → chunk-IF6DCCK2.js} +118 -12
- package/dist/{chunk-2MGDL3I4.js → chunk-MAZLORMD.js} +2 -0
- package/dist/{chunk-5RPHYXND.js → chunk-TWFWLEIP.js} +4 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +1 -1
- package/dist/ink/App.d.ts.map +1 -1
- package/dist/ink/Modal.d.ts +6 -0
- package/dist/ink/Modal.d.ts.map +1 -1
- package/dist/ink/index.d.ts +18 -0
- package/dist/ink/index.d.ts.map +1 -1
- package/dist/ink/index.js +74 -11
- package/dist/session.d.ts +45 -5
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +13 -5
- package/dist/state.d.ts +26 -2
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +3 -1
- package/package.json +5 -5
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
|
|
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-
|
|
4
|
+
} from "./chunk-MAZLORMD.js";
|
|
5
5
|
import {
|
|
6
6
|
formatHelpText,
|
|
7
7
|
isKnownCommandWord,
|
|
8
8
|
parseCommand,
|
|
9
9
|
unknownCommandMessage
|
|
10
|
-
} from "./chunk-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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/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
|
|
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() {
|
package/dist/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"
|
|
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
package/dist/ink/App.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/ink/Modal.d.ts
CHANGED
|
@@ -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;
|
package/dist/ink/Modal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/ink/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
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"}
|
package/dist/ink/index.d.ts
CHANGED
|
@@ -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
|
package/dist/ink/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ink/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsD,MAAM,OAAO,CAAC;
|
|
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
|
-
|
|
8
|
-
|
|
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-
|
|
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
|
|
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
|
-
|
|
1007
|
-
const
|
|
1008
|
-
|
|
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
|
package/dist/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACxM,OAAO,EAAY,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AACvF,OAAO,EAA0B,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG3H,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAuC,KAAK,YAAY,EAAqB,MAAM,gBAAgB,CAAC;AAG3G,OAAO,EAAoC,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE1G;;;;;;;;;wCASwC;AACxC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;wEAEoE;IACpE,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB;;;;;;;;8DAQ0D;IAC1D,KAAK,CAAC,EAAE,MAAM,UAAU,GAAG,IAAI,CAAC;IAChC;;;;;;;;;;gBAUY;IACZ,aAAa,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAMpC;;;;;;;;;;;;qDAYiD;IACjD,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC3C,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC1C;yEACqE;IACrE,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC7C,sEAAsE;IACtE,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC3C;;8EAE0E;IAC1E,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC/F,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC/C;;0DAEsD;IACtD,eAAe,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACnF;;;;;;8EAM0E;IAC1E,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,EAAE,UAAU,CAAC,EAAE,iBAAiB,KAAK,WAAW,CAAC;IACrI,yFAAyF;IACzF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gFAAgF;IAChF,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IACzD;;;;;;;;;;6BAUyB;IACzB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,6EAA6E;IAC7E,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,kEAAkE;IAClE,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChD;;;wEAGoE;IACpE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC;;;iFAG6E;IAC7E,UAAU,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IACxC;;;;;qEAKiE;IACjE,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;2EAKuE;IACvE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;;yDAMqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,YAAY,CAAC;IAQ5B;6EACyE;IACzE,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,gBAAgB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD;;wCAEoC;IACpC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD;mFAC+E;IAC/E,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB,EAAE,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzF;AAED;gEACgE;AAChE,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC;;;;;;;;;mDASmD;AACnD,eAAO,MAAM,cAAc,OAAQ,CAAC;AAiBpC,qBAAa,WAAW;IAkFV,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe;IAjFpD,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC;IAC1B,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,UAAU,CAA8C;IAMhE,OAAO,CAAC,UAAU,CAAM;IACxB;gFAC4E;IAC5E,OAAO,CAAC,qBAAqB,CAAK;IAClC;;;;qFAIiF;IACjF,OAAO,CAAC,aAAa,CAAS;IAC9B;;;;+EAI2E;IAC3E,OAAO,CAAC,UAAU,CAAS;IAK3B,OAAO,CAAC,cAAc,CAAiD;IAEvE,sEAAsE;IACtE,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,MAAM,CAAgC;IAC9C;wEACoE;IACpE,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAkD;IACjE;;;qEAGiE;IACjE,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAS;IAOzB,OAAO,CAAC,UAAU,CAAK;IAOvB,OAAO,CAAC,QAAQ,CAAS;IACzB;;;qEAGiE;IACjE,OAAO,CAAC,UAAU,CAAgC;IAClD;;;2BAGuB;IACvB,OAAO,CAAC,YAAY,CAAoE;IACxF,SAAS,UAAS;IAClB;;;;;kBAKc;IACd,OAAO,CAAC,gBAAgB,CAAuB;gBAEhB,IAAI,EAAE,eAAe;IAIpD,gBAAgB,CAAC,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAE5C,cAAc,IAAI,0BAA0B,EAAE;IAE9C,WAAW,IAAI,QAAQ;IAEvB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKrC;0DACsD;IACtD,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;IAK7C,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAEpC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAI3C;;;;;;;uCAOmC;IACnC,OAAO,CAAC,oBAAoB;IAO5B;;;;6EAIyE;YAC3D,aAAa;IAM3B,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAIrF,6EAA6E;IAC7E,gBAAgB,IAAI,IAAI;IACxB,kBAAkB,IAAI,IAAI;IAE1B,SAAS,CAAC,SAAS,IAAI,IAAI;IAa3B;;;;;;;;;;;;;;2CAcuC;IACvC,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,aAAa;IAOrB;;gCAE4B;IAC5B,SAAS,CAAC,OAAO,IAAI,IAAI;IAazB;;;;;;;;;;;;;+EAa2E;IAC3E,OAAO,CAAC,SAAS;IAIjB;;;;;6BAKyB;IACzB,OAAO,CAAC,MAAM;IAMd,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IAwMhC;;;;;;;wEAOoE;IACpE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IASjC;;;;;;;;;;;;+EAY2E;IACrE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BzC;;;iFAG6E;YAC/D,UAAU;YAUV,UAAU;IAoGxB;;;;;;;;;;;;;oEAagE;YAClD,QAAQ;IAStB;;;;;;;;;;mEAU+D;YACjD,cAAc;IAkB5B;;;;;;;;;;sCAUkC;YACpB,eAAe;YAyBf,eAAe;YAmBf,kBAAkB;IAiBhC;;;;;;;;;;;;;;gFAc4E;YAC9D,WAAW;IASzB;;;;;;;;;;;;mEAY+D;YACjD,aAAa;IAoF3B;mEAC+D;IACzD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrC;;;;;kCAK8B;IAC9B,eAAe,IAAI,IAAI;IAgBvB;gBACY;IACZ,QAAQ,IAAI,IAAI;IAIhB;;;yDAGqD;IACrD,SAAS,IAAI,IAAI;IAkBjB;;;;;qCAKiC;IACjC,eAAe,IAAI,eAAe;IAWlC;;4BAEwB;IACxB,WAAW,IAAI,IAAI;IAInB;;;;cAIU;IACV,YAAY,IAAI,IAAI;IAIpB,4EAA4E;IAC5E,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOrC;4EACwE;IAClE,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IASzC;;;;wEAIoE;IAC9D,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBxC;;;4DAGwD;IAClD,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAS1C;;;qBAGiB;YACH,iBAAiB;IAW/B,+EAA+E;YACjE,OAAO;IAcrB,uEAAuE;IACjE,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8CxC;;iEAE6D;cAC7C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlD;;;;;;;;;mCAS+B;cACf,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,aAAa,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YAgBzF,OAAO;IAyFrB;;;;kEAI8D;YAChD,eAAe;YAOf,KAAK;IAenB;0EACsE;IACtE,KAAK,IAAI,IAAI;IAOb;;;;;;;;;;;cAWU;IACV,aAAa,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,GAAG,YAAY,CAAC;IAkChG,OAAO,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAS7D,oDAAoD;IACpD,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,UAAU,GAAG,IAAI,GAAG,IAAI;IAI3D;;;;;qFAKiF;IACjF,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,cAAc;IAgBtB;;;;;;qBAMiB;IACjB,OAAO,CAAC,qBAAqB;IAW7B;+EAC2E;IAC3E,uBAAuB,CAAC,CAAC,EAAE,kBAAkB,GAAG,IAAI;IAMpD;;;4BAGwB;IACxB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAK/C,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxE,wFAAwF;IACxF,yBAAyB,IAAI,IAAI;CAGlC"}
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
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
|
package/dist/state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/dist/state.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@corenel/term",
|
|
3
|
-
"version": "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.
|
|
50
|
-
"@corenel/protocol": "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.
|
|
58
|
+
"@corenel/tools-node": "0.5.1"
|
|
59
59
|
},
|
|
60
60
|
"license": "Elastic-2.0",
|
|
61
61
|
"engines": {
|
|
62
|
-
"node": ">=
|
|
62
|
+
"node": ">=22"
|
|
63
63
|
},
|
|
64
64
|
"files": [
|
|
65
65
|
"dist",
|