callman-core 1.21.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/index.d.ts +13 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +19 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/outputSchemas.d.ts +43 -0
- package/dist/ai/outputSchemas.d.ts.map +1 -0
- package/dist/ai/outputSchemas.js +38 -0
- package/dist/ai/outputSchemas.js.map +1 -0
- package/dist/ai/parse/diagram.d.ts +3 -0
- package/dist/ai/parse/diagram.d.ts.map +1 -0
- package/dist/ai/parse/diagram.js +24 -0
- package/dist/ai/parse/diagram.js.map +1 -0
- package/dist/ai/parse/scenario.d.ts +3 -0
- package/dist/ai/parse/scenario.d.ts.map +1 -0
- package/dist/ai/parse/scenario.js +23 -0
- package/dist/ai/parse/scenario.js.map +1 -0
- package/dist/ai/parse/shared.d.ts +5 -0
- package/dist/ai/parse/shared.d.ts.map +1 -0
- package/dist/ai/parse/shared.js +49 -0
- package/dist/ai/parse/shared.js.map +1 -0
- package/dist/ai/parse/unified.d.ts +10 -0
- package/dist/ai/parse/unified.d.ts.map +1 -0
- package/dist/ai/parse/unified.js +105 -0
- package/dist/ai/parse/unified.js.map +1 -0
- package/dist/ai/prompts/diagram.d.ts +4 -0
- package/dist/ai/prompts/diagram.d.ts.map +1 -0
- package/dist/ai/prompts/diagram.js +132 -0
- package/dist/ai/prompts/diagram.js.map +1 -0
- package/dist/ai/prompts/fragments.d.ts +5 -0
- package/dist/ai/prompts/fragments.d.ts.map +1 -0
- package/dist/ai/prompts/fragments.js +27 -0
- package/dist/ai/prompts/fragments.js.map +1 -0
- package/dist/ai/prompts/scenario.d.ts +12 -0
- package/dist/ai/prompts/scenario.d.ts.map +1 -0
- package/dist/ai/prompts/scenario.js +204 -0
- package/dist/ai/prompts/scenario.js.map +1 -0
- package/dist/ai/prompts/scenarioNodeDefaults.d.ts +3 -0
- package/dist/ai/prompts/scenarioNodeDefaults.d.ts.map +1 -0
- package/dist/ai/prompts/scenarioNodeDefaults.js +166 -0
- package/dist/ai/prompts/scenarioNodeDefaults.js.map +1 -0
- package/dist/ai/prompts/unified.d.ts +13 -0
- package/dist/ai/prompts/unified.d.ts.map +1 -0
- package/dist/ai/prompts/unified.js +123 -0
- package/dist/ai/prompts/unified.js.map +1 -0
- package/dist/ai/types.d.ts +100 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +9 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/scenario-runner/adapters/ai-executor.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/ai-executor.js +7 -8
- package/dist/scenario-runner/adapters/ai-executor.js.map +1 -1
- package/dist/scenario-runner/adapters/helpers/aiExample.d.ts +1 -0
- package/dist/scenario-runner/adapters/helpers/aiExample.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/helpers/aiExample.js +64 -0
- package/dist/scenario-runner/adapters/helpers/aiExample.js.map +1 -1
- package/dist/scenario-runner/adapters/index.d.ts +1 -1
- package/dist/scenario-runner/adapters/index.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/index.js +1 -1
- package/dist/scenario-runner/adapters/index.js.map +1 -1
- package/dist-cjs/ai/index.js +58 -0
- package/dist-cjs/ai/index.js.map +1 -0
- package/dist-cjs/ai/outputSchemas.js +41 -0
- package/dist-cjs/ai/outputSchemas.js.map +1 -0
- package/dist-cjs/ai/parse/diagram.js +28 -0
- package/dist-cjs/ai/parse/diagram.js.map +1 -0
- package/dist-cjs/ai/parse/scenario.js +27 -0
- package/dist-cjs/ai/parse/scenario.js.map +1 -0
- package/dist-cjs/ai/parse/shared.js +56 -0
- package/dist-cjs/ai/parse/shared.js.map +1 -0
- package/dist-cjs/ai/parse/unified.js +109 -0
- package/dist-cjs/ai/parse/unified.js.map +1 -0
- package/dist-cjs/ai/prompts/diagram.js +137 -0
- package/dist-cjs/ai/prompts/diagram.js.map +1 -0
- package/dist-cjs/ai/prompts/fragments.js +31 -0
- package/dist-cjs/ai/prompts/fragments.js.map +1 -0
- package/dist-cjs/ai/prompts/scenario.js +209 -0
- package/dist-cjs/ai/prompts/scenario.js.map +1 -0
- package/dist-cjs/ai/prompts/scenarioNodeDefaults.js +170 -0
- package/dist-cjs/ai/prompts/scenarioNodeDefaults.js.map +1 -0
- package/dist-cjs/ai/prompts/unified.js +128 -0
- package/dist-cjs/ai/prompts/unified.js.map +1 -0
- package/dist-cjs/ai/types.js +12 -0
- package/dist-cjs/ai/types.js.map +1 -0
- package/dist-cjs/index.js +5 -5
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/scenario-runner/adapters/ai-executor.js +6 -7
- package/dist-cjs/scenario-runner/adapters/ai-executor.js.map +1 -1
- package/dist-cjs/scenario-runner/adapters/helpers/aiExample.js +66 -1
- package/dist-cjs/scenario-runner/adapters/helpers/aiExample.js.map +1 -1
- package/dist-cjs/scenario-runner/adapters/index.js +2 -1
- package/dist-cjs/scenario-runner/adapters/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export { extractJsonPayload } from "./jsonRepair.js";
|
|
3
|
+
export { DIAGRAM_OUTPUT_SCHEMA, SCENARIO_OUTPUT_SCHEMA, UNIFIED_OUTPUT_SCHEMA, } from "./outputSchemas.js";
|
|
4
|
+
export { CONTRACT_RULES_SPEC, STAGE_DESCRIPTIONS, truncateForPrompt, } from "./prompts/fragments.js";
|
|
5
|
+
export { buildUnifiedSystemPrompt, buildUnifiedUserPrompt } from "./prompts/unified.js";
|
|
6
|
+
export { buildDiagramSystemPrompt, buildDiagramUserPrompt } from "./prompts/diagram.js";
|
|
7
|
+
export { buildScenarioSystemPrompt, buildScenarioUserPrompt, SCENARIO_AI_REFERENCE_TYPES, type BuildScenarioSystemPromptOptions, } from "./prompts/scenario.js";
|
|
8
|
+
export { defaultScenarioNodeConfig, SCENARIO_NODE_DEFAULT_CONFIGS, } from "./prompts/scenarioNodeDefaults.js";
|
|
9
|
+
export { isRecord as isAiRecord, parseEnvelope, scriptHasSyntaxError } from "./parse/shared.js";
|
|
10
|
+
export { parseAiUnifiedOutput, type ParseAiUnifiedOptions } from "./parse/unified.js";
|
|
11
|
+
export { parseAiDiagramOutput } from "./parse/diagram.js";
|
|
12
|
+
export { parseAiScenarioOutput } from "./parse/scenario.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAOA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,2BAA2B,EAC3B,KAAK,gCAAgC,GACtC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/ai/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Central AI surface: every shared assistant prompt, parser, output schema and
|
|
2
|
+
// wire-level type lives here — one source consumed by the backend (hosted
|
|
3
|
+
// generation) and the desktop (local-CLI generation). CSP-safe throughout: no
|
|
4
|
+
// zod, no ajv, no unguarded `new Function` (this code runs in the Electron
|
|
5
|
+
// renderer). Prompts must stay self-contained prose that survives being
|
|
6
|
+
// PREPENDED to the user prompt (Codex/Cursor CLIs have no system flag).
|
|
7
|
+
export * from "./types.js";
|
|
8
|
+
export { extractJsonPayload } from "./jsonRepair.js";
|
|
9
|
+
export { DIAGRAM_OUTPUT_SCHEMA, SCENARIO_OUTPUT_SCHEMA, UNIFIED_OUTPUT_SCHEMA, } from "./outputSchemas.js";
|
|
10
|
+
export { CONTRACT_RULES_SPEC, STAGE_DESCRIPTIONS, truncateForPrompt, } from "./prompts/fragments.js";
|
|
11
|
+
export { buildUnifiedSystemPrompt, buildUnifiedUserPrompt } from "./prompts/unified.js";
|
|
12
|
+
export { buildDiagramSystemPrompt, buildDiagramUserPrompt } from "./prompts/diagram.js";
|
|
13
|
+
export { buildScenarioSystemPrompt, buildScenarioUserPrompt, SCENARIO_AI_REFERENCE_TYPES, } from "./prompts/scenario.js";
|
|
14
|
+
export { defaultScenarioNodeConfig, SCENARIO_NODE_DEFAULT_CONFIGS, } from "./prompts/scenarioNodeDefaults.js";
|
|
15
|
+
export { isRecord as isAiRecord, parseEnvelope, scriptHasSyntaxError } from "./parse/shared.js";
|
|
16
|
+
export { parseAiUnifiedOutput } from "./parse/unified.js";
|
|
17
|
+
export { parseAiDiagramOutput } from "./parse/diagram.js";
|
|
18
|
+
export { parseAiScenarioOutput } from "./parse/scenario.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,0EAA0E;AAC1E,8EAA8E;AAC9E,2EAA2E;AAC3E,wEAAwE;AACxE,wEAAwE;AAExE,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,2BAA2B,GAE5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAA8B,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const UNIFIED_OUTPUT_SCHEMA: {
|
|
2
|
+
readonly type: "object";
|
|
3
|
+
readonly properties: {
|
|
4
|
+
readonly reply: {
|
|
5
|
+
readonly type: "string";
|
|
6
|
+
};
|
|
7
|
+
readonly contract: {
|
|
8
|
+
readonly type: readonly ["object", "null"];
|
|
9
|
+
};
|
|
10
|
+
readonly scripts: {
|
|
11
|
+
readonly type: "array";
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
readonly required: readonly ["reply"];
|
|
15
|
+
readonly additionalProperties: true;
|
|
16
|
+
};
|
|
17
|
+
export declare const DIAGRAM_OUTPUT_SCHEMA: {
|
|
18
|
+
readonly type: "object";
|
|
19
|
+
readonly properties: {
|
|
20
|
+
readonly reply: {
|
|
21
|
+
readonly type: "string";
|
|
22
|
+
};
|
|
23
|
+
readonly diagram: {
|
|
24
|
+
readonly type: readonly ["object", "null"];
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
readonly required: readonly ["reply"];
|
|
28
|
+
readonly additionalProperties: true;
|
|
29
|
+
};
|
|
30
|
+
export declare const SCENARIO_OUTPUT_SCHEMA: {
|
|
31
|
+
readonly type: "object";
|
|
32
|
+
readonly properties: {
|
|
33
|
+
readonly reply: {
|
|
34
|
+
readonly type: "string";
|
|
35
|
+
};
|
|
36
|
+
readonly scenario: {
|
|
37
|
+
readonly type: readonly ["object", "null"];
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
readonly required: readonly ["reply"];
|
|
41
|
+
readonly additionalProperties: true;
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=outputSchemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outputSchemas.d.ts","sourceRoot":"","sources":["../../src/ai/outputSchemas.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;CASxB,CAAC;AAEX,eAAO,MAAM,qBAAqB;;;;;;;;;;;;CAQxB,CAAC;AAEX,eAAO,MAAM,sBAAsB;;;;;;;;;;;;CAQzB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// JSON Schemas describing each AI feature's expected output envelope. These are
|
|
2
|
+
// passed to runLocalAi/runLocalAiStream and used ONLY by providers whose spec
|
|
3
|
+
// supports structured output (currently Codex, via --output-schema) — other
|
|
4
|
+
// providers ignore them and rely on the prompt + the jsonRepair fallback.
|
|
5
|
+
//
|
|
6
|
+
// Deliberately PERMISSIVE: only the top-level envelope is pinned (so the model
|
|
7
|
+
// wraps its answer in { reply, <payload> }); the nested contract/diagram/scenario
|
|
8
|
+
// bodies stay open (additionalProperties) because they are validated downstream
|
|
9
|
+
// by the feature parsers, not here. Tighten later if a model needs more steering.
|
|
10
|
+
export const UNIFIED_OUTPUT_SCHEMA = {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
reply: { type: "string" },
|
|
14
|
+
contract: { type: ["object", "null"] },
|
|
15
|
+
scripts: { type: "array" },
|
|
16
|
+
},
|
|
17
|
+
required: ["reply"],
|
|
18
|
+
additionalProperties: true,
|
|
19
|
+
};
|
|
20
|
+
export const DIAGRAM_OUTPUT_SCHEMA = {
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
reply: { type: "string" },
|
|
24
|
+
diagram: { type: ["object", "null"] },
|
|
25
|
+
},
|
|
26
|
+
required: ["reply"],
|
|
27
|
+
additionalProperties: true,
|
|
28
|
+
};
|
|
29
|
+
export const SCENARIO_OUTPUT_SCHEMA = {
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: {
|
|
32
|
+
reply: { type: "string" },
|
|
33
|
+
scenario: { type: ["object", "null"] },
|
|
34
|
+
},
|
|
35
|
+
required: ["reply"],
|
|
36
|
+
additionalProperties: true,
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=outputSchemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outputSchemas.js","sourceRoot":"","sources":["../../src/ai/outputSchemas.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,8EAA8E;AAC9E,4EAA4E;AAC5E,0EAA0E;AAC1E,EAAE;AACF,+EAA+E;AAC/E,kFAAkF;AAClF,gFAAgF;AAChF,kFAAkF;AAElF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;QACtC,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;KAC3B;IACD,QAAQ,EAAE,CAAC,OAAO,CAAC;IACnB,oBAAoB,EAAE,IAAI;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;KACtC;IACD,QAAQ,EAAE,CAAC,OAAO,CAAC;IACnB,oBAAoB,EAAE,IAAI;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;KACvC;IACD,QAAQ,EAAE,CAAC,OAAO,CAAC;IACnB,oBAAoB,EAAE,IAAI;CAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagram.d.ts","sourceRoot":"","sources":["../../../src/ai/parse/diagram.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,eAAO,MAAM,oBAAoB,GAAI,KAAK,MAAM,KAAG,eAiBlD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Parser for the diagram assistant's envelope. Only a light structural gate
|
|
2
|
+
// here (a diagram must carry node + edge arrays); anything else degrades to
|
|
3
|
+
// reply-only so a chatty response never throws. The authoritative validation
|
|
4
|
+
// (types, edge terminals, component keys) runs in the desktop via
|
|
5
|
+
// safeParseDiagramDocument before anything touches the canvas.
|
|
6
|
+
import { envelopeReply, isRecord, parseEnvelope } from "./shared.js";
|
|
7
|
+
export const parseAiDiagramOutput = (raw) => {
|
|
8
|
+
const json = parseEnvelope(raw);
|
|
9
|
+
const reply = envelopeReply(json);
|
|
10
|
+
const diagram = json.diagram == null ? null : json.diagram;
|
|
11
|
+
if (isRecord(diagram)) {
|
|
12
|
+
const { nodes, edges } = diagram;
|
|
13
|
+
if (!Array.isArray(nodes) || !Array.isArray(edges)) {
|
|
14
|
+
// Not a usable diagram payload → treat as a plain reply.
|
|
15
|
+
return { reply, diagram: null };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else if (diagram !== null) {
|
|
19
|
+
// A non-object, non-null diagram value is not usable.
|
|
20
|
+
return { reply, diagram: null };
|
|
21
|
+
}
|
|
22
|
+
return { reply, diagram };
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=diagram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagram.js","sourceRoot":"","sources":["../../../src/ai/parse/diagram.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4EAA4E;AAC5E,6EAA6E;AAC7E,kEAAkE;AAClE,+DAA+D;AAG/D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAW,EAAmB,EAAE;IACnE,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IAE3D,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,yDAAyD;YACzD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC5B,sDAAsD;QACtD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../../../src/ai/parse/scenario.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,eAAO,MAAM,qBAAqB,GAAI,KAAK,MAAM,KAAG,gBAgBnD,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Parser for the scenario assistant's envelope. Only a light structural gate
|
|
2
|
+
// here (a scenario must carry node + edge arrays); anything else degrades to
|
|
3
|
+
// reply-only so a chatty response never throws. The authoritative validation
|
|
4
|
+
// (node configs, graph rules) runs downstream — desktop sanitizeScenario +
|
|
5
|
+
// buildScenarioValidationSnapshot; backend zod on save. Mirrors the diagram
|
|
6
|
+
// parser.
|
|
7
|
+
import { envelopeReply, isRecord, parseEnvelope } from "./shared.js";
|
|
8
|
+
export const parseAiScenarioOutput = (raw) => {
|
|
9
|
+
const json = parseEnvelope(raw);
|
|
10
|
+
const reply = envelopeReply(json);
|
|
11
|
+
const scenario = json.scenario == null ? null : json.scenario;
|
|
12
|
+
if (isRecord(scenario)) {
|
|
13
|
+
const { nodes, edges } = scenario;
|
|
14
|
+
if (!Array.isArray(nodes) || !Array.isArray(edges)) {
|
|
15
|
+
// Not a usable scenario payload → treat as a plain reply.
|
|
16
|
+
return { reply, scenario: null };
|
|
17
|
+
}
|
|
18
|
+
return { reply, scenario };
|
|
19
|
+
}
|
|
20
|
+
// A non-object, non-null scenario value is not usable.
|
|
21
|
+
return { reply, scenario: null };
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=scenario.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../../src/ai/parse/scenario.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,2EAA2E;AAC3E,4EAA4E;AAC5E,UAAU;AAGV,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAW,EAAoB,EAAE;IACrE,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;IAE9D,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,0DAA0D;YAC1D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACnC,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAED,uDAAuD;IACvD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACnC,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
|
|
2
|
+
export declare const parseEnvelope: (raw: string) => Record<string, unknown>;
|
|
3
|
+
export declare const envelopeReply: (envelope: Record<string, unknown>) => string;
|
|
4
|
+
export declare const scriptHasSyntaxError: (code: string) => boolean;
|
|
5
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/ai/parse/shared.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAC;AAKvE,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAWjE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MACD,CAAC;AAgBlE,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,OAQnD,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Shared parse helpers for the AI assistants' JSON envelopes. CSP-safe by
|
|
2
|
+
// design: no zod, no ajv, no unguarded `new Function` — these run in the
|
|
3
|
+
// Electron renderer (local-CLI generation) AND in the backend (hosted
|
|
4
|
+
// generation). Hosts add their own stricter gates at their own boundaries.
|
|
5
|
+
import { extractJsonPayload } from "../jsonRepair.js";
|
|
6
|
+
export const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
// Parse the raw model text into the { reply, ... } envelope record. Throws a
|
|
8
|
+
// plain Error (hosts map it: backend → AppError 502 AI_BAD_OUTPUT, desktop →
|
|
9
|
+
// toast) when the text is not JSON even after repair, or not an object.
|
|
10
|
+
export const parseEnvelope = (raw) => {
|
|
11
|
+
let json;
|
|
12
|
+
try {
|
|
13
|
+
json = JSON.parse(extractJsonPayload(raw));
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new Error("The AI model returned malformed JSON.");
|
|
17
|
+
}
|
|
18
|
+
if (!isRecord(json)) {
|
|
19
|
+
throw new Error("The AI model output did not match the expected shape.");
|
|
20
|
+
}
|
|
21
|
+
return json;
|
|
22
|
+
};
|
|
23
|
+
export const envelopeReply = (envelope) => typeof envelope.reply === "string" ? envelope.reply.trim() : "";
|
|
24
|
+
// Compile-only syntax check for generated scripts. `new Function` PARSES
|
|
25
|
+
// without EXECUTING, so a SyntaxError is thrown at construction for bad code.
|
|
26
|
+
// Some Electron renderers block `eval`/`new Function` via CSP — in that case
|
|
27
|
+
// the check is unavailable, so we skip it (never falsely drop a valid script).
|
|
28
|
+
// Detected once.
|
|
29
|
+
const syntaxCheckAvailable = (() => {
|
|
30
|
+
try {
|
|
31
|
+
new Function("return (async () => {});");
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
})();
|
|
38
|
+
export const scriptHasSyntaxError = (code) => {
|
|
39
|
+
if (!syntaxCheckAvailable)
|
|
40
|
+
return false;
|
|
41
|
+
try {
|
|
42
|
+
new Function(`return (async () => {\n${code}\n});`);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/ai/parse/shared.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,yEAAyE;AACzE,sEAAsE;AACtE,2EAA2E;AAE3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CAC3E,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEvE,6EAA6E;AAC7E,6EAA6E;AAC7E,wEAAwE;AACxE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAA2B,EAAE;IACpE,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAiC,EAAU,EAAE,CACzE,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAElE,yEAAyE;AACzE,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,iBAAiB;AACjB,MAAM,oBAAoB,GAAG,CAAC,GAAY,EAAE;IAC1C,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,0BAA0B,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC,EAAE,CAAC;AAEL,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAW,EAAE;IAC5D,IAAI,CAAC,oBAAoB;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,0BAA0B,IAAI,OAAO,CAAC,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AiScriptStage, AiUnifiedOutput } from "../types.js";
|
|
2
|
+
export interface ParseAiUnifiedOptions {
|
|
3
|
+
/** Host hook: reject a contract rule (e.g. backend's zod operator gate). */
|
|
4
|
+
validateRule?: (rule: {
|
|
5
|
+
path: string;
|
|
6
|
+
rules: Record<string, unknown>;
|
|
7
|
+
}) => boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const parseAiUnifiedOutput: (raw: string, allowedPaths: string[], existingPaths: string[], allowedStages: AiScriptStage[], options?: ParseAiUnifiedOptions) => AiUnifiedOutput;
|
|
10
|
+
//# sourceMappingURL=unified.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unified.d.ts","sourceRoot":"","sources":["../../../src/ai/parse/unified.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAwC,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA6FxG,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC;CACpF;AAED,eAAO,MAAM,oBAAoB,GAC/B,KAAK,MAAM,EACX,cAAc,MAAM,EAAE,EACtB,eAAe,MAAM,EAAE,EACvB,eAAe,aAAa,EAAE,EAC9B,UAAS,qBAA0B,KAClC,eAeF,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Parser for the unified request-chat envelope. Canonical implementation —
|
|
2
|
+
// merges the previously-duplicated backend (zod-gated) and desktop (CSP-safe)
|
|
3
|
+
// parsers: splits the single JSON envelope, restricts contract `add` paths to
|
|
4
|
+
// the discovered schema (index-tolerant), restricts `remove` to existing
|
|
5
|
+
// paths, filters scripts to the allowed stages, syntax-checks each script
|
|
6
|
+
// (where CSP allows), and de-duplicates — the guardrails that make the raw
|
|
7
|
+
// model JSON safe to apply.
|
|
8
|
+
//
|
|
9
|
+
// Operator-level rule validation is host-pluggable (`validateRule`): the
|
|
10
|
+
// backend passes its zod-backed check so hallucinated operators are still
|
|
11
|
+
// rejected server-side; the desktop passes nothing (its apply path guards).
|
|
12
|
+
import { envelopeReply, isRecord, parseEnvelope, scriptHasSyntaxError } from "./shared.js";
|
|
13
|
+
// Collapse concrete array indices to the wildcard form so `scores[2]` matches
|
|
14
|
+
// the `scores[]` the schema discovered.
|
|
15
|
+
const normalizeArrayIndices = (path) => path.replace(/\[\d+\]/g, "[]");
|
|
16
|
+
const parseScripts = (raw, allowedStages) => {
|
|
17
|
+
if (!Array.isArray(raw))
|
|
18
|
+
return { scripts: [], note: "" };
|
|
19
|
+
const allowed = new Set(allowedStages);
|
|
20
|
+
const byStage = new Map();
|
|
21
|
+
const dropped = [];
|
|
22
|
+
for (const entry of raw) {
|
|
23
|
+
if (!isRecord(entry) || typeof entry.stage !== "string" || typeof entry.code !== "string") {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const stage = entry.stage;
|
|
27
|
+
if (!allowed.has(stage)) {
|
|
28
|
+
dropped.push(`${entry.stage} (not a targeted stage)`);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (scriptHasSyntaxError(entry.code)) {
|
|
32
|
+
dropped.push(`${stage} (syntax error)`);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Last write wins per stage.
|
|
36
|
+
byStage.set(stage, entry.code);
|
|
37
|
+
}
|
|
38
|
+
// Preserve the order the stages were targeted in.
|
|
39
|
+
const scripts = allowedStages
|
|
40
|
+
.filter((stage) => byStage.has(stage))
|
|
41
|
+
.map((stage) => ({ stage, code: byStage.get(stage) }));
|
|
42
|
+
const note = dropped.length ? `Skipped: ${dropped.join(", ")}.` : "";
|
|
43
|
+
return { scripts, note };
|
|
44
|
+
};
|
|
45
|
+
const parseContract = (raw, allowedPaths, existingPaths, validateRule) => {
|
|
46
|
+
if (!isRecord(raw))
|
|
47
|
+
return null;
|
|
48
|
+
const addRaw = Array.isArray(raw.add) ? raw.add : [];
|
|
49
|
+
// Tolerate the model using the legacy `rules` key alongside `add`.
|
|
50
|
+
const rulesRaw = Array.isArray(raw.rules) ? raw.rules : [];
|
|
51
|
+
const removeRaw = Array.isArray(raw.remove) ? raw.remove : [];
|
|
52
|
+
const allowedNormalized = new Set(allowedPaths.map(normalizeArrayIndices));
|
|
53
|
+
const seenAdd = new Set();
|
|
54
|
+
const add = [];
|
|
55
|
+
for (const candidate of [...addRaw, ...rulesRaw]) {
|
|
56
|
+
if (!isRecord(candidate))
|
|
57
|
+
continue;
|
|
58
|
+
const { path, rules } = candidate;
|
|
59
|
+
if (typeof path !== "string" || path.trim().length === 0)
|
|
60
|
+
continue;
|
|
61
|
+
if (!isRecord(rules))
|
|
62
|
+
continue;
|
|
63
|
+
// Restrict to discovered schema paths (index-tolerant) when a schema was
|
|
64
|
+
// provided, so fully hallucinated paths are dropped.
|
|
65
|
+
if (allowedNormalized.size > 0 && !allowedNormalized.has(normalizeArrayIndices(path))) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (validateRule && !validateRule({ path, rules }))
|
|
69
|
+
continue;
|
|
70
|
+
if (seenAdd.has(path))
|
|
71
|
+
continue;
|
|
72
|
+
seenAdd.add(path);
|
|
73
|
+
add.push({ path, rules });
|
|
74
|
+
}
|
|
75
|
+
// Removals must reference a rule that actually exists for this request.
|
|
76
|
+
const existing = new Set(existingPaths);
|
|
77
|
+
const seenRemove = new Set();
|
|
78
|
+
const remove = [];
|
|
79
|
+
for (const path of removeRaw) {
|
|
80
|
+
if (typeof path !== "string")
|
|
81
|
+
continue;
|
|
82
|
+
if (existing.size > 0 && !existing.has(path))
|
|
83
|
+
continue;
|
|
84
|
+
if (seenRemove.has(path))
|
|
85
|
+
continue;
|
|
86
|
+
seenRemove.add(path);
|
|
87
|
+
remove.push(path);
|
|
88
|
+
}
|
|
89
|
+
if (add.length === 0 && remove.length === 0)
|
|
90
|
+
return null;
|
|
91
|
+
return { add, remove };
|
|
92
|
+
};
|
|
93
|
+
export const parseAiUnifiedOutput = (raw, allowedPaths, existingPaths, allowedStages, options = {}) => {
|
|
94
|
+
const json = parseEnvelope(raw);
|
|
95
|
+
let reply = envelopeReply(json);
|
|
96
|
+
const contract = json.contract == null
|
|
97
|
+
? null
|
|
98
|
+
: parseContract(json.contract, allowedPaths, existingPaths, options.validateRule);
|
|
99
|
+
const { scripts, note } = parseScripts(json.scripts, allowedStages);
|
|
100
|
+
if (note) {
|
|
101
|
+
reply = reply ? `${reply}\n\n${note}` : note;
|
|
102
|
+
}
|
|
103
|
+
return { reply, contract, scripts };
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=unified.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unified.js","sourceRoot":"","sources":["../../../src/ai/parse/unified.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DiagramPromptInput } from "../types.js";
|
|
2
|
+
export declare const buildDiagramSystemPrompt: () => string;
|
|
3
|
+
export declare const buildDiagramUserPrompt: ({ instruction, mode, document, components, selection, canvas, }: DiagramPromptInput) => string;
|
|
4
|
+
//# sourceMappingURL=diagram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagram.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/diagram.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,eAAO,MAAM,wBAAwB,QAAO,MAkG9B,CAAC;AAEf,eAAO,MAAM,sBAAsB,GAAI,iEAOpC,kBAAkB,KAAG,MA6BvB,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Prompt builders for the diagram-studio assistant. Mirrors the unified prompt
|
|
2
|
+
// pattern (system = rules + output shape, user = context + instruction) but the
|
|
3
|
+
// model produces a whole DiagramDocument instead of contract/script changes.
|
|
4
|
+
//
|
|
5
|
+
// The DiagramDocument schema itself lives in the desktop app
|
|
6
|
+
// (features/diagram-studio/model/schema.ts) — it is described here in prose so
|
|
7
|
+
// the model emits the right shape; the client runs the authoritative validator
|
|
8
|
+
// (safeParseDiagramDocument) before applying anything to the canvas.
|
|
9
|
+
export const buildDiagramSystemPrompt = () => [
|
|
10
|
+
"You are a STAFF-level software/systems architect and domain expert embedded in a visual",
|
|
11
|
+
"diagram studio. You have deep, practical knowledge of real production systems across",
|
|
12
|
+
"domains (fintech/investing, e-commerce, payments, streaming, IoT, ML, SaaS, etc.). From",
|
|
13
|
+
"the user's instruction plus the CONTEXT below, YOU produce a diagram. Respond with ONE",
|
|
14
|
+
"JSON object ONLY (no markdown, no prose outside JSON), shaped:",
|
|
15
|
+
"",
|
|
16
|
+
'{"reply": string, "diagram": <DiagramDocument> | null}',
|
|
17
|
+
"",
|
|
18
|
+
"DiagramDocument shape:",
|
|
19
|
+
"{",
|
|
20
|
+
' "schemaVersion": 1,',
|
|
21
|
+
' "id": string, // keep the existing id on edits; a short id when creating',
|
|
22
|
+
' "meta": {"title": string}, // a concise diagram title',
|
|
23
|
+
' "nodes": [{',
|
|
24
|
+
' "id": string, // stable + unique; REUSE existing ids on edits',
|
|
25
|
+
' "type": string, // MUST be one of AVAILABLE COMPONENT TYPES below',
|
|
26
|
+
' "position": {"x": number, "y": number},',
|
|
27
|
+
' "size": {"width": number, "height": number},',
|
|
28
|
+
' "label": string, // short, clear',
|
|
29
|
+
' "rotation": number, // optional; degrees clockwise 0-359 (omit or 0 = upright)',
|
|
30
|
+
' "style": { // ALL fields optional',
|
|
31
|
+
' "fill": {"raw":"#RRGGBB"}, "stroke": {"raw":"#RRGGBB"}, "textColor": {"raw":"#RRGGBB"},',
|
|
32
|
+
' "strokeWidth": number, "radius": number, "dashed": boolean, "opacity": number, // opacity 0-100',
|
|
33
|
+
' "fontSize": number, "fontFamily": string, "fontStyle": number, // fontStyle BITMASK: bold=1|italic=2|underline=4',
|
|
34
|
+
' "align": "left"|"center"|"right", "verticalAlign": "top"|"middle"|"bottom", "shadow": boolean',
|
|
35
|
+
" },",
|
|
36
|
+
' "parentId": string // optional: id of a container/group/pool node',
|
|
37
|
+
" }],",
|
|
38
|
+
' "edges": [{',
|
|
39
|
+
' "id": string,',
|
|
40
|
+
' "source": string, // an existing node id',
|
|
41
|
+
' "target": string, // an existing node id',
|
|
42
|
+
' "label": string, // optional edge label',
|
|
43
|
+
' "routing": "orthogonal"|"straight"|"curved", // optional (default orthogonal)',
|
|
44
|
+
' "markerEnd": "classicThin"|"classic"|"none" // optional arrowhead',
|
|
45
|
+
" }]",
|
|
46
|
+
"}",
|
|
47
|
+
"",
|
|
48
|
+
"RULES:",
|
|
49
|
+
"- Use ONLY `type` values from AVAILABLE COMPONENT TYPES. When unsure, fall back to a",
|
|
50
|
+
" generic shape: `rect`, `flow.process`, `flow.decision`, `flow.terminator`, `cylinder`.",
|
|
51
|
+
"- Every node needs a short, meaningful `label` and a sensible `size` (e.g. 140x64).",
|
|
52
|
+
'- COLORS in `style` MUST be objects: `{"raw": "#ff0000"}` (a hex string wrapped in',
|
|
53
|
+
' `{"raw": ...}`), NEVER a bare string like `"#ff0000"`. Applies to fill/stroke/textColor.',
|
|
54
|
+
"- STYLING (all `style` fields optional; use TASTEFULLY — clarity over decoration): you may set",
|
|
55
|
+
" strokeWidth, radius (rounded corners), dashed, opacity (0-100), fontSize, fontFamily,",
|
|
56
|
+
" fontStyle, align, verticalAlign, and shadow to emphasize structure. `fontStyle` is a BITMASK:",
|
|
57
|
+
" bold=1, italic=2, underline=4 — combine by ADDING (bold+italic = 3). A node's `rotation` is",
|
|
58
|
+
" degrees clockwise; only rotate when it genuinely helps (a rotated label/arrow) — keep primary",
|
|
59
|
+
" shapes upright. Default to NO extra styling unless it improves readability.",
|
|
60
|
+
"- Every edge's `source` and `target` MUST reference a node `id` that exists in `nodes`.",
|
|
61
|
+
"- Positions need not be exact — the app auto-lays-out the result — but still give rough,",
|
|
62
|
+
" non-overlapping coordinates (step nodes down/right so nothing stacks at 0,0).",
|
|
63
|
+
"- CREATE mode: build the whole diagram from scratch.",
|
|
64
|
+
"- EDIT mode: return the COMPLETE updated document. REUSE the ids of existing nodes/edges",
|
|
65
|
+
" and KEEP their `position` unless the user asked to move them; only add, remove, or",
|
|
66
|
+
" change what the instruction implies. Never drop unrelated nodes/edges.",
|
|
67
|
+
"- EDIT mode — EDGES: copy every UNCHANGED edge VERBATIM. Keep its id, source, target AND",
|
|
68
|
+
" every field already on it (including routing, waypoints, sourceAnchor, targetAnchor)",
|
|
69
|
+
" EXACTLY as given — do NOT re-route, re-point, reorder, or strip routing fields. Only touch",
|
|
70
|
+
" the specific edge(s) the instruction is about, and add new edges only for genuinely new",
|
|
71
|
+
" connections. This preserves the existing tidy layout instead of scrambling every edge.",
|
|
72
|
+
"- If the message is a question or implies no change → `diagram` null, `reply` only.",
|
|
73
|
+
"- `reply` is ALWAYS a short, natural sentence: what you built or changed (or the answer).",
|
|
74
|
+
"",
|
|
75
|
+
"DEPTH & DOMAIN EXPERTISE (this is what separates a good diagram from a toy one):",
|
|
76
|
+
"- Before emitting, THINK like a senior engineer designing this system for real. Enumerate",
|
|
77
|
+
" the components a production-grade version of THIS specific domain actually needs — the",
|
|
78
|
+
" end-to-end flows, the supporting services, the data stores, and the cross-cutting concerns",
|
|
79
|
+
" (auth/identity, caching, queues/streaming, observability, external/third-party integrations).",
|
|
80
|
+
"- Be COMPREHENSIVE, not minimal. A vague ask like \"design an X platform\" should yield a",
|
|
81
|
+
" realistic architecture (typically ~10-20 nodes), NOT 4-5 generic boxes. Cover the whole",
|
|
82
|
+
" lifecycle, not just the happy path.",
|
|
83
|
+
"- Example of the expected depth — \"design an event-driven investment platform\" should include",
|
|
84
|
+
" things a real one has: client apps, API gateway, auth/identity (OAuth/OIDC), user",
|
|
85
|
+
" onboarding/KYC, account & funding/payments, an order/trade service, an execution/broker",
|
|
86
|
+
" integration (e.g. a third-party like DriveWealth), a market-data / real-time price feed,",
|
|
87
|
+
" portfolio & positions, a ledger, a notification service, an event bus / streaming (Kafka),",
|
|
88
|
+
" primary DB(s), a cache (Redis), and observability. Apply the SAME rigor to any domain.",
|
|
89
|
+
"- Prefer SPECIFIC catalog components over generic rectangles when they fit (e.g. an API",
|
|
90
|
+
" gateway, message queue/Kafka, Redis cache, a concrete database like Postgres/MongoDB, an",
|
|
91
|
+
" auth provider) — pick the closest matching `type` from AVAILABLE COMPONENT TYPES.",
|
|
92
|
+
"- Organize for readability: group related components under a container/frame or pool",
|
|
93
|
+
" (`frame`, `pool.horizontal`/`pool.vertical`) via `parentId`, and give edges meaningful",
|
|
94
|
+
" labels for the real interaction (e.g. \"Place order\", \"Stream quotes\", \"Publish event\").",
|
|
95
|
+
"- Only trim when the user explicitly asks for something simple/high-level.",
|
|
96
|
+
"",
|
|
97
|
+
"GROUPS / CONTAINERS (how nesting works here):",
|
|
98
|
+
"- To group nodes, add ONE container node (`type` = `frame`, `pool.horizontal`, or",
|
|
99
|
+
" `pool.vertical`) with a title `label`, then set each member node's `parentId` to that",
|
|
100
|
+
" container's `id`. The container must appear in `nodes` too.",
|
|
101
|
+
"- The app AUTO-LAYS-OUT children INSIDE the container and AUTO-SIZES the container to fit",
|
|
102
|
+
" them — so you do NOT need exact child positions or a correct container size. Just declare",
|
|
103
|
+
" the parentId relationships and give each child a normal node `size` (e.g. 150x60). Do not",
|
|
104
|
+
" try to hand-pack children into a box; let the layout do it.",
|
|
105
|
+
"- Edges may connect a child to a node outside its container, or to the container itself.",
|
|
106
|
+
].join("\n");
|
|
107
|
+
export const buildDiagramUserPrompt = ({ instruction, mode, document, components = [], selection = [], canvas, }) => {
|
|
108
|
+
const componentLines = components.length
|
|
109
|
+
? components.map((c) => `${c.type} — ${c.label} (${c.category})`).join("\n")
|
|
110
|
+
: "(none provided — use generic shapes)";
|
|
111
|
+
const documentBlock = mode === "edit" && document ? JSON.stringify(document) : "(none — creating a new diagram)";
|
|
112
|
+
const canvasLine = canvas && (canvas.width || canvas.height)
|
|
113
|
+
? `CANVAS SIZE: ${Math.round(canvas.width ?? 0)} x ${Math.round(canvas.height ?? 0)}`
|
|
114
|
+
: null;
|
|
115
|
+
return [
|
|
116
|
+
`MODE: ${mode}`,
|
|
117
|
+
canvasLine,
|
|
118
|
+
"",
|
|
119
|
+
"AVAILABLE COMPONENT TYPES (type — label (category)):",
|
|
120
|
+
componentLines,
|
|
121
|
+
"",
|
|
122
|
+
"CURRENT DIAGRAM (edit mode; full document JSON):",
|
|
123
|
+
documentBlock,
|
|
124
|
+
"",
|
|
125
|
+
`SELECTED CELL IDS: ${selection.length ? selection.join(", ") : "(none)"}`,
|
|
126
|
+
"",
|
|
127
|
+
`INSTRUCTION: ${instruction}`,
|
|
128
|
+
]
|
|
129
|
+
.filter((line) => line !== null)
|
|
130
|
+
.join("\n");
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=diagram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagram.js","sourceRoot":"","sources":["../../../src/ai/prompts/diagram.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AiScriptStage } from "../types.js";
|
|
2
|
+
export declare const CONTRACT_RULES_SPEC: string;
|
|
3
|
+
export declare const STAGE_DESCRIPTIONS: Record<AiScriptStage, string>;
|
|
4
|
+
export declare const truncateForPrompt: (value: string, max?: number) => string;
|
|
5
|
+
//# sourceMappingURL=fragments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragments.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/fragments.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,eAAO,MAAM,mBAAmB,QAQpB,CAAC;AAIb,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAS5D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,EAAE,YAAQ,KAAG,MACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Shared prompt fragments consumed by more than one assistant prompt (and by
|
|
2
|
+
// the backend's legacy contract-only prompt). Single source — the backend and
|
|
3
|
+
// desktop copies of these constants were duplicated and had already drifted
|
|
4
|
+
// before centralization.
|
|
5
|
+
import { SCENARIO_CONTRACT_FORMATS } from "../../contract/formats.js";
|
|
6
|
+
// Terse operator vocabulary the model must stick to. Kept compact on purpose —
|
|
7
|
+
// it's the bulk of the system prompt and we pay tokens for every word. Mirrors
|
|
8
|
+
// ContractRuleRules so the output maps 1:1 onto a rule.
|
|
9
|
+
export const CONTRACT_RULES_SPEC = [
|
|
10
|
+
"Each rule's `rules` object may use ONLY these keys (omit the rest):",
|
|
11
|
+
"- common: required(bool), type(string|number|boolean|object|array|null), equals(string|number|bool), notEmpty(bool)",
|
|
12
|
+
"- number: min,max,greaterThan,lessThan(number); integer,positive,negative,nonZero(bool)",
|
|
13
|
+
"- string: minLength,maxLength(int); pattern,contains,notContains,startsWith,endsWith(string); caseSensitive(bool); enumValues(array); format(enum)",
|
|
14
|
+
"- array: minItems,maxItems(int); sorted({order:asc|desc,field?}); unique({mode:whole|byField,fields?})",
|
|
15
|
+
"- object: requiredKeys,forbiddenKeys(string[]); minProperties,maxProperties(int); strictSchema(bool)",
|
|
16
|
+
`- format values: ${SCENARIO_CONTRACT_FORMATS.join(", ")}`,
|
|
17
|
+
].join("\n");
|
|
18
|
+
// What each request-script slot means + which pm.* surface it exposes. Fed to
|
|
19
|
+
// the model so it knows, e.g., that pm.response does not exist pre-request.
|
|
20
|
+
export const STAGE_DESCRIPTIONS = {
|
|
21
|
+
"pre-request": "Runs BEFORE the HTTP call. `pm.response` does NOT exist. `pm.request` mutations (setHeader/setQueryParam/setRawBody/setUrl) take effect. Use for setup: auth tokens, computed headers/body, seeding env/DB/Redis.",
|
|
22
|
+
"post-response": "Runs immediately AFTER the response. `pm.response` is available; `pm.request` mutations have no effect. Use to capture values from the response into variables.",
|
|
23
|
+
tests: "Runs after the response and any declared DB/Redis steps. `pm.response`, `pm.db.post`, `pm.redis.results.post` are available. Put assertions inside `pm.test(...)`.",
|
|
24
|
+
kafka: "Runs when a Kafka event is matched (post-response/tests context). `pm.response` and `pm.kafka.event()` / `pm.kafka.messages()` are available. Put assertions inside `pm.test(...)`.",
|
|
25
|
+
};
|
|
26
|
+
export const truncateForPrompt = (value, max = 80) => value.length > max ? `${value.slice(0, max)}…` : value;
|
|
27
|
+
//# sourceMappingURL=fragments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragments.js","sourceRoot":"","sources":["../../../src/ai/prompts/fragments.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,yBAAyB;AAEzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAGtE,+EAA+E;AAC/E,+EAA+E;AAC/E,wDAAwD;AACxD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,qEAAqE;IACrE,qHAAqH;IACrH,yFAAyF;IACzF,oJAAoJ;IACpJ,wGAAwG;IACxG,sGAAsG;IACtG,oBAAoB,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;CAC3D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,8EAA8E;AAC9E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,kBAAkB,GAAkC;IAC/D,aAAa,EACX,mNAAmN;IACrN,eAAe,EACb,iKAAiK;IACnK,KAAK,EACH,oKAAoK;IACtK,KAAK,EACH,qLAAqL;CACxL,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAE,GAAG,GAAG,EAAE,EAAU,EAAE,CACnE,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ScenarioPromptInput } from "../types.js";
|
|
2
|
+
export declare const SCENARIO_AI_REFERENCE_TYPES: readonly ["request", "db", "redis", "kafka", "condition", "assertion", "script", "set-vars", "poll", "foreach", "websocket", "ai", "wait", "notification", "aggregator", "end"];
|
|
3
|
+
export interface BuildScenarioSystemPromptOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Canonical default config per node type shown in the reference. Hosts with
|
|
6
|
+
* a real node factory (desktop) inject it; default = core's static map.
|
|
7
|
+
*/
|
|
8
|
+
defaultConfigFor?: (type: string) => unknown;
|
|
9
|
+
}
|
|
10
|
+
export declare const buildScenarioSystemPrompt: (options?: BuildScenarioSystemPromptOptions) => string;
|
|
11
|
+
export declare const buildScenarioUserPrompt: (input: ScenarioPromptInput) => string;
|
|
12
|
+
//# sourceMappingURL=scenario.d.ts.map
|