@corenel/term 0.1.0 → 0.2.1
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/LICENSE +93 -0
- package/dist/chunk-2D7G4YW2.js +97 -0
- package/dist/chunk-CB5RFNB4.js +33 -0
- package/dist/chunk-F4ENQXQQ.js +909 -0
- package/dist/chunk-I44FC7PE.js +142 -0
- package/dist/chunk-IK4ZANNW.js +95 -0
- package/dist/chunk-M44CET5L.js +40 -0
- package/dist/chunk-OSJFMQCW.js +44 -0
- package/dist/{chunk-R6AXTD55.js → chunk-VTJEWHM3.js} +19 -1
- package/dist/commands.d.ts +14 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +1 -1
- package/dist/describe.d.ts +23 -0
- package/dist/describe.d.ts.map +1 -1
- package/dist/describe.js +6 -1
- package/dist/diff.d.ts +100 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +18 -0
- package/dist/ink/App.d.ts +12 -0
- package/dist/ink/App.d.ts.map +1 -1
- package/dist/ink/Modal.d.ts.map +1 -1
- package/dist/ink/TodoBlock.d.ts +10 -0
- package/dist/ink/TodoBlock.d.ts.map +1 -0
- package/dist/ink/banner.d.ts +36 -0
- package/dist/ink/banner.d.ts.map +1 -0
- package/dist/ink/index.d.ts.map +1 -1
- package/dist/ink/index.js +300 -140
- package/dist/ink/items.d.ts.map +1 -1
- package/dist/ink/scroll.d.ts +14 -2
- package/dist/ink/scroll.d.ts.map +1 -1
- package/dist/ink/status.d.ts.map +1 -1
- package/dist/ink/theme.d.ts +9 -0
- package/dist/ink/theme.d.ts.map +1 -1
- package/dist/ink/todos.d.ts +20 -0
- package/dist/ink/todos.d.ts.map +1 -0
- package/dist/markdown.d.ts.map +1 -1
- package/dist/persist.d.ts +27 -4
- package/dist/persist.d.ts.map +1 -1
- package/dist/persist.js +3 -1
- package/dist/policySource.d.ts +26 -0
- package/dist/policySource.d.ts.map +1 -0
- package/dist/policySource.js +8 -0
- package/dist/session.d.ts +199 -13
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +10 -5
- package/dist/state.d.ts +84 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +5 -3
- package/dist/writePreview.d.ts +58 -0
- package/dist/writePreview.d.ts.map +1 -0
- package/dist/writePreview.js +9 -0
- package/package.json +19 -6
- package/dist/chunk-47IH6X5H.js +0 -20
- package/dist/chunk-HAQGHLW6.js +0 -235
- package/dist/chunk-HYWLODZT.js +0 -1230
- package/dist/chunk-TCVDVYMF.js +0 -40
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type NamespacedTool } from '@corenel/harness/tools/namespaces';
|
|
2
|
+
import type { Policy } from '@corenel/protocol';
|
|
3
|
+
import { type PolicySource } from '../policySource';
|
|
4
|
+
/** The posture phrase, derived from the same `resolveLevel()` the loop's own
|
|
5
|
+
* `PermissionService` calls before every tool check. Covers the four shapes
|
|
6
|
+
* the brief names, plus one more (shell allowed, writes denied outright) it
|
|
7
|
+
* asked to have added rather than left wrong. */
|
|
8
|
+
export declare function posture(policy: Policy): string;
|
|
9
|
+
export interface BannerOptions {
|
|
10
|
+
policy: Policy;
|
|
11
|
+
source: PolicySource;
|
|
12
|
+
tools: readonly NamespacedTool[];
|
|
13
|
+
cwd: string;
|
|
14
|
+
/** Terminal width. Missing/non-positive falls back to `DEFAULT_COLUMNS`. */
|
|
15
|
+
columns?: number;
|
|
16
|
+
/** Suppression gate (brief rule 5): nothing prints when this isn't `true`. */
|
|
17
|
+
isTTY: boolean;
|
|
18
|
+
}
|
|
19
|
+
/** Pure builder. `''` means "print nothing" -- the caller (`writeBanner`)
|
|
20
|
+
* writes only when this is non-empty. */
|
|
21
|
+
export declare function buildBanner(opts: BannerOptions): string;
|
|
22
|
+
export interface BannerOut {
|
|
23
|
+
readonly isTTY?: boolean;
|
|
24
|
+
readonly columns?: number;
|
|
25
|
+
write(chunk: string): void;
|
|
26
|
+
}
|
|
27
|
+
/** How many terminal lines `writeBanner` would emit for these options -- 0 when
|
|
28
|
+
* it would print nothing. `runTui` needs this BEFORE it primes the scroll, so
|
|
29
|
+
* the prime can reserve room for the banner instead of scrolling it away; see
|
|
30
|
+
* `primeScroll`'s `reserve` option. */
|
|
31
|
+
export declare function bannerHeight(out: BannerOut, opts: Omit<BannerOptions, 'isTTY' | 'columns'>): number;
|
|
32
|
+
/** The only thing here that touches a real stream -- called once, straight to
|
|
33
|
+
* stdout, AFTER `primeScroll` has reserved room for it (see `runTui` in
|
|
34
|
+
* `ink/index.tsx`, and `bannerHeight` above). */
|
|
35
|
+
export declare function writeBanner(out: BannerOut, opts: Omit<BannerOptions, 'isTTY' | 'columns'>): void;
|
|
36
|
+
//# sourceMappingURL=banner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/ink/banner.ts"],"names":[],"mappings":"AAcA,OAAO,EAAsC,KAAK,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC5G,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmCjE;;;iDAGiD;AACjD,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAU9C;AAwBD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;yCACyC;AACzC,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAuCvD;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;uCAGuC;AACvC,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG,MAAM,CAInG;AAED;;iDAEiD;AACjD,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG,IAAI,CAGhG"}
|
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;AAK3E,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
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,CA8JnG;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAyD3D"}
|
package/dist/ink/index.js
CHANGED
|
@@ -1,108 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
|
-
STANDARD_POLICY,
|
|
3
2
|
TermSession,
|
|
4
|
-
matchesAnyGlob,
|
|
5
3
|
parseMarkdown
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-F4ENQXQQ.js";
|
|
5
|
+
import "../chunk-OSJFMQCW.js";
|
|
8
6
|
import {
|
|
9
|
-
filterCommands
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import "../chunk-
|
|
7
|
+
filterCommands,
|
|
8
|
+
parseCommand
|
|
9
|
+
} from "../chunk-VTJEWHM3.js";
|
|
10
|
+
import "../chunk-M44CET5L.js";
|
|
11
|
+
import {
|
|
12
|
+
formatEndingChange
|
|
13
|
+
} from "../chunk-I44FC7PE.js";
|
|
14
|
+
import "../chunk-IK4ZANNW.js";
|
|
15
|
+
import {
|
|
16
|
+
formatOrd
|
|
17
|
+
} from "../chunk-2D7G4YW2.js";
|
|
18
|
+
import {
|
|
19
|
+
sourceLabel
|
|
20
|
+
} from "../chunk-CB5RFNB4.js";
|
|
13
21
|
|
|
14
22
|
// src/ink/index.tsx
|
|
15
23
|
import { useCallback, useState as useState2, useSyncExternalStore } from "react";
|
|
16
24
|
import { render, useApp, useInput } from "ink";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
var LEVEL_RANK = { allow: 0, ask: 1, deny: 2 };
|
|
20
|
-
function subjectMatches(tool, glob) {
|
|
21
|
-
if (tool.address && matchesAnyGlob(tool.address, [glob])) return true;
|
|
22
|
-
return matchesAnyGlob(tool.name, [glob]);
|
|
23
|
-
}
|
|
24
|
-
function specificity(glob) {
|
|
25
|
-
const literal = glob.replace(/\*/g, "").length;
|
|
26
|
-
return (glob.includes("*") ? 0 : 1e4) + literal;
|
|
27
|
-
}
|
|
28
|
-
function matchLevel(tool, rules) {
|
|
29
|
-
let best;
|
|
30
|
-
let bestScore = -1;
|
|
31
|
-
for (const [glob, level] of Object.entries(rules)) {
|
|
32
|
-
if (!subjectMatches(tool, glob)) continue;
|
|
33
|
-
const score = specificity(glob);
|
|
34
|
-
if (score > bestScore) {
|
|
35
|
-
bestScore = score;
|
|
36
|
-
best = level;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return best;
|
|
40
|
-
}
|
|
41
|
-
function mostRestrictive(a, b) {
|
|
42
|
-
return LEVEL_RANK[a] >= LEVEL_RANK[b] ? a : b;
|
|
43
|
-
}
|
|
44
|
-
var PermissionService = class {
|
|
45
|
-
policy;
|
|
46
|
-
prompt;
|
|
47
|
-
defaultForReadOnly;
|
|
48
|
-
defaultForMutating;
|
|
49
|
-
ceiling;
|
|
50
|
-
sessionAllow = /* @__PURE__ */ new Set();
|
|
51
|
-
constructor(opts) {
|
|
52
|
-
this.policy = opts.policy;
|
|
53
|
-
if (opts.prompt) this.prompt = opts.prompt;
|
|
54
|
-
this.defaultForReadOnly = opts.defaultForReadOnly ?? "allow";
|
|
55
|
-
this.defaultForMutating = opts.defaultForMutating ?? "ask";
|
|
56
|
-
if (opts.ceiling) this.ceiling = opts.ceiling;
|
|
57
|
-
}
|
|
58
|
-
/** Pre-approve a tool-name glob for the rest of the session (an "ask" becomes "allow"). */
|
|
59
|
-
preApprove(toolGlob) {
|
|
60
|
-
this.sessionAllow.add(toolGlob);
|
|
61
|
-
}
|
|
62
|
-
reset() {
|
|
63
|
-
this.sessionAllow.clear();
|
|
64
|
-
}
|
|
65
|
-
async check(tool, input) {
|
|
66
|
-
const level = this.resolveLevel(tool);
|
|
67
|
-
return this.decide(level, tool.name, input);
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Resolve the effective level. Base precedence (highest first):
|
|
71
|
-
* policy.permissions glob > tool.permission > mutates heuristic > policy.defaultPermission.
|
|
72
|
-
* Then the ceiling clamps to the more restrictive of base and ceiling.
|
|
73
|
-
*/
|
|
74
|
-
resolveLevel(tool) {
|
|
75
|
-
return mostRestrictive(this.resolveBaseLevel(tool), this.resolveCeilingLevel(tool));
|
|
76
|
-
}
|
|
77
|
-
resolveBaseLevel(tool) {
|
|
78
|
-
const matched = this.policy.permissions && matchLevel(tool, this.policy.permissions);
|
|
79
|
-
if (matched) return matched;
|
|
80
|
-
if (tool.mutates && this.policy.mutatingDefault) return this.policy.mutatingDefault;
|
|
81
|
-
if (tool.permission) return tool.permission;
|
|
82
|
-
if (this.policy.defaultPermission) return this.policy.defaultPermission;
|
|
83
|
-
if (tool.mutates) return this.defaultForMutating;
|
|
84
|
-
return this.defaultForReadOnly;
|
|
85
|
-
}
|
|
86
|
-
resolveCeilingLevel(tool) {
|
|
87
|
-
const c = this.ceiling;
|
|
88
|
-
if (!c) return "allow";
|
|
89
|
-
const matched = c.overrides && matchLevel(tool, c.overrides);
|
|
90
|
-
if (matched) return matched;
|
|
91
|
-
return c.defaultLevel ?? "allow";
|
|
92
|
-
}
|
|
93
|
-
async decide(level, name, input) {
|
|
94
|
-
if (level === "allow") return "allow";
|
|
95
|
-
if (level === "deny") return "deny";
|
|
96
|
-
if (this.sessionAllow.size && matchesAnyGlob(name, [...this.sessionAllow])) return "allow";
|
|
97
|
-
if (!this.prompt) return "deny";
|
|
98
|
-
return this.prompt.ask({ tool: name, input });
|
|
99
|
-
}
|
|
100
|
-
};
|
|
25
|
+
import { PermissionService as PermissionService2 } from "@corenel/harness/guardrail/permission-service";
|
|
26
|
+
import { STANDARD_POLICY } from "@corenel/harness/guardrail/builtins";
|
|
101
27
|
|
|
102
28
|
// src/ink/App.tsx
|
|
103
29
|
import { useEffect, useState } from "react";
|
|
104
30
|
import { homedir } from "node:os";
|
|
105
|
-
import { Box as
|
|
31
|
+
import { Box as Box5, Static, Text as Text5, useStdout } from "ink";
|
|
106
32
|
import TextInput from "ink-text-input";
|
|
107
33
|
|
|
108
34
|
// src/ink/items.tsx
|
|
@@ -126,7 +52,16 @@ var glyph = {
|
|
|
126
52
|
ok: "\u2713",
|
|
127
53
|
fail: "\u2717",
|
|
128
54
|
bar: "\u2502",
|
|
129
|
-
sep: "\xB7"
|
|
55
|
+
sep: "\xB7",
|
|
56
|
+
/** The in-progress marker on a todo row -- the only status among
|
|
57
|
+
* pending/in_progress/completed/blocked without an existing glyph above. */
|
|
58
|
+
active: "\u25B8",
|
|
59
|
+
/** A restored tool row's outcome marker: a resumed conversation has no
|
|
60
|
+
* recorded success/failure for it (see persist.ts), so it must read as
|
|
61
|
+
* NEITHER `ok` nor `fail` -- a plain dash, not `sep`, which is this same
|
|
62
|
+
* row's own leading bullet a few columns to the left and would read as a
|
|
63
|
+
* second bullet rather than a status. */
|
|
64
|
+
unknown: "\u2013"
|
|
130
65
|
};
|
|
131
66
|
function tokens(n) {
|
|
132
67
|
return n >= 1e3 ? `${(n / 1e3).toFixed(1)}k` : `${n}`;
|
|
@@ -145,7 +80,7 @@ function CommittedRow({ item }) {
|
|
|
145
80
|
/* @__PURE__ */ jsx(Text, { bold: true, children: item.text })
|
|
146
81
|
] });
|
|
147
82
|
case "assistant":
|
|
148
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: parseMarkdown(item.text).map((b, i) => /* @__PURE__ */ jsx(MdLine, { block: b }, i)) });
|
|
83
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: item.leadingBlank ? 1 : 0, children: parseMarkdown(item.text).map((b, i) => /* @__PURE__ */ jsx(MdLine, { block: b }, i)) });
|
|
149
84
|
case "tool":
|
|
150
85
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
151
86
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
@@ -153,18 +88,16 @@ function CommittedRow({ item }) {
|
|
|
153
88
|
glyph.bullet,
|
|
154
89
|
" "
|
|
155
90
|
] }),
|
|
91
|
+
/* @__PURE__ */ jsx(Text, { color: palette.dim, children: formatOrd(item.ord) }),
|
|
156
92
|
/* @__PURE__ */ jsx(Text, { color: palette.tool, children: item.name.padEnd(11) }),
|
|
157
93
|
/* @__PURE__ */ jsx(Text, { color: palette.ink, children: item.subject }),
|
|
158
|
-
/* @__PURE__ */ jsxs(Text, { color: item.isError ? palette.bad : palette.good, children: [
|
|
94
|
+
/* @__PURE__ */ jsxs(Text, { color: item.restored ? palette.dim : item.isError ? palette.bad : palette.good, children: [
|
|
159
95
|
" ",
|
|
160
|
-
item.isError ? glyph.fail : glyph.ok
|
|
96
|
+
item.restored ? glyph.unknown : item.isError ? glyph.fail : glyph.ok
|
|
161
97
|
] }),
|
|
162
98
|
/* @__PURE__ */ jsxs(Text, { color: palette.dim, children: [
|
|
163
99
|
item.durationMs !== void 0 ? ` ${(item.durationMs / 1e3).toFixed(1)}s` : "",
|
|
164
|
-
item.offloadedBytes !== void 0 ? ` offloaded ${Math.round(item.offloadedBytes / 1024)} KB` : ""
|
|
165
|
-
" ",
|
|
166
|
-
"#",
|
|
167
|
-
item.ord
|
|
100
|
+
item.offloadedBytes !== void 0 ? ` offloaded ${Math.round(item.offloadedBytes / 1024)} KB` : ""
|
|
168
101
|
] })
|
|
169
102
|
] }),
|
|
170
103
|
item.preview.map((line, i) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
@@ -173,7 +106,7 @@ function CommittedRow({ item }) {
|
|
|
173
106
|
glyph.bar,
|
|
174
107
|
" "
|
|
175
108
|
] }),
|
|
176
|
-
/* @__PURE__ */ jsx(Text, { color: item.isError ? palette.bad : palette.soft, children: line })
|
|
109
|
+
/* @__PURE__ */ jsx(Text, { color: !item.restored && item.isError ? palette.bad : palette.soft, children: line })
|
|
177
110
|
] }, i))
|
|
178
111
|
] });
|
|
179
112
|
case "note":
|
|
@@ -213,18 +146,25 @@ function MdLine({ block }) {
|
|
|
213
146
|
return /* @__PURE__ */ jsx(Text, { color: palette.soft, children: block.text });
|
|
214
147
|
}
|
|
215
148
|
}
|
|
149
|
+
function deltaTail(delta, max = 80) {
|
|
150
|
+
const lines = delta.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
151
|
+
const last = lines.at(-1) ?? "";
|
|
152
|
+
return last.length > max ? `\u2026${last.slice(-max)}` : last;
|
|
153
|
+
}
|
|
216
154
|
function LiveToolRow({ tool }) {
|
|
155
|
+
const tail = tool.delta ? deltaTail(tool.delta) : "";
|
|
217
156
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
218
157
|
/* @__PURE__ */ jsxs(Text, { color: palette.amber, children: [
|
|
219
158
|
glyph.bullet,
|
|
220
159
|
" "
|
|
221
160
|
] }),
|
|
161
|
+
/* @__PURE__ */ jsx(Text, { color: palette.dim, children: formatOrd(tool.ord) }),
|
|
222
162
|
/* @__PURE__ */ jsx(Text, { color: palette.tool, children: tool.name.padEnd(11) }),
|
|
223
163
|
/* @__PURE__ */ jsx(Text, { color: palette.ink, children: tool.subject }),
|
|
224
164
|
/* @__PURE__ */ jsxs(Text, { color: palette.dim, children: [
|
|
225
165
|
" ",
|
|
226
|
-
"running\u2026
|
|
227
|
-
|
|
166
|
+
"running\u2026",
|
|
167
|
+
tail ? ` ${tail}` : ""
|
|
228
168
|
] })
|
|
229
169
|
] });
|
|
230
170
|
}
|
|
@@ -232,6 +172,42 @@ function LiveToolRow({ tool }) {
|
|
|
232
172
|
// src/ink/Modal.tsx
|
|
233
173
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
234
174
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
175
|
+
function DiffPreview({ diff }) {
|
|
176
|
+
const contentUnchanged = diff.added === 0 && diff.removed === 0;
|
|
177
|
+
const endingRow = diff.endingChange && /* @__PURE__ */ jsx2(Text2, { color: palette.amber, bold: true, children: formatEndingChange(diff.endingChange, contentUnchanged) });
|
|
178
|
+
const unexplainedRow = diff.unexplainedChange && /* @__PURE__ */ jsx2(Text2, { color: palette.amber, bold: true, children: "the file changes in a way not shown above (e.g. trailing whitespace or encoding)" });
|
|
179
|
+
if (diff.noop) {
|
|
180
|
+
return /* @__PURE__ */ jsx2(Text2, { color: palette.dim, children: "(no change -- new content is identical to what's on disk)" });
|
|
181
|
+
}
|
|
182
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
183
|
+
endingRow,
|
|
184
|
+
unexplainedRow,
|
|
185
|
+
diff.isNewFile && /* @__PURE__ */ jsx2(Text2, { color: palette.dim, children: "(new file)" }),
|
|
186
|
+
diff.rows.map((r, i) => {
|
|
187
|
+
if (r.kind === "skip") {
|
|
188
|
+
const label = r.reason === "changes" ? `\u2026 ${r.count} more changed line${r.count === 1 ? "" : "s"}` : `\u2026 ${r.count} unchanged line${r.count === 1 ? "" : "s"}`;
|
|
189
|
+
return /* @__PURE__ */ jsx2(Text2, { color: palette.dim, children: label }, i);
|
|
190
|
+
}
|
|
191
|
+
return /* @__PURE__ */ jsxs2(
|
|
192
|
+
Text2,
|
|
193
|
+
{
|
|
194
|
+
color: r.kind === "add" ? palette.good : r.kind === "del" ? palette.bad : palette.dim,
|
|
195
|
+
children: [
|
|
196
|
+
r.kind === "add" ? "+ " : r.kind === "del" ? "- " : " ",
|
|
197
|
+
r.text
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
i
|
|
201
|
+
);
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ jsxs2(Text2, { color: palette.dim, children: [
|
|
204
|
+
"+",
|
|
205
|
+
diff.added,
|
|
206
|
+
" \u2212",
|
|
207
|
+
diff.removed
|
|
208
|
+
] })
|
|
209
|
+
] });
|
|
210
|
+
}
|
|
235
211
|
function ModalView({ modal }) {
|
|
236
212
|
if (modal.kind === "permission") {
|
|
237
213
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: palette.warn, paddingX: 1, children: [
|
|
@@ -240,6 +216,7 @@ function ModalView({ modal }) {
|
|
|
240
216
|
" wants to run"
|
|
241
217
|
] }),
|
|
242
218
|
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { bold: true, children: modal.detail }) }),
|
|
219
|
+
modal.diff && /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(DiffPreview, { diff: modal.diff }) }),
|
|
243
220
|
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
244
221
|
/* @__PURE__ */ jsx2(Text2, { color: palette.good, children: "[y]" }),
|
|
245
222
|
/* @__PURE__ */ jsx2(Text2, { color: palette.dim, children: " run it " }),
|
|
@@ -292,6 +269,74 @@ function PaletteView({ items, selected }) {
|
|
|
292
269
|
] });
|
|
293
270
|
}
|
|
294
271
|
|
|
272
|
+
// src/ink/TodoBlock.tsx
|
|
273
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
274
|
+
|
|
275
|
+
// src/ink/todos.ts
|
|
276
|
+
var DEFAULT_TODO_ROW_CAP = 4;
|
|
277
|
+
function visibleTodos(todos, cap = DEFAULT_TODO_ROW_CAP) {
|
|
278
|
+
const total = todos.length;
|
|
279
|
+
const done = todos.filter((t) => t.status === "completed").length;
|
|
280
|
+
const outstanding = todos.filter((t) => t.status !== "completed");
|
|
281
|
+
if (outstanding.length === 0) return null;
|
|
282
|
+
const inProgress = outstanding.filter((t) => t.status === "in_progress");
|
|
283
|
+
const rest = outstanding.filter((t) => t.status !== "in_progress");
|
|
284
|
+
const ordered = [...inProgress, ...rest];
|
|
285
|
+
const header = `todos ${done}/${total} done`;
|
|
286
|
+
const rowCap = Math.max(cap, 0);
|
|
287
|
+
if (ordered.length <= rowCap) {
|
|
288
|
+
return { header, rows: toRows(ordered), overflow: null };
|
|
289
|
+
}
|
|
290
|
+
const shown = Math.max(rowCap - 1, 0);
|
|
291
|
+
const remaining = ordered.length - shown;
|
|
292
|
+
return {
|
|
293
|
+
header,
|
|
294
|
+
rows: toRows(ordered.slice(0, shown)),
|
|
295
|
+
overflow: `\u2026 ${remaining} more`
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
function toRows(items) {
|
|
299
|
+
return items.map((t) => ({ id: t.id, title: t.title, status: t.status }));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// src/ink/TodoBlock.tsx
|
|
303
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
304
|
+
function marker(status) {
|
|
305
|
+
switch (status) {
|
|
306
|
+
case "in_progress":
|
|
307
|
+
return { char: glyph.active, color: palette.amber };
|
|
308
|
+
case "completed":
|
|
309
|
+
return { char: glyph.ok, color: palette.good };
|
|
310
|
+
case "blocked":
|
|
311
|
+
return { char: glyph.fail, color: palette.bad };
|
|
312
|
+
case "pending":
|
|
313
|
+
default:
|
|
314
|
+
return { char: glyph.bullet, color: palette.dim };
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function TodoRowView({ row }) {
|
|
318
|
+
const { char, color } = marker(row.status);
|
|
319
|
+
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
320
|
+
/* @__PURE__ */ jsxs4(Text4, { color, children: [
|
|
321
|
+
char,
|
|
322
|
+
" "
|
|
323
|
+
] }),
|
|
324
|
+
/* @__PURE__ */ jsx4(Text4, { color: row.status === "in_progress" ? palette.ink : palette.soft, children: row.title })
|
|
325
|
+
] });
|
|
326
|
+
}
|
|
327
|
+
function TodoBlock({ todos }) {
|
|
328
|
+
const view = visibleTodos(todos);
|
|
329
|
+
if (!view) return null;
|
|
330
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
|
|
331
|
+
/* @__PURE__ */ jsx4(Text4, { color: palette.dim, children: view.header }),
|
|
332
|
+
view.rows.map((row) => /* @__PURE__ */ jsx4(TodoRowView, { row }, row.id)),
|
|
333
|
+
view.overflow ? /* @__PURE__ */ jsxs4(Text4, { color: palette.dim, children: [
|
|
334
|
+
" ",
|
|
335
|
+
view.overflow
|
|
336
|
+
] }) : null
|
|
337
|
+
] });
|
|
338
|
+
}
|
|
339
|
+
|
|
295
340
|
// src/ink/status.ts
|
|
296
341
|
var DEFAULT_COLUMNS = 80;
|
|
297
342
|
var MIN_GAP = 2;
|
|
@@ -335,7 +380,7 @@ function fitStatus(left, identity, columns) {
|
|
|
335
380
|
}
|
|
336
381
|
|
|
337
382
|
// src/ink/App.tsx
|
|
338
|
-
import { jsx as
|
|
383
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
339
384
|
function useColumns() {
|
|
340
385
|
const { stdout } = useStdout();
|
|
341
386
|
const [columns, setColumns] = useState(stdout?.columns ?? DEFAULT_COLUMNS);
|
|
@@ -366,28 +411,28 @@ function App(props) {
|
|
|
366
411
|
const shellSeg = !busy ? ` ${glyph.sep} shell ${props.approveAll ? "auto-approved" : "asks first"}` : "";
|
|
367
412
|
const statusLeft = ` ${statusWord}${roundSeg}${tokenSeg}${escSeg}${queuedSeg}${shellSeg}`;
|
|
368
413
|
const { right: statusRight } = fitStatus(statusLeft, { model: props.model, cwd: props.cwd, home: homedir() }, columns);
|
|
369
|
-
return /* @__PURE__ */
|
|
370
|
-
/* @__PURE__ */
|
|
371
|
-
state.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
414
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
415
|
+
/* @__PURE__ */ jsx5(Static, { items: state.committed, children: (item) => /* @__PURE__ */ jsx5(CommittedRow, { item }, item.id) }, `transcript-${state.transcriptGen}`),
|
|
416
|
+
state.live?.tools.map((t) => /* @__PURE__ */ jsx5(LiveToolRow, { tool: t }, t.callId)),
|
|
417
|
+
state.live?.streaming ? /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { color: palette.soft, children: state.live.streaming }) }) : null,
|
|
418
|
+
/* @__PURE__ */ jsx5(TodoBlock, { todos: state.todos }),
|
|
419
|
+
state.modal ? /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(ModalView, { modal: state.modal }) }) : null,
|
|
420
|
+
paletteItems.length && !state.modal ? /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(PaletteView, { items: paletteItems, selected: paletteSelected }) }) : null,
|
|
421
|
+
state.pendingSkill ? /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
422
|
+
/* @__PURE__ */ jsxs5(Text5, { color: palette.ember, children: [
|
|
375
423
|
glyph.sep,
|
|
376
|
-
"
|
|
377
|
-
|
|
378
|
-
"
|
|
379
|
-
] })
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
paletteItems.length && !state.modal ? /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(PaletteView, { items: paletteItems, selected: paletteSelected }) }) : null,
|
|
385
|
-
/* @__PURE__ */ jsxs4(Box4, { borderStyle: "round", borderColor: palette.dim, paddingX: 1, marginTop: 1, children: [
|
|
386
|
-
/* @__PURE__ */ jsxs4(Text4, { color: palette.ember, children: [
|
|
424
|
+
" skill armed: ",
|
|
425
|
+
state.pendingSkill,
|
|
426
|
+
" "
|
|
427
|
+
] }),
|
|
428
|
+
/* @__PURE__ */ jsx5(Text5, { color: palette.dim, children: "-- applies to your next message, then clears" })
|
|
429
|
+
] }) : null,
|
|
430
|
+
/* @__PURE__ */ jsxs5(Box5, { borderStyle: "round", borderColor: palette.dim, paddingX: 1, marginTop: 1, children: [
|
|
431
|
+
/* @__PURE__ */ jsxs5(Text5, { color: palette.ember, children: [
|
|
387
432
|
glyph.prompt,
|
|
388
433
|
" "
|
|
389
434
|
] }),
|
|
390
|
-
/* @__PURE__ */
|
|
435
|
+
/* @__PURE__ */ jsx5(
|
|
391
436
|
TextInput,
|
|
392
437
|
{
|
|
393
438
|
value: props.value,
|
|
@@ -395,24 +440,35 @@ function App(props) {
|
|
|
395
440
|
onSubmit: state.modal ? props.onAnswer : props.onSubmit,
|
|
396
441
|
placeholder: "",
|
|
397
442
|
focus: props.focus
|
|
398
|
-
}
|
|
443
|
+
},
|
|
444
|
+
props.inputKey
|
|
399
445
|
)
|
|
400
446
|
] }),
|
|
401
|
-
/* @__PURE__ */
|
|
402
|
-
|
|
403
|
-
|
|
447
|
+
state.committed.length === 0 ? /* @__PURE__ */ jsx5(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsxs5(Text5, { color: palette.soft, children: [
|
|
448
|
+
"Type a request. ",
|
|
449
|
+
/* @__PURE__ */ jsxs5(Text5, { color: palette.dim, children: [
|
|
450
|
+
"/help for commands ",
|
|
451
|
+
glyph.sep,
|
|
452
|
+
" Ctrl-C stops a turn ",
|
|
453
|
+
glyph.sep,
|
|
454
|
+
" Ctrl-D leaves"
|
|
455
|
+
] })
|
|
456
|
+
] }) }) : null,
|
|
457
|
+
/* @__PURE__ */ jsxs5(Box5, { justifyContent: "space-between", children: [
|
|
458
|
+
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
459
|
+
/* @__PURE__ */ jsxs5(Text5, { color: busy ? palette.amber : palette.dim, children: [
|
|
404
460
|
" ",
|
|
405
461
|
statusWord
|
|
406
462
|
] }),
|
|
407
|
-
/* @__PURE__ */
|
|
463
|
+
/* @__PURE__ */ jsxs5(Text5, { color: palette.dim, children: [
|
|
408
464
|
roundSeg,
|
|
409
465
|
tokenSeg,
|
|
410
466
|
escSeg,
|
|
411
467
|
queuedSeg
|
|
412
468
|
] }),
|
|
413
|
-
!busy ? /* @__PURE__ */
|
|
469
|
+
!busy ? /* @__PURE__ */ jsx5(Text5, { color: props.approveAll ? palette.ember : palette.warn, children: shellSeg }) : null
|
|
414
470
|
] }),
|
|
415
|
-
statusRight ? /* @__PURE__ */
|
|
471
|
+
statusRight ? /* @__PURE__ */ jsx5(Text5, { color: palette.dim, children: statusRight }) : null
|
|
416
472
|
] })
|
|
417
473
|
] });
|
|
418
474
|
}
|
|
@@ -423,12 +479,84 @@ function primeScroll(out, opts) {
|
|
|
423
479
|
if (opts.resuming) return 0;
|
|
424
480
|
const rows = out.rows;
|
|
425
481
|
if (typeof rows !== "number" || !Number.isFinite(rows) || rows <= 0) return 0;
|
|
426
|
-
|
|
427
|
-
|
|
482
|
+
const reserve = typeof opts.reserve === "number" && Number.isFinite(opts.reserve) && opts.reserve > 0 ? Math.floor(opts.reserve) : 0;
|
|
483
|
+
const lines = Math.max(0, rows - reserve);
|
|
484
|
+
if (lines > 0) out.write("\n".repeat(lines));
|
|
485
|
+
return lines;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// src/ink/banner.ts
|
|
489
|
+
import { PermissionService } from "@corenel/harness/guardrail/permission-service";
|
|
490
|
+
import { NAMESPACE_LABELS, resolveNamespace } from "@corenel/harness/tools/namespaces";
|
|
491
|
+
var ART = [
|
|
492
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588",
|
|
493
|
+
"\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588",
|
|
494
|
+
"\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588",
|
|
495
|
+
"\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588",
|
|
496
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588"
|
|
497
|
+
];
|
|
498
|
+
var ART_MIN_COLUMNS = Math.max(...ART.map((r) => r.length));
|
|
499
|
+
var WORDMARK = "corenel";
|
|
500
|
+
var DEFAULT_COLUMNS2 = 80;
|
|
501
|
+
var SHELL_SUBJECT = { name: "shell", address: "shell:shell", mutates: true };
|
|
502
|
+
var WRITE_SUBJECT = { name: "write_file", address: "fs:write_file", mutates: true };
|
|
503
|
+
function posture(policy) {
|
|
504
|
+
const permission = new PermissionService({ policy });
|
|
505
|
+
const shellLevel = permission.resolveLevel(SHELL_SUBJECT);
|
|
506
|
+
if (shellLevel === "ask") return "shell asks first";
|
|
507
|
+
if (shellLevel === "deny") return "shell off";
|
|
508
|
+
const writeLevel = permission.resolveLevel(WRITE_SUBJECT);
|
|
509
|
+
if (writeLevel === "allow") return "nothing asks -- unattended";
|
|
510
|
+
if (writeLevel === "ask") return "shell runs, writes ask";
|
|
511
|
+
return "shell runs, writes off";
|
|
512
|
+
}
|
|
513
|
+
function toolBreakdown(tools) {
|
|
514
|
+
const counts = /* @__PURE__ */ new Map();
|
|
515
|
+
for (const t of tools) {
|
|
516
|
+
const ns = resolveNamespace(t);
|
|
517
|
+
counts.set(ns, (counts.get(ns) ?? 0) + 1);
|
|
518
|
+
}
|
|
519
|
+
return NAMESPACE_LABELS.filter(({ ns }) => counts.has(ns)).map(({ ns, label }) => `${label} ${counts.get(ns)}`).join(", ");
|
|
520
|
+
}
|
|
521
|
+
function truncateLeft(path, max) {
|
|
522
|
+
if (path.length <= max) return path;
|
|
523
|
+
if (max <= 1) return path.slice(-max);
|
|
524
|
+
return `\u2026${path.slice(path.length - (max - 1))}`;
|
|
525
|
+
}
|
|
526
|
+
function buildBanner(opts) {
|
|
527
|
+
if (opts.isTTY !== true) return "";
|
|
528
|
+
const columns = opts.columns !== void 0 && opts.columns > 0 ? opts.columns : DEFAULT_COLUMNS2;
|
|
529
|
+
const total = opts.tools.length;
|
|
530
|
+
const breakdown = toolBreakdown(opts.tools);
|
|
531
|
+
const toolsFull = breakdown ? `${total} tools (${breakdown})` : `${total} tools`;
|
|
532
|
+
const toolsShort = `${total} tools`;
|
|
533
|
+
const label = sourceLabel(opts.source);
|
|
534
|
+
const policySuffix = label ? ` \xB7 policy ${label}` : "";
|
|
535
|
+
const p = posture(opts.policy);
|
|
536
|
+
const build = (toolsStr, cwd) => ` ${p} \xB7 ${toolsStr} \xB7 ${cwd}${policySuffix}`;
|
|
537
|
+
let statusLine = build(toolsFull, opts.cwd);
|
|
538
|
+
if (statusLine.length > columns) statusLine = build(toolsShort, opts.cwd);
|
|
539
|
+
if (statusLine.length > columns) {
|
|
540
|
+
const overshoot = statusLine.length - columns;
|
|
541
|
+
const budget = Math.max(1, opts.cwd.length - overshoot);
|
|
542
|
+
statusLine = build(toolsShort, truncateLeft(opts.cwd, budget));
|
|
543
|
+
}
|
|
544
|
+
if (statusLine.length > columns) statusLine = statusLine.slice(0, columns);
|
|
545
|
+
if (columns < ART_MIN_COLUMNS) return [WORDMARK, "", statusLine].join("\n");
|
|
546
|
+
return [...ART, "", statusLine].join("\n");
|
|
547
|
+
}
|
|
548
|
+
function bannerHeight(out, opts) {
|
|
549
|
+
const text = buildBanner({ ...opts, isTTY: out.isTTY === true, ...out.columns !== void 0 ? { columns: out.columns } : {} });
|
|
550
|
+
return text ? text.split("\n").length + 1 : 0;
|
|
551
|
+
}
|
|
552
|
+
function writeBanner(out, opts) {
|
|
553
|
+
const text = buildBanner({ ...opts, isTTY: out.isTTY === true, ...out.columns !== void 0 ? { columns: out.columns } : {} });
|
|
554
|
+
if (text) out.write(`${text}
|
|
555
|
+
`);
|
|
428
556
|
}
|
|
429
557
|
|
|
430
558
|
// src/ink/index.tsx
|
|
431
|
-
import { jsx as
|
|
559
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
432
560
|
function Root({ session, deps }) {
|
|
433
561
|
const state = useSyncExternalStore(
|
|
434
562
|
useCallback((fn) => session.subscribe(fn), [session]),
|
|
@@ -438,6 +566,11 @@ function Root({ session, deps }) {
|
|
|
438
566
|
const { exit } = useApp();
|
|
439
567
|
const [sawSigint, setSawSigint] = useState2(false);
|
|
440
568
|
const [paletteIndex, setPaletteIndex] = useState2(0);
|
|
569
|
+
const [fieldGen, setFieldGen] = useState2(0);
|
|
570
|
+
const completeTo = (v) => {
|
|
571
|
+
setValue(v);
|
|
572
|
+
setFieldGen((g) => g + 1);
|
|
573
|
+
};
|
|
441
574
|
const handleChange = (v) => {
|
|
442
575
|
const cleaned = v.replace(/\x1b/g, "");
|
|
443
576
|
if (state.modal?.kind === "user" && value === "" && cleaned.length === 1) {
|
|
@@ -487,7 +620,7 @@ function Root({ session, deps }) {
|
|
|
487
620
|
}
|
|
488
621
|
if (key.tab) {
|
|
489
622
|
const chosen = paletteItems[Math.min(paletteIndex, paletteItems.length - 1)];
|
|
490
|
-
if (chosen)
|
|
623
|
+
if (chosen) completeTo(`/${chosen.name} `);
|
|
491
624
|
setPaletteIndex(0);
|
|
492
625
|
return;
|
|
493
626
|
}
|
|
@@ -511,7 +644,7 @@ function Root({ session, deps }) {
|
|
|
511
644
|
}
|
|
512
645
|
if (sawSigint) setSawSigint(false);
|
|
513
646
|
});
|
|
514
|
-
return /* @__PURE__ */
|
|
647
|
+
return /* @__PURE__ */ jsx6(
|
|
515
648
|
App,
|
|
516
649
|
{
|
|
517
650
|
state,
|
|
@@ -523,6 +656,22 @@ function Root({ session, deps }) {
|
|
|
523
656
|
value,
|
|
524
657
|
onChange: handleChange,
|
|
525
658
|
onSubmit: (v) => {
|
|
659
|
+
const items = v.startsWith("/") ? filterCommands(v) : [];
|
|
660
|
+
if (items.length > 0 && !parseCommand(v)) {
|
|
661
|
+
const chosen = items[Math.min(paletteIndex, items.length - 1)];
|
|
662
|
+
if (chosen) {
|
|
663
|
+
if (chosen.args) {
|
|
664
|
+
completeTo(`/${chosen.name} `);
|
|
665
|
+
setPaletteIndex(0);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
setValue("");
|
|
669
|
+
void session.submit(`/${chosen.name}`).then(() => {
|
|
670
|
+
if (session.wantsExit) exit();
|
|
671
|
+
});
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
526
675
|
setValue("");
|
|
527
676
|
void session.submit(v).then(() => {
|
|
528
677
|
if (session.wantsExit) exit();
|
|
@@ -536,20 +685,31 @@ function Root({ session, deps }) {
|
|
|
536
685
|
else session.answer(v.trim() ? { [modal.questions[0].header]: [v.trim()] } : null);
|
|
537
686
|
},
|
|
538
687
|
focus: state.modal?.kind !== "permission",
|
|
539
|
-
paletteSelected: paletteIndex
|
|
688
|
+
paletteSelected: paletteIndex,
|
|
689
|
+
inputKey: fieldGen
|
|
540
690
|
}
|
|
541
691
|
);
|
|
542
692
|
}
|
|
543
693
|
async function runTui(deps) {
|
|
544
694
|
const session = new TermSession(deps);
|
|
545
695
|
if (deps.resume) await session.resume(deps.resume.id);
|
|
546
|
-
const permission = new
|
|
547
|
-
policy: STANDARD_POLICY,
|
|
696
|
+
const permission = new PermissionService2({
|
|
697
|
+
policy: deps.policy ?? STANDARD_POLICY,
|
|
548
698
|
prompt: { ask: (req) => session.askPermission(req) }
|
|
549
699
|
});
|
|
550
700
|
session.attachPermission(permission);
|
|
551
|
-
|
|
552
|
-
|
|
701
|
+
const bannerOpts = {
|
|
702
|
+
policy: deps.policy ?? STANDARD_POLICY,
|
|
703
|
+
source: deps.policySource ?? { kind: "default" },
|
|
704
|
+
tools: deps.tools,
|
|
705
|
+
cwd: deps.cwd
|
|
706
|
+
};
|
|
707
|
+
primeScroll(process.stdout, {
|
|
708
|
+
resuming: deps.resume != null,
|
|
709
|
+
reserve: bannerHeight(process.stdout, bannerOpts)
|
|
710
|
+
});
|
|
711
|
+
writeBanner(process.stdout, bannerOpts);
|
|
712
|
+
const app = render(/* @__PURE__ */ jsx6(Root, { session, deps }), {
|
|
553
713
|
/* LOAD-BEARING — do not "clean up" or default this away. Ink's own App
|
|
554
714
|
* component (build/components/App.js, handleInput) intercepts the raw
|
|
555
715
|
* \x03 byte and calls handleExit() BEFORE it ever emits the 'input'
|
package/dist/ink/items.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../src/ink/items.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../src/ink/items.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKxD;gDACgD;AAChD,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAwDlF;AA4CD,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAW5E"}
|