@zhiman_innies/innies-codex 0.122.39 → 0.122.40
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/README.md +350 -0
- package/assets/innies-catalog.json +969 -0
- package/assets/superpowers/LICENSE +21 -0
- package/assets/superpowers/skills/brainstorming/SKILL.md +195 -0
- package/assets/superpowers/skills/brainstorming/scripts/frame-template.html +214 -0
- package/assets/superpowers/skills/brainstorming/scripts/helper.js +88 -0
- package/assets/superpowers/skills/brainstorming/scripts/server.cjs +354 -0
- package/assets/superpowers/skills/brainstorming/scripts/start-server.sh +148 -0
- package/assets/superpowers/skills/brainstorming/scripts/stop-server.sh +56 -0
- package/assets/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/assets/superpowers/skills/brainstorming/visual-companion.md +287 -0
- package/assets/superpowers/skills/dispatching-parallel-agents/SKILL.md +182 -0
- package/assets/superpowers/skills/executing-plans/SKILL.md +70 -0
- package/assets/superpowers/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/assets/superpowers/skills/receiving-code-review/SKILL.md +213 -0
- package/assets/superpowers/skills/requesting-code-review/SKILL.md +105 -0
- package/assets/superpowers/skills/requesting-code-review/code-reviewer.md +146 -0
- package/assets/superpowers/skills/subagent-driven-development/SKILL.md +277 -0
- package/assets/superpowers/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/assets/superpowers/skills/subagent-driven-development/implementer-prompt.md +113 -0
- package/assets/superpowers/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/assets/superpowers/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/assets/superpowers/skills/systematic-debugging/SKILL.md +296 -0
- package/assets/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/assets/superpowers/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/assets/superpowers/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/assets/superpowers/skills/systematic-debugging/find-polluter.sh +63 -0
- package/assets/superpowers/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/assets/superpowers/skills/systematic-debugging/test-academic.md +14 -0
- package/assets/superpowers/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/assets/superpowers/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/assets/superpowers/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/assets/superpowers/skills/test-driven-development/SKILL.md +371 -0
- package/assets/superpowers/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/assets/superpowers/skills/using-git-worktrees/SKILL.md +218 -0
- package/assets/superpowers/skills/using-superpowers/SKILL.md +125 -0
- package/assets/superpowers/skills/using-superpowers/references/codex-tools.md +104 -0
- package/assets/superpowers/skills/using-superpowers/references/gemini-tools.md +33 -0
- package/assets/superpowers/skills/verification-before-completion/SKILL.md +139 -0
- package/assets/superpowers/skills/writing-plans/SKILL.md +152 -0
- package/assets/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/assets/superpowers/skills/writing-skills/SKILL.md +655 -0
- package/assets/superpowers/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/assets/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/assets/superpowers/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/assets/superpowers/skills/writing-skills/persuasion-principles.md +187 -0
- package/assets/superpowers/skills/writing-skills/render-graphs.js +168 -0
- package/assets/superpowers/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/bin/codex.js +216 -0
- package/bin/innies-coding-runtime.js +786 -0
- package/bin/innies-config.js +573 -0
- package/bin/innies-init.js +9 -0
- package/bin/innies.js +77 -0
- package/bin/rg +79 -0
- package/package.json +29 -1
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const DEFAULT_MODEL = "qwen35_35b";
|
|
10
|
+
const DEFAULT_PROVIDER = "zhiman_35b";
|
|
11
|
+
const DASHSCOPE_MODEL = "qwen3.6-plus";
|
|
12
|
+
const QWEN_MODELS = new Set([DEFAULT_MODEL, DASHSCOPE_MODEL]);
|
|
13
|
+
const LEGACY_MODELS = new Set(["qwen-plus", "qwen-plus-latest"]);
|
|
14
|
+
const DEFAULT_HOME_DIR = ".inniescoder";
|
|
15
|
+
const DEFAULT_CATALOG_FILENAME = "catalog.json";
|
|
16
|
+
const DEFAULT_CONFIG_FILENAME = "config.toml";
|
|
17
|
+
const DEFAULT_STATE_FILENAME = "innies-state.json";
|
|
18
|
+
const DEFAULT_SUPERPOWERS_DIRNAME = "superpowers";
|
|
19
|
+
const INSTALL_SUPERPOWERS_ENV = "INNIES_INSTALL_SUPERPOWERS";
|
|
20
|
+
const SUPERPOWERS_MARKER_FILENAME = ".innies-superpowers.marker";
|
|
21
|
+
const ZHIMAN_35B_PROVIDER_HEADER = "[model_providers.zhiman_35b]";
|
|
22
|
+
const ZHIMAN_35B_RESPONSES_BASE_URL = "http://101.237.37.116:7380/v1";
|
|
23
|
+
const DASHSCOPE_PROVIDER_HEADER = "[model_providers.dashscope]";
|
|
24
|
+
const DASHSCOPE_RESPONSES_BASE_URL =
|
|
25
|
+
"https://dashscope.aliyuncs.com/api/v2/apps/protocols/compatible-mode/v1";
|
|
26
|
+
const RESERVED_PROVIDER_HEADERS = Object.freeze([
|
|
27
|
+
"[model_providers.openai]",
|
|
28
|
+
"[model_providers.ollama]",
|
|
29
|
+
"[model_providers.lmstudio]",
|
|
30
|
+
]);
|
|
31
|
+
const MODEL_SELECTION_STATES = Object.freeze({
|
|
32
|
+
MANAGED_DEFAULT: "managed_default",
|
|
33
|
+
USER_SELECTED: "user_selected",
|
|
34
|
+
});
|
|
35
|
+
const ROOT_MANAGED_SETTINGS = Object.freeze([
|
|
36
|
+
["model_provider", null],
|
|
37
|
+
["model", null],
|
|
38
|
+
["model_catalog_json", null],
|
|
39
|
+
["model_reasoning_effort", null],
|
|
40
|
+
]);
|
|
41
|
+
const LEGACY_MANAGED_GPT_MODEL = "gpt-5.5";
|
|
42
|
+
const LEGACY_MANAGED_GPT_PROVIDER = "openai";
|
|
43
|
+
const LEGACY_MANAGED_GPT_REASONING = "high";
|
|
44
|
+
|
|
45
|
+
export function resolveInniesHome() {
|
|
46
|
+
if (process.env.INNIES_HOME) {
|
|
47
|
+
return process.env.INNIES_HOME;
|
|
48
|
+
}
|
|
49
|
+
return path.join(os.homedir(), DEFAULT_HOME_DIR);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function ensureInniesHomeDefaults(homeDir) {
|
|
53
|
+
const state = loadInniesState(homeDir);
|
|
54
|
+
const catalogPath = path.join(homeDir, DEFAULT_CATALOG_FILENAME);
|
|
55
|
+
ensureInniesCatalog(catalogPath);
|
|
56
|
+
if (shouldInstallInniesSuperpowers()) {
|
|
57
|
+
ensureInniesSuperpowers(homeDir);
|
|
58
|
+
} else {
|
|
59
|
+
removeManagedInniesSuperpowers(homeDir);
|
|
60
|
+
}
|
|
61
|
+
const nextState = ensureInniesConfig(
|
|
62
|
+
path.join(homeDir, DEFAULT_CONFIG_FILENAME),
|
|
63
|
+
catalogPath,
|
|
64
|
+
state,
|
|
65
|
+
);
|
|
66
|
+
writeInniesState(homeDir, nextState);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function defaultCatalogAssetPath() {
|
|
70
|
+
return path.join(__dirname, "..", "assets", "innies-catalog.json");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function defaultSuperpowersAssetPath() {
|
|
74
|
+
return path.join(__dirname, "..", "assets", DEFAULT_SUPERPOWERS_DIRNAME);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function shouldInstallInniesSuperpowers() {
|
|
78
|
+
const value = process.env[INSTALL_SUPERPOWERS_ENV]?.trim().toLowerCase();
|
|
79
|
+
return value === "1" || value === "true" || value === "yes";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function loadDefaultCatalog() {
|
|
83
|
+
return JSON.parse(fs.readFileSync(defaultCatalogAssetPath(), "utf8"));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function writeJsonFile(filePath, value) {
|
|
87
|
+
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function ensureInniesSuperpowers(homeDir) {
|
|
91
|
+
const sourceDir = defaultSuperpowersAssetPath();
|
|
92
|
+
if (!fs.existsSync(sourceDir)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const destDir = path.join(homeDir, DEFAULT_SUPERPOWERS_DIRNAME);
|
|
97
|
+
const markerPath = path.join(destDir, SUPERPOWERS_MARKER_FILENAME);
|
|
98
|
+
const fingerprint = directoryFingerprint(sourceDir);
|
|
99
|
+
if (
|
|
100
|
+
fs.existsSync(destDir) &&
|
|
101
|
+
readTextFile(markerPath)?.trim() === fingerprint
|
|
102
|
+
) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (fs.existsSync(markerPath)) {
|
|
107
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
108
|
+
}
|
|
109
|
+
copyDirectoryContents(sourceDir, destDir);
|
|
110
|
+
fs.writeFileSync(markerPath, `${fingerprint}\n`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function removeManagedInniesSuperpowers(homeDir) {
|
|
114
|
+
const destDir = path.join(homeDir, DEFAULT_SUPERPOWERS_DIRNAME);
|
|
115
|
+
const markerPath = path.join(destDir, SUPERPOWERS_MARKER_FILENAME);
|
|
116
|
+
if (!fs.existsSync(markerPath)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function readTextFile(filePath) {
|
|
124
|
+
try {
|
|
125
|
+
return fs.readFileSync(filePath, "utf8");
|
|
126
|
+
} catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function directoryFingerprint(rootDir) {
|
|
132
|
+
const hash = crypto.createHash("sha256");
|
|
133
|
+
for (const relativePath of listRelativeFiles(rootDir)) {
|
|
134
|
+
const sourcePath = path.join(rootDir, relativePath);
|
|
135
|
+
hash.update(relativePath.split(path.sep).join("/"));
|
|
136
|
+
hash.update("\0");
|
|
137
|
+
hash.update(fs.readFileSync(sourcePath));
|
|
138
|
+
hash.update("\0");
|
|
139
|
+
}
|
|
140
|
+
return hash.digest("hex");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function listRelativeFiles(rootDir, currentDir = rootDir) {
|
|
144
|
+
const entries = fs
|
|
145
|
+
.readdirSync(currentDir, { withFileTypes: true })
|
|
146
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
147
|
+
const files = [];
|
|
148
|
+
|
|
149
|
+
for (const entry of entries) {
|
|
150
|
+
const entryPath = path.join(currentDir, entry.name);
|
|
151
|
+
if (entry.isDirectory()) {
|
|
152
|
+
files.push(...listRelativeFiles(rootDir, entryPath));
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (entry.isFile()) {
|
|
156
|
+
files.push(path.relative(rootDir, entryPath));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return files;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function copyDirectoryContents(sourceDir, destDir) {
|
|
164
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
165
|
+
const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
|
|
166
|
+
for (const entry of entries) {
|
|
167
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
168
|
+
const destPath = path.join(destDir, entry.name);
|
|
169
|
+
if (entry.isDirectory()) {
|
|
170
|
+
copyDirectoryContents(sourcePath, destPath);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (entry.isFile()) {
|
|
174
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
175
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
176
|
+
fs.chmodSync(destPath, fs.statSync(sourcePath).mode);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function stateFilePath(homeDir) {
|
|
182
|
+
return path.join(homeDir, DEFAULT_STATE_FILENAME);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function defaultInniesState() {
|
|
186
|
+
return {
|
|
187
|
+
model_selection_state: MODEL_SELECTION_STATES.MANAGED_DEFAULT,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function loadInniesState(homeDir) {
|
|
192
|
+
const filePath = stateFilePath(homeDir);
|
|
193
|
+
if (!fs.existsSync(filePath)) {
|
|
194
|
+
return defaultInniesState();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
199
|
+
if (
|
|
200
|
+
parsed &&
|
|
201
|
+
Object.values(MODEL_SELECTION_STATES).includes(parsed.model_selection_state)
|
|
202
|
+
) {
|
|
203
|
+
return parsed;
|
|
204
|
+
}
|
|
205
|
+
} catch {}
|
|
206
|
+
|
|
207
|
+
return defaultInniesState();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function writeInniesState(homeDir, state) {
|
|
211
|
+
writeJsonFile(stateFilePath(homeDir), state);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function ensureInniesCatalog(catalogPath) {
|
|
215
|
+
const defaultCatalog = loadDefaultCatalog();
|
|
216
|
+
if (!fs.existsSync(catalogPath)) {
|
|
217
|
+
writeJsonFile(catalogPath, defaultCatalog);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let existingCatalog;
|
|
222
|
+
try {
|
|
223
|
+
existingCatalog = JSON.parse(fs.readFileSync(catalogPath, "utf8"));
|
|
224
|
+
} catch {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (shouldReplaceLegacyCatalog(existingCatalog)) {
|
|
229
|
+
writeJsonFile(catalogPath, defaultCatalog);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function shouldReplaceLegacyCatalog(catalog) {
|
|
234
|
+
if (!catalog || !Array.isArray(catalog.models)) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const slugs = catalog.models
|
|
239
|
+
.map((model) => model?.slug)
|
|
240
|
+
.filter((slug) => typeof slug === "string");
|
|
241
|
+
|
|
242
|
+
if (slugs.length === 0) {
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (slugs.length === 1 && slugs[0] === DEFAULT_MODEL) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
for (const qwenModel of catalog.models.filter((model) =>
|
|
251
|
+
QWEN_MODELS.has(model?.slug),
|
|
252
|
+
)) {
|
|
253
|
+
if (
|
|
254
|
+
qwenModel.apply_patch_tool_type !== "function" ||
|
|
255
|
+
qwenModel.supports_reasoning_summaries !== false ||
|
|
256
|
+
qwenModel.support_verbosity !== false ||
|
|
257
|
+
Object.prototype.hasOwnProperty.call(qwenModel, "default_reasoning_level") ||
|
|
258
|
+
!Array.isArray(qwenModel.supported_reasoning_levels) ||
|
|
259
|
+
qwenModel.supported_reasoning_levels.length !== 0
|
|
260
|
+
) {
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (!slugs.includes(DEFAULT_MODEL)) {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return slugs.some((slug) => LEGACY_MODELS.has(slug));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function ensureInniesConfig(configPath, catalogPath, state) {
|
|
273
|
+
if (!fs.existsSync(configPath)) {
|
|
274
|
+
fs.writeFileSync(configPath, defaultInniesConfig(catalogPath, managedDefaultModel()));
|
|
275
|
+
return defaultInniesState();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const existing = fs.readFileSync(configPath, "utf8");
|
|
279
|
+
const nextState = determineModelSelectionState(existing, state);
|
|
280
|
+
const updated = normalizeInniesConfig(existing, catalogPath, nextState);
|
|
281
|
+
if (updated !== existing) {
|
|
282
|
+
fs.writeFileSync(configPath, updated);
|
|
283
|
+
}
|
|
284
|
+
return nextState;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function defaultInniesConfig(catalogPath, managedDefault) {
|
|
288
|
+
const lines = managedDefault
|
|
289
|
+
? managedDefaultLines(catalogPath, managedDefault)
|
|
290
|
+
: [`model_catalog_json = ${JSON.stringify(catalogPath)}`];
|
|
291
|
+
return [
|
|
292
|
+
...lines,
|
|
293
|
+
"",
|
|
294
|
+
defaultZhiman35bProviderBlock(),
|
|
295
|
+
"",
|
|
296
|
+
defaultDashscopeProviderBlock(),
|
|
297
|
+
"",
|
|
298
|
+
].join("\n");
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function normalizeInniesConfig(contents, catalogPath, state) {
|
|
302
|
+
if (contents.trim() === "") {
|
|
303
|
+
return defaultInniesConfig(catalogPath, managedDefaultModel());
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const isUserSelected =
|
|
307
|
+
state.model_selection_state === MODEL_SELECTION_STATES.USER_SELECTED;
|
|
308
|
+
const managedDefault = isUserSelected ? null : managedDefaultModel();
|
|
309
|
+
const managedSettings = ROOT_MANAGED_SETTINGS;
|
|
310
|
+
const unmanagedContents = stripManagedRootSettings(contents, managedSettings).trim();
|
|
311
|
+
const managedLines = isUserSelected
|
|
312
|
+
? preservedUserManagedLines(contents, catalogPath)
|
|
313
|
+
: managedDefault
|
|
314
|
+
? managedDefaultLines(catalogPath, managedDefault)
|
|
315
|
+
: catalogOnlyManagedLines(catalogPath);
|
|
316
|
+
let updated = `${managedLines.join("\n")}\n`;
|
|
317
|
+
|
|
318
|
+
if (unmanagedContents !== "") {
|
|
319
|
+
updated = `${updated}\n${unmanagedContents}\n`;
|
|
320
|
+
} else {
|
|
321
|
+
updated = `${updated}\n`;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
updated = normalizeManagedProviderBlocks(stripReservedProviderBlocks(updated));
|
|
325
|
+
if (!updated.includes(ZHIMAN_35B_PROVIDER_HEADER)) {
|
|
326
|
+
updated = `${updated.trimEnd()}\n\n${defaultZhiman35bProviderBlock()}\n`;
|
|
327
|
+
}
|
|
328
|
+
if (!updated.includes(DASHSCOPE_PROVIDER_HEADER)) {
|
|
329
|
+
updated = `${updated.trimEnd()}\n\n${defaultDashscopeProviderBlock()}\n`;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return updated;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function managedDefaultLines(catalogPath, managedDefault) {
|
|
336
|
+
return [
|
|
337
|
+
`model_provider = ${JSON.stringify(managedDefault.provider)}`,
|
|
338
|
+
`model = ${JSON.stringify(managedDefault.model)}`,
|
|
339
|
+
`model_catalog_json = ${JSON.stringify(catalogPath)}`,
|
|
340
|
+
];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function catalogOnlyManagedLines(catalogPath) {
|
|
344
|
+
return [`model_catalog_json = ${JSON.stringify(catalogPath)}`];
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function preservedUserManagedLines(contents, catalogPath) {
|
|
348
|
+
const preservedModelProvider = readRootSetting(contents, "model_provider");
|
|
349
|
+
const preservedModel = readRootSetting(contents, "model");
|
|
350
|
+
const preservedModelValue = extractRootSettingValue(contents, "model");
|
|
351
|
+
const preservedProviderValue = extractRootSettingValue(contents, "model_provider");
|
|
352
|
+
const preservesQwenModel =
|
|
353
|
+
(preservedModelValue === DEFAULT_MODEL &&
|
|
354
|
+
(preservedProviderValue == null || preservedProviderValue === DEFAULT_PROVIDER)) ||
|
|
355
|
+
(preservedModelValue === DASHSCOPE_MODEL &&
|
|
356
|
+
(preservedProviderValue == null || preservedProviderValue === "dashscope"));
|
|
357
|
+
const preservedEffort = preservesQwenModel
|
|
358
|
+
? null
|
|
359
|
+
: readRootSetting(contents, "model_reasoning_effort");
|
|
360
|
+
|
|
361
|
+
return [
|
|
362
|
+
preservedModelProvider ?? 'model_provider = "openai"',
|
|
363
|
+
preservedModel ?? 'model = "gpt-5.5"',
|
|
364
|
+
`model_catalog_json = ${JSON.stringify(catalogPath)}`,
|
|
365
|
+
...(preservedEffort ? [preservedEffort] : []),
|
|
366
|
+
];
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function readRootSetting(contents, key) {
|
|
370
|
+
const settingPattern = new RegExp(`^\\s*${key}\\s*=.*$`, "m");
|
|
371
|
+
return contents.match(settingPattern)?.[0] ?? null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function stripReservedProviderBlocks(contents) {
|
|
375
|
+
const lines = contents.split(/\r?\n/);
|
|
376
|
+
const keptLines = [];
|
|
377
|
+
let skippingReservedBlock = false;
|
|
378
|
+
|
|
379
|
+
for (const line of lines) {
|
|
380
|
+
const trimmed = line.trim();
|
|
381
|
+
const isSectionHeader = /^\[[^\]]+\]$/.test(trimmed);
|
|
382
|
+
if (isSectionHeader) {
|
|
383
|
+
skippingReservedBlock = RESERVED_PROVIDER_HEADERS.includes(trimmed);
|
|
384
|
+
}
|
|
385
|
+
if (!skippingReservedBlock) {
|
|
386
|
+
keptLines.push(line);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return keptLines.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd();
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function determineModelSelectionState(contents, previousState) {
|
|
394
|
+
const currentModel = extractRootSettingValue(contents, "model");
|
|
395
|
+
const currentProvider = extractRootSettingValue(contents, "model_provider");
|
|
396
|
+
if (currentModel == null && currentProvider == null) {
|
|
397
|
+
return previousState;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (
|
|
401
|
+
currentModel === DEFAULT_MODEL &&
|
|
402
|
+
(currentProvider == null || currentProvider === DEFAULT_PROVIDER)
|
|
403
|
+
) {
|
|
404
|
+
return previousState;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (
|
|
408
|
+
currentModel === DASHSCOPE_MODEL &&
|
|
409
|
+
(currentProvider == null || currentProvider === "dashscope")
|
|
410
|
+
) {
|
|
411
|
+
return previousState;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (
|
|
415
|
+
previousState.model_selection_state === MODEL_SELECTION_STATES.MANAGED_DEFAULT &&
|
|
416
|
+
currentModel === LEGACY_MANAGED_GPT_MODEL &&
|
|
417
|
+
currentProvider === LEGACY_MANAGED_GPT_PROVIDER &&
|
|
418
|
+
extractRootSettingValue(contents, "model_reasoning_effort") ===
|
|
419
|
+
LEGACY_MANAGED_GPT_REASONING
|
|
420
|
+
) {
|
|
421
|
+
return previousState;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (
|
|
425
|
+
currentModel != null &&
|
|
426
|
+
!LEGACY_MODELS.has(currentModel) &&
|
|
427
|
+
(currentModel !== DEFAULT_MODEL || currentProvider !== DEFAULT_PROVIDER) &&
|
|
428
|
+
(currentModel !== DASHSCOPE_MODEL || currentProvider !== "dashscope")
|
|
429
|
+
) {
|
|
430
|
+
return {
|
|
431
|
+
model_selection_state: MODEL_SELECTION_STATES.USER_SELECTED,
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return previousState;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function extractRootSettingValue(contents, key) {
|
|
439
|
+
const match = contents.match(new RegExp(`^\\s*${key}\\s*=\\s*\"([^\"]*)\"`, "m"));
|
|
440
|
+
return match?.[1] ?? null;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function stripManagedRootSettings(contents, managedSettings = ROOT_MANAGED_SETTINGS) {
|
|
444
|
+
const managedKeys = new Set(managedSettings.map(([key]) => key));
|
|
445
|
+
const lines = contents.split(/\r?\n/);
|
|
446
|
+
const keptLines = [];
|
|
447
|
+
let inRootTable = true;
|
|
448
|
+
|
|
449
|
+
for (const line of lines) {
|
|
450
|
+
const trimmed = line.trim();
|
|
451
|
+
if (/^\[[^\]]+\]$/.test(trimmed)) {
|
|
452
|
+
inRootTable = false;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const rootSetting = line.match(/^\s*([A-Za-z0-9_]+)\s*=/);
|
|
456
|
+
if (inRootTable && rootSetting && managedKeys.has(rootSetting[1])) {
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
keptLines.push(line);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return keptLines.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function managedDefaultModel() {
|
|
467
|
+
return {
|
|
468
|
+
provider: DEFAULT_PROVIDER,
|
|
469
|
+
model: DEFAULT_MODEL,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function normalizeManagedProviderBlocks(contents) {
|
|
474
|
+
let updated = normalizeProviderBlock(contents, {
|
|
475
|
+
providerHeader: ZHIMAN_35B_PROVIDER_HEADER,
|
|
476
|
+
baseUrl: ZHIMAN_35B_RESPONSES_BASE_URL,
|
|
477
|
+
envKey: "ZHIMAN_35B_API_KEY",
|
|
478
|
+
});
|
|
479
|
+
updated = normalizeProviderBlock(updated, {
|
|
480
|
+
providerHeader: DASHSCOPE_PROVIDER_HEADER,
|
|
481
|
+
baseUrl: DASHSCOPE_RESPONSES_BASE_URL,
|
|
482
|
+
envKey: "DASHSCOPE_API_KEY",
|
|
483
|
+
});
|
|
484
|
+
return updated;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function normalizeProviderBlock(contents, provider) {
|
|
488
|
+
const lines = contents.split(/\r?\n/);
|
|
489
|
+
const updated = [];
|
|
490
|
+
let inProviderBlock = false;
|
|
491
|
+
let sawBaseUrl = false;
|
|
492
|
+
let sawWireApi = false;
|
|
493
|
+
let sawEnvKey = false;
|
|
494
|
+
let sawBearerToken = false;
|
|
495
|
+
|
|
496
|
+
const finishProviderBlock = () => {
|
|
497
|
+
if (!inProviderBlock) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (!sawBaseUrl) {
|
|
501
|
+
updated.push(`base_url = ${JSON.stringify(provider.baseUrl)}`);
|
|
502
|
+
}
|
|
503
|
+
if (!sawWireApi) {
|
|
504
|
+
updated.push('wire_api = "responses"');
|
|
505
|
+
}
|
|
506
|
+
if (!sawEnvKey) {
|
|
507
|
+
updated.push(`env_key = ${JSON.stringify(provider.envKey)}`);
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
for (const line of lines) {
|
|
512
|
+
const trimmed = line.trim();
|
|
513
|
+
const isSectionHeader = /^\[[^\]]+\]$/.test(trimmed);
|
|
514
|
+
if (isSectionHeader) {
|
|
515
|
+
finishProviderBlock();
|
|
516
|
+
inProviderBlock = trimmed === provider.providerHeader;
|
|
517
|
+
sawBaseUrl = false;
|
|
518
|
+
sawWireApi = false;
|
|
519
|
+
sawEnvKey = false;
|
|
520
|
+
sawBearerToken = false;
|
|
521
|
+
updated.push(line);
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (inProviderBlock) {
|
|
526
|
+
if (/^\s*base_url\s*=/.test(line)) {
|
|
527
|
+
updated.push(`base_url = ${JSON.stringify(provider.baseUrl)}`);
|
|
528
|
+
sawBaseUrl = true;
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
if (/^\s*wire_api\s*=/.test(line)) {
|
|
532
|
+
updated.push('wire_api = "responses"');
|
|
533
|
+
sawWireApi = true;
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
if (/^\s*env_key\s*=/.test(line)) {
|
|
537
|
+
updated.push(`env_key = ${JSON.stringify(provider.envKey)}`);
|
|
538
|
+
sawEnvKey = true;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
if (/^\s*experimental_bearer_token\s*=/.test(line)) {
|
|
542
|
+
updated.push(line);
|
|
543
|
+
sawBearerToken = true;
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
updated.push(line);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
finishProviderBlock();
|
|
552
|
+
return updated.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd();
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function defaultZhiman35bProviderBlock() {
|
|
556
|
+
return [
|
|
557
|
+
ZHIMAN_35B_PROVIDER_HEADER,
|
|
558
|
+
'name = "zhiman_35b"',
|
|
559
|
+
`base_url = ${JSON.stringify(ZHIMAN_35B_RESPONSES_BASE_URL)}`,
|
|
560
|
+
'wire_api = "responses"',
|
|
561
|
+
'env_key = "ZHIMAN_35B_API_KEY"',
|
|
562
|
+
].join("\n");
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function defaultDashscopeProviderBlock() {
|
|
566
|
+
return [
|
|
567
|
+
DASHSCOPE_PROVIDER_HEADER,
|
|
568
|
+
'name = "DashScope"',
|
|
569
|
+
`base_url = ${JSON.stringify(DASHSCOPE_RESPONSES_BASE_URL)}`,
|
|
570
|
+
'wire_api = "responses"',
|
|
571
|
+
'env_key = "DASHSCOPE_API_KEY"',
|
|
572
|
+
].join("\n");
|
|
573
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
|
|
5
|
+
import { ensureInniesHomeDefaults, resolveInniesHome } from "./innies-config.js";
|
|
6
|
+
|
|
7
|
+
const codexHome = resolveInniesHome();
|
|
8
|
+
fs.mkdirSync(codexHome, { recursive: true });
|
|
9
|
+
ensureInniesHomeDefaults(codexHome);
|
package/bin/innies.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
import { maybeRunInniesCodingRuntime } from "./innies-coding-runtime.js";
|
|
7
|
+
import { ensureInniesHomeDefaults, resolveInniesHome } from "./innies-config.js";
|
|
8
|
+
|
|
9
|
+
const INNIES_HOME_ENV_VAR = "INNIES_HOME";
|
|
10
|
+
|
|
11
|
+
function isVersionRequest(args) {
|
|
12
|
+
return args.length === 1 && (args[0] === "--version" || args[0] === "-V");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (isVersionRequest(process.argv.slice(2))) {
|
|
16
|
+
const packageJson = JSON.parse(
|
|
17
|
+
fs.readFileSync(new URL("../package.json", import.meta.url), "utf8"),
|
|
18
|
+
);
|
|
19
|
+
const runtimeVersion = `innies-cli ${packageJson.version}`;
|
|
20
|
+
writeExternalRuntimeSmokeResult(runtimeVersion);
|
|
21
|
+
console.log(runtimeVersion);
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const codexHome = resolveInniesHome();
|
|
26
|
+
process.env[INNIES_HOME_ENV_VAR] = codexHome;
|
|
27
|
+
process.env.CODEX_HOME = codexHome;
|
|
28
|
+
fs.mkdirSync(codexHome, { recursive: true });
|
|
29
|
+
|
|
30
|
+
ensureInniesHomeDefaults(codexHome);
|
|
31
|
+
|
|
32
|
+
if (await maybeRunInniesCodingRuntime()) {
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
await import("./codex.js");
|
|
37
|
+
|
|
38
|
+
function writeExternalRuntimeSmokeResult(runtimeVersion) {
|
|
39
|
+
if (process.env.INNIES_CODING_STAGE !== "external_runtime_smoke") {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const resultFile = process.env.INNIES_CODING_AGENT_RUN_RESULT_FILE;
|
|
43
|
+
if (!resultFile) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fs.mkdirSync(path.dirname(resultFile), { recursive: true });
|
|
48
|
+
fs.writeFileSync(
|
|
49
|
+
resultFile,
|
|
50
|
+
`${JSON.stringify(
|
|
51
|
+
{
|
|
52
|
+
stage: "external_runtime_smoke",
|
|
53
|
+
status: "success",
|
|
54
|
+
input_metadata_json: {
|
|
55
|
+
workflow_id: process.env.INNIES_CODING_WORKFLOW_ID || null,
|
|
56
|
+
runtime_version: runtimeVersion,
|
|
57
|
+
},
|
|
58
|
+
output_artifact_list: [
|
|
59
|
+
{
|
|
60
|
+
artifact_type: "external_runtime_smoke",
|
|
61
|
+
status: "generated",
|
|
62
|
+
content_json: {
|
|
63
|
+
runtime_version: runtimeVersion,
|
|
64
|
+
},
|
|
65
|
+
metadata_json: {
|
|
66
|
+
workflow_id: process.env.INNIES_CODING_WORKFLOW_ID || null,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
failure_context_json: {},
|
|
71
|
+
},
|
|
72
|
+
null,
|
|
73
|
+
2,
|
|
74
|
+
)}\n`,
|
|
75
|
+
"utf8",
|
|
76
|
+
);
|
|
77
|
+
}
|