@growthub/cli 0.9.18 → 0.10.1
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-custom-workspace-starter-v1/apps/workspace/app/api/workspace/reference-options/route.js +62 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/refresh-sources/route.js +13 -2
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/resolver-templates/route.js +23 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/sandbox-run/route.js +35 -5
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/test-source/route.js +15 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/DataModelShell.jsx +2277 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/DataTable.jsx +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/FieldEditor.jsx +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/FieldManager.jsx +9 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/ObjectSidebar.jsx +41 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/RecordDrawer.jsx +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/ReferencePicker.jsx +244 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/SandboxRunPanel.jsx +21 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/SourceTestPanel.jsx +15 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/StatusPill.jsx +13 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/ToggleField.jsx +41 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/dm-shared.jsx +99 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/page.jsx +2 -1528
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/globals.css +99 -6
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/docs/connector-template-authoring.md +8 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/docs/data-model-reference-fields.md +15 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/docs/mcp-chrome-tool-connectors.md +12 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/docs/resolver-template-library.md +17 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/source-resolver-registry.js +13 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/README.md +12 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/chrome-bridge.js +22 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/custom-http.js +23 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/generic-commerce.js +22 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/generic-crm.js +23 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/generic-project-management.js +22 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/generic-spreadsheet.js +22 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/mcp-tool.js +22 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/template-registry.js +50 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/webhook.js +22 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/references/collect-reference-options.js +133 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/references/reference-resolver-registry.js +17 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/references/resolver-loader.js +6 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/references/resolvers/README.md +8 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/references/resolvers/local-data-model.js +11 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/references/resolvers/source-records.js +34 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/adapters/README.md +5 -3
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/default-local-intelligence.js +203 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/sandboxes/index.js +1 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/data-model/field-contracts.js +81 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/data-model/reference-option-schema.js +59 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/data-model/reference-options.js +29 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-data-model.js +534 -23
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-schema.js +131 -1
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/helpers/export-training-traces.mjs +144 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/helpers/grade-raw-pairs.mjs +279 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/helpers/harvest-cursor-traces.mjs +288 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/helpers/upload-graded-traces.mjs +128 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/kit.json +10 -0
- package/assets/worker-kits/growthub-custom-workspace-starter-v1/templates/seeded-configs/alignment-loop.config.json +264 -0
- package/dist/index.js +486 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10255,6 +10255,7 @@ var init_growthub_bridge_client = __esm({
|
|
|
10255
10255
|
constructor(session = readActiveSession()) {
|
|
10256
10256
|
this.session = session;
|
|
10257
10257
|
}
|
|
10258
|
+
session;
|
|
10258
10259
|
async listAssets(query = {}) {
|
|
10259
10260
|
const url = bridgeUrl(this.session, "/api/cli/profile", {
|
|
10260
10261
|
view: "gallery-assets",
|
|
@@ -11249,6 +11250,65 @@ var init_scaffold_session_memory = __esm({
|
|
|
11249
11250
|
// src/starter/init.ts
|
|
11250
11251
|
import fs58 from "node:fs";
|
|
11251
11252
|
import path68 from "node:path";
|
|
11253
|
+
function readJsonFile2(filePath) {
|
|
11254
|
+
return JSON.parse(fs58.readFileSync(filePath, "utf8"));
|
|
11255
|
+
}
|
|
11256
|
+
function mergeDataModelObjects(baseObjects, seedObjects) {
|
|
11257
|
+
const readId = (value) => {
|
|
11258
|
+
const candidate = value.id;
|
|
11259
|
+
return typeof candidate === "string" ? candidate : "";
|
|
11260
|
+
};
|
|
11261
|
+
const merged = [...baseObjects];
|
|
11262
|
+
const indexById = /* @__PURE__ */ new Map();
|
|
11263
|
+
for (let i = 0; i < merged.length; i += 1) {
|
|
11264
|
+
const id = readId(merged[i]);
|
|
11265
|
+
if (id) indexById.set(id, i);
|
|
11266
|
+
}
|
|
11267
|
+
for (const seedObject of seedObjects) {
|
|
11268
|
+
const id = readId(seedObject);
|
|
11269
|
+
if (id && indexById.has(id)) {
|
|
11270
|
+
merged[indexById.get(id)] = {
|
|
11271
|
+
...merged[indexById.get(id)],
|
|
11272
|
+
...seedObject
|
|
11273
|
+
};
|
|
11274
|
+
continue;
|
|
11275
|
+
}
|
|
11276
|
+
merged.push(seedObject);
|
|
11277
|
+
if (id) indexById.set(id, merged.length - 1);
|
|
11278
|
+
}
|
|
11279
|
+
return merged;
|
|
11280
|
+
}
|
|
11281
|
+
function applySeededConfig(opts) {
|
|
11282
|
+
const seedSlug = opts.seedConfig.trim();
|
|
11283
|
+
if (!seedSlug) return;
|
|
11284
|
+
const seedPath = path68.join(opts.kitPath, "templates", "seeded-configs", `${seedSlug}.config.json`);
|
|
11285
|
+
if (!fs58.existsSync(seedPath)) {
|
|
11286
|
+
throw new Error(
|
|
11287
|
+
`Seeded config "${seedSlug}" was not found at ${seedPath}. Create templates/seeded-configs/<slug>.config.json in the starter kit first.`
|
|
11288
|
+
);
|
|
11289
|
+
}
|
|
11290
|
+
const outConfigPath = path68.join(opts.outPath, "apps", "workspace", "growthub.config.json");
|
|
11291
|
+
if (!fs58.existsSync(outConfigPath)) {
|
|
11292
|
+
throw new Error(`Expected workspace config at ${outConfigPath} while applying seeded config "${seedSlug}".`);
|
|
11293
|
+
}
|
|
11294
|
+
const baseConfig = readJsonFile2(outConfigPath);
|
|
11295
|
+
const seedConfig = readJsonFile2(seedPath);
|
|
11296
|
+
const mergedObjects = mergeDataModelObjects(
|
|
11297
|
+
Array.isArray(baseConfig.dataModel?.objects) ? baseConfig.dataModel.objects : [],
|
|
11298
|
+
Array.isArray(seedConfig.dataModel?.objects) ? seedConfig.dataModel.objects : []
|
|
11299
|
+
);
|
|
11300
|
+
const mergedConfig = {
|
|
11301
|
+
...baseConfig,
|
|
11302
|
+
...seedConfig,
|
|
11303
|
+
dataModel: {
|
|
11304
|
+
...baseConfig.dataModel || {},
|
|
11305
|
+
...seedConfig.dataModel || {},
|
|
11306
|
+
objects: mergedObjects
|
|
11307
|
+
}
|
|
11308
|
+
};
|
|
11309
|
+
fs58.writeFileSync(outConfigPath, `${JSON.stringify(mergedConfig, null, 2)}
|
|
11310
|
+
`, "utf8");
|
|
11311
|
+
}
|
|
11252
11312
|
async function initStarterWorkspace(opts) {
|
|
11253
11313
|
const kitId = opts.kitId ?? DEFAULT_STARTER_KIT_ID;
|
|
11254
11314
|
const absOut = path68.resolve(opts.out);
|
|
@@ -11257,6 +11317,13 @@ async function initStarterWorkspace(opts) {
|
|
|
11257
11317
|
}
|
|
11258
11318
|
const info = getBundledKitSourceInfo(kitId);
|
|
11259
11319
|
copyBundledKitSource(kitId, absOut);
|
|
11320
|
+
if (opts.seedConfig) {
|
|
11321
|
+
applySeededConfig({
|
|
11322
|
+
outPath: absOut,
|
|
11323
|
+
kitPath: info.assetRoot,
|
|
11324
|
+
seedConfig: opts.seedConfig
|
|
11325
|
+
});
|
|
11326
|
+
}
|
|
11260
11327
|
const reg = registerKitFork({
|
|
11261
11328
|
forkPath: absOut,
|
|
11262
11329
|
kitId: info.id,
|
|
@@ -29569,6 +29636,329 @@ function cleanMarkdownResponse(text70) {
|
|
|
29569
29636
|
return cleaned.trim();
|
|
29570
29637
|
}
|
|
29571
29638
|
|
|
29639
|
+
// src/runtime/native-intelligence/tool-intent-policy.ts
|
|
29640
|
+
function contractForSlug(slug, contracts) {
|
|
29641
|
+
return contracts.find((c) => c.slug === slug);
|
|
29642
|
+
}
|
|
29643
|
+
function validateIntentInputAgainstContract(intent, contract) {
|
|
29644
|
+
const warnings = [];
|
|
29645
|
+
const allowedKeys = new Set(contract.inputs.map((i) => i.key));
|
|
29646
|
+
for (const key of Object.keys(intent.input)) {
|
|
29647
|
+
if (!allowedKeys.has(key)) {
|
|
29648
|
+
warnings.push(`stripped unknown field "${key}" on tool "${intent.toolSlug}"`);
|
|
29649
|
+
}
|
|
29650
|
+
}
|
|
29651
|
+
for (const field of contract.inputs) {
|
|
29652
|
+
if (!field.required) continue;
|
|
29653
|
+
const v = intent.input[field.key];
|
|
29654
|
+
if (v === void 0 || v === null || v === "") {
|
|
29655
|
+
warnings.push(`missing required contract field "${field.key}" for tool "${intent.toolSlug}"`);
|
|
29656
|
+
}
|
|
29657
|
+
}
|
|
29658
|
+
return warnings;
|
|
29659
|
+
}
|
|
29660
|
+
function validateLocalModelToolIntents(intents, policy, availableContracts) {
|
|
29661
|
+
const validated = [];
|
|
29662
|
+
const rejected = [];
|
|
29663
|
+
const warnings = [];
|
|
29664
|
+
if (policy.mode === "disabled") {
|
|
29665
|
+
for (const intent of intents) {
|
|
29666
|
+
rejected.push({
|
|
29667
|
+
intent,
|
|
29668
|
+
reasons: ["tool policy mode is disabled"]
|
|
29669
|
+
});
|
|
29670
|
+
}
|
|
29671
|
+
return { validated, rejected, warnings };
|
|
29672
|
+
}
|
|
29673
|
+
const allowed = new Set(policy.allowedToolSlugs.map((s) => s.trim()).filter(Boolean));
|
|
29674
|
+
const minConfidence = typeof policy.minConfidence === "number" ? policy.minConfidence : void 0;
|
|
29675
|
+
for (const intent of intents) {
|
|
29676
|
+
const reasons = [];
|
|
29677
|
+
const slug = String(intent.toolSlug || "").trim();
|
|
29678
|
+
if (!slug) {
|
|
29679
|
+
reasons.push("missing toolSlug");
|
|
29680
|
+
rejected.push({ intent, reasons });
|
|
29681
|
+
continue;
|
|
29682
|
+
}
|
|
29683
|
+
if (!allowed.has(slug)) {
|
|
29684
|
+
reasons.push(`toolSlug "${slug}" is not in allowedToolSlugs`);
|
|
29685
|
+
}
|
|
29686
|
+
const contract = contractForSlug(slug, availableContracts);
|
|
29687
|
+
if (!contract) {
|
|
29688
|
+
reasons.push(`no contract summary for slug "${slug}"`);
|
|
29689
|
+
}
|
|
29690
|
+
if (minConfidence !== void 0 && !(typeof intent.confidence === "number" && intent.confidence >= minConfidence)) {
|
|
29691
|
+
reasons.push(`confidence ${intent.confidence} below minimum ${minConfidence}`);
|
|
29692
|
+
}
|
|
29693
|
+
if (reasons.length) {
|
|
29694
|
+
rejected.push({ intent: { ...intent, toolSlug: slug }, reasons });
|
|
29695
|
+
continue;
|
|
29696
|
+
}
|
|
29697
|
+
const contractNonNull = contract;
|
|
29698
|
+
const fieldWarnings = validateIntentInputAgainstContract({ ...intent, toolSlug: slug }, contractNonNull);
|
|
29699
|
+
warnings.push(...fieldWarnings);
|
|
29700
|
+
const strippedInput = {};
|
|
29701
|
+
const allowedKeys = new Set(contractNonNull.inputs.map((i) => i.key));
|
|
29702
|
+
for (const [k, v] of Object.entries(intent.input)) {
|
|
29703
|
+
if (allowedKeys.has(k)) strippedInput[k] = v;
|
|
29704
|
+
}
|
|
29705
|
+
validated.push({
|
|
29706
|
+
...intent,
|
|
29707
|
+
toolSlug: slug,
|
|
29708
|
+
input: strippedInput,
|
|
29709
|
+
warnings: fieldWarnings
|
|
29710
|
+
});
|
|
29711
|
+
}
|
|
29712
|
+
return { validated, rejected, warnings };
|
|
29713
|
+
}
|
|
29714
|
+
|
|
29715
|
+
// src/runtime/native-intelligence/sandbox-runner.ts
|
|
29716
|
+
var ENVELOPE_VERSION = "growthub-local-model-sandbox-v1";
|
|
29717
|
+
function traceLine(type, payload) {
|
|
29718
|
+
return JSON.stringify({ type, at: (/* @__PURE__ */ new Date()).toISOString(), ...payload });
|
|
29719
|
+
}
|
|
29720
|
+
function defaultToolPolicy(ctx) {
|
|
29721
|
+
return ctx.toolPolicy ?? {
|
|
29722
|
+
mode: "propose-only",
|
|
29723
|
+
allowedToolSlugs: ctx.allowedToolSlugs,
|
|
29724
|
+
requiresDeterministicValidation: true
|
|
29725
|
+
};
|
|
29726
|
+
}
|
|
29727
|
+
function buildSandboxSystemPrompt(input) {
|
|
29728
|
+
const ctx = input.context;
|
|
29729
|
+
const policy = defaultToolPolicy(ctx);
|
|
29730
|
+
const contractSummaries = ctx.availableContracts.map((c) => ({
|
|
29731
|
+
slug: c.slug,
|
|
29732
|
+
displayName: c.displayName,
|
|
29733
|
+
requiredBindings: c.requiredBindings,
|
|
29734
|
+
inputs: c.inputs.map((i) => ({ key: i.key, required: i.required, type: i.type }))
|
|
29735
|
+
}));
|
|
29736
|
+
const schemaHint = input.responseSchema ? `
|
|
29737
|
+
Optional response schema hint (follow when compatible):
|
|
29738
|
+
${JSON.stringify(input.responseSchema)}
|
|
29739
|
+
` : "";
|
|
29740
|
+
return [
|
|
29741
|
+
"You are Growthub Local Intelligence in a governed sandbox.",
|
|
29742
|
+
"Return a single JSON object only (no markdown fences).",
|
|
29743
|
+
"You must not claim to have executed tools or APIs.",
|
|
29744
|
+
"toolIntents are proposals only; include confidence between 0 and 1.",
|
|
29745
|
+
"",
|
|
29746
|
+
`taskId: ${ctx.taskId}`,
|
|
29747
|
+
`businessObjectType: ${input.businessObjectType}`,
|
|
29748
|
+
input.businessObjectId ? `businessObjectId: ${input.businessObjectId}` : "",
|
|
29749
|
+
`executionMode: ${ctx.executionMode}`,
|
|
29750
|
+
`toolPolicy.mode: ${policy.mode}`,
|
|
29751
|
+
`allowedToolSlugs: ${JSON.stringify(ctx.allowedToolSlugs)}`,
|
|
29752
|
+
"",
|
|
29753
|
+
"Available CMS / node contracts (summaries):",
|
|
29754
|
+
JSON.stringify(contractSummaries, null, 2),
|
|
29755
|
+
"",
|
|
29756
|
+
ctx.bindings ? `Current bindings:
|
|
29757
|
+
${JSON.stringify(ctx.bindings)}
|
|
29758
|
+
` : "",
|
|
29759
|
+
ctx.sourceRecordRefs?.length ? `sourceRecordRefs: ${JSON.stringify(ctx.sourceRecordRefs)}
|
|
29760
|
+
` : "",
|
|
29761
|
+
schemaHint,
|
|
29762
|
+
"JSON shape:",
|
|
29763
|
+
"{",
|
|
29764
|
+
' "text": string (optional concise narrative),',
|
|
29765
|
+
' "json": object (optional structured payload),',
|
|
29766
|
+
' "toolIntents": [{ "toolSlug", "reason", "input", "confidence" }],',
|
|
29767
|
+
' "warnings": string[],',
|
|
29768
|
+
' "confidence": number',
|
|
29769
|
+
"}"
|
|
29770
|
+
].filter(Boolean).join("\n");
|
|
29771
|
+
}
|
|
29772
|
+
function buildSandboxUserPrompt(input) {
|
|
29773
|
+
return [`User intent:
|
|
29774
|
+
${input.userIntent.trim()}`].join("\n\n");
|
|
29775
|
+
}
|
|
29776
|
+
function buildLocalIntelligenceSandboxPrompts(input) {
|
|
29777
|
+
return {
|
|
29778
|
+
systemPrompt: buildSandboxSystemPrompt(input),
|
|
29779
|
+
userPrompt: buildSandboxUserPrompt(input)
|
|
29780
|
+
};
|
|
29781
|
+
}
|
|
29782
|
+
function coerceToolIntents(raw) {
|
|
29783
|
+
if (!Array.isArray(raw)) return [];
|
|
29784
|
+
const out = [];
|
|
29785
|
+
for (const item of raw) {
|
|
29786
|
+
if (!item || typeof item !== "object") continue;
|
|
29787
|
+
const rec = item;
|
|
29788
|
+
const toolSlug = typeof rec.toolSlug === "string" ? rec.toolSlug.trim() : "";
|
|
29789
|
+
if (!toolSlug) continue;
|
|
29790
|
+
const reason = typeof rec.reason === "string" ? rec.reason : "";
|
|
29791
|
+
const inputObj = rec.input && typeof rec.input === "object" && !Array.isArray(rec.input) ? rec.input : {};
|
|
29792
|
+
const confidence = typeof rec.confidence === "number" && Number.isFinite(rec.confidence) ? rec.confidence : 0;
|
|
29793
|
+
out.push({ toolSlug, reason, input: inputObj, confidence });
|
|
29794
|
+
}
|
|
29795
|
+
return out;
|
|
29796
|
+
}
|
|
29797
|
+
function parseLocalModelSandboxResult(rawText) {
|
|
29798
|
+
const warnings = [];
|
|
29799
|
+
const trimmed = rawText.trim();
|
|
29800
|
+
if (!trimmed) {
|
|
29801
|
+
return { toolIntents: [], warnings: ["empty model response"], confidence: 0 };
|
|
29802
|
+
}
|
|
29803
|
+
let parsed;
|
|
29804
|
+
try {
|
|
29805
|
+
parsed = JSON.parse(trimmed);
|
|
29806
|
+
} catch {
|
|
29807
|
+
return {
|
|
29808
|
+
text: trimmed,
|
|
29809
|
+
toolIntents: [],
|
|
29810
|
+
warnings: ["model output was not valid JSON"],
|
|
29811
|
+
confidence: 0
|
|
29812
|
+
};
|
|
29813
|
+
}
|
|
29814
|
+
if (!parsed || typeof parsed !== "object") {
|
|
29815
|
+
return { toolIntents: [], warnings: ["parsed JSON was not an object"], confidence: 0 };
|
|
29816
|
+
}
|
|
29817
|
+
const obj = parsed;
|
|
29818
|
+
const text70 = typeof obj.text === "string" ? obj.text : void 0;
|
|
29819
|
+
const json = obj.json && typeof obj.json === "object" && !Array.isArray(obj.json) ? obj.json : void 0;
|
|
29820
|
+
const toolIntents = coerceToolIntents(obj.toolIntents);
|
|
29821
|
+
const w = Array.isArray(obj.warnings) ? obj.warnings.filter((w2) => typeof w2 === "string") : [];
|
|
29822
|
+
warnings.push(...w);
|
|
29823
|
+
const confidence = typeof obj.confidence === "number" && Number.isFinite(obj.confidence) ? obj.confidence : 0;
|
|
29824
|
+
return { text: text70, json, toolIntents, warnings, confidence };
|
|
29825
|
+
}
|
|
29826
|
+
function emptyEnvelope(input, config, adapterMode, message, fallback) {
|
|
29827
|
+
const result = {
|
|
29828
|
+
toolIntents: [],
|
|
29829
|
+
warnings: [message],
|
|
29830
|
+
confidence: 0
|
|
29831
|
+
};
|
|
29832
|
+
return {
|
|
29833
|
+
version: ENVELOPE_VERSION,
|
|
29834
|
+
taskId: input.taskId,
|
|
29835
|
+
businessObjectType: input.businessObjectType,
|
|
29836
|
+
businessObjectId: input.businessObjectId,
|
|
29837
|
+
adapter: {
|
|
29838
|
+
kind: "local-intelligence",
|
|
29839
|
+
mode: adapterMode,
|
|
29840
|
+
modelId: config.localModel ?? config.modelId,
|
|
29841
|
+
endpoint: config.endpoint
|
|
29842
|
+
},
|
|
29843
|
+
result,
|
|
29844
|
+
validatedToolIntents: [],
|
|
29845
|
+
rejectedToolIntents: [],
|
|
29846
|
+
rawText: "",
|
|
29847
|
+
latencyMs: 0,
|
|
29848
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29849
|
+
trace: [traceLine("local-model-sandbox-run-completed", { taskId: input.taskId, ok: false, fallback })],
|
|
29850
|
+
fallback
|
|
29851
|
+
};
|
|
29852
|
+
}
|
|
29853
|
+
async function runLocalIntelligenceSandboxTask(input, config, options) {
|
|
29854
|
+
const adapterMode = String(input.adapterMode ?? "ollama");
|
|
29855
|
+
const toolPolicy = defaultToolPolicy(input.context);
|
|
29856
|
+
const trace = [];
|
|
29857
|
+
trace.push(traceLine("local-intelligence-adapter-selected", { kind: "local-intelligence", mode: adapterMode }));
|
|
29858
|
+
trace.push(traceLine("local-model-sandbox-run-started", { taskId: input.taskId }));
|
|
29859
|
+
const systemPrompt = buildSandboxSystemPrompt(input);
|
|
29860
|
+
const userPrompt = buildSandboxUserPrompt(input);
|
|
29861
|
+
const backend = options?.backend ?? createNativeIntelligenceBackend(config);
|
|
29862
|
+
let rawText = "";
|
|
29863
|
+
let latencyMs = 0;
|
|
29864
|
+
let resolvedModelId = config.localModel ?? config.modelId;
|
|
29865
|
+
try {
|
|
29866
|
+
const completion = await backend.complete({
|
|
29867
|
+
systemPrompt,
|
|
29868
|
+
userPrompt,
|
|
29869
|
+
temperature: config.defaultTemperature,
|
|
29870
|
+
maxTokens: config.defaultMaxTokens,
|
|
29871
|
+
responseFormat: "json",
|
|
29872
|
+
sandboxContext: input.context,
|
|
29873
|
+
toolPolicy
|
|
29874
|
+
});
|
|
29875
|
+
rawText = completion.text;
|
|
29876
|
+
latencyMs = completion.latencyMs;
|
|
29877
|
+
resolvedModelId = completion.modelId || resolvedModelId;
|
|
29878
|
+
} catch (err) {
|
|
29879
|
+
const message = err instanceof Error ? err.message : "model backend error";
|
|
29880
|
+
trace.push(traceLine("local-model-sandbox-run-completed", { taskId: input.taskId, ok: false, error: message }));
|
|
29881
|
+
const env = emptyEnvelope(input, config, adapterMode, message, true);
|
|
29882
|
+
env.trace = [...trace, ...env.trace ?? []];
|
|
29883
|
+
return env;
|
|
29884
|
+
}
|
|
29885
|
+
const parsed = parseLocalModelSandboxResult(rawText);
|
|
29886
|
+
for (const intent of parsed.toolIntents) {
|
|
29887
|
+
trace.push(traceLine("local-model-tool-intent-proposed", { toolSlug: intent.toolSlug, confidence: intent.confidence }));
|
|
29888
|
+
}
|
|
29889
|
+
const validation = validateLocalModelToolIntents(parsed.toolIntents, toolPolicy, input.context.availableContracts);
|
|
29890
|
+
for (const r of validation.rejected) {
|
|
29891
|
+
trace.push(traceLine("local-model-tool-intent-rejected", { toolSlug: r.intent.toolSlug, reasons: r.reasons }));
|
|
29892
|
+
}
|
|
29893
|
+
const mergedWarnings = [...parsed.warnings, ...validation.warnings];
|
|
29894
|
+
const result = {
|
|
29895
|
+
text: parsed.text,
|
|
29896
|
+
json: parsed.json,
|
|
29897
|
+
toolIntents: parsed.toolIntents,
|
|
29898
|
+
warnings: mergedWarnings,
|
|
29899
|
+
confidence: parsed.confidence
|
|
29900
|
+
};
|
|
29901
|
+
trace.push(traceLine("local-model-sandbox-run-completed", { taskId: input.taskId, ok: true }));
|
|
29902
|
+
return {
|
|
29903
|
+
version: ENVELOPE_VERSION,
|
|
29904
|
+
taskId: input.taskId,
|
|
29905
|
+
businessObjectType: input.businessObjectType,
|
|
29906
|
+
businessObjectId: input.businessObjectId,
|
|
29907
|
+
adapter: {
|
|
29908
|
+
kind: "local-intelligence",
|
|
29909
|
+
mode: adapterMode,
|
|
29910
|
+
modelId: resolvedModelId,
|
|
29911
|
+
endpoint: config.endpoint
|
|
29912
|
+
},
|
|
29913
|
+
result,
|
|
29914
|
+
validatedToolIntents: validation.validated,
|
|
29915
|
+
rejectedToolIntents: validation.rejected,
|
|
29916
|
+
rawText,
|
|
29917
|
+
latencyMs,
|
|
29918
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29919
|
+
trace,
|
|
29920
|
+
fallback: false
|
|
29921
|
+
};
|
|
29922
|
+
}
|
|
29923
|
+
|
|
29924
|
+
// src/runtime/native-intelligence/source-record-export.ts
|
|
29925
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
29926
|
+
function hashSystemPrompt(systemPrompt) {
|
|
29927
|
+
return createHash3("sha256").update(systemPrompt, "utf8").digest("hex");
|
|
29928
|
+
}
|
|
29929
|
+
function sandboxEnvelopeToTraceRecord(envelope, options) {
|
|
29930
|
+
return {
|
|
29931
|
+
version: "growthub-local-intelligence-trace-v1",
|
|
29932
|
+
taskId: envelope.taskId,
|
|
29933
|
+
businessObjectType: envelope.businessObjectType,
|
|
29934
|
+
businessObjectId: envelope.businessObjectId,
|
|
29935
|
+
modelId: envelope.adapter.modelId,
|
|
29936
|
+
systemPromptHash: hashSystemPrompt(options.systemPrompt),
|
|
29937
|
+
input: {
|
|
29938
|
+
userIntent: options.userIntent,
|
|
29939
|
+
availableContracts: options.availableContracts ?? [],
|
|
29940
|
+
bindings: envelope.result.json && typeof envelope.result.json === "object" && envelope.result.json !== null && "bindings" in envelope.result.json && typeof envelope.result.json.bindings === "object" ? envelope.result.json.bindings : void 0
|
|
29941
|
+
},
|
|
29942
|
+
output: {
|
|
29943
|
+
json: envelope.result.json,
|
|
29944
|
+
toolIntents: envelope.result.toolIntents,
|
|
29945
|
+
warnings: [
|
|
29946
|
+
...envelope.result.warnings,
|
|
29947
|
+
...envelope.validatedToolIntents?.flatMap((v) => v.warnings) ?? []
|
|
29948
|
+
]
|
|
29949
|
+
},
|
|
29950
|
+
validation: {
|
|
29951
|
+
acceptedToolIntents: envelope.validatedToolIntents ?? [],
|
|
29952
|
+
rejectedToolIntents: envelope.rejectedToolIntents ?? []
|
|
29953
|
+
},
|
|
29954
|
+
createdAt: envelope.createdAt
|
|
29955
|
+
};
|
|
29956
|
+
}
|
|
29957
|
+
function formatTraceRecordLine(record) {
|
|
29958
|
+
return `${JSON.stringify(record)}
|
|
29959
|
+
`;
|
|
29960
|
+
}
|
|
29961
|
+
|
|
29572
29962
|
// src/runtime/native-intelligence/index.ts
|
|
29573
29963
|
function resolveConfigPath2() {
|
|
29574
29964
|
return path50.resolve(resolvePaperclipHomeDir(), "native-intelligence", "config.json");
|
|
@@ -35599,10 +35989,11 @@ async function runBrowseSkills(opts) {
|
|
|
35599
35989
|
}
|
|
35600
35990
|
function registerStarterCommands(program2) {
|
|
35601
35991
|
const starter = program2.command("starter").description("Custom Workspace Starter Kit \u2014 scaffold or import a fork with full v1 Self-Healing Fork Sync wiring.");
|
|
35602
|
-
starter.command("init").description("Scaffold a new custom workspace from the starter kit and auto-register it as a fork.").requiredOption("--out <path>", "Destination directory for the new workspace").option("--kit <kit-id>", `Source kit id (default: ${DEFAULT_STARTER_KIT_ID})`).option("--name <label>", "Human label for the fork").option("--upstream <owner/repo>", "Upstream GitHub repo \u2014 when set, also creates a remote fork").option("--destination-org <org>", "Create the GitHub fork under an org").option("--fork-name <name>", "Override the GitHub fork name").option("--remote-sync-mode <mode>", "Initial policy.remoteSyncMode \u2014 off|branch|pr (default: off)").option("--json", "Emit machine-readable output").action(async (opts) => {
|
|
35992
|
+
starter.command("init").description("Scaffold a new custom workspace from the starter kit and auto-register it as a fork.").requiredOption("--out <path>", "Destination directory for the new workspace").option("--kit <kit-id>", `Source kit id (default: ${DEFAULT_STARTER_KIT_ID})`).option("--seed-config <slug>", "Named seeded config from templates/seeded-configs/<slug>.config.json").option("--name <label>", "Human label for the fork").option("--upstream <owner/repo>", "Upstream GitHub repo \u2014 when set, also creates a remote fork").option("--destination-org <org>", "Create the GitHub fork under an org").option("--fork-name <name>", "Override the GitHub fork name").option("--remote-sync-mode <mode>", "Initial policy.remoteSyncMode \u2014 off|branch|pr (default: off)").option("--json", "Emit machine-readable output").action(async (opts) => {
|
|
35603
35993
|
await runStarterInit({
|
|
35604
35994
|
out: opts.out,
|
|
35605
35995
|
kitId: opts.kit ?? DEFAULT_STARTER_KIT_ID,
|
|
35996
|
+
seedConfig: opts.seedConfig,
|
|
35606
35997
|
name: opts.name,
|
|
35607
35998
|
upstream: opts.upstream,
|
|
35608
35999
|
destinationOrg: opts.destinationOrg,
|
|
@@ -39681,6 +40072,7 @@ async function runNativeIntelligenceHub() {
|
|
|
39681
40072
|
{ value: "models", label: "Manage local custom models", hint: "select active favorite/default model" },
|
|
39682
40073
|
{ value: "prompt", label: "Prompt local model (chat flow)", hint: "human first local prompt submissions" },
|
|
39683
40074
|
{ value: "flows", label: "Run native-intelligence with your prompt", hint: "planner/normalizer/recommender/summarizer" },
|
|
40075
|
+
{ value: "sandbox", label: "Run sandboxed local model task", hint: "governed JSON + validated tool intents (no execution)" },
|
|
39684
40076
|
{ value: "marketing-context", label: "Marketing Context Builder", hint: "auto-draft product-marketing-context from project artifacts" },
|
|
39685
40077
|
{ value: "provider-config", label: "Configure API provider", hint: "Claude, OpenAI, Gemini, OpenRouter, or local" },
|
|
39686
40078
|
{ value: "__back_to_hub", label: "\u2190 Back to main menu" }
|
|
@@ -39794,6 +40186,10 @@ API key: ${result.apiKey ? "configured" : "not needed"}`,
|
|
|
39794
40186
|
await runMarketingContextBuilder(baseUrl, defaultModel);
|
|
39795
40187
|
continue;
|
|
39796
40188
|
}
|
|
40189
|
+
if (action === "sandbox") {
|
|
40190
|
+
await runLocalIntelligenceSandboxDiscovery(baseUrl, defaultModel);
|
|
40191
|
+
continue;
|
|
40192
|
+
}
|
|
39797
40193
|
const customPrompt = await p42.text({
|
|
39798
40194
|
message: "Enter your local intelligence prompt",
|
|
39799
40195
|
placeholder: "Describe what you want to create/analyze"
|
|
@@ -39807,6 +40203,95 @@ API key: ${result.apiKey ? "configured" : "not needed"}`,
|
|
|
39807
40203
|
await runNativeIntelligenceFlowSuite(baseUrl, defaultModel, prompt);
|
|
39808
40204
|
}
|
|
39809
40205
|
}
|
|
40206
|
+
async function runLocalIntelligenceSandboxDiscovery(baseUrl, defaultModel) {
|
|
40207
|
+
const userIntent = await p42.text({
|
|
40208
|
+
message: "Describe the governed sandbox task",
|
|
40209
|
+
placeholder: "e.g. Inspect bindings and propose safe next steps"
|
|
40210
|
+
});
|
|
40211
|
+
if (p42.isCancel(userIntent)) return;
|
|
40212
|
+
const intent = String(userIntent).trim();
|
|
40213
|
+
if (!intent) {
|
|
40214
|
+
p42.note("Intent was empty.", "Sandboxed local model");
|
|
40215
|
+
return;
|
|
40216
|
+
}
|
|
40217
|
+
const boRaw = await p42.text({
|
|
40218
|
+
message: "Business object type (metadata label)",
|
|
40219
|
+
placeholder: "sandbox-environment",
|
|
40220
|
+
defaultValue: "sandbox-environment"
|
|
40221
|
+
});
|
|
40222
|
+
if (p42.isCancel(boRaw)) return;
|
|
40223
|
+
const businessObjectType = String(boRaw || "sandbox-environment").trim() || "sandbox-environment";
|
|
40224
|
+
const spinner15 = p42.spinner();
|
|
40225
|
+
spinner15.start("Loading contracts and running governed local model sandbox\u2026");
|
|
40226
|
+
try {
|
|
40227
|
+
const contracts = await loadRuntimeContracts();
|
|
40228
|
+
const allowed = contracts.map((c) => c.slug);
|
|
40229
|
+
const config = {
|
|
40230
|
+
...readIntelligenceConfig(),
|
|
40231
|
+
backendType: "local",
|
|
40232
|
+
endpoint: `${baseUrl.replace(/\/$/, "")}/chat/completions`,
|
|
40233
|
+
localModel: defaultModel
|
|
40234
|
+
};
|
|
40235
|
+
const health = await checkBackendHealth(config);
|
|
40236
|
+
const taskId = `task_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
40237
|
+
const taskInput = {
|
|
40238
|
+
taskId,
|
|
40239
|
+
businessObjectType,
|
|
40240
|
+
userIntent: intent,
|
|
40241
|
+
context: {
|
|
40242
|
+
taskId,
|
|
40243
|
+
businessObjectType,
|
|
40244
|
+
executionMode: "local",
|
|
40245
|
+
allowedToolSlugs: allowed,
|
|
40246
|
+
availableContracts: contracts,
|
|
40247
|
+
toolPolicy: {
|
|
40248
|
+
mode: "propose-only",
|
|
40249
|
+
allowedToolSlugs: allowed,
|
|
40250
|
+
requiresDeterministicValidation: true,
|
|
40251
|
+
minConfidence: 0.15
|
|
40252
|
+
}
|
|
40253
|
+
},
|
|
40254
|
+
adapterMode: "ollama"
|
|
40255
|
+
};
|
|
40256
|
+
const envelope = await runLocalIntelligenceSandboxTask(taskInput, config);
|
|
40257
|
+
spinner15.stop(health.available ? "Sandbox run finished." : "Sandbox run finished (check backend health).");
|
|
40258
|
+
const tracePreview = (envelope.trace ?? []).slice(-8).join("\n");
|
|
40259
|
+
p42.note(
|
|
40260
|
+
[
|
|
40261
|
+
`adapter: ${envelope.adapter.mode} \xB7 model: ${envelope.adapter.modelId}`,
|
|
40262
|
+
`latencyMs: ${envelope.latencyMs}`,
|
|
40263
|
+
`confidence: ${envelope.result.confidence}`,
|
|
40264
|
+
`validated intents: ${envelope.validatedToolIntents?.length ?? 0} \xB7 rejected: ${envelope.rejectedToolIntents?.length ?? 0}`,
|
|
40265
|
+
envelope.fallback ? "Note: deterministic fallback envelope after backend error." : "",
|
|
40266
|
+
"",
|
|
40267
|
+
"Trace (recent):",
|
|
40268
|
+
tracePreview || "(none)",
|
|
40269
|
+
"",
|
|
40270
|
+
"Envelope JSON:",
|
|
40271
|
+
JSON.stringify(envelope, null, 2).slice(0, 12e3)
|
|
40272
|
+
].filter(Boolean).join("\n"),
|
|
40273
|
+
"Governed local model sandbox"
|
|
40274
|
+
);
|
|
40275
|
+
const exportChoice = await p42.confirm({
|
|
40276
|
+
message: "Print one JSONL distillation trace line to copy?",
|
|
40277
|
+
initialValue: false
|
|
40278
|
+
});
|
|
40279
|
+
if (!p42.isCancel(exportChoice) && exportChoice) {
|
|
40280
|
+
const prompts = buildLocalIntelligenceSandboxPrompts(taskInput);
|
|
40281
|
+
const line = formatTraceRecordLine(
|
|
40282
|
+
sandboxEnvelopeToTraceRecord(envelope, {
|
|
40283
|
+
systemPrompt: prompts.systemPrompt,
|
|
40284
|
+
userIntent: intent,
|
|
40285
|
+
availableContracts: contracts.map((c) => ({ slug: c.slug, displayName: c.displayName }))
|
|
40286
|
+
})
|
|
40287
|
+
);
|
|
40288
|
+
p42.note(line.trimEnd(), "JSONL trace record");
|
|
40289
|
+
}
|
|
40290
|
+
} catch (err) {
|
|
40291
|
+
spinner15.stop("Sandbox run failed.");
|
|
40292
|
+
p42.note(err instanceof Error ? err.message : String(err), "Governed local model sandbox");
|
|
40293
|
+
}
|
|
40294
|
+
}
|
|
39810
40295
|
async function runMarketingContextBuilder(baseUrl, model) {
|
|
39811
40296
|
const projectDir = await p42.text({
|
|
39812
40297
|
message: "Project directory to scan",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@growthub/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "CLI control plane for Growthub Local and Agent Workspace as Code: export, fork, inspect, operate, sync, and optionally activate governed AI workspaces.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|