@inventarch/cli 0.0.0-stage → 1.0.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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +19 -2
- package/SPEC.md +30 -0
- package/assets/base/71f0665cb1ffc3f3964fc7710528451f635d664bdf4b8c95005ee97c21db5928.ia.tgz +0 -0
- package/assets/base.json +6 -0
- package/assets/host/43a1f8c471141b1f2f46cef4411a9a61c00da1c1aa19d277189ae2423282bfd6.tgz +0 -0
- package/assets/host.json +6 -0
- package/assets/vocabulary.json +3268 -0
- package/dist/args.d.ts +62 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +117 -0
- package/dist/args.js.map +1 -0
- package/dist/briefing.d.ts +76 -0
- package/dist/briefing.d.ts.map +1 -0
- package/dist/briefing.js +105 -0
- package/dist/briefing.js.map +1 -0
- package/dist/channel.d.ts +22 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +74 -0
- package/dist/channel.js.map +1 -0
- package/dist/claude-cli.d.ts +35 -0
- package/dist/claude-cli.d.ts.map +1 -0
- package/dist/claude-cli.js +101 -0
- package/dist/claude-cli.js.map +1 -0
- package/dist/commands.d.ts +39 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +436 -0
- package/dist/commands.js.map +1 -0
- package/dist/compile.d.ts +39 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +136 -0
- package/dist/compile.js.map +1 -0
- package/dist/consumer.d.ts +137 -0
- package/dist/consumer.d.ts.map +1 -0
- package/dist/consumer.js +366 -0
- package/dist/consumer.js.map +1 -0
- package/dist/decline.d.ts +7 -0
- package/dist/decline.d.ts.map +1 -0
- package/dist/decline.js +78 -0
- package/dist/decline.js.map +1 -0
- package/dist/distribute.d.ts +163 -0
- package/dist/distribute.d.ts.map +1 -0
- package/dist/distribute.js +664 -0
- package/dist/distribute.js.map +1 -0
- package/dist/doctor-user.d.ts +45 -0
- package/dist/doctor-user.d.ts.map +1 -0
- package/dist/doctor-user.js +193 -0
- package/dist/doctor-user.js.map +1 -0
- package/dist/doctor.d.ts +57 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +754 -0
- package/dist/doctor.js.map +1 -0
- package/dist/format.d.ts +25 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +168 -0
- package/dist/format.js.map +1 -0
- package/dist/home-remedy.d.ts +10 -0
- package/dist/home-remedy.d.ts.map +1 -0
- package/dist/home-remedy.js +26 -0
- package/dist/home-remedy.js.map +1 -0
- package/dist/host-projection.d.ts +11 -0
- package/dist/host-projection.d.ts.map +1 -0
- package/dist/host-projection.js +73 -0
- package/dist/host-projection.js.map +1 -0
- package/dist/host.d.ts +162 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +599 -0
- package/dist/host.js.map +1 -0
- package/dist/init.d.ts +217 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +840 -0
- package/dist/init.js.map +1 -0
- package/dist/inspect.d.ts +32 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +226 -0
- package/dist/inspect.js.map +1 -0
- package/dist/main.d.ts +24 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +215 -0
- package/dist/main.js.map +1 -0
- package/dist/operation-help.d.ts +14 -0
- package/dist/operation-help.d.ts.map +1 -0
- package/dist/operation-help.js +75 -0
- package/dist/operation-help.js.map +1 -0
- package/dist/pack.d.ts +17 -0
- package/dist/pack.d.ts.map +1 -0
- package/dist/pack.js +121 -0
- package/dist/pack.js.map +1 -0
- package/dist/render.d.ts +165 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +277 -0
- package/dist/render.js.map +1 -0
- package/dist/session.d.ts +13 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +25 -0
- package/dist/session.js.map +1 -0
- package/dist/user-host.d.ts +59 -0
- package/dist/user-host.d.ts.map +1 -0
- package/dist/user-host.js +228 -0
- package/dist/user-host.js.map +1 -0
- package/dist/validate.d.ts +53 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +220 -0
- package/dist/validate.js.map +1 -0
- package/dist/vocabulary.d.ts +55 -0
- package/dist/vocabulary.d.ts.map +1 -0
- package/dist/vocabulary.js +179 -0
- package/dist/vocabulary.js.map +1 -0
- package/package.json +153 -3
package/dist/render.js
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal presentation primitives for the consumer CLI: docs/specs/consumer-cli-contract/README.md §6.
|
|
3
|
+
* Everything here is pure. The environment is a parameter, so no function reads process.env, process.stdout or a clock.
|
|
4
|
+
*/
|
|
5
|
+
/** §6.4: 80 is the ceiling; below 40 a label/value block drops its value column; below 60 header pairs split. */
|
|
6
|
+
export const MAX_WIDTH = 80;
|
|
7
|
+
export const NARROW_WIDTH = 40;
|
|
8
|
+
export const HEADER_WIDTH = 60;
|
|
9
|
+
/** §6.4: a bare digest field shows 12 hex characters and an explicit ellipsis. */
|
|
10
|
+
export const DIGEST_CHARACTERS = 12;
|
|
11
|
+
const UTF8 = /utf-?8/i;
|
|
12
|
+
const LOCALE_NAMES = ['LC_ALL', 'LC_CTYPE', 'LANG'];
|
|
13
|
+
/** §6.7 colour precedence and §6.3's ASCII rule, resolved from an explicit environment rather than from the process. */
|
|
14
|
+
export function resolveCapabilities(terminal, flags = {}) {
|
|
15
|
+
const env = terminal.env, force = env['FORCE_COLOR'];
|
|
16
|
+
const color = env['NO_COLOR'] !== undefined
|
|
17
|
+
? false
|
|
18
|
+
: flags.color === false
|
|
19
|
+
? false
|
|
20
|
+
: flags.json === true
|
|
21
|
+
? false
|
|
22
|
+
: flags.color === true || (force !== undefined && force !== '0')
|
|
23
|
+
? true
|
|
24
|
+
: terminal.isTTY && env['TERM'] !== 'dumb';
|
|
25
|
+
const locales = LOCALE_NAMES.map((name) => env[name]).filter((value) => value !== undefined);
|
|
26
|
+
const ascii = flags.ascii === true ||
|
|
27
|
+
env['IA_ASCII'] !== undefined ||
|
|
28
|
+
(locales.length > 0 && !locales.some((value) => UTF8.test(value)));
|
|
29
|
+
const columns = terminal.columns;
|
|
30
|
+
const sized = terminal.isTTY && typeof columns === 'number' && Number.isInteger(columns) && columns > 0;
|
|
31
|
+
return { color, ascii, width: sized ? Math.min(columns, MAX_WIDTH) : MAX_WIDTH };
|
|
32
|
+
}
|
|
33
|
+
const SGR = { bold: '1', dim: '2', red: '31', yellow: '33', green: '32', cyan: '36' };
|
|
34
|
+
/** §6.1: a styled run is reset at its end and never left open across a newline, so each line is styled on its own. */
|
|
35
|
+
export function style(text, role, color) {
|
|
36
|
+
if (!color || !role)
|
|
37
|
+
return text;
|
|
38
|
+
return text
|
|
39
|
+
.split('\n')
|
|
40
|
+
.map((line) => (line === '' ? line : `\u001b[${SGR[role]}m${line}\u001b[0m`))
|
|
41
|
+
.join('\n');
|
|
42
|
+
}
|
|
43
|
+
const SYMBOLS = {
|
|
44
|
+
success: { unicode: '✔', ascii: '[ok]', role: 'green' },
|
|
45
|
+
error: { unicode: '✖', ascii: '[error]', role: 'red' },
|
|
46
|
+
warning: { unicode: '▲', ascii: '[warn]', role: 'yellow' },
|
|
47
|
+
unknown: { unicode: '?', ascii: '[?]', role: null },
|
|
48
|
+
info: { unicode: '•', ascii: '*', role: null },
|
|
49
|
+
step: { unicode: '→', ascii: '->', role: null },
|
|
50
|
+
added: { unicode: '+', ascii: '+', role: 'green' },
|
|
51
|
+
removed: { unicode: '-', ascii: '-', role: null },
|
|
52
|
+
updated: { unicode: '~', ascii: '~', role: null },
|
|
53
|
+
};
|
|
54
|
+
/** Every symbol is one UTF-16 unit per display column, so length is the declared §6.3 width; no emoji is admitted. */
|
|
55
|
+
export function statusSymbol(name, ascii) {
|
|
56
|
+
const definition = SYMBOLS[name], text = ascii ? definition.ascii : definition.unicode;
|
|
57
|
+
return { text, width: text.length, role: definition.role };
|
|
58
|
+
}
|
|
59
|
+
/** One unbreakable run: an identity, path, package id, digest, URL or a command that must stay copy-pasteable. */
|
|
60
|
+
export const atom = (text, role = null, gap = 1) => ({ text, gap, role });
|
|
61
|
+
/** Prose, split at word boundaries; runs of spaces inside the text are preserved as wider gaps. */
|
|
62
|
+
export function words(text, role = null, gap = 1) {
|
|
63
|
+
const tokens = [];
|
|
64
|
+
let pending = 0;
|
|
65
|
+
for (const part of text.split(' ')) {
|
|
66
|
+
if (part === '') {
|
|
67
|
+
if (tokens.length > 0)
|
|
68
|
+
pending += 1;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
tokens.push({ text: part, gap: tokens.length === 0 ? gap : pending + 1, role });
|
|
72
|
+
pending = 0;
|
|
73
|
+
}
|
|
74
|
+
return tokens;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* §6.4: words wrap at the effective width; a token is never split, so an over-wide identifier overruns its line whole.
|
|
78
|
+
* `firstColumn` differs from `column` only where a value starts past its label and then hangs back at rule 3's column.
|
|
79
|
+
*/
|
|
80
|
+
export function wrapTokens(tokens, column, caps, firstColumn = column) {
|
|
81
|
+
const lines = [];
|
|
82
|
+
let plain = '', styled = '', open = false;
|
|
83
|
+
for (const token of tokens) {
|
|
84
|
+
const text = style(token.text, token.role, caps.color);
|
|
85
|
+
if (!open) {
|
|
86
|
+
plain = token.text;
|
|
87
|
+
styled = text;
|
|
88
|
+
open = true;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const gap = ' '.repeat(token.gap);
|
|
92
|
+
if ((lines.length === 0 ? firstColumn : column) + plain.length + gap.length + token.text.length <= caps.width) {
|
|
93
|
+
plain += gap + token.text;
|
|
94
|
+
styled += gap + text;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
lines.push(styled);
|
|
98
|
+
plain = token.text;
|
|
99
|
+
styled = text;
|
|
100
|
+
}
|
|
101
|
+
if (open)
|
|
102
|
+
lines.push(styled);
|
|
103
|
+
return lines;
|
|
104
|
+
}
|
|
105
|
+
/** §6.4 rule 1. */
|
|
106
|
+
export const indentOf = (depth) => 2 * depth;
|
|
107
|
+
/** The widest symbol of a block, which rule 2 measures the whole block's content column from. */
|
|
108
|
+
export const blockSymbolWidth = (names, ascii) => Math.max(0, ...names.map((name) => (name === undefined ? 0 : statusSymbol(name, ascii).width)));
|
|
109
|
+
/** §6.4 rule 2: `2·d + width + 2`, where width is the block's widest symbol and never less than this row's own. */
|
|
110
|
+
export const contentColumn = (base, symbol, symbolWidth = 0) => base + (symbol === null ? 0 : Math.max(symbolWidth, symbol.width) + 2);
|
|
111
|
+
export const entryColumn = (options, ascii) => contentColumn(options.column ?? indentOf(options.depth ?? 0), options.symbol === undefined ? null : statusSymbol(options.symbol, ascii), options.symbolWidth ?? 0);
|
|
112
|
+
/**
|
|
113
|
+
* One entry: block indent, the status symbol, two spaces, then its facts. §6.4 rule 3 hangs every continuation —
|
|
114
|
+
* a wrapped line or a further fact — at the entry's content column.
|
|
115
|
+
*/
|
|
116
|
+
export function entry(facts, options, caps) {
|
|
117
|
+
const base = options.column ?? indentOf(options.depth ?? 0);
|
|
118
|
+
const symbol = options.symbol === undefined ? null : statusSymbol(options.symbol, caps.ascii);
|
|
119
|
+
const column = contentColumn(base, symbol, options.symbolWidth ?? 0);
|
|
120
|
+
const prefix = ' '.repeat(base) +
|
|
121
|
+
(symbol === null ? '' : style(symbol.text, symbol.role, caps.color) + ' '.repeat(column - base - symbol.width));
|
|
122
|
+
const hanging = ' '.repeat(column);
|
|
123
|
+
const lines = facts.flatMap((fact) => wrapTokens(fact, column, caps));
|
|
124
|
+
return lines.map((line, index) => (index === 0 ? prefix : hanging) + line);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* §6.4 rule 4: one value column per block at `max(len(label)) + 2`, never shared across a blank line, over the one
|
|
128
|
+
* content column rule 2 gives the block. A value that wraps hangs at the entry's content column, which is rule 3 and
|
|
129
|
+
* not the value column. Below 40 columns, or when the padding would leave no room for a value, the block drops the
|
|
130
|
+
* value column and each field renders as `label value`.
|
|
131
|
+
*/
|
|
132
|
+
export function fieldRows(fields, options, caps) {
|
|
133
|
+
const pad = Math.max(0, ...fields.map((field) => field.label.length)) + 2;
|
|
134
|
+
const base = options.column ?? indentOf(options.depth ?? 0);
|
|
135
|
+
const symbolWidth = blockSymbolWidth(fields.map((field) => field.symbol), caps.ascii);
|
|
136
|
+
const column = base + (symbolWidth === 0 ? 0 : symbolWidth + 2);
|
|
137
|
+
const degraded = caps.width < NARROW_WIDTH || column + pad >= caps.width;
|
|
138
|
+
return fields.flatMap((field) => {
|
|
139
|
+
const placement = { ...options, symbol: field.symbol, symbolWidth };
|
|
140
|
+
const symbol = field.symbol === undefined ? null : statusSymbol(field.symbol, caps.ascii);
|
|
141
|
+
const prefix = ' '.repeat(base) +
|
|
142
|
+
(symbol === null ? '' : style(symbol.text, symbol.role, caps.color) + ' '.repeat(column - base - symbol.width));
|
|
143
|
+
const value = degraded ? [] : wrapTokens(field.value, column, caps, column + pad);
|
|
144
|
+
const rows = degraded
|
|
145
|
+
? entry([
|
|
146
|
+
[
|
|
147
|
+
atom(field.label, null, 0),
|
|
148
|
+
...field.value.map((token, index) => (index === 0 ? { ...token, gap: 2 } : token)),
|
|
149
|
+
],
|
|
150
|
+
], placement, caps)
|
|
151
|
+
: value.length === 0
|
|
152
|
+
? [prefix + field.label]
|
|
153
|
+
: value.map((line, index) => (index === 0 ? prefix + field.label.padEnd(pad) : ' '.repeat(column)) + line);
|
|
154
|
+
return field.action ? [...rows, ...entry([field.action], { column, symbol: 'step' }, caps)] : rows;
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/** §6.4 rule 5: bold label, two spaces, value; further pairs share the line until the width drops below 60. */
|
|
158
|
+
export function headerLine(label, value, trailing, caps) {
|
|
159
|
+
const head = style(label, 'bold', caps.color) + ' ' + value;
|
|
160
|
+
if (caps.width < HEADER_WIDTH)
|
|
161
|
+
return [head, ...trailing.map((item) => item.text)];
|
|
162
|
+
let visible = label.length + 2 + value.length, line = head;
|
|
163
|
+
for (const item of trailing) {
|
|
164
|
+
const start = Math.max(item.column ?? visible + 4, visible + 4);
|
|
165
|
+
line += ' '.repeat(start - visible) + item.text;
|
|
166
|
+
visible = start + item.text.length;
|
|
167
|
+
}
|
|
168
|
+
return [line];
|
|
169
|
+
}
|
|
170
|
+
export const sectionLabel = (text, caps) => style(text, 'bold', caps.color);
|
|
171
|
+
/** §6.4 rule 6: exactly one blank line between blocks, never two, and no trailing blank before the process exits. */
|
|
172
|
+
export function document(blocks, options = {}) {
|
|
173
|
+
const body = blocks
|
|
174
|
+
.filter((block) => block.length > 0)
|
|
175
|
+
.map((block) => block.join('\n'))
|
|
176
|
+
.join('\n\n');
|
|
177
|
+
if (body === '')
|
|
178
|
+
return '';
|
|
179
|
+
return (options.leadingBlank === true ? '\n' : '') + body + '\n';
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* One argument of a printed command, quoted only when a space or a quote would split or end it, so an invocation
|
|
183
|
+
* rebuilt from parsed arguments is the one a reader can paste back.
|
|
184
|
+
*/
|
|
185
|
+
export const quote = (value) => (/[ "]/.test(value) ? JSON.stringify(value) : value);
|
|
186
|
+
/** §6.4: a command is unbreakable prose. The caller chooses the `\` break so every line stays runnable. */
|
|
187
|
+
export function commandFacts(lead, command, tail, column, caps) {
|
|
188
|
+
const lines = [];
|
|
189
|
+
let current = '';
|
|
190
|
+
for (const piece of command.split(' ')) {
|
|
191
|
+
// The lead is glued to the first word, so the quoted command starts where the quote ends.
|
|
192
|
+
const candidate = current === '' ? lead + piece : `${current} ${piece}`;
|
|
193
|
+
if (current !== '' && column + candidate.length + 2 > caps.width) {
|
|
194
|
+
lines.push(`${current} \\`);
|
|
195
|
+
current = piece;
|
|
196
|
+
}
|
|
197
|
+
else
|
|
198
|
+
current = candidate;
|
|
199
|
+
}
|
|
200
|
+
lines.push(current + tail);
|
|
201
|
+
return lines.map((line) => [atom(line, null, 0)]);
|
|
202
|
+
}
|
|
203
|
+
const BARE_DIGEST = /^[0-9a-f]+$/i;
|
|
204
|
+
/**
|
|
205
|
+
* §6.4: only a bare digest field is truncated. A value carrying a path, URL or any other separator is returned whole,
|
|
206
|
+
* because truncating a digest inside an identifier destroys the identifier.
|
|
207
|
+
*/
|
|
208
|
+
export const truncateDigest = (value, ascii) => value.length > DIGEST_CHARACTERS && BARE_DIGEST.test(value)
|
|
209
|
+
? value.slice(0, DIGEST_CHARACTERS) + (ascii ? '...' : '…')
|
|
210
|
+
: value;
|
|
211
|
+
/**
|
|
212
|
+
* §6.5: strip what the block already shows. Findings embed `path:line: identity: `; RuntimeError and DbError embed
|
|
213
|
+
* `code: `; DistributionError embeds nothing. Without this, two of the three families print their code twice.
|
|
214
|
+
*/
|
|
215
|
+
export function stripMessage(message, context) {
|
|
216
|
+
let text = message;
|
|
217
|
+
for (const prefix of [context.location, context.identity, context.code]) {
|
|
218
|
+
if (prefix && text.startsWith(prefix + ': '))
|
|
219
|
+
text = text.slice(prefix.length + 2);
|
|
220
|
+
}
|
|
221
|
+
return text;
|
|
222
|
+
}
|
|
223
|
+
/** §6.5: location, identity, cause, next action, in that order, with nothing interleaved. */
|
|
224
|
+
export function errorBlock(error, options, caps) {
|
|
225
|
+
const placement = {
|
|
226
|
+
...options,
|
|
227
|
+
symbol: error.severity ?? 'error',
|
|
228
|
+
...(error.symbolWidth === undefined ? {} : { symbolWidth: error.symbolWidth }),
|
|
229
|
+
};
|
|
230
|
+
const location = error.location === null || error.location === '' ? '(whole workspace)' : error.location;
|
|
231
|
+
const head = [atom(location, 'cyan', 0)];
|
|
232
|
+
if (error.check)
|
|
233
|
+
head.push(atom(error.check, null, 2));
|
|
234
|
+
const facts = [head];
|
|
235
|
+
if (error.identity)
|
|
236
|
+
facts.push([atom(error.identity, 'cyan', 0)]);
|
|
237
|
+
// §6.1 colours a warning code yellow and an error code red; the element order is the same either way.
|
|
238
|
+
const codeRole = error.severity === 'warning' ? 'yellow' : 'red';
|
|
239
|
+
facts.push([atom(error.code, codeRole, 0), ...words(stripMessage(error.message, error), null, 2)]);
|
|
240
|
+
const lines = [...entry(facts, placement, caps)];
|
|
241
|
+
if (error.next)
|
|
242
|
+
lines.push(...entry([error.next], { column: entryColumn(placement, caps.ascii), symbol: 'step' }, caps));
|
|
243
|
+
return lines;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* §6.6: progress lives on the sink the caller supplies, which is stderr — never structured stdout. It is rewritten in
|
|
247
|
+
* place only on a TTY, degrades to one appended line per phase otherwise, is erased before the result is written, and
|
|
248
|
+
* never carries the completion: `done` always emits a terminal state line as text.
|
|
249
|
+
*/
|
|
250
|
+
export function createProgress(sink, options) {
|
|
251
|
+
let pending = false;
|
|
252
|
+
const clear = () => {
|
|
253
|
+
if (pending && sink.isTTY)
|
|
254
|
+
sink.write('\r\u001b[K');
|
|
255
|
+
pending = false;
|
|
256
|
+
};
|
|
257
|
+
return {
|
|
258
|
+
phase: (text) => {
|
|
259
|
+
if (!options.enabled)
|
|
260
|
+
return;
|
|
261
|
+
if (!sink.isTTY) {
|
|
262
|
+
sink.write(text + '\n');
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
clear();
|
|
266
|
+
sink.write(text);
|
|
267
|
+
pending = true;
|
|
268
|
+
},
|
|
269
|
+
clear,
|
|
270
|
+
done: (text) => {
|
|
271
|
+
clear();
|
|
272
|
+
if (options.enabled)
|
|
273
|
+
sink.write(text + '\n');
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opening a workspace for a consumer verb: docs/specs/consumer-cli-contract/README.md §2.0 and §3.
|
|
3
|
+
*
|
|
4
|
+
* The open is the one step every workspace verb shares and the one that decides class 3 rather than class 1:
|
|
5
|
+
* a root that cannot be read produced no finding set, so it is a refusal and never a diagnostic. The service's
|
|
6
|
+
* own code is carried through unchanged (§4.1); only the next action is the CLI's.
|
|
7
|
+
*/
|
|
8
|
+
import { openWorkspaceSession } from '@inventarch/distribution/services';
|
|
9
|
+
export type Session = ReturnType<typeof openWorkspaceSession>;
|
|
10
|
+
export declare const codeOf: (error: unknown, fallback: string) => string;
|
|
11
|
+
/** §2.5: IA-DB-SOURCE-UNAVAILABLE here means an interrupted installation blocks the read, not a bad path. */
|
|
12
|
+
export declare function openSession(root: string): Session;
|
|
13
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAGzE,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAE9D,eAAO,MAAM,MAAM,GAAI,OAAO,OAAO,EAAE,UAAU,MAAM,KAAG,MAG5C,CAAC;AAEf,6GAA6G;AAC7G,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAejD"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opening a workspace for a consumer verb: docs/specs/consumer-cli-contract/README.md §2.0 and §3.
|
|
3
|
+
*
|
|
4
|
+
* The open is the one step every workspace verb shares and the one that decides class 3 rather than class 1:
|
|
5
|
+
* a root that cannot be read produced no finding set, so it is a refusal and never a diagnostic. The service's
|
|
6
|
+
* own code is carried through unchanged (§4.1); only the next action is the CLI's.
|
|
7
|
+
*/
|
|
8
|
+
import { openWorkspaceSession } from '@inventarch/distribution/services';
|
|
9
|
+
import { Refusal } from './consumer.js';
|
|
10
|
+
export const codeOf = (error, fallback) => error !== null && typeof error === 'object' && 'code' in error && typeof error.code === 'string'
|
|
11
|
+
? error.code
|
|
12
|
+
: fallback;
|
|
13
|
+
/** §2.5: IA-DB-SOURCE-UNAVAILABLE here means an interrupted installation blocks the read, not a bad path. */
|
|
14
|
+
export function openSession(root) {
|
|
15
|
+
try {
|
|
16
|
+
return openWorkspaceSession({ root });
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
const code = codeOf(error, 'IA-DB-ROOT-INVALID');
|
|
20
|
+
throw new Refusal(code, error instanceof Error ? error.message : String(error), 3, { path: root }, code === 'IA-DB-SOURCE-UNAVAILABLE'
|
|
21
|
+
? `An interrupted installation blocks the read. Run "ia-distribution recover --root ${root}".`
|
|
22
|
+
: 'Pass --root <path> with an existing workspace, or run "ia init" to see what a new one would contain.');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAIxC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,QAAgB,EAAU,EAAE,CACjE,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;IAC9F,CAAC,CAAC,KAAK,CAAC,IAAI;IACZ,CAAC,CAAC,QAAQ,CAAC;AAEf,6GAA6G;AAC7G,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,OAAO,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;QACjD,MAAM,IAAI,OAAO,CACf,IAAI,EACJ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACtD,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,EACd,IAAI,KAAK,0BAA0B;YACjC,CAAC,CAAC,oFAAoF,IAAI,IAAI;YAC9F,CAAC,CAAC,sGAAsG,CAC3G,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { PluginFile } from '@inventarch/compliance';
|
|
2
|
+
import type { Channel } from './channel.js';
|
|
3
|
+
import type { ClaudeRunner } from './claude-cli.js';
|
|
4
|
+
import type { Context, Result } from './consumer.js';
|
|
5
|
+
export interface UserHostView {
|
|
6
|
+
readonly host: 'claude';
|
|
7
|
+
readonly remove: boolean;
|
|
8
|
+
readonly home: string;
|
|
9
|
+
readonly marketplace: string;
|
|
10
|
+
readonly plugin: {
|
|
11
|
+
readonly version: string;
|
|
12
|
+
readonly cli: string;
|
|
13
|
+
readonly channel: Channel['kind'];
|
|
14
|
+
};
|
|
15
|
+
/** The plugin already materialized in the IA home, read from its own metadata; null when absent or unreadable. */
|
|
16
|
+
readonly installed: {
|
|
17
|
+
readonly version: string;
|
|
18
|
+
} | null;
|
|
19
|
+
/** Whether `claude` can be run. Without it the commands are printed, not run. */
|
|
20
|
+
readonly claude: boolean;
|
|
21
|
+
/** Claude CLI argument vectors, in the order apply runs them. */
|
|
22
|
+
readonly commands: readonly (readonly string[])[];
|
|
23
|
+
readonly files: readonly PluginFile[];
|
|
24
|
+
}
|
|
25
|
+
/** §6.2 (amended): the digest is of the files rendered with a placeholder version, so it changes whenever the renderer's output does. */
|
|
26
|
+
export declare function buildClaudePlugin(input: {
|
|
27
|
+
readonly cliVersion: string;
|
|
28
|
+
readonly channel: Channel;
|
|
29
|
+
readonly entry: string;
|
|
30
|
+
}): {
|
|
31
|
+
readonly version: string;
|
|
32
|
+
readonly files: readonly PluginFile[];
|
|
33
|
+
};
|
|
34
|
+
/** A Claude command as a reader can paste it back. */
|
|
35
|
+
export declare const claudeCommand: (command: readonly string[]) => string;
|
|
36
|
+
/**
|
|
37
|
+
* §7.1's plan. It reads the IA home and asks `claude` what it lists; it writes nothing. `claude` is first run (the
|
|
38
|
+
* availability probe) only after every usage check and refusal has passed, so a class-2 invocation does no work
|
|
39
|
+
* (contract §3). The runner is returned so apply reuses it instead of probing again.
|
|
40
|
+
*/
|
|
41
|
+
export declare function collectUserHost(context: Context, runnerFor?: (env: Readonly<Record<string, string | undefined>>) => ClaudeRunner): {
|
|
42
|
+
readonly view: UserHostView;
|
|
43
|
+
readonly runner: ClaudeRunner;
|
|
44
|
+
};
|
|
45
|
+
export interface UserHostApplied {
|
|
46
|
+
/** `plugin-directory-removed`: a removal without `claude`, so only the directory went and the commands are printed. */
|
|
47
|
+
readonly status: 'plugin-registered' | 'plugin-materialized' | 'plugin-removed' | 'plugin-directory-removed';
|
|
48
|
+
/** The Claude commands that ran and exited 0, in order. Empty when `claude` was unavailable. */
|
|
49
|
+
readonly ran: readonly (readonly string[])[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* §6.3: materialize, then register through `claude`; removal runs `claude` first and deletes the directory last, so a
|
|
53
|
+
* failed uninstall leaves the marketplace Claude still points at. A failing command refuses naming itself and the
|
|
54
|
+
* rerun, and the commands before it have run. A rerun converges: registration repeats two idempotent commands, and
|
|
55
|
+
* removal asks claude again what is left (§2.3).
|
|
56
|
+
*/
|
|
57
|
+
export declare function applyUserHost(view: UserHostView, runner: ClaudeRunner): UserHostApplied;
|
|
58
|
+
export declare function runUserHost(context: Context): Promise<Result>;
|
|
59
|
+
//# sourceMappingURL=user-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-host.d.ts","sourceRoot":"","sources":["../src/user-host.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAWzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAMrD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,CAAC;IACvG,kHAAkH;IAClH,QAAQ,CAAC,SAAS,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACxD,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC;AAED,yIAAyI;AACzI,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,GAAG;IACF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC,CAaA;AAID,sDAAsD;AACtD,eAAO,MAAM,aAAa,GAAI,SAAS,SAAS,MAAM,EAAE,KAAG,MAAqD,CAAC;AAEjH;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,SAAS,GAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK,YAA2B,GAC5F;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CA2ChE;AAiCD,MAAM,WAAW,eAAe;IAC9B,uHAAuH;IACvH,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,qBAAqB,GAAG,gBAAgB,GAAG,0BAA0B,CAAC;IAC7G,gGAAgG;IAChG,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;CAC9C;AACD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,eAAe,CAyBvF;AAsFD,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BnE"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ia host <host> --user`: docs/specs/host-plugin-distribution/README.md §6.3 (amended, item 5) and §7.1.
|
|
3
|
+
*
|
|
4
|
+
* Needs no workspace. Plans by default and writes nothing while planning; `--apply` renders the plugin, swaps it into
|
|
5
|
+
* the IA home's marketplace directory, then runs Claude's own `claude plugin …` commands. Without `claude` it
|
|
6
|
+
* materializes and prints the commands. It never reads or edits Claude's settings files. A service refusal keeps its
|
|
7
|
+
* code and message (contract §4.1) and gains the next action the CLI can supply, as `ia host` does.
|
|
8
|
+
*/
|
|
9
|
+
import { createHash } from 'node:crypto';
|
|
10
|
+
import { existsSync } from 'node:fs';
|
|
11
|
+
import { join, resolve } from 'node:path';
|
|
12
|
+
import { renderClaudePlugin } from '@inventarch/compliance';
|
|
13
|
+
import { hostRow } from '@inventarch/distribution/hosts';
|
|
14
|
+
import { assertIaHomeUsable } from '@inventarch/distribution/ia-home';
|
|
15
|
+
import { MARKETPLACE_DIR, materializeMarketplace, readMaterializedPlugin, removeMarketplace, } from '@inventarch/distribution/plugin-home';
|
|
16
|
+
import { UsageError } from './args.js';
|
|
17
|
+
import { detectChannel, updateInstruction } from './channel.js';
|
|
18
|
+
import { claudeRunner, observeClaude, registrationCommands, removalCommands } from './claude-cli.js';
|
|
19
|
+
import { confirm, Refusal, refusalOf } from './consumer.js';
|
|
20
|
+
import { homeSrcRemedy, hostHome, located } from './home-remedy.js';
|
|
21
|
+
import { blockSymbolWidth, commandFacts, document, entry, headerLine, indentOf, quote, words } from './render.js';
|
|
22
|
+
/** §6.2 (amended): the digest is of the files rendered with a placeholder version, so it changes whenever the renderer's output does. */
|
|
23
|
+
export function buildClaudePlugin(input) {
|
|
24
|
+
const base = {
|
|
25
|
+
cliVersion: input.cliVersion,
|
|
26
|
+
channel: input.channel.kind,
|
|
27
|
+
entry: input.entry,
|
|
28
|
+
install: updateInstruction(input.channel),
|
|
29
|
+
};
|
|
30
|
+
const draft = renderClaudePlugin({ ...base, version: '0.0.0' });
|
|
31
|
+
const digest = createHash('sha256')
|
|
32
|
+
.update(draft.map((file) => `${file.path}\0${file.text}`).join('\0'))
|
|
33
|
+
.digest('hex');
|
|
34
|
+
const version = `${input.cliVersion}+${digest.slice(0, 12)}`;
|
|
35
|
+
return { version, files: renderClaudePlugin({ ...base, version }) };
|
|
36
|
+
}
|
|
37
|
+
/** The rerun a next action names; the only user-level host is Claude. */
|
|
38
|
+
const rerunOf = (remove) => `ia host claude --user${remove ? ' --remove' : ''} --apply`;
|
|
39
|
+
/** A Claude command as a reader can paste it back. */
|
|
40
|
+
export const claudeCommand = (command) => ['claude', ...command].map(quote).join(' ');
|
|
41
|
+
/**
|
|
42
|
+
* §7.1's plan. It reads the IA home and asks `claude` what it lists; it writes nothing. `claude` is first run (the
|
|
43
|
+
* availability probe) only after every usage check and refusal has passed, so a class-2 invocation does no work
|
|
44
|
+
* (contract §3). The runner is returned so apply reuses it instead of probing again.
|
|
45
|
+
*/
|
|
46
|
+
export function collectUserHost(context, runnerFor = claudeRunner) {
|
|
47
|
+
const { args, host } = context;
|
|
48
|
+
const name = args.positionals[0] ?? '';
|
|
49
|
+
// §4: the adapter table decides. Unknown is usage, and so is --root (§7.1); both precede every read.
|
|
50
|
+
const row = hostRow(name);
|
|
51
|
+
if (row === undefined)
|
|
52
|
+
throw new UsageError(`ia host takes claude, codex or cursor; got ${name}`);
|
|
53
|
+
if (args.value('root') !== undefined)
|
|
54
|
+
throw new UsageError('--root does not apply with --user; the user-level entry point belongs to no workspace');
|
|
55
|
+
// §4: a row without a user-level entry point — Codex (partial) and Cursor (planned) — refuses naming the host.
|
|
56
|
+
if (row.user === 'none')
|
|
57
|
+
throw new Refusal('IA-DIST-HOST-UNSUPPORTED', `${row.label} has no user-level entry point in this release; nothing was written`, 3, null, 'Run "ia host claude --user".');
|
|
58
|
+
const home = hostHome(host.env);
|
|
59
|
+
// Host plugin distribution spec §3: refuse a home that looks like a workspace now, before apply attempts a write.
|
|
60
|
+
located(null, homeSrcRemedy(home), () => assertIaHomeUsable(home));
|
|
61
|
+
const channel = detectChannel(host.packageRoot);
|
|
62
|
+
const plugin = buildClaudePlugin({
|
|
63
|
+
cliVersion: host.version,
|
|
64
|
+
channel,
|
|
65
|
+
entry: resolve(host.packageRoot, 'dist/main.js'),
|
|
66
|
+
});
|
|
67
|
+
const marketplace = resolve(home, MARKETPLACE_DIR);
|
|
68
|
+
const remove = args.flag('remove');
|
|
69
|
+
const installed = readMaterializedPlugin(home);
|
|
70
|
+
const runner = runnerFor(host.env);
|
|
71
|
+
const view = {
|
|
72
|
+
host: 'claude',
|
|
73
|
+
remove,
|
|
74
|
+
home,
|
|
75
|
+
marketplace,
|
|
76
|
+
plugin: { version: plugin.version, cli: host.version, channel: channel.kind },
|
|
77
|
+
installed: installed === null ? null : { version: installed.version },
|
|
78
|
+
claude: runner.available,
|
|
79
|
+
// §2.3: registration is idempotent and needs no observation; removal asks claude what exists.
|
|
80
|
+
commands: remove ? removalCommands(observeClaude(runner)) : registrationCommands(marketplace),
|
|
81
|
+
files: plugin.files,
|
|
82
|
+
};
|
|
83
|
+
return { view, runner };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A marketplace refusal from `@inventarch/distribution/plugin-home`, its code and message kept, located at the IA home's
|
|
87
|
+
* `claude` directory (which holds the marketplace and its lock) and given a next action. Anything without an IA-DIST
|
|
88
|
+
* code is not the service's refusal and passes through unchanged.
|
|
89
|
+
*/
|
|
90
|
+
function marketplaceRefusal(error, view) {
|
|
91
|
+
const refusal = refusalOf(error);
|
|
92
|
+
if (!refusal.code.startsWith('IA-DIST-'))
|
|
93
|
+
return error;
|
|
94
|
+
const directory = join(view.home, 'claude'), rerun = rerunOf(view.remove);
|
|
95
|
+
const next = refusal.code === 'IA-DIST-INSTALL-BUSY'
|
|
96
|
+
? // Two causes share the code: files held open during a rename, and another run holding the lock.
|
|
97
|
+
`Wait for any other "ia host --user" run to finish and close Claude Code sessions, editors or terminals using ${directory}; if no run is active, delete ${join(directory, '.lock')}; then rerun "${rerun}".`
|
|
98
|
+
: refusal.code === 'IA-DIST-RECOVERY-REQUIRED'
|
|
99
|
+
? `Rerun "${rerun}".`
|
|
100
|
+
: refusal.code === 'IA-DIST-PATH-UNSAFE' && existsSync(join(view.home, 'src'))
|
|
101
|
+
? homeSrcRemedy(view.home)
|
|
102
|
+
: refusal.code === 'IA-DIST-INPUT-INVALID'
|
|
103
|
+
? `Check the permissions of ${directory}, then rerun "${rerun}".`
|
|
104
|
+
: refusal.next;
|
|
105
|
+
return new Refusal(refusal.code, refusal.message, 3, refusal.where ?? { path: directory }, next);
|
|
106
|
+
}
|
|
107
|
+
function marketplaceStep(view, run) {
|
|
108
|
+
try {
|
|
109
|
+
return run();
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
throw marketplaceRefusal(error, view);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* §6.3: materialize, then register through `claude`; removal runs `claude` first and deletes the directory last, so a
|
|
117
|
+
* failed uninstall leaves the marketplace Claude still points at. A failing command refuses naming itself and the
|
|
118
|
+
* rerun, and the commands before it have run. A rerun converges: registration repeats two idempotent commands, and
|
|
119
|
+
* removal asks claude again what is left (§2.3).
|
|
120
|
+
*/
|
|
121
|
+
export function applyUserHost(view, runner) {
|
|
122
|
+
if (!view.remove)
|
|
123
|
+
marketplaceStep(view, () => materializeMarketplace(view.home, view.files));
|
|
124
|
+
const ran = [];
|
|
125
|
+
if (view.claude)
|
|
126
|
+
for (const command of view.commands) {
|
|
127
|
+
const result = runner.run(command);
|
|
128
|
+
if (result.status !== 0)
|
|
129
|
+
throw new Refusal('IA-CLI-HOST-COMMAND-FAILED', `${claudeCommand(command)} exited ${result.status ?? 'without a status'}: ${result.output || 'no output'}`, 3, null, `Run "${claudeCommand(command)}" yourself to see why, then rerun "${rerunOf(view.remove)}".`);
|
|
130
|
+
ran.push([...command]);
|
|
131
|
+
}
|
|
132
|
+
if (view.remove)
|
|
133
|
+
marketplaceStep(view, () => removeMarketplace(view.home));
|
|
134
|
+
const status = view.remove
|
|
135
|
+
? view.claude
|
|
136
|
+
? 'plugin-removed'
|
|
137
|
+
: 'plugin-directory-removed'
|
|
138
|
+
: view.claude
|
|
139
|
+
? 'plugin-registered'
|
|
140
|
+
: 'plugin-materialized';
|
|
141
|
+
return { status, ran };
|
|
142
|
+
}
|
|
143
|
+
/** §7.1 `--json`: the plan always, and `applied` only after an apply. The rendered files are not part of it. */
|
|
144
|
+
const envelope = (view, applied) => ({
|
|
145
|
+
version: 1,
|
|
146
|
+
command: 'host',
|
|
147
|
+
user: true,
|
|
148
|
+
host: view.host,
|
|
149
|
+
apply: applied !== null,
|
|
150
|
+
plan: {
|
|
151
|
+
remove: view.remove,
|
|
152
|
+
home: view.home,
|
|
153
|
+
marketplace: view.marketplace,
|
|
154
|
+
plugin: view.plugin,
|
|
155
|
+
installed: view.installed,
|
|
156
|
+
claude: view.claude,
|
|
157
|
+
commands: view.commands,
|
|
158
|
+
},
|
|
159
|
+
...(applied === null ? {} : { applied }),
|
|
160
|
+
});
|
|
161
|
+
const DONE = {
|
|
162
|
+
'plugin-registered': 'Registered: the plugin is written and each claude command exited 0. Claude Code loads it at its next session start.',
|
|
163
|
+
'plugin-materialized': 'Written; not registered with Claude.',
|
|
164
|
+
'plugin-removed': 'Removed: each claude command exited 0 and the plugin directory is deleted.',
|
|
165
|
+
'plugin-directory-removed': 'Deleted the plugin directory; not removed from Claude.',
|
|
166
|
+
};
|
|
167
|
+
const unavailable = (view, applied) => applied
|
|
168
|
+
? 'claude could not be run: run the claude commands above by hand.'
|
|
169
|
+
: `claude could not be run: apply ${view.remove ? 'deletes the directory' : 'writes the plugin'}, and the claude commands above must then be run by hand.`;
|
|
170
|
+
/** The content column of a depth-1 step (§6.4 rule 2), so a wrapped command breaks within the width. */
|
|
171
|
+
const STEP_COLUMN = (caps) => indentOf(1) + blockSymbolWidth(['step'], caps.ascii) + 2;
|
|
172
|
+
const summary = (view, context, applied = false) => {
|
|
173
|
+
const { caps } = context;
|
|
174
|
+
return [
|
|
175
|
+
[
|
|
176
|
+
...headerLine('Plan', `host claude --user${view.remove ? ' --remove' : ''}`, [], caps),
|
|
177
|
+
...headerLine('Home', view.home, [], caps),
|
|
178
|
+
],
|
|
179
|
+
[
|
|
180
|
+
...(view.remove
|
|
181
|
+
? []
|
|
182
|
+
: entry([words(`Write the plugin ${view.plugin.version} to ${view.marketplace}`)], { depth: 1, symbol: 'step' }, caps)),
|
|
183
|
+
...view.commands.flatMap((command) => entry(commandFacts('', claudeCommand(command), '', STEP_COLUMN(caps), caps), { depth: 1, symbol: 'step' }, caps)),
|
|
184
|
+
...(view.remove ? entry([words(`Delete ${view.marketplace}`)], { depth: 1, symbol: 'step' }, caps) : []),
|
|
185
|
+
],
|
|
186
|
+
...(view.claude ? [] : [entry([words(unavailable(view, applied))], { depth: 1, symbol: 'warning' }, caps)]),
|
|
187
|
+
];
|
|
188
|
+
};
|
|
189
|
+
function render(view, applied, context) {
|
|
190
|
+
const { caps } = context;
|
|
191
|
+
const [header, ...rest] = summary(view, context, applied !== null);
|
|
192
|
+
return document([
|
|
193
|
+
header,
|
|
194
|
+
applied === null
|
|
195
|
+
? entry([words('This is a preview. Nothing has been written.')], { depth: 1 }, caps)
|
|
196
|
+
: entry([words(DONE[applied.status])], { depth: 1, symbol: 'success' }, caps),
|
|
197
|
+
...rest,
|
|
198
|
+
...(applied === null
|
|
199
|
+
? [
|
|
200
|
+
entry(commandFacts('Apply with "', `${rerunOf(view.remove)} --yes`, '".', 3, caps), { depth: 0, symbol: 'step' }, caps),
|
|
201
|
+
]
|
|
202
|
+
: []),
|
|
203
|
+
], { leadingBlank: true });
|
|
204
|
+
}
|
|
205
|
+
const CONFIRMATION = 'Install the InventArch plugin? [y/N] ';
|
|
206
|
+
const REMOVAL_CONFIRMATION = 'Remove the InventArch plugin? [y/N] ';
|
|
207
|
+
export async function runUserHost(context) {
|
|
208
|
+
const { args, caps, host, json } = context;
|
|
209
|
+
const { view, runner } = collectUserHost(context);
|
|
210
|
+
const done = (applied) => json
|
|
211
|
+
? { exitCode: 0, stdout: JSON.stringify(envelope(view, applied)) + '\n', stderr: '' }
|
|
212
|
+
: { exitCode: 0, stdout: render(view, applied, context), stderr: '' };
|
|
213
|
+
if (!args.flag('apply'))
|
|
214
|
+
return done(null);
|
|
215
|
+
// §2.8 rule 3. Parsing has already refused every --apply whose question cannot be asked or answered.
|
|
216
|
+
if (!args.flag('yes') &&
|
|
217
|
+
!(await confirm(host.interaction, document(summary(view, context), { leadingBlank: true }), view.remove ? REMOVAL_CONFIRMATION : CONFIRMATION)))
|
|
218
|
+
return {
|
|
219
|
+
exitCode: 0,
|
|
220
|
+
stdout: document([entry([words('Nothing was applied.')], { depth: 0, symbol: 'info' }, caps)], {
|
|
221
|
+
leadingBlank: true,
|
|
222
|
+
}),
|
|
223
|
+
stderr: '',
|
|
224
|
+
};
|
|
225
|
+
host.signal?.throwIfAborted();
|
|
226
|
+
return done(applyUserHost(view, runner));
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=user-host.js.map
|