@corenel/term 0.3.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/ContextOverlay.d.ts +2 -1
- package/dist/ink/ContextOverlay.d.ts.map +1 -1
- package/dist/ink/HelpOverlay.d.ts +9 -2
- package/dist/ink/HelpOverlay.d.ts.map +1 -1
- package/dist/ink/McpOverlay.d.ts +2 -7
- package/dist/ink/McpOverlay.d.ts.map +1 -1
- package/dist/ink/Modal.d.ts +11 -2
- 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 +293 -98
- package/dist/ink/overlayBudget.d.ts +27 -0
- package/dist/ink/overlayBudget.d.ts.map +1 -0
- package/dist/session.d.ts +51 -8
- 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;
|
|
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"}
|
|
@@ -8,8 +8,9 @@ import { type ContextSnapshot } from '../contextText';
|
|
|
8
8
|
* so a turn that lands while this is open updates the numbers on the very
|
|
9
9
|
* next frame with no re-fetch and no re-open -- unlike the `/mcp` manager,
|
|
10
10
|
* there is nothing here that needs fetching in the first place. */
|
|
11
|
-
export declare function ContextOverlay({ snapshot }: {
|
|
11
|
+
export declare function ContextOverlay({ snapshot, rows }: {
|
|
12
12
|
snapshot: ContextSnapshot;
|
|
13
|
+
rows?: number;
|
|
13
14
|
}): React.ReactElement;
|
|
14
15
|
/** Build the overlay's data straight off live `TuiState` and the two
|
|
15
16
|
* host-supplied static facts -- exported so App.tsx can assemble it without
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextOverlay.d.ts","sourceRoot":"","sources":["../../src/ink/ContextOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ContextOverlay.d.ts","sourceRoot":"","sources":["../../src/ink/ContextOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AASrE;;;;;;mEAMmE;AACnE,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;IAAE,QAAQ,EAAE,eAAe,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAsBnH;AAED;;yEAEyE;AACzE,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CAS1H"}
|
|
@@ -7,6 +7,13 @@ import React from 'react';
|
|
|
7
7
|
* Rendered FROM `TERM_COMMANDS` -- the same table `parseCommand` dispatches
|
|
8
8
|
* against, the palette filters, and `formatHelpText` renders as text --
|
|
9
9
|
* rather than from a hand-written constant, so this list cannot fall behind
|
|
10
|
-
* the commands it documents.
|
|
11
|
-
|
|
10
|
+
* the commands it documents.
|
|
11
|
+
*
|
|
12
|
+
* `rows` bounds the command list to what the terminal can actually show (see
|
|
13
|
+
* overlayBudget.ts's module doc) -- a full command table is ~18 rows on its
|
|
14
|
+
* own, comfortably taller than a lot of real terminals once the input box and
|
|
15
|
+
* status row are accounted for. */
|
|
16
|
+
export declare function HelpOverlay({ rows }: {
|
|
17
|
+
rows?: number;
|
|
18
|
+
}): React.ReactElement;
|
|
12
19
|
//# sourceMappingURL=HelpOverlay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HelpOverlay.d.ts","sourceRoot":"","sources":["../../src/ink/HelpOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"HelpOverlay.d.ts","sourceRoot":"","sources":["../../src/ink/HelpOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAc1B;;;;;;;;;;;;;mCAamC;AACnC,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAsB3E"}
|
package/dist/ink/McpOverlay.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { McpManager } from '../state';
|
|
3
|
-
|
|
4
|
-
* `TermSession`'s own `/mcp` dispatch (see mcpText.ts's module comment). It
|
|
5
|
-
* holds no server list, connection state, or login state of its own; every
|
|
6
|
-
* field it renders comes straight off `modal`, which the session owns and
|
|
7
|
-
* refreshes after a mutation, the same way the text `/mcp` commands already
|
|
8
|
-
* do. See ink/index.tsx's `useInput` for what a/x/l/esc/arrows actually run. */
|
|
9
|
-
export declare function McpOverlay({ modal }: {
|
|
3
|
+
export declare function McpOverlay({ modal, rows }: {
|
|
10
4
|
modal: McpManager;
|
|
5
|
+
rows?: number;
|
|
11
6
|
}): React.ReactElement;
|
|
12
7
|
//# sourceMappingURL=McpOverlay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpOverlay.d.ts","sourceRoot":"","sources":["../../src/ink/McpOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"McpOverlay.d.ts","sourceRoot":"","sources":["../../src/ink/McpOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAwB3C,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAqFpG"}
|
package/dist/ink/Modal.d.ts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
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;
|
|
6
12
|
* a help view, Task 10) before this is ever called, so this stays narrowed
|
|
7
|
-
* to the two `Modal` variants it actually knows how to draw.
|
|
8
|
-
|
|
13
|
+
* to the two `Modal` variants it actually knows how to draw. `rows` bounds
|
|
14
|
+
* both the diff preview and the options list to the terminal's actual
|
|
15
|
+
* height (see overlayBudget.ts's module doc). */
|
|
16
|
+
export declare function ModalView({ modal, rows }: {
|
|
9
17
|
modal: PermissionAsk | UserAsk;
|
|
18
|
+
rows?: number;
|
|
10
19
|
}): React.ReactElement;
|
|
11
20
|
//# sourceMappingURL=Modal.d.ts.map
|
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"}
|