@garygentry/system1 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gary Gentry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # @garygentry/system1
2
+
3
+ The `decide` CLI: typed, calibrated decisions for coding agents, hooks and CI.
4
+
5
+ ```sh
6
+ npm i -g @garygentry/system1
7
+ decide doctor --format brief
8
+ ```
9
+
10
+ `decide` sends a closed judgement (yes/no, pick one of N, rate on a scale) to a decision model and returns a typed, calibrated answer in about 300 ms for about $0.00003 an item. It reads and splits the content itself, excludes secret-shaped files, scrubs secrets from what it sends, and never sends anything until the repo has given consent with `decide config egress allow`.
11
+
12
+ Full documentation, the skills for Claude Code, Codex and Pi, and what gets sent: **https://github.com/garygentry/system1**
13
+
14
+ MIT
@@ -0,0 +1,116 @@
1
+ # Third-party notices
2
+
3
+ The `decide` CLI ships as a single bundle with these packages compiled into
4
+ it. Their licences and copyright notices are reproduced in full, as those
5
+ licences require. Generated by `node tools/notices.mjs`; do not edit.
6
+
7
+ - picomatch 4.0.7 (MIT)
8
+ - tinyglobby 0.2.17 (MIT)
9
+ - typebox 1.3.34 (MIT)
10
+ - yaml 2.9.1 (ISC)
11
+
12
+ ---
13
+
14
+ ## picomatch 4.0.7
15
+
16
+ ```
17
+ The MIT License (MIT)
18
+
19
+ Copyright (c) 2017-present, Jon Schlinkert.
20
+
21
+ Permission is hereby granted, free of charge, to any person obtaining a copy
22
+ of this software and associated documentation files (the "Software"), to deal
23
+ in the Software without restriction, including without limitation the rights
24
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25
+ copies of the Software, and to permit persons to whom the Software is
26
+ furnished to do so, subject to the following conditions:
27
+
28
+ The above copyright notice and this permission notice shall be included in
29
+ all copies or substantial portions of the Software.
30
+
31
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37
+ THE SOFTWARE.
38
+ ```
39
+
40
+ ---
41
+
42
+ ## tinyglobby 0.2.17
43
+
44
+ ```
45
+ MIT License
46
+
47
+ Copyright (c) 2024 Madeline Gurriarán
48
+
49
+ Permission is hereby granted, free of charge, to any person obtaining a copy
50
+ of this software and associated documentation files (the "Software"), to deal
51
+ in the Software without restriction, including without limitation the rights
52
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53
+ copies of the Software, and to permit persons to whom the Software is
54
+ furnished to do so, subject to the following conditions:
55
+
56
+ The above copyright notice and this permission notice shall be included in all
57
+ copies or substantial portions of the Software.
58
+
59
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
65
+ SOFTWARE.
66
+ ```
67
+
68
+ ---
69
+
70
+ ## typebox 1.3.34
71
+
72
+ ```
73
+ TypeBox
74
+
75
+ The MIT License (MIT)
76
+
77
+ Copyright (c) 2017-2026 Haydn Paterson
78
+
79
+ Permission is hereby granted, free of charge, to any person obtaining a copy
80
+ of this software and associated documentation files (the "Software"), to deal
81
+ in the Software without restriction, including without limitation the rights
82
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
83
+ copies of the Software, and to permit persons to whom the Software is
84
+ furnished to do so, subject to the following conditions:
85
+
86
+ The above copyright notice and this permission notice shall be included in
87
+ all copies or substantial portions of the Software.
88
+
89
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
90
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
91
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
92
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
93
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
94
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
95
+ THE SOFTWARE.
96
+ ```
97
+
98
+ ---
99
+
100
+ ## yaml 2.9.1
101
+
102
+ ```
103
+ Copyright Eemeli Aro <eemeli@gmail.com>
104
+
105
+ Permission to use, copy, modify, and/or distribute this software for any purpose
106
+ with or without fee is hereby granted, provided that the above copyright notice
107
+ and this permission notice appear in all copies.
108
+
109
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
110
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
111
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
112
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
113
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
114
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
115
+ THIS SOFTWARE.
116
+ ```
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
3
+ import {
4
+ DecisionsError,
5
+ EXIT,
6
+ VERSION,
7
+ emit,
8
+ extractFormat
9
+ } from "./chunk-7LVHD6A5.mjs";
10
+
11
+ // src/bin.ts
12
+ import { readFileSync as readFileSync2 } from "node:fs";
13
+
14
+ // src/bundled.ts
15
+ import { existsSync, readFileSync } from "node:fs";
16
+ import { dirname, join } from "node:path";
17
+ import { fileURLToPath } from "node:url";
18
+ var PACKAGE = "@garygentry/system1";
19
+ function bundledSpecsDir(from = fileURLToPath(import.meta.url)) {
20
+ const root = packageRoot(dirname(from));
21
+ if (!root) return void 0;
22
+ const own = join(root, "specs");
23
+ if (existsSync(own)) return own;
24
+ const checkout = join(root, "..", "..");
25
+ const plugin = join(checkout, "plugins", "system1", "specs");
26
+ return existsSync(join(checkout, "catalog.yaml")) && existsSync(plugin) ? plugin : void 0;
27
+ }
28
+ function packageRoot(start) {
29
+ for (let dir = start; ; dir = dirname(dir)) {
30
+ const manifest = join(dir, "package.json");
31
+ if (existsSync(manifest)) {
32
+ try {
33
+ if (JSON.parse(readFileSync(manifest, "utf8")).name === PACKAGE)
34
+ return dir;
35
+ } catch {
36
+ }
37
+ }
38
+ if (dirname(dir) === dir) return void 0;
39
+ }
40
+ }
41
+
42
+ // src/main.ts
43
+ var HELP = `decide ${VERSION} \u2014 typed, calibrated decisions for coding agents
44
+
45
+ Usage: decide <command> [options] [--format json|jsonl|brief]
46
+
47
+ Commands:
48
+ ask One state, one question set, one call
49
+ many One question set over many items (fan-out), filtered to what matters
50
+ usage Measured spend from the ledger (--session, --since)
51
+ config Show resolved config; \`config egress allow|deny|status\` for consent
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)
54
+ ping Check the endpoint is reachable (no key, no spend)
55
+ doctor Check decide works from this shell; prints the fix for each problem
56
+ version Print the version
57
+
58
+ Questions: --spec <name|path> | --question name:noul:<text>
59
+ --question name:choice:<text>:key=desc|key=desc|none=None of these
60
+ --question name:score:<text>:level 0|level 1|level 2
61
+ --questions <file|-|inline YAML/JSON> (a question set; richer than --question)
62
+ --input <file|-> (full tool input as JSON; flags override it)
63
+ Sources: --glob <pattern>\u2026 --file <path[:L1-L2]>\u2026 --jsonl <path>
64
+ --diff <range> [--staged] --text <text> --stdin
65
+ Split: --split file|hunk|row|join|lines:N[/overlap] (default: file; join = one state)
66
+ Project: --keep 'relevant>=0.7'\u2026 --sort relevant:desc --limit N --fields a,b
67
+ --allow-outside (read files that resolve outside the repo)
68
+ Run: --dry-run --confirm --record | --replay | --live --model <id> --concurrency N
69
+
70
+ Output is one JSON envelope by default: {v, ok, command, result | error}.
71
+ Exit codes: 0 ok \xB7 1 failure \xB7 2 usage \xB7 3 egress refused \xB7 4 budget guard
72
+ 5 provider error \xB7 6 replay miss
73
+ `;
74
+ var DEFAULT_FORMAT = "json";
75
+ async function main(argv, io) {
76
+ const [command, ...args] = argv;
77
+ let format;
78
+ let rest;
79
+ let explicitFormat;
80
+ try {
81
+ ;
82
+ ({ format, rest, explicit: explicitFormat } = extractFormat(args, DEFAULT_FORMAT));
83
+ } catch (error) {
84
+ return emit(io, command ?? "decide", DEFAULT_FORMAT, () => {
85
+ throw error;
86
+ });
87
+ }
88
+ if (command === void 0 || command === "help" || command === "--help" || command === "-h" || rest.includes("--help")) {
89
+ io.out(HELP);
90
+ return EXIT.ok;
91
+ }
92
+ switch (command) {
93
+ case "ask":
94
+ return (await import("./decide-PW7REJ6Y.mjs")).runAskCommand(rest, io, format);
95
+ case "many":
96
+ return (await import("./decide-PW7REJ6Y.mjs")).runManyCommand(rest, io, format);
97
+ case "usage":
98
+ return (await import("./misc-6VZKJEN4.mjs")).runUsageCommand(rest, io, format);
99
+ case "config":
100
+ return (await import("./config-QR35VKVT.mjs")).runConfigCommand(rest, io, format);
101
+ case "spec":
102
+ return (await import("./spec-Z2LZJ5EZ.mjs")).runSpecCommand(rest, io, format);
103
+ case "schema":
104
+ return (await import("./misc-6VZKJEN4.mjs")).runSchemaCommand(rest, io, format);
105
+ case "ping":
106
+ return (await import("./misc-6VZKJEN4.mjs")).runPingCommand(io, format);
107
+ case "doctor":
108
+ return (await import("./doctor-HAT6XVTW.mjs")).runDoctorCommand(io, format);
109
+ case "version":
110
+ case "--version":
111
+ case "-v":
112
+ return emit(
113
+ io,
114
+ "version",
115
+ // Bare `decide version` prints the number; an explicit --format wins.
116
+ explicitFormat ? format : "brief",
117
+ () => ({ version: VERSION }),
118
+ (r, f) => f === "json" ? void 0 : r.version
119
+ );
120
+ default:
121
+ return emit(io, command, format, () => {
122
+ throw new DecisionsError(
123
+ "invalid-request",
124
+ `unknown command "${command}". Run \`decide help\`.`
125
+ );
126
+ });
127
+ }
128
+ }
129
+
130
+ // src/bin.ts
131
+ var line = (stream) => (text) => stream.write(text.endsWith("\n") ? text : `${text}
132
+ `);
133
+ process.exitCode = await main(process.argv.slice(2), {
134
+ out: line(process.stdout),
135
+ err: line(process.stderr),
136
+ env: process.env,
137
+ cwd: process.cwd(),
138
+ readStdin: () => readFileSync2(0, "utf8"),
139
+ interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY),
140
+ ...bundledSpecsDir() ? { bundledSpecs: bundledSpecsDir() } : {}
141
+ });
@@ -0,0 +1,130 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+
3
+ // src/format.ts
4
+ function briefAnswer(name, answer, undecided) {
5
+ const flag = undecided ? " UNDECIDED" : "";
6
+ switch (answer.type) {
7
+ case "noul":
8
+ return `${name}=${fix(answer.noul)}${flag}`;
9
+ case "choice":
10
+ return `${name}=${answer.choice}(${fix(answer.confidence)})${flag}`;
11
+ case "score": {
12
+ const top = answer.legend ? Object.keys(answer.legend).length - 1 : void 0;
13
+ return `${name}=${fix(answer.score)}${top !== void 0 ? `/${top}` : ""}(${fix(answer.confidence)})${flag}`;
14
+ }
15
+ }
16
+ }
17
+ function briefAnswers(answers, undecided = []) {
18
+ return Object.entries(answers).map(([name, a]) => briefAnswer(name, a, undecided.includes(name))).join(" ");
19
+ }
20
+ function where(row) {
21
+ return row.id;
22
+ }
23
+ function quoted(row) {
24
+ return row.excerpt ? ` "${row.excerpt}"` : "";
25
+ }
26
+ function briefMany(r) {
27
+ const lines = [];
28
+ if (r.dryRun) {
29
+ lines.push(
30
+ `decide many (dry run): would send ${r.counts.items} item(s) to ${r.model} \xB7 ${projected(r.projection)} \xB7 no calls made`
31
+ );
32
+ if (r.sampleIds?.length) lines.push(`first: ${r.sampleIds.join(", ")}`);
33
+ } else {
34
+ const c = r.counts;
35
+ lines.push(
36
+ `decide many: ${c.kept}${c.keptTotal > c.kept ? ` (of ${c.keptTotal})` : ""} kept of ${c.items} \xB7 ${c.undecided} undecided \xB7 ${c.dropped} dropped${c.failed ? ` \xB7 ${c.failed} FAILED` : ""} \xB7 ${r.source} ${r.model} \xB7 ${measured(r.usage)} \xB7 ${seconds(r.wallClockMs)}`
37
+ );
38
+ if (r.kept.length) {
39
+ lines.push("kept:");
40
+ for (const row of r.kept)
41
+ lines.push(` ${where(row)} ${briefAnswers(row.answers, row.undecided)}${quoted(row)}`);
42
+ }
43
+ if (r.undecided.length) {
44
+ lines.push("undecided (too flat to judge; read these yourself):");
45
+ for (const row of r.undecided)
46
+ lines.push(` ${where(row)} ${briefAnswers(row.answers, row.questions)}${quoted(row)}`);
47
+ }
48
+ if (r.failed.length) {
49
+ lines.push("failed:");
50
+ for (const f of r.failed) lines.push(` ${f.id} ${f.code}: ${firstLine(f.message)}`);
51
+ }
52
+ }
53
+ lines.push(...withheld(r.skipped, r.redactions));
54
+ return lines.join("\n");
55
+ }
56
+ function briefAsk(r) {
57
+ const lines = [
58
+ `decide ask: ${r.id} \xB7 ${r.source} ${r.servedBy} \xB7 ${r.latencyMs} ms \xB7 ${measured(r.usage)}`,
59
+ ...Object.entries(r.answers).map(
60
+ ([name, a]) => ` ${briefAnswer(name, a, r.undecided.includes(name))}`
61
+ )
62
+ ];
63
+ if (r.verdict) lines.push(`verdict: ${r.verdict}`);
64
+ lines.push(...withheld(r.skipped, r.redactions));
65
+ return lines.join("\n");
66
+ }
67
+ function briefSpecCheck(r) {
68
+ const c = r.counts;
69
+ const parts = [`${c.pass} pass`, `${c.fail} fail`, `${c.undecided} undecided`];
70
+ if (c.captured) parts.push(`${c.captured} captured`);
71
+ if (c.withheld) parts.push(`${c.withheld} withheld`);
72
+ const lines = [
73
+ `decide spec check: ${r.spec} ${r.passed ? "PASSED" : "FAILED"} \xB7 ${parts.join(" \xB7 ")} \xB7 ${r.source} ${r.model} \xB7 ${measured(r.usage)}`
74
+ ];
75
+ for (const e of r.examples) {
76
+ const label = e.status === "pass" ? "pass" : e.status.toUpperCase();
77
+ if (e.status === "withheld") {
78
+ lines.push(` ${label} ${e.id} ${e.reason ?? ""}`);
79
+ continue;
80
+ }
81
+ lines.push(` ${label} ${e.id} ${e.answers ? briefAnswers(e.answers, e.undecided) : ""}`);
82
+ for (const f of e.failures ?? []) lines.push(` expected ${f.question}: ${f.expected}`);
83
+ if (e.status !== "pass" && e.answers) {
84
+ for (const [name, a] of Object.entries(e.answers)) {
85
+ if (a.type !== "noul") lines.push(` ${name}: ${distribution(a.probabilities)}`);
86
+ }
87
+ }
88
+ }
89
+ lines.push(...withheld(r.skipped, { total: 0, items: 0 }));
90
+ return lines.join("\n");
91
+ }
92
+ function distribution(probabilities) {
93
+ return Object.entries(probabilities).sort((a, b) => b[1] - a[1]).map(([k, p]) => `${k} ${fix(p)}`).join(" \xB7 ");
94
+ }
95
+ function withheld(skipped, redactions) {
96
+ const lines = [];
97
+ if (skipped.total > 0) {
98
+ const reasons = Object.entries(skipped.byReason).map(([k, v]) => `${k} ${v}`).join(", ");
99
+ const excluded = skipped.sample.filter((s) => s.reason === "excluded").map((s) => s.path);
100
+ lines.push(
101
+ `withheld: ${skipped.total} (${reasons})${excluded.length ? ` e.g. ${excluded.join(", ")}` : ""}`
102
+ );
103
+ }
104
+ if (redactions.total > 0)
105
+ lines.push(
106
+ `redacted: ${redactions.total} secret(s) in ${redactions.items} item(s) before sending`
107
+ );
108
+ return lines;
109
+ }
110
+ function projected(p) {
111
+ return `projected $${p.projectedUsd.toFixed(6)} (~${p.estimatedInputTokens} tokens, price as of ${p.priceAsOf})`;
112
+ }
113
+ function measured(u) {
114
+ return u.reported === false ? `$${u.cost.toFixed(6)} measured (incomplete: the provider reported no usage for at least one call)` : `$${u.cost.toFixed(6)} measured`;
115
+ }
116
+ function seconds(ms) {
117
+ return ms < 1e3 ? `${ms} ms` : `${(ms / 1e3).toFixed(1)} s`;
118
+ }
119
+ function fix(n) {
120
+ return Number.isInteger(n) ? String(n) : n.toFixed(2);
121
+ }
122
+ function firstLine(text) {
123
+ return text.split("\n")[0] ?? text;
124
+ }
125
+
126
+ export {
127
+ briefMany,
128
+ briefAsk,
129
+ briefSpecCheck
130
+ };
@@ -0,0 +1,165 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
+ }) : x)(function(x) {
11
+ if (typeof require !== "undefined") return require.apply(this, arguments);
12
+ throw Error('Dynamic require of "' + x + '" is not supported');
13
+ });
14
+ var __commonJS = (cb, mod) => function __require2() {
15
+ try {
16
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
17
+ } catch (e) {
18
+ throw mod = 0, e;
19
+ }
20
+ };
21
+ var __export = (target, all) => {
22
+ for (var name in all)
23
+ __defProp(target, name, { get: all[name], enumerable: true });
24
+ };
25
+ var __copyProps = (to, from, except, desc) => {
26
+ if (from && typeof from === "object" || typeof from === "function") {
27
+ for (let key of __getOwnPropNames(from))
28
+ if (!__hasOwnProp.call(to, key) && key !== except)
29
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
30
+ }
31
+ return to;
32
+ };
33
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
34
+ // If the importer is in node compatibility mode or this is not an ESM
35
+ // file that has been converted to a CommonJS file using a Babel-
36
+ // compatible transform (i.e. "__esModule" has not been set), then set
37
+ // "default" to the CommonJS "module.exports" for node compatibility.
38
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
39
+ mod
40
+ ));
41
+
42
+ // ../core/dist/errors.js
43
+ var DecisionsError = class extends Error {
44
+ code;
45
+ details;
46
+ constructor(code, message, details = {}) {
47
+ super(message);
48
+ this.code = code;
49
+ this.details = details;
50
+ this.name = "DecisionsError";
51
+ }
52
+ };
53
+ var ProviderError = class extends DecisionsError {
54
+ status;
55
+ constructor(code, message, status) {
56
+ super(code, message, status === void 0 ? {} : { status });
57
+ this.status = status;
58
+ this.name = "ProviderError";
59
+ }
60
+ };
61
+ function isDecisionsError(error) {
62
+ return error instanceof DecisionsError;
63
+ }
64
+
65
+ // src/exit-codes.ts
66
+ var EXIT = {
67
+ ok: 0,
68
+ failure: 1,
69
+ usage: 2,
70
+ egressRefused: 3,
71
+ budgetGuard: 4,
72
+ providerError: 5,
73
+ replayMiss: 6
74
+ };
75
+ var BY_CODE = {
76
+ "invalid-request": EXIT.usage,
77
+ "state-too-large": EXIT.usage,
78
+ "unknown-model": EXIT.usage,
79
+ "config-error": EXIT.usage,
80
+ "source-error": EXIT.usage,
81
+ "no-key": EXIT.usage,
82
+ "egress-refused": EXIT.egressRefused,
83
+ "budget-exceeded": EXIT.budgetGuard,
84
+ "provider-unreachable": EXIT.providerError,
85
+ "provider-http": EXIT.providerError,
86
+ "malformed-response": EXIT.providerError,
87
+ "replay-miss": EXIT.replayMiss
88
+ };
89
+ function exitFor(code) {
90
+ return code === "error" ? EXIT.failure : BY_CODE[code];
91
+ }
92
+
93
+ // src/envelope.ts
94
+ var ENVELOPE_VERSION = 1;
95
+ var FORMATS = ["json", "jsonl", "brief"];
96
+ function ok(command, result) {
97
+ return { v: ENVELOPE_VERSION, ok: true, command, result };
98
+ }
99
+ function fail(command, code, message, details) {
100
+ return {
101
+ v: ENVELOPE_VERSION,
102
+ ok: false,
103
+ command,
104
+ error: { code, message, ...details && Object.keys(details).length ? { details } : {} }
105
+ };
106
+ }
107
+
108
+ // src/run.ts
109
+ async function emit(io, command, format, body, render = () => void 0) {
110
+ try {
111
+ const result = await body();
112
+ io.out(render(result, format) ?? JSON.stringify(ok(command, result)));
113
+ return EXIT.ok;
114
+ } catch (error) {
115
+ const code = isDecisionsError(error) ? error.code : "error";
116
+ const message = error instanceof Error ? error.message : String(error);
117
+ const details = isDecisionsError(error) ? error.details : void 0;
118
+ io.out(
119
+ format === "brief" ? `decide ${command}: error ${code} \u2014 ${message}` : JSON.stringify(fail(command, code, message, details))
120
+ );
121
+ if (!isDecisionsError(error) && error instanceof Error && io.env.SYSTEM1_DEBUG)
122
+ io.err(error.stack ?? "");
123
+ return exitFor(code);
124
+ }
125
+ }
126
+ function extractFormat(argv, fallback) {
127
+ const rest = [];
128
+ let format;
129
+ for (let i = 0; i < argv.length; i += 1) {
130
+ const arg = argv[i];
131
+ if (arg === "--format") {
132
+ format = argv[i + 1];
133
+ i += 1;
134
+ } else if (arg.startsWith("--format=")) {
135
+ format = arg.slice("--format=".length);
136
+ } else {
137
+ rest.push(arg);
138
+ }
139
+ }
140
+ if (format === void 0) return { format: fallback, rest, explicit: false };
141
+ if (!FORMATS.includes(format)) {
142
+ throw new DecisionsError("invalid-request", `--format must be one of ${FORMATS.join(", ")}`);
143
+ }
144
+ return { format, rest, explicit: true };
145
+ }
146
+
147
+ // ../core/dist/version.js
148
+ var VERSION = "0.1.0";
149
+ var CLI_PACKAGE = "@garygentry/system1";
150
+
151
+ export {
152
+ __require,
153
+ __commonJS,
154
+ __export,
155
+ __toESM,
156
+ DecisionsError,
157
+ ProviderError,
158
+ isDecisionsError,
159
+ VERSION,
160
+ CLI_PACKAGE,
161
+ EXIT,
162
+ ENVELOPE_VERSION,
163
+ emit,
164
+ extractFormat
165
+ };