@garygentry/system1 0.1.0 → 0.3.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/dist/bundle/chunks/{bin-IIUCANF7.mjs → bin-TCIHP5PC.mjs} +13 -10
- package/dist/bundle/chunks/{chunk-A7ODZFMY.mjs → chunk-4BSTNWLV.mjs} +2 -2
- package/dist/bundle/chunks/{chunk-7LVHD6A5.mjs → chunk-NUIZJRI6.mjs} +1 -1
- package/dist/bundle/chunks/{chunk-V7OTO67I.mjs → chunk-S5AIBUL7.mjs} +243 -11
- package/dist/bundle/chunks/{config-QR35VKVT.mjs → config-REALJZDR.mjs} +6 -4
- package/dist/bundle/chunks/{decide-PW7REJ6Y.mjs → decide-XVVRKQ3V.mjs} +3 -3
- package/dist/bundle/chunks/{doctor-HAT6XVTW.mjs → doctor-TKFVFCZV.mjs} +8 -3
- package/dist/bundle/chunks/{misc-6VZKJEN4.mjs → misc-FHOVQJ2G.mjs} +6 -4
- package/dist/bundle/chunks/route-NMFOTXLI.mjs +64 -0
- package/dist/bundle/chunks/{spec-Z2LZJ5EZ.mjs → spec-734MPBKB.mjs} +11 -9
- package/dist/bundle/decide.mjs +1 -1
- package/package.json +3 -3
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
VERSION,
|
|
7
7
|
emit,
|
|
8
8
|
extractFormat
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
10
10
|
|
|
11
11
|
// src/bin.ts
|
|
12
12
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
@@ -50,7 +50,8 @@ Commands:
|
|
|
50
50
|
usage Measured spend from the ledger (--session, --since)
|
|
51
51
|
config Show resolved config; \`config egress allow|deny|status\` for consent
|
|
52
52
|
spec list | show <name> | validate [name|path] | check <name> [--live]
|
|
53
|
-
schema Print the JSON Schema of a tool's input (ask, many, usage, spec-check)
|
|
53
|
+
schema Print the JSON Schema of a tool's input (ask, many, usage, spec-check, route)
|
|
54
|
+
route Does a prompt call for the ask skill? (--text|--stdin|--hook; local, sends nothing)
|
|
54
55
|
ping Check the endpoint is reachable (no key, no spend)
|
|
55
56
|
doctor Check decide works from this shell; prints the fix for each problem
|
|
56
57
|
version Print the version
|
|
@@ -91,21 +92,23 @@ async function main(argv, io) {
|
|
|
91
92
|
}
|
|
92
93
|
switch (command) {
|
|
93
94
|
case "ask":
|
|
94
|
-
return (await import("./decide-
|
|
95
|
+
return (await import("./decide-XVVRKQ3V.mjs")).runAskCommand(rest, io, format);
|
|
95
96
|
case "many":
|
|
96
|
-
return (await import("./decide-
|
|
97
|
+
return (await import("./decide-XVVRKQ3V.mjs")).runManyCommand(rest, io, format);
|
|
97
98
|
case "usage":
|
|
98
|
-
return (await import("./misc-
|
|
99
|
+
return (await import("./misc-FHOVQJ2G.mjs")).runUsageCommand(rest, io, format);
|
|
99
100
|
case "config":
|
|
100
|
-
return (await import("./config-
|
|
101
|
+
return (await import("./config-REALJZDR.mjs")).runConfigCommand(rest, io, format);
|
|
101
102
|
case "spec":
|
|
102
|
-
return (await import("./spec-
|
|
103
|
+
return (await import("./spec-734MPBKB.mjs")).runSpecCommand(rest, io, format);
|
|
103
104
|
case "schema":
|
|
104
|
-
return (await import("./misc-
|
|
105
|
+
return (await import("./misc-FHOVQJ2G.mjs")).runSchemaCommand(rest, io, format);
|
|
106
|
+
case "route":
|
|
107
|
+
return (await import("./route-NMFOTXLI.mjs")).runRouteCommand(rest, io, format);
|
|
105
108
|
case "ping":
|
|
106
|
-
return (await import("./misc-
|
|
109
|
+
return (await import("./misc-FHOVQJ2G.mjs")).runPingCommand(io, format);
|
|
107
110
|
case "doctor":
|
|
108
|
-
return (await import("./doctor-
|
|
111
|
+
return (await import("./doctor-TKFVFCZV.mjs")).runDoctorCommand(io, format);
|
|
109
112
|
case "version":
|
|
110
113
|
case "--version":
|
|
111
114
|
case "-v":
|
|
@@ -2,10 +2,10 @@ import { createRequire as __decideRequire } from "node:module"; const require =
|
|
|
2
2
|
import {
|
|
3
3
|
parseFileRef,
|
|
4
4
|
parseQuestionSet
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-S5AIBUL7.mjs";
|
|
6
6
|
import {
|
|
7
7
|
DecisionsError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
9
9
|
|
|
10
10
|
// src/args.ts
|
|
11
11
|
import { readFileSync } from "node:fs";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
__require,
|
|
10
10
|
__toESM,
|
|
11
11
|
isDecisionsError
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
13
13
|
|
|
14
14
|
// ../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/nodes/identity.js
|
|
15
15
|
var require_identity = __commonJS({
|
|
@@ -9165,6 +9165,107 @@ function escapeRegExp(text) {
|
|
|
9165
9165
|
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9166
9166
|
}
|
|
9167
9167
|
|
|
9168
|
+
// ../core/dist/route/route.js
|
|
9169
|
+
var ROUTE_DEFAULTS = {
|
|
9170
|
+
enabled: true,
|
|
9171
|
+
builtin: true,
|
|
9172
|
+
disable: [],
|
|
9173
|
+
triggers: [],
|
|
9174
|
+
ignore: []
|
|
9175
|
+
};
|
|
9176
|
+
var both = (...parts) => `^${parts.map((p) => `(?=[\\s\\S]*?(${p}))`).join("")}`;
|
|
9177
|
+
var ITEMS = "tickets?|reviews?|commits?|failures?|errors?|lines|rows?|entries|items?|issues?|comments?|messages?|emails?|commands?|records?|files?|tests?|alerts?|findings?|results?|prs?|pull requests?|responses?|reports?|incidents?|warnings?|changes?|hunks?|packages?|candidates?";
|
|
9178
|
+
var FILE = "\\b[\\w./-]+\\.(?:jsonl|ndjson|csv|tsv|txt|log|sh)\\b";
|
|
9179
|
+
var BATCH = `\\b(?:each|every|all\\s+(?:the\\s+|of\\s+the\\s+)?(?:\\d+\\s+)?(?:${ITEMS})|line\\s+by\\s+line|one\\s+by\\s+one)\\b|\\b\\d{2,}\\s+(?:[\\w-]+\\s+){0,2}(?:${ITEMS})\\b`;
|
|
9180
|
+
var RULESET = "\\b(?:rules?|criteri(?:a|on)|requirements?|checklist|polic(?:y|ies)|guidelines?|conventions?|standards?|our\\s+bar|TASK\\.md)\\b";
|
|
9181
|
+
var EVIDENCE = "\\b(?:diff|uncommitted|working\\s+tree|staged|changes?|patch|pr|pull\\s+request|branch|test[-\\s]output(?:\\.log)?|test\\s+results?|TASK\\.md)\\b";
|
|
9182
|
+
var GATES = "commit|merge|push|ship|release|approve|deploy|land|run";
|
|
9183
|
+
var BUILTIN_TRIGGERS = [
|
|
9184
|
+
{
|
|
9185
|
+
// "triage every CI failure", "go through tickets.jsonl and flag any where…",
|
|
9186
|
+
// "which of these would pass on a rerun", "the ones complaining about…"
|
|
9187
|
+
name: "batch-judgement",
|
|
9188
|
+
pattern: both(
|
|
9189
|
+
// A verb glued to a hyphen is another word: "rate-limit", "score-board".
|
|
9190
|
+
`\\b(?:(?:classify|categori[sz]e|label|triage|bucket|grade|rate|score|rank|screen|vet|judge|assess)(?!-)|sort\\s+out|route\\s+(?:each|every|all|these|those|the)|flag\\s+(?:any|all|every|each|which|the\\s+ones|anything)|mark\\s+(?:any|all|every|each|which|the\\s+ones)|split\\s+(?:\\w+\\s+)?into|pull\\s+out\\s+(?:the|any|all|every)|tell\\s+me\\s+which|which\\s+of\\s+(?:them|these|those|the\\s+\\w+)|which\\s+ones|which\\s+(?:${ITEMS})\\s+(?:could|would|might|should|are|is|will|look|seem|need)|the\\s+ones\\s+(?:that|where|which|who|with|about|complaining|mentioning)|anything\\s+that\\s+(?:looks|seems|sounds|reads)|is\\s+each|are\\s+any\\s+of|whether\\s+each|verdicts?)\\b`,
|
|
9191
|
+
`${FILE}|${BATCH}`
|
|
9192
|
+
)
|
|
9193
|
+
},
|
|
9194
|
+
{
|
|
9195
|
+
// "250 packages. Which single one…", "which of the packages is the best fit"
|
|
9196
|
+
name: "pick-from-many",
|
|
9197
|
+
pattern: both("\\b(?:best\\s+(?:fit|match|one|option|choice)|which\\s+(?:single\\s+)?one|single\\s+best|pick\\s+(?:the|one)|choose\\s+(?:the|one))\\b", `${FILE}|\\b\\d{2,}\\s+(?:[\\w-]+\\s+){0,2}(?:${ITEMS}|libraries|options|helpers|modules|functions)\\b|\\bout\\s+of\\s+(?:all|the|these)\\b`)
|
|
9198
|
+
},
|
|
9199
|
+
{
|
|
9200
|
+
// "check the diff against these rules", "does it meet the acceptance
|
|
9201
|
+
// criteria", "grade each criterion pass or fail", "hold the diff to our rules"
|
|
9202
|
+
name: "criteria-check",
|
|
9203
|
+
pattern: both("\\b(?:against\\s+(?:our|the|these|this|my|each|every)?\\s*(?:[\\w-]+\\s+){0,2}(?:rules?|criteri(?:a|on)|requirements?|checklist|polic(?:y|ies)|guidelines?|conventions?|standards?|spec)|hold\\s+(?:it|this|them|the\\s+[\\w-]+(?:\\s+[\\w-]+)?)\\s+(?:up\\s+)?(?:to|against)|meets?|satisf(?:y|ies)|violat\\w*|compl(?:y|ies|iant)|pass(?:es)?\\s+(?:our|the)\\s+(?:bar|rules|checks?|checklist)|pass\\s+or\\s+fail|pass/fail|per[-\\s]criteri(?:on|a)|tick\\s+off|(?:one|a|separate)\\s+verdict|verdicts?\\s+(?:for|on)|grade\\s+(?:each|every|them|it)|(?:each|every)\\s+(?:acceptance\\s+)?(?:criteri(?:on|a)|rule|requirement|checklist\\s+item|item))\\b", RULESET)
|
|
9204
|
+
},
|
|
9205
|
+
{
|
|
9206
|
+
// "is the task actually done?", "am i done?", "ready to merge?", "can I ship this"
|
|
9207
|
+
name: "done-check",
|
|
9208
|
+
pattern: both("\\b(?:am\\s+i\\s+(?:actually\\s+|really\\s+)?done|are\\s+we\\s+(?:actually\\s+|really\\s+)?done|is\\s+(?:it|this|that|(?:the|my|our)\\s+\\w+(?!\\s+(?:description|message|title|name|docs?|readme|summary|text|comment)))(?:\\s+[\\w.]+){0,4}?\\s+(?:actually\\s+|really\\s+|fully\\s+|truly\\s+)?(?:done|complete|finished)|(?:ready|good|ok|safe)\\s+to\\s+(?:merge|ship|commit|push|land|release)|can\\s+(?:i|we)\\s+(?:ship|merge|land|commit|push)\\s+(?:this|it)|(?:about|going)\\s+to\\s+(?:open\\s+a\\s+pr|merge|ship|push|commit|release))\\b", `${EVIDENCE}|${FILE}`, "\\?|\\b(?:check|verify|confirm|tell\\s+me|make\\s+sure|grade|hold)\\b")
|
|
9209
|
+
},
|
|
9210
|
+
{
|
|
9211
|
+
// "before I commit… is it safe?", "which commands could lose data before the bot runs it"
|
|
9212
|
+
name: "gate-check",
|
|
9213
|
+
pattern: both(`\\bbefore\\s+(?:i|we|the\\s+\\w+)\\s+(?:${GATES})s?\\b`, `${RULESET}|\\b(?:safe|destructive|verdict|violat\\w*|could\\s+(?:lose|break|delete|destroy|wipe))\\b`)
|
|
9214
|
+
}
|
|
9215
|
+
];
|
|
9216
|
+
var BUILTIN_IGNORE = [
|
|
9217
|
+
"\\b(?:don'?t|do\\s+not|without)\\s+(?:use\\s+|using\\s+)?(?:system\\s?1|decide)\\b"
|
|
9218
|
+
];
|
|
9219
|
+
var DEFAULT_MESSAGE = "System 1 routing hint ({triggers}): the user wants closed verdicts over text. Load the system1:ask skill now, before you read the files or the diff, and let `decide` give the verdicts; do not grade them yourself. Skip this only if the user said not to use System 1.";
|
|
9220
|
+
function compilePattern(pattern, where) {
|
|
9221
|
+
try {
|
|
9222
|
+
return new RegExp(pattern, "i");
|
|
9223
|
+
} catch (error) {
|
|
9224
|
+
throw new DecisionsError("config-error", `${where}: invalid regular expression ${JSON.stringify(pattern)}: ${error.message}`, { pattern });
|
|
9225
|
+
}
|
|
9226
|
+
}
|
|
9227
|
+
function activeTriggers(config) {
|
|
9228
|
+
const unknown = config.disable.filter((n) => !BUILTIN_TRIGGERS.some((t) => t.name === n));
|
|
9229
|
+
if (unknown.length > 0) {
|
|
9230
|
+
throw new DecisionsError("config-error", `route.disable names unknown built-in trigger(s): ${unknown.join(", ")}. Built-ins: ${BUILTIN_TRIGGERS.map((t) => t.name).join(", ")}`);
|
|
9231
|
+
}
|
|
9232
|
+
const builtins = config.builtin ? BUILTIN_TRIGGERS.filter((t) => !config.disable.includes(t.name)) : [];
|
|
9233
|
+
return [
|
|
9234
|
+
...builtins.map((t) => ({ ...t, source: "builtin" })),
|
|
9235
|
+
...config.triggers.map((t) => ({ ...t, source: "config" }))
|
|
9236
|
+
];
|
|
9237
|
+
}
|
|
9238
|
+
function route(prompt, config) {
|
|
9239
|
+
const triggers = activeTriggers(config);
|
|
9240
|
+
const ignore = [...config.builtin ? BUILTIN_IGNORE : [], ...config.ignore];
|
|
9241
|
+
const compiled = triggers.map((t) => ({
|
|
9242
|
+
...t,
|
|
9243
|
+
re: compilePattern(t.pattern, `route trigger "${t.name}"`)
|
|
9244
|
+
}));
|
|
9245
|
+
const vetoes = ignore.map((p) => ({ p, re: compilePattern(p, "route.ignore") }));
|
|
9246
|
+
if (!config.enabled)
|
|
9247
|
+
return { enabled: false, matched: false, triggers: [] };
|
|
9248
|
+
const hits = [];
|
|
9249
|
+
for (const t of compiled) {
|
|
9250
|
+
const m = t.re.exec(prompt);
|
|
9251
|
+
const text = m?.[0] || m?.slice(1).filter(Boolean).join(" \u2026 ");
|
|
9252
|
+
if (m)
|
|
9253
|
+
hits.push({ name: t.name, source: t.source, text: (text ?? "").slice(0, 120) });
|
|
9254
|
+
}
|
|
9255
|
+
if (hits.length === 0)
|
|
9256
|
+
return { enabled: true, matched: false, triggers: [] };
|
|
9257
|
+
const veto = vetoes.find((v) => v.re.test(prompt));
|
|
9258
|
+
if (veto)
|
|
9259
|
+
return { enabled: true, matched: false, triggers: hits, ignoredBy: veto.p };
|
|
9260
|
+
const names = hits.map((h) => h.name).join(", ");
|
|
9261
|
+
return {
|
|
9262
|
+
enabled: true,
|
|
9263
|
+
matched: true,
|
|
9264
|
+
triggers: hits,
|
|
9265
|
+
message: (config.message ?? DEFAULT_MESSAGE).replaceAll("{triggers}", names)
|
|
9266
|
+
};
|
|
9267
|
+
}
|
|
9268
|
+
|
|
9168
9269
|
// ../core/dist/model/validate.js
|
|
9169
9270
|
function assertQuestionSet(questions) {
|
|
9170
9271
|
const problems = [];
|
|
@@ -9423,7 +9524,8 @@ var DEFAULTS = {
|
|
|
9423
9524
|
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
9424
9525
|
budget: { maxCalls: 200, maxUsd: 0.05 },
|
|
9425
9526
|
egress: { consent: { granted: false }, exclude: [] },
|
|
9426
|
-
profiles: []
|
|
9527
|
+
profiles: [],
|
|
9528
|
+
route: ROUTE_DEFAULTS
|
|
9427
9529
|
};
|
|
9428
9530
|
function findRepoRoot(cwd) {
|
|
9429
9531
|
let dir = resolve(cwd);
|
|
@@ -9470,7 +9572,8 @@ function loadConfig(options = {}) {
|
|
|
9470
9572
|
...stringList(repo, "egress.exclude", repoFile)
|
|
9471
9573
|
]
|
|
9472
9574
|
},
|
|
9473
|
-
profiles: [...profileList(user, userFile), ...profileList(repo, repoFile)]
|
|
9575
|
+
profiles: [...profileList(user, userFile), ...profileList(repo, repoFile)],
|
|
9576
|
+
route: readRoute(user, userFile, repo, repoFile, env)
|
|
9474
9577
|
};
|
|
9475
9578
|
const key = resolveApiKey(env, userDir);
|
|
9476
9579
|
const session = detectSession(env);
|
|
@@ -9520,9 +9623,9 @@ function pick(key, type, ...layers2) {
|
|
|
9520
9623
|
}
|
|
9521
9624
|
return void 0;
|
|
9522
9625
|
}
|
|
9523
|
-
function pickIn(
|
|
9626
|
+
function pickIn(section2, key, ...layers2) {
|
|
9524
9627
|
for (const layer of layers2) {
|
|
9525
|
-
const value = layer?.[
|
|
9628
|
+
const value = layer?.[section2]?.[key];
|
|
9526
9629
|
if (typeof value === "number" && value >= 0)
|
|
9527
9630
|
return value;
|
|
9528
9631
|
}
|
|
@@ -9580,6 +9683,69 @@ function profileList(layer, file) {
|
|
|
9580
9683
|
};
|
|
9581
9684
|
});
|
|
9582
9685
|
}
|
|
9686
|
+
function readRoute(user, userFile, repo, repoFile, env) {
|
|
9687
|
+
const sections = [
|
|
9688
|
+
{ layer: section(user, "route", userFile), file: userFile },
|
|
9689
|
+
{ layer: section(repo, "route", repoFile), file: repoFile }
|
|
9690
|
+
];
|
|
9691
|
+
const known = ["enabled", "builtin", "disable", "triggers", "ignore", "message"];
|
|
9692
|
+
const route2 = { ...ROUTE_DEFAULTS, disable: [], triggers: [], ignore: [] };
|
|
9693
|
+
for (const { layer, file } of sections) {
|
|
9694
|
+
if (!layer)
|
|
9695
|
+
continue;
|
|
9696
|
+
const extra = Object.keys(layer).filter((k) => !known.includes(k));
|
|
9697
|
+
if (extra.length > 0) {
|
|
9698
|
+
throw new DecisionsError("config-error", `${file}: unknown route key(s) ${extra.join(", ")}. Known: ${known.join(", ")}`, { file });
|
|
9699
|
+
}
|
|
9700
|
+
for (const key of ["enabled", "builtin"]) {
|
|
9701
|
+
const v = layer[key];
|
|
9702
|
+
if (v === void 0)
|
|
9703
|
+
continue;
|
|
9704
|
+
if (typeof v !== "boolean")
|
|
9705
|
+
throw new DecisionsError("config-error", `${file}: route.${key} must be true or false`, {
|
|
9706
|
+
file
|
|
9707
|
+
});
|
|
9708
|
+
route2[key] = v;
|
|
9709
|
+
}
|
|
9710
|
+
if (layer.message !== void 0) {
|
|
9711
|
+
if (typeof layer.message !== "string" || !layer.message.trim())
|
|
9712
|
+
throw new DecisionsError("config-error", `${file}: route.message must be text`, { file });
|
|
9713
|
+
route2.message = layer.message;
|
|
9714
|
+
}
|
|
9715
|
+
for (const key of ["disable", "ignore"]) {
|
|
9716
|
+
const v = layer[key];
|
|
9717
|
+
if (v === void 0)
|
|
9718
|
+
continue;
|
|
9719
|
+
if (!Array.isArray(v) || !v.every((x) => typeof x === "string"))
|
|
9720
|
+
throw new DecisionsError("config-error", `${file}: route.${key} must be a list of strings`, { file });
|
|
9721
|
+
route2[key].push(...v);
|
|
9722
|
+
}
|
|
9723
|
+
if (layer.triggers !== void 0)
|
|
9724
|
+
route2.triggers.push(...triggerList(layer.triggers, file));
|
|
9725
|
+
}
|
|
9726
|
+
if (/^(0|off|false|no)$/i.test(env.SYSTEM1_ROUTE ?? ""))
|
|
9727
|
+
route2.enabled = false;
|
|
9728
|
+
return route2;
|
|
9729
|
+
}
|
|
9730
|
+
function section(layer, key, file) {
|
|
9731
|
+
const value = layer?.[key];
|
|
9732
|
+
if (value === void 0 || value === null)
|
|
9733
|
+
return void 0;
|
|
9734
|
+
if (typeof value !== "object" || Array.isArray(value))
|
|
9735
|
+
throw new DecisionsError("config-error", `${file}: ${key} must be a mapping`, { file });
|
|
9736
|
+
return value;
|
|
9737
|
+
}
|
|
9738
|
+
function triggerList(value, file) {
|
|
9739
|
+
if (!Array.isArray(value))
|
|
9740
|
+
throw new DecisionsError("config-error", `${file}: route.triggers must be a list`, { file });
|
|
9741
|
+
return value.map((t, i) => {
|
|
9742
|
+
const { name, pattern } = t ?? {};
|
|
9743
|
+
if (typeof name !== "string" || !name.trim() || typeof pattern !== "string" || !pattern) {
|
|
9744
|
+
throw new DecisionsError("config-error", `${file}: route.triggers[${i}] needs a name and a pattern (a regular expression)`, { file });
|
|
9745
|
+
}
|
|
9746
|
+
return { name, pattern };
|
|
9747
|
+
});
|
|
9748
|
+
}
|
|
9583
9749
|
function resolveApiKey(env, userDir) {
|
|
9584
9750
|
const fromEnv = nonEmpty2(env.OPENROUTER_API_KEY);
|
|
9585
9751
|
if (fromEnv)
|
|
@@ -9618,7 +9784,7 @@ function setConsent(repoRoot, granted, by, now = /* @__PURE__ */ new Date()) {
|
|
|
9618
9784
|
function assertConsent(consent, repoRoot) {
|
|
9619
9785
|
if (consent.granted)
|
|
9620
9786
|
return;
|
|
9621
|
-
throw new DecisionsError("egress-refused", `This repo has not agreed to send content to the decision model's provider.
|
|
9787
|
+
throw new DecisionsError("egress-refused", `This repo has not agreed to send content to the decision model's provider. Consent is the user's: they run \`decide config egress allow\` in ${repoRoot} themselves (the setup skill explains what gets sent). Replay of recorded answers works without consent.`, { repoRoot });
|
|
9622
9788
|
}
|
|
9623
9789
|
|
|
9624
9790
|
// ../core/dist/egress/exclude.js
|
|
@@ -18822,7 +18988,12 @@ function resolvePath(cwd, path) {
|
|
|
18822
18988
|
realAbsolute = realpathSync2(absolute);
|
|
18823
18989
|
} catch {
|
|
18824
18990
|
}
|
|
18825
|
-
|
|
18991
|
+
let realCwd = cwd;
|
|
18992
|
+
try {
|
|
18993
|
+
realCwd = realpathSync2(cwd);
|
|
18994
|
+
} catch {
|
|
18995
|
+
}
|
|
18996
|
+
const real = toRel(realCwd, realAbsolute);
|
|
18826
18997
|
return {
|
|
18827
18998
|
absolute,
|
|
18828
18999
|
display: toRel(cwd, absolute),
|
|
@@ -18951,7 +19122,7 @@ function gitIgnored(cwd, paths) {
|
|
|
18951
19122
|
if (error.status === 1)
|
|
18952
19123
|
return [];
|
|
18953
19124
|
if (error.signal === "SIGKILL") {
|
|
18954
|
-
throw new DecisionsError("source-error", `git check-ignore did not answer within ${GIT_TIMEOUT_MS} ms. Name the files with --file, or run where git works.`);
|
|
19125
|
+
throw new DecisionsError("source-error", `git check-ignore did not answer within ${GIT_TIMEOUT_MS} ms, which usually means a sandbox is blocking child processes (\`decide doctor\` prints the fix for Codex). Name the files with --file, or run where git works.`);
|
|
18955
19126
|
}
|
|
18956
19127
|
throw new DecisionsError("source-error", `git check-ignore failed: ${String(error)}`);
|
|
18957
19128
|
}
|
|
@@ -19564,11 +19735,16 @@ var SpecCheckInput = typebox_exports.Object({
|
|
|
19564
19735
|
/** Proceed past the spend guard. */
|
|
19565
19736
|
confirm: typebox_exports.Optional(typebox_exports.Boolean())
|
|
19566
19737
|
}, strict);
|
|
19738
|
+
var RouteInput = typebox_exports.Object({
|
|
19739
|
+
/** The user's prompt, as the harness hook received it. */
|
|
19740
|
+
prompt: typebox_exports.String()
|
|
19741
|
+
}, strict);
|
|
19567
19742
|
var TOOL_SCHEMAS = {
|
|
19568
19743
|
ask: AskInput,
|
|
19569
19744
|
many: ManyInput,
|
|
19570
19745
|
usage: UsageInput,
|
|
19571
|
-
"spec-check": SpecCheckInput
|
|
19746
|
+
"spec-check": SpecCheckInput,
|
|
19747
|
+
route: RouteInput
|
|
19572
19748
|
};
|
|
19573
19749
|
|
|
19574
19750
|
// ../core/dist/tools/context.js
|
|
@@ -19756,7 +19932,8 @@ function createDecider(options) {
|
|
|
19756
19932
|
const started = performance.now();
|
|
19757
19933
|
const record = fixtures?.lookup(namespace, request);
|
|
19758
19934
|
if (!record) {
|
|
19759
|
-
|
|
19935
|
+
const where = `(namespace "${namespace}", key ${key.slice(0, 12)}\u2026)`;
|
|
19936
|
+
throw new DecisionsError("replay-miss", transport ? `No recorded answer for this request ${where}. Record it with a live call (without --replay or SYSTEM1_REPLAY).` : `No API key is set, so only recorded answers can be used, and this request has none ${where}. Set OPENROUTER_API_KEY for a live answer (the setup skill shows where it goes).`, { namespace, key });
|
|
19760
19937
|
}
|
|
19761
19938
|
log2("replay", profile.id, ZERO);
|
|
19762
19939
|
return {
|
|
@@ -20217,6 +20394,31 @@ async function runAsk(ctx, rawInput) {
|
|
|
20217
20394
|
// ../core/dist/tools/doctor.js
|
|
20218
20395
|
import { accessSync, constants, statSync as statSync4 } from "node:fs";
|
|
20219
20396
|
import { delimiter, join as join5 } from "node:path";
|
|
20397
|
+
function routeCheck(config) {
|
|
20398
|
+
try {
|
|
20399
|
+
route("", config);
|
|
20400
|
+
if (!config.enabled) {
|
|
20401
|
+
return {
|
|
20402
|
+
name: "route",
|
|
20403
|
+
status: "ok",
|
|
20404
|
+
detail: "routing hints are off (route.enabled or SYSTEM1_ROUTE)"
|
|
20405
|
+
};
|
|
20406
|
+
}
|
|
20407
|
+
const names = activeTriggers(config).map((t) => t.name);
|
|
20408
|
+
return {
|
|
20409
|
+
name: "route",
|
|
20410
|
+
status: "ok",
|
|
20411
|
+
detail: `routing hints on: ${names.length ? names.join(", ") : "no triggers"}`
|
|
20412
|
+
};
|
|
20413
|
+
} catch (error) {
|
|
20414
|
+
return {
|
|
20415
|
+
name: "route",
|
|
20416
|
+
status: "warn",
|
|
20417
|
+
detail: `routing hints are silent: ${error instanceof Error ? error.message : String(error)}`,
|
|
20418
|
+
fix: 'correct route: in the config file (test it with `decide route --text "\u2026"`)'
|
|
20419
|
+
};
|
|
20420
|
+
}
|
|
20421
|
+
}
|
|
20220
20422
|
var CODEX_RULE = 'prefix_rule(pattern = ["decide"], decision = "allow")';
|
|
20221
20423
|
async function runDoctor(options) {
|
|
20222
20424
|
const { env } = options;
|
|
@@ -20259,7 +20461,8 @@ async function runDoctor(options) {
|
|
|
20259
20461
|
name: "key",
|
|
20260
20462
|
status: "warn",
|
|
20261
20463
|
detail: "no API key: only replay works",
|
|
20262
|
-
|
|
20464
|
+
// The file this shell would read: XDG_CONFIG_HOME moves it.
|
|
20465
|
+
fix: `set OPENROUTER_API_KEY, or write \`openrouter_api_key: <key>\` to ${join5(userConfigDir(env, options.home), "credentials")} (chmod 600)`
|
|
20263
20466
|
});
|
|
20264
20467
|
checks.push(config.egress.consent.granted ? { name: "consent", status: "ok", detail: `egress consent granted for ${config.repoRoot}` } : {
|
|
20265
20468
|
name: "consent",
|
|
@@ -20267,6 +20470,7 @@ async function runDoctor(options) {
|
|
|
20267
20470
|
detail: `no egress consent for ${config.repoRoot}: live calls are refused`,
|
|
20268
20471
|
fix: "the user runs `decide config egress allow` in this repo, if they agree"
|
|
20269
20472
|
});
|
|
20473
|
+
checks.push(routeCheck(config.route));
|
|
20270
20474
|
let reach;
|
|
20271
20475
|
try {
|
|
20272
20476
|
reach = await ping({
|
|
@@ -20387,6 +20591,33 @@ function which(name, path) {
|
|
|
20387
20591
|
return void 0;
|
|
20388
20592
|
}
|
|
20389
20593
|
|
|
20594
|
+
// ../core/dist/tools/route.js
|
|
20595
|
+
function runRoute(options, rawInput) {
|
|
20596
|
+
const problems = checkRouteInput(rawInput);
|
|
20597
|
+
if (problems.length > 0) {
|
|
20598
|
+
throw new DecisionsError("invalid-request", `Invalid route input:
|
|
20599
|
+
${problems.join("\n ")}`, {
|
|
20600
|
+
problems
|
|
20601
|
+
});
|
|
20602
|
+
}
|
|
20603
|
+
const input = rawInput;
|
|
20604
|
+
const config = loadConfig(options);
|
|
20605
|
+
const { user, repo } = config.layers;
|
|
20606
|
+
return {
|
|
20607
|
+
...route(input.prompt, config.route),
|
|
20608
|
+
files: { ...user ? { user } : {}, ...repo ? { repo } : {} }
|
|
20609
|
+
};
|
|
20610
|
+
}
|
|
20611
|
+
function checkRouteInput(input) {
|
|
20612
|
+
if (typeof input !== "object" || input === null || Array.isArray(input))
|
|
20613
|
+
return ["/ must be an object"];
|
|
20614
|
+
const extra = Object.keys(input).filter((k) => k !== "prompt");
|
|
20615
|
+
return [
|
|
20616
|
+
...typeof input.prompt === "string" ? [] : ["/prompt must be a string"],
|
|
20617
|
+
...extra.map((k) => `/${k} is not allowed`)
|
|
20618
|
+
];
|
|
20619
|
+
}
|
|
20620
|
+
|
|
20390
20621
|
// ../core/dist/tools/spec-check.js
|
|
20391
20622
|
async function runSpecCheck(ctx, rawInput) {
|
|
20392
20623
|
const input = checkInput("spec-check", rawInput);
|
|
@@ -20577,6 +20808,7 @@ export {
|
|
|
20577
20808
|
runMany,
|
|
20578
20809
|
runAsk,
|
|
20579
20810
|
runDoctor,
|
|
20811
|
+
runRoute,
|
|
20580
20812
|
runSpecCheck,
|
|
20581
20813
|
runUsage,
|
|
20582
20814
|
resolveConnection
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
typedParse
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4BSTNWLV.mjs";
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_EXCLUDES,
|
|
7
7
|
createContext,
|
|
8
8
|
loadConfig,
|
|
9
9
|
repoConfigPath,
|
|
10
10
|
setConsent
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-S5AIBUL7.mjs";
|
|
12
12
|
import {
|
|
13
13
|
DecisionsError,
|
|
14
14
|
emit
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
16
16
|
|
|
17
17
|
// src/commands/config.ts
|
|
18
18
|
function runConfigCommand(argv, io, format) {
|
|
@@ -24,11 +24,12 @@ function runConfigCommand(argv, io, format) {
|
|
|
24
24
|
(r, f) => f === "brief" ? brief(r) : void 0
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
|
+
var CONFIG_OPTIONS = { confirm: { type: "boolean" }, by: { type: "string" } };
|
|
27
28
|
function body(argv, io) {
|
|
28
29
|
const { values, positionals } = typedParse({
|
|
29
30
|
args: argv,
|
|
30
31
|
allowPositionals: true,
|
|
31
|
-
options:
|
|
32
|
+
options: CONFIG_OPTIONS
|
|
32
33
|
});
|
|
33
34
|
const [section = "show", action = "status"] = positionals;
|
|
34
35
|
const cwd = io.cwd ?? process.cwd();
|
|
@@ -112,5 +113,6 @@ function brief(r) {
|
|
|
112
113
|
].join("\n");
|
|
113
114
|
}
|
|
114
115
|
export {
|
|
116
|
+
CONFIG_OPTIONS,
|
|
115
117
|
runConfigCommand
|
|
116
118
|
};
|
|
@@ -6,17 +6,17 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
buildInput,
|
|
8
8
|
parseDecideFlags
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-4BSTNWLV.mjs";
|
|
10
10
|
import {
|
|
11
11
|
createContext,
|
|
12
12
|
runAsk,
|
|
13
13
|
runMany
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-S5AIBUL7.mjs";
|
|
15
15
|
import {
|
|
16
16
|
DecisionsError,
|
|
17
17
|
ENVELOPE_VERSION,
|
|
18
18
|
emit
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
20
20
|
|
|
21
21
|
// src/commands/decide.ts
|
|
22
22
|
import { readFileSync } from "node:fs";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
runDoctor
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-S5AIBUL7.mjs";
|
|
5
5
|
import {
|
|
6
6
|
emit
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
8
8
|
|
|
9
9
|
// src/commands/doctor.ts
|
|
10
10
|
import { execFile } from "node:child_process";
|
|
@@ -25,7 +25,7 @@ function runDoctorCommand(io, format) {
|
|
|
25
25
|
}
|
|
26
26
|
function brief(r) {
|
|
27
27
|
const lines = [
|
|
28
|
-
`decide doctor: ${r
|
|
28
|
+
`decide doctor: ${headline(r)} \xB7 ${r.live ? "live ready" : "replay only"} \xB7 harness ${r.harness ?? "none"} \xB7 session ${r.session ?? "none"}`
|
|
29
29
|
];
|
|
30
30
|
for (const c of r.checks) {
|
|
31
31
|
lines.push(` ${c.status.padEnd(4)} ${c.name}: ${c.detail}`);
|
|
@@ -33,6 +33,11 @@ function brief(r) {
|
|
|
33
33
|
}
|
|
34
34
|
return lines.join("\n");
|
|
35
35
|
}
|
|
36
|
+
function headline(r) {
|
|
37
|
+
if (!r.healthy) return "PROBLEMS FOUND";
|
|
38
|
+
const missing = r.checks.filter((c) => c.status === "warn").map((c) => c.name);
|
|
39
|
+
return !r.live && missing.length > 0 ? `SETUP NEEDED (${missing.join(", ")})` : "healthy";
|
|
40
|
+
}
|
|
36
41
|
function probeVersion(path, env, timeoutMs = 2e3) {
|
|
37
42
|
return new Promise((resolve) => {
|
|
38
43
|
let settled = false;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
typedParse
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4BSTNWLV.mjs";
|
|
5
5
|
import {
|
|
6
6
|
TOOL_SCHEMAS,
|
|
7
7
|
createContext,
|
|
8
8
|
ping,
|
|
9
9
|
resolveConnection,
|
|
10
10
|
runUsage
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-S5AIBUL7.mjs";
|
|
12
12
|
import {
|
|
13
13
|
DecisionsError,
|
|
14
14
|
EXIT,
|
|
15
15
|
emit
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
17
17
|
|
|
18
18
|
// src/commands/misc.ts
|
|
19
19
|
function runSchemaCommand(argv, io, format) {
|
|
@@ -28,6 +28,7 @@ function runSchemaCommand(argv, io, format) {
|
|
|
28
28
|
return TOOL_SCHEMAS[tool];
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
+
var USAGE_OPTIONS = { session: { type: "string" }, since: { type: "string" } };
|
|
31
32
|
function runUsageCommand(argv, io, format) {
|
|
32
33
|
return emit(
|
|
33
34
|
io,
|
|
@@ -36,7 +37,7 @@ function runUsageCommand(argv, io, format) {
|
|
|
36
37
|
() => {
|
|
37
38
|
const { values } = typedParse({
|
|
38
39
|
args: argv,
|
|
39
|
-
options:
|
|
40
|
+
options: USAGE_OPTIONS
|
|
40
41
|
});
|
|
41
42
|
const ctx = createContext({ ...io, cwd: io.cwd ?? process.cwd(), env: io.env });
|
|
42
43
|
return runUsage(ctx, {
|
|
@@ -72,6 +73,7 @@ async function runPingCommand(io, format) {
|
|
|
72
73
|
return failed ? EXIT.providerError : code;
|
|
73
74
|
}
|
|
74
75
|
export {
|
|
76
|
+
USAGE_OPTIONS,
|
|
75
77
|
runPingCommand,
|
|
76
78
|
runSchemaCommand,
|
|
77
79
|
runUsageCommand
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
typedParse
|
|
4
|
+
} from "./chunk-4BSTNWLV.mjs";
|
|
5
|
+
import {
|
|
6
|
+
runRoute
|
|
7
|
+
} from "./chunk-S5AIBUL7.mjs";
|
|
8
|
+
import {
|
|
9
|
+
DecisionsError,
|
|
10
|
+
emit
|
|
11
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
12
|
+
|
|
13
|
+
// src/commands/route.ts
|
|
14
|
+
import { readFileSync } from "node:fs";
|
|
15
|
+
var ROUTE_OPTIONS = {
|
|
16
|
+
text: { type: "string" },
|
|
17
|
+
stdin: { type: "boolean" },
|
|
18
|
+
hook: { type: "boolean" }
|
|
19
|
+
};
|
|
20
|
+
function runRouteCommand(argv, io, format) {
|
|
21
|
+
return emit(
|
|
22
|
+
io,
|
|
23
|
+
"route",
|
|
24
|
+
format,
|
|
25
|
+
() => {
|
|
26
|
+
const { values } = typedParse({ args: argv, options: ROUTE_OPTIONS });
|
|
27
|
+
const given = [values.text !== void 0, values.stdin, values.hook].filter(Boolean).length;
|
|
28
|
+
if (given !== 1) {
|
|
29
|
+
throw new DecisionsError(
|
|
30
|
+
"invalid-request",
|
|
31
|
+
"Usage: decide route --text <prompt> | --stdin | --hook (exactly one)"
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
const read = io.readStdin ?? (() => readFileSync(0, "utf8"));
|
|
35
|
+
let prompt = values.text;
|
|
36
|
+
let cwd = io.cwd ?? process.cwd();
|
|
37
|
+
if (values.stdin) prompt = read();
|
|
38
|
+
if (values.hook) {
|
|
39
|
+
const event = parseHookEvent(read());
|
|
40
|
+
prompt = event.prompt;
|
|
41
|
+
if (event.cwd) cwd = event.cwd;
|
|
42
|
+
}
|
|
43
|
+
return runRoute({ cwd, env: io.env, ...io.home ? { home: io.home } : {} }, { prompt });
|
|
44
|
+
},
|
|
45
|
+
(r, f) => f === "brief" ? r.message ?? "" : void 0
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
function parseHookEvent(text) {
|
|
49
|
+
let event;
|
|
50
|
+
try {
|
|
51
|
+
event = JSON.parse(text);
|
|
52
|
+
} catch {
|
|
53
|
+
throw new DecisionsError("invalid-request", "--hook expects a JSON hook event on stdin");
|
|
54
|
+
}
|
|
55
|
+
const { prompt, cwd } = event ?? {};
|
|
56
|
+
if (typeof prompt !== "string") {
|
|
57
|
+
throw new DecisionsError("invalid-request", "--hook: the event has no `prompt` string");
|
|
58
|
+
}
|
|
59
|
+
return { prompt, ...typeof cwd === "string" && cwd ? { cwd } : {} };
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
ROUTE_OPTIONS,
|
|
63
|
+
runRouteCommand
|
|
64
|
+
};
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-5LVOFZF3.mjs";
|
|
5
5
|
import {
|
|
6
6
|
typedParse
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4BSTNWLV.mjs";
|
|
8
8
|
import {
|
|
9
9
|
assertExamples,
|
|
10
10
|
createContext,
|
|
@@ -12,11 +12,11 @@ import {
|
|
|
12
12
|
listSpecs,
|
|
13
13
|
loadSpec,
|
|
14
14
|
runSpecCheck
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-S5AIBUL7.mjs";
|
|
16
16
|
import {
|
|
17
17
|
DecisionsError,
|
|
18
18
|
emit
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-NUIZJRI6.mjs";
|
|
20
20
|
|
|
21
21
|
// src/commands/spec.ts
|
|
22
22
|
function runSpecCommand(argv, io, format) {
|
|
@@ -105,19 +105,21 @@ function checkInput(argv) {
|
|
|
105
105
|
...values.model ? { model: values.model } : {}
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
|
+
var SPEC_OPTIONS = {
|
|
109
|
+
live: { type: "boolean" },
|
|
110
|
+
replay: { type: "boolean" },
|
|
111
|
+
confirm: { type: "boolean" },
|
|
112
|
+
model: { type: "string" }
|
|
113
|
+
};
|
|
108
114
|
function parse(argv) {
|
|
109
115
|
return typedParse({
|
|
110
116
|
args: argv,
|
|
111
117
|
allowPositionals: true,
|
|
112
118
|
strict: true,
|
|
113
|
-
options:
|
|
114
|
-
live: { type: "boolean" },
|
|
115
|
-
replay: { type: "boolean" },
|
|
116
|
-
confirm: { type: "boolean" },
|
|
117
|
-
model: { type: "string" }
|
|
118
|
-
}
|
|
119
|
+
options: SPEC_OPTIONS
|
|
119
120
|
});
|
|
120
121
|
}
|
|
121
122
|
export {
|
|
123
|
+
SPEC_OPTIONS,
|
|
122
124
|
runSpecCommand
|
|
123
125
|
};
|
package/dist/bundle/decide.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@garygentry/system1",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The `decide` CLI: typed, calibrated decisions for coding agents, hooks and CI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
],
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
|
-
"url": "https://github.com/garygentry/system1",
|
|
23
|
+
"url": "git+https://github.com/garygentry/system1.git",
|
|
24
24
|
"directory": "packages/cli"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
27
27
|
"node": ">=22"
|
|
28
28
|
},
|
|
29
29
|
"bin": {
|
|
30
|
-
"decide": "
|
|
30
|
+
"decide": "dist/bundle/decide.mjs"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"dist/bundle",
|