@letterstory/cli 0.33.6 → 0.33.8

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/lib/cli.mjs CHANGED
@@ -45,7 +45,7 @@ import {
45
45
  } from "./commands.mjs";
46
46
 
47
47
  // Keep in sync with cli/package.json.
48
- export const VERSION = "0.33.6";
48
+ export const VERSION = "0.33.8";
49
49
 
50
50
  // Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
51
51
  // can't accidentally swallow the id as --json's value.
@@ -109,6 +109,7 @@ export const ARGS = {
109
109
  input: { value: (flags) => readBodyInput(flags) },
110
110
  kernel_id: "kernel",
111
111
  target_word_count: { flag: "words", type: "num" },
112
+ target_word_tolerance: { flag: "words-tolerance", type: "num" },
112
113
  label: "label",
113
114
  // The flag is --read-as, which is what shipped; an earlier draft called it --brief-mode.
114
115
  content_kind: {
@@ -218,6 +219,22 @@ export const ARGS = {
218
219
  kernel_id: { positional: 1, label: "kernel-id", required: true },
219
220
  eval_id: { positional: 2, label: "eval-id", required: true },
220
221
  },
222
+ update_kernel: {
223
+ kernel_id: { positional: 0, label: "kernel-id", required: true },
224
+ name: "name",
225
+ description: "description",
226
+ // A whole-document JSON file, same reasoning as add_kernel_custom_eval's detector/repair:
227
+ // register/humor/inquisitive/notes together are a real object, not four independent
228
+ // flags — kernelVoiceConfigSchema requires register/humor/inquisitive all at once, so a
229
+ // partial flag set would just fail the tool's own validation anyway.
230
+ voice_config: { value: (flags) => readJsonFileFlag(flags, "voice-config-file") },
231
+ },
232
+ archive_kernel: {
233
+ kernel_id: { positional: 0, label: "kernel-id", required: true },
234
+ },
235
+ get_kernel_endpoint_run_steps: {
236
+ run_id: { positional: 0, label: "run-id", required: true },
237
+ },
221
238
  };
222
239
 
223
240
  export async function cmdKernel(ctx) {
@@ -237,6 +254,10 @@ export async function cmdKernel(ctx) {
237
254
  return kernelEndpoint(rest);
238
255
  case "eval":
239
256
  return kernelEval(rest);
257
+ case "update":
258
+ return kernelUpdate(rest);
259
+ case "archive":
260
+ return kernelArchive(rest);
240
261
  case "write":
241
262
  return kernelWrite(rest);
242
263
  case "polish":
@@ -249,7 +270,7 @@ export async function cmdKernel(ctx) {
249
270
  return kernelBalance(rest);
250
271
  default:
251
272
  throw new CliError(
252
- `Unknown kernel subcommand: ${sub ?? "(none)"}. Try: list, endpoints, endpoint, eval, write, polish, run-status, runs, balance, run, status`
273
+ `Unknown kernel subcommand: ${sub ?? "(none)"}. Try: list, endpoints, endpoint, eval, update, archive, write, polish, run-status, runs, balance, run, status`
253
274
  );
254
275
  }
255
276
  }
@@ -472,6 +493,39 @@ async function kernelEval(ctx) {
472
493
  throw new CliError(`Unknown kernel eval action: ${action ?? "(none)"}. Try: add, rm`);
473
494
  }
474
495
 
496
+ /**
497
+ * `kernel update <kernel-id>` — name/description/voice on an org-owned kernel. Raw
498
+ * prompt/config editing stays staff-only (the app's own developer console), same as always.
499
+ */
500
+ async function kernelUpdate(ctx) {
501
+ const { client, positionals, flags, io } = ctx;
502
+ const args = argsFromFlags(ARGS.update_kernel, flags, positionals);
503
+ if (args.name === undefined && args.description === undefined && args.voice_config === undefined) {
504
+ throw new CliError("Provide at least one of --name, --description, --voice-config-file <path>.");
505
+ }
506
+ const result = await client.callTool("update_kernel", args);
507
+ ok(ctx, `Updated kernel ${args.kernel_id}.`);
508
+ printResult(io, flags, result);
509
+ return 0;
510
+ }
511
+
512
+ /**
513
+ * `kernel archive <kernel-id>` — never a hard delete; every run it ever produced keeps its
514
+ * attribution. Requires --yes, same as every other destructive kernel/endpoint command.
515
+ */
516
+ async function kernelArchive(ctx) {
517
+ const { client, positionals, flags, io } = ctx;
518
+ const args = argsFromFlags(ARGS.archive_kernel, flags, positionals);
519
+ if (!flags.yes) {
520
+ io.error(`Re-run with --yes to confirm: ${ctx.bin} kernel archive ${args.kernel_id} --yes`);
521
+ return 1;
522
+ }
523
+ const result = await client.callTool("archive_kernel", args);
524
+ ok(ctx, `Archived kernel ${args.kernel_id}.`);
525
+ printResult(io, flags, result);
526
+ return 0;
527
+ }
528
+
475
529
  /**
476
530
  * The OTHER door: run the same pipeline against a document you already have, instead of
477
531
  * writing a new one. Decomposed into a brief and GENERATED FRESH (content_kind: "article",
@@ -535,6 +589,16 @@ async function kernelPolish(ctx) {
535
589
  async function kernelRunStatus(ctx) {
536
590
  const { client, positionals, flags, io } = ctx;
537
591
  const runId = requirePositional(positionals, 0, "run-id");
592
+ if (flags.steps === true) {
593
+ // The round-by-round draft trace instead of the run summary — the same view the app's
594
+ // kernel detail page shows as its version-diff and rule-trip panels.
595
+ const result = await client.callTool(
596
+ "get_kernel_endpoint_run_steps",
597
+ argsFromFlags(ARGS.get_kernel_endpoint_run_steps, flags, positionals)
598
+ );
599
+ printResult(io, flags, result);
600
+ return 0;
601
+ }
538
602
  const result = await client.callTool("get_kernel_endpoint_run", { run_id: runId });
539
603
  printRecordLine(ctx, result);
540
604
  printResult(io, flags, result);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.33.6",
3
+ "version": "0.33.8",
4
4
  "description": "Spin up and manage Letterstory phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",