@skein-code/cli 0.3.1 → 0.3.3
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 +5 -0
- package/dist/cli.js +157 -20
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -85,6 +85,10 @@ To install the published package from npm:
|
|
|
85
85
|
npm install -g @skein-code/cli
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
Once installed, upgrade in place with `skein update` (it detects your package
|
|
89
|
+
manager and runs the matching global install). Add `--check` to only report a
|
|
90
|
+
newer version, or `--yes` to skip the confirmation prompt.
|
|
91
|
+
|
|
88
92
|
`skein` is the primary command. Existing installations can continue using
|
|
89
93
|
`mosaic` or `mosaic-code`; the `.mosaic/` project state and `MOSAIC_*`
|
|
90
94
|
environment variables remain compatible with this release.
|
|
@@ -224,6 +228,7 @@ skein --print [prompt] headless agent run
|
|
|
224
228
|
skein init project setup
|
|
225
229
|
skein doctor prerequisite and fallback checks
|
|
226
230
|
skein doctor --visual terminal rendering and input calibration
|
|
231
|
+
skein update upgrade to the latest release
|
|
227
232
|
skein config show resolved, redacted configuration
|
|
228
233
|
skein index build/update the selected index
|
|
229
234
|
skein search <query> ranked grounded spans
|
package/dist/cli.js
CHANGED
|
@@ -220,7 +220,7 @@ function isSqliteBusy(error) {
|
|
|
220
220
|
// package.json
|
|
221
221
|
var package_default = {
|
|
222
222
|
name: "@skein-code/cli",
|
|
223
|
-
version: "0.3.
|
|
223
|
+
version: "0.3.3",
|
|
224
224
|
description: "A context-first, model-agnostic coding agent with an auditable terminal workspace.",
|
|
225
225
|
type: "module",
|
|
226
226
|
license: "MIT",
|
|
@@ -236,8 +236,8 @@ var package_default = {
|
|
|
236
236
|
},
|
|
237
237
|
skein: {
|
|
238
238
|
releaseNotes: [
|
|
239
|
-
|
|
240
|
-
"
|
|
239
|
+
'Quieter turns: greetings like "hi" no longer dump a context panel',
|
|
240
|
+
"Redesigned entry banner into a bordered hero card with aligned metadata"
|
|
241
241
|
]
|
|
242
242
|
},
|
|
243
243
|
bin: {
|
|
@@ -7613,6 +7613,14 @@ function classifyTurnIntent(input2) {
|
|
|
7613
7613
|
if (/\b(explain|trace|understand|why|how)\b|解释|分析|梳理|为什么|如何/.test(value)) return "explain";
|
|
7614
7614
|
return "implement";
|
|
7615
7615
|
}
|
|
7616
|
+
function isTrivialTurn(input2) {
|
|
7617
|
+
const value = input2.trim().toLocaleLowerCase();
|
|
7618
|
+
if (!value) return true;
|
|
7619
|
+
if (value.includes("@") || value.includes("/") || value.includes("\\")) return false;
|
|
7620
|
+
if (value.length > 40) return false;
|
|
7621
|
+
const smallTalk = /^(hi+|hey+|hello+|yo|sup|hiya|howdy|ping|test|check|你好+|您好|哈喽|哈啰|哈罗|嗨+|在吗|在么|在不在|thanks?|thank you|thx|ty|cheers|谢谢|多谢|感谢|辛苦了|辛苦|ok|okay|okey|好的?|收到|明白|了解|nice|cool|great|awesome|bye|再见|拜拜|good ?(morning|night|evening|afternoon)|morning|gm|gn)[\s!.,。!?~、]*$/u;
|
|
7622
|
+
return smallTalk.test(value);
|
|
7623
|
+
}
|
|
7616
7624
|
function buildTurnDirective(input2) {
|
|
7617
7625
|
const intent = classifyTurnIntent(input2);
|
|
7618
7626
|
const guidance = {
|
|
@@ -7887,8 +7895,9 @@ var AgentRunner = class {
|
|
|
7887
7895
|
this.contextManager.startTurn(this.session, request);
|
|
7888
7896
|
this.session.messages.push(message("user", request));
|
|
7889
7897
|
await this.persist();
|
|
7898
|
+
const trivialTurn = isTrivialTurn(request);
|
|
7890
7899
|
const packed = await this.packContext(request);
|
|
7891
|
-
await emit({ type: "context", packed });
|
|
7900
|
+
if (!trivialTurn) await emit({ type: "context", packed });
|
|
7892
7901
|
const mentions = await this.packMentions(request);
|
|
7893
7902
|
const retrievedContext = buildRetrievedContext(
|
|
7894
7903
|
packed,
|
|
@@ -7927,7 +7936,7 @@ var AgentRunner = class {
|
|
|
7927
7936
|
...augmentation.skills?.length ? [`skills:${augmentation.skills.length}`] : [],
|
|
7928
7937
|
...augmentation.memoryCount ? [`memory:${augmentation.memoryCount}`] : []
|
|
7929
7938
|
];
|
|
7930
|
-
await emit({
|
|
7939
|
+
if (!trivialTurn) await emit({
|
|
7931
7940
|
type: "prompt",
|
|
7932
7941
|
intent: turnDirective.intent,
|
|
7933
7942
|
sections: promptSections,
|
|
@@ -12673,20 +12682,37 @@ function ThemePreview({ name, width, glyphs }) {
|
|
|
12673
12682
|
}
|
|
12674
12683
|
function Banner({ model, engine, workspace, version, width, glyphs }) {
|
|
12675
12684
|
const theme = useTheme();
|
|
12676
|
-
const
|
|
12685
|
+
const rowWidth = safeWidth(width);
|
|
12677
12686
|
const wordmark = `${glyphs.brand} ${PRODUCT_NAME.toUpperCase().split("").join(" ")}`;
|
|
12678
|
-
const
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
|
|
12689
|
-
|
|
12687
|
+
const innerWidth = Math.max(1, rowWidth - 4);
|
|
12688
|
+
const tagline = `v${version} ${glyphs.separator} a terminal coding agent you can see through`;
|
|
12689
|
+
const metaRows = [
|
|
12690
|
+
{ label: "model", value: sanitizeInlineTerminalText(model) },
|
|
12691
|
+
{ label: "engine", value: sanitizeInlineTerminalText(engine) },
|
|
12692
|
+
{ label: "cwd", value: compactDisplayPath(sanitizeInlineTerminalText(workspace), Math.max(12, innerWidth - 8)) }
|
|
12693
|
+
];
|
|
12694
|
+
const labelCol = 8;
|
|
12695
|
+
const hint = `type a request ${glyphs.separator} /help for commands ${glyphs.separator} @ to attach files`;
|
|
12696
|
+
return /* @__PURE__ */ jsxs(
|
|
12697
|
+
Box,
|
|
12698
|
+
{
|
|
12699
|
+
marginBottom: 1,
|
|
12700
|
+
flexDirection: "column",
|
|
12701
|
+
width: rowWidth,
|
|
12702
|
+
borderStyle: glyphs.borderStyle,
|
|
12703
|
+
borderColor: theme.border,
|
|
12704
|
+
paddingX: 1,
|
|
12705
|
+
children: [
|
|
12706
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: truncateDisplay(wordmark, innerWidth) }),
|
|
12707
|
+
/* @__PURE__ */ jsx(Text, { color: theme.muted, children: truncateDisplay(tagline, innerWidth) }),
|
|
12708
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, flexDirection: "column", children: metaRows.map((row) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
12709
|
+
/* @__PURE__ */ jsx(Text, { color: theme.dim, children: padDisplay(row.label, labelCol) }),
|
|
12710
|
+
/* @__PURE__ */ jsx(Text, { color: theme.text, children: truncateDisplay(row.value, Math.max(1, innerWidth - labelCol)) })
|
|
12711
|
+
] }, row.label)) }),
|
|
12712
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: theme.dim, children: truncateDisplay(hint, innerWidth) }) })
|
|
12713
|
+
]
|
|
12714
|
+
}
|
|
12715
|
+
);
|
|
12690
12716
|
}
|
|
12691
12717
|
function UpdateNotice({ current, latest, command: command2, highlights, width, glyphs }) {
|
|
12692
12718
|
const theme = useTheme();
|
|
@@ -13659,8 +13685,7 @@ function estimateTimelineItemRows(item, { width, compact = false, showToolOutput
|
|
|
13659
13685
|
if (item.kind === "agent" || item.kind === "agent-message") return rowWidth < 64 ? 2 : 1;
|
|
13660
13686
|
if (item.kind === "workflow") return rowWidth < 64 ? 2 : 1;
|
|
13661
13687
|
if (item.kind === "banner") {
|
|
13662
|
-
|
|
13663
|
-
return wordmarkRows + 3 + 1;
|
|
13688
|
+
return 2 + 2 + 1 + 3 + 1 + 1 + 1;
|
|
13664
13689
|
}
|
|
13665
13690
|
return 1;
|
|
13666
13691
|
}
|
|
@@ -17151,6 +17176,61 @@ function escapeXml2(value) {
|
|
|
17151
17176
|
})[character] ?? character);
|
|
17152
17177
|
}
|
|
17153
17178
|
|
|
17179
|
+
// src/utils/self-update.ts
|
|
17180
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
17181
|
+
import { realpathSync } from "node:fs";
|
|
17182
|
+
var GLOBAL_INSTALL_ARGS = {
|
|
17183
|
+
npm: (spec) => ["install", "-g", spec],
|
|
17184
|
+
pnpm: (spec) => ["add", "-g", spec],
|
|
17185
|
+
yarn: (spec) => ["global", "add", spec],
|
|
17186
|
+
bun: (spec) => ["add", "-g", spec]
|
|
17187
|
+
};
|
|
17188
|
+
function detectPackageManager(binaryPath = process.argv[1], env = process.env) {
|
|
17189
|
+
const fromAgent = parseUserAgent(env.npm_config_user_agent);
|
|
17190
|
+
if (fromAgent) return fromAgent;
|
|
17191
|
+
let resolved = binaryPath ?? "";
|
|
17192
|
+
try {
|
|
17193
|
+
if (resolved) resolved = realpathSync(resolved);
|
|
17194
|
+
} catch {
|
|
17195
|
+
}
|
|
17196
|
+
const path = resolved.replace(/\\/g, "/").toLowerCase();
|
|
17197
|
+
if (/(^|\/)\.bun\/|(^|\/)bun\//.test(path)) return "bun";
|
|
17198
|
+
if (/(^|\/)pnpm(\/|-global\/|$)/.test(path)) return "pnpm";
|
|
17199
|
+
if (/(^|\/)yarn\//.test(path)) return "yarn";
|
|
17200
|
+
return "npm";
|
|
17201
|
+
}
|
|
17202
|
+
function parseUserAgent(agent) {
|
|
17203
|
+
if (!agent) return null;
|
|
17204
|
+
const name = agent.trim().split("/")[0]?.toLowerCase();
|
|
17205
|
+
if (name === "pnpm" || name === "yarn" || name === "bun" || name === "npm") return name;
|
|
17206
|
+
return null;
|
|
17207
|
+
}
|
|
17208
|
+
function resolveUpgradePlan(options = {}) {
|
|
17209
|
+
const env = options.env ?? process.env;
|
|
17210
|
+
const spec = `${PACKAGE_NAME}@${options.version ?? "latest"}`;
|
|
17211
|
+
const manager = detectPackageManager(options.binaryPath, env);
|
|
17212
|
+
const args = GLOBAL_INSTALL_ARGS[manager](spec);
|
|
17213
|
+
return { command: manager, args, manager, display: `${manager} ${args.join(" ")}` };
|
|
17214
|
+
}
|
|
17215
|
+
function upgradeCommandOverride(env = process.env) {
|
|
17216
|
+
const raw = env.SKEIN_UPDATE_COMMAND ?? env.MOSAIC_UPDATE_COMMAND;
|
|
17217
|
+
const trimmed = raw?.trim();
|
|
17218
|
+
return trimmed ? trimmed : void 0;
|
|
17219
|
+
}
|
|
17220
|
+
function runUpgrade(plan) {
|
|
17221
|
+
return new Promise((resolve24) => {
|
|
17222
|
+
const child = spawn2(plan.command, plan.args, {
|
|
17223
|
+
stdio: "inherit",
|
|
17224
|
+
shell: plan.shell ?? false
|
|
17225
|
+
});
|
|
17226
|
+
child.on("error", () => resolve24({ ok: false, exitCode: 127, display: plan.display }));
|
|
17227
|
+
child.on("close", (code) => {
|
|
17228
|
+
const exitCode = code ?? 1;
|
|
17229
|
+
resolve24({ ok: exitCode === 0, exitCode, display: plan.display });
|
|
17230
|
+
});
|
|
17231
|
+
});
|
|
17232
|
+
}
|
|
17233
|
+
|
|
17154
17234
|
// src/cli.tsx
|
|
17155
17235
|
var cliGlyphs = resolveCliGlyphs();
|
|
17156
17236
|
var defaultWarningListeners = process.listeners("warning");
|
|
@@ -17254,6 +17334,63 @@ program.command("doctor").description("Diagnose prerequisites and safe fallbacks
|
|
|
17254
17334
|
const ok = await runDoctor(config, { json: options.json === true, visual: options.visual === true });
|
|
17255
17335
|
if (!ok) process.exitCode = 1;
|
|
17256
17336
|
});
|
|
17337
|
+
program.command("update").description("Update to the latest published release").option("--check", "only report whether a newer version is available").option("--yes", "skip the confirmation prompt and upgrade immediately").option("--json", "print the result as JSON").action(async (options) => {
|
|
17338
|
+
const json = options.json === true;
|
|
17339
|
+
const current = package_default.version;
|
|
17340
|
+
const notice = await refreshUpdateCache(current, { force: true }).catch(() => void 0);
|
|
17341
|
+
if (!notice) {
|
|
17342
|
+
if (json) printObject({ current, latest: current, upToDate: true }, true);
|
|
17343
|
+
else process.stdout.write(`${chalk4.green(cliGlyphs.success)} Already on the latest release (v${current}).
|
|
17344
|
+
`);
|
|
17345
|
+
return;
|
|
17346
|
+
}
|
|
17347
|
+
const override = upgradeCommandOverride();
|
|
17348
|
+
const plan = override ? { command: override, args: [], manager: "custom", display: override, shell: true } : { ...resolveUpgradePlan({ version: notice.latest }), shell: false };
|
|
17349
|
+
if (json && options.check === true) {
|
|
17350
|
+
printObject({ current, latest: notice.latest, upToDate: false, command: plan.display, ...notice.highlights ? { highlights: notice.highlights } : {} }, true);
|
|
17351
|
+
return;
|
|
17352
|
+
}
|
|
17353
|
+
process.stdout.write(`${chalk4.cyan(cliGlyphs.brand)} Update available ${chalk4.dim(`v${current}`)} ${cliGlyphs.separator} ${chalk4.green(`v${notice.latest}`)}
|
|
17354
|
+
`);
|
|
17355
|
+
for (const highlight of notice.highlights ?? []) {
|
|
17356
|
+
process.stdout.write(` ${cliGlyphs.separator} ${highlight}
|
|
17357
|
+
`);
|
|
17358
|
+
}
|
|
17359
|
+
if (options.check === true) {
|
|
17360
|
+
process.stdout.write(` Run ${chalk4.cyan(`${PRODUCT_COMMAND} update`)} to install ${chalk4.dim(`(${plan.display})`)}.
|
|
17361
|
+
`);
|
|
17362
|
+
return;
|
|
17363
|
+
}
|
|
17364
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
17365
|
+
if (options.yes !== true) {
|
|
17366
|
+
if (!interactive) {
|
|
17367
|
+
process.stdout.write(` Re-run with ${chalk4.cyan(`${PRODUCT_COMMAND} update --yes`)} to install ${chalk4.dim(`(${plan.display})`)}.
|
|
17368
|
+
`);
|
|
17369
|
+
return;
|
|
17370
|
+
}
|
|
17371
|
+
const rl = createInterface2({ input, output });
|
|
17372
|
+
try {
|
|
17373
|
+
const answer = (await rl.question(` Install ${chalk4.dim(plan.display)}? [Y/n] `)).trim().toLowerCase();
|
|
17374
|
+
if (answer === "n" || answer === "no") {
|
|
17375
|
+
process.stdout.write(" Update cancelled.\n");
|
|
17376
|
+
return;
|
|
17377
|
+
}
|
|
17378
|
+
} finally {
|
|
17379
|
+
rl.close();
|
|
17380
|
+
}
|
|
17381
|
+
}
|
|
17382
|
+
process.stdout.write(`${chalk4.dim(`${cliGlyphs.running} ${plan.display}`)}
|
|
17383
|
+
`);
|
|
17384
|
+
const result = await runUpgrade(plan);
|
|
17385
|
+
if (result.ok) {
|
|
17386
|
+
process.stdout.write(`${chalk4.green(cliGlyphs.success)} Updated to v${notice.latest}. Restart ${PRODUCT_COMMAND} to use it.
|
|
17387
|
+
`);
|
|
17388
|
+
} else {
|
|
17389
|
+
process.stdout.write(`${chalk4.red(cliGlyphs.error)} Update failed (exit ${result.exitCode}). Run ${chalk4.cyan(plan.display)} manually.
|
|
17390
|
+
`);
|
|
17391
|
+
process.exitCode = 1;
|
|
17392
|
+
}
|
|
17393
|
+
});
|
|
17257
17394
|
program.command("migrate").description("Inspect or migrate legacy .mosaic state into .skein").option("-w, --workspace <path>", "workspace root").option("--json", "print a migration manifest as JSON").option("--yes", "perform the migration after conflict checks").option("--rollback", "verify and roll back a completed migration").option("--recover", "inspect or recover interrupted migration/rollback state").option("--home", "operate on the user-level Skein/Mosaic namespace").action(async (options) => {
|
|
17258
17395
|
if (options.home && options.workspace) throw new Error("--workspace cannot be combined with --home.");
|
|
17259
17396
|
if (options.recover && options.rollback) throw new Error("--recover and --rollback cannot be combined.");
|