@noir-ai/cli 1.17.0-beta.1 → 1.18.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 +89 -27
- package/dist/bin.js.map +1 -1
- package/dist/hygiene-scan.js +10 -1
- package/dist/hygiene-scan.js.map +1 -1
- package/dist/index.js +123 -61
- package/dist/index.js.map +1 -1
- package/dist/tui/{chunk-NZMM6YXE.js → chunk-A5XEQWRN.js} +82 -26
- package/dist/tui/chunk-A5XEQWRN.js.map +1 -0
- package/dist/tui/{create-4XGNRRP7.js → create-GUXMIKZB.js} +2 -2
- package/dist/tui/index.js +1 -1
- package/dist/tui/{sync-Q3KXM5RQ.js → sync-PXMB4SJT.js} +2 -2
- package/package.json +11 -11
- package/dist/tui/chunk-NZMM6YXE.js.map +0 -1
- /package/dist/tui/{create-4XGNRRP7.js.map → create-GUXMIKZB.js.map} +0 -0
- /package/dist/tui/{sync-Q3KXM5RQ.js.map → sync-PXMB4SJT.js.map} +0 -0
package/dist/bin.js
CHANGED
|
@@ -1999,7 +1999,8 @@ function hasScannableLayout(root) {
|
|
|
1999
1999
|
}
|
|
2000
2000
|
function addHygieneFile(rel, walk) {
|
|
2001
2001
|
const name = rel.slice(rel.lastIndexOf("/") + 1);
|
|
2002
|
-
if (name.startsWith(".") || HYGIENE_EXCLUDED_FILES.has(name))
|
|
2002
|
+
if (name.startsWith(".") || HYGIENE_EXCLUDED_FILES.has(name) || HYGIENE_EXCLUDED_PATHS.has(rel))
|
|
2003
|
+
return;
|
|
2003
2004
|
const kind = hygieneKindOf(rel);
|
|
2004
2005
|
if (kind === null) return;
|
|
2005
2006
|
if (walk.files.length >= HYGIENE_MAX_FILES) {
|
|
@@ -2117,7 +2118,7 @@ function scanOutputHygiene(root) {
|
|
|
2117
2118
|
warn: findings.length - fail2
|
|
2118
2119
|
};
|
|
2119
2120
|
}
|
|
2120
|
-
var HYGIENE_FINDING_CAP, HYGIENE_MAX_FILE_BYTES, HYGIENE_MAX_FILES, HYGIENE_CODE_EXTENSIONS, HYGIENE_MARKDOWN_EXTENSIONS, HYGIENE_SKIP_DIRS, HYGIENE_EXCLUDED_DIRS, HYGIENE_EXCLUDED_FILES, NO_SKIP_DIRS;
|
|
2121
|
+
var HYGIENE_FINDING_CAP, HYGIENE_MAX_FILE_BYTES, HYGIENE_MAX_FILES, HYGIENE_CODE_EXTENSIONS, HYGIENE_MARKDOWN_EXTENSIONS, HYGIENE_SKIP_DIRS, HYGIENE_EXCLUDED_DIRS, HYGIENE_EXCLUDED_FILES, HYGIENE_EXCLUDED_PATHS, NO_SKIP_DIRS;
|
|
2121
2122
|
var init_hygiene_scan = __esm({
|
|
2122
2123
|
"src/hygiene-scan.ts"() {
|
|
2123
2124
|
"use strict";
|
|
@@ -2129,6 +2130,14 @@ var init_hygiene_scan = __esm({
|
|
|
2129
2130
|
HYGIENE_SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage"]);
|
|
2130
2131
|
HYGIENE_EXCLUDED_DIRS = /* @__PURE__ */ new Set(["docs/internal", "docs/decisions", "docs/roadmap"]);
|
|
2131
2132
|
HYGIENE_EXCLUDED_FILES = /* @__PURE__ */ new Set(["CHANGELOG.md"]);
|
|
2133
|
+
HYGIENE_EXCLUDED_PATHS = /* @__PURE__ */ new Set([
|
|
2134
|
+
"docs/README.md",
|
|
2135
|
+
"docs/reference/cli.md",
|
|
2136
|
+
"docs/reference/config.md",
|
|
2137
|
+
"docs/reference/mcp-tools.md",
|
|
2138
|
+
"docs/reference/packages.md",
|
|
2139
|
+
"docs/reference/skills.md"
|
|
2140
|
+
]);
|
|
2132
2141
|
NO_SKIP_DIRS = /* @__PURE__ */ new Set();
|
|
2133
2142
|
}
|
|
2134
2143
|
});
|
|
@@ -4444,6 +4453,7 @@ function collectLeaves(cmd, path, out) {
|
|
|
4444
4453
|
const isLeaf = hasAction(cmd) && children.length === 0;
|
|
4445
4454
|
if (isLeaf) {
|
|
4446
4455
|
const argv = path;
|
|
4456
|
+
if (INTERNAL_LEAF_COMMANDS.has(argv.join(" "))) return;
|
|
4447
4457
|
const id = argv.join(" ");
|
|
4448
4458
|
const description = cmd.description() || argv.join(" ");
|
|
4449
4459
|
out.push({
|
|
@@ -4467,7 +4477,7 @@ function buildPaletteCommands(program2) {
|
|
|
4467
4477
|
collectLeaves(program2, [], out);
|
|
4468
4478
|
return out;
|
|
4469
4479
|
}
|
|
4470
|
-
var DESTRUCTIVE_PREFIXES;
|
|
4480
|
+
var DESTRUCTIVE_PREFIXES, INTERNAL_LEAF_COMMANDS;
|
|
4471
4481
|
var init_registry = __esm({
|
|
4472
4482
|
"src/tui/commands/registry.ts"() {
|
|
4473
4483
|
"use strict";
|
|
@@ -4489,6 +4499,7 @@ var init_registry = __esm({
|
|
|
4489
4499
|
["update"],
|
|
4490
4500
|
["run"]
|
|
4491
4501
|
];
|
|
4502
|
+
INTERNAL_LEAF_COMMANDS = /* @__PURE__ */ new Set(["hook"]);
|
|
4492
4503
|
}
|
|
4493
4504
|
});
|
|
4494
4505
|
|
|
@@ -4948,8 +4959,55 @@ var init_home = __esm({
|
|
|
4948
4959
|
}
|
|
4949
4960
|
});
|
|
4950
4961
|
|
|
4962
|
+
// src/commands/hook.ts
|
|
4963
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
4964
|
+
import { join as join5 } from "path";
|
|
4965
|
+
function hook() {
|
|
4966
|
+
let eventName = "SessionStart";
|
|
4967
|
+
let root = process.cwd();
|
|
4968
|
+
try {
|
|
4969
|
+
const input = JSON.parse(readFileSync4(0, "utf8"));
|
|
4970
|
+
if (typeof input.hook_event_name === "string" && input.hook_event_name !== "") {
|
|
4971
|
+
eventName = input.hook_event_name;
|
|
4972
|
+
}
|
|
4973
|
+
if (typeof input.cwd === "string" && input.cwd !== "") root = input.cwd;
|
|
4974
|
+
} catch {
|
|
4975
|
+
}
|
|
4976
|
+
process.stdout.write(JSON.stringify(hookOutput(eventName, root)));
|
|
4977
|
+
}
|
|
4978
|
+
function hookOutput(eventName, root) {
|
|
4979
|
+
let routerPath = null;
|
|
4980
|
+
let rulesPath = null;
|
|
4981
|
+
for (let dir = root; ; dir = join5(dir, "..")) {
|
|
4982
|
+
const router = join5(dir, ".noir", "router.md");
|
|
4983
|
+
const rules = join5(dir, ".noir", "rules", "anti-slop.md");
|
|
4984
|
+
if (existsSync3(router) || existsSync3(rules)) {
|
|
4985
|
+
routerPath = router;
|
|
4986
|
+
rulesPath = rules;
|
|
4987
|
+
break;
|
|
4988
|
+
}
|
|
4989
|
+
const parent = join5(dir, "..");
|
|
4990
|
+
if (parent === dir) break;
|
|
4991
|
+
}
|
|
4992
|
+
const parts = [];
|
|
4993
|
+
for (const path of [routerPath, rulesPath]) {
|
|
4994
|
+
if (path === null) continue;
|
|
4995
|
+
try {
|
|
4996
|
+
const text = readFileSync4(path, "utf8").trim();
|
|
4997
|
+
if (text !== "") parts.push(text);
|
|
4998
|
+
} catch {
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
return parts.length === 0 ? { hookSpecificOutput: { hookEventName: eventName } } : { hookSpecificOutput: { hookEventName: eventName, additionalContext: parts.join("\n\n") } };
|
|
5002
|
+
}
|
|
5003
|
+
var init_hook = __esm({
|
|
5004
|
+
"src/commands/hook.ts"() {
|
|
5005
|
+
"use strict";
|
|
5006
|
+
}
|
|
5007
|
+
});
|
|
5008
|
+
|
|
4951
5009
|
// src/commands/memory.ts
|
|
4952
|
-
import { readFileSync as
|
|
5010
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
4953
5011
|
import { loadProjectInfo as loadProjectInfo13 } from "@noir-ai/core";
|
|
4954
5012
|
function resolveWorkspace() {
|
|
4955
5013
|
const routing = workspaceRoutingTarget(process.cwd());
|
|
@@ -5167,14 +5225,14 @@ async function resolveCaptureContent(opts) {
|
|
|
5167
5225
|
if (typeof opts.content === "string" && opts.content.length > 0) return opts.content;
|
|
5168
5226
|
if (typeof opts.file === "string" && opts.file.length > 0) {
|
|
5169
5227
|
try {
|
|
5170
|
-
return
|
|
5228
|
+
return readFileSync5(opts.file, "utf8");
|
|
5171
5229
|
} catch {
|
|
5172
5230
|
fail(EXIT.USAGE, `memory capture could not read --file ${opts.file}`, opts);
|
|
5173
5231
|
}
|
|
5174
5232
|
}
|
|
5175
5233
|
if (!process.stdin.isTTY) {
|
|
5176
5234
|
try {
|
|
5177
|
-
return
|
|
5235
|
+
return readFileSync5(0, "utf8");
|
|
5178
5236
|
} catch {
|
|
5179
5237
|
fail(
|
|
5180
5238
|
EXIT.USAGE,
|
|
@@ -6557,8 +6615,8 @@ var init_run_status = __esm({
|
|
|
6557
6615
|
});
|
|
6558
6616
|
|
|
6559
6617
|
// src/commands/run.ts
|
|
6560
|
-
import { existsSync as
|
|
6561
|
-
import { join as
|
|
6618
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
6619
|
+
import { join as join6 } from "path";
|
|
6562
6620
|
import { SUPPORTED_HOSTS } from "@noir-ai/adapters";
|
|
6563
6621
|
import { isDeniedEnvKey as isDeniedEnvKey2, loadNoirEnv as loadNoirEnv3, NOIR_DIR as NOIR_DIR2, parseConfig, paths as paths2 } from "@noir-ai/core";
|
|
6564
6622
|
function credentialNote(env2, sources) {
|
|
@@ -6618,7 +6676,7 @@ async function runOnce(prompt, opts, resumeSessionId) {
|
|
|
6618
6676
|
const customBinary = opts.command ?? profile.binary;
|
|
6619
6677
|
const extraArgs = resumeSessionId === void 0 ? profile.args : [...profile.args ?? [], "--resume", resumeSessionId];
|
|
6620
6678
|
const env2 = profile.env ? mergeEnv(process.env, profile.env) : void 0;
|
|
6621
|
-
if (!
|
|
6679
|
+
if (!existsSync4(join6(root, NOIR_DIR2, ".env"))) {
|
|
6622
6680
|
log(
|
|
6623
6681
|
`This project has no ${NOIR_DIR2}/.env \u2014 that is where Noir reads project credentials and run config from. Run \`noir init\` to scaffold one (\`noir run\` works without it).`,
|
|
6624
6682
|
opts
|
|
@@ -6781,7 +6839,7 @@ function safeTranscript(host, lines) {
|
|
|
6781
6839
|
function writeTranscript(host, lines, root = process.cwd()) {
|
|
6782
6840
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6783
6841
|
const dir = paths2.transcriptsDir(root);
|
|
6784
|
-
const file =
|
|
6842
|
+
const file = join6(dir, `${host}-${ts}.jsonl`);
|
|
6785
6843
|
try {
|
|
6786
6844
|
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
6787
6845
|
writeFileSync4(file, `${lines.join("\n")}${lines.length > 0 ? "\n" : ""}`, { mode: 384 });
|
|
@@ -6917,8 +6975,8 @@ var init_conflict = __esm({
|
|
|
6917
6975
|
});
|
|
6918
6976
|
|
|
6919
6977
|
// src/dedup-write.ts
|
|
6920
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
6921
|
-
import { join as
|
|
6978
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync5 } from "fs";
|
|
6979
|
+
import { join as join7 } from "path";
|
|
6922
6980
|
import { sha256Hex as sha256Hex2, sha256Hex12 } from "@noir-ai/core";
|
|
6923
6981
|
async function checkWritePathDedup(root, res, opts) {
|
|
6924
6982
|
const result = { found: [], conflicts: [] };
|
|
@@ -6929,10 +6987,10 @@ async function checkWritePathDedup(root, res, opts) {
|
|
|
6929
6987
|
if (embed === void 0) return result;
|
|
6930
6988
|
const cachedEmbed = makeCachedEmbed(cache, embed);
|
|
6931
6989
|
for (const proposedRel of writtenHostFiles) {
|
|
6932
|
-
const proposedAbs =
|
|
6990
|
+
const proposedAbs = join7(root, proposedRel);
|
|
6933
6991
|
let proposedText;
|
|
6934
6992
|
try {
|
|
6935
|
-
proposedText =
|
|
6993
|
+
proposedText = readFileSync6(proposedAbs, "utf8");
|
|
6936
6994
|
} catch {
|
|
6937
6995
|
continue;
|
|
6938
6996
|
}
|
|
@@ -6976,7 +7034,7 @@ async function checkWritePathDedup(root, res, opts) {
|
|
|
6976
7034
|
`
|
|
6977
7035
|
);
|
|
6978
7036
|
}
|
|
6979
|
-
const matchedText = safeRead(
|
|
7037
|
+
const matchedText = safeRead(join7(root, matchedRel));
|
|
6980
7038
|
result.conflicts.push({
|
|
6981
7039
|
path: proposedRel,
|
|
6982
7040
|
mode: "artifact",
|
|
@@ -7060,21 +7118,21 @@ async function promptDedupAction(root, proposedRel, matchedRel, proposedText, si
|
|
|
7060
7118
|
if (clack.isCancel(choice)) return "preserve";
|
|
7061
7119
|
if (choice === "skip") {
|
|
7062
7120
|
try {
|
|
7063
|
-
rmSync(
|
|
7121
|
+
rmSync(join7(root, proposedRel), { force: true });
|
|
7064
7122
|
} catch {
|
|
7065
7123
|
}
|
|
7066
7124
|
return "preserve";
|
|
7067
7125
|
} else if (choice === "replace") {
|
|
7068
7126
|
try {
|
|
7069
|
-
writeFileSync5(
|
|
7127
|
+
writeFileSync5(join7(root, matchedRel), proposedText, "utf8");
|
|
7070
7128
|
} catch {
|
|
7071
7129
|
}
|
|
7072
7130
|
return "replace";
|
|
7073
7131
|
} else if (choice === "mirror") {
|
|
7074
7132
|
try {
|
|
7075
|
-
const existing =
|
|
7133
|
+
const existing = readFileSync6(join7(root, matchedRel), "utf8");
|
|
7076
7134
|
writeFileSync5(
|
|
7077
|
-
|
|
7135
|
+
join7(root, matchedRel),
|
|
7078
7136
|
`${existing}
|
|
7079
7137
|
|
|
7080
7138
|
<!-- mirrored from ${proposedRel} -->
|
|
@@ -7092,11 +7150,11 @@ function emptyCache() {
|
|
|
7092
7150
|
return { version: DEDUP_CACHE_VERSION, model: "", entries: {} };
|
|
7093
7151
|
}
|
|
7094
7152
|
function cachePath(root) {
|
|
7095
|
-
return
|
|
7153
|
+
return join7(root, ".noir", "dedup-cache.json");
|
|
7096
7154
|
}
|
|
7097
7155
|
function loadCache(root) {
|
|
7098
7156
|
try {
|
|
7099
|
-
const raw =
|
|
7157
|
+
const raw = readFileSync6(cachePath(root), "utf8");
|
|
7100
7158
|
const parsed = JSON.parse(raw);
|
|
7101
7159
|
if (parsed.version !== DEDUP_CACHE_VERSION) return emptyCache();
|
|
7102
7160
|
if (typeof parsed.entries !== "object" || parsed.entries === null) return emptyCache();
|
|
@@ -7111,7 +7169,7 @@ function loadCache(root) {
|
|
|
7111
7169
|
}
|
|
7112
7170
|
function saveCache(root, cache) {
|
|
7113
7171
|
try {
|
|
7114
|
-
mkdirSync4(
|
|
7172
|
+
mkdirSync4(join7(root, ".noir"), { recursive: true });
|
|
7115
7173
|
writeFileSync5(cachePath(root), JSON.stringify(cache), "utf8");
|
|
7116
7174
|
} catch {
|
|
7117
7175
|
}
|
|
@@ -7128,7 +7186,7 @@ function makeCachedEmbed(cache, embed) {
|
|
|
7128
7186
|
}
|
|
7129
7187
|
function safeRead(abs) {
|
|
7130
7188
|
try {
|
|
7131
|
-
return
|
|
7189
|
+
return readFileSync6(abs, "utf8");
|
|
7132
7190
|
} catch {
|
|
7133
7191
|
return void 0;
|
|
7134
7192
|
}
|
|
@@ -7166,7 +7224,7 @@ var init_dedup_write = __esm({
|
|
|
7166
7224
|
});
|
|
7167
7225
|
|
|
7168
7226
|
// src/init.ts
|
|
7169
|
-
import { existsSync as
|
|
7227
|
+
import { existsSync as existsSync5 } from "fs";
|
|
7170
7228
|
import { resolveAdapter as resolveAdapter3 } from "@noir-ai/adapters";
|
|
7171
7229
|
import { loadProjectInfo as loadProjectInfo15, paths as paths3 } from "@noir-ai/core";
|
|
7172
7230
|
import { scaffold } from "@noir-ai/create";
|
|
@@ -7231,7 +7289,7 @@ async function init(root, opts) {
|
|
|
7231
7289
|
}
|
|
7232
7290
|
function resolveInitHost(root, opts) {
|
|
7233
7291
|
if (opts.host !== void 0) return opts.host;
|
|
7234
|
-
if (!
|
|
7292
|
+
if (!existsSync5(paths3.config(root))) return "claude";
|
|
7235
7293
|
try {
|
|
7236
7294
|
return loadProjectInfo15(root).config.host;
|
|
7237
7295
|
} catch {
|
|
@@ -7703,7 +7761,7 @@ var sync_exports = {};
|
|
|
7703
7761
|
__export(sync_exports, {
|
|
7704
7762
|
sync: () => sync
|
|
7705
7763
|
});
|
|
7706
|
-
import { existsSync as
|
|
7764
|
+
import { existsSync as existsSync6 } from "fs";
|
|
7707
7765
|
import { resolveAdapter as resolveAdapter6 } from "@noir-ai/adapters";
|
|
7708
7766
|
import { loadProjectInfo as loadProjectInfo19, paths as paths4 } from "@noir-ai/core";
|
|
7709
7767
|
import { scaffold as scaffold3 } from "@noir-ai/create";
|
|
@@ -7776,7 +7834,7 @@ async function sync(root, opts = {}) {
|
|
|
7776
7834
|
}
|
|
7777
7835
|
function resolveSyncHost(root, opts) {
|
|
7778
7836
|
if (opts.host !== void 0) return opts.host;
|
|
7779
|
-
if (!
|
|
7837
|
+
if (!existsSync6(paths4.config(root))) return "claude";
|
|
7780
7838
|
try {
|
|
7781
7839
|
return loadProjectInfo19(root).config.host;
|
|
7782
7840
|
} catch {
|
|
@@ -8138,6 +8196,9 @@ function createProgram() {
|
|
|
8138
8196
|
program2.command("env").description("which configuration is in effect and where each value comes from").action(async (...args) => {
|
|
8139
8197
|
await env(toCliOptions(actionGlobals(args)));
|
|
8140
8198
|
});
|
|
8199
|
+
program2.command("hook", { hidden: true }).description("host hook runner (SessionStart / SubagentStart context injection)").action(async () => {
|
|
8200
|
+
await hook();
|
|
8201
|
+
});
|
|
8141
8202
|
const contextGrp = program2.command("context").description("context engine");
|
|
8142
8203
|
contextGrp.command("search").description("hybrid search over the indexed context").argument("<query>", "search query").option("--limit <n>", "max results", "10").action(async (...args) => {
|
|
8143
8204
|
const cmd = trailingCmd(args);
|
|
@@ -8525,6 +8586,7 @@ var init_bin = __esm({
|
|
|
8525
8586
|
init_env();
|
|
8526
8587
|
init_handoff();
|
|
8527
8588
|
init_home();
|
|
8589
|
+
init_hook();
|
|
8528
8590
|
init_memory();
|
|
8529
8591
|
init_release();
|
|
8530
8592
|
init_run();
|