@izkac/forgekit 0.3.12 → 0.3.13
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/bin/forge.mjs +107 -107
- package/bin/forgekit.mjs +83 -83
- package/bin/review.mjs +81 -81
- package/package.json +1 -1
- package/scripts/prepack.mjs +78 -78
- package/scripts/run-tests.mjs +50 -50
- package/src/adr.mjs +236 -236
- package/src/adr.test.mjs +170 -170
- package/src/change.mjs +327 -234
- package/src/change.test.mjs +145 -83
- package/src/cleanup-sessions.mjs +84 -84
- package/src/config.mjs +103 -103
- package/src/defer.mjs +75 -75
- package/src/doctor.mjs +350 -341
- package/src/doctor.test.mjs +114 -114
- package/src/init.mjs +680 -621
- package/src/install.mjs +815 -815
- package/src/install.test.mjs +180 -180
- package/src/integrity-check.mjs +60 -60
- package/src/integrity.mjs +682 -682
- package/src/integrity.test.mjs +566 -566
- package/src/lib.mjs +143 -143
- package/src/models.defaults.json +41 -41
- package/src/new-session.mjs +99 -99
- package/src/openspec-overlays/README.md +19 -19
- package/src/openspec-overlays/openspec-apply-change-footer.md +14 -14
- package/src/openspec-overlays/opsx-apply-completion-step.md +1 -1
- package/src/openspec-overlays/opsx-apply-implement-step.md +11 -11
- package/src/paths.mjs +92 -92
- package/src/plan-engine.mjs +321 -278
- package/src/plan-engine.test.mjs +447 -283
- package/src/preferences.defaults.json +78 -78
- package/src/preferences.mjs +438 -438
- package/src/preferences.test.mjs +174 -174
- package/src/record-evidence.mjs +204 -204
- package/src/resolve-model.mjs +312 -312
- package/src/resolve-model.test.mjs +194 -194
- package/src/review/cli.test.mjs +117 -117
- package/src/review/export.mjs +172 -172
- package/src/review/export.test.mjs +197 -197
- package/src/review/fixtures/valid-review.json +42 -42
- package/src/review/lib.mjs +894 -894
- package/src/review/lib.test.mjs +266 -266
- package/src/review/schema.json +196 -196
- package/src/review/signals.test.mjs +62 -62
- package/src/score-cli.mjs +68 -68
- package/src/score.mjs +568 -568
- package/src/score.test.mjs +366 -366
- package/src/session-reminder.mjs +207 -207
- package/src/session-status.mjs +70 -70
- package/src/set-models.mjs +186 -186
- package/src/set-phase.mjs +205 -205
- package/src/set-prefs.mjs +294 -294
- package/src/specs-sync.mjs +234 -0
- package/src/specs-sync.test.mjs +114 -0
- package/src/spine.mjs +93 -93
- package/src/triage-prompt.mjs +175 -175
- package/src/triage-prompt.test.mjs +50 -50
- package/src/vendor-openspec-overlays.mjs +176 -176
- package/src/vendor-openspec-overlays.test.mjs +62 -62
- package/vendor/skills/archive-to-adr/SKILL.md +149 -149
- package/vendor/skills/forge/SKILL.md +136 -136
- package/vendor/skills/forge/docs/forge.md +650 -647
- package/vendor/skills/forge/phases/brainstorm.md +23 -23
- package/vendor/skills/forge/phases/finish.md +90 -87
- package/vendor/skills/forge/phases/implement.md +77 -77
- package/vendor/skills/forge/phases/plan-openspec.md +60 -60
- package/vendor/skills/forge/phases/plan-specs.md +163 -117
- package/vendor/skills/forge/phases/review.md +25 -25
- package/vendor/skills/forge/phases/verify.md +124 -124
- package/vendor/skills/forge/references/forge-layout.md +85 -85
- package/vendor/skills/forge/references/pace.md +115 -115
- package/vendor/skills/forge/references/plan-routing.md +52 -51
- package/vendor/skills/forge/references/runtime-integrity.md +232 -232
- package/vendor/skills/forge/references/substantial-work.md +37 -37
- package/vendor/skills/forge/references/test-evidence.md +30 -30
- package/vendor/skills/forge/references/test-strategy.md +68 -68
- package/vendor/skills/forge/skills/subagent-driven-development/SKILL.md +87 -87
- package/vendor/skills/forge/subagents/final-reviewer-prompt.md +56 -56
- package/vendor/skills/forge/subagents/implementer-prompt.md +38 -38
- package/vendor/skills/git-resolve-adr-conflict/SKILL.md +132 -132
- package/vendor/skills/thorough-code-review/SKILL.md +290 -290
- package/vendor/skills/thorough-code-review/examples.md +133 -133
- package/vendor/skills/thorough-code-review/reference/accepted-risks.md +26 -26
- package/vendor/skills/thorough-code-review/reference/lenses.md +96 -96
- package/vendor/skills/thorough-code-review/reference/phase1-scout.md +62 -62
- package/vendor/skills/thorough-code-review/reference/phase2-skeptic.md +105 -105
- package/vendor/skills/thorough-code-review/reference/report-schema.json +222 -222
- package/vendor/skills/thorough-code-review/reference/report-template.md +115 -115
- package/vendor/skills/thorough-code-review/reference/severity-rubric.md +49 -49
- package/vendor/skills/thorough-code-review/reference/signals-preflight.md +55 -55
- package/vendor/templates/adr/README.md +7 -7
- package/vendor/templates/adr/decisions.md +141 -141
- package/vendor/templates/adr/hooks/check-pending-adrs.mjs +74 -74
- package/vendor/templates/adr/hooks/check-pending-adrs.sh +3 -3
- package/vendor/templates/adr/hooks/openspec-archive-agent-message.mjs +52 -52
- package/vendor/templates/adr/hooks/openspec-archive-agent-message.sh +3 -3
- package/vendor/templates/project/claude/commands/forge-apply.md +75 -75
- package/vendor/templates/project/claude/commands/forge-brainstorm.md +7 -7
- package/vendor/templates/project/claude/commands/forge-build.md +17 -17
- package/vendor/templates/project/claude/commands/forge-plan.md +12 -12
- package/vendor/templates/project/claude/commands/forge-skip.md +14 -14
- package/vendor/templates/project/claude/commands/forge-status.md +16 -16
- package/vendor/templates/project/claude/commands/forge.md +16 -16
- package/vendor/templates/project/claude/hooks/forge-prompt-hook.mjs +73 -73
- package/vendor/templates/project/claude/hooks/forge-session-start.mjs +19 -19
- package/vendor/templates/project/claude/hooks/forge-triage-hook.mjs +77 -77
- package/vendor/templates/project/cursor/commands/forge-apply.md +75 -75
- package/vendor/templates/project/cursor/commands/forge-brainstorm.md +10 -10
- package/vendor/templates/project/cursor/commands/forge-build.md +17 -17
- package/vendor/templates/project/cursor/commands/forge-plan.md +15 -15
- package/vendor/templates/project/cursor/commands/forge-skip.md +14 -14
- package/vendor/templates/project/cursor/commands/forge-status.md +16 -16
- package/vendor/templates/project/cursor/commands/forge.md +16 -16
- package/vendor/templates/project/cursor/hooks/forge-session-start.mjs +30 -30
- package/vendor/templates/project/cursor/hooks/forge-session-start.sh +3 -3
package/src/set-models.mjs
CHANGED
|
@@ -1,186 +1,186 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Get or set the checkout-local Forge subagent billing preference.
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* forge set-models # print effective billing
|
|
7
|
-
* forge set-models included # set local billing
|
|
8
|
-
* forge set-models metered
|
|
9
|
-
*
|
|
10
|
-
* Options:
|
|
11
|
-
* --forge-dir <path> Forge root (default: .forge under cwd)
|
|
12
|
-
* --defaults <path> Defaults JSON path
|
|
13
|
-
* --json Machine-readable stdout for get
|
|
14
|
-
* --help
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import fs from 'node:fs';
|
|
18
|
-
import path from 'node:path';
|
|
19
|
-
import { pathToFileURL } from 'node:url';
|
|
20
|
-
import {
|
|
21
|
-
BILLING_LANES,
|
|
22
|
-
DEFAULTS_PATH,
|
|
23
|
-
loadJsonFile,
|
|
24
|
-
loadMergedConfig,
|
|
25
|
-
} from './resolve-model.mjs';
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {string[]} argv
|
|
29
|
-
*/
|
|
30
|
-
export function parseArgs(argv) {
|
|
31
|
-
const opts = {
|
|
32
|
-
billing: null,
|
|
33
|
-
forgeDir: null,
|
|
34
|
-
defaults: null,
|
|
35
|
-
json: false,
|
|
36
|
-
help: false,
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
40
|
-
const arg = argv[i];
|
|
41
|
-
if (arg === '--forge-dir') opts.forgeDir = argv[++i];
|
|
42
|
-
else if (arg === '--defaults') opts.defaults = argv[++i];
|
|
43
|
-
else if (arg === '--json') opts.json = true;
|
|
44
|
-
else if (arg === '--help' || arg === '-h') opts.help = true;
|
|
45
|
-
else if (arg === '--') continue;
|
|
46
|
-
else if (!arg.startsWith('-') && opts.billing === null) opts.billing = arg;
|
|
47
|
-
else throw new Error(`Unknown argument: ${arg}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return opts;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @param {{ forgeDir: string, billing: string }} opts
|
|
55
|
-
*/
|
|
56
|
-
export function writeLocalBilling(opts) {
|
|
57
|
-
if (!BILLING_LANES.includes(opts.billing)) {
|
|
58
|
-
throw new Error(`Unknown billing "${opts.billing}". Expected one of: ${BILLING_LANES.join(', ')}`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
fs.mkdirSync(opts.forgeDir, { recursive: true });
|
|
62
|
-
const localPath = path.join(opts.forgeDir, 'models.local.json');
|
|
63
|
-
|
|
64
|
-
/** @type {Record<string, unknown>} */
|
|
65
|
-
let existing = {};
|
|
66
|
-
if (fs.existsSync(localPath)) {
|
|
67
|
-
existing = loadJsonFile(localPath);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const next = { ...existing, billing: opts.billing };
|
|
71
|
-
fs.writeFileSync(localPath, `${JSON.stringify(next, null, 2)}\n`, 'utf8');
|
|
72
|
-
return { localPath, billing: opts.billing };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* @param {{ forgeDir?: string, defaultsPath?: string, cwd?: string }} [paths]
|
|
77
|
-
*/
|
|
78
|
-
export function getEffectiveBilling(paths = {}) {
|
|
79
|
-
const { config, sources, localPath } = loadMergedConfig({
|
|
80
|
-
defaultsPath: paths.defaultsPath,
|
|
81
|
-
forgeDir: paths.forgeDir,
|
|
82
|
-
cwd: paths.cwd,
|
|
83
|
-
});
|
|
84
|
-
const billing =
|
|
85
|
-
typeof config.billing === 'string' && BILLING_LANES.includes(config.billing)
|
|
86
|
-
? config.billing
|
|
87
|
-
: 'included';
|
|
88
|
-
return {
|
|
89
|
-
billing,
|
|
90
|
-
localPath,
|
|
91
|
-
localExists: fs.existsSync(localPath),
|
|
92
|
-
source: sources,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function printHelp() {
|
|
97
|
-
process.stdout.write(`Usage: forge set-models [included|metered] [options]
|
|
98
|
-
|
|
99
|
-
Get or set checkout-local Forge subagent billing lane.
|
|
100
|
-
|
|
101
|
-
forge models
|
|
102
|
-
Print effective lane only — does NOT create .forge/models.local.json.
|
|
103
|
-
Without a local file, this prints the committed default (usually "included").
|
|
104
|
-
|
|
105
|
-
forge models included|metered
|
|
106
|
-
Write/update .forge/models.local.json (gitignored, per-checkout).
|
|
107
|
-
|
|
108
|
-
forge models -- --json
|
|
109
|
-
Same get, with paths and localExists.
|
|
110
|
-
|
|
111
|
-
Defaults: models.defaults.json
|
|
112
|
-
Local overlay: .forge/models.local.json (appears only after a set)
|
|
113
|
-
|
|
114
|
-
Options:
|
|
115
|
-
--forge-dir <path> Forge directory (default: .forge)
|
|
116
|
-
--defaults <path> Defaults JSON path
|
|
117
|
-
--json JSON stdout when getting
|
|
118
|
-
--help Show help
|
|
119
|
-
`);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* @param {string[]} argv
|
|
124
|
-
* @param {{ cwd?: string, stdout?: NodeJS.WritableStream, stderr?: NodeJS.WritableStream }} [io]
|
|
125
|
-
*/
|
|
126
|
-
export function runSetModels(argv, io = {}) {
|
|
127
|
-
const stdout = io.stdout ?? process.stdout;
|
|
128
|
-
const stderr = io.stderr ?? process.stderr;
|
|
129
|
-
const cwd = io.cwd ?? process.cwd();
|
|
130
|
-
|
|
131
|
-
let opts;
|
|
132
|
-
try {
|
|
133
|
-
opts = parseArgs(argv);
|
|
134
|
-
} catch (err) {
|
|
135
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
136
|
-
stderr.write(`${msg}\n`);
|
|
137
|
-
return 2;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (opts.help) {
|
|
141
|
-
printHelp();
|
|
142
|
-
return 0;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const forgeDir = opts.forgeDir ?? path.join(cwd, '.forge');
|
|
146
|
-
const defaultsPath = opts.defaults ?? DEFAULTS_PATH;
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
if (opts.billing) {
|
|
150
|
-
const written = writeLocalBilling({ forgeDir, billing: opts.billing });
|
|
151
|
-
stdout.write(`billing=${written.billing}\n`);
|
|
152
|
-
stdout.write(`wrote ${written.localPath}\n`);
|
|
153
|
-
return 0;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const effective = getEffectiveBilling({
|
|
157
|
-
forgeDir,
|
|
158
|
-
defaultsPath,
|
|
159
|
-
cwd,
|
|
160
|
-
});
|
|
161
|
-
if (opts.json) {
|
|
162
|
-
stdout.write(`${JSON.stringify(effective, null, 2)}\n`);
|
|
163
|
-
} else {
|
|
164
|
-
stdout.write(`billing=${effective.billing}\n`);
|
|
165
|
-
if (effective.localExists) {
|
|
166
|
-
stdout.write(`local=${effective.localPath}\n`);
|
|
167
|
-
} else {
|
|
168
|
-
stdout.write(`local=(none — using models.defaults.json)\n`);
|
|
169
|
-
stdout.write(`hint: forge models included|metered # writes .forge/models.local.json\n`);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return 0;
|
|
173
|
-
} catch (err) {
|
|
174
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
175
|
-
stderr.write(`${msg}\n`);
|
|
176
|
-
return 1;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const isMain =
|
|
181
|
-
process.argv[1] &&
|
|
182
|
-
import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
|
|
183
|
-
|
|
184
|
-
if (isMain) {
|
|
185
|
-
process.exitCode = runSetModels(process.argv.slice(2));
|
|
186
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Get or set the checkout-local Forge subagent billing preference.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* forge set-models # print effective billing
|
|
7
|
+
* forge set-models included # set local billing
|
|
8
|
+
* forge set-models metered
|
|
9
|
+
*
|
|
10
|
+
* Options:
|
|
11
|
+
* --forge-dir <path> Forge root (default: .forge under cwd)
|
|
12
|
+
* --defaults <path> Defaults JSON path
|
|
13
|
+
* --json Machine-readable stdout for get
|
|
14
|
+
* --help
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import { pathToFileURL } from 'node:url';
|
|
20
|
+
import {
|
|
21
|
+
BILLING_LANES,
|
|
22
|
+
DEFAULTS_PATH,
|
|
23
|
+
loadJsonFile,
|
|
24
|
+
loadMergedConfig,
|
|
25
|
+
} from './resolve-model.mjs';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {string[]} argv
|
|
29
|
+
*/
|
|
30
|
+
export function parseArgs(argv) {
|
|
31
|
+
const opts = {
|
|
32
|
+
billing: null,
|
|
33
|
+
forgeDir: null,
|
|
34
|
+
defaults: null,
|
|
35
|
+
json: false,
|
|
36
|
+
help: false,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
40
|
+
const arg = argv[i];
|
|
41
|
+
if (arg === '--forge-dir') opts.forgeDir = argv[++i];
|
|
42
|
+
else if (arg === '--defaults') opts.defaults = argv[++i];
|
|
43
|
+
else if (arg === '--json') opts.json = true;
|
|
44
|
+
else if (arg === '--help' || arg === '-h') opts.help = true;
|
|
45
|
+
else if (arg === '--') continue;
|
|
46
|
+
else if (!arg.startsWith('-') && opts.billing === null) opts.billing = arg;
|
|
47
|
+
else throw new Error(`Unknown argument: ${arg}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return opts;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {{ forgeDir: string, billing: string }} opts
|
|
55
|
+
*/
|
|
56
|
+
export function writeLocalBilling(opts) {
|
|
57
|
+
if (!BILLING_LANES.includes(opts.billing)) {
|
|
58
|
+
throw new Error(`Unknown billing "${opts.billing}". Expected one of: ${BILLING_LANES.join(', ')}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fs.mkdirSync(opts.forgeDir, { recursive: true });
|
|
62
|
+
const localPath = path.join(opts.forgeDir, 'models.local.json');
|
|
63
|
+
|
|
64
|
+
/** @type {Record<string, unknown>} */
|
|
65
|
+
let existing = {};
|
|
66
|
+
if (fs.existsSync(localPath)) {
|
|
67
|
+
existing = loadJsonFile(localPath);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const next = { ...existing, billing: opts.billing };
|
|
71
|
+
fs.writeFileSync(localPath, `${JSON.stringify(next, null, 2)}\n`, 'utf8');
|
|
72
|
+
return { localPath, billing: opts.billing };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {{ forgeDir?: string, defaultsPath?: string, cwd?: string }} [paths]
|
|
77
|
+
*/
|
|
78
|
+
export function getEffectiveBilling(paths = {}) {
|
|
79
|
+
const { config, sources, localPath } = loadMergedConfig({
|
|
80
|
+
defaultsPath: paths.defaultsPath,
|
|
81
|
+
forgeDir: paths.forgeDir,
|
|
82
|
+
cwd: paths.cwd,
|
|
83
|
+
});
|
|
84
|
+
const billing =
|
|
85
|
+
typeof config.billing === 'string' && BILLING_LANES.includes(config.billing)
|
|
86
|
+
? config.billing
|
|
87
|
+
: 'included';
|
|
88
|
+
return {
|
|
89
|
+
billing,
|
|
90
|
+
localPath,
|
|
91
|
+
localExists: fs.existsSync(localPath),
|
|
92
|
+
source: sources,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function printHelp() {
|
|
97
|
+
process.stdout.write(`Usage: forge set-models [included|metered] [options]
|
|
98
|
+
|
|
99
|
+
Get or set checkout-local Forge subagent billing lane.
|
|
100
|
+
|
|
101
|
+
forge models
|
|
102
|
+
Print effective lane only — does NOT create .forge/models.local.json.
|
|
103
|
+
Without a local file, this prints the committed default (usually "included").
|
|
104
|
+
|
|
105
|
+
forge models included|metered
|
|
106
|
+
Write/update .forge/models.local.json (gitignored, per-checkout).
|
|
107
|
+
|
|
108
|
+
forge models -- --json
|
|
109
|
+
Same get, with paths and localExists.
|
|
110
|
+
|
|
111
|
+
Defaults: models.defaults.json
|
|
112
|
+
Local overlay: .forge/models.local.json (appears only after a set)
|
|
113
|
+
|
|
114
|
+
Options:
|
|
115
|
+
--forge-dir <path> Forge directory (default: .forge)
|
|
116
|
+
--defaults <path> Defaults JSON path
|
|
117
|
+
--json JSON stdout when getting
|
|
118
|
+
--help Show help
|
|
119
|
+
`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {string[]} argv
|
|
124
|
+
* @param {{ cwd?: string, stdout?: NodeJS.WritableStream, stderr?: NodeJS.WritableStream }} [io]
|
|
125
|
+
*/
|
|
126
|
+
export function runSetModels(argv, io = {}) {
|
|
127
|
+
const stdout = io.stdout ?? process.stdout;
|
|
128
|
+
const stderr = io.stderr ?? process.stderr;
|
|
129
|
+
const cwd = io.cwd ?? process.cwd();
|
|
130
|
+
|
|
131
|
+
let opts;
|
|
132
|
+
try {
|
|
133
|
+
opts = parseArgs(argv);
|
|
134
|
+
} catch (err) {
|
|
135
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
136
|
+
stderr.write(`${msg}\n`);
|
|
137
|
+
return 2;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (opts.help) {
|
|
141
|
+
printHelp();
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const forgeDir = opts.forgeDir ?? path.join(cwd, '.forge');
|
|
146
|
+
const defaultsPath = opts.defaults ?? DEFAULTS_PATH;
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
if (opts.billing) {
|
|
150
|
+
const written = writeLocalBilling({ forgeDir, billing: opts.billing });
|
|
151
|
+
stdout.write(`billing=${written.billing}\n`);
|
|
152
|
+
stdout.write(`wrote ${written.localPath}\n`);
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const effective = getEffectiveBilling({
|
|
157
|
+
forgeDir,
|
|
158
|
+
defaultsPath,
|
|
159
|
+
cwd,
|
|
160
|
+
});
|
|
161
|
+
if (opts.json) {
|
|
162
|
+
stdout.write(`${JSON.stringify(effective, null, 2)}\n`);
|
|
163
|
+
} else {
|
|
164
|
+
stdout.write(`billing=${effective.billing}\n`);
|
|
165
|
+
if (effective.localExists) {
|
|
166
|
+
stdout.write(`local=${effective.localPath}\n`);
|
|
167
|
+
} else {
|
|
168
|
+
stdout.write(`local=(none — using models.defaults.json)\n`);
|
|
169
|
+
stdout.write(`hint: forge models included|metered # writes .forge/models.local.json\n`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return 0;
|
|
173
|
+
} catch (err) {
|
|
174
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
175
|
+
stderr.write(`${msg}\n`);
|
|
176
|
+
return 1;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const isMain =
|
|
181
|
+
process.argv[1] &&
|
|
182
|
+
import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
|
|
183
|
+
|
|
184
|
+
if (isMain) {
|
|
185
|
+
process.exitCode = runSetModels(process.argv.slice(2));
|
|
186
|
+
}
|