@noir-ai/cli 1.0.0-beta.1 → 1.2.0-beta.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/dist/bin.js +151 -69
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-UXT7YWQY.js → chunk-OMUB7XOA.js} +237 -86
- package/dist/chunk-OMUB7XOA.js.map +1 -0
- package/dist/chunk-UGUQQSWH.js +67 -0
- package/dist/chunk-UGUQQSWH.js.map +1 -0
- package/dist/create-WP5ZKMCW.js +42 -0
- package/dist/create-WP5ZKMCW.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +4 -2
- package/dist/sync-IEH2BVXU.js +46 -0
- package/dist/sync-IEH2BVXU.js.map +1 -0
- package/package.json +9 -8
- package/dist/chunk-UXT7YWQY.js.map +0 -1
- package/dist/sync-7YLRJYMR.js +0 -20
- package/dist/sync-7YLRJYMR.js.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -7,15 +7,19 @@ import {
|
|
|
7
7
|
handleError,
|
|
8
8
|
inferExitCode,
|
|
9
9
|
info,
|
|
10
|
-
init,
|
|
11
10
|
isInteractive,
|
|
12
11
|
log,
|
|
13
12
|
serve,
|
|
14
|
-
table
|
|
15
|
-
|
|
13
|
+
table,
|
|
14
|
+
warn
|
|
15
|
+
} from "./chunk-OMUB7XOA.js";
|
|
16
|
+
import {
|
|
17
|
+
init
|
|
18
|
+
} from "./chunk-UGUQQSWH.js";
|
|
16
19
|
|
|
17
20
|
// src/bin.ts
|
|
18
21
|
import { pathToFileURL } from "url";
|
|
22
|
+
import { SUPPORTED_HOSTS } from "@noir-ai/adapters";
|
|
19
23
|
import { NOIR_VERSION as NOIR_VERSION3 } from "@noir-ai/core";
|
|
20
24
|
import { Command, Option } from "commander";
|
|
21
25
|
|
|
@@ -58,7 +62,7 @@ async function probeDaemon(opts = {}) {
|
|
|
58
62
|
return { running: false };
|
|
59
63
|
}
|
|
60
64
|
const body = await res.json().catch(() => null);
|
|
61
|
-
if (
|
|
65
|
+
if (body?.ok !== true) {
|
|
62
66
|
if (opts.verbose) process.stderr.write("noir: daemon probe: /health body not ok\n");
|
|
63
67
|
return { running: false };
|
|
64
68
|
}
|
|
@@ -95,7 +99,7 @@ async function connectClient(client, url, opts) {
|
|
|
95
99
|
async function callToolParse(client, opts, name, args) {
|
|
96
100
|
const result = await client.callTool({ name, arguments: args }).catch((err) => failDaemonDown(opts, err));
|
|
97
101
|
const block = result.content?.[0];
|
|
98
|
-
if (
|
|
102
|
+
if (block?.type !== "text" || typeof block.text !== "string") {
|
|
99
103
|
failDaemonDown(opts, new Error(`tool '${name}' returned no text content`));
|
|
100
104
|
}
|
|
101
105
|
const text = block.text;
|
|
@@ -183,10 +187,10 @@ function failTool(label, envelope, opts) {
|
|
|
183
187
|
function toHit(raw) {
|
|
184
188
|
const h = raw ?? {};
|
|
185
189
|
return {
|
|
186
|
-
path: typeof h
|
|
187
|
-
score: typeof h
|
|
188
|
-
snippet: typeof h
|
|
189
|
-
source: typeof h
|
|
190
|
+
path: typeof h.path === "string" ? h.path : "<unknown>",
|
|
191
|
+
score: typeof h.score === "number" ? h.score : 0,
|
|
192
|
+
snippet: typeof h.snippet === "string" ? h.snippet : "",
|
|
193
|
+
source: typeof h.source === "string" ? h.source : ""
|
|
190
194
|
};
|
|
191
195
|
}
|
|
192
196
|
async function contextSearch(opts) {
|
|
@@ -422,7 +426,7 @@ async function daemonStatus(opts) {
|
|
|
422
426
|
} catch {
|
|
423
427
|
health = null;
|
|
424
428
|
}
|
|
425
|
-
if (
|
|
429
|
+
if (health?.ok !== true) {
|
|
426
430
|
clearDaemonRecord();
|
|
427
431
|
fail(
|
|
428
432
|
EXIT.DAEMON_DOWN,
|
|
@@ -553,15 +557,15 @@ function toHit2(raw) {
|
|
|
553
557
|
const h = raw ?? {};
|
|
554
558
|
const arr = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
555
559
|
return {
|
|
556
|
-
id: typeof h
|
|
557
|
-
type: typeof h
|
|
558
|
-
score: typeof h
|
|
559
|
-
content: typeof h
|
|
560
|
-
concepts: arr(h
|
|
561
|
-
files: arr(h
|
|
562
|
-
ts: typeof h
|
|
563
|
-
importance: typeof h
|
|
564
|
-
source: typeof h
|
|
560
|
+
id: typeof h.id === "string" ? h.id : "",
|
|
561
|
+
type: typeof h.type === "string" ? h.type : "",
|
|
562
|
+
score: typeof h.score === "number" ? h.score : 0,
|
|
563
|
+
content: typeof h.content === "string" ? h.content : "",
|
|
564
|
+
concepts: arr(h.concepts),
|
|
565
|
+
files: arr(h.files),
|
|
566
|
+
ts: typeof h.ts === "number" ? h.ts : 0,
|
|
567
|
+
importance: typeof h.importance === "number" ? h.importance : 0,
|
|
568
|
+
source: typeof h.source === "string" ? h.source : ""
|
|
565
569
|
};
|
|
566
570
|
}
|
|
567
571
|
function failTool2(label, envelope, opts) {
|
|
@@ -612,8 +616,8 @@ async function memorySave(opts) {
|
|
|
612
616
|
const content = await resolveContent(opts);
|
|
613
617
|
const files = splitCsv(opts.files);
|
|
614
618
|
const args = { content };
|
|
615
|
-
if (typeof opts.type === "string" && opts.type.length > 0) args
|
|
616
|
-
if (files !== void 0) args
|
|
619
|
+
if (typeof opts.type === "string" && opts.type.length > 0) args.type = opts.type;
|
|
620
|
+
if (files !== void 0) args.files = files;
|
|
617
621
|
const res = await callDaemonTool(opts, "memory_save", args);
|
|
618
622
|
if (res.ok !== true) failTool2("memory save", res, opts);
|
|
619
623
|
const id = typeof res.id === "string" ? res.id : "";
|
|
@@ -654,7 +658,7 @@ function renderObservation(obs, opts) {
|
|
|
654
658
|
if (obs[key] !== void 0) rows.push({ Field: key, Value: obs[key] });
|
|
655
659
|
}
|
|
656
660
|
if (rows.length > 0) table(rows, ["Field", "Value"], opts);
|
|
657
|
-
const content = obs
|
|
661
|
+
const content = obs.content;
|
|
658
662
|
if (typeof content === "string") log(`
|
|
659
663
|
${content}`, opts);
|
|
660
664
|
}
|
|
@@ -664,9 +668,9 @@ async function memorySessions(opts) {
|
|
|
664
668
|
const sessions = Array.isArray(res.sessions) ? res.sessions.map((raw) => {
|
|
665
669
|
const s = raw ?? {};
|
|
666
670
|
return {
|
|
667
|
-
id: typeof s
|
|
668
|
-
count: typeof s
|
|
669
|
-
lastTs: typeof s
|
|
671
|
+
id: typeof s.id === "string" ? s.id : "",
|
|
672
|
+
count: typeof s.count === "number" ? s.count : 0,
|
|
673
|
+
lastTs: typeof s.lastTs === "number" ? s.lastTs : 0
|
|
670
674
|
};
|
|
671
675
|
}) : [];
|
|
672
676
|
const data = { sessions };
|
|
@@ -711,8 +715,8 @@ async function memoryConsolidate(opts) {
|
|
|
711
715
|
const types = splitCsv(opts.types);
|
|
712
716
|
const limit = parseLimit2(opts.limit, "memory consolidate", opts);
|
|
713
717
|
const args = {};
|
|
714
|
-
if (types !== void 0) args
|
|
715
|
-
if (limit !== void 0) args
|
|
718
|
+
if (types !== void 0) args.types = types;
|
|
719
|
+
if (limit !== void 0) args.limit = limit;
|
|
716
720
|
const res = await callDaemonTool(
|
|
717
721
|
opts,
|
|
718
722
|
"memory_consolidate",
|
|
@@ -735,15 +739,15 @@ async function memoryConsolidate(opts) {
|
|
|
735
739
|
const l = lessons[i];
|
|
736
740
|
if (l === void 0) continue;
|
|
737
741
|
const obs = l ?? {};
|
|
738
|
-
const id = typeof obs
|
|
739
|
-
const content = typeof obs
|
|
742
|
+
const id = typeof obs.id === "string" ? obs.id : `<lesson ${i + 1}>`;
|
|
743
|
+
const content = typeof obs.content === "string" ? obs.content : "";
|
|
740
744
|
log(`- ${id}: ${content}`, opts);
|
|
741
745
|
}
|
|
742
746
|
return;
|
|
743
747
|
}
|
|
744
748
|
const env = res;
|
|
745
|
-
const reason = (typeof env
|
|
746
|
-
const logged = env
|
|
749
|
+
const reason = (typeof env.reason === "string" ? env.reason : void 0) ?? (typeof env.error === "string" ? env.error : void 0) ?? "unknown";
|
|
750
|
+
const logged = env.logged === true || env.degraded === true;
|
|
747
751
|
const suffix = logged ? " (logged)" : "";
|
|
748
752
|
fail(EXIT.ERROR, `memory consolidate did not run: ${reason}${suffix}`, opts);
|
|
749
753
|
}
|
|
@@ -751,7 +755,10 @@ async function memoryConsolidate(opts) {
|
|
|
751
755
|
// src/commands/skills.ts
|
|
752
756
|
import { claudeAdapter } from "@noir-ai/adapters";
|
|
753
757
|
import { loadProjectInfo as loadProjectInfo4 } from "@noir-ai/core";
|
|
754
|
-
import {
|
|
758
|
+
import {
|
|
759
|
+
discoverAll,
|
|
760
|
+
emitSkillsToDir
|
|
761
|
+
} from "@noir-ai/skills";
|
|
755
762
|
var CATEGORY = {
|
|
756
763
|
"noir-brainstorm": "discovery",
|
|
757
764
|
"noir-intake": "discovery",
|
|
@@ -790,9 +797,9 @@ function categoryOf(name) {
|
|
|
790
797
|
if (mapped !== void 0) return mapped;
|
|
791
798
|
return name.replace(/^noir-/, "") || "general";
|
|
792
799
|
}
|
|
793
|
-
function toRow(s) {
|
|
800
|
+
function toRow(s, kind = "builtin") {
|
|
794
801
|
const description = typeof s.frontmatter.description === "string" ? s.frontmatter.description : "";
|
|
795
|
-
return { name: s.name, category: categoryOf(s.name), description };
|
|
802
|
+
return { name: s.name, category: categoryOf(s.name), description, kind };
|
|
796
803
|
}
|
|
797
804
|
function truncate(text, max) {
|
|
798
805
|
if (text.length <= max) return text;
|
|
@@ -803,30 +810,39 @@ function truncate(text, max) {
|
|
|
803
810
|
}
|
|
804
811
|
async function skillsList(opts) {
|
|
805
812
|
let builtins;
|
|
813
|
+
let integrations;
|
|
806
814
|
try {
|
|
807
|
-
|
|
815
|
+
const all = discoverAll();
|
|
816
|
+
builtins = all.builtins;
|
|
817
|
+
integrations = all.integrations;
|
|
808
818
|
} catch (err) {
|
|
809
819
|
fail(
|
|
810
820
|
EXIT.ERROR,
|
|
811
|
-
`skills list: could not discover
|
|
821
|
+
`skills list: could not discover skills (${err instanceof Error ? err.message : String(err)})`,
|
|
812
822
|
opts
|
|
813
823
|
);
|
|
814
824
|
}
|
|
815
|
-
const rows =
|
|
825
|
+
const rows = [
|
|
826
|
+
...builtins.map((b) => toRow(b, "builtin")),
|
|
827
|
+
...integrations.map((i) => toRow(i, "integration"))
|
|
828
|
+
];
|
|
816
829
|
const data = { count: rows.length, skills: rows };
|
|
817
830
|
if (opts.json === true) {
|
|
818
831
|
process.stdout.write(`${JSON.stringify({ ok: true, data })}
|
|
819
832
|
`);
|
|
820
833
|
return;
|
|
821
834
|
}
|
|
822
|
-
|
|
835
|
+
const intCount = integrations.length;
|
|
836
|
+
const banner = intCount > 0 ? `noir skills \u2014 ${rows.length} skill${rows.length === 1 ? "" : "s"} (${builtins.length} builtin, ${intCount} integration${intCount === 1 ? "" : "s"})` : `noir skills \u2014 ${rows.length} builtin skill${rows.length === 1 ? "" : "s"}`;
|
|
837
|
+
log(banner, opts);
|
|
823
838
|
table(
|
|
824
839
|
rows.map((r) => ({
|
|
825
840
|
Skill: r.name,
|
|
841
|
+
Kind: r.kind,
|
|
826
842
|
Category: r.category,
|
|
827
843
|
Description: truncate(r.description, 80)
|
|
828
844
|
})),
|
|
829
|
-
["Skill", "Category", "Description"],
|
|
845
|
+
["Skill", "Kind", "Category", "Description"],
|
|
830
846
|
opts
|
|
831
847
|
);
|
|
832
848
|
}
|
|
@@ -850,10 +866,12 @@ async function skillsSync(opts) {
|
|
|
850
866
|
}
|
|
851
867
|
const dir = claudeAdapter.skillsDir({ root });
|
|
852
868
|
const summary = await emitSkillsToDir(dir);
|
|
869
|
+
const pruned = summary.pruned ?? [];
|
|
853
870
|
const data = {
|
|
854
871
|
emitted: summary.emitted,
|
|
855
872
|
references: summary.references,
|
|
856
|
-
dir
|
|
873
|
+
dir,
|
|
874
|
+
pruned
|
|
857
875
|
};
|
|
858
876
|
if (opts.json === true) {
|
|
859
877
|
process.stdout.write(`${JSON.stringify({ ok: true, data })}
|
|
@@ -864,6 +882,12 @@ async function skillsSync(opts) {
|
|
|
864
882
|
`Synced ${summary.emitted.length} Noir skill${summary.emitted.length === 1 ? "" : "s"} to ${dir}.`,
|
|
865
883
|
opts
|
|
866
884
|
);
|
|
885
|
+
if (pruned.length > 0) {
|
|
886
|
+
warn(
|
|
887
|
+
`Pruned ${pruned.length} stale noir-* skill dir${pruned.length === 1 ? "" : "s"}: ${pruned.join(", ")}`,
|
|
888
|
+
opts
|
|
889
|
+
);
|
|
890
|
+
}
|
|
867
891
|
}
|
|
868
892
|
|
|
869
893
|
// src/commands/status.ts
|
|
@@ -876,7 +900,7 @@ async function tryTool(caller, name) {
|
|
|
876
900
|
}
|
|
877
901
|
}
|
|
878
902
|
function pickStore(s) {
|
|
879
|
-
if (
|
|
903
|
+
if (s?.ok !== true) return null;
|
|
880
904
|
return {
|
|
881
905
|
docCount: s.docCount,
|
|
882
906
|
vecCount: s.vecCount,
|
|
@@ -890,7 +914,7 @@ function describeEmbedder2(e) {
|
|
|
890
914
|
return `${e.kind} \xB7 ${model} (${e.dim}-dim)`;
|
|
891
915
|
}
|
|
892
916
|
function pickContext(c) {
|
|
893
|
-
if (
|
|
917
|
+
if (c?.ok !== true) return null;
|
|
894
918
|
return {
|
|
895
919
|
docCount: c.docCount,
|
|
896
920
|
vecCount: c.vecCount,
|
|
@@ -900,7 +924,7 @@ function pickContext(c) {
|
|
|
900
924
|
};
|
|
901
925
|
}
|
|
902
926
|
function pickWorkflow(w) {
|
|
903
|
-
if (
|
|
927
|
+
if (w?.ok !== true) return null;
|
|
904
928
|
return {
|
|
905
929
|
taskId: w.taskId,
|
|
906
930
|
phase: w.phase,
|
|
@@ -911,7 +935,7 @@ function pickWorkflow(w) {
|
|
|
911
935
|
};
|
|
912
936
|
}
|
|
913
937
|
function pickMemory(m) {
|
|
914
|
-
if (
|
|
938
|
+
if (m?.ok !== true || !Array.isArray(m.sessions)) return null;
|
|
915
939
|
let observations = 0;
|
|
916
940
|
for (const s of m.sessions) observations += s.count;
|
|
917
941
|
return { sessions: m.sessions.length, observations };
|
|
@@ -1186,15 +1210,20 @@ function toStatusOptions(g) {
|
|
|
1186
1210
|
input: g.input !== false
|
|
1187
1211
|
};
|
|
1188
1212
|
}
|
|
1213
|
+
function parseHost(raw) {
|
|
1214
|
+
if (raw === void 0) return void 0;
|
|
1215
|
+
return raw;
|
|
1216
|
+
}
|
|
1189
1217
|
function createProgram() {
|
|
1190
1218
|
const program2 = new Command();
|
|
1191
1219
|
program2.name("noir").description("Noir \u2014 discipline, context, and memory layer for agentic CLIs.").version(NOIR_VERSION3, "-v, --version").addOption(new Option("--json", "emit machine-readable JSON to stdout")).addOption(new Option("--no-input", "never prompt; error if input is required")).addOption(new Option("--quiet", "suppress non-essential diagnostics")).addOption(new Option("--verbose", "show additional diagnostic detail")).addOption(new Option("--cwd <path>", "run as if started in <path>")).exitOverride((err) => {
|
|
1192
1220
|
throw err;
|
|
1193
1221
|
}).configureOutput({
|
|
1194
|
-
//
|
|
1195
|
-
// errors
|
|
1196
|
-
//
|
|
1197
|
-
|
|
1222
|
+
// Stream discipline: --help/--version → stdout (conventional; users pipe
|
|
1223
|
+
// them), errors → stderr. --json data is emitted by command actions via
|
|
1224
|
+
// process.stdout directly, NOT by commander's writeOut, so routing help/
|
|
1225
|
+
// version to stdout does not conflict with --json payloads.
|
|
1226
|
+
writeOut: (str) => process.stdout.write(str),
|
|
1198
1227
|
writeErr: (str) => process.stderr.write(str)
|
|
1199
1228
|
});
|
|
1200
1229
|
program2.hook("preAction", (_thisCmd, actionCmd) => {
|
|
@@ -1211,13 +1240,66 @@ function createProgram() {
|
|
|
1211
1240
|
}
|
|
1212
1241
|
}
|
|
1213
1242
|
});
|
|
1214
|
-
program2.command("init").description("scaffold Noir in the current project (.noir/, .mcp.json, CLAUDE.md, skills)").option("--transport <transport>", "stdio | streamable-http (default: stdio)", "stdio").option("--url <url>", "streamable-http daemon URL (localhost only)").
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1243
|
+
program2.command("init").description("scaffold Noir in the current project (.noir/, .mcp.json, CLAUDE.md, skills)").option("--transport <transport>", "stdio | streamable-http (default: stdio)", "stdio").option("--url <url>", "streamable-http daemon URL (localhost only)").option(
|
|
1244
|
+
"--upgrade",
|
|
1245
|
+
"run scaffold migrations before re-emitting (re-run on an existing project)"
|
|
1246
|
+
).addOption(
|
|
1247
|
+
// S10: target host. Defaults to `'claude'` (the regression anchor). The
|
|
1248
|
+
// chosen host is forwarded to scaffold() + skills emission via
|
|
1249
|
+
// resolveAdapter. The choice list mirrors `SUPPORTED_HOSTS` so a new host
|
|
1250
|
+
// lands here automatically; commander rejects anything else as usage=2.
|
|
1251
|
+
new Option(
|
|
1252
|
+
"--host <id>",
|
|
1253
|
+
"target agentic CLI (default: claude) \u2014 drives host-side emission"
|
|
1254
|
+
).choices(SUPPORTED_HOSTS)
|
|
1255
|
+
).action(
|
|
1256
|
+
async (opts) => {
|
|
1257
|
+
const transport = opts.transport === "streamable-http" ? "streamable-http" : "stdio";
|
|
1258
|
+
const upgrade = opts.upgrade === true;
|
|
1259
|
+
const host = parseHost(opts.host);
|
|
1260
|
+
await init(process.cwd(), {
|
|
1261
|
+
transport,
|
|
1262
|
+
url: opts.url,
|
|
1263
|
+
...upgrade ? { upgrade } : {},
|
|
1264
|
+
...host !== void 0 ? { host } : {}
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
);
|
|
1268
|
+
program2.command("create [dir]").description("bootstrap the Noir AI layer in a new or empty directory").option("--transport <transport>", "stdio | streamable-http (default: stdio)", "stdio").option("--url <url>", "streamable-http daemon URL (localhost only)").addOption(
|
|
1269
|
+
new Option(
|
|
1270
|
+
"--host <id>",
|
|
1271
|
+
"target agentic CLI (default: claude) \u2014 drives host-side emission"
|
|
1272
|
+
).choices(SUPPORTED_HOSTS)
|
|
1273
|
+
).action(
|
|
1274
|
+
async (dir, opts) => {
|
|
1275
|
+
const transport = opts.transport === "streamable-http" ? "streamable-http" : "stdio";
|
|
1276
|
+
const host = parseHost(opts.host);
|
|
1277
|
+
const { create } = await import("./create-WP5ZKMCW.js");
|
|
1278
|
+
await create(dir, {
|
|
1279
|
+
transport,
|
|
1280
|
+
url: opts.url,
|
|
1281
|
+
...host !== void 0 ? { host } : {}
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
);
|
|
1285
|
+
program2.command("sync").description(
|
|
1286
|
+
"re-emit Noir managed files (.mcp.json, CLAUDE.md blocks, NOIR.md brief, ignores) + skills"
|
|
1287
|
+
).addOption(
|
|
1288
|
+
// S10: optional `--host` override. When omitted, sync reads host from
|
|
1289
|
+
// `.noir/config.yml` (whatever `noir init --host <id>` persisted). The
|
|
1290
|
+
// override is rarely needed — documented as advanced.
|
|
1291
|
+
new Option(
|
|
1292
|
+
"--host <id>",
|
|
1293
|
+
"override the configured host (advanced; default reads .noir/config.yml)"
|
|
1294
|
+
).choices(SUPPORTED_HOSTS)
|
|
1295
|
+
).action(async (opts) => {
|
|
1296
|
+
const { sync } = await import("./sync-IEH2BVXU.js");
|
|
1297
|
+
const host = parseHost(opts.host);
|
|
1298
|
+
if (host === void 0) {
|
|
1299
|
+
await sync(process.cwd());
|
|
1300
|
+
} else {
|
|
1301
|
+
await sync(process.cwd(), { host });
|
|
1302
|
+
}
|
|
1221
1303
|
});
|
|
1222
1304
|
const mcpCmd = program2.command("mcp").description("MCP server control");
|
|
1223
1305
|
mcpCmd.command("serve").description("run the Noir MCP server (stdio, or via the shared daemon)").option("--stdio", "force the stdio transport").action(async (opts) => {
|
|
@@ -1230,7 +1312,7 @@ function createProgram() {
|
|
|
1230
1312
|
daemonGrp.command("start").description("start the Noir daemon (foreground; backgrounding deferred)").option("--detach", "run in the background (not yet implemented; exits 2)").action(async (...args) => {
|
|
1231
1313
|
const cmd = trailingCmd(args);
|
|
1232
1314
|
const g = cmd.optsWithGlobals();
|
|
1233
|
-
const detach = g
|
|
1315
|
+
const detach = g.detach === true;
|
|
1234
1316
|
await daemonStart({ ...toCliOptions(g), ...detach ? { detach } : {} });
|
|
1235
1317
|
});
|
|
1236
1318
|
daemonGrp.command("stop").description("stop the Noir daemon").action(async (...args) => {
|
|
@@ -1256,7 +1338,7 @@ function createProgram() {
|
|
|
1256
1338
|
const cmd = trailingCmd(args);
|
|
1257
1339
|
const g = cmd.optsWithGlobals();
|
|
1258
1340
|
const query = typeof args[0] === "string" ? args[0] : "";
|
|
1259
|
-
const limit = typeof g
|
|
1341
|
+
const limit = typeof g.limit === "string" ? g.limit : void 0;
|
|
1260
1342
|
await contextSearch({
|
|
1261
1343
|
...toCliOptions(g),
|
|
1262
1344
|
query,
|
|
@@ -1271,8 +1353,8 @@ function createProgram() {
|
|
|
1271
1353
|
).option("--force", "ignore content-hash caching (recognized; not yet honored)").action(async (...args) => {
|
|
1272
1354
|
const cmd = trailingCmd(args);
|
|
1273
1355
|
const g = cmd.optsWithGlobals();
|
|
1274
|
-
const rawPaths = Array.isArray(g
|
|
1275
|
-
const force = g
|
|
1356
|
+
const rawPaths = Array.isArray(g.path) ? g.path.filter((p) => typeof p === "string") : [];
|
|
1357
|
+
const force = g.force === true;
|
|
1276
1358
|
await contextIndex({
|
|
1277
1359
|
...toCliOptions(g),
|
|
1278
1360
|
...rawPaths.length === 0 ? {} : { paths: rawPaths },
|
|
@@ -1290,7 +1372,7 @@ function createProgram() {
|
|
|
1290
1372
|
const cmd = trailingCmd(args);
|
|
1291
1373
|
const g = cmd.optsWithGlobals();
|
|
1292
1374
|
const query = typeof args[0] === "string" ? args[0] : "";
|
|
1293
|
-
const limit = typeof g
|
|
1375
|
+
const limit = typeof g.limit === "string" ? g.limit : void 0;
|
|
1294
1376
|
await memoryRecall({
|
|
1295
1377
|
...toCliOptions(g),
|
|
1296
1378
|
query,
|
|
@@ -1303,9 +1385,9 @@ function createProgram() {
|
|
|
1303
1385
|
).option("--files <files>", "comma-separated related file paths").action(async (...args) => {
|
|
1304
1386
|
const cmd = trailingCmd(args);
|
|
1305
1387
|
const g = cmd.optsWithGlobals();
|
|
1306
|
-
const content = typeof g
|
|
1307
|
-
const type = typeof g
|
|
1308
|
-
const files = typeof g
|
|
1388
|
+
const content = typeof g.content === "string" ? g.content : void 0;
|
|
1389
|
+
const type = typeof g.type === "string" ? g.type : void 0;
|
|
1390
|
+
const files = typeof g.files === "string" ? g.files : void 0;
|
|
1309
1391
|
await memorySave({
|
|
1310
1392
|
...toCliOptions(g),
|
|
1311
1393
|
...content === void 0 ? {} : { content },
|
|
@@ -1326,8 +1408,8 @@ function createProgram() {
|
|
|
1326
1408
|
memoryGrp.command("consolidate").description("consolidate memories into a derived lesson (provider-explicit)").option("--types <types>", "comma-separated observation types to consolidate").option("--limit <n>", "cap on candidate observations").action(async (...args) => {
|
|
1327
1409
|
const cmd = trailingCmd(args);
|
|
1328
1410
|
const g = cmd.optsWithGlobals();
|
|
1329
|
-
const types = typeof g
|
|
1330
|
-
const limit = typeof g
|
|
1411
|
+
const types = typeof g.types === "string" ? g.types : void 0;
|
|
1412
|
+
const limit = typeof g.limit === "string" ? g.limit : void 0;
|
|
1331
1413
|
await memoryConsolidate({
|
|
1332
1414
|
...toCliOptions(g),
|
|
1333
1415
|
...types === void 0 ? {} : { types },
|
|
@@ -1354,8 +1436,8 @@ function createProgram() {
|
|
|
1354
1436
|
taskGrp.command("new").description("start a new workflow task").requiredOption("--slug <slug>", "task slug").option("--mode <mode>", "full | quick").action(async (...args) => {
|
|
1355
1437
|
const cmd = trailingCmd(args);
|
|
1356
1438
|
const g = cmd.optsWithGlobals();
|
|
1357
|
-
const slug = typeof g
|
|
1358
|
-
const mode = typeof g
|
|
1439
|
+
const slug = typeof g.slug === "string" ? g.slug : "";
|
|
1440
|
+
const mode = typeof g.mode === "string" ? g.mode : void 0;
|
|
1359
1441
|
await taskNew({
|
|
1360
1442
|
...toCliOptions(g),
|
|
1361
1443
|
slug,
|
|
@@ -1375,8 +1457,8 @@ function createProgram() {
|
|
|
1375
1457
|
taskGrp.command("advance").description("advance the active task to the next phase").option("--to <phase>", "target phase").option("--force <reason>", "force the gate with a reason").action(async (...args) => {
|
|
1376
1458
|
const cmd = trailingCmd(args);
|
|
1377
1459
|
const g = cmd.optsWithGlobals();
|
|
1378
|
-
const to = typeof g
|
|
1379
|
-
const force = typeof g
|
|
1460
|
+
const to = typeof g.to === "string" ? g.to : void 0;
|
|
1461
|
+
const force = typeof g.force === "string" ? g.force : void 0;
|
|
1380
1462
|
await taskAdvance({
|
|
1381
1463
|
...toCliOptions(g),
|
|
1382
1464
|
...to === void 0 ? {} : { to },
|