@growthub/cli 0.3.59 → 0.3.60
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/assets/worker-kits/growthub-zernio-social-v1/.env.example +5 -0
- package/assets/worker-kits/growthub-zernio-social-v1/QUICKSTART.md +36 -4
- package/assets/worker-kits/growthub-zernio-social-v1/bundles/growthub-zernio-social-v1.json +30 -1
- package/assets/worker-kits/growthub-zernio-social-v1/docs/growthub-agentic-social-platform-ui-shell.md +134 -0
- package/assets/worker-kits/growthub-zernio-social-v1/docs/local-adapters.md +2 -2
- package/assets/worker-kits/growthub-zernio-social-v1/growthub-meta/README.md +5 -8
- package/assets/worker-kits/growthub-zernio-social-v1/growthub-meta/kit-standard.md +1 -1
- package/assets/worker-kits/growthub-zernio-social-v1/kit.json +33 -1
- package/assets/worker-kits/growthub-zernio-social-v1/skills.md +1 -1
- package/assets/worker-kits/growthub-zernio-social-v1/studio/.env.example +3 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/dist/assets/index-DTmBMuXr.js +78 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/dist/assets/index-gHr-nTMF.css +1 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/dist/index.html +14 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/index.html +13 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/package-lock.json +1677 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/package.json +20 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/serve.mjs +60 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/App.jsx +130 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/api.js +146 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/app.css +558 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/lib/rules.js +64 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/lib/templates.js +207 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/main.jsx +10 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Accounts.jsx +57 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Agent.jsx +167 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Analytics.jsx +164 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/ApiKeys.jsx +143 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Automations.jsx +122 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/CommentRules.jsx +592 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Compose.jsx +185 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Dashboard.jsx +87 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Inbox.jsx +144 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Queues.jsx +167 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Scheduled.jsx +85 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Sequences.jsx +160 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/src/views/Templates.jsx +275 -0
- package/assets/worker-kits/growthub-zernio-social-v1/studio/vite.config.js +7 -0
- package/assets/worker-kits/growthub-zernio-social-v1/workers/zernio-social-operator/CLAUDE.md +3 -3
- package/dist/index.js +1183 -592
- package/package.json +1 -1
- package/assets/worker-kits/growthub-zernio-social-v1/docs/postiz-ui-shell-integration.md +0 -166
package/dist/index.js
CHANGED
|
@@ -583,7 +583,8 @@ var init_agent = __esm({
|
|
|
583
583
|
});
|
|
584
584
|
adapterConfigSchema = z6.record(z6.unknown()).superRefine((value, ctx) => {
|
|
585
585
|
const envValue = value.env;
|
|
586
|
-
if (envValue === void 0)
|
|
586
|
+
if (envValue === void 0)
|
|
587
|
+
return;
|
|
587
588
|
const parsed = envConfigSchema.safeParse(envValue);
|
|
588
589
|
if (!parsed.success) {
|
|
589
590
|
ctx.addIssue({
|
|
@@ -1171,9 +1172,11 @@ var init_access = __esm({
|
|
|
1171
1172
|
import { z as z18 } from "zod";
|
|
1172
1173
|
function isValidCronExpression(expression) {
|
|
1173
1174
|
const trimmed = expression.trim();
|
|
1174
|
-
if (!trimmed)
|
|
1175
|
+
if (!trimmed)
|
|
1176
|
+
return false;
|
|
1175
1177
|
const fields = trimmed.split(/\s+/);
|
|
1176
|
-
if (fields.length !== 5)
|
|
1178
|
+
if (fields.length !== 5)
|
|
1179
|
+
return false;
|
|
1177
1180
|
return fields.every((f) => CRON_FIELD_PATTERN.test(f));
|
|
1178
1181
|
}
|
|
1179
1182
|
var jsonSchemaSchema, CRON_FIELD_PATTERN, pluginJobDeclarationSchema, pluginWebhookDeclarationSchema, pluginToolDeclarationSchema, pluginUiSlotDeclarationSchema, entityScopedLauncherPlacementZones, launcherBoundsByEnvironment, pluginLauncherActionDeclarationSchema, pluginLauncherRenderDeclarationSchema, pluginLauncherDeclarationSchema, pluginManifestV1Schema, installPluginSchema, upsertPluginConfigSchema, patchPluginConfigSchema, updatePluginStatusSchema, uninstallPluginSchema, pluginStateScopeKeySchema, setPluginStateSchema, listPluginStateSchema;
|
|
@@ -1183,7 +1186,8 @@ var init_plugin = __esm({
|
|
|
1183
1186
|
init_constants();
|
|
1184
1187
|
jsonSchemaSchema = z18.record(z18.unknown()).refine(
|
|
1185
1188
|
(val) => {
|
|
1186
|
-
if (Object.keys(val).length === 0)
|
|
1189
|
+
if (Object.keys(val).length === 0)
|
|
1190
|
+
return true;
|
|
1187
1191
|
return typeof val.type === "string" || val.$ref !== void 0 || val.oneOf !== void 0 || val.anyOf !== void 0 || val.allOf !== void 0;
|
|
1188
1192
|
},
|
|
1189
1193
|
{ message: "Must be a valid JSON Schema object (requires at least a 'type', '$ref', or composition keyword)" }
|
|
@@ -1819,7 +1823,8 @@ function buildSurfaceRuntimeContract(profile = "dx") {
|
|
|
1819
1823
|
});
|
|
1820
1824
|
}
|
|
1821
1825
|
function initializeSurfaceRuntimeContract(profile = "dx") {
|
|
1822
|
-
if (runtimeContract && runtimeContract.profile === profile)
|
|
1826
|
+
if (runtimeContract && runtimeContract.profile === profile)
|
|
1827
|
+
return runtimeContract;
|
|
1823
1828
|
runtimeContract = buildSurfaceRuntimeContract(profile);
|
|
1824
1829
|
return runtimeContract;
|
|
1825
1830
|
}
|
|
@@ -1846,7 +1851,8 @@ function mapGtmKnowledgeKind(sourceType) {
|
|
|
1846
1851
|
return sourceType === "table" ? "table" : "item";
|
|
1847
1852
|
}
|
|
1848
1853
|
function formatConnectorLabel(type) {
|
|
1849
|
-
if (!type?.trim())
|
|
1854
|
+
if (!type?.trim())
|
|
1855
|
+
return "Manual";
|
|
1850
1856
|
return humanizeToken(type);
|
|
1851
1857
|
}
|
|
1852
1858
|
function formatKnowledgeGroupLabel(table) {
|
|
@@ -1903,7 +1909,8 @@ function createDefaultGtmState(now = (/* @__PURE__ */ new Date()).toISOString())
|
|
|
1903
1909
|
}
|
|
1904
1910
|
function coerceGtmState(raw) {
|
|
1905
1911
|
const fallback = createDefaultGtmState();
|
|
1906
|
-
if (!raw || typeof raw !== "object")
|
|
1912
|
+
if (!raw || typeof raw !== "object")
|
|
1913
|
+
return fallback;
|
|
1907
1914
|
const candidate = raw;
|
|
1908
1915
|
const fallbackItemTemplate = fallback.knowledge.table;
|
|
1909
1916
|
const fallbackConnectorTemplate = fallback.connectors[0] ?? {
|
|
@@ -2089,7 +2096,8 @@ import os from "node:os";
|
|
|
2089
2096
|
import path from "node:path";
|
|
2090
2097
|
function resolvePaperclipHomeDir() {
|
|
2091
2098
|
const envHome = process.env.PAPERCLIP_HOME?.trim();
|
|
2092
|
-
if (envHome)
|
|
2099
|
+
if (envHome)
|
|
2100
|
+
return path.resolve(expandHomePrefix(envHome));
|
|
2093
2101
|
return path.resolve(os.homedir(), ".paperclip");
|
|
2094
2102
|
}
|
|
2095
2103
|
function resolvePaperclipInstanceId(override) {
|
|
@@ -2127,8 +2135,10 @@ function resolveDefaultBackupDir(instanceId) {
|
|
|
2127
2135
|
return path.resolve(resolvePaperclipInstanceRoot(instanceId), "data", "backups");
|
|
2128
2136
|
}
|
|
2129
2137
|
function expandHomePrefix(value) {
|
|
2130
|
-
if (value === "~")
|
|
2131
|
-
|
|
2138
|
+
if (value === "~")
|
|
2139
|
+
return os.homedir();
|
|
2140
|
+
if (value.startsWith("~/"))
|
|
2141
|
+
return path.resolve(os.homedir(), value.slice(2));
|
|
2132
2142
|
return value;
|
|
2133
2143
|
}
|
|
2134
2144
|
function describeLocalInstancePaths(instanceId) {
|
|
@@ -2167,14 +2177,17 @@ function findConfigFileFromAncestors(startDir) {
|
|
|
2167
2177
|
return candidate;
|
|
2168
2178
|
}
|
|
2169
2179
|
const nextDir = path2.resolve(currentDir, "..");
|
|
2170
|
-
if (nextDir === currentDir)
|
|
2180
|
+
if (nextDir === currentDir)
|
|
2181
|
+
break;
|
|
2171
2182
|
currentDir = nextDir;
|
|
2172
2183
|
}
|
|
2173
2184
|
return null;
|
|
2174
2185
|
}
|
|
2175
2186
|
function resolveConfigPath(overridePath) {
|
|
2176
|
-
if (overridePath)
|
|
2177
|
-
|
|
2187
|
+
if (overridePath)
|
|
2188
|
+
return path2.resolve(overridePath);
|
|
2189
|
+
if (process.env.PAPERCLIP_CONFIG)
|
|
2190
|
+
return path2.resolve(process.env.PAPERCLIP_CONFIG);
|
|
2178
2191
|
return findConfigFileFromAncestors(process.cwd()) ?? resolveDefaultConfigPath(resolvePaperclipInstanceId());
|
|
2179
2192
|
}
|
|
2180
2193
|
function parseJson(filePath) {
|
|
@@ -2185,7 +2198,8 @@ function parseJson(filePath) {
|
|
|
2185
2198
|
}
|
|
2186
2199
|
}
|
|
2187
2200
|
function migrateLegacyConfig(raw) {
|
|
2188
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
2201
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
2202
|
+
return raw;
|
|
2189
2203
|
const config = { ...raw };
|
|
2190
2204
|
const databaseRaw = config.database;
|
|
2191
2205
|
if (typeof databaseRaw !== "object" || databaseRaw === null || Array.isArray(databaseRaw)) {
|
|
@@ -2218,7 +2232,8 @@ function formatValidationError(err) {
|
|
|
2218
2232
|
}
|
|
2219
2233
|
function readConfig(configPath) {
|
|
2220
2234
|
const filePath = resolveConfigPath(configPath);
|
|
2221
|
-
if (!fs.existsSync(filePath))
|
|
2235
|
+
if (!fs.existsSync(filePath))
|
|
2236
|
+
return null;
|
|
2222
2237
|
const raw = parseJson(filePath);
|
|
2223
2238
|
const migrated = migrateLegacyConfig(raw);
|
|
2224
2239
|
const parsed = paperclipConfigSchema.safeParse(migrated);
|
|
@@ -2296,8 +2311,10 @@ function loadPaperclipEnvFile(configPath) {
|
|
|
2296
2311
|
loadAgentJwtEnvFile(resolveEnvFilePath(configPath));
|
|
2297
2312
|
}
|
|
2298
2313
|
function loadAgentJwtEnvFile(filePath = resolveEnvFilePath()) {
|
|
2299
|
-
if (loadedEnvFiles.has(filePath))
|
|
2300
|
-
|
|
2314
|
+
if (loadedEnvFiles.has(filePath))
|
|
2315
|
+
return;
|
|
2316
|
+
if (!fs2.existsSync(filePath))
|
|
2317
|
+
return;
|
|
2301
2318
|
loadedEnvFiles.add(filePath);
|
|
2302
2319
|
loadDotenv({ path: filePath, override: false, quiet: true });
|
|
2303
2320
|
}
|
|
@@ -2307,7 +2324,8 @@ function readAgentJwtSecretFromEnv(configPath) {
|
|
|
2307
2324
|
return isNonEmpty(raw) ? raw.trim() : null;
|
|
2308
2325
|
}
|
|
2309
2326
|
function readAgentJwtSecretFromEnvFile(filePath = resolveEnvFilePath()) {
|
|
2310
|
-
if (!fs2.existsSync(filePath))
|
|
2327
|
+
if (!fs2.existsSync(filePath))
|
|
2328
|
+
return null;
|
|
2311
2329
|
const raw = fs2.readFileSync(filePath, "utf-8");
|
|
2312
2330
|
const values = parseEnvFile(raw);
|
|
2313
2331
|
const value = values[JWT_SECRET_ENV_KEY];
|
|
@@ -2331,7 +2349,8 @@ function writeAgentJwtEnv(secret, filePath = resolveEnvFilePath()) {
|
|
|
2331
2349
|
mergePaperclipEnvEntries({ [JWT_SECRET_ENV_KEY]: secret }, filePath);
|
|
2332
2350
|
}
|
|
2333
2351
|
function readPaperclipEnvEntries(filePath = resolveEnvFilePath()) {
|
|
2334
|
-
if (!fs2.existsSync(filePath))
|
|
2352
|
+
if (!fs2.existsSync(filePath))
|
|
2353
|
+
return {};
|
|
2335
2354
|
return parseEnvFile(fs2.readFileSync(filePath, "utf-8"));
|
|
2336
2355
|
}
|
|
2337
2356
|
function writePaperclipEnvEntries(entries, filePath = resolveEnvFilePath()) {
|
|
@@ -2370,7 +2389,8 @@ function unique(items) {
|
|
|
2370
2389
|
}
|
|
2371
2390
|
function resolveRuntimeLikePath(value, configPath) {
|
|
2372
2391
|
const expanded = expandHomePrefix(value);
|
|
2373
|
-
if (path4.isAbsolute(expanded))
|
|
2392
|
+
if (path4.isAbsolute(expanded))
|
|
2393
|
+
return path4.resolve(expanded);
|
|
2374
2394
|
const cwd = process.cwd();
|
|
2375
2395
|
const configDir = configPath ? path4.dirname(configPath) : null;
|
|
2376
2396
|
const workspaceRoot = configDir ? path4.resolve(configDir, "..") : cwd;
|
|
@@ -2463,8 +2483,10 @@ async function promptDatabase(current) {
|
|
|
2463
2483
|
defaultValue: base.connectionString ?? "",
|
|
2464
2484
|
placeholder: "postgres://user:pass@localhost:5432/paperclip",
|
|
2465
2485
|
validate: (val) => {
|
|
2466
|
-
if (!val)
|
|
2467
|
-
|
|
2486
|
+
if (!val)
|
|
2487
|
+
return "Connection string is required for PostgreSQL mode";
|
|
2488
|
+
if (!val.startsWith("postgres"))
|
|
2489
|
+
return "Must be a postgres:// or postgresql:// URL";
|
|
2468
2490
|
}
|
|
2469
2491
|
});
|
|
2470
2492
|
if (p.isCancel(value)) {
|
|
@@ -2489,7 +2511,8 @@ async function promptDatabase(current) {
|
|
|
2489
2511
|
placeholder: "54329",
|
|
2490
2512
|
validate: (val) => {
|
|
2491
2513
|
const n = Number(val);
|
|
2492
|
-
if (!Number.isInteger(n) || n < 1 || n > 65535)
|
|
2514
|
+
if (!Number.isInteger(n) || n < 1 || n > 65535)
|
|
2515
|
+
return "Port must be an integer between 1 and 65535";
|
|
2493
2516
|
}
|
|
2494
2517
|
});
|
|
2495
2518
|
if (p.isCancel(portValue)) {
|
|
@@ -2523,8 +2546,10 @@ async function promptDatabase(current) {
|
|
|
2523
2546
|
placeholder: "60",
|
|
2524
2547
|
validate: (val) => {
|
|
2525
2548
|
const n = Number(val);
|
|
2526
|
-
if (!Number.isInteger(n) || n < 1)
|
|
2527
|
-
|
|
2549
|
+
if (!Number.isInteger(n) || n < 1)
|
|
2550
|
+
return "Interval must be a positive integer";
|
|
2551
|
+
if (n > 10080)
|
|
2552
|
+
return "Interval must be 10080 minutes (7 days) or less";
|
|
2528
2553
|
return void 0;
|
|
2529
2554
|
}
|
|
2530
2555
|
});
|
|
@@ -2538,8 +2563,10 @@ async function promptDatabase(current) {
|
|
|
2538
2563
|
placeholder: "30",
|
|
2539
2564
|
validate: (val) => {
|
|
2540
2565
|
const n = Number(val);
|
|
2541
|
-
if (!Number.isInteger(n) || n < 1)
|
|
2542
|
-
|
|
2566
|
+
if (!Number.isInteger(n) || n < 1)
|
|
2567
|
+
return "Retention must be a positive integer";
|
|
2568
|
+
if (n > 3650)
|
|
2569
|
+
return "Retention must be 3650 days or less";
|
|
2543
2570
|
return void 0;
|
|
2544
2571
|
}
|
|
2545
2572
|
});
|
|
@@ -2578,7 +2605,8 @@ async function promptLlm() {
|
|
|
2578
2605
|
p2.cancel("Setup cancelled.");
|
|
2579
2606
|
process.exit(0);
|
|
2580
2607
|
}
|
|
2581
|
-
if (!configureLlm)
|
|
2608
|
+
if (!configureLlm)
|
|
2609
|
+
return void 0;
|
|
2582
2610
|
const provider = await p2.select({
|
|
2583
2611
|
message: "LLM provider",
|
|
2584
2612
|
options: [
|
|
@@ -2593,7 +2621,8 @@ async function promptLlm() {
|
|
|
2593
2621
|
const apiKey = await p2.password({
|
|
2594
2622
|
message: `${provider === "claude" ? "Anthropic" : "OpenAI"} API key`,
|
|
2595
2623
|
validate: (val) => {
|
|
2596
|
-
if (!val)
|
|
2624
|
+
if (!val)
|
|
2625
|
+
return "API key is required";
|
|
2597
2626
|
}
|
|
2598
2627
|
});
|
|
2599
2628
|
if (p2.isCancel(apiKey)) {
|
|
@@ -2708,7 +2737,8 @@ async function promptSecrets(current) {
|
|
|
2708
2737
|
defaultValue: keyFilePath,
|
|
2709
2738
|
placeholder: fallbackDefault,
|
|
2710
2739
|
validate: (value) => {
|
|
2711
|
-
if (!value || value.trim().length === 0)
|
|
2740
|
+
if (!value || value.trim().length === 0)
|
|
2741
|
+
return "Key file path is required";
|
|
2712
2742
|
}
|
|
2713
2743
|
});
|
|
2714
2744
|
if (p4.isCancel(keyPath)) {
|
|
@@ -2786,7 +2816,8 @@ async function promptStorage(current) {
|
|
|
2786
2816
|
defaultValue: base.localDisk.baseDir || defaultStorageBaseDir(),
|
|
2787
2817
|
placeholder: defaultStorageBaseDir(),
|
|
2788
2818
|
validate: (value) => {
|
|
2789
|
-
if (!value || value.trim().length === 0)
|
|
2819
|
+
if (!value || value.trim().length === 0)
|
|
2820
|
+
return "Storage base directory is required";
|
|
2790
2821
|
}
|
|
2791
2822
|
});
|
|
2792
2823
|
if (p5.isCancel(baseDir)) {
|
|
@@ -2806,7 +2837,8 @@ async function promptStorage(current) {
|
|
|
2806
2837
|
defaultValue: base.s3.bucket || "paperclip",
|
|
2807
2838
|
placeholder: "paperclip",
|
|
2808
2839
|
validate: (value) => {
|
|
2809
|
-
if (!value || value.trim().length === 0)
|
|
2840
|
+
if (!value || value.trim().length === 0)
|
|
2841
|
+
return "Bucket is required";
|
|
2810
2842
|
}
|
|
2811
2843
|
});
|
|
2812
2844
|
if (p5.isCancel(bucket)) {
|
|
@@ -2818,7 +2850,8 @@ async function promptStorage(current) {
|
|
|
2818
2850
|
defaultValue: base.s3.region || "us-east-1",
|
|
2819
2851
|
placeholder: "us-east-1",
|
|
2820
2852
|
validate: (value) => {
|
|
2821
|
-
if (!value || value.trim().length === 0)
|
|
2853
|
+
if (!value || value.trim().length === 0)
|
|
2854
|
+
return "Region is required";
|
|
2822
2855
|
}
|
|
2823
2856
|
});
|
|
2824
2857
|
if (p5.isCancel(region)) {
|
|
@@ -2879,14 +2912,16 @@ function normalizeHostnameInput(raw) {
|
|
|
2879
2912
|
try {
|
|
2880
2913
|
const url = input.includes("://") ? new URL(input) : new URL(`http://${input}`);
|
|
2881
2914
|
const hostname = url.hostname.trim().toLowerCase();
|
|
2882
|
-
if (!hostname)
|
|
2915
|
+
if (!hostname)
|
|
2916
|
+
throw new Error("Hostname is required");
|
|
2883
2917
|
return hostname;
|
|
2884
2918
|
} catch {
|
|
2885
2919
|
throw new Error(`Invalid hostname: ${raw}`);
|
|
2886
2920
|
}
|
|
2887
2921
|
}
|
|
2888
2922
|
function parseHostnameCsv(raw) {
|
|
2889
|
-
if (!raw.trim())
|
|
2923
|
+
if (!raw.trim())
|
|
2924
|
+
return [];
|
|
2890
2925
|
const unique3 = /* @__PURE__ */ new Set();
|
|
2891
2926
|
for (const part of raw.split(",")) {
|
|
2892
2927
|
const hostname = normalizeHostnameInput(part);
|
|
@@ -2956,7 +2991,8 @@ async function promptServer(opts) {
|
|
|
2956
2991
|
defaultValue: currentServer?.host ?? hostDefault,
|
|
2957
2992
|
placeholder: hostDefault,
|
|
2958
2993
|
validate: (val) => {
|
|
2959
|
-
if (!val.trim())
|
|
2994
|
+
if (!val.trim())
|
|
2995
|
+
return "Host is required";
|
|
2960
2996
|
}
|
|
2961
2997
|
});
|
|
2962
2998
|
if (p6.isCancel(hostStr)) {
|
|
@@ -3008,7 +3044,8 @@ async function promptServer(opts) {
|
|
|
3008
3044
|
placeholder: "https://paperclip.example.com",
|
|
3009
3045
|
validate: (val) => {
|
|
3010
3046
|
const candidate = val.trim();
|
|
3011
|
-
if (!candidate)
|
|
3047
|
+
if (!candidate)
|
|
3048
|
+
return "Public base URL is required for public exposure";
|
|
3012
3049
|
try {
|
|
3013
3050
|
const url = new URL(candidate);
|
|
3014
3051
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
@@ -5502,7 +5539,8 @@ function isSafeIdentifier(value) {
|
|
|
5502
5539
|
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
|
|
5503
5540
|
}
|
|
5504
5541
|
function quoteIdentifier(value) {
|
|
5505
|
-
if (!isSafeIdentifier(value))
|
|
5542
|
+
if (!isSafeIdentifier(value))
|
|
5543
|
+
throw new Error(`Unsafe SQL identifier: ${value}`);
|
|
5506
5544
|
return `"${value.replaceAll('"', '""')}"`;
|
|
5507
5545
|
}
|
|
5508
5546
|
function quoteLiteral(value) {
|
|
@@ -5537,10 +5575,13 @@ async function listJournalMigrationEntries() {
|
|
|
5537
5575
|
try {
|
|
5538
5576
|
const raw = await readFile(MIGRATIONS_JOURNAL_JSON, "utf8");
|
|
5539
5577
|
const parsed = JSON.parse(raw);
|
|
5540
|
-
if (!Array.isArray(parsed.entries))
|
|
5578
|
+
if (!Array.isArray(parsed.entries))
|
|
5579
|
+
return [];
|
|
5541
5580
|
return parsed.entries.map((entry, entryIndex) => {
|
|
5542
|
-
if (typeof entry?.tag !== "string")
|
|
5543
|
-
|
|
5581
|
+
if (typeof entry?.tag !== "string")
|
|
5582
|
+
return null;
|
|
5583
|
+
if (typeof entry?.when !== "number" || !Number.isFinite(entry.when))
|
|
5584
|
+
return null;
|
|
5544
5585
|
const order = Number.isInteger(entry.idx) ? Number(entry.idx) : entryIndex;
|
|
5545
5586
|
return { fileName: `${entry.tag}.sql`, folderMillis: entry.when, order };
|
|
5546
5587
|
}).filter((entry) => entry !== null);
|
|
@@ -5561,10 +5602,14 @@ async function orderMigrationsByJournal(migrationFiles) {
|
|
|
5561
5602
|
return [...migrationFiles].sort((left, right) => {
|
|
5562
5603
|
const leftOrder = orderByFileName.get(left);
|
|
5563
5604
|
const rightOrder = orderByFileName.get(right);
|
|
5564
|
-
if (leftOrder === void 0 && rightOrder === void 0)
|
|
5565
|
-
|
|
5566
|
-
if (
|
|
5567
|
-
|
|
5605
|
+
if (leftOrder === void 0 && rightOrder === void 0)
|
|
5606
|
+
return left.localeCompare(right);
|
|
5607
|
+
if (leftOrder === void 0)
|
|
5608
|
+
return 1;
|
|
5609
|
+
if (rightOrder === void 0)
|
|
5610
|
+
return -1;
|
|
5611
|
+
if (leftOrder === rightOrder)
|
|
5612
|
+
return left.localeCompare(right);
|
|
5568
5613
|
return leftOrder - rightOrder;
|
|
5569
5614
|
});
|
|
5570
5615
|
}
|
|
@@ -5610,9 +5655,12 @@ async function ensureMigrationJournalTable(sql2) {
|
|
|
5610
5655
|
}
|
|
5611
5656
|
async function migrationHistoryEntryExists(sql2, qualifiedTable, columnNames, migrationFile, hash) {
|
|
5612
5657
|
const predicates = [];
|
|
5613
|
-
if (columnNames.has("hash"))
|
|
5614
|
-
|
|
5615
|
-
if (
|
|
5658
|
+
if (columnNames.has("hash"))
|
|
5659
|
+
predicates.push(`hash = ${quoteLiteral(hash)}`);
|
|
5660
|
+
if (columnNames.has("name"))
|
|
5661
|
+
predicates.push(`name = ${quoteLiteral(migrationFile)}`);
|
|
5662
|
+
if (predicates.length === 0)
|
|
5663
|
+
return false;
|
|
5616
5664
|
const rows = await sql2.unsafe(
|
|
5617
5665
|
`SELECT 1 AS one FROM ${qualifiedTable} WHERE ${predicates.join(" OR ")} LIMIT 1`
|
|
5618
5666
|
);
|
|
@@ -5635,13 +5683,15 @@ async function recordMigrationHistoryEntry(sql2, qualifiedTable, columnNames, mi
|
|
|
5635
5683
|
insertColumns.push(quoteIdentifier("created_at"));
|
|
5636
5684
|
insertValues.push(quoteLiteral(String(createdAt)));
|
|
5637
5685
|
}
|
|
5638
|
-
if (insertColumns.length === 0)
|
|
5686
|
+
if (insertColumns.length === 0)
|
|
5687
|
+
return;
|
|
5639
5688
|
await sql2.unsafe(
|
|
5640
5689
|
`INSERT INTO ${qualifiedTable} (${insertColumns.join(", ")}) VALUES (${insertValues.join(", ")})`
|
|
5641
5690
|
);
|
|
5642
5691
|
}
|
|
5643
5692
|
async function applyPendingMigrationsManually(url, pendingMigrations) {
|
|
5644
|
-
if (pendingMigrations.length === 0)
|
|
5693
|
+
if (pendingMigrations.length === 0)
|
|
5694
|
+
return;
|
|
5645
5695
|
const orderedPendingMigrations = await orderMigrationsByJournal(pendingMigrations);
|
|
5646
5696
|
const journalEntries = await listJournalMigrationEntries();
|
|
5647
5697
|
const folderMillisByFileName = new Map(
|
|
@@ -5661,7 +5711,8 @@ async function applyPendingMigrationsManually(url, pendingMigrations) {
|
|
|
5661
5711
|
migrationFile,
|
|
5662
5712
|
hash
|
|
5663
5713
|
);
|
|
5664
|
-
if (existingEntry)
|
|
5714
|
+
if (existingEntry)
|
|
5715
|
+
continue;
|
|
5665
5716
|
await runInTransaction(sql2, async () => {
|
|
5666
5717
|
for (const statement of splitMigrationStatements(migrationContent)) {
|
|
5667
5718
|
await sql2.unsafe(statement);
|
|
@@ -5774,10 +5825,12 @@ async function migrationStatementAlreadyApplied(sql2, statement) {
|
|
|
5774
5825
|
}
|
|
5775
5826
|
async function migrationContentAlreadyApplied(sql2, migrationContent) {
|
|
5776
5827
|
const statements = splitMigrationStatements(migrationContent);
|
|
5777
|
-
if (statements.length === 0)
|
|
5828
|
+
if (statements.length === 0)
|
|
5829
|
+
return false;
|
|
5778
5830
|
for (const statement of statements) {
|
|
5779
5831
|
const applied = await migrationStatementAlreadyApplied(sql2, statement);
|
|
5780
|
-
if (!applied)
|
|
5832
|
+
if (!applied)
|
|
5833
|
+
return false;
|
|
5781
5834
|
}
|
|
5782
5835
|
return true;
|
|
5783
5836
|
}
|
|
@@ -5794,7 +5847,8 @@ async function loadAppliedMigrations(sql2, migrationTableSchema, availableMigrat
|
|
|
5794
5847
|
const hashesToMigrationFiles = await mapHashesToMigrationFiles(availableMigrations);
|
|
5795
5848
|
const appliedFromHashes = rows2.map((row) => hashesToMigrationFiles.get(row.hash)).filter((name) => Boolean(name));
|
|
5796
5849
|
if (appliedFromHashes.length > 0) {
|
|
5797
|
-
if (appliedFromHashes.length === rows2.length)
|
|
5850
|
+
if (appliedFromHashes.length === rows2.length)
|
|
5851
|
+
return appliedFromHashes;
|
|
5798
5852
|
return appliedFromHashes;
|
|
5799
5853
|
}
|
|
5800
5854
|
if (columnNames.has("created_at")) {
|
|
@@ -5813,7 +5867,8 @@ async function loadAppliedMigrations(sql2, migrationTableSchema, availableMigrat
|
|
|
5813
5867
|
const rows = await sql2.unsafe(`SELECT id FROM ${qualifiedTable} ORDER BY id`);
|
|
5814
5868
|
const journalMigrationFiles = await listJournalMigrationFiles();
|
|
5815
5869
|
const appliedFromIds = rows.map((row) => journalMigrationFiles[row.id - 1]).filter((name) => Boolean(name));
|
|
5816
|
-
if (appliedFromIds.length > 0)
|
|
5870
|
+
if (appliedFromIds.length > 0)
|
|
5871
|
+
return appliedFromIds;
|
|
5817
5872
|
return availableMigrations.slice(0, Math.max(0, rows.length));
|
|
5818
5873
|
}
|
|
5819
5874
|
async function reconcilePendingMigrationHistory(url) {
|
|
@@ -5835,7 +5890,8 @@ async function reconcilePendingMigrationHistory(url) {
|
|
|
5835
5890
|
for (const migrationFile of state.pendingMigrations) {
|
|
5836
5891
|
const migrationContent = await readMigrationFileContent(migrationFile);
|
|
5837
5892
|
const alreadyApplied = await migrationContentAlreadyApplied(sql2, migrationContent);
|
|
5838
|
-
if (!alreadyApplied)
|
|
5893
|
+
if (!alreadyApplied)
|
|
5894
|
+
break;
|
|
5839
5895
|
const hash = createHash("sha256").update(migrationContent).digest("hex");
|
|
5840
5896
|
const folderMillis = folderMillisByFile.get(migrationFile) ?? Date.now();
|
|
5841
5897
|
const existingByHash = columnNames.has("hash") ? await sql2.unsafe(
|
|
@@ -5876,7 +5932,8 @@ async function reconcilePendingMigrationHistory(url) {
|
|
|
5876
5932
|
insertColumns.push(quoteIdentifier("created_at"));
|
|
5877
5933
|
insertValues.push(quoteLiteral(String(folderMillis)));
|
|
5878
5934
|
}
|
|
5879
|
-
if (insertColumns.length === 0)
|
|
5935
|
+
if (insertColumns.length === 0)
|
|
5936
|
+
break;
|
|
5880
5937
|
await sql2.unsafe(
|
|
5881
5938
|
`INSERT INTO ${qualifiedTable} (${insertColumns.join(", ")}) VALUES (${insertValues.join(", ")})`
|
|
5882
5939
|
);
|
|
@@ -5898,11 +5955,14 @@ async function discoverMigrationTableSchema(sql2) {
|
|
|
5898
5955
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
5899
5956
|
WHERE c.relname = ${DRIZZLE_MIGRATIONS_TABLE} AND c.relkind = 'r'
|
|
5900
5957
|
`;
|
|
5901
|
-
if (rows.length === 0)
|
|
5958
|
+
if (rows.length === 0)
|
|
5959
|
+
return null;
|
|
5902
5960
|
const drizzleSchema = rows.find(({ schemaName }) => schemaName === "drizzle");
|
|
5903
|
-
if (drizzleSchema)
|
|
5961
|
+
if (drizzleSchema)
|
|
5962
|
+
return drizzleSchema.schemaName;
|
|
5904
5963
|
const publicSchema = rows.find(({ schemaName }) => schemaName === "public");
|
|
5905
|
-
if (publicSchema)
|
|
5964
|
+
if (publicSchema)
|
|
5965
|
+
return publicSchema.schemaName;
|
|
5906
5966
|
return rows[0]?.schemaName ?? null;
|
|
5907
5967
|
}
|
|
5908
5968
|
async function inspectMigrations(url) {
|
|
@@ -5961,7 +6021,8 @@ async function inspectMigrations(url) {
|
|
|
5961
6021
|
}
|
|
5962
6022
|
async function applyPendingMigrations(url) {
|
|
5963
6023
|
const initialState = await inspectMigrations(url);
|
|
5964
|
-
if (initialState.status === "upToDate")
|
|
6024
|
+
if (initialState.status === "upToDate")
|
|
6025
|
+
return;
|
|
5965
6026
|
if (initialState.reason === "no-migration-journal-empty-db") {
|
|
5966
6027
|
const sql2 = createUtilitySql(url);
|
|
5967
6028
|
try {
|
|
@@ -5971,7 +6032,8 @@ async function applyPendingMigrations(url) {
|
|
|
5971
6032
|
await sql2.end();
|
|
5972
6033
|
}
|
|
5973
6034
|
const bootstrappedState = await inspectMigrations(url);
|
|
5974
|
-
if (bootstrappedState.status === "upToDate")
|
|
6035
|
+
if (bootstrappedState.status === "upToDate")
|
|
6036
|
+
return;
|
|
5975
6037
|
throw new Error(
|
|
5976
6038
|
`Failed to bootstrap migrations: ${bootstrappedState.pendingMigrations.join(", ")}`
|
|
5977
6039
|
);
|
|
@@ -5982,11 +6044,13 @@ async function applyPendingMigrations(url) {
|
|
|
5982
6044
|
);
|
|
5983
6045
|
}
|
|
5984
6046
|
let state = await inspectMigrations(url);
|
|
5985
|
-
if (state.status === "upToDate")
|
|
6047
|
+
if (state.status === "upToDate")
|
|
6048
|
+
return;
|
|
5986
6049
|
const repair = await reconcilePendingMigrationHistory(url);
|
|
5987
6050
|
if (repair.repairedMigrations.length > 0) {
|
|
5988
6051
|
state = await inspectMigrations(url);
|
|
5989
|
-
if (state.status === "upToDate")
|
|
6052
|
+
if (state.status === "upToDate")
|
|
6053
|
+
return;
|
|
5990
6054
|
}
|
|
5991
6055
|
if (state.status !== "needsMigrations" || state.reason !== "pending-migrations") {
|
|
5992
6056
|
throw new Error("Migrations are still pending after migration-history reconciliation; run inspectMigrations for details.");
|
|
@@ -6032,7 +6096,8 @@ async function ensurePostgresDatabase(url, databaseName) {
|
|
|
6032
6096
|
const existing = await sql2`
|
|
6033
6097
|
select 1 as one from pg_database where datname = ${databaseName} limit 1
|
|
6034
6098
|
`;
|
|
6035
|
-
if (existing.length > 0)
|
|
6099
|
+
if (existing.length > 0)
|
|
6100
|
+
return "exists";
|
|
6036
6101
|
await sql2.unsafe(`create database "${databaseName}" encoding 'UTF8' lc_collate 'C' lc_ctype 'C' template template0`);
|
|
6037
6102
|
return "created";
|
|
6038
6103
|
} finally {
|
|
@@ -6071,12 +6136,14 @@ function timestamp56(date2 = /* @__PURE__ */ new Date()) {
|
|
|
6071
6136
|
return `${date2.getFullYear()}${pad(date2.getMonth() + 1)}${pad(date2.getDate())}-${pad(date2.getHours())}${pad(date2.getMinutes())}${pad(date2.getSeconds())}`;
|
|
6072
6137
|
}
|
|
6073
6138
|
function pruneOldBackups(backupDir, retentionDays, filenamePrefix) {
|
|
6074
|
-
if (!existsSync(backupDir))
|
|
6139
|
+
if (!existsSync(backupDir))
|
|
6140
|
+
return 0;
|
|
6075
6141
|
const safeRetention = Math.max(1, Math.trunc(retentionDays));
|
|
6076
6142
|
const cutoff = Date.now() - safeRetention * 24 * 60 * 60 * 1e3;
|
|
6077
6143
|
let pruned = 0;
|
|
6078
6144
|
for (const name of readdirSync(backupDir)) {
|
|
6079
|
-
if (!name.startsWith(`${filenamePrefix}-`) || !name.endsWith(".sql"))
|
|
6145
|
+
if (!name.startsWith(`${filenamePrefix}-`) || !name.endsWith(".sql"))
|
|
6146
|
+
continue;
|
|
6080
6147
|
const fullPath = resolve(backupDir, name);
|
|
6081
6148
|
const stat2 = statSync(fullPath);
|
|
6082
6149
|
if (stat2.mtimeMs < cutoff) {
|
|
@@ -6087,8 +6154,10 @@ function pruneOldBackups(backupDir, retentionDays, filenamePrefix) {
|
|
|
6087
6154
|
return pruned;
|
|
6088
6155
|
}
|
|
6089
6156
|
function formatBackupSize(sizeBytes) {
|
|
6090
|
-
if (sizeBytes < 1024)
|
|
6091
|
-
|
|
6157
|
+
if (sizeBytes < 1024)
|
|
6158
|
+
return `${sizeBytes}B`;
|
|
6159
|
+
if (sizeBytes < 1024 * 1024)
|
|
6160
|
+
return `${(sizeBytes / 1024).toFixed(1)}K`;
|
|
6092
6161
|
return `${(sizeBytes / (1024 * 1024)).toFixed(1)}M`;
|
|
6093
6162
|
}
|
|
6094
6163
|
function formatSqlLiteral(value) {
|
|
@@ -6106,10 +6175,12 @@ function normalizeTableNameSet(values) {
|
|
|
6106
6175
|
}
|
|
6107
6176
|
function normalizeNullifyColumnMap(values) {
|
|
6108
6177
|
const out = /* @__PURE__ */ new Map();
|
|
6109
|
-
if (!values)
|
|
6178
|
+
if (!values)
|
|
6179
|
+
return out;
|
|
6110
6180
|
for (const [tableName, columns] of Object.entries(values)) {
|
|
6111
6181
|
const normalizedTable = tableName.trim();
|
|
6112
|
-
if (normalizedTable.length === 0)
|
|
6182
|
+
if (normalizedTable.length === 0)
|
|
6183
|
+
continue;
|
|
6113
6184
|
const normalizedColumns = new Set(
|
|
6114
6185
|
columns.map((column) => column.trim()).filter((column) => column.length > 0)
|
|
6115
6186
|
);
|
|
@@ -6179,7 +6250,8 @@ async function runDatabaseBackup(opts) {
|
|
|
6179
6250
|
const labels2 = e.labels.map((l) => `'${l.replace(/'/g, "''")}'`).join(", ");
|
|
6180
6251
|
emitStatement(`CREATE TYPE "public"."${e.typname}" AS ENUM (${labels2});`);
|
|
6181
6252
|
}
|
|
6182
|
-
if (enums.length > 0)
|
|
6253
|
+
if (enums.length > 0)
|
|
6254
|
+
emit("");
|
|
6183
6255
|
const allSequences = await sql2`
|
|
6184
6256
|
SELECT
|
|
6185
6257
|
s.sequence_schema,
|
|
@@ -6208,8 +6280,10 @@ async function runDatabaseBackup(opts) {
|
|
|
6208
6280
|
(seq) => !seq.owner_table || includedTableNames.has(tableKey(seq.owner_schema ?? "public", seq.owner_table))
|
|
6209
6281
|
);
|
|
6210
6282
|
const schemas = /* @__PURE__ */ new Set();
|
|
6211
|
-
for (const table of tables)
|
|
6212
|
-
|
|
6283
|
+
for (const table of tables)
|
|
6284
|
+
schemas.add(table.schema_name);
|
|
6285
|
+
for (const seq of sequences)
|
|
6286
|
+
schemas.add(seq.sequence_schema);
|
|
6213
6287
|
const extraSchemas = [...schemas].filter((schemaName) => schemaName !== "public");
|
|
6214
6288
|
if (extraSchemas.length > 0) {
|
|
6215
6289
|
emit("-- Schemas");
|
|
@@ -6255,8 +6329,10 @@ async function runDatabaseBackup(opts) {
|
|
|
6255
6329
|
typeStr = col.data_type;
|
|
6256
6330
|
}
|
|
6257
6331
|
let def = ` "${col.column_name}" ${typeStr}`;
|
|
6258
|
-
if (col.column_default != null)
|
|
6259
|
-
|
|
6332
|
+
if (col.column_default != null)
|
|
6333
|
+
def += ` DEFAULT ${col.column_default}`;
|
|
6334
|
+
if (col.is_nullable === "NO")
|
|
6335
|
+
def += " NOT NULL";
|
|
6260
6336
|
colDefs.push(def);
|
|
6261
6337
|
}
|
|
6262
6338
|
const pk = await sql2`
|
|
@@ -6378,7 +6454,8 @@ async function runDatabaseBackup(opts) {
|
|
|
6378
6454
|
for (const { schema_name, tablename } of tables) {
|
|
6379
6455
|
const qualifiedTableName = quoteQualifiedName(schema_name, tablename);
|
|
6380
6456
|
const count = await sql2.unsafe(`SELECT count(*)::int AS n FROM ${qualifiedTableName}`);
|
|
6381
|
-
if (excludedTableNames.has(tablename) || (count[0]?.n ?? 0) === 0)
|
|
6457
|
+
if (excludedTableNames.has(tablename) || (count[0]?.n ?? 0) === 0)
|
|
6458
|
+
continue;
|
|
6382
6459
|
const cols = await sql2`
|
|
6383
6460
|
SELECT column_name, data_type
|
|
6384
6461
|
FROM information_schema.columns
|
|
@@ -6393,11 +6470,16 @@ async function runDatabaseBackup(opts) {
|
|
|
6393
6470
|
const values = row.map((rawValue, index51) => {
|
|
6394
6471
|
const columnName = cols[index51]?.column_name;
|
|
6395
6472
|
const val = columnName && nullifiedColumns.has(columnName) ? null : rawValue;
|
|
6396
|
-
if (val === null || val === void 0)
|
|
6397
|
-
|
|
6398
|
-
if (typeof val === "
|
|
6399
|
-
|
|
6400
|
-
if (typeof val === "
|
|
6473
|
+
if (val === null || val === void 0)
|
|
6474
|
+
return "NULL";
|
|
6475
|
+
if (typeof val === "boolean")
|
|
6476
|
+
return val ? "true" : "false";
|
|
6477
|
+
if (typeof val === "number")
|
|
6478
|
+
return String(val);
|
|
6479
|
+
if (val instanceof Date)
|
|
6480
|
+
return formatSqlLiteral(val.toISOString());
|
|
6481
|
+
if (typeof val === "object")
|
|
6482
|
+
return formatSqlLiteral(JSON.stringify(val));
|
|
6401
6483
|
return formatSqlLiteral(String(val));
|
|
6402
6484
|
});
|
|
6403
6485
|
emitStatement(`INSERT INTO ${qualifiedTableName} (${colNames}) VALUES (${values.join(", ")});`);
|
|
@@ -6562,9 +6644,11 @@ function createInviteToken() {
|
|
|
6562
6644
|
return `pcp_bootstrap_${randomBytes3(24).toString("hex")}`;
|
|
6563
6645
|
}
|
|
6564
6646
|
function resolveDbUrl(configPath, explicitDbUrl) {
|
|
6565
|
-
if (explicitDbUrl)
|
|
6647
|
+
if (explicitDbUrl)
|
|
6648
|
+
return explicitDbUrl;
|
|
6566
6649
|
const config = readConfig(configPath);
|
|
6567
|
-
if (process.env.DATABASE_URL)
|
|
6650
|
+
if (process.env.DATABASE_URL)
|
|
6651
|
+
return process.env.DATABASE_URL;
|
|
6568
6652
|
if (config?.database.mode === "postgres" && config.database.connectionString) {
|
|
6569
6653
|
return config.database.connectionString;
|
|
6570
6654
|
}
|
|
@@ -6575,9 +6659,11 @@ function resolveDbUrl(configPath, explicitDbUrl) {
|
|
|
6575
6659
|
return null;
|
|
6576
6660
|
}
|
|
6577
6661
|
function resolveBaseUrl(configPath, explicitBaseUrl) {
|
|
6578
|
-
if (explicitBaseUrl)
|
|
6662
|
+
if (explicitBaseUrl)
|
|
6663
|
+
return explicitBaseUrl.replace(/\/+$/, "");
|
|
6579
6664
|
const fromEnv = process.env.PAPERCLIP_PUBLIC_URL ?? process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL ?? process.env.BETTER_AUTH_URL ?? process.env.BETTER_AUTH_BASE_URL;
|
|
6580
|
-
if (fromEnv?.trim())
|
|
6665
|
+
if (fromEnv?.trim())
|
|
6666
|
+
return fromEnv.trim().replace(/\/+$/, "");
|
|
6581
6667
|
const config = readConfig(configPath);
|
|
6582
6668
|
if (config?.auth.baseUrlMode === "explicit" && config.auth.publicBaseUrl) {
|
|
6583
6669
|
return config.auth.publicBaseUrl.replace(/\/+$/, "");
|
|
@@ -7080,13 +7166,15 @@ import fs7 from "node:fs";
|
|
|
7080
7166
|
import path6 from "node:path";
|
|
7081
7167
|
function decodeMasterKey(raw) {
|
|
7082
7168
|
const trimmed = raw.trim();
|
|
7083
|
-
if (!trimmed)
|
|
7169
|
+
if (!trimmed)
|
|
7170
|
+
return null;
|
|
7084
7171
|
if (/^[A-Fa-f0-9]{64}$/.test(trimmed)) {
|
|
7085
7172
|
return Buffer.from(trimmed, "hex");
|
|
7086
7173
|
}
|
|
7087
7174
|
try {
|
|
7088
7175
|
const decoded = Buffer.from(trimmed, "base64");
|
|
7089
|
-
if (decoded.length === 32)
|
|
7176
|
+
if (decoded.length === 32)
|
|
7177
|
+
return decoded;
|
|
7090
7178
|
} catch {
|
|
7091
7179
|
}
|
|
7092
7180
|
if (Buffer.byteLength(trimmed, "utf8") === 32) {
|
|
@@ -7096,8 +7184,10 @@ function decodeMasterKey(raw) {
|
|
|
7096
7184
|
}
|
|
7097
7185
|
function withStrictModeNote(base, config) {
|
|
7098
7186
|
const strictModeDisabledInDeployedSetup = config.database.mode === "postgres" && config.secrets.strictMode === false;
|
|
7099
|
-
if (!strictModeDisabledInDeployedSetup)
|
|
7100
|
-
|
|
7187
|
+
if (!strictModeDisabledInDeployedSetup)
|
|
7188
|
+
return base;
|
|
7189
|
+
if (base.status === "fail")
|
|
7190
|
+
return base;
|
|
7101
7191
|
return {
|
|
7102
7192
|
...base,
|
|
7103
7193
|
status: "warn",
|
|
@@ -7350,15 +7440,18 @@ function printResult(result) {
|
|
|
7350
7440
|
}
|
|
7351
7441
|
}
|
|
7352
7442
|
async function maybeRepair(result, opts) {
|
|
7353
|
-
if (result.status === "pass" || !result.canRepair || !result.repair)
|
|
7354
|
-
|
|
7443
|
+
if (result.status === "pass" || !result.canRepair || !result.repair)
|
|
7444
|
+
return false;
|
|
7445
|
+
if (!opts.repair)
|
|
7446
|
+
return false;
|
|
7355
7447
|
let shouldRepair = opts.yes;
|
|
7356
7448
|
if (!shouldRepair) {
|
|
7357
7449
|
const answer = await p8.confirm({
|
|
7358
7450
|
message: `Repair "${result.name}"?`,
|
|
7359
7451
|
initialValue: true
|
|
7360
7452
|
});
|
|
7361
|
-
if (p8.isCancel(answer))
|
|
7453
|
+
if (p8.isCancel(answer))
|
|
7454
|
+
return false;
|
|
7362
7455
|
shouldRepair = answer;
|
|
7363
7456
|
}
|
|
7364
7457
|
if (shouldRepair) {
|
|
@@ -7376,7 +7469,8 @@ async function runRepairableCheck(input) {
|
|
|
7376
7469
|
let result = await input.run();
|
|
7377
7470
|
printResult(result);
|
|
7378
7471
|
const repaired = await maybeRepair(result, input.opts);
|
|
7379
|
-
if (!repaired)
|
|
7472
|
+
if (!repaired)
|
|
7473
|
+
return result;
|
|
7380
7474
|
loadPaperclipEnvFile(input.configPath);
|
|
7381
7475
|
result = await input.run();
|
|
7382
7476
|
printResult(result);
|
|
@@ -7388,8 +7482,10 @@ function printSummary(results) {
|
|
|
7388
7482
|
const failed = results.filter((r) => r.status === "fail").length;
|
|
7389
7483
|
const parts = [];
|
|
7390
7484
|
parts.push(pc3.green(`${passed} passed`));
|
|
7391
|
-
if (warned)
|
|
7392
|
-
|
|
7485
|
+
if (warned)
|
|
7486
|
+
parts.push(pc3.yellow(`${warned} warnings`));
|
|
7487
|
+
if (failed)
|
|
7488
|
+
parts.push(pc3.red(`${failed} failed`));
|
|
7393
7489
|
p8.note(parts.join(", "), "Summary");
|
|
7394
7490
|
if (failed > 0) {
|
|
7395
7491
|
p8.outro(pc3.red("Some checks failed. Fix the issues above and re-run doctor."));
|
|
@@ -7484,10 +7580,12 @@ function resolveBootstrapInviteBaseUrl(config, startedServer) {
|
|
|
7484
7580
|
}
|
|
7485
7581
|
function formatError(err) {
|
|
7486
7582
|
if (err instanceof Error) {
|
|
7487
|
-
if (err.message && err.message.trim().length > 0)
|
|
7583
|
+
if (err.message && err.message.trim().length > 0)
|
|
7584
|
+
return err.message;
|
|
7488
7585
|
return err.name;
|
|
7489
7586
|
}
|
|
7490
|
-
if (typeof err === "string")
|
|
7587
|
+
if (typeof err === "string")
|
|
7588
|
+
return err;
|
|
7491
7589
|
try {
|
|
7492
7590
|
return JSON.stringify(err);
|
|
7493
7591
|
} catch {
|
|
@@ -7495,21 +7593,27 @@ function formatError(err) {
|
|
|
7495
7593
|
}
|
|
7496
7594
|
}
|
|
7497
7595
|
function isModuleNotFoundError(err) {
|
|
7498
|
-
if (!(err instanceof Error))
|
|
7596
|
+
if (!(err instanceof Error))
|
|
7597
|
+
return false;
|
|
7499
7598
|
const code = err.code;
|
|
7500
|
-
if (code === "ERR_MODULE_NOT_FOUND")
|
|
7599
|
+
if (code === "ERR_MODULE_NOT_FOUND")
|
|
7600
|
+
return true;
|
|
7501
7601
|
return err.message.includes("Cannot find module");
|
|
7502
7602
|
}
|
|
7503
7603
|
function getMissingModuleSpecifier(err) {
|
|
7504
|
-
if (!(err instanceof Error))
|
|
7604
|
+
if (!(err instanceof Error))
|
|
7605
|
+
return null;
|
|
7505
7606
|
const packageMatch = err.message.match(/Cannot find package '([^']+)' imported from/);
|
|
7506
|
-
if (packageMatch?.[1])
|
|
7607
|
+
if (packageMatch?.[1])
|
|
7608
|
+
return packageMatch[1];
|
|
7507
7609
|
const moduleMatch = err.message.match(/Cannot find module '([^']+)'/);
|
|
7508
|
-
if (moduleMatch?.[1])
|
|
7610
|
+
if (moduleMatch?.[1])
|
|
7611
|
+
return moduleMatch[1];
|
|
7509
7612
|
return null;
|
|
7510
7613
|
}
|
|
7511
7614
|
function maybeEnableUiDevMiddleware(entrypoint) {
|
|
7512
|
-
if (process.env.PAPERCLIP_UI_DEV_MIDDLEWARE !== void 0)
|
|
7615
|
+
if (process.env.PAPERCLIP_UI_DEV_MIDDLEWARE !== void 0)
|
|
7616
|
+
return;
|
|
7513
7617
|
const normalized = entrypoint.replaceAll("\\", "/");
|
|
7514
7618
|
if (normalized.endsWith("/server/src/index.ts") || normalized.endsWith("@paperclipai/server/src/index.ts")) {
|
|
7515
7619
|
process.env.PAPERCLIP_UI_DEV_MIDDLEWARE = "true";
|
|
@@ -7578,24 +7682,31 @@ import * as p10 from "@clack/prompts";
|
|
|
7578
7682
|
import path8 from "node:path";
|
|
7579
7683
|
import pc5 from "picocolors";
|
|
7580
7684
|
function parseBooleanFromEnv(rawValue) {
|
|
7581
|
-
if (rawValue === void 0)
|
|
7685
|
+
if (rawValue === void 0)
|
|
7686
|
+
return null;
|
|
7582
7687
|
const lower = rawValue.trim().toLowerCase();
|
|
7583
|
-
if (lower === "true" || lower === "1" || lower === "yes")
|
|
7584
|
-
|
|
7688
|
+
if (lower === "true" || lower === "1" || lower === "yes")
|
|
7689
|
+
return true;
|
|
7690
|
+
if (lower === "false" || lower === "0" || lower === "no")
|
|
7691
|
+
return false;
|
|
7585
7692
|
return null;
|
|
7586
7693
|
}
|
|
7587
7694
|
function parseNumberFromEnv(rawValue) {
|
|
7588
|
-
if (!rawValue)
|
|
7695
|
+
if (!rawValue)
|
|
7696
|
+
return null;
|
|
7589
7697
|
const parsed = Number(rawValue);
|
|
7590
|
-
if (!Number.isFinite(parsed))
|
|
7698
|
+
if (!Number.isFinite(parsed))
|
|
7699
|
+
return null;
|
|
7591
7700
|
return parsed;
|
|
7592
7701
|
}
|
|
7593
7702
|
function parseEnumFromEnv(rawValue, allowedValues) {
|
|
7594
|
-
if (!rawValue)
|
|
7703
|
+
if (!rawValue)
|
|
7704
|
+
return null;
|
|
7595
7705
|
return allowedValues.includes(rawValue) ? rawValue : null;
|
|
7596
7706
|
}
|
|
7597
7707
|
function resolvePathFromEnv(rawValue) {
|
|
7598
|
-
if (!rawValue || rawValue.trim().length === 0)
|
|
7708
|
+
if (!rawValue || rawValue.trim().length === 0)
|
|
7709
|
+
return null;
|
|
7599
7710
|
return path8.resolve(expandHomePrefix(rawValue.trim()));
|
|
7600
7711
|
}
|
|
7601
7712
|
function quickstartDefaultsFromEnv() {
|
|
@@ -8063,7 +8174,8 @@ async function envCommand(opts) {
|
|
|
8063
8174
|
const requiredRows = sortedRows.filter((row) => row.required);
|
|
8064
8175
|
const optionalRows = sortedRows.filter((row) => !row.required);
|
|
8065
8176
|
const formatSection = (title, entries) => {
|
|
8066
|
-
if (entries.length === 0)
|
|
8177
|
+
if (entries.length === 0)
|
|
8178
|
+
return;
|
|
8067
8179
|
p11.log.message(pc6.bold(title));
|
|
8068
8180
|
for (const entry of entries) {
|
|
8069
8181
|
const status = entry.source === "missing" ? pc6.red("missing") : entry.source === "default" ? pc6.yellow("default") : pc6.green("set");
|
|
@@ -8290,14 +8402,16 @@ function uniqueByKey(rows) {
|
|
|
8290
8402
|
const seen = /* @__PURE__ */ new Set();
|
|
8291
8403
|
const result = [];
|
|
8292
8404
|
for (const row of rows) {
|
|
8293
|
-
if (seen.has(row.key))
|
|
8405
|
+
if (seen.has(row.key))
|
|
8406
|
+
continue;
|
|
8294
8407
|
seen.add(row.key);
|
|
8295
8408
|
result.push(row);
|
|
8296
8409
|
}
|
|
8297
8410
|
return result;
|
|
8298
8411
|
}
|
|
8299
8412
|
function quoteShellValue(value) {
|
|
8300
|
-
if (value === "")
|
|
8413
|
+
if (value === "")
|
|
8414
|
+
return '""';
|
|
8301
8415
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
8302
8416
|
}
|
|
8303
8417
|
|
|
@@ -8510,11 +8624,14 @@ import pc18 from "picocolors";
|
|
|
8510
8624
|
// ../packages/adapters/claude-local/src/cli/format-event.ts
|
|
8511
8625
|
import pc9 from "picocolors";
|
|
8512
8626
|
function asErrorText(value) {
|
|
8513
|
-
if (typeof value === "string")
|
|
8514
|
-
|
|
8627
|
+
if (typeof value === "string")
|
|
8628
|
+
return value;
|
|
8629
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
8630
|
+
return "";
|
|
8515
8631
|
const obj = value;
|
|
8516
8632
|
const message = typeof obj.message === "string" && obj.message || typeof obj.error === "string" && obj.error || typeof obj.code === "string" && obj.code || "";
|
|
8517
|
-
if (message)
|
|
8633
|
+
if (message)
|
|
8634
|
+
return message;
|
|
8518
8635
|
try {
|
|
8519
8636
|
return JSON.stringify(obj);
|
|
8520
8637
|
} catch {
|
|
@@ -8523,7 +8640,8 @@ function asErrorText(value) {
|
|
|
8523
8640
|
}
|
|
8524
8641
|
function printClaudeStreamEvent(raw, debug) {
|
|
8525
8642
|
const line = raw.trim();
|
|
8526
|
-
if (!line)
|
|
8643
|
+
if (!line)
|
|
8644
|
+
return;
|
|
8527
8645
|
let parsed = null;
|
|
8528
8646
|
try {
|
|
8529
8647
|
parsed = JSON.parse(line);
|
|
@@ -8542,12 +8660,14 @@ function printClaudeStreamEvent(raw, debug) {
|
|
|
8542
8660
|
const message = typeof parsed.message === "object" && parsed.message !== null && !Array.isArray(parsed.message) ? parsed.message : {};
|
|
8543
8661
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
8544
8662
|
for (const blockRaw of content) {
|
|
8545
|
-
if (typeof blockRaw !== "object" || blockRaw === null || Array.isArray(blockRaw))
|
|
8663
|
+
if (typeof blockRaw !== "object" || blockRaw === null || Array.isArray(blockRaw))
|
|
8664
|
+
continue;
|
|
8546
8665
|
const block = blockRaw;
|
|
8547
8666
|
const blockType = typeof block.type === "string" ? block.type : "";
|
|
8548
8667
|
if (blockType === "text") {
|
|
8549
8668
|
const text63 = typeof block.text === "string" ? block.text : "";
|
|
8550
|
-
if (text63)
|
|
8669
|
+
if (text63)
|
|
8670
|
+
console.log(pc9.green(`assistant: ${text63}`));
|
|
8551
8671
|
} else if (blockType === "tool_use") {
|
|
8552
8672
|
const name = typeof block.name === "string" ? block.name : "unknown";
|
|
8553
8673
|
console.log(pc9.yellow(`tool_call: ${name}`));
|
|
@@ -8593,7 +8713,8 @@ function printClaudeStreamEvent(raw, debug) {
|
|
|
8593
8713
|
// ../packages/adapters/codex-local/src/cli/format-event.ts
|
|
8594
8714
|
import pc10 from "picocolors";
|
|
8595
8715
|
function asRecord(value) {
|
|
8596
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
8716
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
8717
|
+
return null;
|
|
8597
8718
|
return value;
|
|
8598
8719
|
}
|
|
8599
8720
|
function asString(value, fallback = "") {
|
|
@@ -8603,11 +8724,14 @@ function asNumber(value, fallback = 0) {
|
|
|
8603
8724
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
8604
8725
|
}
|
|
8605
8726
|
function errorText(value) {
|
|
8606
|
-
if (typeof value === "string")
|
|
8727
|
+
if (typeof value === "string")
|
|
8728
|
+
return value;
|
|
8607
8729
|
const rec = asRecord(value);
|
|
8608
|
-
if (!rec)
|
|
8730
|
+
if (!rec)
|
|
8731
|
+
return "";
|
|
8609
8732
|
const msg = typeof rec.message === "string" && rec.message || typeof rec.error === "string" && rec.error || typeof rec.code === "string" && rec.code || "";
|
|
8610
|
-
if (msg)
|
|
8733
|
+
if (msg)
|
|
8734
|
+
return msg;
|
|
8611
8735
|
try {
|
|
8612
8736
|
return JSON.stringify(rec);
|
|
8613
8737
|
} catch {
|
|
@@ -8619,7 +8743,8 @@ function printItemStarted(item) {
|
|
|
8619
8743
|
if (itemType === "command_execution") {
|
|
8620
8744
|
const command = asString(item.command);
|
|
8621
8745
|
console.log(pc10.yellow("tool_call: command_execution"));
|
|
8622
|
-
if (command)
|
|
8746
|
+
if (command)
|
|
8747
|
+
console.log(pc10.gray(command));
|
|
8623
8748
|
return true;
|
|
8624
8749
|
}
|
|
8625
8750
|
if (itemType === "tool_use") {
|
|
@@ -8640,12 +8765,14 @@ function printItemCompleted(item) {
|
|
|
8640
8765
|
const itemType = asString(item.type);
|
|
8641
8766
|
if (itemType === "agent_message") {
|
|
8642
8767
|
const text63 = asString(item.text);
|
|
8643
|
-
if (text63)
|
|
8768
|
+
if (text63)
|
|
8769
|
+
console.log(pc10.green(`assistant: ${text63}`));
|
|
8644
8770
|
return true;
|
|
8645
8771
|
}
|
|
8646
8772
|
if (itemType === "reasoning") {
|
|
8647
8773
|
const text63 = asString(item.text);
|
|
8648
|
-
if (text63)
|
|
8774
|
+
if (text63)
|
|
8775
|
+
console.log(pc10.gray(`thinking: ${text63}`));
|
|
8649
8776
|
return true;
|
|
8650
8777
|
}
|
|
8651
8778
|
if (itemType === "tool_use") {
|
|
@@ -8673,7 +8800,8 @@ function printItemCompleted(item) {
|
|
|
8673
8800
|
exitCode !== null ? `exit_code=${exitCode}` : ""
|
|
8674
8801
|
].filter(Boolean);
|
|
8675
8802
|
console.log((isError ? pc10.red : pc10.cyan)(summaryParts.join(" ")));
|
|
8676
|
-
if (output)
|
|
8803
|
+
if (output)
|
|
8804
|
+
console.log((isError ? pc10.red : pc10.gray)(output));
|
|
8677
8805
|
return true;
|
|
8678
8806
|
}
|
|
8679
8807
|
if (itemType === "file_change") {
|
|
@@ -8690,21 +8818,24 @@ function printItemCompleted(item) {
|
|
|
8690
8818
|
}
|
|
8691
8819
|
if (itemType === "error") {
|
|
8692
8820
|
const message = errorText(item.message ?? item.error ?? item);
|
|
8693
|
-
if (message)
|
|
8821
|
+
if (message)
|
|
8822
|
+
console.log(pc10.red(`error: ${message}`));
|
|
8694
8823
|
return true;
|
|
8695
8824
|
}
|
|
8696
8825
|
if (itemType === "tool_result") {
|
|
8697
8826
|
const isError = item.is_error === true || asString(item.status) === "error";
|
|
8698
8827
|
const text63 = asString(item.content) || asString(item.result) || asString(item.output);
|
|
8699
8828
|
console.log((isError ? pc10.red : pc10.cyan)(`tool_result${isError ? " (error)" : ""}`));
|
|
8700
|
-
if (text63)
|
|
8829
|
+
if (text63)
|
|
8830
|
+
console.log((isError ? pc10.red : pc10.gray)(text63));
|
|
8701
8831
|
return true;
|
|
8702
8832
|
}
|
|
8703
8833
|
return false;
|
|
8704
8834
|
}
|
|
8705
8835
|
function printCodexStreamEvent(raw, _debug) {
|
|
8706
8836
|
const line = raw.trim();
|
|
8707
|
-
if (!line)
|
|
8837
|
+
if (!line)
|
|
8838
|
+
return;
|
|
8708
8839
|
let parsed = null;
|
|
8709
8840
|
try {
|
|
8710
8841
|
parsed = JSON.parse(line);
|
|
@@ -8756,7 +8887,8 @@ function printCodexStreamEvent(raw, _debug) {
|
|
|
8756
8887
|
console.log(
|
|
8757
8888
|
pc10.red(`result: subtype=${subtype || "unknown"} is_error=${isError ? "true" : "false"}`)
|
|
8758
8889
|
);
|
|
8759
|
-
if (errors.length > 0)
|
|
8890
|
+
if (errors.length > 0)
|
|
8891
|
+
console.log(pc10.red(`errors: ${errors.join(" | ")}`));
|
|
8760
8892
|
}
|
|
8761
8893
|
return;
|
|
8762
8894
|
}
|
|
@@ -8772,7 +8904,8 @@ function printCodexStreamEvent(raw, _debug) {
|
|
|
8772
8904
|
}
|
|
8773
8905
|
if (type === "error") {
|
|
8774
8906
|
const message = errorText(parsed.message ?? parsed.error ?? parsed);
|
|
8775
|
-
if (message)
|
|
8907
|
+
if (message)
|
|
8908
|
+
console.log(pc10.red(`error: ${message}`));
|
|
8776
8909
|
return;
|
|
8777
8910
|
}
|
|
8778
8911
|
console.log(line);
|
|
@@ -8784,7 +8917,8 @@ import pc11 from "picocolors";
|
|
|
8784
8917
|
// ../packages/adapters/cursor-local/src/shared/stream.ts
|
|
8785
8918
|
function normalizeCursorStreamLine(rawLine) {
|
|
8786
8919
|
const trimmed = rawLine.trim();
|
|
8787
|
-
if (!trimmed)
|
|
8920
|
+
if (!trimmed)
|
|
8921
|
+
return { stream: null, line: "" };
|
|
8788
8922
|
const prefixed = trimmed.match(/^(stdout|stderr)\s*[:=]?\s*([\[{].*)$/i);
|
|
8789
8923
|
if (!prefixed) {
|
|
8790
8924
|
return { stream: null, line: trimmed };
|
|
@@ -8796,7 +8930,8 @@ function normalizeCursorStreamLine(rawLine) {
|
|
|
8796
8930
|
|
|
8797
8931
|
// ../packages/adapters/cursor-local/src/cli/format-event.ts
|
|
8798
8932
|
function asRecord2(value) {
|
|
8799
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
8933
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
8934
|
+
return null;
|
|
8800
8935
|
return value;
|
|
8801
8936
|
}
|
|
8802
8937
|
function asString2(value, fallback = "") {
|
|
@@ -8806,8 +8941,10 @@ function asNumber2(value, fallback = 0) {
|
|
|
8806
8941
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
8807
8942
|
}
|
|
8808
8943
|
function stringifyUnknown(value) {
|
|
8809
|
-
if (typeof value === "string")
|
|
8810
|
-
|
|
8944
|
+
if (typeof value === "string")
|
|
8945
|
+
return value;
|
|
8946
|
+
if (value === null || value === void 0)
|
|
8947
|
+
return "";
|
|
8811
8948
|
try {
|
|
8812
8949
|
return JSON.stringify(value, null, 2);
|
|
8813
8950
|
} catch {
|
|
@@ -8817,46 +8954,58 @@ function stringifyUnknown(value) {
|
|
|
8817
8954
|
function printUserMessage(messageRaw) {
|
|
8818
8955
|
if (typeof messageRaw === "string") {
|
|
8819
8956
|
const text63 = messageRaw.trim();
|
|
8820
|
-
if (text63)
|
|
8957
|
+
if (text63)
|
|
8958
|
+
console.log(pc11.gray(`user: ${text63}`));
|
|
8821
8959
|
return;
|
|
8822
8960
|
}
|
|
8823
8961
|
const message = asRecord2(messageRaw);
|
|
8824
|
-
if (!message)
|
|
8962
|
+
if (!message)
|
|
8963
|
+
return;
|
|
8825
8964
|
const directText = asString2(message.text).trim();
|
|
8826
|
-
if (directText)
|
|
8965
|
+
if (directText)
|
|
8966
|
+
console.log(pc11.gray(`user: ${directText}`));
|
|
8827
8967
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
8828
8968
|
for (const partRaw of content) {
|
|
8829
8969
|
const part = asRecord2(partRaw);
|
|
8830
|
-
if (!part)
|
|
8970
|
+
if (!part)
|
|
8971
|
+
continue;
|
|
8831
8972
|
const type = asString2(part.type).trim();
|
|
8832
|
-
if (type !== "output_text" && type !== "text")
|
|
8973
|
+
if (type !== "output_text" && type !== "text")
|
|
8974
|
+
continue;
|
|
8833
8975
|
const text63 = asString2(part.text).trim();
|
|
8834
|
-
if (text63)
|
|
8976
|
+
if (text63)
|
|
8977
|
+
console.log(pc11.gray(`user: ${text63}`));
|
|
8835
8978
|
}
|
|
8836
8979
|
}
|
|
8837
8980
|
function printAssistantMessage(messageRaw) {
|
|
8838
8981
|
if (typeof messageRaw === "string") {
|
|
8839
8982
|
const text63 = messageRaw.trim();
|
|
8840
|
-
if (text63)
|
|
8983
|
+
if (text63)
|
|
8984
|
+
console.log(pc11.green(`assistant: ${text63}`));
|
|
8841
8985
|
return;
|
|
8842
8986
|
}
|
|
8843
8987
|
const message = asRecord2(messageRaw);
|
|
8844
|
-
if (!message)
|
|
8988
|
+
if (!message)
|
|
8989
|
+
return;
|
|
8845
8990
|
const directText = asString2(message.text).trim();
|
|
8846
|
-
if (directText)
|
|
8991
|
+
if (directText)
|
|
8992
|
+
console.log(pc11.green(`assistant: ${directText}`));
|
|
8847
8993
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
8848
8994
|
for (const partRaw of content) {
|
|
8849
8995
|
const part = asRecord2(partRaw);
|
|
8850
|
-
if (!part)
|
|
8996
|
+
if (!part)
|
|
8997
|
+
continue;
|
|
8851
8998
|
const type = asString2(part.type).trim();
|
|
8852
8999
|
if (type === "output_text" || type === "text") {
|
|
8853
9000
|
const text63 = asString2(part.text).trim();
|
|
8854
|
-
if (text63)
|
|
9001
|
+
if (text63)
|
|
9002
|
+
console.log(pc11.green(`assistant: ${text63}`));
|
|
8855
9003
|
continue;
|
|
8856
9004
|
}
|
|
8857
9005
|
if (type === "thinking") {
|
|
8858
9006
|
const text63 = asString2(part.text).trim();
|
|
8859
|
-
if (text63)
|
|
9007
|
+
if (text63)
|
|
9008
|
+
console.log(pc11.gray(`thinking: ${text63}`));
|
|
8860
9009
|
continue;
|
|
8861
9010
|
}
|
|
8862
9011
|
if (type === "tool_call") {
|
|
@@ -8876,7 +9025,8 @@ function printAssistantMessage(messageRaw) {
|
|
|
8876
9025
|
const isError = part.is_error === true || asString2(part.status).toLowerCase() === "error";
|
|
8877
9026
|
const contentText = asString2(part.output) || asString2(part.text) || asString2(part.result) || stringifyUnknown(part.output ?? part.result ?? part.text ?? part);
|
|
8878
9027
|
console.log((isError ? pc11.red : pc11.cyan)(`tool_result${isError ? " (error)" : ""}`));
|
|
8879
|
-
if (contentText)
|
|
9028
|
+
if (contentText)
|
|
9029
|
+
console.log((isError ? pc11.red : pc11.gray)(contentText));
|
|
8880
9030
|
}
|
|
8881
9031
|
}
|
|
8882
9032
|
}
|
|
@@ -8946,7 +9096,8 @@ function printLegacyToolEvent(part) {
|
|
|
8946
9096
|
}
|
|
8947
9097
|
function printCursorStreamEvent(raw, _debug) {
|
|
8948
9098
|
const line = normalizeCursorStreamLine(raw).line;
|
|
8949
|
-
if (!line)
|
|
9099
|
+
if (!line)
|
|
9100
|
+
return;
|
|
8950
9101
|
let parsed = null;
|
|
8951
9102
|
try {
|
|
8952
9103
|
parsed = JSON.parse(line);
|
|
@@ -8977,7 +9128,8 @@ function printCursorStreamEvent(raw, _debug) {
|
|
|
8977
9128
|
}
|
|
8978
9129
|
if (type === "thinking") {
|
|
8979
9130
|
const text63 = asString2(parsed.text).trim() || asString2(asRecord2(parsed.delta)?.text).trim();
|
|
8980
|
-
if (text63)
|
|
9131
|
+
if (text63)
|
|
9132
|
+
console.log(pc11.gray(`thinking: ${text63}`));
|
|
8981
9133
|
return;
|
|
8982
9134
|
}
|
|
8983
9135
|
if (type === "tool_call") {
|
|
@@ -8998,9 +9150,11 @@ function printCursorStreamEvent(raw, _debug) {
|
|
|
8998
9150
|
console.log(pc11.blue(`result: subtype=${subtype}`));
|
|
8999
9151
|
console.log(pc11.blue(`tokens: in=${input} out=${output} cached=${cached} cost=$${cost.toFixed(6)}`));
|
|
9000
9152
|
const resultText = asString2(parsed.result).trim();
|
|
9001
|
-
if (resultText)
|
|
9153
|
+
if (resultText)
|
|
9154
|
+
console.log((isError ? pc11.red : pc11.green)(`assistant: ${resultText}`));
|
|
9002
9155
|
const errors = Array.isArray(parsed.errors) ? parsed.errors.map((value) => stringifyUnknown(value)).filter(Boolean) : [];
|
|
9003
|
-
if (errors.length > 0)
|
|
9156
|
+
if (errors.length > 0)
|
|
9157
|
+
console.log(pc11.red(`errors: ${errors.join(" | ")}`));
|
|
9004
9158
|
return;
|
|
9005
9159
|
}
|
|
9006
9160
|
if (type === "error") {
|
|
@@ -9016,7 +9170,8 @@ function printCursorStreamEvent(raw, _debug) {
|
|
|
9016
9170
|
if (type === "text") {
|
|
9017
9171
|
const part = asRecord2(parsed.part);
|
|
9018
9172
|
const text63 = asString2(part?.text);
|
|
9019
|
-
if (text63)
|
|
9173
|
+
if (text63)
|
|
9174
|
+
console.log(pc11.green(`assistant: ${text63}`));
|
|
9020
9175
|
return;
|
|
9021
9176
|
}
|
|
9022
9177
|
if (type === "tool_use") {
|
|
@@ -9047,7 +9202,8 @@ function printCursorStreamEvent(raw, _debug) {
|
|
|
9047
9202
|
// ../packages/adapters/gemini-local/src/cli/format-event.ts
|
|
9048
9203
|
import pc12 from "picocolors";
|
|
9049
9204
|
function asRecord3(value) {
|
|
9050
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9205
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9206
|
+
return null;
|
|
9051
9207
|
return value;
|
|
9052
9208
|
}
|
|
9053
9209
|
function asString3(value, fallback = "") {
|
|
@@ -9057,8 +9213,10 @@ function asNumber3(value, fallback = 0) {
|
|
|
9057
9213
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
9058
9214
|
}
|
|
9059
9215
|
function stringifyUnknown2(value) {
|
|
9060
|
-
if (typeof value === "string")
|
|
9061
|
-
|
|
9216
|
+
if (typeof value === "string")
|
|
9217
|
+
return value;
|
|
9218
|
+
if (value === null || value === void 0)
|
|
9219
|
+
return "";
|
|
9062
9220
|
try {
|
|
9063
9221
|
return JSON.stringify(value, null, 2);
|
|
9064
9222
|
} catch {
|
|
@@ -9066,11 +9224,14 @@ function stringifyUnknown2(value) {
|
|
|
9066
9224
|
}
|
|
9067
9225
|
}
|
|
9068
9226
|
function errorText2(value) {
|
|
9069
|
-
if (typeof value === "string")
|
|
9227
|
+
if (typeof value === "string")
|
|
9228
|
+
return value;
|
|
9070
9229
|
const rec = asRecord3(value);
|
|
9071
|
-
if (!rec)
|
|
9230
|
+
if (!rec)
|
|
9231
|
+
return "";
|
|
9072
9232
|
const msg = typeof rec.message === "string" && rec.message || typeof rec.error === "string" && rec.error || typeof rec.code === "string" && rec.code || "";
|
|
9073
|
-
if (msg)
|
|
9233
|
+
if (msg)
|
|
9234
|
+
return msg;
|
|
9074
9235
|
try {
|
|
9075
9236
|
return JSON.stringify(rec);
|
|
9076
9237
|
} catch {
|
|
@@ -9080,40 +9241,48 @@ function errorText2(value) {
|
|
|
9080
9241
|
function printTextMessage(prefix, colorize, messageRaw) {
|
|
9081
9242
|
if (typeof messageRaw === "string") {
|
|
9082
9243
|
const text63 = messageRaw.trim();
|
|
9083
|
-
if (text63)
|
|
9244
|
+
if (text63)
|
|
9245
|
+
console.log(colorize(`${prefix}: ${text63}`));
|
|
9084
9246
|
return;
|
|
9085
9247
|
}
|
|
9086
9248
|
const message = asRecord3(messageRaw);
|
|
9087
|
-
if (!message)
|
|
9249
|
+
if (!message)
|
|
9250
|
+
return;
|
|
9088
9251
|
const directText = asString3(message.text).trim();
|
|
9089
|
-
if (directText)
|
|
9252
|
+
if (directText)
|
|
9253
|
+
console.log(colorize(`${prefix}: ${directText}`));
|
|
9090
9254
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
9091
9255
|
for (const partRaw of content) {
|
|
9092
9256
|
const part = asRecord3(partRaw);
|
|
9093
|
-
if (!part)
|
|
9257
|
+
if (!part)
|
|
9258
|
+
continue;
|
|
9094
9259
|
const type = asString3(part.type).trim();
|
|
9095
9260
|
if (type === "output_text" || type === "text" || type === "content") {
|
|
9096
9261
|
const text63 = asString3(part.text).trim() || asString3(part.content).trim();
|
|
9097
|
-
if (text63)
|
|
9262
|
+
if (text63)
|
|
9263
|
+
console.log(colorize(`${prefix}: ${text63}`));
|
|
9098
9264
|
continue;
|
|
9099
9265
|
}
|
|
9100
9266
|
if (type === "thinking") {
|
|
9101
9267
|
const text63 = asString3(part.text).trim();
|
|
9102
|
-
if (text63)
|
|
9268
|
+
if (text63)
|
|
9269
|
+
console.log(pc12.gray(`thinking: ${text63}`));
|
|
9103
9270
|
continue;
|
|
9104
9271
|
}
|
|
9105
9272
|
if (type === "tool_call") {
|
|
9106
9273
|
const name = asString3(part.name, asString3(part.tool, "tool"));
|
|
9107
9274
|
console.log(pc12.yellow(`tool_call: ${name}`));
|
|
9108
9275
|
const input = part.input ?? part.arguments ?? part.args;
|
|
9109
|
-
if (input !== void 0)
|
|
9276
|
+
if (input !== void 0)
|
|
9277
|
+
console.log(pc12.gray(stringifyUnknown2(input)));
|
|
9110
9278
|
continue;
|
|
9111
9279
|
}
|
|
9112
9280
|
if (type === "tool_result" || type === "tool_response") {
|
|
9113
9281
|
const isError = part.is_error === true || asString3(part.status).toLowerCase() === "error";
|
|
9114
9282
|
const contentText = asString3(part.output) || asString3(part.text) || asString3(part.result) || stringifyUnknown2(part.output ?? part.result ?? part.text ?? part.response);
|
|
9115
9283
|
console.log((isError ? pc12.red : pc12.cyan)(`tool_result${isError ? " (error)" : ""}`));
|
|
9116
|
-
if (contentText)
|
|
9284
|
+
if (contentText)
|
|
9285
|
+
console.log((isError ? pc12.red : pc12.gray)(contentText));
|
|
9117
9286
|
}
|
|
9118
9287
|
}
|
|
9119
9288
|
}
|
|
@@ -9132,7 +9301,8 @@ function printUsage(parsed) {
|
|
|
9132
9301
|
}
|
|
9133
9302
|
function printGeminiStreamEvent(raw, _debug) {
|
|
9134
9303
|
const line = raw.trim();
|
|
9135
|
-
if (!line)
|
|
9304
|
+
if (!line)
|
|
9305
|
+
return;
|
|
9136
9306
|
let parsed = null;
|
|
9137
9307
|
try {
|
|
9138
9308
|
parsed = JSON.parse(line);
|
|
@@ -9152,7 +9322,8 @@ function printGeminiStreamEvent(raw, _debug) {
|
|
|
9152
9322
|
}
|
|
9153
9323
|
if (subtype === "error") {
|
|
9154
9324
|
const text63 = errorText2(parsed.error ?? parsed.message ?? parsed.detail);
|
|
9155
|
-
if (text63)
|
|
9325
|
+
if (text63)
|
|
9326
|
+
console.log(pc12.red(`error: ${text63}`));
|
|
9156
9327
|
return;
|
|
9157
9328
|
}
|
|
9158
9329
|
console.log(pc12.blue(`system: ${subtype || "event"}`));
|
|
@@ -9168,7 +9339,8 @@ function printGeminiStreamEvent(raw, _debug) {
|
|
|
9168
9339
|
}
|
|
9169
9340
|
if (type === "thinking") {
|
|
9170
9341
|
const text63 = asString3(parsed.text).trim() || asString3(asRecord3(parsed.delta)?.text).trim();
|
|
9171
|
-
if (text63)
|
|
9342
|
+
if (text63)
|
|
9343
|
+
console.log(pc12.gray(`thinking: ${text63}`));
|
|
9172
9344
|
return;
|
|
9173
9345
|
}
|
|
9174
9346
|
if (type === "tool_call") {
|
|
@@ -9205,7 +9377,8 @@ function printGeminiStreamEvent(raw, _debug) {
|
|
|
9205
9377
|
}
|
|
9206
9378
|
if (type === "error") {
|
|
9207
9379
|
const text63 = errorText2(parsed.error ?? parsed.message ?? parsed.detail);
|
|
9208
|
-
if (text63)
|
|
9380
|
+
if (text63)
|
|
9381
|
+
console.log(pc12.red(`error: ${text63}`));
|
|
9209
9382
|
return;
|
|
9210
9383
|
}
|
|
9211
9384
|
console.log(line);
|
|
@@ -9221,7 +9394,8 @@ function safeJsonParse(text63) {
|
|
|
9221
9394
|
}
|
|
9222
9395
|
}
|
|
9223
9396
|
function asRecord4(value) {
|
|
9224
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9397
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9398
|
+
return null;
|
|
9225
9399
|
return value;
|
|
9226
9400
|
}
|
|
9227
9401
|
function asString4(value, fallback = "") {
|
|
@@ -9231,12 +9405,15 @@ function asNumber4(value, fallback = 0) {
|
|
|
9231
9405
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
9232
9406
|
}
|
|
9233
9407
|
function errorText3(value) {
|
|
9234
|
-
if (typeof value === "string")
|
|
9408
|
+
if (typeof value === "string")
|
|
9409
|
+
return value;
|
|
9235
9410
|
const rec = asRecord4(value);
|
|
9236
|
-
if (!rec)
|
|
9411
|
+
if (!rec)
|
|
9412
|
+
return "";
|
|
9237
9413
|
const data = asRecord4(rec.data);
|
|
9238
9414
|
const message = asString4(rec.message) || asString4(data?.message) || asString4(rec.name) || "";
|
|
9239
|
-
if (message)
|
|
9415
|
+
if (message)
|
|
9416
|
+
return message;
|
|
9240
9417
|
try {
|
|
9241
9418
|
return JSON.stringify(rec);
|
|
9242
9419
|
} catch {
|
|
@@ -9245,7 +9422,8 @@ function errorText3(value) {
|
|
|
9245
9422
|
}
|
|
9246
9423
|
function printOpenCodeStreamEvent(raw, _debug) {
|
|
9247
9424
|
const line = raw.trim();
|
|
9248
|
-
if (!line)
|
|
9425
|
+
if (!line)
|
|
9426
|
+
return;
|
|
9249
9427
|
const parsed = asRecord4(safeJsonParse(line));
|
|
9250
9428
|
if (!parsed) {
|
|
9251
9429
|
console.log(line);
|
|
@@ -9260,13 +9438,15 @@ function printOpenCodeStreamEvent(raw, _debug) {
|
|
|
9260
9438
|
if (type === "text") {
|
|
9261
9439
|
const part = asRecord4(parsed.part);
|
|
9262
9440
|
const text63 = asString4(part?.text).trim();
|
|
9263
|
-
if (text63)
|
|
9441
|
+
if (text63)
|
|
9442
|
+
console.log(pc13.green(`assistant: ${text63}`));
|
|
9264
9443
|
return;
|
|
9265
9444
|
}
|
|
9266
9445
|
if (type === "reasoning") {
|
|
9267
9446
|
const part = asRecord4(parsed.part);
|
|
9268
9447
|
const text63 = asString4(part?.text).trim();
|
|
9269
|
-
if (text63)
|
|
9448
|
+
if (text63)
|
|
9449
|
+
console.log(pc13.gray(`thinking: ${text63}`));
|
|
9270
9450
|
return;
|
|
9271
9451
|
}
|
|
9272
9452
|
if (type === "tool_use") {
|
|
@@ -9282,13 +9462,15 @@ function printOpenCodeStreamEvent(raw, _debug) {
|
|
|
9282
9462
|
const metaParts = [`status=${status}`];
|
|
9283
9463
|
if (metadata) {
|
|
9284
9464
|
for (const [key, value] of Object.entries(metadata)) {
|
|
9285
|
-
if (value !== void 0 && value !== null)
|
|
9465
|
+
if (value !== void 0 && value !== null)
|
|
9466
|
+
metaParts.push(`${key}=${value}`);
|
|
9286
9467
|
}
|
|
9287
9468
|
}
|
|
9288
9469
|
console.log((isError ? pc13.red : pc13.gray)(`tool_result ${metaParts.join(" ")}`));
|
|
9289
9470
|
}
|
|
9290
9471
|
const output = (asString4(state?.output) || asString4(state?.error)).trim();
|
|
9291
|
-
if (output)
|
|
9472
|
+
if (output)
|
|
9473
|
+
console.log((isError ? pc13.red : pc13.gray)(output));
|
|
9292
9474
|
return;
|
|
9293
9475
|
}
|
|
9294
9476
|
if (type === "step_finish") {
|
|
@@ -9306,7 +9488,8 @@ function printOpenCodeStreamEvent(raw, _debug) {
|
|
|
9306
9488
|
}
|
|
9307
9489
|
if (type === "error") {
|
|
9308
9490
|
const message = errorText3(parsed.error ?? parsed.message);
|
|
9309
|
-
if (message)
|
|
9491
|
+
if (message)
|
|
9492
|
+
console.log(pc13.red(`error: ${message}`));
|
|
9310
9493
|
return;
|
|
9311
9494
|
}
|
|
9312
9495
|
console.log(line);
|
|
@@ -9322,20 +9505,24 @@ function safeJsonParse2(text63) {
|
|
|
9322
9505
|
}
|
|
9323
9506
|
}
|
|
9324
9507
|
function asRecord5(value) {
|
|
9325
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9508
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9509
|
+
return null;
|
|
9326
9510
|
return value;
|
|
9327
9511
|
}
|
|
9328
9512
|
function asString5(value, fallback = "") {
|
|
9329
9513
|
return typeof value === "string" ? value : fallback;
|
|
9330
9514
|
}
|
|
9331
9515
|
function extractTextContent(content) {
|
|
9332
|
-
if (typeof content === "string")
|
|
9333
|
-
|
|
9516
|
+
if (typeof content === "string")
|
|
9517
|
+
return content;
|
|
9518
|
+
if (!Array.isArray(content))
|
|
9519
|
+
return "";
|
|
9334
9520
|
return content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("");
|
|
9335
9521
|
}
|
|
9336
9522
|
function printPiStreamEvent(raw, _debug) {
|
|
9337
9523
|
const line = raw.trim();
|
|
9338
|
-
if (!line)
|
|
9524
|
+
if (!line)
|
|
9525
|
+
return;
|
|
9339
9526
|
const parsed = asRecord5(safeJsonParse2(line));
|
|
9340
9527
|
if (!parsed) {
|
|
9341
9528
|
console.log(line);
|
|
@@ -9407,7 +9594,8 @@ function printPiStreamEvent(raw, _debug) {
|
|
|
9407
9594
|
import pc15 from "picocolors";
|
|
9408
9595
|
function printOpenClawGatewayStreamEvent(raw, debug) {
|
|
9409
9596
|
const line = raw.trim();
|
|
9410
|
-
if (!line)
|
|
9597
|
+
if (!line)
|
|
9598
|
+
return;
|
|
9411
9599
|
if (!debug) {
|
|
9412
9600
|
console.log(line);
|
|
9413
9601
|
return;
|
|
@@ -9426,7 +9614,8 @@ function printOpenClawGatewayStreamEvent(raw, debug) {
|
|
|
9426
9614
|
// src/adapters/process/format-event.ts
|
|
9427
9615
|
function printProcessStdoutEvent(raw, _debug) {
|
|
9428
9616
|
const line = raw.trim();
|
|
9429
|
-
if (line)
|
|
9617
|
+
if (line)
|
|
9618
|
+
console.log(line);
|
|
9430
9619
|
}
|
|
9431
9620
|
|
|
9432
9621
|
// src/adapters/process/index.ts
|
|
@@ -9438,7 +9627,8 @@ var processCLIAdapter = {
|
|
|
9438
9627
|
// src/adapters/http/format-event.ts
|
|
9439
9628
|
function printHttpStdoutEvent(raw, _debug) {
|
|
9440
9629
|
const line = raw.trim();
|
|
9441
|
-
if (line)
|
|
9630
|
+
if (line)
|
|
9631
|
+
console.log(line);
|
|
9442
9632
|
}
|
|
9443
9633
|
|
|
9444
9634
|
// src/adapters/http/index.ts
|
|
@@ -9470,7 +9660,8 @@ var EVENT_PREFIXES = {
|
|
|
9470
9660
|
};
|
|
9471
9661
|
function printOpenAgentsStreamEvent(raw, _debug) {
|
|
9472
9662
|
const line = raw.trim();
|
|
9473
|
-
if (!line)
|
|
9663
|
+
if (!line)
|
|
9664
|
+
return;
|
|
9474
9665
|
try {
|
|
9475
9666
|
const event = JSON.parse(line);
|
|
9476
9667
|
if (event.type && event.detail) {
|
|
@@ -9492,7 +9683,8 @@ var openAgentsCLIAdapter = {
|
|
|
9492
9683
|
// src/adapters/qwen/format-event.ts
|
|
9493
9684
|
function printQwenStreamEvent(raw, _debug) {
|
|
9494
9685
|
const line = raw.trim();
|
|
9495
|
-
if (!line)
|
|
9686
|
+
if (!line)
|
|
9687
|
+
return;
|
|
9496
9688
|
try {
|
|
9497
9689
|
const parsed = JSON.parse(line);
|
|
9498
9690
|
if (parsed.type === "result" && typeof parsed.text === "string") {
|
|
@@ -9581,14 +9773,17 @@ function findContextFileFromAncestors(startDir) {
|
|
|
9581
9773
|
return candidate;
|
|
9582
9774
|
}
|
|
9583
9775
|
const nextDir = path9.resolve(currentDir, "..");
|
|
9584
|
-
if (nextDir === currentDir)
|
|
9776
|
+
if (nextDir === currentDir)
|
|
9777
|
+
break;
|
|
9585
9778
|
currentDir = nextDir;
|
|
9586
9779
|
}
|
|
9587
9780
|
return null;
|
|
9588
9781
|
}
|
|
9589
9782
|
function resolveContextPath(overridePath) {
|
|
9590
|
-
if (overridePath)
|
|
9591
|
-
|
|
9783
|
+
if (overridePath)
|
|
9784
|
+
return path9.resolve(overridePath);
|
|
9785
|
+
if (process.env.PAPERCLIP_CONTEXT)
|
|
9786
|
+
return path9.resolve(process.env.PAPERCLIP_CONTEXT);
|
|
9592
9787
|
return findContextFileFromAncestors(process.cwd()) ?? resolveDefaultContextPath();
|
|
9593
9788
|
}
|
|
9594
9789
|
function defaultClientContext() {
|
|
@@ -9611,7 +9806,8 @@ function toStringOrUndefined(value) {
|
|
|
9611
9806
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
9612
9807
|
}
|
|
9613
9808
|
function normalizeProfile(value) {
|
|
9614
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9809
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
9810
|
+
return {};
|
|
9615
9811
|
const profile = value;
|
|
9616
9812
|
return {
|
|
9617
9813
|
apiBase: toStringOrUndefined(profile.apiBase),
|
|
@@ -9630,7 +9826,8 @@ function normalizeContext(raw) {
|
|
|
9630
9826
|
const profiles = {};
|
|
9631
9827
|
if (typeof rawProfiles === "object" && rawProfiles !== null && !Array.isArray(rawProfiles)) {
|
|
9632
9828
|
for (const [name, profile] of Object.entries(rawProfiles)) {
|
|
9633
|
-
if (!name.trim())
|
|
9829
|
+
if (!name.trim())
|
|
9830
|
+
continue;
|
|
9634
9831
|
profiles[name] = normalizeProfile(profile);
|
|
9635
9832
|
}
|
|
9636
9833
|
}
|
|
@@ -9783,7 +9980,8 @@ function buildUrl(apiBase, path36) {
|
|
|
9783
9980
|
const [pathname, query] = normalizedPath.split("?");
|
|
9784
9981
|
const url = new URL2(apiBase);
|
|
9785
9982
|
url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
|
|
9786
|
-
if (query)
|
|
9983
|
+
if (query)
|
|
9984
|
+
url.search = query;
|
|
9787
9985
|
return url.toString();
|
|
9788
9986
|
}
|
|
9789
9987
|
function safeParseJson(text63) {
|
|
@@ -9804,7 +10002,8 @@ async function toApiError(response) {
|
|
|
9804
10002
|
return new ApiRequestError(response.status, `Request failed with status ${response.status}`, void 0, parsed);
|
|
9805
10003
|
}
|
|
9806
10004
|
function toStringRecord(headers) {
|
|
9807
|
-
if (!headers)
|
|
10005
|
+
if (!headers)
|
|
10006
|
+
return {};
|
|
9808
10007
|
if (Array.isArray(headers)) {
|
|
9809
10008
|
return Object.fromEntries(headers.map(([key, value]) => [key, String(value)]));
|
|
9810
10009
|
}
|
|
@@ -9881,19 +10080,23 @@ function formatInlineRecord(record) {
|
|
|
9881
10080
|
const seen = /* @__PURE__ */ new Set();
|
|
9882
10081
|
const parts = [];
|
|
9883
10082
|
for (const key of keyOrder) {
|
|
9884
|
-
if (!(key in record))
|
|
10083
|
+
if (!(key in record))
|
|
10084
|
+
continue;
|
|
9885
10085
|
parts.push(`${key}=${renderValue(record[key])}`);
|
|
9886
10086
|
seen.add(key);
|
|
9887
10087
|
}
|
|
9888
10088
|
for (const [key, value] of Object.entries(record)) {
|
|
9889
|
-
if (seen.has(key))
|
|
9890
|
-
|
|
10089
|
+
if (seen.has(key))
|
|
10090
|
+
continue;
|
|
10091
|
+
if (typeof value === "object")
|
|
10092
|
+
continue;
|
|
9891
10093
|
parts.push(`${key}=${renderValue(value)}`);
|
|
9892
10094
|
}
|
|
9893
10095
|
return parts.join(" ");
|
|
9894
10096
|
}
|
|
9895
10097
|
function renderValue(value) {
|
|
9896
|
-
if (value === null || value === void 0)
|
|
10098
|
+
if (value === null || value === void 0)
|
|
10099
|
+
return "-";
|
|
9897
10100
|
if (typeof value === "string") {
|
|
9898
10101
|
const compact = value.replace(/\s+/g, " ").trim();
|
|
9899
10102
|
return compact.length > 90 ? `${compact.slice(0, 87)}...` : compact;
|
|
@@ -9920,7 +10123,8 @@ function inferApiBaseFromConfig(configPath) {
|
|
|
9920
10123
|
return `http://${envHost}:${port}`;
|
|
9921
10124
|
}
|
|
9922
10125
|
function readKeyFromProfileEnv(profile) {
|
|
9923
|
-
if (!profile.apiKeyEnvVarName)
|
|
10126
|
+
if (!profile.apiKeyEnvVarName)
|
|
10127
|
+
return void 0;
|
|
9924
10128
|
return process.env[profile.apiKeyEnvVarName]?.trim() || void 0;
|
|
9925
10129
|
}
|
|
9926
10130
|
function handleCommandError(error) {
|
|
@@ -9943,11 +10147,14 @@ function asRecord6(value) {
|
|
|
9943
10147
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
9944
10148
|
}
|
|
9945
10149
|
function asErrorText2(value) {
|
|
9946
|
-
if (typeof value === "string")
|
|
10150
|
+
if (typeof value === "string")
|
|
10151
|
+
return value;
|
|
9947
10152
|
const obj = asRecord6(value);
|
|
9948
|
-
if (!obj)
|
|
10153
|
+
if (!obj)
|
|
10154
|
+
return "";
|
|
9949
10155
|
const message = typeof obj.message === "string" && obj.message || typeof obj.error === "string" && obj.error || typeof obj.code === "string" && obj.code || "";
|
|
9950
|
-
if (message)
|
|
10156
|
+
if (message)
|
|
10157
|
+
return message;
|
|
9951
10158
|
try {
|
|
9952
10159
|
return JSON.stringify(obj);
|
|
9953
10160
|
} catch {
|
|
@@ -9997,9 +10204,12 @@ async function heartbeatRun(opts) {
|
|
|
9997
10204
|
let logOffset = 0;
|
|
9998
10205
|
let stdoutJsonBuffer = "";
|
|
9999
10206
|
const printRawChunk = (stream, chunk) => {
|
|
10000
|
-
if (stream === "stdout")
|
|
10001
|
-
|
|
10002
|
-
else
|
|
10207
|
+
if (stream === "stdout")
|
|
10208
|
+
process.stdout.write(pc18.green("[stdout] ") + chunk);
|
|
10209
|
+
else if (stream === "stderr")
|
|
10210
|
+
process.stdout.write(pc18.red("[stderr] ") + chunk);
|
|
10211
|
+
else
|
|
10212
|
+
process.stdout.write(pc18.yellow("[system] ") + chunk);
|
|
10003
10213
|
};
|
|
10004
10214
|
const printAdapterInvoke = (payload) => {
|
|
10005
10215
|
const adapterType2 = typeof payload.adapterType === "string" ? payload.adapterType : "unknown";
|
|
@@ -10010,7 +10220,8 @@ async function heartbeatRun(opts) {
|
|
|
10010
10220
|
const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
|
|
10011
10221
|
const context = typeof payload.context === "object" && payload.context !== null && !Array.isArray(payload.context) ? payload.context : null;
|
|
10012
10222
|
console.log(pc18.cyan(`Adapter: ${adapterType2}`));
|
|
10013
|
-
if (cwd)
|
|
10223
|
+
if (cwd)
|
|
10224
|
+
console.log(pc18.cyan(`Working dir: ${cwd}`));
|
|
10014
10225
|
if (command) {
|
|
10015
10226
|
const rendered = args.length > 0 ? `${command} ${args.join(" ")}` : command;
|
|
10016
10227
|
console.log(pc18.cyan(`Command: ${rendered}`));
|
|
@@ -10048,7 +10259,8 @@ async function heartbeatRun(opts) {
|
|
|
10048
10259
|
};
|
|
10049
10260
|
const handleEvent = (event) => {
|
|
10050
10261
|
const payload = normalizePayload(event.payload);
|
|
10051
|
-
if (event.runId !== runId)
|
|
10262
|
+
if (event.runId !== runId)
|
|
10263
|
+
return;
|
|
10052
10264
|
const eventType = typeof event.eventType === "string" ? event.eventType : typeof event.type === "string" ? event.type : "";
|
|
10053
10265
|
if (eventType === "heartbeat.run.status") {
|
|
10054
10266
|
const status = typeof payload.status === "string" ? payload.status : null;
|
|
@@ -10060,7 +10272,8 @@ async function heartbeatRun(opts) {
|
|
|
10060
10272
|
} else if (eventType === "heartbeat.run.log") {
|
|
10061
10273
|
const stream = typeof payload.stream === "string" ? payload.stream : "system";
|
|
10062
10274
|
const chunk = typeof payload.chunk === "string" ? payload.chunk : "";
|
|
10063
|
-
if (!chunk)
|
|
10275
|
+
if (!chunk)
|
|
10276
|
+
return;
|
|
10064
10277
|
if (stream === "stdout" || stream === "stderr" || stream === "system") {
|
|
10065
10278
|
handleStreamChunk(stream, chunk);
|
|
10066
10279
|
}
|
|
@@ -10116,9 +10329,11 @@ async function heartbeatRun(opts) {
|
|
|
10116
10329
|
);
|
|
10117
10330
|
if (logResult && logResult.content) {
|
|
10118
10331
|
for (const chunk of logResult.content.split(/\r?\n/)) {
|
|
10119
|
-
if (!chunk)
|
|
10332
|
+
if (!chunk)
|
|
10333
|
+
continue;
|
|
10120
10334
|
const parsed = safeParseLogLine(chunk);
|
|
10121
|
-
if (!parsed)
|
|
10335
|
+
if (!parsed)
|
|
10336
|
+
continue;
|
|
10122
10337
|
handleStreamChunk(parsed.stream, parsed.chunk);
|
|
10123
10338
|
}
|
|
10124
10339
|
if (typeof logResult.nextOffset === "number") {
|
|
@@ -10152,10 +10367,14 @@ async function heartbeatRun(opts) {
|
|
|
10152
10367
|
const resultText = typeof resultObj.result === "string" ? resultObj.result.trim() : "";
|
|
10153
10368
|
if (subtype || isError || errors.length > 0 || resultText) {
|
|
10154
10369
|
console.log(pc18.red("Claude result details:"));
|
|
10155
|
-
if (subtype)
|
|
10156
|
-
|
|
10157
|
-
if (
|
|
10158
|
-
|
|
10370
|
+
if (subtype)
|
|
10371
|
+
console.log(pc18.red(` subtype: ${subtype}`));
|
|
10372
|
+
if (isError)
|
|
10373
|
+
console.log(pc18.red(" is_error: true"));
|
|
10374
|
+
if (errors.length > 0)
|
|
10375
|
+
console.log(pc18.red(` errors: ${errors.join(" | ")}`));
|
|
10376
|
+
if (resultText)
|
|
10377
|
+
console.log(pc18.red(` result: ${resultText}`));
|
|
10159
10378
|
}
|
|
10160
10379
|
}
|
|
10161
10380
|
const stderrExcerpt = typeof finalRun.stderrExcerpt === "string" ? finalRun.stderrExcerpt.trim() : "";
|
|
@@ -10183,7 +10402,8 @@ function safeParseLogLine(line) {
|
|
|
10183
10402
|
const parsed = JSON.parse(line);
|
|
10184
10403
|
const stream = parsed.stream === "stdout" || parsed.stream === "stderr" || parsed.stream === "system" ? parsed.stream : "system";
|
|
10185
10404
|
const chunk = typeof parsed.chunk === "string" ? parsed.chunk : "";
|
|
10186
|
-
if (!chunk)
|
|
10405
|
+
if (!chunk)
|
|
10406
|
+
return null;
|
|
10187
10407
|
return { stream, chunk };
|
|
10188
10408
|
} catch {
|
|
10189
10409
|
return null;
|
|
@@ -10217,7 +10437,8 @@ function trimSlashes(value) {
|
|
|
10217
10437
|
}
|
|
10218
10438
|
function pickParam(url, name) {
|
|
10219
10439
|
const value = url.searchParams.get(name);
|
|
10220
|
-
if (value === null)
|
|
10440
|
+
if (value === null)
|
|
10441
|
+
return void 0;
|
|
10221
10442
|
const trimmed = value.trim();
|
|
10222
10443
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
10223
10444
|
}
|
|
@@ -10357,14 +10578,16 @@ async function startLoginFlow(opts) {
|
|
|
10357
10578
|
url.searchParams.set("state", state);
|
|
10358
10579
|
url.searchParams.set("callback", callbackUrl);
|
|
10359
10580
|
url.searchParams.set("machineLabel", machineLabel);
|
|
10360
|
-
if (workspaceLabel)
|
|
10581
|
+
if (workspaceLabel)
|
|
10582
|
+
url.searchParams.set("workspaceLabel", workspaceLabel);
|
|
10361
10583
|
url.searchParams.set("source", "cli");
|
|
10362
10584
|
return url.toString();
|
|
10363
10585
|
})();
|
|
10364
10586
|
let timeoutHandle = setTimeout(() => {
|
|
10365
10587
|
rejecter?.(new Error(`CLI login timed out after ${Math.round(timeoutMs / 1e3)}s.`));
|
|
10366
10588
|
}, timeoutMs);
|
|
10367
|
-
if (typeof timeoutHandle.unref === "function")
|
|
10589
|
+
if (typeof timeoutHandle.unref === "function")
|
|
10590
|
+
timeoutHandle.unref();
|
|
10368
10591
|
const close = () => {
|
|
10369
10592
|
if (timeoutHandle) {
|
|
10370
10593
|
clearTimeout(timeoutHandle);
|
|
@@ -10426,11 +10649,13 @@ function toStringOrUndefined2(value) {
|
|
|
10426
10649
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
10427
10650
|
}
|
|
10428
10651
|
function normalizeSession(raw) {
|
|
10429
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
10652
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
10653
|
+
return null;
|
|
10430
10654
|
const record = raw;
|
|
10431
10655
|
const accessToken = toStringOrUndefined2(record.accessToken);
|
|
10432
10656
|
const hostedBaseUrl = toStringOrUndefined2(record.hostedBaseUrl);
|
|
10433
|
-
if (!accessToken || !hostedBaseUrl)
|
|
10657
|
+
if (!accessToken || !hostedBaseUrl)
|
|
10658
|
+
return null;
|
|
10434
10659
|
const issuedAt = toStringOrUndefined2(record.issuedAt) ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
10435
10660
|
return {
|
|
10436
10661
|
version: 1,
|
|
@@ -10447,7 +10672,8 @@ function normalizeSession(raw) {
|
|
|
10447
10672
|
}
|
|
10448
10673
|
function readSession() {
|
|
10449
10674
|
const filePath = resolveSessionPath();
|
|
10450
|
-
if (!fs11.existsSync(filePath))
|
|
10675
|
+
if (!fs11.existsSync(filePath))
|
|
10676
|
+
return null;
|
|
10451
10677
|
const raw = parseJson3(filePath);
|
|
10452
10678
|
return normalizeSession(raw);
|
|
10453
10679
|
}
|
|
@@ -10463,14 +10689,17 @@ function writeSession(session) {
|
|
|
10463
10689
|
}
|
|
10464
10690
|
function clearSession() {
|
|
10465
10691
|
const filePath = resolveSessionPath();
|
|
10466
|
-
if (!fs11.existsSync(filePath))
|
|
10692
|
+
if (!fs11.existsSync(filePath))
|
|
10693
|
+
return false;
|
|
10467
10694
|
fs11.rmSync(filePath, { force: true });
|
|
10468
10695
|
return true;
|
|
10469
10696
|
}
|
|
10470
10697
|
function isSessionExpired(session, now = /* @__PURE__ */ new Date()) {
|
|
10471
|
-
if (!session.expiresAt)
|
|
10698
|
+
if (!session.expiresAt)
|
|
10699
|
+
return false;
|
|
10472
10700
|
const expires = Date.parse(session.expiresAt);
|
|
10473
|
-
if (Number.isNaN(expires))
|
|
10701
|
+
if (Number.isNaN(expires))
|
|
10702
|
+
return false;
|
|
10474
10703
|
return expires <= now.getTime();
|
|
10475
10704
|
}
|
|
10476
10705
|
function describeSessionPath() {
|
|
@@ -10493,16 +10722,19 @@ function toStringOrUndefined3(value) {
|
|
|
10493
10722
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
10494
10723
|
}
|
|
10495
10724
|
function toStringArray(value) {
|
|
10496
|
-
if (!Array.isArray(value))
|
|
10725
|
+
if (!Array.isArray(value))
|
|
10726
|
+
return [];
|
|
10497
10727
|
const out = [];
|
|
10498
10728
|
for (const item of value) {
|
|
10499
10729
|
const normalized = toStringOrUndefined3(item);
|
|
10500
|
-
if (normalized && !out.includes(normalized))
|
|
10730
|
+
if (normalized && !out.includes(normalized))
|
|
10731
|
+
out.push(normalized);
|
|
10501
10732
|
}
|
|
10502
10733
|
return out;
|
|
10503
10734
|
}
|
|
10504
10735
|
function toRecord(value) {
|
|
10505
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
10736
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
10737
|
+
return void 0;
|
|
10506
10738
|
return value;
|
|
10507
10739
|
}
|
|
10508
10740
|
function normalizeExecutionDefaults(value) {
|
|
@@ -10523,10 +10755,12 @@ function defaultExecutionPreferences() {
|
|
|
10523
10755
|
};
|
|
10524
10756
|
}
|
|
10525
10757
|
function normalizeOverlay(raw) {
|
|
10526
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
10758
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
10759
|
+
return null;
|
|
10527
10760
|
const record = raw;
|
|
10528
10761
|
const hostedBaseUrl = toStringOrUndefined3(record.hostedBaseUrl);
|
|
10529
|
-
if (!hostedBaseUrl)
|
|
10762
|
+
if (!hostedBaseUrl)
|
|
10763
|
+
return null;
|
|
10530
10764
|
return {
|
|
10531
10765
|
version: 1,
|
|
10532
10766
|
hostedBaseUrl,
|
|
@@ -10546,7 +10780,8 @@ function normalizeOverlay(raw) {
|
|
|
10546
10780
|
}
|
|
10547
10781
|
function readHostedOverlay() {
|
|
10548
10782
|
const filePath = resolveHostedOverlayPath();
|
|
10549
|
-
if (!fs12.existsSync(filePath))
|
|
10783
|
+
if (!fs12.existsSync(filePath))
|
|
10784
|
+
return null;
|
|
10550
10785
|
return normalizeOverlay(parseJson4(filePath));
|
|
10551
10786
|
}
|
|
10552
10787
|
function writeHostedOverlay(overlay) {
|
|
@@ -10561,7 +10796,8 @@ function writeHostedOverlay(overlay) {
|
|
|
10561
10796
|
}
|
|
10562
10797
|
function clearHostedOverlay() {
|
|
10563
10798
|
const filePath = resolveHostedOverlayPath();
|
|
10564
|
-
if (!fs12.existsSync(filePath))
|
|
10799
|
+
if (!fs12.existsSync(filePath))
|
|
10800
|
+
return false;
|
|
10565
10801
|
fs12.rmSync(filePath, { force: true });
|
|
10566
10802
|
return true;
|
|
10567
10803
|
}
|
|
@@ -10841,15 +11077,19 @@ function trimSlashes2(value) {
|
|
|
10841
11077
|
}
|
|
10842
11078
|
function resolveHostedBaseUrl(opts) {
|
|
10843
11079
|
const explicit = opts.baseUrl?.trim();
|
|
10844
|
-
if (explicit)
|
|
11080
|
+
if (explicit)
|
|
11081
|
+
return trimSlashes2(explicit);
|
|
10845
11082
|
const envBase = process.env.GROWTHUB_BASE_URL?.trim();
|
|
10846
|
-
if (envBase)
|
|
11083
|
+
if (envBase)
|
|
11084
|
+
return trimSlashes2(envBase);
|
|
10847
11085
|
try {
|
|
10848
11086
|
const config = readConfig(opts.configPath);
|
|
10849
11087
|
const configuredBase = config?.auth?.growthubBaseUrl?.trim();
|
|
10850
|
-
if (configuredBase)
|
|
11088
|
+
if (configuredBase)
|
|
11089
|
+
return trimSlashes2(configuredBase);
|
|
10851
11090
|
const portalBase = config?.auth?.growthubPortalBaseUrl?.trim();
|
|
10852
|
-
if (portalBase)
|
|
11091
|
+
if (portalBase)
|
|
11092
|
+
return trimSlashes2(portalBase);
|
|
10853
11093
|
} catch {
|
|
10854
11094
|
}
|
|
10855
11095
|
return DEFAULT_HOSTED_BASE_URL;
|
|
@@ -11037,8 +11277,10 @@ async function authLogout(opts) {
|
|
|
11037
11277
|
console.log(pc19.dim("No hosted session or overlay present. Local workspace profile is untouched."));
|
|
11038
11278
|
return;
|
|
11039
11279
|
}
|
|
11040
|
-
if (sessionCleared)
|
|
11041
|
-
|
|
11280
|
+
if (sessionCleared)
|
|
11281
|
+
console.log(pc19.green("Cleared hosted session."));
|
|
11282
|
+
if (overlayCleared)
|
|
11283
|
+
console.log(pc19.green("Cleared hosted overlay."));
|
|
11042
11284
|
console.log(pc19.dim("Local workspace profile is untouched."));
|
|
11043
11285
|
}
|
|
11044
11286
|
async function authWhoami(opts) {
|
|
@@ -11076,7 +11318,8 @@ async function authWhoami(opts) {
|
|
|
11076
11318
|
return;
|
|
11077
11319
|
}
|
|
11078
11320
|
console.log(pc19.bold(`Signed in${payload.email ? ` as ${payload.email}` : payload.userId ? ` as ${payload.userId}` : ""}.`));
|
|
11079
|
-
if (payload.hostedBaseUrl)
|
|
11321
|
+
if (payload.hostedBaseUrl)
|
|
11322
|
+
console.log(pc19.dim(`Hosted: ${payload.hostedBaseUrl}`));
|
|
11080
11323
|
if (payload.orgName || payload.orgId) {
|
|
11081
11324
|
console.log(pc19.dim(`Org: ${payload.orgName ?? payload.orgId}`));
|
|
11082
11325
|
}
|
|
@@ -11123,7 +11366,8 @@ function printEffectiveProfileHuman(effective) {
|
|
|
11123
11366
|
if (effective.hosted.orgName || effective.hosted.orgId) {
|
|
11124
11367
|
console.log(` Org: ${effective.hosted.orgName ?? effective.hosted.orgId}`);
|
|
11125
11368
|
}
|
|
11126
|
-
if (effective.hosted.hostedBaseUrl)
|
|
11369
|
+
if (effective.hosted.hostedBaseUrl)
|
|
11370
|
+
console.log(` Hosted: ${effective.hosted.hostedBaseUrl}`);
|
|
11127
11371
|
if (effective.hosted.linkedInstanceId) {
|
|
11128
11372
|
console.log(` Linked instance: ${effective.hosted.linkedInstanceId}`);
|
|
11129
11373
|
}
|
|
@@ -11133,8 +11377,10 @@ function printEffectiveProfileHuman(effective) {
|
|
|
11133
11377
|
if (effective.hosted.gatedKitSlugs.length > 0) {
|
|
11134
11378
|
console.log(` Gated kits: ${effective.hosted.gatedKitSlugs.join(", ")}`);
|
|
11135
11379
|
}
|
|
11136
|
-
if (effective.hosted.lastPulledAt)
|
|
11137
|
-
|
|
11380
|
+
if (effective.hosted.lastPulledAt)
|
|
11381
|
+
console.log(pc20.dim(` Last pulled: ${effective.hosted.lastPulledAt}`));
|
|
11382
|
+
if (effective.hosted.lastPushedAt)
|
|
11383
|
+
console.log(pc20.dim(` Last pushed: ${effective.hosted.lastPushedAt}`));
|
|
11138
11384
|
}
|
|
11139
11385
|
console.log(pc20.bold("Execution defaults"));
|
|
11140
11386
|
console.log(
|
|
@@ -11153,7 +11399,8 @@ async function runProfileStatus(opts) {
|
|
|
11153
11399
|
printEffectiveProfileHuman(effective);
|
|
11154
11400
|
}
|
|
11155
11401
|
function normalizeExecutionPrefs(value, fallback) {
|
|
11156
|
-
if (!value)
|
|
11402
|
+
if (!value)
|
|
11403
|
+
return fallback;
|
|
11157
11404
|
const preferredMode = value.preferredMode === "local" || value.preferredMode === "serverless" || value.preferredMode === "browser" || value.preferredMode === "auto" ? value.preferredMode : fallback.preferredMode;
|
|
11158
11405
|
return {
|
|
11159
11406
|
preferredMode,
|
|
@@ -11349,7 +11596,8 @@ import * as p15 from "@clack/prompts";
|
|
|
11349
11596
|
import pc21 from "picocolors";
|
|
11350
11597
|
function resolveConnectionString(configPath) {
|
|
11351
11598
|
const envUrl = process.env.DATABASE_URL?.trim();
|
|
11352
|
-
if (envUrl)
|
|
11599
|
+
if (envUrl)
|
|
11600
|
+
return { value: envUrl, source: "DATABASE_URL" };
|
|
11353
11601
|
const config = readConfig(configPath);
|
|
11354
11602
|
if (config?.database.mode === "postgres" && config.database.connectionString?.trim()) {
|
|
11355
11603
|
return { value: config.database.connectionString.trim(), source: "config.database.connectionString" };
|
|
@@ -11496,7 +11744,8 @@ function normalizeSelector(input) {
|
|
|
11496
11744
|
return input.trim();
|
|
11497
11745
|
}
|
|
11498
11746
|
function parseInclude(input) {
|
|
11499
|
-
if (!input || !input.trim())
|
|
11747
|
+
if (!input || !input.trim())
|
|
11748
|
+
return { company: true, agents: true };
|
|
11500
11749
|
const values = input.split(",").map((part) => part.trim().toLowerCase()).filter(Boolean);
|
|
11501
11750
|
const include = {
|
|
11502
11751
|
company: values.includes("company"),
|
|
@@ -11508,11 +11757,14 @@ function parseInclude(input) {
|
|
|
11508
11757
|
return include;
|
|
11509
11758
|
}
|
|
11510
11759
|
function parseAgents(input) {
|
|
11511
|
-
if (!input || !input.trim())
|
|
11760
|
+
if (!input || !input.trim())
|
|
11761
|
+
return "all";
|
|
11512
11762
|
const normalized = input.trim().toLowerCase();
|
|
11513
|
-
if (normalized === "all")
|
|
11763
|
+
if (normalized === "all")
|
|
11764
|
+
return "all";
|
|
11514
11765
|
const values = input.split(",").map((part) => part.trim()).filter(Boolean);
|
|
11515
|
-
if (values.length === 0)
|
|
11766
|
+
if (values.length === 0)
|
|
11767
|
+
return "all";
|
|
11516
11768
|
return Array.from(new Set(values));
|
|
11517
11769
|
}
|
|
11518
11770
|
function isHttpUrl(input) {
|
|
@@ -11578,8 +11830,10 @@ function resolveCompanyForDeletion(companies2, selectorRaw, by = "auto") {
|
|
|
11578
11830
|
`Selector '${selector}' is ambiguous (matches both an ID and a shortname). Re-run with --by id or --by prefix.`
|
|
11579
11831
|
);
|
|
11580
11832
|
}
|
|
11581
|
-
if (idMatch)
|
|
11582
|
-
|
|
11833
|
+
if (idMatch)
|
|
11834
|
+
return idMatch;
|
|
11835
|
+
if (prefixMatch)
|
|
11836
|
+
return prefixMatch;
|
|
11583
11837
|
throw new Error(
|
|
11584
11838
|
`No company found for selector '${selector}'. Use company ID or issue prefix (for example PAP).`
|
|
11585
11839
|
);
|
|
@@ -11828,9 +12082,12 @@ function registerIssueCommands(program2) {
|
|
|
11828
12082
|
try {
|
|
11829
12083
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11830
12084
|
const params = new URLSearchParams();
|
|
11831
|
-
if (opts.status)
|
|
11832
|
-
|
|
11833
|
-
if (opts.
|
|
12085
|
+
if (opts.status)
|
|
12086
|
+
params.set("status", opts.status);
|
|
12087
|
+
if (opts.assigneeAgentId)
|
|
12088
|
+
params.set("assigneeAgentId", opts.assigneeAgentId);
|
|
12089
|
+
if (opts.projectId)
|
|
12090
|
+
params.set("projectId", opts.projectId);
|
|
11834
12091
|
const query = params.toString();
|
|
11835
12092
|
const path36 = `/api/companies/${ctx.companyId}/issues${query ? `?${query}` : ""}`;
|
|
11836
12093
|
const rows = await ctx.api.get(path36) ?? [];
|
|
@@ -11969,11 +12226,13 @@ function registerIssueCommands(program2) {
|
|
|
11969
12226
|
);
|
|
11970
12227
|
}
|
|
11971
12228
|
function parseCsv(value) {
|
|
11972
|
-
if (!value)
|
|
12229
|
+
if (!value)
|
|
12230
|
+
return [];
|
|
11973
12231
|
return value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
11974
12232
|
}
|
|
11975
12233
|
function parseOptionalInt(value) {
|
|
11976
|
-
if (value === void 0)
|
|
12234
|
+
if (value === void 0)
|
|
12235
|
+
return void 0;
|
|
11977
12236
|
const parsed = Number.parseInt(value, 10);
|
|
11978
12237
|
if (!Number.isFinite(parsed)) {
|
|
11979
12238
|
throw new Error(`Invalid integer value: ${value}`);
|
|
@@ -11981,12 +12240,15 @@ function parseOptionalInt(value) {
|
|
|
11981
12240
|
return parsed;
|
|
11982
12241
|
}
|
|
11983
12242
|
function parseHiddenAt(value) {
|
|
11984
|
-
if (value === void 0)
|
|
11985
|
-
|
|
12243
|
+
if (value === void 0)
|
|
12244
|
+
return void 0;
|
|
12245
|
+
if (value.trim().toLowerCase() === "null")
|
|
12246
|
+
return null;
|
|
11986
12247
|
return value;
|
|
11987
12248
|
}
|
|
11988
12249
|
function filterIssueRows(rows, match) {
|
|
11989
|
-
if (!match?.trim())
|
|
12250
|
+
if (!match?.trim())
|
|
12251
|
+
return rows;
|
|
11990
12252
|
const needle = match.trim().toLowerCase();
|
|
11991
12253
|
return rows.filter((row) => {
|
|
11992
12254
|
const text63 = [row.identifier, row.title, row.description].filter((part) => Boolean(part)).join("\n").toLowerCase();
|
|
@@ -12016,10 +12278,12 @@ async function resolvePaperclipSkillsDir(moduleDir, additionalCandidates = []) {
|
|
|
12016
12278
|
];
|
|
12017
12279
|
const seenRoots = /* @__PURE__ */ new Set();
|
|
12018
12280
|
for (const root of candidates) {
|
|
12019
|
-
if (seenRoots.has(root))
|
|
12281
|
+
if (seenRoots.has(root))
|
|
12282
|
+
continue;
|
|
12020
12283
|
seenRoots.add(root);
|
|
12021
12284
|
const isDirectory = await fs14.stat(root).then((stats) => stats.isDirectory()).catch(() => false);
|
|
12022
|
-
if (isDirectory)
|
|
12285
|
+
if (isDirectory)
|
|
12286
|
+
return root;
|
|
12023
12287
|
}
|
|
12024
12288
|
return null;
|
|
12025
12289
|
}
|
|
@@ -12029,12 +12293,15 @@ async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames)
|
|
|
12029
12293
|
const entries = await fs14.readdir(skillsHome, { withFileTypes: true });
|
|
12030
12294
|
const removed = [];
|
|
12031
12295
|
for (const entry of entries) {
|
|
12032
|
-
if (allowed.has(entry.name))
|
|
12296
|
+
if (allowed.has(entry.name))
|
|
12297
|
+
continue;
|
|
12033
12298
|
const target = path16.join(skillsHome, entry.name);
|
|
12034
12299
|
const existing = await fs14.lstat(target).catch(() => null);
|
|
12035
|
-
if (!existing?.isSymbolicLink())
|
|
12300
|
+
if (!existing?.isSymbolicLink())
|
|
12301
|
+
continue;
|
|
12036
12302
|
const linkedPath = await fs14.readlink(target).catch(() => null);
|
|
12037
|
-
if (!linkedPath)
|
|
12303
|
+
if (!linkedPath)
|
|
12304
|
+
continue;
|
|
12038
12305
|
const resolvedLinkedPath = path16.isAbsolute(linkedPath) ? linkedPath : path16.resolve(path16.dirname(target), linkedPath);
|
|
12039
12306
|
if (!isMaintainerOnlySkillTarget(linkedPath) && !isMaintainerOnlySkillTarget(resolvedLinkedPath)) {
|
|
12040
12307
|
continue;
|
|
@@ -12080,7 +12347,8 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool) {
|
|
|
12080
12347
|
entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name)
|
|
12081
12348
|
);
|
|
12082
12349
|
for (const entry of entries) {
|
|
12083
|
-
if (!entry.isDirectory())
|
|
12350
|
+
if (!entry.isDirectory())
|
|
12351
|
+
continue;
|
|
12084
12352
|
const source = path17.join(sourceSkillsDir, entry.name);
|
|
12085
12353
|
const target = path17.join(targetSkillsDir, entry.name);
|
|
12086
12354
|
const existing = await fs15.lstat(target).catch(() => null);
|
|
@@ -12277,7 +12545,8 @@ function registerApprovalCommands(program2) {
|
|
|
12277
12545
|
try {
|
|
12278
12546
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12279
12547
|
const params = new URLSearchParams();
|
|
12280
|
-
if (opts.status)
|
|
12548
|
+
if (opts.status)
|
|
12549
|
+
params.set("status", opts.status);
|
|
12281
12550
|
const query = params.toString();
|
|
12282
12551
|
const rows = await ctx.api.get(
|
|
12283
12552
|
`/api/companies/${ctx.companyId}/approvals${query ? `?${query}` : ""}`
|
|
@@ -12411,7 +12680,8 @@ function registerApprovalCommands(program2) {
|
|
|
12411
12680
|
);
|
|
12412
12681
|
}
|
|
12413
12682
|
function parseCsv2(value) {
|
|
12414
|
-
if (!value)
|
|
12683
|
+
if (!value)
|
|
12684
|
+
return void 0;
|
|
12415
12685
|
const rows = value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
12416
12686
|
return rows.length > 0 ? rows : void 0;
|
|
12417
12687
|
}
|
|
@@ -12435,9 +12705,12 @@ function registerActivityCommands(program2) {
|
|
|
12435
12705
|
try {
|
|
12436
12706
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12437
12707
|
const params = new URLSearchParams();
|
|
12438
|
-
if (opts.agentId)
|
|
12439
|
-
|
|
12440
|
-
if (opts.
|
|
12708
|
+
if (opts.agentId)
|
|
12709
|
+
params.set("agentId", opts.agentId);
|
|
12710
|
+
if (opts.entityType)
|
|
12711
|
+
params.set("entityType", opts.entityType);
|
|
12712
|
+
if (opts.entityId)
|
|
12713
|
+
params.set("entityId", opts.entityId);
|
|
12441
12714
|
const query = params.toString();
|
|
12442
12715
|
const path36 = `/api/companies/${ctx.companyId}/activity${query ? `?${query}` : ""}`;
|
|
12443
12716
|
const rows = await ctx.api.get(path36) ?? [];
|
|
@@ -12492,7 +12765,8 @@ init_home();
|
|
|
12492
12765
|
import path18 from "node:path";
|
|
12493
12766
|
function applyDataDirOverride(options, support = {}) {
|
|
12494
12767
|
const rawDataDir = options.dataDir?.trim();
|
|
12495
|
-
if (!rawDataDir)
|
|
12768
|
+
if (!rawDataDir)
|
|
12769
|
+
return null;
|
|
12496
12770
|
const resolvedDataDir = path18.resolve(expandHomePrefix(rawDataDir));
|
|
12497
12771
|
process.env.PAPERCLIP_HOME = resolvedDataDir;
|
|
12498
12772
|
if (support.hasConfigOption) {
|
|
@@ -12529,7 +12803,8 @@ function resolveGtmStatePath() {
|
|
|
12529
12803
|
}
|
|
12530
12804
|
function readState() {
|
|
12531
12805
|
const filePath = resolveGtmStatePath();
|
|
12532
|
-
if (!fs16.existsSync(filePath))
|
|
12806
|
+
if (!fs16.existsSync(filePath))
|
|
12807
|
+
return createDefaultGtmState();
|
|
12533
12808
|
return coerceGtmState(JSON.parse(fs16.readFileSync(filePath, "utf-8")));
|
|
12534
12809
|
}
|
|
12535
12810
|
function writeState(state) {
|
|
@@ -12573,17 +12848,22 @@ function printJsonOrMessage(payload, json, message) {
|
|
|
12573
12848
|
console.log(JSON.stringify(payload, null, 2));
|
|
12574
12849
|
return;
|
|
12575
12850
|
}
|
|
12576
|
-
if (message)
|
|
12851
|
+
if (message)
|
|
12852
|
+
console.log(pc23.green(message));
|
|
12577
12853
|
console.log(payload);
|
|
12578
12854
|
}
|
|
12579
12855
|
function registerGtmCommands(program2) {
|
|
12580
12856
|
const gtm = program2.command("gtm").description("Growthub GTM substrate on the local machine");
|
|
12581
12857
|
gtm.command("init").description("Initialize the local GTM substrate state").option("--account-email <email>", "Growthub account email").option("--workspace <name>", "Workspace label").option("--gh-app-path <path>", "Path to gh-app").option("--internal-socials-path <path>", "Reference UI path for internal-socials").option("--local-sdr-path <path>", "Reference/local runner path for growthub-sdr").option("--json", "Output raw JSON").action((opts) => {
|
|
12582
12858
|
const state = createDefaultGtmState();
|
|
12583
|
-
if (opts.accountEmail)
|
|
12584
|
-
|
|
12585
|
-
if (opts.
|
|
12586
|
-
|
|
12859
|
+
if (opts.accountEmail)
|
|
12860
|
+
state.profile.growthubAccountEmail = opts.accountEmail.trim();
|
|
12861
|
+
if (opts.workspace)
|
|
12862
|
+
state.profile.workspaceName = opts.workspace.trim();
|
|
12863
|
+
if (opts.ghAppPath)
|
|
12864
|
+
state.profile.ghAppPath = opts.ghAppPath.trim();
|
|
12865
|
+
if (opts.internalSocialsPath)
|
|
12866
|
+
state.workflow.referenceInterfaces.internalSocialsPath = opts.internalSocialsPath.trim();
|
|
12587
12867
|
if (opts.localSdrPath) {
|
|
12588
12868
|
state.workflow.referenceInterfaces.localSdrPath = opts.localSdrPath.trim();
|
|
12589
12869
|
state.workflow.runnerPath = path19.resolve(opts.localSdrPath.trim(), "sdr-bot.mjs");
|
|
@@ -12758,10 +13038,12 @@ function resolveWorktreeLocalPaths(opts) {
|
|
|
12758
13038
|
};
|
|
12759
13039
|
}
|
|
12760
13040
|
function rewriteLocalUrlPort(rawUrl, port) {
|
|
12761
|
-
if (!rawUrl)
|
|
13041
|
+
if (!rawUrl)
|
|
13042
|
+
return void 0;
|
|
12762
13043
|
try {
|
|
12763
13044
|
const parsed = new URL(rawUrl);
|
|
12764
|
-
if (!isLoopbackHost2(parsed.hostname))
|
|
13045
|
+
if (!isLoopbackHost2(parsed.hostname))
|
|
13046
|
+
return rawUrl;
|
|
12765
13047
|
parsed.port = String(port);
|
|
12766
13048
|
return parsed.toString();
|
|
12767
13049
|
} catch {
|
|
@@ -12916,7 +13198,8 @@ function resolveGitWorktreeAddArgs(input) {
|
|
|
12916
13198
|
return ["worktree", "add", "-b", input.branchName, input.targetPath, commitish];
|
|
12917
13199
|
}
|
|
12918
13200
|
function readPidFilePort(postmasterPidFile) {
|
|
12919
|
-
if (!existsSync2(postmasterPidFile))
|
|
13201
|
+
if (!existsSync2(postmasterPidFile))
|
|
13202
|
+
return null;
|
|
12920
13203
|
try {
|
|
12921
13204
|
const lines = readFileSync(postmasterPidFile, "utf8").split("\n");
|
|
12922
13205
|
const port = Number(lines[3]?.trim());
|
|
@@ -12926,10 +13209,12 @@ function readPidFilePort(postmasterPidFile) {
|
|
|
12926
13209
|
}
|
|
12927
13210
|
}
|
|
12928
13211
|
function readRunningPostmasterPid(postmasterPidFile) {
|
|
12929
|
-
if (!existsSync2(postmasterPidFile))
|
|
13212
|
+
if (!existsSync2(postmasterPidFile))
|
|
13213
|
+
return null;
|
|
12930
13214
|
try {
|
|
12931
13215
|
const pid = Number(readFileSync(postmasterPidFile, "utf8").split("\n")[0]?.trim());
|
|
12932
|
-
if (!Number.isInteger(pid) || pid <= 0)
|
|
13216
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
13217
|
+
return null;
|
|
12933
13218
|
process.kill(pid, 0);
|
|
12934
13219
|
return pid;
|
|
12935
13220
|
} catch {
|
|
@@ -12998,9 +13283,11 @@ function detectGitWorkspaceInfo(cwd) {
|
|
|
12998
13283
|
}
|
|
12999
13284
|
}
|
|
13000
13285
|
function copyDirectoryContents(sourceDir, targetDir) {
|
|
13001
|
-
if (!existsSync2(sourceDir))
|
|
13286
|
+
if (!existsSync2(sourceDir))
|
|
13287
|
+
return false;
|
|
13002
13288
|
const entries = readdirSync2(sourceDir, { withFileTypes: true });
|
|
13003
|
-
if (entries.length === 0)
|
|
13289
|
+
if (entries.length === 0)
|
|
13290
|
+
return false;
|
|
13004
13291
|
mkdirSync2(targetDir, { recursive: true });
|
|
13005
13292
|
let copied = false;
|
|
13006
13293
|
for (const entry of entries) {
|
|
@@ -13029,7 +13316,8 @@ function copyDirectoryContents(sourceDir, targetDir) {
|
|
|
13029
13316
|
}
|
|
13030
13317
|
function copyGitHooksToWorktreeGitDir(cwd) {
|
|
13031
13318
|
const workspace = detectGitWorkspaceInfo(cwd);
|
|
13032
|
-
if (!workspace)
|
|
13319
|
+
if (!workspace)
|
|
13320
|
+
return null;
|
|
13033
13321
|
const sourceHooksPath = workspace.hooksPath;
|
|
13034
13322
|
const targetHooksPath = path21.resolve(workspace.gitDir, "hooks");
|
|
13035
13323
|
if (sourceHooksPath === targetHooksPath) {
|
|
@@ -13060,7 +13348,8 @@ function rebindWorkspaceCwd(input) {
|
|
|
13060
13348
|
}
|
|
13061
13349
|
async function rebindSeededProjectWorkspaces(input) {
|
|
13062
13350
|
const targetRepo = detectGitWorkspaceInfo(input.currentCwd);
|
|
13063
|
-
if (!targetRepo)
|
|
13351
|
+
if (!targetRepo)
|
|
13352
|
+
return [];
|
|
13064
13353
|
const db = createDb(input.targetConnectionString);
|
|
13065
13354
|
const closableDb = db;
|
|
13066
13355
|
try {
|
|
@@ -13072,19 +13361,25 @@ async function rebindSeededProjectWorkspaces(input) {
|
|
|
13072
13361
|
const rebound = [];
|
|
13073
13362
|
for (const row of rows) {
|
|
13074
13363
|
const workspaceCwd = nonEmpty2(row.cwd);
|
|
13075
|
-
if (!workspaceCwd)
|
|
13364
|
+
if (!workspaceCwd)
|
|
13365
|
+
continue;
|
|
13076
13366
|
const sourceRepo = detectGitWorkspaceInfo(workspaceCwd);
|
|
13077
|
-
if (!sourceRepo)
|
|
13078
|
-
|
|
13367
|
+
if (!sourceRepo)
|
|
13368
|
+
continue;
|
|
13369
|
+
if (sourceRepo.commonDir !== targetRepo.commonDir)
|
|
13370
|
+
continue;
|
|
13079
13371
|
const reboundCwd = rebindWorkspaceCwd({
|
|
13080
13372
|
sourceRepoRoot: sourceRepo.root,
|
|
13081
13373
|
targetRepoRoot: targetRepo.root,
|
|
13082
13374
|
workspaceCwd
|
|
13083
13375
|
});
|
|
13084
|
-
if (!reboundCwd)
|
|
13376
|
+
if (!reboundCwd)
|
|
13377
|
+
continue;
|
|
13085
13378
|
const normalizedCurrent = path21.resolve(workspaceCwd);
|
|
13086
|
-
if (reboundCwd === normalizedCurrent)
|
|
13087
|
-
|
|
13379
|
+
if (reboundCwd === normalizedCurrent)
|
|
13380
|
+
continue;
|
|
13381
|
+
if (!existsSync2(reboundCwd))
|
|
13382
|
+
continue;
|
|
13088
13383
|
await db.update(projectWorkspaces).set({
|
|
13089
13384
|
cwd: reboundCwd,
|
|
13090
13385
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -13101,8 +13396,10 @@ async function rebindSeededProjectWorkspaces(input) {
|
|
|
13101
13396
|
}
|
|
13102
13397
|
}
|
|
13103
13398
|
function resolveSourceConfigPath(opts) {
|
|
13104
|
-
if (opts.sourceConfigPathOverride)
|
|
13105
|
-
|
|
13399
|
+
if (opts.sourceConfigPathOverride)
|
|
13400
|
+
return path21.resolve(opts.sourceConfigPathOverride);
|
|
13401
|
+
if (opts.fromConfig)
|
|
13402
|
+
return path21.resolve(opts.fromConfig);
|
|
13106
13403
|
if (!opts.fromDataDir && !opts.fromInstance) {
|
|
13107
13404
|
return resolveConfigPath();
|
|
13108
13405
|
}
|
|
@@ -13586,7 +13883,8 @@ async function worktreeCleanupCommand(nameArg, opts) {
|
|
|
13586
13883
|
spinner10.start(`Removing git worktree at ${linkedWorktree.worktree}...`);
|
|
13587
13884
|
try {
|
|
13588
13885
|
const removeArgs = ["worktree", "remove", linkedWorktree.worktree];
|
|
13589
|
-
if (opts.force)
|
|
13886
|
+
if (opts.force)
|
|
13887
|
+
removeArgs.push("--force");
|
|
13590
13888
|
execFileSync("git", removeArgs, {
|
|
13591
13889
|
cwd: sourceCwd,
|
|
13592
13890
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -13668,8 +13966,10 @@ function registerWorktreeCommands(program2) {
|
|
|
13668
13966
|
import path22 from "node:path";
|
|
13669
13967
|
import pc25 from "picocolors";
|
|
13670
13968
|
function resolvePackageArg(packageArg, isLocal) {
|
|
13671
|
-
if (!isLocal)
|
|
13672
|
-
|
|
13969
|
+
if (!isLocal)
|
|
13970
|
+
return packageArg;
|
|
13971
|
+
if (path22.isAbsolute(packageArg))
|
|
13972
|
+
return packageArg;
|
|
13673
13973
|
if (packageArg.startsWith("~")) {
|
|
13674
13974
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
13675
13975
|
return path22.resolve(home, packageArg.slice(1).replace(/^[\\/]/, ""));
|
|
@@ -13976,7 +14276,8 @@ function isBundleManifestV2(manifest) {
|
|
|
13976
14276
|
return manifest.schemaVersion === 2;
|
|
13977
14277
|
}
|
|
13978
14278
|
function normalizeManifest(manifest) {
|
|
13979
|
-
if (isManifestV2(manifest))
|
|
14279
|
+
if (isManifestV2(manifest))
|
|
14280
|
+
return manifest;
|
|
13980
14281
|
return {
|
|
13981
14282
|
schemaVersion: 2,
|
|
13982
14283
|
kit: {
|
|
@@ -13998,7 +14299,8 @@ function normalizeManifest(manifest) {
|
|
|
13998
14299
|
};
|
|
13999
14300
|
}
|
|
14000
14301
|
function normalizeBundleManifest(manifest) {
|
|
14001
|
-
if (isBundleManifestV2(manifest))
|
|
14302
|
+
if (isBundleManifestV2(manifest))
|
|
14303
|
+
return manifest;
|
|
14002
14304
|
return {
|
|
14003
14305
|
schemaVersion: 2,
|
|
14004
14306
|
bundle: manifest.bundle,
|
|
@@ -14033,7 +14335,8 @@ function resolveBundledKitAssetsRoot() {
|
|
|
14033
14335
|
path23.resolve(moduleDir, "../assets/worker-kits")
|
|
14034
14336
|
];
|
|
14035
14337
|
for (const candidate of candidates) {
|
|
14036
|
-
if (fs17.existsSync(candidate))
|
|
14338
|
+
if (fs17.existsSync(candidate))
|
|
14339
|
+
return candidate;
|
|
14037
14340
|
}
|
|
14038
14341
|
throw new Error("Could not locate bundled worker kit assets.");
|
|
14039
14342
|
}
|
|
@@ -14245,7 +14548,8 @@ function validateKitDirectory(kitPath) {
|
|
|
14245
14548
|
errors.push({ field: "frozenAssetPaths", message: "Missing required 'frozenAssetPaths' array" });
|
|
14246
14549
|
} else {
|
|
14247
14550
|
for (const assetPath of frozenAssets) {
|
|
14248
|
-
if (typeof assetPath !== "string")
|
|
14551
|
+
if (typeof assetPath !== "string")
|
|
14552
|
+
continue;
|
|
14249
14553
|
const fullPath = path23.resolve(kitPath, assetPath);
|
|
14250
14554
|
if (!fs17.existsSync(fullPath)) {
|
|
14251
14555
|
errors.push({ field: "frozenAssetPaths", message: `Frozen asset not found: ${assetPath}` });
|
|
@@ -14264,7 +14568,8 @@ function validateKitDirectory(kitPath) {
|
|
|
14264
14568
|
errors.push({ field: "outputStandard.requiredPaths", message: "Missing required 'outputStandard.requiredPaths' array" });
|
|
14265
14569
|
} else {
|
|
14266
14570
|
for (const reqPath of requiredPaths) {
|
|
14267
|
-
if (typeof reqPath !== "string")
|
|
14571
|
+
if (typeof reqPath !== "string")
|
|
14572
|
+
continue;
|
|
14268
14573
|
const fullPath = path23.resolve(kitPath, reqPath);
|
|
14269
14574
|
if (!fs17.existsSync(fullPath)) {
|
|
14270
14575
|
errors.push({ field: "outputStandard.requiredPaths", message: `Required output path not found: ${reqPath}` });
|
|
@@ -14326,15 +14631,19 @@ function loadResolvedBundledKit(assetRoot, catalogEntry) {
|
|
|
14326
14631
|
function fuzzyResolveKitId(input) {
|
|
14327
14632
|
const needle = input.toLowerCase().trim();
|
|
14328
14633
|
const exact = BUNDLED_KIT_CATALOG.find((e) => e.id === needle);
|
|
14329
|
-
if (exact)
|
|
14634
|
+
if (exact)
|
|
14635
|
+
return exact.id;
|
|
14330
14636
|
const suffix = BUNDLED_KIT_CATALOG.find((e) => e.id.endsWith(needle));
|
|
14331
|
-
if (suffix)
|
|
14637
|
+
if (suffix)
|
|
14638
|
+
return suffix.id;
|
|
14332
14639
|
const contains = BUNDLED_KIT_CATALOG.find((e) => e.id.includes(needle));
|
|
14333
|
-
if (contains)
|
|
14640
|
+
if (contains)
|
|
14641
|
+
return contains.id;
|
|
14334
14642
|
const tokens = needle.split(/[-\s]+/).filter((t) => t.length > 2);
|
|
14335
14643
|
for (const token of tokens) {
|
|
14336
14644
|
const tokenMatch = BUNDLED_KIT_CATALOG.find((e) => e.id.includes(token));
|
|
14337
|
-
if (tokenMatch)
|
|
14645
|
+
if (tokenMatch)
|
|
14646
|
+
return tokenMatch.id;
|
|
14338
14647
|
}
|
|
14339
14648
|
return null;
|
|
14340
14649
|
}
|
|
@@ -14574,8 +14883,10 @@ var TYPE_CONFIG = {
|
|
|
14574
14883
|
ops: { color: pc26.yellow, emoji: "\u2699\uFE0F ", label: "Ops" }
|
|
14575
14884
|
};
|
|
14576
14885
|
function displayTypeForFamily(family) {
|
|
14577
|
-
if (family === "workflow" || family === "operator")
|
|
14578
|
-
|
|
14886
|
+
if (family === "workflow" || family === "operator")
|
|
14887
|
+
return "specialized_agents";
|
|
14888
|
+
if (family === "studio" || family === "ops")
|
|
14889
|
+
return family;
|
|
14579
14890
|
return family;
|
|
14580
14891
|
}
|
|
14581
14892
|
function typeColor(family, text63) {
|
|
@@ -14585,11 +14896,13 @@ function typeColor(family, text63) {
|
|
|
14585
14896
|
function typeBadge(family) {
|
|
14586
14897
|
const type = displayTypeForFamily(family);
|
|
14587
14898
|
const cfg = TYPE_CONFIG[type];
|
|
14588
|
-
if (!cfg)
|
|
14899
|
+
if (!cfg)
|
|
14900
|
+
return String(type);
|
|
14589
14901
|
return cfg.color(`${cfg.emoji} ${cfg.label}`);
|
|
14590
14902
|
}
|
|
14591
14903
|
function truncate(str, max) {
|
|
14592
|
-
if (str.length <= max)
|
|
14904
|
+
if (str.length <= max)
|
|
14905
|
+
return str;
|
|
14593
14906
|
return str.slice(0, max - 1) + "\u2026";
|
|
14594
14907
|
}
|
|
14595
14908
|
function displayKitName(name) {
|
|
@@ -14621,7 +14934,8 @@ function folderOpenLabel(folderPath) {
|
|
|
14621
14934
|
return terminalLink(label, href);
|
|
14622
14935
|
}
|
|
14623
14936
|
function renderProgressBar(progress) {
|
|
14624
|
-
if (!process.stdout.isTTY)
|
|
14937
|
+
if (!process.stdout.isTTY)
|
|
14938
|
+
return;
|
|
14625
14939
|
const width = 24;
|
|
14626
14940
|
const filled = Math.max(0, Math.min(width, Math.round(progress.percent / 100 * width)));
|
|
14627
14941
|
const bar = `${"=".repeat(filled)}${"-".repeat(width - filled)}`;
|
|
@@ -14645,9 +14959,12 @@ function printKitCard(item) {
|
|
|
14645
14959
|
]));
|
|
14646
14960
|
}
|
|
14647
14961
|
function getActionLabel(action) {
|
|
14648
|
-
if (action === "download")
|
|
14649
|
-
|
|
14650
|
-
if (action === "
|
|
14962
|
+
if (action === "download")
|
|
14963
|
+
return "download";
|
|
14964
|
+
if (action === "inspect")
|
|
14965
|
+
return "inspect";
|
|
14966
|
+
if (action === "copy-id")
|
|
14967
|
+
return "print id";
|
|
14651
14968
|
return action;
|
|
14652
14969
|
}
|
|
14653
14970
|
async function confirmKitActions(input) {
|
|
@@ -14733,7 +15050,8 @@ async function runInteractivePicker(opts) {
|
|
|
14733
15050
|
p17.cancel("Cancelled.");
|
|
14734
15051
|
process.exit(0);
|
|
14735
15052
|
}
|
|
14736
|
-
if (typeChoice === "__back_to_hub")
|
|
15053
|
+
if (typeChoice === "__back_to_hub")
|
|
15054
|
+
return "back";
|
|
14737
15055
|
const filtered = typeChoice === "all" ? kits : kits.filter((k) => displayTypeForFamily(k.family) === typeChoice);
|
|
14738
15056
|
const showTypeBadgeInKitChoices = typeChoice === "all";
|
|
14739
15057
|
if (filtered.length === 0) {
|
|
@@ -14756,7 +15074,8 @@ async function runInteractivePicker(opts) {
|
|
|
14756
15074
|
p17.cancel("Cancelled.");
|
|
14757
15075
|
process.exit(0);
|
|
14758
15076
|
}
|
|
14759
|
-
if (kitChoice === "__back_to_type")
|
|
15077
|
+
if (kitChoice === "__back_to_type")
|
|
15078
|
+
break;
|
|
14760
15079
|
const selected = filtered.find((kit) => kit.id === kitChoice);
|
|
14761
15080
|
if (!selected) {
|
|
14762
15081
|
p17.cancel("Selected kit was not found.");
|
|
@@ -14774,7 +15093,8 @@ async function runInteractivePicker(opts) {
|
|
|
14774
15093
|
p17.cancel("Cancelled.");
|
|
14775
15094
|
process.exit(0);
|
|
14776
15095
|
}
|
|
14777
|
-
if (nextStep === "back_to_kits")
|
|
15096
|
+
if (nextStep === "back_to_kits")
|
|
15097
|
+
continue;
|
|
14778
15098
|
while (true) {
|
|
14779
15099
|
const action = await p17.select({
|
|
14780
15100
|
message: "What would you like to do?",
|
|
@@ -14789,7 +15109,8 @@ async function runInteractivePicker(opts) {
|
|
|
14789
15109
|
p17.cancel("Cancelled.");
|
|
14790
15110
|
process.exit(0);
|
|
14791
15111
|
}
|
|
14792
|
-
if (action === "back_to_kits")
|
|
15112
|
+
if (action === "back_to_kits")
|
|
15113
|
+
break;
|
|
14793
15114
|
const confirmed = await confirmKitActions({
|
|
14794
15115
|
kits: [selected],
|
|
14795
15116
|
actions: [action]
|
|
@@ -14806,7 +15127,8 @@ async function runInteractivePicker(opts) {
|
|
|
14806
15127
|
p17.cancel("Cancelled.");
|
|
14807
15128
|
process.exit(0);
|
|
14808
15129
|
}
|
|
14809
|
-
if (reviewChoice === "back_to_kits")
|
|
15130
|
+
if (reviewChoice === "back_to_kits")
|
|
15131
|
+
break;
|
|
14810
15132
|
continue;
|
|
14811
15133
|
}
|
|
14812
15134
|
if (action === "copy-id") {
|
|
@@ -14894,7 +15216,8 @@ function runInspect(kitId, outDir) {
|
|
|
14894
15216
|
}
|
|
14895
15217
|
console.log(hr());
|
|
14896
15218
|
console.log(pc26.bold(" Required Paths:"));
|
|
14897
|
-
for (const rp of info.requiredPaths)
|
|
15219
|
+
for (const rp of info.requiredPaths)
|
|
15220
|
+
console.log(" " + pc26.dim("\xB7") + " " + rp);
|
|
14898
15221
|
console.log("");
|
|
14899
15222
|
}
|
|
14900
15223
|
function registerKitCommands(program2) {
|
|
@@ -15306,7 +15629,8 @@ function resolveSharedTemplatesRoot() {
|
|
|
15306
15629
|
path25.resolve(moduleDir, "../../assets/shared-templates"),
|
|
15307
15630
|
path25.resolve(moduleDir, "../assets/shared-templates")
|
|
15308
15631
|
]) {
|
|
15309
|
-
if (fs18.existsSync(candidate))
|
|
15632
|
+
if (fs18.existsSync(candidate))
|
|
15633
|
+
return candidate;
|
|
15310
15634
|
}
|
|
15311
15635
|
throw new Error("Shared template assets not found at cli/assets/shared-templates/");
|
|
15312
15636
|
}
|
|
@@ -15316,16 +15640,20 @@ function resolveSlug(input) {
|
|
|
15316
15640
|
const tokens = needle.split(/[-_/\s]+/).filter((t) => t.length > 2);
|
|
15317
15641
|
for (const token of tokens) {
|
|
15318
15642
|
const match = TEMPLATE_CATALOG.find((a) => a.slug.includes(token) || a.id.includes(token));
|
|
15319
|
-
if (match)
|
|
15643
|
+
if (match)
|
|
15644
|
+
return match;
|
|
15320
15645
|
}
|
|
15321
15646
|
return null;
|
|
15322
15647
|
})();
|
|
15323
15648
|
}
|
|
15324
15649
|
function listArtifacts(filter = {}) {
|
|
15325
15650
|
let results = [...TEMPLATE_CATALOG];
|
|
15326
|
-
if (filter.type)
|
|
15327
|
-
|
|
15328
|
-
if (filter.
|
|
15651
|
+
if (filter.type)
|
|
15652
|
+
results = results.filter((a) => a.type === filter.type);
|
|
15653
|
+
if (filter.subtype)
|
|
15654
|
+
results = results.filter((a) => a.type === "scene-module" && a.subtype === filter.subtype);
|
|
15655
|
+
if (filter.family)
|
|
15656
|
+
results = results.filter((a) => a.family === filter.family);
|
|
15329
15657
|
if (filter.format) {
|
|
15330
15658
|
const fmt = filter.format.toLowerCase();
|
|
15331
15659
|
results = results.filter(
|
|
@@ -15339,10 +15667,12 @@ function listArtifacts(filter = {}) {
|
|
|
15339
15667
|
}
|
|
15340
15668
|
function getArtifact(slugOrId) {
|
|
15341
15669
|
const artifact = resolveSlug(slugOrId);
|
|
15342
|
-
if (!artifact)
|
|
15670
|
+
if (!artifact)
|
|
15671
|
+
throw new Error(`Unknown template '${slugOrId}'. Run 'growthub template list' to browse.`);
|
|
15343
15672
|
const root = resolveSharedTemplatesRoot();
|
|
15344
15673
|
const absolutePath = path25.resolve(root, artifact.path);
|
|
15345
|
-
if (!fs18.existsSync(absolutePath))
|
|
15674
|
+
if (!fs18.existsSync(absolutePath))
|
|
15675
|
+
throw new Error(`Template file missing: ${absolutePath}`);
|
|
15346
15676
|
return { artifact, content: fs18.readFileSync(absolutePath, "utf8"), absolutePath };
|
|
15347
15677
|
}
|
|
15348
15678
|
function copyArtifact(slugOrId, destDir) {
|
|
@@ -15360,25 +15690,29 @@ var GROUP_META = {
|
|
|
15360
15690
|
"scene-modules/cta": { label: "Scene Modules \u2014 CTA", description: "Final scene \u2014 offer close, guarantee, conversion" }
|
|
15361
15691
|
};
|
|
15362
15692
|
function groupKey(a) {
|
|
15363
|
-
if (a.type === "ad-format")
|
|
15693
|
+
if (a.type === "ad-format")
|
|
15694
|
+
return "ad-formats";
|
|
15364
15695
|
return `scene-modules/${a.subtype}`;
|
|
15365
15696
|
}
|
|
15366
15697
|
function groupArtifacts(artifacts) {
|
|
15367
15698
|
const map = /* @__PURE__ */ new Map();
|
|
15368
15699
|
for (const a of artifacts) {
|
|
15369
15700
|
const key = groupKey(a);
|
|
15370
|
-
if (!map.has(key))
|
|
15701
|
+
if (!map.has(key))
|
|
15702
|
+
map.set(key, []);
|
|
15371
15703
|
map.get(key).push(a);
|
|
15372
15704
|
}
|
|
15373
15705
|
const ordered = [];
|
|
15374
15706
|
for (const key of GROUP_ORDER) {
|
|
15375
|
-
if (!map.has(key))
|
|
15707
|
+
if (!map.has(key))
|
|
15708
|
+
continue;
|
|
15376
15709
|
const items = map.get(key);
|
|
15377
15710
|
const meta = GROUP_META[key] ?? { label: key, description: "" };
|
|
15378
15711
|
ordered.push({ key, label: meta.label, description: meta.description, count: items.length, artifacts: items });
|
|
15379
15712
|
}
|
|
15380
15713
|
for (const [key, items] of map) {
|
|
15381
|
-
if (GROUP_ORDER.includes(key))
|
|
15714
|
+
if (GROUP_ORDER.includes(key))
|
|
15715
|
+
continue;
|
|
15382
15716
|
ordered.push({ key, label: key, description: "", count: items.length, artifacts: items });
|
|
15383
15717
|
}
|
|
15384
15718
|
return ordered;
|
|
@@ -15413,11 +15747,15 @@ function box2(lines) {
|
|
|
15413
15747
|
return [top, ...body, bottom].join("\n");
|
|
15414
15748
|
}
|
|
15415
15749
|
function badge(a) {
|
|
15416
|
-
if (a.type === "ad-format")
|
|
15750
|
+
if (a.type === "ad-format")
|
|
15751
|
+
return pc27.cyan("\u{1F3AC} Ad Format");
|
|
15417
15752
|
if (a.type === "scene-module") {
|
|
15418
|
-
if (a.subtype === "hook")
|
|
15419
|
-
|
|
15420
|
-
if (a.subtype === "
|
|
15753
|
+
if (a.subtype === "hook")
|
|
15754
|
+
return pc27.yellow("\u{1FA9D} Hook");
|
|
15755
|
+
if (a.subtype === "body")
|
|
15756
|
+
return pc27.blue("\u{1F9E9} Body");
|
|
15757
|
+
if (a.subtype === "cta")
|
|
15758
|
+
return pc27.green("\u{1F3AF} CTA");
|
|
15421
15759
|
}
|
|
15422
15760
|
return pc27.magenta("\u{1F9E9} Module");
|
|
15423
15761
|
}
|
|
@@ -15523,7 +15861,8 @@ async function runTemplatePicker(opts) {
|
|
|
15523
15861
|
p18.cancel("Cancelled.");
|
|
15524
15862
|
process.exit(0);
|
|
15525
15863
|
}
|
|
15526
|
-
if (familyChoice === "__back_to_hub")
|
|
15864
|
+
if (familyChoice === "__back_to_hub")
|
|
15865
|
+
return "back";
|
|
15527
15866
|
const filteredArtifacts = artifacts.filter((artifact) => artifact.family === familyChoice);
|
|
15528
15867
|
const groups = groupArtifacts(filteredArtifacts);
|
|
15529
15868
|
const groupChoice = await p18.select({
|
|
@@ -15633,7 +15972,8 @@ Any agent or kit resolves them by slug.
|
|
|
15633
15972
|
}
|
|
15634
15973
|
filter.subtype = sub;
|
|
15635
15974
|
}
|
|
15636
|
-
if (opts.format)
|
|
15975
|
+
if (opts.format)
|
|
15976
|
+
filter.format = opts.format;
|
|
15637
15977
|
if (opts.json) {
|
|
15638
15978
|
console.log(JSON.stringify(listArtifacts(filter), null, 2));
|
|
15639
15979
|
return;
|
|
@@ -15709,7 +16049,8 @@ var NoActiveSessionError = class extends Error {
|
|
|
15709
16049
|
};
|
|
15710
16050
|
function requireSession() {
|
|
15711
16051
|
const session = readSession();
|
|
15712
|
-
if (!session)
|
|
16052
|
+
if (!session)
|
|
16053
|
+
throw new NoActiveSessionError();
|
|
15713
16054
|
if (isSessionExpired(session)) {
|
|
15714
16055
|
throw new HostedExecutionError(
|
|
15715
16056
|
401,
|
|
@@ -15730,7 +16071,8 @@ function isUnavailable(err) {
|
|
|
15730
16071
|
}
|
|
15731
16072
|
function isPlaceholderString(value) {
|
|
15732
16073
|
const normalized = value.trim().toLowerCase();
|
|
15733
|
-
if (!normalized)
|
|
16074
|
+
if (!normalized)
|
|
16075
|
+
return true;
|
|
15734
16076
|
return normalized.startsWith("enter ") || normalized.startsWith("select ") || normalized === "placeholder";
|
|
15735
16077
|
}
|
|
15736
16078
|
function sanitizeBindingValue(value) {
|
|
@@ -15906,7 +16248,8 @@ async function executeWorkflowStream(request, session, opts) {
|
|
|
15906
16248
|
const nodeResults = /* @__PURE__ */ new Map();
|
|
15907
16249
|
while (true) {
|
|
15908
16250
|
const { value, done } = await reader.read();
|
|
15909
|
-
if (done)
|
|
16251
|
+
if (done)
|
|
16252
|
+
break;
|
|
15910
16253
|
buffer += decoder.decode(value, { stream: true });
|
|
15911
16254
|
let newlineIndex = buffer.indexOf("\n");
|
|
15912
16255
|
while (newlineIndex >= 0) {
|
|
@@ -15965,7 +16308,8 @@ async function executeWorkflowStream(request, session, opts) {
|
|
|
15965
16308
|
};
|
|
15966
16309
|
}
|
|
15967
16310
|
function applyWorkflowEvent(event, nodeResults, request) {
|
|
15968
|
-
if (!event.nodeId)
|
|
16311
|
+
if (!event.nodeId)
|
|
16312
|
+
return;
|
|
15969
16313
|
const current = nodeResults.get(event.nodeId);
|
|
15970
16314
|
const next = current ?? {
|
|
15971
16315
|
nodeId: event.nodeId,
|
|
@@ -15986,13 +16330,16 @@ function applyWorkflowEvent(event, nodeResults, request) {
|
|
|
15986
16330
|
function collectArtifacts(executionLog) {
|
|
15987
16331
|
const artifacts = [];
|
|
15988
16332
|
for (const entry of executionLog) {
|
|
15989
|
-
if (entry.type !== "cmsNode" || typeof entry.nodeId !== "string")
|
|
16333
|
+
if (entry.type !== "cmsNode" || typeof entry.nodeId !== "string")
|
|
16334
|
+
continue;
|
|
15990
16335
|
const output = entry.output;
|
|
15991
|
-
if (typeof output !== "object" || output === null)
|
|
16336
|
+
if (typeof output !== "object" || output === null)
|
|
16337
|
+
continue;
|
|
15992
16338
|
const record = output;
|
|
15993
16339
|
const images = Array.isArray(record.images) ? record.images : [];
|
|
15994
16340
|
for (const image of images) {
|
|
15995
|
-
if (!image || typeof image !== "object")
|
|
16341
|
+
if (!image || typeof image !== "object")
|
|
16342
|
+
continue;
|
|
15996
16343
|
const imageRecord = image;
|
|
15997
16344
|
const storagePath = typeof imageRecord.storage_path === "string" ? imageRecord.storage_path : void 0;
|
|
15998
16345
|
artifacts.push({
|
|
@@ -16006,7 +16353,8 @@ function collectArtifacts(executionLog) {
|
|
|
16006
16353
|
}
|
|
16007
16354
|
const slides = Array.isArray(record.slides) ? record.slides : [];
|
|
16008
16355
|
for (const slide of slides) {
|
|
16009
|
-
if (!slide || typeof slide !== "object")
|
|
16356
|
+
if (!slide || typeof slide !== "object")
|
|
16357
|
+
continue;
|
|
16010
16358
|
const slideRecord = slide;
|
|
16011
16359
|
const storagePath = typeof slideRecord.storage_path === "string" ? slideRecord.storage_path : void 0;
|
|
16012
16360
|
artifacts.push({
|
|
@@ -16040,14 +16388,18 @@ function summarizeExecution(executionLog) {
|
|
|
16040
16388
|
workflowRunId = entry.workflowRunId;
|
|
16041
16389
|
}
|
|
16042
16390
|
const output = entry.output;
|
|
16043
|
-
if (typeof output !== "object" || output === null)
|
|
16391
|
+
if (typeof output !== "object" || output === null)
|
|
16392
|
+
continue;
|
|
16044
16393
|
const record = output;
|
|
16045
16394
|
if (!outputText && typeof record.text === "string" && record.text.trim().length > 0) {
|
|
16046
16395
|
outputText = record.text.trim();
|
|
16047
16396
|
}
|
|
16048
|
-
if (Array.isArray(record.images))
|
|
16049
|
-
|
|
16050
|
-
if (Array.isArray(record.
|
|
16397
|
+
if (Array.isArray(record.images))
|
|
16398
|
+
imageCount += record.images.length;
|
|
16399
|
+
if (Array.isArray(record.slides))
|
|
16400
|
+
slideCount += record.slides.length;
|
|
16401
|
+
if (Array.isArray(record.videos))
|
|
16402
|
+
videoCount += record.videos.length;
|
|
16051
16403
|
}
|
|
16052
16404
|
return {
|
|
16053
16405
|
...outputText ? { outputText } : {},
|
|
@@ -16228,30 +16580,41 @@ function toCapabilityNode(record) {
|
|
|
16228
16580
|
}
|
|
16229
16581
|
function inferFamilyFromSlug(slug) {
|
|
16230
16582
|
const normalized = slug.toLowerCase();
|
|
16231
|
-
if (normalized.includes("video"))
|
|
16232
|
-
|
|
16233
|
-
if (normalized.includes("
|
|
16234
|
-
|
|
16235
|
-
if (normalized.includes("
|
|
16236
|
-
|
|
16237
|
-
if (normalized.includes("
|
|
16583
|
+
if (normalized.includes("video"))
|
|
16584
|
+
return "video";
|
|
16585
|
+
if (normalized.includes("image"))
|
|
16586
|
+
return "image";
|
|
16587
|
+
if (normalized.includes("slide"))
|
|
16588
|
+
return "slides";
|
|
16589
|
+
if (normalized.includes("research"))
|
|
16590
|
+
return "research";
|
|
16591
|
+
if (normalized.includes("vision"))
|
|
16592
|
+
return "vision";
|
|
16593
|
+
if (normalized.includes("text") || normalized.includes("llm"))
|
|
16594
|
+
return "text";
|
|
16595
|
+
if (normalized.includes("data"))
|
|
16596
|
+
return "data";
|
|
16238
16597
|
return "ops";
|
|
16239
16598
|
}
|
|
16240
16599
|
async function deriveCapabilitiesFromHostedWorkflows() {
|
|
16241
16600
|
const session = readSession();
|
|
16242
|
-
if (!session || isSessionExpired(session))
|
|
16601
|
+
if (!session || isSessionExpired(session))
|
|
16602
|
+
return [];
|
|
16243
16603
|
const list = await listHostedWorkflows(session);
|
|
16244
16604
|
const workflows = list?.workflows ?? [];
|
|
16245
|
-
if (workflows.length === 0)
|
|
16605
|
+
if (workflows.length === 0)
|
|
16606
|
+
return [];
|
|
16246
16607
|
const bySlug = /* @__PURE__ */ new Map();
|
|
16247
16608
|
for (const workflow of workflows.slice(0, 50)) {
|
|
16248
16609
|
const detail = await fetchHostedWorkflow(session, workflow.workflowId);
|
|
16249
16610
|
const nodes = Array.isArray(detail?.latestVersion?.config?.nodes) ? detail?.latestVersion?.config?.nodes : [];
|
|
16250
16611
|
for (const node of nodes) {
|
|
16251
|
-
if (node.type !== "cmsNode")
|
|
16612
|
+
if (node.type !== "cmsNode")
|
|
16613
|
+
continue;
|
|
16252
16614
|
const data = node.data ?? {};
|
|
16253
16615
|
const slug = typeof data.slug === "string" ? data.slug : null;
|
|
16254
|
-
if (!slug)
|
|
16616
|
+
if (!slug)
|
|
16617
|
+
continue;
|
|
16255
16618
|
const inputs = data.inputs ?? {};
|
|
16256
16619
|
if (!bySlug.has(slug)) {
|
|
16257
16620
|
bySlug.set(slug, {
|
|
@@ -16275,15 +16638,21 @@ async function deriveCapabilitiesFromHostedWorkflows() {
|
|
|
16275
16638
|
return [...bySlug.values()];
|
|
16276
16639
|
}
|
|
16277
16640
|
function matchesQuery(node, query) {
|
|
16278
|
-
if (query.enabledOnly !== false && !node.enabled)
|
|
16279
|
-
|
|
16280
|
-
if (query.
|
|
16281
|
-
|
|
16282
|
-
if (query.
|
|
16641
|
+
if (query.enabledOnly !== false && !node.enabled)
|
|
16642
|
+
return false;
|
|
16643
|
+
if (query.family && node.family !== query.family)
|
|
16644
|
+
return false;
|
|
16645
|
+
if (query.executionKind && node.executionKind !== query.executionKind)
|
|
16646
|
+
return false;
|
|
16647
|
+
if (query.outputType && !node.outputTypes.includes(query.outputType))
|
|
16648
|
+
return false;
|
|
16649
|
+
if (query.slug && !node.slug.includes(query.slug))
|
|
16650
|
+
return false;
|
|
16283
16651
|
if (query.search) {
|
|
16284
16652
|
const term = query.search.toLowerCase();
|
|
16285
16653
|
const haystack = `${node.slug} ${node.displayName} ${node.description ?? ""} ${node.category}`.toLowerCase();
|
|
16286
|
-
if (!haystack.includes(term))
|
|
16654
|
+
if (!haystack.includes(term))
|
|
16655
|
+
return false;
|
|
16287
16656
|
}
|
|
16288
16657
|
return true;
|
|
16289
16658
|
}
|
|
@@ -16397,7 +16766,8 @@ function createMachineCapabilityResolver() {
|
|
|
16397
16766
|
const profile = computeEffectiveProfile();
|
|
16398
16767
|
const registry = createCmsCapabilityRegistryClient();
|
|
16399
16768
|
const capability = await registry.getCapability(slug);
|
|
16400
|
-
if (!capability)
|
|
16769
|
+
if (!capability)
|
|
16770
|
+
return null;
|
|
16401
16771
|
return resolveBinding(capability, profile);
|
|
16402
16772
|
},
|
|
16403
16773
|
getMachineContext() {
|
|
@@ -16446,13 +16816,17 @@ var FAMILY_CONFIG = {
|
|
|
16446
16816
|
};
|
|
16447
16817
|
function familyBadge(family) {
|
|
16448
16818
|
const cfg = FAMILY_CONFIG[family];
|
|
16449
|
-
if (!cfg)
|
|
16819
|
+
if (!cfg)
|
|
16820
|
+
return family;
|
|
16450
16821
|
return cfg.color(`${cfg.emoji} ${cfg.label}`);
|
|
16451
16822
|
}
|
|
16452
16823
|
function executionKindLabel(kind) {
|
|
16453
|
-
if (kind === "hosted-execute")
|
|
16454
|
-
|
|
16455
|
-
if (kind === "
|
|
16824
|
+
if (kind === "hosted-execute")
|
|
16825
|
+
return pc28.cyan("hosted");
|
|
16826
|
+
if (kind === "provider-assembly")
|
|
16827
|
+
return pc28.yellow("provider");
|
|
16828
|
+
if (kind === "local-only")
|
|
16829
|
+
return pc28.green("local");
|
|
16456
16830
|
return kind;
|
|
16457
16831
|
}
|
|
16458
16832
|
function hr3(width = 72) {
|
|
@@ -16562,7 +16936,8 @@ async function runCapabilityPicker(opts) {
|
|
|
16562
16936
|
p19.cancel("Cancelled.");
|
|
16563
16937
|
process.exit(0);
|
|
16564
16938
|
}
|
|
16565
|
-
if (familyChoice === "__back_to_hub")
|
|
16939
|
+
if (familyChoice === "__back_to_hub")
|
|
16940
|
+
return "back";
|
|
16566
16941
|
const query = familyChoice === "all" ? void 0 : { family: familyChoice };
|
|
16567
16942
|
let result;
|
|
16568
16943
|
try {
|
|
@@ -16591,9 +16966,11 @@ async function runCapabilityPicker(opts) {
|
|
|
16591
16966
|
p19.cancel("Cancelled.");
|
|
16592
16967
|
process.exit(0);
|
|
16593
16968
|
}
|
|
16594
|
-
if (capChoice === "__back_to_family")
|
|
16969
|
+
if (capChoice === "__back_to_family")
|
|
16970
|
+
break;
|
|
16595
16971
|
const selected = result.nodes.find((n) => n.slug === capChoice);
|
|
16596
|
-
if (!selected)
|
|
16972
|
+
if (!selected)
|
|
16973
|
+
continue;
|
|
16597
16974
|
printCapabilityCard(selected);
|
|
16598
16975
|
const nextStep = await p19.select({
|
|
16599
16976
|
message: "Next step",
|
|
@@ -16606,7 +16983,8 @@ async function runCapabilityPicker(opts) {
|
|
|
16606
16983
|
p19.cancel("Cancelled.");
|
|
16607
16984
|
process.exit(0);
|
|
16608
16985
|
}
|
|
16609
|
-
if (nextStep === "back_to_caps")
|
|
16986
|
+
if (nextStep === "back_to_caps")
|
|
16987
|
+
continue;
|
|
16610
16988
|
if (nextStep === "resolve") {
|
|
16611
16989
|
try {
|
|
16612
16990
|
const resolver = createMachineCapabilityResolver();
|
|
@@ -16895,12 +17273,15 @@ function detectCycle(nodes) {
|
|
|
16895
17273
|
const visited = /* @__PURE__ */ new Set();
|
|
16896
17274
|
const inStack = /* @__PURE__ */ new Set();
|
|
16897
17275
|
function dfs(nodeId) {
|
|
16898
|
-
if (inStack.has(nodeId))
|
|
16899
|
-
|
|
17276
|
+
if (inStack.has(nodeId))
|
|
17277
|
+
return true;
|
|
17278
|
+
if (visited.has(nodeId))
|
|
17279
|
+
return false;
|
|
16900
17280
|
visited.add(nodeId);
|
|
16901
17281
|
inStack.add(nodeId);
|
|
16902
17282
|
for (const upstream of adjacency.get(nodeId) ?? []) {
|
|
16903
|
-
if (dfs(upstream))
|
|
17283
|
+
if (dfs(upstream))
|
|
17284
|
+
return true;
|
|
16904
17285
|
}
|
|
16905
17286
|
inStack.delete(nodeId);
|
|
16906
17287
|
return false;
|
|
@@ -16918,15 +17299,21 @@ function detectCycle(nodes) {
|
|
|
16918
17299
|
|
|
16919
17300
|
// src/runtime/cms-node-contracts/introspect.ts
|
|
16920
17301
|
function toFieldType(value) {
|
|
16921
|
-
if (Array.isArray(value))
|
|
16922
|
-
|
|
16923
|
-
if (typeof value === "
|
|
16924
|
-
|
|
16925
|
-
if (
|
|
17302
|
+
if (Array.isArray(value))
|
|
17303
|
+
return "array";
|
|
17304
|
+
if (typeof value === "string")
|
|
17305
|
+
return "string";
|
|
17306
|
+
if (typeof value === "number")
|
|
17307
|
+
return "number";
|
|
17308
|
+
if (typeof value === "boolean")
|
|
17309
|
+
return "boolean";
|
|
17310
|
+
if (value && typeof value === "object")
|
|
17311
|
+
return "object";
|
|
16926
17312
|
return "unknown";
|
|
16927
17313
|
}
|
|
16928
17314
|
function outputTypeFromSchema(value) {
|
|
16929
|
-
if (typeof value === "string")
|
|
17315
|
+
if (typeof value === "string")
|
|
17316
|
+
return value;
|
|
16930
17317
|
if (value && typeof value === "object" && typeof value.type === "string") {
|
|
16931
17318
|
return value.type;
|
|
16932
17319
|
}
|
|
@@ -16983,19 +17370,24 @@ function sanitizeValue(value) {
|
|
|
16983
17370
|
return value;
|
|
16984
17371
|
}
|
|
16985
17372
|
function coerceValue(value, templateValue) {
|
|
16986
|
-
if (templateValue === void 0)
|
|
17373
|
+
if (templateValue === void 0)
|
|
17374
|
+
return value;
|
|
16987
17375
|
if (typeof templateValue === "number") {
|
|
16988
|
-
if (typeof value === "number")
|
|
17376
|
+
if (typeof value === "number")
|
|
17377
|
+
return value;
|
|
16989
17378
|
if (typeof value === "string" && value.trim().length > 0 && !Number.isNaN(Number(value))) {
|
|
16990
17379
|
return Number(value);
|
|
16991
17380
|
}
|
|
16992
17381
|
return templateValue;
|
|
16993
17382
|
}
|
|
16994
17383
|
if (typeof templateValue === "boolean") {
|
|
16995
|
-
if (typeof value === "boolean")
|
|
17384
|
+
if (typeof value === "boolean")
|
|
17385
|
+
return value;
|
|
16996
17386
|
if (typeof value === "string") {
|
|
16997
|
-
if (value.toLowerCase() === "true")
|
|
16998
|
-
|
|
17387
|
+
if (value.toLowerCase() === "true")
|
|
17388
|
+
return true;
|
|
17389
|
+
if (value.toLowerCase() === "false")
|
|
17390
|
+
return false;
|
|
16999
17391
|
}
|
|
17000
17392
|
return templateValue;
|
|
17001
17393
|
}
|
|
@@ -17003,7 +17395,8 @@ function coerceValue(value, templateValue) {
|
|
|
17003
17395
|
return Array.isArray(value) ? value : templateValue;
|
|
17004
17396
|
}
|
|
17005
17397
|
if (templateValue && typeof templateValue === "object") {
|
|
17006
|
-
if (value && typeof value === "object" && !Array.isArray(value))
|
|
17398
|
+
if (value && typeof value === "object" && !Array.isArray(value))
|
|
17399
|
+
return value;
|
|
17007
17400
|
return templateValue;
|
|
17008
17401
|
}
|
|
17009
17402
|
return value;
|
|
@@ -17021,9 +17414,12 @@ function normalizeNodeBindings(rawBindings, node) {
|
|
|
17021
17414
|
const sanitized = sanitizeValue(rawValue);
|
|
17022
17415
|
const coerced = coerceValue(sanitized, templateValue);
|
|
17023
17416
|
merged[key] = coerced;
|
|
17024
|
-
if (hasIncoming)
|
|
17025
|
-
|
|
17026
|
-
if (
|
|
17417
|
+
if (hasIncoming)
|
|
17418
|
+
providedCount += 1;
|
|
17419
|
+
if (!hasIncoming)
|
|
17420
|
+
defaultedCount += 1;
|
|
17421
|
+
if (sanitized !== rawValue || coerced !== sanitized)
|
|
17422
|
+
normalizedCount += 1;
|
|
17027
17423
|
}
|
|
17028
17424
|
for (const [key, value] of Object.entries(incoming)) {
|
|
17029
17425
|
if (!(key in merged)) {
|
|
@@ -17043,7 +17439,8 @@ function validateNodeBindings(normalizedBindings, node) {
|
|
|
17043
17439
|
const missingRequiredInputs = [];
|
|
17044
17440
|
const missingRequiredBindings = [];
|
|
17045
17441
|
for (const input of contract.inputs) {
|
|
17046
|
-
if (!input.required)
|
|
17442
|
+
if (!input.required)
|
|
17443
|
+
continue;
|
|
17047
17444
|
const value = normalizedBindings[input.key];
|
|
17048
17445
|
if (value === void 0 || value === null || value === "") {
|
|
17049
17446
|
missingRequiredInputs.push(input.key);
|
|
@@ -17201,7 +17598,8 @@ function buildPreExecutionSummary(input) {
|
|
|
17201
17598
|
...input.pipeline,
|
|
17202
17599
|
nodes: input.pipeline.nodes.map((node) => {
|
|
17203
17600
|
const capability = input.registryBySlug.get(node.slug);
|
|
17204
|
-
if (!capability)
|
|
17601
|
+
if (!capability)
|
|
17602
|
+
return node;
|
|
17205
17603
|
const normalized = normalizeNodeBindings(node.bindings, capability);
|
|
17206
17604
|
return { ...node, bindings: normalized.bindings };
|
|
17207
17605
|
})
|
|
@@ -17264,7 +17662,8 @@ function resolveArtifactManifestPath(artifactId) {
|
|
|
17264
17662
|
}
|
|
17265
17663
|
function readLocalManifest(artifactId) {
|
|
17266
17664
|
const filePath = resolveArtifactManifestPath(artifactId);
|
|
17267
|
-
if (!fs19.existsSync(filePath))
|
|
17665
|
+
if (!fs19.existsSync(filePath))
|
|
17666
|
+
return null;
|
|
17268
17667
|
try {
|
|
17269
17668
|
return JSON.parse(fs19.readFileSync(filePath, "utf-8"));
|
|
17270
17669
|
} catch {
|
|
@@ -17280,7 +17679,8 @@ function writeLocalManifest(manifest) {
|
|
|
17280
17679
|
}
|
|
17281
17680
|
function listLocalManifests() {
|
|
17282
17681
|
const dir = resolveArtifactsDir();
|
|
17283
|
-
if (!fs19.existsSync(dir))
|
|
17682
|
+
if (!fs19.existsSync(dir))
|
|
17683
|
+
return [];
|
|
17284
17684
|
return fs19.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => {
|
|
17285
17685
|
try {
|
|
17286
17686
|
const content = fs19.readFileSync(path27.resolve(dir, entry.name), "utf-8");
|
|
@@ -17291,12 +17691,18 @@ function listLocalManifests() {
|
|
|
17291
17691
|
}).filter((m) => m !== null).sort((a, b) => (b.createdAt ?? "").localeCompare(a.createdAt ?? ""));
|
|
17292
17692
|
}
|
|
17293
17693
|
function matchesQuery2(manifest, query) {
|
|
17294
|
-
if (query.artifactType && manifest.artifactType !== query.artifactType)
|
|
17295
|
-
|
|
17296
|
-
if (query.
|
|
17297
|
-
|
|
17298
|
-
if (query.
|
|
17299
|
-
|
|
17694
|
+
if (query.artifactType && manifest.artifactType !== query.artifactType)
|
|
17695
|
+
return false;
|
|
17696
|
+
if (query.pipelineId && manifest.pipelineId !== query.pipelineId)
|
|
17697
|
+
return false;
|
|
17698
|
+
if (query.sourceNodeSlug && manifest.sourceNodeSlug !== query.sourceNodeSlug)
|
|
17699
|
+
return false;
|
|
17700
|
+
if (query.executionContext && manifest.executionContext !== query.executionContext)
|
|
17701
|
+
return false;
|
|
17702
|
+
if (query.status && manifest.status !== query.status)
|
|
17703
|
+
return false;
|
|
17704
|
+
if (query.threadId && manifest.threadId !== query.threadId)
|
|
17705
|
+
return false;
|
|
17300
17706
|
return true;
|
|
17301
17707
|
}
|
|
17302
17708
|
function createArtifactManifest(input) {
|
|
@@ -17343,7 +17749,8 @@ function createArtifactStore() {
|
|
|
17343
17749
|
},
|
|
17344
17750
|
update(artifactId, patch) {
|
|
17345
17751
|
const existing = readLocalManifest(artifactId);
|
|
17346
|
-
if (!existing)
|
|
17752
|
+
if (!existing)
|
|
17753
|
+
return null;
|
|
17347
17754
|
const updated = {
|
|
17348
17755
|
...existing,
|
|
17349
17756
|
...patch.status !== void 0 ? { status: patch.status } : {},
|
|
@@ -17448,7 +17855,8 @@ function createNativeIntelligenceBackend(config) {
|
|
|
17448
17855
|
break;
|
|
17449
17856
|
}
|
|
17450
17857
|
}
|
|
17451
|
-
if (result)
|
|
17858
|
+
if (result)
|
|
17859
|
+
break;
|
|
17452
17860
|
}
|
|
17453
17861
|
if (!result) {
|
|
17454
17862
|
throw lastError ?? new NativeIntelligenceBackendError(502, "Model backend returned no response.");
|
|
@@ -17492,7 +17900,8 @@ function resolveModelCandidates(config) {
|
|
|
17492
17900
|
function resolveEndpointCandidates(config) {
|
|
17493
17901
|
const primary = config.endpoint;
|
|
17494
17902
|
const candidates = [primary];
|
|
17495
|
-
if (config.backendType !== "local")
|
|
17903
|
+
if (config.backendType !== "local")
|
|
17904
|
+
return candidates;
|
|
17496
17905
|
const normalized = primary.toLowerCase();
|
|
17497
17906
|
if ((normalized.includes("localhost:8080") || normalized.includes("127.0.0.1:8080")) && !candidates.includes("http://127.0.0.1:11434/v1/chat/completions")) {
|
|
17498
17907
|
candidates.push("http://127.0.0.1:11434/v1/chat/completions");
|
|
@@ -17501,16 +17910,20 @@ function resolveEndpointCandidates(config) {
|
|
|
17501
17910
|
}
|
|
17502
17911
|
function shouldTryNextModel(status, errorText4, attemptedModel, config, candidates) {
|
|
17503
17912
|
const hasNextCandidate = candidates[candidates.length - 1] !== attemptedModel;
|
|
17504
|
-
if (!hasNextCandidate)
|
|
17505
|
-
|
|
17913
|
+
if (!hasNextCandidate)
|
|
17914
|
+
return false;
|
|
17915
|
+
if (config.backendType !== "local")
|
|
17916
|
+
return false;
|
|
17506
17917
|
const normalizedError = errorText4.toLowerCase();
|
|
17507
17918
|
return status === 404 || normalizedError.includes("model") && normalizedError.includes("not found");
|
|
17508
17919
|
}
|
|
17509
17920
|
function extractCompletionText(response) {
|
|
17510
17921
|
if (response.choices && response.choices.length > 0) {
|
|
17511
17922
|
const choice = response.choices[0];
|
|
17512
|
-
if (choice.message?.content)
|
|
17513
|
-
|
|
17923
|
+
if (choice.message?.content)
|
|
17924
|
+
return choice.message.content;
|
|
17925
|
+
if (choice.text)
|
|
17926
|
+
return choice.text;
|
|
17514
17927
|
}
|
|
17515
17928
|
throw new NativeIntelligenceBackendError(
|
|
17516
17929
|
502,
|
|
@@ -17855,7 +18268,8 @@ function buildDeterministicNormalization(input) {
|
|
|
17855
18268
|
}
|
|
17856
18269
|
}
|
|
17857
18270
|
for (const [key, value] of Object.entries(rawBindings)) {
|
|
17858
|
-
if (contract.inputs.some((i) => i.key === key))
|
|
18271
|
+
if (contract.inputs.some((i) => i.key === key))
|
|
18272
|
+
continue;
|
|
17859
18273
|
normalizedBindings[key] = value;
|
|
17860
18274
|
fields.push({
|
|
17861
18275
|
key,
|
|
@@ -17874,9 +18288,11 @@ function buildDeterministicNormalization(input) {
|
|
|
17874
18288
|
};
|
|
17875
18289
|
}
|
|
17876
18290
|
function isPlaceholderValue(value) {
|
|
17877
|
-
if (typeof value !== "string")
|
|
18291
|
+
if (typeof value !== "string")
|
|
18292
|
+
return false;
|
|
17878
18293
|
const normalized = value.trim().toLowerCase();
|
|
17879
|
-
if (!normalized)
|
|
18294
|
+
if (!normalized)
|
|
18295
|
+
return true;
|
|
17880
18296
|
return normalized.startsWith("enter ") || normalized.startsWith("select ") || normalized === "placeholder" || normalized === "todo" || normalized === "tbd" || normalized === "n/a" || normalized === "none" || normalized === "your_" || normalized.startsWith("your_") || normalized.startsWith("<") && normalized.endsWith(">");
|
|
17881
18297
|
}
|
|
17882
18298
|
function coerceToFieldType(value, targetType) {
|
|
@@ -17888,20 +18304,24 @@ function coerceToFieldType(value, targetType) {
|
|
|
17888
18304
|
}
|
|
17889
18305
|
if (targetType === "boolean" && typeof value === "string") {
|
|
17890
18306
|
const lower = value.trim().toLowerCase();
|
|
17891
|
-
if (lower === "true" || lower === "yes" || lower === "1")
|
|
17892
|
-
|
|
18307
|
+
if (lower === "true" || lower === "yes" || lower === "1")
|
|
18308
|
+
return true;
|
|
18309
|
+
if (lower === "false" || lower === "no" || lower === "0")
|
|
18310
|
+
return false;
|
|
17893
18311
|
}
|
|
17894
18312
|
if (targetType === "array" && typeof value === "string") {
|
|
17895
18313
|
try {
|
|
17896
18314
|
const parsed = JSON.parse(value);
|
|
17897
|
-
if (Array.isArray(parsed))
|
|
18315
|
+
if (Array.isArray(parsed))
|
|
18316
|
+
return parsed;
|
|
17898
18317
|
} catch {
|
|
17899
18318
|
}
|
|
17900
18319
|
}
|
|
17901
18320
|
if (targetType === "object" && typeof value === "string") {
|
|
17902
18321
|
try {
|
|
17903
18322
|
const parsed = JSON.parse(value);
|
|
17904
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
18323
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
18324
|
+
return parsed;
|
|
17905
18325
|
} catch {
|
|
17906
18326
|
}
|
|
17907
18327
|
}
|
|
@@ -17933,7 +18353,8 @@ function toNormalizationResult(raw, input) {
|
|
|
17933
18353
|
const fields = [];
|
|
17934
18354
|
if (Array.isArray(raw.fields)) {
|
|
17935
18355
|
for (const f of raw.fields) {
|
|
17936
|
-
if (typeof f.key !== "string")
|
|
18356
|
+
if (typeof f.key !== "string")
|
|
18357
|
+
continue;
|
|
17937
18358
|
const action = validateAction(f.action);
|
|
17938
18359
|
normalizedBindings[f.key] = f.normalizedValue ?? f.originalValue ?? input.rawBindings[f.key];
|
|
17939
18360
|
fields.push({
|
|
@@ -18130,19 +18551,26 @@ function scoreWorkflowMatch(workflow, intentTokens, intentLower) {
|
|
|
18130
18551
|
const descLower = (workflow.description ?? "").toLowerCase();
|
|
18131
18552
|
const slugsLower = workflow.nodeSlugs.map((s) => s.toLowerCase()).join(" ");
|
|
18132
18553
|
for (const token of intentTokens) {
|
|
18133
|
-
if (nameLower.includes(token))
|
|
18134
|
-
|
|
18135
|
-
if (
|
|
18554
|
+
if (nameLower.includes(token))
|
|
18555
|
+
score += 2;
|
|
18556
|
+
if (descLower.includes(token))
|
|
18557
|
+
score += 1;
|
|
18558
|
+
if (slugsLower.includes(token))
|
|
18559
|
+
score += 1.5;
|
|
18136
18560
|
}
|
|
18137
18561
|
for (const slug of workflow.nodeSlugs) {
|
|
18138
18562
|
if (intentLower.includes(slug.toLowerCase())) {
|
|
18139
18563
|
score += 2;
|
|
18140
18564
|
}
|
|
18141
18565
|
}
|
|
18142
|
-
if (workflow.label === "canonical")
|
|
18143
|
-
|
|
18144
|
-
if (workflow.label === "
|
|
18145
|
-
|
|
18566
|
+
if (workflow.label === "canonical")
|
|
18567
|
+
score += 2;
|
|
18568
|
+
if (workflow.label === "experimental")
|
|
18569
|
+
score += 0.5;
|
|
18570
|
+
if (workflow.label === "archived")
|
|
18571
|
+
score -= 3;
|
|
18572
|
+
if (workflow.versionCount >= 3)
|
|
18573
|
+
score += 1;
|
|
18146
18574
|
return score;
|
|
18147
18575
|
}
|
|
18148
18576
|
function scoreContractMatch(contract, intentTokens, intentLower) {
|
|
@@ -18151,9 +18579,12 @@ function scoreContractMatch(contract, intentTokens, intentLower) {
|
|
|
18151
18579
|
const nameLower = contract.displayName.toLowerCase();
|
|
18152
18580
|
const familyLower = contract.family.toLowerCase();
|
|
18153
18581
|
for (const token of intentTokens) {
|
|
18154
|
-
if (slugLower.includes(token))
|
|
18155
|
-
|
|
18156
|
-
if (
|
|
18582
|
+
if (slugLower.includes(token))
|
|
18583
|
+
score += 2;
|
|
18584
|
+
if (nameLower.includes(token))
|
|
18585
|
+
score += 2;
|
|
18586
|
+
if (familyLower.includes(token))
|
|
18587
|
+
score += 1;
|
|
18157
18588
|
}
|
|
18158
18589
|
for (const outputType of contract.outputTypes) {
|
|
18159
18590
|
if (intentLower.includes(outputType.toLowerCase())) {
|
|
@@ -18287,10 +18718,14 @@ function buildDeterministicPlan(input) {
|
|
|
18287
18718
|
const usedSlugs = /* @__PURE__ */ new Set();
|
|
18288
18719
|
const warnings = [];
|
|
18289
18720
|
for (const { contract, score } of scoredContracts) {
|
|
18290
|
-
if (selectedNodes.length >= maxNodes)
|
|
18291
|
-
|
|
18292
|
-
if (
|
|
18293
|
-
|
|
18721
|
+
if (selectedNodes.length >= maxNodes)
|
|
18722
|
+
break;
|
|
18723
|
+
if (score <= 0)
|
|
18724
|
+
break;
|
|
18725
|
+
if (usedSlugs.has(contract.slug))
|
|
18726
|
+
continue;
|
|
18727
|
+
if (constraints?.avoidSlugs?.includes(contract.slug))
|
|
18728
|
+
continue;
|
|
18294
18729
|
const suggestedBindings = {};
|
|
18295
18730
|
for (const field of contract.inputs) {
|
|
18296
18731
|
suggestedBindings[field.key] = field.defaultValue ?? "";
|
|
@@ -18342,20 +18777,26 @@ function scoreContract(contract, intentTokens, intentLower, constraints) {
|
|
|
18342
18777
|
const nameLower = contract.displayName.toLowerCase();
|
|
18343
18778
|
const familyLower = contract.family.toLowerCase();
|
|
18344
18779
|
for (const token of intentTokens) {
|
|
18345
|
-
if (slugLower.includes(token))
|
|
18346
|
-
|
|
18347
|
-
if (
|
|
18780
|
+
if (slugLower.includes(token))
|
|
18781
|
+
score += 2;
|
|
18782
|
+
if (nameLower.includes(token))
|
|
18783
|
+
score += 2;
|
|
18784
|
+
if (familyLower.includes(token))
|
|
18785
|
+
score += 1;
|
|
18348
18786
|
}
|
|
18349
18787
|
if (constraints?.requiredOutputTypes) {
|
|
18350
18788
|
for (const requiredType of constraints.requiredOutputTypes) {
|
|
18351
|
-
if (contract.outputTypes.includes(requiredType))
|
|
18789
|
+
if (contract.outputTypes.includes(requiredType))
|
|
18790
|
+
score += 3;
|
|
18352
18791
|
}
|
|
18353
18792
|
}
|
|
18354
18793
|
if (constraints?.preferredFamilies) {
|
|
18355
|
-
if (constraints.preferredFamilies.includes(contract.family))
|
|
18794
|
+
if (constraints.preferredFamilies.includes(contract.family))
|
|
18795
|
+
score += 2;
|
|
18356
18796
|
}
|
|
18357
18797
|
for (const outType of contract.outputTypes) {
|
|
18358
|
-
if (intentLower.includes(outType.toLowerCase()))
|
|
18798
|
+
if (intentLower.includes(outType.toLowerCase()))
|
|
18799
|
+
score += 1.5;
|
|
18359
18800
|
}
|
|
18360
18801
|
return score;
|
|
18361
18802
|
}
|
|
@@ -18363,15 +18804,19 @@ function findBestExistingWorkflow(workflows, intentTokens, intentLower) {
|
|
|
18363
18804
|
let best = null;
|
|
18364
18805
|
let bestScore = 0;
|
|
18365
18806
|
for (const wf of workflows) {
|
|
18366
|
-
if (wf.label === "archived")
|
|
18807
|
+
if (wf.label === "archived")
|
|
18808
|
+
continue;
|
|
18367
18809
|
let score = 0;
|
|
18368
18810
|
const nameLower = wf.name.toLowerCase();
|
|
18369
18811
|
const slugsLower = wf.nodeSlugs.join(" ").toLowerCase();
|
|
18370
18812
|
for (const token of intentTokens) {
|
|
18371
|
-
if (nameLower.includes(token))
|
|
18372
|
-
|
|
18813
|
+
if (nameLower.includes(token))
|
|
18814
|
+
score += 2;
|
|
18815
|
+
if (slugsLower.includes(token))
|
|
18816
|
+
score += 1.5;
|
|
18373
18817
|
}
|
|
18374
|
-
if (wf.label === "canonical")
|
|
18818
|
+
if (wf.label === "canonical")
|
|
18819
|
+
score += 1;
|
|
18375
18820
|
if (score > bestScore) {
|
|
18376
18821
|
bestScore = score;
|
|
18377
18822
|
best = wf;
|
|
@@ -18399,7 +18844,8 @@ function buildPlannerPrompt(input) {
|
|
|
18399
18844
|
];
|
|
18400
18845
|
if (constraints) {
|
|
18401
18846
|
sections.push("", "Constraints:");
|
|
18402
|
-
if (constraints.maxNodes)
|
|
18847
|
+
if (constraints.maxNodes)
|
|
18848
|
+
sections.push(` Max Nodes: ${constraints.maxNodes}`);
|
|
18403
18849
|
if (constraints.requiredOutputTypes?.length) {
|
|
18404
18850
|
sections.push(` Required Output Types: ${constraints.requiredOutputTypes.join(", ")}`);
|
|
18405
18851
|
}
|
|
@@ -18433,7 +18879,8 @@ function validatePlanningResult(raw, input) {
|
|
|
18433
18879
|
const warnings = Array.isArray(raw.warnings) ? [...raw.warnings] : [];
|
|
18434
18880
|
if (Array.isArray(raw.proposedNodes)) {
|
|
18435
18881
|
for (const node of raw.proposedNodes) {
|
|
18436
|
-
if (typeof node.slug !== "string")
|
|
18882
|
+
if (typeof node.slug !== "string")
|
|
18883
|
+
continue;
|
|
18437
18884
|
if (!availableSlugs.has(node.slug)) {
|
|
18438
18885
|
warnings.push(`Proposed node slug "${node.slug}" is not in the available contracts \u2014 skipped.`);
|
|
18439
18886
|
continue;
|
|
@@ -18502,7 +18949,8 @@ function writeIntelligenceConfig(config) {
|
|
|
18502
18949
|
`, "utf-8");
|
|
18503
18950
|
}
|
|
18504
18951
|
function validateModelId(id) {
|
|
18505
|
-
if (id === "gemma3" || id === "gemma3n" || id === "codegemma")
|
|
18952
|
+
if (id === "gemma3" || id === "gemma3n" || id === "codegemma")
|
|
18953
|
+
return id;
|
|
18506
18954
|
return "gemma3";
|
|
18507
18955
|
}
|
|
18508
18956
|
function createNativeIntelligenceProvider(configOverride) {
|
|
@@ -18582,7 +19030,8 @@ async function runPipelineAssembler(opts) {
|
|
|
18582
19030
|
p20.cancel("Cancelled.");
|
|
18583
19031
|
process.exit(0);
|
|
18584
19032
|
}
|
|
18585
|
-
if (entryChoice === "__back_to_hub")
|
|
19033
|
+
if (entryChoice === "__back_to_hub")
|
|
19034
|
+
return "back";
|
|
18586
19035
|
} else {
|
|
18587
19036
|
p20.note("Execution mode is fixed to hosted for Dynamic Pipelines.", "Hosted only");
|
|
18588
19037
|
}
|
|
@@ -18647,9 +19096,11 @@ async function runPipelineAssembler(opts) {
|
|
|
18647
19096
|
p20.cancel("Cancelled.");
|
|
18648
19097
|
process.exit(0);
|
|
18649
19098
|
}
|
|
18650
|
-
if (capChoice === "__back")
|
|
19099
|
+
if (capChoice === "__back")
|
|
19100
|
+
continue;
|
|
18651
19101
|
const cap = capabilities.find((c) => c.slug === capChoice);
|
|
18652
|
-
if (!cap)
|
|
19102
|
+
if (!cap)
|
|
19103
|
+
continue;
|
|
18653
19104
|
const bindings = {};
|
|
18654
19105
|
for (const bindingKey of cap.requiredBindings) {
|
|
18655
19106
|
const value = await p20.text({
|
|
@@ -18759,7 +19210,8 @@ async function runPipelineAssembler(opts) {
|
|
|
18759
19210
|
message: `Save hosted workflow "${workflowName}"?`,
|
|
18760
19211
|
initialValue: true
|
|
18761
19212
|
});
|
|
18762
|
-
if (p20.isCancel(confirmed) || !confirmed)
|
|
19213
|
+
if (p20.isCancel(confirmed) || !confirmed)
|
|
19214
|
+
continue;
|
|
18763
19215
|
try {
|
|
18764
19216
|
const saveResult = await saveHostedWorkflow(session, {
|
|
18765
19217
|
name: workflowName,
|
|
@@ -18811,7 +19263,8 @@ async function runPipelineAssembler(opts) {
|
|
|
18811
19263
|
message: "Execute this pipeline through the hosted runtime?",
|
|
18812
19264
|
initialValue: false
|
|
18813
19265
|
});
|
|
18814
|
-
if (p20.isCancel(confirmed) || !confirmed)
|
|
19266
|
+
if (p20.isCancel(confirmed) || !confirmed)
|
|
19267
|
+
continue;
|
|
18815
19268
|
try {
|
|
18816
19269
|
const executionClient = createHostedExecutionClient();
|
|
18817
19270
|
const pipeline2 = builder.build();
|
|
@@ -18868,7 +19321,8 @@ function loadPipelineFromFileOrJson(input) {
|
|
|
18868
19321
|
}
|
|
18869
19322
|
}
|
|
18870
19323
|
function renderExecutionProgress(completed, total, detail) {
|
|
18871
|
-
if (!process.stdout.isTTY)
|
|
19324
|
+
if (!process.stdout.isTTY)
|
|
19325
|
+
return;
|
|
18872
19326
|
const width = 24;
|
|
18873
19327
|
const safeCompleted = Math.max(0, Math.min(completed, total));
|
|
18874
19328
|
const percent = total <= 0 ? 0 : Math.round(safeCompleted / total * 100);
|
|
@@ -18908,7 +19362,8 @@ async function executeHostedPipeline(pipeline, opts) {
|
|
|
18908
19362
|
let startupSettled = false;
|
|
18909
19363
|
startupSpinner?.start("Preparing hosted workflow execution...");
|
|
18910
19364
|
const settleStartup = (message) => {
|
|
18911
|
-
if (!startupSpinner || startupSettled)
|
|
19365
|
+
if (!startupSpinner || startupSettled)
|
|
19366
|
+
return;
|
|
18912
19367
|
startupSettled = true;
|
|
18913
19368
|
startupSpinner.stop(message ?? "Hosted workflow execution started.");
|
|
18914
19369
|
};
|
|
@@ -18950,10 +19405,13 @@ async function executeHostedPipeline(pipeline, opts) {
|
|
|
18950
19405
|
console.log(pc30.bold("Pipeline Execution Result"));
|
|
18951
19406
|
console.log(hr4());
|
|
18952
19407
|
console.log(` ${pc30.dim("Execution ID:")} ${result.executionId}`);
|
|
18953
|
-
if (result.threadId)
|
|
19408
|
+
if (result.threadId)
|
|
19409
|
+
console.log(` ${pc30.dim("Thread ID:")} ${result.threadId}`);
|
|
18954
19410
|
console.log(` ${pc30.dim("Status:")} ${result.status === "succeeded" ? pc30.green(result.status) : pc30.red(result.status)}`);
|
|
18955
|
-
if (result.startedAt)
|
|
18956
|
-
|
|
19411
|
+
if (result.startedAt)
|
|
19412
|
+
console.log(` ${pc30.dim("Started:")} ${result.startedAt}`);
|
|
19413
|
+
if (result.completedAt)
|
|
19414
|
+
console.log(` ${pc30.dim("Completed:")} ${result.completedAt}`);
|
|
18957
19415
|
console.log(hr4());
|
|
18958
19416
|
for (const [nodeId, nodeResult] of Object.entries(result.nodeResults)) {
|
|
18959
19417
|
const statusColor3 = nodeResult.status === "succeeded" ? pc30.green : pc30.red;
|
|
@@ -18972,12 +19430,18 @@ async function executeHostedPipeline(pipeline, opts) {
|
|
|
18972
19430
|
if (result.summary) {
|
|
18973
19431
|
console.log("");
|
|
18974
19432
|
console.log(pc30.bold(" Summary:"));
|
|
18975
|
-
if (result.summary.outputText)
|
|
18976
|
-
|
|
18977
|
-
if (typeof result.summary.
|
|
18978
|
-
|
|
18979
|
-
if (result.summary.
|
|
18980
|
-
|
|
19433
|
+
if (result.summary.outputText)
|
|
19434
|
+
console.log(` ${pc30.dim("\xB7")} ${result.summary.outputText}`);
|
|
19435
|
+
if (typeof result.summary.imageCount === "number")
|
|
19436
|
+
console.log(` ${pc30.dim("\xB7")} images: ${result.summary.imageCount}`);
|
|
19437
|
+
if (typeof result.summary.slideCount === "number")
|
|
19438
|
+
console.log(` ${pc30.dim("\xB7")} slides: ${result.summary.slideCount}`);
|
|
19439
|
+
if (typeof result.summary.videoCount === "number")
|
|
19440
|
+
console.log(` ${pc30.dim("\xB7")} videos: ${result.summary.videoCount}`);
|
|
19441
|
+
if (result.summary.workflowRunId)
|
|
19442
|
+
console.log(` ${pc30.dim("\xB7")} workflow_run_id: ${result.summary.workflowRunId}`);
|
|
19443
|
+
if (result.summary.keyboardShortcutHint)
|
|
19444
|
+
console.log(` ${pc30.dim("\xB7")} ${result.summary.keyboardShortcutHint}`);
|
|
18981
19445
|
}
|
|
18982
19446
|
try {
|
|
18983
19447
|
const credits = await fetchHostedCredits(session);
|
|
@@ -19024,7 +19488,8 @@ async function renderIntelligenceSummary(pipeline, capabilities, phase) {
|
|
|
19024
19488
|
const missingRequired = [];
|
|
19025
19489
|
if (contract) {
|
|
19026
19490
|
for (const input2 of contract.inputs) {
|
|
19027
|
-
if (!input2.required)
|
|
19491
|
+
if (!input2.required)
|
|
19492
|
+
continue;
|
|
19028
19493
|
const value = node.bindings[input2.key];
|
|
19029
19494
|
if (value === void 0 || value === null || value === "") {
|
|
19030
19495
|
missingRequired.push(input2.key);
|
|
@@ -19126,7 +19591,8 @@ Examples:
|
|
|
19126
19591
|
const nodeRef = issue.nodeId ? ` [${issue.nodeId}]` : "";
|
|
19127
19592
|
console.log(`${prefix}${nodeRef}: ${issue.message}`);
|
|
19128
19593
|
}
|
|
19129
|
-
if (!result.valid)
|
|
19594
|
+
if (!result.valid)
|
|
19595
|
+
process.exitCode = 1;
|
|
19130
19596
|
} catch (err) {
|
|
19131
19597
|
console.error(pc30.red("Validation failed: " + err.message));
|
|
19132
19598
|
process.exitCode = 1;
|
|
@@ -19208,10 +19674,13 @@ Examples:
|
|
|
19208
19674
|
console.log(pc30.bold("Pipeline Execution Result"));
|
|
19209
19675
|
console.log(hr4());
|
|
19210
19676
|
console.log(` ${pc30.dim("Execution ID:")} ${result.executionId}`);
|
|
19211
|
-
if (result.threadId)
|
|
19677
|
+
if (result.threadId)
|
|
19678
|
+
console.log(` ${pc30.dim("Thread ID:")} ${result.threadId}`);
|
|
19212
19679
|
console.log(` ${pc30.dim("Status:")} ${result.status === "succeeded" ? pc30.green(result.status) : pc30.red(result.status)}`);
|
|
19213
|
-
if (result.startedAt)
|
|
19214
|
-
|
|
19680
|
+
if (result.startedAt)
|
|
19681
|
+
console.log(` ${pc30.dim("Started:")} ${result.startedAt}`);
|
|
19682
|
+
if (result.completedAt)
|
|
19683
|
+
console.log(` ${pc30.dim("Completed:")} ${result.completedAt}`);
|
|
19215
19684
|
console.log(hr4());
|
|
19216
19685
|
for (const [nodeId, nodeResult] of Object.entries(result.nodeResults)) {
|
|
19217
19686
|
const statusColor3 = nodeResult.status === "succeeded" ? pc30.green : pc30.red;
|
|
@@ -19230,12 +19699,18 @@ Examples:
|
|
|
19230
19699
|
if (result.summary) {
|
|
19231
19700
|
console.log("");
|
|
19232
19701
|
console.log(pc30.bold(" Summary:"));
|
|
19233
|
-
if (result.summary.outputText)
|
|
19234
|
-
|
|
19235
|
-
if (typeof result.summary.
|
|
19236
|
-
|
|
19237
|
-
if (result.summary.
|
|
19238
|
-
|
|
19702
|
+
if (result.summary.outputText)
|
|
19703
|
+
console.log(` ${pc30.dim("\xB7")} ${result.summary.outputText}`);
|
|
19704
|
+
if (typeof result.summary.imageCount === "number")
|
|
19705
|
+
console.log(` ${pc30.dim("\xB7")} images: ${result.summary.imageCount}`);
|
|
19706
|
+
if (typeof result.summary.slideCount === "number")
|
|
19707
|
+
console.log(` ${pc30.dim("\xB7")} slides: ${result.summary.slideCount}`);
|
|
19708
|
+
if (typeof result.summary.videoCount === "number")
|
|
19709
|
+
console.log(` ${pc30.dim("\xB7")} videos: ${result.summary.videoCount}`);
|
|
19710
|
+
if (result.summary.workflowRunId)
|
|
19711
|
+
console.log(` ${pc30.dim("\xB7")} workflow_run_id: ${result.summary.workflowRunId}`);
|
|
19712
|
+
if (result.summary.keyboardShortcutHint)
|
|
19713
|
+
console.log(` ${pc30.dim("\xB7")} ${result.summary.keyboardShortcutHint}`);
|
|
19239
19714
|
}
|
|
19240
19715
|
try {
|
|
19241
19716
|
const credits = await fetchHostedCredits(session);
|
|
@@ -19286,14 +19761,19 @@ var ARTIFACT_TYPE_CONFIG = {
|
|
|
19286
19761
|
};
|
|
19287
19762
|
function artifactTypeBadge(type) {
|
|
19288
19763
|
const cfg = ARTIFACT_TYPE_CONFIG[type];
|
|
19289
|
-
if (!cfg)
|
|
19764
|
+
if (!cfg)
|
|
19765
|
+
return type;
|
|
19290
19766
|
return cfg.color(`${cfg.emoji} ${type}`);
|
|
19291
19767
|
}
|
|
19292
19768
|
function statusColor(status) {
|
|
19293
|
-
if (status === "ready")
|
|
19294
|
-
|
|
19295
|
-
if (status === "
|
|
19296
|
-
|
|
19769
|
+
if (status === "ready")
|
|
19770
|
+
return pc31.green(status);
|
|
19771
|
+
if (status === "generating" || status === "pending")
|
|
19772
|
+
return pc31.yellow(status);
|
|
19773
|
+
if (status === "failed")
|
|
19774
|
+
return pc31.red(status);
|
|
19775
|
+
if (status === "archived")
|
|
19776
|
+
return pc31.dim(status);
|
|
19297
19777
|
return status;
|
|
19298
19778
|
}
|
|
19299
19779
|
function printArtifactTable(artifacts) {
|
|
@@ -19329,7 +19809,8 @@ function printArtifactDetail(art) {
|
|
|
19329
19809
|
console.log(pc31.bold("Artifact: " + art.id));
|
|
19330
19810
|
console.log(hr5());
|
|
19331
19811
|
const kv = (label, value) => {
|
|
19332
|
-
if (value === void 0)
|
|
19812
|
+
if (value === void 0)
|
|
19813
|
+
return;
|
|
19333
19814
|
console.log(` ${pc31.bold(label.padEnd(22))} ${value}`);
|
|
19334
19815
|
};
|
|
19335
19816
|
kv("Type:", artifactTypeBadge(art.artifactType));
|
|
@@ -19414,10 +19895,12 @@ function resolveStorePath() {
|
|
|
19414
19895
|
return path30.resolve(resolvePaperclipHomeDir(), "workflow-hygiene", "labels.json");
|
|
19415
19896
|
}
|
|
19416
19897
|
function readStoreFile(filePath) {
|
|
19417
|
-
if (!fs22.existsSync(filePath))
|
|
19898
|
+
if (!fs22.existsSync(filePath))
|
|
19899
|
+
return { records: [] };
|
|
19418
19900
|
try {
|
|
19419
19901
|
const raw = JSON.parse(fs22.readFileSync(filePath, "utf-8"));
|
|
19420
|
-
if (!Array.isArray(raw.records))
|
|
19902
|
+
if (!Array.isArray(raw.records))
|
|
19903
|
+
return { records: [] };
|
|
19421
19904
|
return raw;
|
|
19422
19905
|
} catch {
|
|
19423
19906
|
return { records: [] };
|
|
@@ -19429,8 +19912,10 @@ function writeStoreFile(filePath, data) {
|
|
|
19429
19912
|
`, "utf-8");
|
|
19430
19913
|
}
|
|
19431
19914
|
function inferDefaultLabel(name, createdAt, versionCount) {
|
|
19432
|
-
if (versionCount >= 3)
|
|
19433
|
-
|
|
19915
|
+
if (versionCount >= 3)
|
|
19916
|
+
return "canonical";
|
|
19917
|
+
if (name.toLowerCase().includes("experiment"))
|
|
19918
|
+
return "experimental";
|
|
19434
19919
|
if (createdAt && Date.now() - Date.parse(createdAt) > 1e3 * 60 * 60 * 24 * 90) {
|
|
19435
19920
|
return "archived";
|
|
19436
19921
|
}
|
|
@@ -19469,8 +19954,10 @@ function createWorkflowHygieneStore() {
|
|
|
19469
19954
|
// src/runtime/workflow-hygiene/summaries.ts
|
|
19470
19955
|
import pc32 from "picocolors";
|
|
19471
19956
|
function renderWorkflowLabel(label) {
|
|
19472
|
-
if (label === "canonical")
|
|
19473
|
-
|
|
19957
|
+
if (label === "canonical")
|
|
19958
|
+
return pc32.green("canonical");
|
|
19959
|
+
if (label === "archived")
|
|
19960
|
+
return pc32.dim("archived");
|
|
19474
19961
|
return pc32.yellow("experimental");
|
|
19475
19962
|
}
|
|
19476
19963
|
function enrichWorkflowSummaries(entries, store) {
|
|
@@ -19533,10 +20020,12 @@ function resolveDeletedWorkflowIdsPath() {
|
|
|
19533
20020
|
}
|
|
19534
20021
|
function readDeletedWorkflowIds() {
|
|
19535
20022
|
const filePath = resolveDeletedWorkflowIdsPath();
|
|
19536
|
-
if (!fs23.existsSync(filePath))
|
|
20023
|
+
if (!fs23.existsSync(filePath))
|
|
20024
|
+
return /* @__PURE__ */ new Set();
|
|
19537
20025
|
try {
|
|
19538
20026
|
const raw = JSON.parse(fs23.readFileSync(filePath, "utf-8"));
|
|
19539
|
-
if (!Array.isArray(raw?.workflowIds))
|
|
20027
|
+
if (!Array.isArray(raw?.workflowIds))
|
|
20028
|
+
return /* @__PURE__ */ new Set();
|
|
19540
20029
|
return new Set(raw.workflowIds.filter((value) => typeof value === "string"));
|
|
19541
20030
|
} catch {
|
|
19542
20031
|
return /* @__PURE__ */ new Set();
|
|
@@ -19555,8 +20044,10 @@ function markWorkflowDeletedLocally(workflowId) {
|
|
|
19555
20044
|
}
|
|
19556
20045
|
function effectiveWorkflowLabel(entry, hygieneStore) {
|
|
19557
20046
|
const explicitLabel = hygieneStore.getLabel(entry.workflowId);
|
|
19558
|
-
if (explicitLabel)
|
|
19559
|
-
|
|
20047
|
+
if (explicitLabel)
|
|
20048
|
+
return explicitLabel;
|
|
20049
|
+
if (entry.isActive === false)
|
|
20050
|
+
return "archived";
|
|
19560
20051
|
return entry.workflowLabel ?? "experimental";
|
|
19561
20052
|
}
|
|
19562
20053
|
function withEffectiveWorkflowLabels(entries, hygieneStore) {
|
|
@@ -19571,7 +20062,8 @@ function filterLocallyDeletedWorkflows(entries) {
|
|
|
19571
20062
|
}
|
|
19572
20063
|
function listLocalSavedWorkflows() {
|
|
19573
20064
|
const dir = resolveSavedWorkflowsDir();
|
|
19574
|
-
if (!fs23.existsSync(dir))
|
|
20065
|
+
if (!fs23.existsSync(dir))
|
|
20066
|
+
return [];
|
|
19575
20067
|
const entries = fs23.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".json")).map((e) => {
|
|
19576
20068
|
try {
|
|
19577
20069
|
const raw = JSON.parse(fs23.readFileSync(path31.resolve(dir, e.name), "utf-8"));
|
|
@@ -19599,7 +20091,8 @@ async function listSavedWorkflows() {
|
|
|
19599
20091
|
}
|
|
19600
20092
|
try {
|
|
19601
20093
|
const response = await listHostedWorkflows(session);
|
|
19602
|
-
if (!response || !Array.isArray(response.workflows))
|
|
20094
|
+
if (!response || !Array.isArray(response.workflows))
|
|
20095
|
+
return listLocalSavedWorkflows();
|
|
19603
20096
|
return response.workflows.map((workflow) => ({
|
|
19604
20097
|
workflowId: workflow.workflowId,
|
|
19605
20098
|
pipelineId: workflow.workflowId,
|
|
@@ -19697,10 +20190,12 @@ function toDynamicPipelineFromHostedWorkflow(entry, pipeline) {
|
|
|
19697
20190
|
});
|
|
19698
20191
|
const upstreamNodeIdsByTarget = /* @__PURE__ */ new Map();
|
|
19699
20192
|
for (const edge of rawEdges) {
|
|
19700
|
-
if (typeof edge !== "object" || edge === null)
|
|
20193
|
+
if (typeof edge !== "object" || edge === null)
|
|
20194
|
+
continue;
|
|
19701
20195
|
const source = typeof edge.source === "string" ? edge.source : null;
|
|
19702
20196
|
const target = typeof edge.target === "string" ? edge.target : null;
|
|
19703
|
-
if (!source || !target || source === "start-1" || target === "end-1")
|
|
20197
|
+
if (!source || !target || source === "start-1" || target === "end-1")
|
|
20198
|
+
continue;
|
|
19704
20199
|
const existing = upstreamNodeIdsByTarget.get(target) ?? [];
|
|
19705
20200
|
existing.push(source);
|
|
19706
20201
|
upstreamNodeIdsByTarget.set(target, existing);
|
|
@@ -19726,7 +20221,8 @@ function toDynamicPipelineFromHostedWorkflow(entry, pipeline) {
|
|
|
19726
20221
|
}
|
|
19727
20222
|
function toExecutableSavedWorkflowPipeline(entry, pipeline) {
|
|
19728
20223
|
const looksLikeDynamicPipeline = Array.isArray(pipeline.nodes) && pipeline.nodes.every((node) => {
|
|
19729
|
-
if (typeof node !== "object" || node === null)
|
|
20224
|
+
if (typeof node !== "object" || node === null)
|
|
20225
|
+
return false;
|
|
19730
20226
|
const record = node;
|
|
19731
20227
|
return typeof record.id === "string" && typeof record.slug === "string";
|
|
19732
20228
|
});
|
|
@@ -19777,7 +20273,8 @@ async function paginatedSelect(message, allOptions, opts) {
|
|
|
19777
20273
|
message: message + pageInfo,
|
|
19778
20274
|
options
|
|
19779
20275
|
});
|
|
19780
|
-
if (p21.isCancel(choice))
|
|
20276
|
+
if (p21.isCancel(choice))
|
|
20277
|
+
return choice;
|
|
19781
20278
|
if (choice === "__next_page") {
|
|
19782
20279
|
offset += PAGE_SIZE;
|
|
19783
20280
|
continue;
|
|
@@ -19791,7 +20288,8 @@ async function paginatedSelect(message, allOptions, opts) {
|
|
|
19791
20288
|
message: "Search items",
|
|
19792
20289
|
placeholder: "Type to filter..."
|
|
19793
20290
|
});
|
|
19794
|
-
if (p21.isCancel(term))
|
|
20291
|
+
if (p21.isCancel(term))
|
|
20292
|
+
return term;
|
|
19795
20293
|
const searchStr = term.toLowerCase().trim();
|
|
19796
20294
|
if (searchStr) {
|
|
19797
20295
|
filtered = allOptions.filter((o) => {
|
|
@@ -19816,7 +20314,8 @@ function printTemplateCard(node) {
|
|
|
19816
20314
|
const contract = introspectNodeContract(node);
|
|
19817
20315
|
const lines = renderContractCard(contract);
|
|
19818
20316
|
lines.splice(1, 0, `${familyLabel(node.family)} ${node.enabled ? pc33.green("enabled") : pc33.red("disabled")}`);
|
|
19819
|
-
if (node.description)
|
|
20317
|
+
if (node.description)
|
|
20318
|
+
lines.push("", pc33.dim(node.description));
|
|
19820
20319
|
console.log("");
|
|
19821
20320
|
console.log(box5(lines));
|
|
19822
20321
|
console.log("");
|
|
@@ -19916,7 +20415,8 @@ async function runWorkflowPicker(opts) {
|
|
|
19916
20415
|
].join("\n"),
|
|
19917
20416
|
"Authentication Required"
|
|
19918
20417
|
);
|
|
19919
|
-
if (opts.allowBackToHub)
|
|
20418
|
+
if (opts.allowBackToHub)
|
|
20419
|
+
return "back";
|
|
19920
20420
|
return "done";
|
|
19921
20421
|
}
|
|
19922
20422
|
p21.intro(pc33.bold("Workflows"));
|
|
@@ -19947,7 +20447,8 @@ async function runWorkflowPicker(opts) {
|
|
|
19947
20447
|
p21.cancel("Cancelled.");
|
|
19948
20448
|
process.exit(0);
|
|
19949
20449
|
}
|
|
19950
|
-
if (topChoice === "__back_to_hub")
|
|
20450
|
+
if (topChoice === "__back_to_hub")
|
|
20451
|
+
return "back";
|
|
19951
20452
|
if (topChoice === "contracts" && refreshedAccess.state !== "ready") {
|
|
19952
20453
|
p21.note(
|
|
19953
20454
|
[
|
|
@@ -19989,7 +20490,8 @@ async function runWorkflowPicker(opts) {
|
|
|
19989
20490
|
p21.cancel("Cancelled.");
|
|
19990
20491
|
process.exit(0);
|
|
19991
20492
|
}
|
|
19992
|
-
if (contractsMenuChoice === "__back_to_workflow")
|
|
20493
|
+
if (contractsMenuChoice === "__back_to_workflow")
|
|
20494
|
+
break;
|
|
19993
20495
|
if (contractsMenuChoice === "show_tree") {
|
|
19994
20496
|
showDiscoveryTree = true;
|
|
19995
20497
|
continue;
|
|
@@ -20015,9 +20517,11 @@ async function runWorkflowPicker(opts) {
|
|
|
20015
20517
|
p21.cancel("Cancelled.");
|
|
20016
20518
|
process.exit(0);
|
|
20017
20519
|
}
|
|
20018
|
-
if (contractChoice === "__back")
|
|
20520
|
+
if (contractChoice === "__back")
|
|
20521
|
+
continue;
|
|
20019
20522
|
const selected = nodes.find((node) => node.slug === contractChoice);
|
|
20020
|
-
if (!selected)
|
|
20523
|
+
if (!selected)
|
|
20524
|
+
continue;
|
|
20021
20525
|
printTemplateCard(selected);
|
|
20022
20526
|
const contractAction = await p21.select({
|
|
20023
20527
|
message: "Contract actions",
|
|
@@ -20101,7 +20605,8 @@ async function runWorkflowPicker(opts) {
|
|
|
20101
20605
|
p21.cancel("Cancelled.");
|
|
20102
20606
|
process.exit(0);
|
|
20103
20607
|
}
|
|
20104
|
-
if (choice === "__back")
|
|
20608
|
+
if (choice === "__back")
|
|
20609
|
+
break;
|
|
20105
20610
|
const entry = saved.find((w) => w.workflowId === choice);
|
|
20106
20611
|
if (entry) {
|
|
20107
20612
|
const detailSpinner = p21.spinner();
|
|
@@ -20308,7 +20813,8 @@ async function runWorkflowPicker(opts) {
|
|
|
20308
20813
|
p21.cancel("Cancelled.");
|
|
20309
20814
|
process.exit(0);
|
|
20310
20815
|
}
|
|
20311
|
-
if (familyChoice === "__back_to_workflow_menu")
|
|
20816
|
+
if (familyChoice === "__back_to_workflow_menu")
|
|
20817
|
+
break;
|
|
20312
20818
|
if (familyChoice === "__toggle_view_mode") {
|
|
20313
20819
|
const viewChoice = await p21.select({
|
|
20314
20820
|
message: "Select template view mode",
|
|
@@ -20357,9 +20863,11 @@ async function runWorkflowPicker(opts) {
|
|
|
20357
20863
|
p21.cancel("Cancelled.");
|
|
20358
20864
|
process.exit(0);
|
|
20359
20865
|
}
|
|
20360
|
-
if (templateChoice === "__back")
|
|
20866
|
+
if (templateChoice === "__back")
|
|
20867
|
+
break;
|
|
20361
20868
|
const selected = templates.find((t) => t.slug === templateChoice);
|
|
20362
|
-
if (!selected)
|
|
20869
|
+
if (!selected)
|
|
20870
|
+
continue;
|
|
20363
20871
|
printTemplateCard(selected);
|
|
20364
20872
|
while (true) {
|
|
20365
20873
|
const action = await p21.select({
|
|
@@ -20375,7 +20883,8 @@ async function runWorkflowPicker(opts) {
|
|
|
20375
20883
|
p21.cancel("Cancelled.");
|
|
20376
20884
|
process.exit(0);
|
|
20377
20885
|
}
|
|
20378
|
-
if (action === "back_to_templates")
|
|
20886
|
+
if (action === "back_to_templates")
|
|
20887
|
+
break;
|
|
20379
20888
|
if (action === "resolve") {
|
|
20380
20889
|
try {
|
|
20381
20890
|
const resolver = createMachineCapabilityResolver();
|
|
@@ -20404,7 +20913,8 @@ async function runWorkflowPicker(opts) {
|
|
|
20404
20913
|
const contract = introspectNodeContract(selected);
|
|
20405
20914
|
const rawBindings = {};
|
|
20406
20915
|
for (const input of contract.inputs) {
|
|
20407
|
-
if (!input.required)
|
|
20916
|
+
if (!input.required)
|
|
20917
|
+
continue;
|
|
20408
20918
|
const value = await p21.text({
|
|
20409
20919
|
message: `${selected.displayName} \u2192 ${input.key}`,
|
|
20410
20920
|
placeholder: `Enter ${input.key}`
|
|
@@ -20485,7 +20995,8 @@ async function renderWorkflowIntelligenceSummary(pipeline, capabilities, phase)
|
|
|
20485
20995
|
const missingRequired = [];
|
|
20486
20996
|
if (contract) {
|
|
20487
20997
|
for (const input2 of contract.inputs) {
|
|
20488
|
-
if (!input2.required)
|
|
20998
|
+
if (!input2.required)
|
|
20999
|
+
continue;
|
|
20489
21000
|
const value = node.bindings[input2.key];
|
|
20490
21001
|
if (value === void 0 || value === null || value === "") {
|
|
20491
21002
|
missingRequired.push(input2.key);
|
|
@@ -20562,8 +21073,10 @@ Examples:
|
|
|
20562
21073
|
}
|
|
20563
21074
|
const registry = createCmsCapabilityRegistryClient();
|
|
20564
21075
|
const query = {};
|
|
20565
|
-
if (opts.family)
|
|
20566
|
-
|
|
21076
|
+
if (opts.family)
|
|
21077
|
+
query.family = opts.family;
|
|
21078
|
+
if (opts.search)
|
|
21079
|
+
query.search = opts.search;
|
|
20567
21080
|
try {
|
|
20568
21081
|
const { nodes, meta } = await registry.listCapabilities(
|
|
20569
21082
|
Object.keys(query).length > 0 ? query : void 0
|
|
@@ -20693,7 +21206,8 @@ function ensureSecureFile(filePath) {
|
|
|
20693
21206
|
}
|
|
20694
21207
|
function readHarnessCredentials(harnessId) {
|
|
20695
21208
|
const filePath = resolveHarnessAuthFile(harnessId);
|
|
20696
|
-
if (!fs24.existsSync(filePath))
|
|
21209
|
+
if (!fs24.existsSync(filePath))
|
|
21210
|
+
return {};
|
|
20697
21211
|
try {
|
|
20698
21212
|
const parsed = JSON.parse(fs24.readFileSync(filePath, "utf-8"));
|
|
20699
21213
|
const creds = {};
|
|
@@ -20744,8 +21258,10 @@ function setHarnessCredentials(harnessId, updates) {
|
|
|
20744
21258
|
ensureSecureFile(filePath);
|
|
20745
21259
|
}
|
|
20746
21260
|
function maskSecret(value) {
|
|
20747
|
-
if (!value)
|
|
20748
|
-
|
|
21261
|
+
if (!value)
|
|
21262
|
+
return "(not set)";
|
|
21263
|
+
if (value.length <= 4)
|
|
21264
|
+
return "****";
|
|
20749
21265
|
return `${"*".repeat(Math.max(4, value.length - 4))}${value.slice(-4)}`;
|
|
20750
21266
|
}
|
|
20751
21267
|
|
|
@@ -20845,8 +21361,10 @@ async function createOpenAgentsSession(config, input) {
|
|
|
20845
21361
|
const body = {
|
|
20846
21362
|
prompt: input.prompt
|
|
20847
21363
|
};
|
|
20848
|
-
if (input.repoUrl)
|
|
20849
|
-
|
|
21364
|
+
if (input.repoUrl)
|
|
21365
|
+
body.repoUrl = input.repoUrl;
|
|
21366
|
+
if (input.branch)
|
|
21367
|
+
body.branch = input.branch;
|
|
20850
21368
|
const controller = new AbortController();
|
|
20851
21369
|
const timeoutId = setTimeout(
|
|
20852
21370
|
() => controller.abort(),
|
|
@@ -20982,7 +21500,8 @@ function writeOpenAgentsConfig(config) {
|
|
|
20982
21500
|
setHarnessCredential("open-agents", "apiKey", config.apiKey);
|
|
20983
21501
|
}
|
|
20984
21502
|
function validateBackendType(value) {
|
|
20985
|
-
if (value === "local" || value === "hosted")
|
|
21503
|
+
if (value === "local" || value === "hosted")
|
|
21504
|
+
return value;
|
|
20986
21505
|
return "local";
|
|
20987
21506
|
}
|
|
20988
21507
|
function validateAuthMode(value) {
|
|
@@ -20995,17 +21514,25 @@ function validateAuthMode(value) {
|
|
|
20995
21514
|
// src/commands/open-agents.ts
|
|
20996
21515
|
init_banner();
|
|
20997
21516
|
function statusColor2(status) {
|
|
20998
|
-
if (status === "running")
|
|
20999
|
-
|
|
21000
|
-
if (status === "
|
|
21001
|
-
|
|
21517
|
+
if (status === "running")
|
|
21518
|
+
return pc34.green(status);
|
|
21519
|
+
if (status === "completed")
|
|
21520
|
+
return pc34.cyan(status);
|
|
21521
|
+
if (status === "failed" || status === "cancelled")
|
|
21522
|
+
return pc34.red(status);
|
|
21523
|
+
if (status === "waiting" || status === "idle")
|
|
21524
|
+
return pc34.yellow(status);
|
|
21002
21525
|
return pc34.dim(status);
|
|
21003
21526
|
}
|
|
21004
21527
|
function sandboxBadge(state) {
|
|
21005
|
-
if (state === "running")
|
|
21006
|
-
|
|
21007
|
-
if (state === "
|
|
21008
|
-
|
|
21528
|
+
if (state === "running")
|
|
21529
|
+
return pc34.green("running");
|
|
21530
|
+
if (state === "hibernating")
|
|
21531
|
+
return pc34.yellow("hibernating");
|
|
21532
|
+
if (state === "stopped")
|
|
21533
|
+
return pc34.dim("stopped");
|
|
21534
|
+
if (state === "error")
|
|
21535
|
+
return pc34.red("error");
|
|
21009
21536
|
return pc34.dim(state);
|
|
21010
21537
|
}
|
|
21011
21538
|
function hr7(width = 72) {
|
|
@@ -21033,8 +21560,10 @@ function printSessionCard(session) {
|
|
|
21033
21560
|
`${pc34.dim("Events:")} ${session.eventCount}`,
|
|
21034
21561
|
`${pc34.dim("Created:")} ${session.createdAt}`
|
|
21035
21562
|
];
|
|
21036
|
-
if (session.repoUrl)
|
|
21037
|
-
|
|
21563
|
+
if (session.repoUrl)
|
|
21564
|
+
lines.push(`${pc34.dim("Repo:")} ${session.repoUrl}`);
|
|
21565
|
+
if (session.branch)
|
|
21566
|
+
lines.push(`${pc34.dim("Branch:")} ${session.branch}`);
|
|
21038
21567
|
if (session.prompt) {
|
|
21039
21568
|
const truncated = session.prompt.length > 80 ? session.prompt.slice(0, 77) + "..." : session.prompt;
|
|
21040
21569
|
lines.push(`${pc34.dim("Prompt:")} ${truncated}`);
|
|
@@ -21083,7 +21612,8 @@ async function runOpenAgentsHub(opts) {
|
|
|
21083
21612
|
...opts?.allowBackToHub ? [{ value: "__back_to_hub", label: "\u2190 Back to harness type" }] : []
|
|
21084
21613
|
]
|
|
21085
21614
|
});
|
|
21086
|
-
if (p22.isCancel(action) || action === "__back_to_hub")
|
|
21615
|
+
if (p22.isCancel(action) || action === "__back_to_hub")
|
|
21616
|
+
return "back";
|
|
21087
21617
|
if (action === "setup") {
|
|
21088
21618
|
await runSetupFlow(config);
|
|
21089
21619
|
continue;
|
|
@@ -21119,7 +21649,8 @@ async function runOpenAgentsHub(opts) {
|
|
|
21119
21649
|
}
|
|
21120
21650
|
if (action === "list") {
|
|
21121
21651
|
const listResult = await runSessionListFlow(config);
|
|
21122
|
-
if (listResult === "back")
|
|
21652
|
+
if (listResult === "back")
|
|
21653
|
+
continue;
|
|
21123
21654
|
return "done";
|
|
21124
21655
|
}
|
|
21125
21656
|
if (action === "create") {
|
|
@@ -21141,7 +21672,8 @@ async function runSetupFlow(currentConfig) {
|
|
|
21141
21672
|
],
|
|
21142
21673
|
initialValue: currentConfig.backendType
|
|
21143
21674
|
});
|
|
21144
|
-
if (p22.isCancel(backendChoice))
|
|
21675
|
+
if (p22.isCancel(backendChoice))
|
|
21676
|
+
return;
|
|
21145
21677
|
const authMode = backendChoice === "hosted" ? await p22.select({
|
|
21146
21678
|
message: "Hosted authentication strategy",
|
|
21147
21679
|
options: [
|
|
@@ -21158,13 +21690,15 @@ async function runSetupFlow(currentConfig) {
|
|
|
21158
21690
|
],
|
|
21159
21691
|
initialValue: currentConfig.authMode === "api-key" || currentConfig.authMode === "vercel-managed" ? currentConfig.authMode : "api-key"
|
|
21160
21692
|
}) : "none";
|
|
21161
|
-
if (p22.isCancel(authMode))
|
|
21693
|
+
if (p22.isCancel(authMode))
|
|
21694
|
+
return;
|
|
21162
21695
|
const endpoint = await p22.text({
|
|
21163
21696
|
message: "Backend endpoint",
|
|
21164
21697
|
placeholder: currentConfig.endpoint,
|
|
21165
21698
|
initialValue: currentConfig.endpoint
|
|
21166
21699
|
});
|
|
21167
|
-
if (p22.isCancel(endpoint))
|
|
21700
|
+
if (p22.isCancel(endpoint))
|
|
21701
|
+
return;
|
|
21168
21702
|
let apiKeyValue;
|
|
21169
21703
|
if (authMode === "api-key") {
|
|
21170
21704
|
const existingKeyMasked = maskSecret(currentConfig.apiKey);
|
|
@@ -21177,12 +21711,14 @@ async function runSetupFlow(currentConfig) {
|
|
|
21177
21711
|
],
|
|
21178
21712
|
initialValue: currentConfig.apiKey ? "keep" : "replace"
|
|
21179
21713
|
});
|
|
21180
|
-
if (p22.isCancel(apiKeyMode))
|
|
21714
|
+
if (p22.isCancel(apiKeyMode))
|
|
21715
|
+
return;
|
|
21181
21716
|
if (apiKeyMode === "replace") {
|
|
21182
21717
|
const entered = await p22.password({
|
|
21183
21718
|
message: "Open Agents API key"
|
|
21184
21719
|
});
|
|
21185
|
-
if (p22.isCancel(entered))
|
|
21720
|
+
if (p22.isCancel(entered))
|
|
21721
|
+
return;
|
|
21186
21722
|
apiKeyValue = String(entered).trim() || void 0;
|
|
21187
21723
|
} else if (apiKeyMode === "keep") {
|
|
21188
21724
|
apiKeyValue = currentConfig.apiKey;
|
|
@@ -21197,12 +21733,14 @@ async function runSetupFlow(currentConfig) {
|
|
|
21197
21733
|
placeholder: currentConfig.defaultRepo ?? "",
|
|
21198
21734
|
initialValue: currentConfig.defaultRepo ?? ""
|
|
21199
21735
|
});
|
|
21200
|
-
if (p22.isCancel(defaultRepo))
|
|
21736
|
+
if (p22.isCancel(defaultRepo))
|
|
21737
|
+
return;
|
|
21201
21738
|
const confirmed = await p22.confirm({
|
|
21202
21739
|
message: "Save Open Agents configuration?",
|
|
21203
21740
|
initialValue: true
|
|
21204
21741
|
});
|
|
21205
|
-
if (p22.isCancel(confirmed) || !confirmed)
|
|
21742
|
+
if (p22.isCancel(confirmed) || !confirmed)
|
|
21743
|
+
return;
|
|
21206
21744
|
const newConfig = {
|
|
21207
21745
|
...currentConfig,
|
|
21208
21746
|
backendType: backendChoice,
|
|
@@ -21242,9 +21780,11 @@ async function runSessionListFlow(config) {
|
|
|
21242
21780
|
{ value: "__back", label: "\u2190 Back" }
|
|
21243
21781
|
]
|
|
21244
21782
|
});
|
|
21245
|
-
if (p22.isCancel(sessionChoice) || sessionChoice === "__back")
|
|
21783
|
+
if (p22.isCancel(sessionChoice) || sessionChoice === "__back")
|
|
21784
|
+
return "back";
|
|
21246
21785
|
const selected = sessions.find((s) => s.sessionId === sessionChoice);
|
|
21247
|
-
if (!selected)
|
|
21786
|
+
if (!selected)
|
|
21787
|
+
continue;
|
|
21248
21788
|
printSessionCard(selected);
|
|
21249
21789
|
const nextStep = await p22.select({
|
|
21250
21790
|
message: "What next?",
|
|
@@ -21253,7 +21793,8 @@ async function runSessionListFlow(config) {
|
|
|
21253
21793
|
{ value: "back_to_list", label: "\u2190 Back to session list" }
|
|
21254
21794
|
]
|
|
21255
21795
|
});
|
|
21256
|
-
if (p22.isCancel(nextStep) || nextStep === "back_to_list")
|
|
21796
|
+
if (p22.isCancel(nextStep) || nextStep === "back_to_list")
|
|
21797
|
+
continue;
|
|
21257
21798
|
if (nextStep === "events") {
|
|
21258
21799
|
try {
|
|
21259
21800
|
const events = await pollSessionEvents(config, selected.sessionId);
|
|
@@ -21280,24 +21821,28 @@ async function runCreateSessionFlow(config) {
|
|
|
21280
21821
|
message: "What should the agent do?",
|
|
21281
21822
|
placeholder: "Describe the task for the agent"
|
|
21282
21823
|
});
|
|
21283
|
-
if (p22.isCancel(prompt) || !String(prompt).trim())
|
|
21824
|
+
if (p22.isCancel(prompt) || !String(prompt).trim())
|
|
21825
|
+
return;
|
|
21284
21826
|
const repoUrl = await p22.text({
|
|
21285
21827
|
message: "Repository URL (optional)",
|
|
21286
21828
|
placeholder: config.defaultRepo ?? "https://github.com/org/repo",
|
|
21287
21829
|
initialValue: config.defaultRepo ?? ""
|
|
21288
21830
|
});
|
|
21289
|
-
if (p22.isCancel(repoUrl))
|
|
21831
|
+
if (p22.isCancel(repoUrl))
|
|
21832
|
+
return;
|
|
21290
21833
|
const branch = await p22.text({
|
|
21291
21834
|
message: "Branch (optional)",
|
|
21292
21835
|
placeholder: config.defaultBranch ?? "main",
|
|
21293
21836
|
initialValue: config.defaultBranch ?? ""
|
|
21294
21837
|
});
|
|
21295
|
-
if (p22.isCancel(branch))
|
|
21838
|
+
if (p22.isCancel(branch))
|
|
21839
|
+
return;
|
|
21296
21840
|
const confirmed = await p22.confirm({
|
|
21297
21841
|
message: "Create agent session?",
|
|
21298
21842
|
initialValue: true
|
|
21299
21843
|
});
|
|
21300
|
-
if (p22.isCancel(confirmed) || !confirmed)
|
|
21844
|
+
if (p22.isCancel(confirmed) || !confirmed)
|
|
21845
|
+
return;
|
|
21301
21846
|
const spinner10 = p22.spinner();
|
|
21302
21847
|
spinner10.start("Creating session...");
|
|
21303
21848
|
try {
|
|
@@ -21318,7 +21863,8 @@ async function runResumeSessionFlow(config) {
|
|
|
21318
21863
|
message: "Session ID",
|
|
21319
21864
|
placeholder: "Paste the session ID to resume"
|
|
21320
21865
|
});
|
|
21321
|
-
if (p22.isCancel(sessionId) || !String(sessionId).trim())
|
|
21866
|
+
if (p22.isCancel(sessionId) || !String(sessionId).trim())
|
|
21867
|
+
return;
|
|
21322
21868
|
const spinner10 = p22.spinner();
|
|
21323
21869
|
spinner10.start("Resuming session...");
|
|
21324
21870
|
try {
|
|
@@ -21595,7 +22141,8 @@ async function executeHeadlessPrompt(prompt, configOverride) {
|
|
|
21595
22141
|
timedOut = true;
|
|
21596
22142
|
child.kill("SIGTERM");
|
|
21597
22143
|
setTimeout(() => {
|
|
21598
|
-
if (!child.killed)
|
|
22144
|
+
if (!child.killed)
|
|
22145
|
+
child.kill("SIGKILL");
|
|
21599
22146
|
}, 5e3);
|
|
21600
22147
|
}, config.timeoutMs) : null;
|
|
21601
22148
|
child.stdout.on("data", (data) => {
|
|
@@ -21605,7 +22152,8 @@ async function executeHeadlessPrompt(prompt, configOverride) {
|
|
|
21605
22152
|
stderr += data.toString();
|
|
21606
22153
|
});
|
|
21607
22154
|
child.on("close", (exitCode, signal) => {
|
|
21608
|
-
if (timeoutHandle)
|
|
22155
|
+
if (timeoutHandle)
|
|
22156
|
+
clearTimeout(timeoutHandle);
|
|
21609
22157
|
resolve2({
|
|
21610
22158
|
exitCode,
|
|
21611
22159
|
timedOut,
|
|
@@ -21616,7 +22164,8 @@ async function executeHeadlessPrompt(prompt, configOverride) {
|
|
|
21616
22164
|
});
|
|
21617
22165
|
});
|
|
21618
22166
|
child.on("error", (err) => {
|
|
21619
|
-
if (timeoutHandle)
|
|
22167
|
+
if (timeoutHandle)
|
|
22168
|
+
clearTimeout(timeoutHandle);
|
|
21620
22169
|
resolve2({
|
|
21621
22170
|
exitCode: null,
|
|
21622
22171
|
timedOut: false,
|
|
@@ -21813,7 +22362,8 @@ function writeQwenCodeConfig(config) {
|
|
|
21813
22362
|
function mergeHarnessEnv(runtimeEnv, credentials) {
|
|
21814
22363
|
const merged = {};
|
|
21815
22364
|
for (const [key, value] of Object.entries(runtimeEnv)) {
|
|
21816
|
-
if (typeof value === "string")
|
|
22365
|
+
if (typeof value === "string")
|
|
22366
|
+
merged[key] = value;
|
|
21817
22367
|
}
|
|
21818
22368
|
for (const key of QWEN_CODE_SUPPORTED_ENV_KEYS) {
|
|
21819
22369
|
const secret = credentials[key];
|
|
@@ -21840,7 +22390,8 @@ async function runQwenCodeHub(opts) {
|
|
|
21840
22390
|
...opts?.allowBackToHub ? [{ value: "__back_to_hub", label: "\u2190 Back to harness type" }] : []
|
|
21841
22391
|
]
|
|
21842
22392
|
});
|
|
21843
|
-
if (p23.isCancel(action) || action === "__back_to_hub")
|
|
22393
|
+
if (p23.isCancel(action) || action === "__back_to_hub")
|
|
22394
|
+
return "back";
|
|
21844
22395
|
if (action === "health") {
|
|
21845
22396
|
const env = detectEnvironment(config.binaryPath, config.env);
|
|
21846
22397
|
const guidance = buildSetupGuidance(env);
|
|
@@ -21856,9 +22407,11 @@ async function runQwenCodeHub(opts) {
|
|
|
21856
22407
|
message: "Enter prompt for Qwen Code",
|
|
21857
22408
|
placeholder: "Describe what you want to build or analyze..."
|
|
21858
22409
|
});
|
|
21859
|
-
if (p23.isCancel(rawPrompt))
|
|
22410
|
+
if (p23.isCancel(rawPrompt))
|
|
22411
|
+
continue;
|
|
21860
22412
|
const prompt = String(rawPrompt).trim();
|
|
21861
|
-
if (!prompt)
|
|
22413
|
+
if (!prompt)
|
|
22414
|
+
continue;
|
|
21862
22415
|
const runSpinner = p23.spinner();
|
|
21863
22416
|
runSpinner.start(`Running qwen -p (model: ${config.defaultModel})...`);
|
|
21864
22417
|
const result = await executeHeadlessPrompt(prompt, config);
|
|
@@ -21913,7 +22466,8 @@ async function runConfigureFlow(currentConfig) {
|
|
|
21913
22466
|
placeholder: "qwen3-coder",
|
|
21914
22467
|
defaultValue: currentConfig.defaultModel
|
|
21915
22468
|
});
|
|
21916
|
-
if (p23.isCancel(modelInput))
|
|
22469
|
+
if (p23.isCancel(modelInput))
|
|
22470
|
+
return;
|
|
21917
22471
|
const modeInput = await p23.select({
|
|
21918
22472
|
message: "Approval mode",
|
|
21919
22473
|
options: QWEN_CODE_APPROVAL_MODES.map((mode) => ({
|
|
@@ -21923,13 +22477,15 @@ async function runConfigureFlow(currentConfig) {
|
|
|
21923
22477
|
})),
|
|
21924
22478
|
initialValue: currentConfig.approvalMode
|
|
21925
22479
|
});
|
|
21926
|
-
if (p23.isCancel(modeInput))
|
|
22480
|
+
if (p23.isCancel(modeInput))
|
|
22481
|
+
return;
|
|
21927
22482
|
const binaryInput = await p23.text({
|
|
21928
22483
|
message: "Binary path",
|
|
21929
22484
|
placeholder: "qwen",
|
|
21930
22485
|
defaultValue: currentConfig.binaryPath
|
|
21931
22486
|
});
|
|
21932
|
-
if (p23.isCancel(binaryInput))
|
|
22487
|
+
if (p23.isCancel(binaryInput))
|
|
22488
|
+
return;
|
|
21933
22489
|
const authAction = await p23.select({
|
|
21934
22490
|
message: "Authentication setup",
|
|
21935
22491
|
options: [
|
|
@@ -21951,7 +22507,8 @@ async function runConfigureFlow(currentConfig) {
|
|
|
21951
22507
|
],
|
|
21952
22508
|
initialValue: "skip"
|
|
21953
22509
|
});
|
|
21954
|
-
if (p23.isCancel(authAction))
|
|
22510
|
+
if (p23.isCancel(authAction))
|
|
22511
|
+
return;
|
|
21955
22512
|
const nextEnv = { ...currentConfig.env };
|
|
21956
22513
|
if (authAction === "set-key") {
|
|
21957
22514
|
const providerKey = await p23.select({
|
|
@@ -21968,15 +22525,19 @@ async function runConfigureFlow(currentConfig) {
|
|
|
21968
22525
|
}
|
|
21969
22526
|
]
|
|
21970
22527
|
});
|
|
21971
|
-
if (p23.isCancel(providerKey))
|
|
21972
|
-
|
|
22528
|
+
if (p23.isCancel(providerKey))
|
|
22529
|
+
return;
|
|
22530
|
+
if (providerKey === "__back_to_auth_setup")
|
|
22531
|
+
return;
|
|
21973
22532
|
const keyValue = await p23.password({
|
|
21974
22533
|
message: `${providerKey} value`,
|
|
21975
22534
|
validate: (value) => {
|
|
21976
|
-
if (!value || String(value).trim().length === 0)
|
|
22535
|
+
if (!value || String(value).trim().length === 0)
|
|
22536
|
+
return "Key value is required.";
|
|
21977
22537
|
}
|
|
21978
22538
|
});
|
|
21979
|
-
if (p23.isCancel(keyValue))
|
|
22539
|
+
if (p23.isCancel(keyValue))
|
|
22540
|
+
return;
|
|
21980
22541
|
nextEnv[providerKey] = String(keyValue).trim();
|
|
21981
22542
|
} else if (authAction === "clear-keys") {
|
|
21982
22543
|
for (const key of QWEN_CODE_SUPPORTED_ENV_KEYS) {
|
|
@@ -21987,7 +22548,8 @@ async function runConfigureFlow(currentConfig) {
|
|
|
21987
22548
|
message: `Save Qwen Code config? (model: ${String(modelInput)}, mode: ${modeInput}, binary: ${String(binaryInput)})`,
|
|
21988
22549
|
initialValue: true
|
|
21989
22550
|
});
|
|
21990
|
-
if (p23.isCancel(confirmed) || !confirmed)
|
|
22551
|
+
if (p23.isCancel(confirmed) || !confirmed)
|
|
22552
|
+
return;
|
|
21991
22553
|
writeQwenCodeConfig({
|
|
21992
22554
|
...currentConfig,
|
|
21993
22555
|
defaultModel: String(modelInput).trim() || currentConfig.defaultModel,
|
|
@@ -22053,9 +22615,11 @@ init_home();
|
|
|
22053
22615
|
var program = new Command();
|
|
22054
22616
|
var DATA_DIR_OPTION_HELP = "Growthub data directory root (isolates local instance state)";
|
|
22055
22617
|
function resolveSurfaceProfile(config) {
|
|
22056
|
-
if (typeof config !== "object" || config === null)
|
|
22618
|
+
if (typeof config !== "object" || config === null)
|
|
22619
|
+
return null;
|
|
22057
22620
|
const surface = config.surface;
|
|
22058
|
-
if (typeof surface !== "object" || surface === null)
|
|
22621
|
+
if (typeof surface !== "object" || surface === null)
|
|
22622
|
+
return null;
|
|
22059
22623
|
const profile = surface.profile;
|
|
22060
22624
|
return profile === "dx" || profile === "gtm" ? profile : null;
|
|
22061
22625
|
}
|
|
@@ -22138,7 +22702,8 @@ async function runNativeIntelligenceHub() {
|
|
|
22138
22702
|
{ value: "__back_to_hub", label: "\u2190 Back to main menu" }
|
|
22139
22703
|
]
|
|
22140
22704
|
});
|
|
22141
|
-
if (p24.isCancel(action) || action === "__back_to_hub")
|
|
22705
|
+
if (p24.isCancel(action) || action === "__back_to_hub")
|
|
22706
|
+
return "back";
|
|
22142
22707
|
if (action === "setup") {
|
|
22143
22708
|
const setupLines = [
|
|
22144
22709
|
`OS: ${status.osLabel}`,
|
|
@@ -22167,14 +22732,17 @@ async function runNativeIntelligenceHub() {
|
|
|
22167
22732
|
message: "Choose local custom model adapter",
|
|
22168
22733
|
options: modelOptions
|
|
22169
22734
|
});
|
|
22170
|
-
if (p24.isCancel(adapterChoice) || adapterChoice === "__back_to_local_intel")
|
|
22735
|
+
if (p24.isCancel(adapterChoice) || adapterChoice === "__back_to_local_intel")
|
|
22736
|
+
continue;
|
|
22171
22737
|
const chosenModel = adapterChoice === "__custom_model" ? await promptForCustomModel(defaultModel) : adapterChoice;
|
|
22172
|
-
if (!chosenModel)
|
|
22738
|
+
if (!chosenModel)
|
|
22739
|
+
continue;
|
|
22173
22740
|
const applyConfirmed = await p24.confirm({
|
|
22174
22741
|
message: `Apply Local Intelligence config for model "${chosenModel}"?`,
|
|
22175
22742
|
initialValue: true
|
|
22176
22743
|
});
|
|
22177
|
-
if (p24.isCancel(applyConfirmed) || !applyConfirmed)
|
|
22744
|
+
if (p24.isCancel(applyConfirmed) || !applyConfirmed)
|
|
22745
|
+
continue;
|
|
22178
22746
|
const applySpinner = p24.spinner();
|
|
22179
22747
|
applySpinner.start(`Applying model config (${chosenModel})...`);
|
|
22180
22748
|
writeIntelligenceConfig({
|
|
@@ -22204,7 +22772,8 @@ async function runNativeIntelligenceHub() {
|
|
|
22204
22772
|
message: "Enter your local intelligence prompt",
|
|
22205
22773
|
placeholder: "Describe what you want to create/analyze"
|
|
22206
22774
|
});
|
|
22207
|
-
if (p24.isCancel(customPrompt))
|
|
22775
|
+
if (p24.isCancel(customPrompt))
|
|
22776
|
+
continue;
|
|
22208
22777
|
const prompt = String(customPrompt).trim();
|
|
22209
22778
|
if (!prompt) {
|
|
22210
22779
|
p24.note("Prompt was empty. Nothing was run.", "Local Intelligence");
|
|
@@ -22258,7 +22827,8 @@ function buildSetupCommands(osLabel, baseUrl, recommendedModel) {
|
|
|
22258
22827
|
}
|
|
22259
22828
|
function prioritizeModelOptions(models, favoriteModel, recommendedModel) {
|
|
22260
22829
|
const unique3 = [...new Set(models)];
|
|
22261
|
-
if (unique3.length === 0)
|
|
22830
|
+
if (unique3.length === 0)
|
|
22831
|
+
return unique3;
|
|
22262
22832
|
if (favoriteModel && unique3.includes(favoriteModel)) {
|
|
22263
22833
|
return [favoriteModel, ...unique3.filter((id) => id !== favoriteModel)];
|
|
22264
22834
|
}
|
|
@@ -22273,14 +22843,17 @@ async function promptForCustomModel(defaultModel) {
|
|
|
22273
22843
|
placeholder: "example: gemma3:4b",
|
|
22274
22844
|
defaultValue: defaultModel
|
|
22275
22845
|
});
|
|
22276
|
-
if (p24.isCancel(input))
|
|
22846
|
+
if (p24.isCancel(input))
|
|
22847
|
+
return null;
|
|
22277
22848
|
const trimmed = String(input).trim();
|
|
22278
22849
|
return trimmed.length > 0 ? trimmed : null;
|
|
22279
22850
|
}
|
|
22280
22851
|
function inferCanonicalModelId(modelId) {
|
|
22281
22852
|
const lower = modelId.toLowerCase();
|
|
22282
|
-
if (lower.includes("gemma3n"))
|
|
22283
|
-
|
|
22853
|
+
if (lower.includes("gemma3n"))
|
|
22854
|
+
return "gemma3n";
|
|
22855
|
+
if (lower.includes("codegemma"))
|
|
22856
|
+
return "codegemma";
|
|
22284
22857
|
return "gemma3";
|
|
22285
22858
|
}
|
|
22286
22859
|
async function runLocalPromptChat(baseUrl, defaultModel) {
|
|
@@ -22311,10 +22884,13 @@ async function runLocalPromptChat(baseUrl, defaultModel) {
|
|
|
22311
22884
|
message: `Prompt (${activeModel})`,
|
|
22312
22885
|
placeholder: "Ask anything..."
|
|
22313
22886
|
});
|
|
22314
|
-
if (p24.isCancel(rawPrompt))
|
|
22887
|
+
if (p24.isCancel(rawPrompt))
|
|
22888
|
+
return;
|
|
22315
22889
|
const prompt = String(rawPrompt).trim();
|
|
22316
|
-
if (prompt === "/back")
|
|
22317
|
-
|
|
22890
|
+
if (prompt === "/back")
|
|
22891
|
+
return;
|
|
22892
|
+
if (prompt.length === 0)
|
|
22893
|
+
continue;
|
|
22318
22894
|
const historyContext = renderHistoryContext(thread.messages, 8);
|
|
22319
22895
|
const runSpinner = p24.spinner();
|
|
22320
22896
|
runSpinner.start("Invoking local model...");
|
|
@@ -22392,7 +22968,8 @@ async function completeWithRetry(backend, baseConfig, input) {
|
|
|
22392
22968
|
return await backend.complete(input);
|
|
22393
22969
|
} catch (err) {
|
|
22394
22970
|
const message = err instanceof Error ? err.message.toLowerCase() : String(err).toLowerCase();
|
|
22395
|
-
if (!message.includes("aborted"))
|
|
22971
|
+
if (!message.includes("aborted"))
|
|
22972
|
+
throw err;
|
|
22396
22973
|
const retryBackend = createNativeIntelligenceBackend({
|
|
22397
22974
|
...baseConfig,
|
|
22398
22975
|
timeoutMs: Math.max(baseConfig.timeoutMs, 18e4)
|
|
@@ -22484,9 +23061,11 @@ async function loadRuntimeContracts() {
|
|
|
22484
23061
|
}
|
|
22485
23062
|
async function loadRuntimeWorkflows() {
|
|
22486
23063
|
const session = readSession();
|
|
22487
|
-
if (!session || isSessionExpired(session))
|
|
23064
|
+
if (!session || isSessionExpired(session))
|
|
23065
|
+
return [];
|
|
22488
23066
|
const response = await listHostedWorkflows(session);
|
|
22489
|
-
if (!response?.workflows)
|
|
23067
|
+
if (!response?.workflows)
|
|
23068
|
+
return [];
|
|
22490
23069
|
return response.workflows.map((workflow) => ({
|
|
22491
23070
|
workflowId: workflow.workflowId,
|
|
22492
23071
|
name: workflow.name,
|
|
@@ -22630,7 +23209,8 @@ async function runDiscoveryHub(opts) {
|
|
|
22630
23209
|
p24.cancel("Cancelled.");
|
|
22631
23210
|
process.exit(0);
|
|
22632
23211
|
}
|
|
22633
|
-
if (harnessType === "__back_to_hub")
|
|
23212
|
+
if (harnessType === "__back_to_hub")
|
|
23213
|
+
break;
|
|
22634
23214
|
if (harnessType === "paperclip") {
|
|
22635
23215
|
let paperclipDone = false;
|
|
22636
23216
|
while (!paperclipDone) {
|
|
@@ -22657,7 +23237,8 @@ async function runDiscoveryHub(opts) {
|
|
|
22657
23237
|
p24.cancel("Cancelled.");
|
|
22658
23238
|
process.exit(0);
|
|
22659
23239
|
}
|
|
22660
|
-
if (appModeChoice === "__back_to_harness")
|
|
23240
|
+
if (appModeChoice === "__back_to_harness")
|
|
23241
|
+
break;
|
|
22661
23242
|
if (appModeChoice === "load") {
|
|
22662
23243
|
const existingSurfaces = listLocalSurfaces();
|
|
22663
23244
|
if (existingSurfaces.length === 0) {
|
|
@@ -22734,12 +23315,14 @@ async function runDiscoveryHub(opts) {
|
|
|
22734
23315
|
}
|
|
22735
23316
|
if (harnessType === "open-agents") {
|
|
22736
23317
|
const oaResult = await runOpenAgentsHub({ allowBackToHub: true });
|
|
22737
|
-
if (oaResult === "back")
|
|
23318
|
+
if (oaResult === "back")
|
|
23319
|
+
continue;
|
|
22738
23320
|
return;
|
|
22739
23321
|
}
|
|
22740
23322
|
if (harnessType === "qwen-code") {
|
|
22741
23323
|
const qwenResult = await runQwenCodeHub({ allowBackToHub: true });
|
|
22742
|
-
if (qwenResult === "back")
|
|
23324
|
+
if (qwenResult === "back")
|
|
23325
|
+
continue;
|
|
22743
23326
|
return;
|
|
22744
23327
|
}
|
|
22745
23328
|
}
|
|
@@ -22747,17 +23330,20 @@ async function runDiscoveryHub(opts) {
|
|
|
22747
23330
|
}
|
|
22748
23331
|
if (surfaceChoice === "kits") {
|
|
22749
23332
|
const result2 = await runInteractivePicker({ allowBackToHub: true });
|
|
22750
|
-
if (result2 === "back")
|
|
23333
|
+
if (result2 === "back")
|
|
23334
|
+
continue;
|
|
22751
23335
|
return;
|
|
22752
23336
|
}
|
|
22753
23337
|
if (surfaceChoice === "workflows") {
|
|
22754
23338
|
const result2 = await runWorkflowPicker({ allowBackToHub: true });
|
|
22755
|
-
if (result2 === "back")
|
|
23339
|
+
if (result2 === "back")
|
|
23340
|
+
continue;
|
|
22756
23341
|
return;
|
|
22757
23342
|
}
|
|
22758
23343
|
if (surfaceChoice === "native-intelligence") {
|
|
22759
23344
|
const result2 = await runNativeIntelligenceHub();
|
|
22760
|
-
if (result2 === "back")
|
|
23345
|
+
if (result2 === "back")
|
|
23346
|
+
continue;
|
|
22761
23347
|
return;
|
|
22762
23348
|
}
|
|
22763
23349
|
if (surfaceChoice === "hosted-auth") {
|
|
@@ -22765,7 +23351,8 @@ async function runDiscoveryHub(opts) {
|
|
|
22765
23351
|
continue;
|
|
22766
23352
|
}
|
|
22767
23353
|
const result = await runTemplatePicker({ allowBackToHub: true });
|
|
22768
|
-
if (result === "back")
|
|
23354
|
+
if (result === "back")
|
|
23355
|
+
continue;
|
|
22769
23356
|
return;
|
|
22770
23357
|
}
|
|
22771
23358
|
}
|
|
@@ -22775,16 +23362,20 @@ function isInstallerMode() {
|
|
|
22775
23362
|
function listLocalSurfaces() {
|
|
22776
23363
|
const homeDir = resolvePaperclipHomeDir();
|
|
22777
23364
|
const instancesDir = path35.resolve(homeDir, "instances");
|
|
22778
|
-
if (!fs27.existsSync(instancesDir))
|
|
23365
|
+
if (!fs27.existsSync(instancesDir))
|
|
23366
|
+
return [];
|
|
22779
23367
|
return fs27.readdirSync(instancesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => {
|
|
22780
23368
|
const instanceId = entry.name;
|
|
22781
23369
|
const configPath = path35.resolve(instancesDir, instanceId, "config.json");
|
|
22782
|
-
if (!fs27.existsSync(configPath))
|
|
23370
|
+
if (!fs27.existsSync(configPath))
|
|
23371
|
+
return null;
|
|
22783
23372
|
try {
|
|
22784
23373
|
const config = readConfig(configPath);
|
|
22785
|
-
if (!config)
|
|
23374
|
+
if (!config)
|
|
23375
|
+
return null;
|
|
22786
23376
|
const profile = resolveSurfaceProfile(config);
|
|
22787
|
-
if (!profile)
|
|
23377
|
+
if (!profile)
|
|
23378
|
+
return null;
|
|
22788
23379
|
return {
|
|
22789
23380
|
instanceId,
|
|
22790
23381
|
profile,
|
|
@@ -22820,7 +23411,7 @@ applyDataDirOverride(bootstrapOptions, {
|
|
|
22820
23411
|
loadPaperclipEnvFile(bootstrapOptions.config);
|
|
22821
23412
|
var bootstrapConfig = readConfig(resolveConfigPath(bootstrapOptions.config));
|
|
22822
23413
|
var surfaceRuntime = initializeSurfaceRuntimeContract(resolveSurfaceProfile(bootstrapConfig) ?? void 0);
|
|
22823
|
-
program.name("growthub").description("Growthub CLI \u2014 setup, configure, and run your local Growthub instance").version("0.3.
|
|
23414
|
+
program.name("growthub").description("Growthub CLI \u2014 setup, configure, and run your local Growthub instance").version("0.3.60").addHelpText("after", `
|
|
22824
23415
|
Worker Kits (agent execution environments):
|
|
22825
23416
|
|
|
22826
23417
|
Discovery:
|