@skaile/workspaces 3.25.0 → 3.27.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/CHANGELOG.md +28 -0
- package/dist/app-sdk/index.js +1 -1
- package/dist/{asset-feeds-6RKRMM6C.js → asset-feeds-AJOUKX55.js} +4 -4
- package/dist/{asset-feeds-6RKRMM6C.js.map → asset-feeds-AJOUKX55.js.map} +1 -1
- package/dist/asset-manager/index.js +1 -1
- package/dist/bridge/drivers/claude-sdk.js +3 -3
- package/dist/bridge/drivers/codex.js +1 -1
- package/dist/bridge/drivers/continue.js +2 -2
- package/dist/bridge/drivers/echo.js +3 -3
- package/dist/bridge/drivers/gemini.js +3 -3
- package/dist/bridge/drivers/goose.js +2 -2
- package/dist/bridge/drivers/omp.js +1 -1
- package/dist/bridge/drivers/opencode.js +2 -2
- package/dist/bridge/drivers/qwen.js +3 -3
- package/dist/bridge/index.js +4 -4
- package/dist/{chunk-LRA7VUT6.js → chunk-3U3ZKYR7.js} +3 -3
- package/dist/{chunk-LRA7VUT6.js.map → chunk-3U3ZKYR7.js.map} +1 -1
- package/dist/{chunk-CP62G5PK.js → chunk-53ORCYPJ.js} +347 -16
- package/dist/chunk-53ORCYPJ.js.map +1 -0
- package/dist/{chunk-UEW6C64M.js → chunk-5UWAOYDN.js} +4 -4
- package/dist/{chunk-UEW6C64M.js.map → chunk-5UWAOYDN.js.map} +1 -1
- package/dist/{chunk-V6QKAC3Z.js → chunk-72DG6GSB.js} +8 -5
- package/dist/chunk-72DG6GSB.js.map +1 -0
- package/dist/{chunk-EKFFTOQJ.js → chunk-773WLEXL.js} +2 -2
- package/dist/{chunk-EKFFTOQJ.js.map → chunk-773WLEXL.js.map} +1 -1
- package/dist/{chunk-YNO3LBRH.js → chunk-7P6ASOFL.js} +3 -3
- package/dist/{chunk-YNO3LBRH.js.map → chunk-7P6ASOFL.js.map} +1 -1
- package/dist/{chunk-ZQZXCVYV.js → chunk-AEN2UFDN.js} +2 -2
- package/dist/{chunk-ZQZXCVYV.js.map → chunk-AEN2UFDN.js.map} +1 -1
- package/dist/{chunk-X3DODPMF.js → chunk-AQW4BWNR.js} +2 -2
- package/dist/{chunk-X3DODPMF.js.map → chunk-AQW4BWNR.js.map} +1 -1
- package/dist/{chunk-BKUKF632.js → chunk-AU4TUVHW.js} +3 -3
- package/dist/{chunk-BKUKF632.js.map → chunk-AU4TUVHW.js.map} +1 -1
- package/dist/{chunk-5PFJVZ7F.js → chunk-DY5GHUTC.js} +2 -2
- package/dist/{chunk-5PFJVZ7F.js.map → chunk-DY5GHUTC.js.map} +1 -1
- package/dist/{chunk-HGDFQDHT.js → chunk-F2GEM5B3.js} +6 -6
- package/dist/{chunk-HGDFQDHT.js.map → chunk-F2GEM5B3.js.map} +1 -1
- package/dist/{chunk-J4WDQL42.js → chunk-FFE7YLYO.js} +4 -4
- package/dist/{chunk-J4WDQL42.js.map → chunk-FFE7YLYO.js.map} +1 -1
- package/dist/{chunk-3D3BKCVQ.js → chunk-FYIHH56K.js} +4 -4
- package/dist/{chunk-3D3BKCVQ.js.map → chunk-FYIHH56K.js.map} +1 -1
- package/dist/{chunk-W5LPG3X6.js → chunk-JMYOJ3PA.js} +5 -3
- package/dist/chunk-JMYOJ3PA.js.map +1 -0
- package/dist/{chunk-2FDKUKDE.js → chunk-M6VQU5TS.js} +3 -3
- package/dist/{chunk-2FDKUKDE.js.map → chunk-M6VQU5TS.js.map} +1 -1
- package/dist/{chunk-6NTKN6QC.js → chunk-MQASB52N.js} +3 -3
- package/dist/{chunk-6NTKN6QC.js.map → chunk-MQASB52N.js.map} +1 -1
- package/dist/{chunk-WMZT7VDS.js → chunk-N27DSFA7.js} +209 -12
- package/dist/chunk-N27DSFA7.js.map +1 -0
- package/dist/{chunk-BIPMCNAK.js → chunk-O5JUZIVR.js} +4 -4
- package/dist/{chunk-BIPMCNAK.js.map → chunk-O5JUZIVR.js.map} +1 -1
- package/dist/{chunk-YCMHWNZA.js → chunk-TIOT3ZOQ.js} +3 -3
- package/dist/{chunk-YCMHWNZA.js.map → chunk-TIOT3ZOQ.js.map} +1 -1
- package/dist/{chunk-3CF5HJ6V.js → chunk-UAEGKCE5.js} +6 -6
- package/dist/{chunk-3CF5HJ6V.js.map → chunk-UAEGKCE5.js.map} +1 -1
- package/dist/{chunk-HTIGD3DR.js → chunk-UL4LD7KD.js} +3 -3
- package/dist/{chunk-HTIGD3DR.js.map → chunk-UL4LD7KD.js.map} +1 -1
- package/dist/{chunk-NKPDUYRH.js → chunk-XMULHVKX.js} +4 -4
- package/dist/{chunk-NKPDUYRH.js.map → chunk-XMULHVKX.js.map} +1 -1
- package/dist/{chunk-4YRRPWHY.js → chunk-YLL65VXQ.js} +180 -31
- package/dist/chunk-YLL65VXQ.js.map +1 -0
- package/dist/cli/index.js +37 -37
- package/dist/connectors/index.js +8 -8
- package/dist/{ensure-sources-XYDPVBSP.js → ensure-sources-DYGQNAJM.js} +4 -4
- package/dist/{ensure-sources-XYDPVBSP.js.map → ensure-sources-DYGQNAJM.js.map} +1 -1
- package/dist/factory-assets/connectors/box.js +8 -8
- package/dist/factory-assets/connectors/deploy.js +8 -8
- package/dist/factory-assets/connectors/devserver.js +8 -8
- package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/adapter.js +8 -8
- package/dist/factory-assets/connectors/flow/classifier-subprompt-runner.d.ts +40 -0
- package/dist/factory-assets/connectors/flow/classifier-subprompt-runner.d.ts.map +1 -0
- package/dist/factory-assets/connectors/flow/contract/classifier.d.ts +60 -0
- package/dist/factory-assets/connectors/flow/contract/classifier.d.ts.map +1 -0
- package/dist/factory-assets/connectors/flow/contract/expression.d.ts +22 -0
- package/dist/factory-assets/connectors/flow/contract/expression.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/contract/index.d.ts +2 -1
- package/dist/factory-assets/connectors/flow/contract/index.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/contract/schema.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/contract.js +3 -3
- package/dist/factory-assets/connectors/flow/engine/engine.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts +9 -1
- package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/engine.js +2 -2
- package/dist/factory-assets/connectors/flow/index.d.ts +1 -0
- package/dist/factory-assets/connectors/flow/index.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/run-flow.js +9 -9
- package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts +7 -0
- package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow.js +8 -8
- package/dist/factory-assets/connectors/git.js +8 -8
- package/dist/factory-assets/connectors/gmail.js +8 -8
- package/dist/factory-assets/connectors/googledrive.js +8 -8
- package/dist/factory-assets/connectors/local.js +8 -8
- package/dist/factory-assets/connectors/mattermost.js +8 -8
- package/dist/factory-assets/connectors/memory.js +8 -8
- package/dist/factory-assets/connectors/minio.js +8 -8
- package/dist/factory-assets/connectors/postgres.js +8 -8
- package/dist/factory-assets/connectors/s3.js +8 -8
- package/dist/factory-assets/connectors/sharepoint.js +8 -8
- package/dist/factory-assets/connectors/sqlite.js +8 -8
- package/dist/factory-assets/connectors/static-server.js +8 -8
- package/dist/factory-assets/connectors/tunnel.js +8 -8
- package/dist/factory-assets/connectors/webdav.js +8 -8
- package/dist/factory-assets/connectors/xstate-store.js +8 -8
- package/dist/factory-assets/connectors/xstate.js +8 -8
- package/dist/{flows-4DYGXE4A.js → flows-MI2VM5JZ.js} +3 -3
- package/dist/{flows-4DYGXE4A.js.map → flows-MI2VM5JZ.js.map} +1 -1
- package/dist/{helpers-47SRTVSY.js → helpers-G6XZPN6L.js} +4 -4
- package/dist/{helpers-47SRTVSY.js.map → helpers-G6XZPN6L.js.map} +1 -1
- package/dist/{library-publish-W7CIEIJJ.js → library-publish-WHGKK7G5.js} +8 -8
- package/dist/{library-publish-W7CIEIJJ.js.map → library-publish-WHGKK7G5.js.map} +1 -1
- package/dist/{open-library-B2PEJ3UT.js → open-library-4JSLGWL6.js} +7 -7
- package/dist/{open-library-B2PEJ3UT.js.map → open-library-4JSLGWL6.js.map} +1 -1
- package/dist/{project-TOICQYNZ.js → project-LISE6I5O.js} +5 -5
- package/dist/{project-TOICQYNZ.js.map → project-LISE6I5O.js.map} +1 -1
- package/dist/runner/index.js +14 -14
- package/dist/runner/src/resource-handler.d.ts +34 -1
- package/dist/runner/src/resource-handler.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts +3 -0
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +1 -1
- package/dist/sdk/bridge.js +4 -4
- package/dist/sdk/flow.js +2 -2
- package/dist/sdk/index.js +14 -14
- package/dist/sdk/runner.js +14 -14
- package/dist/sdk/session.js +2 -2
- package/dist/sdk/types.js +1 -1
- package/dist/session/index.js +2 -2
- package/dist/{setup-HLKIP7XW.js → setup-CIRH5BYB.js} +6 -6
- package/dist/{setup-HLKIP7XW.js.map → setup-CIRH5BYB.js.map} +1 -1
- package/dist/{source-HZTCDRGB.js → source-FKVEUOBQ.js} +8 -8
- package/dist/{source-HZTCDRGB.js.map → source-FKVEUOBQ.js.map} +1 -1
- package/dist/{source-manifest-publish-KEDEMOQO.js → source-manifest-publish-LTRXO2OQ.js} +9 -9
- package/dist/{source-manifest-publish-KEDEMOQO.js.map → source-manifest-publish-LTRXO2OQ.js.map} +1 -1
- package/dist/tui/index.js +14 -14
- package/dist/types/index.js +1 -1
- package/dist/types/src/events.d.ts +7 -0
- package/dist/types/src/events.d.ts.map +1 -1
- package/dist/types/src/flow.d.ts +94 -0
- package/dist/types/src/flow.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/protocol.d.ts +11 -0
- package/dist/types/src/protocol.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +13 -1
- package/dist/types/src/version.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +3 -3
- package/dist/workspace-plugin/adapters/omp.js +3 -3
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-4YRRPWHY.js.map +0 -1
- package/dist/chunk-CP62G5PK.js.map +0 -1
- package/dist/chunk-V6QKAC3Z.js.map +0 -1
- package/dist/chunk-W5LPG3X6.js.map +0 -1
- package/dist/chunk-WMZT7VDS.js.map +0 -1
|
@@ -1,5 +1,189 @@
|
|
|
1
1
|
import * as z from 'zod';
|
|
2
2
|
|
|
3
|
+
// factory-assets/connectors/flow/contract/classifier.ts
|
|
4
|
+
var RESERVED_CLASSIFIER_FIELDS = ["confidence", "calibrated"];
|
|
5
|
+
var MAX_CHOICE_OPTIONS = 255;
|
|
6
|
+
var MIN_SCORE_LEVELS = 2;
|
|
7
|
+
var MAX_SCORE_LEVELS = 10;
|
|
8
|
+
function declaredOutputProperties(outputSchema) {
|
|
9
|
+
if (typeof outputSchema !== "object" || outputSchema === null) return [];
|
|
10
|
+
const properties = outputSchema.properties;
|
|
11
|
+
if (typeof properties !== "object" || properties === null) return [];
|
|
12
|
+
return Object.keys(properties);
|
|
13
|
+
}
|
|
14
|
+
function declaresReservedClassifierField(outputSchema) {
|
|
15
|
+
const declared = declaredOutputProperties(outputSchema);
|
|
16
|
+
return RESERVED_CLASSIFIER_FIELDS.some((name) => declared.includes(name));
|
|
17
|
+
}
|
|
18
|
+
function isRecord(value) {
|
|
19
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20
|
+
}
|
|
21
|
+
function typeSet(schema) {
|
|
22
|
+
const type = schema.type;
|
|
23
|
+
if (typeof type === "string") return /* @__PURE__ */ new Set([type]);
|
|
24
|
+
if (Array.isArray(type) && type.every((entry) => typeof entry === "string")) {
|
|
25
|
+
return new Set(type);
|
|
26
|
+
}
|
|
27
|
+
return void 0;
|
|
28
|
+
}
|
|
29
|
+
function sameSet(actual, expected) {
|
|
30
|
+
return actual !== void 0 && actual.size === expected.length && expected.every((entry) => actual.has(entry));
|
|
31
|
+
}
|
|
32
|
+
function decisionOf(field, schema) {
|
|
33
|
+
if (!isRecord(schema)) return { issue: `decision property ${field} must be a schema object` };
|
|
34
|
+
const types = typeSet(schema);
|
|
35
|
+
if (sameSet(types, ["boolean"]) && schema.enum === void 0 && schema.oneOf === void 0) {
|
|
36
|
+
return {
|
|
37
|
+
decision: {
|
|
38
|
+
kind: "binary",
|
|
39
|
+
field,
|
|
40
|
+
...typeof schema.description === "string" ? { description: schema.description } : {}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(schema.enum)) {
|
|
45
|
+
if (types !== void 0 && !sameSet(types, ["string"])) {
|
|
46
|
+
return { issue: `decision property ${field}: an enum decision must be typed string` };
|
|
47
|
+
}
|
|
48
|
+
const labels = schema.enum;
|
|
49
|
+
if (!labels.every((label) => typeof label === "string" && label.length > 0)) {
|
|
50
|
+
return { issue: `decision property ${field}: every enum label must be a non-empty string` };
|
|
51
|
+
}
|
|
52
|
+
if (new Set(labels).size !== labels.length) {
|
|
53
|
+
return { issue: `decision property ${field}: enum labels must be unique` };
|
|
54
|
+
}
|
|
55
|
+
if (labels.length < 2 || labels.length > MAX_CHOICE_OPTIONS) {
|
|
56
|
+
return {
|
|
57
|
+
issue: `decision property ${field}: a choice needs 2\u2013${MAX_CHOICE_OPTIONS} labels`
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
decision: {
|
|
62
|
+
kind: "choice",
|
|
63
|
+
field,
|
|
64
|
+
options: Object.fromEntries(labels.map((label) => [label, null]))
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(schema.oneOf)) {
|
|
69
|
+
const entries = schema.oneOf;
|
|
70
|
+
if (!entries.every(
|
|
71
|
+
(entry) => isRecord(entry) && Object.keys(entry).every((key) => key === "const" || key === "description") && "const" in entry && (entry.description === void 0 || typeof entry.description === "string")
|
|
72
|
+
)) {
|
|
73
|
+
return {
|
|
74
|
+
issue: `decision property ${field}: every oneOf entry must be { "const": \u2026, "description": "\u2026" }`
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const consts = entries.map(
|
|
78
|
+
(entry) => entry.const
|
|
79
|
+
);
|
|
80
|
+
if (new Set(consts).size !== consts.length) {
|
|
81
|
+
return { issue: `decision property ${field}: oneOf consts must be unique` };
|
|
82
|
+
}
|
|
83
|
+
if (consts.every((value) => typeof value === "string" && value.length > 0)) {
|
|
84
|
+
if (types !== void 0 && !sameSet(types, ["string"])) {
|
|
85
|
+
return {
|
|
86
|
+
issue: `decision property ${field}: a string-labelled choice must be typed string`
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (consts.length < 2 || consts.length > MAX_CHOICE_OPTIONS) {
|
|
90
|
+
return {
|
|
91
|
+
issue: `decision property ${field}: a choice needs 2\u2013${MAX_CHOICE_OPTIONS} options`
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
decision: {
|
|
96
|
+
kind: "choice",
|
|
97
|
+
field,
|
|
98
|
+
options: Object.fromEntries(
|
|
99
|
+
entries.map((entry) => [
|
|
100
|
+
entry.const,
|
|
101
|
+
entry.description ?? null
|
|
102
|
+
])
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (consts.every((value) => typeof value === "number" && Number.isInteger(value))) {
|
|
108
|
+
if (types !== void 0 && !sameSet(types, ["integer"])) {
|
|
109
|
+
return { issue: `decision property ${field}: a score must be typed integer` };
|
|
110
|
+
}
|
|
111
|
+
if (consts.length < MIN_SCORE_LEVELS || consts.length > MAX_SCORE_LEVELS) {
|
|
112
|
+
return {
|
|
113
|
+
issue: `decision property ${field}: a score needs ${MIN_SCORE_LEVELS}\u2013${MAX_SCORE_LEVELS} levels`
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const ordered = [...entries].sort(
|
|
117
|
+
(a, b) => a.const - b.const
|
|
118
|
+
);
|
|
119
|
+
return {
|
|
120
|
+
decision: {
|
|
121
|
+
kind: "score",
|
|
122
|
+
field,
|
|
123
|
+
levels: ordered.map((entry) => entry.description ?? String(entry.const)),
|
|
124
|
+
values: ordered.map((entry) => entry.const)
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
issue: `decision property ${field}: oneOf consts must be all non-empty strings (choice) or all integers (score)`
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
issue: `decision property ${field} must be a boolean, a string enum, or a oneOf of { const, description }`
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function checkClassifierShape(outputSchema) {
|
|
137
|
+
if (!declaresReservedClassifierField(outputSchema)) return { classifier: false };
|
|
138
|
+
const schema = outputSchema;
|
|
139
|
+
const properties = schema.properties;
|
|
140
|
+
const issues = [];
|
|
141
|
+
if (schema.type !== "object") issues.push('the output schema must be "type": "object"');
|
|
142
|
+
if (schema.additionalProperties !== false) {
|
|
143
|
+
issues.push("the output schema must set additionalProperties: false");
|
|
144
|
+
}
|
|
145
|
+
const confidence = properties.confidence;
|
|
146
|
+
if (!isRecord(confidence) || !sameSet(typeSet(confidence), ["number", "null"])) {
|
|
147
|
+
issues.push('confidence must be typed ["number", "null"]');
|
|
148
|
+
}
|
|
149
|
+
const calibrated = properties.calibrated;
|
|
150
|
+
if (!isRecord(calibrated) || !sameSet(typeSet(calibrated), ["boolean"])) {
|
|
151
|
+
issues.push('calibrated must be typed "boolean"');
|
|
152
|
+
}
|
|
153
|
+
const decisionFields = Object.keys(properties).filter(
|
|
154
|
+
(name) => !RESERVED_CLASSIFIER_FIELDS.includes(name)
|
|
155
|
+
);
|
|
156
|
+
let decision;
|
|
157
|
+
if (decisionFields.length !== 1) {
|
|
158
|
+
issues.push(
|
|
159
|
+
`a classifier node declares exactly one decision property besides confidence and calibrated (found ${decisionFields.length})`
|
|
160
|
+
);
|
|
161
|
+
} else {
|
|
162
|
+
const result = decisionOf(decisionFields[0], properties[decisionFields[0]]);
|
|
163
|
+
if ("issue" in result) issues.push(result.issue);
|
|
164
|
+
else decision = result.decision;
|
|
165
|
+
}
|
|
166
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
167
|
+
const expectedRequired = [...decisionFields.slice(0, 1), ...RESERVED_CLASSIFIER_FIELDS];
|
|
168
|
+
if (required.length !== expectedRequired.length || !expectedRequired.every((name) => required.includes(name))) {
|
|
169
|
+
issues.push(`required must be exactly [${expectedRequired.map((n) => `"${n}"`).join(", ")}]`);
|
|
170
|
+
}
|
|
171
|
+
if (issues.length > 0 || !decision) return { classifier: true, issues };
|
|
172
|
+
return { classifier: true, decision };
|
|
173
|
+
}
|
|
174
|
+
function classifierDecision(outputSchema) {
|
|
175
|
+
const check = checkClassifierShape(outputSchema);
|
|
176
|
+
return check.classifier && "decision" in check ? check.decision : void 0;
|
|
177
|
+
}
|
|
178
|
+
function withoutReservedClassifierFields(outputSchema) {
|
|
179
|
+
const properties = { ...outputSchema.properties };
|
|
180
|
+
for (const name of RESERVED_CLASSIFIER_FIELDS) delete properties[name];
|
|
181
|
+
const required = Array.isArray(outputSchema.required) ? outputSchema.required.filter(
|
|
182
|
+
(name) => !RESERVED_CLASSIFIER_FIELDS.includes(String(name))
|
|
183
|
+
) : void 0;
|
|
184
|
+
return { ...outputSchema, properties, ...required ? { required } : {} };
|
|
185
|
+
}
|
|
186
|
+
|
|
3
187
|
// factory-assets/connectors/flow/contract/expression.ts
|
|
4
188
|
var FLOW_EXPRESSION_LIMITS = Object.freeze({
|
|
5
189
|
maxLength: 4096,
|
|
@@ -235,20 +419,32 @@ function assertBooleanOperand(value, position) {
|
|
|
235
419
|
if (!isBooleanOperand(value)) throw expressionError("requires boolean operands", position);
|
|
236
420
|
}
|
|
237
421
|
var Parser = class {
|
|
238
|
-
constructor(tokens, context, onPath, onBooleanPath, onEvaluatedPath) {
|
|
422
|
+
constructor(tokens, context, onPath, onBooleanPath, onEvaluatedPath, onComparison) {
|
|
239
423
|
this.tokens = tokens;
|
|
240
424
|
this.context = context;
|
|
241
425
|
this.onPath = onPath;
|
|
242
426
|
this.onBooleanPath = onBooleanPath;
|
|
243
427
|
this.onEvaluatedPath = onEvaluatedPath;
|
|
428
|
+
this.onComparison = onComparison;
|
|
244
429
|
}
|
|
245
430
|
tokens;
|
|
246
431
|
context;
|
|
247
432
|
onPath;
|
|
248
433
|
onBooleanPath;
|
|
249
434
|
onEvaluatedPath;
|
|
435
|
+
onComparison;
|
|
250
436
|
index = 0;
|
|
251
437
|
nesting = 0;
|
|
438
|
+
/** Literal `path == true` conjuncts already parsed, one frame per enclosing `&&` chain. */
|
|
439
|
+
guardFrames = [];
|
|
440
|
+
/**
|
|
441
|
+
* Guards the operand {@link parseComparison} just parsed establishes when true:
|
|
442
|
+
* its own path for a literal `path == true`, or every guard of a parenthesized
|
|
443
|
+
* `&&` group, which is true only when all its conjuncts are.
|
|
444
|
+
*/
|
|
445
|
+
lastGuards = [];
|
|
446
|
+
/** Guards of the `&&` / `||` chain that just finished; empty once a `||` joined it. */
|
|
447
|
+
lastChainGuards = [];
|
|
252
448
|
parse(evaluate2 = true) {
|
|
253
449
|
const value = this.parseOr(evaluate2);
|
|
254
450
|
const trailing = this.peek();
|
|
@@ -272,7 +468,9 @@ var Parser = class {
|
|
|
272
468
|
}
|
|
273
469
|
parseOr(evaluate2) {
|
|
274
470
|
let value = this.parseAnd(evaluate2);
|
|
471
|
+
let disjunction = false;
|
|
275
472
|
while (this.peek().value === "||") {
|
|
473
|
+
disjunction = true;
|
|
276
474
|
const operator = this.take();
|
|
277
475
|
assertBooleanOperand(value, operator.position);
|
|
278
476
|
if (isStaticPath(value)) this.onBooleanPath?.(value.path);
|
|
@@ -282,31 +480,51 @@ var Parser = class {
|
|
|
282
480
|
if (isStaticPath(right)) this.onBooleanPath?.(right.path);
|
|
283
481
|
value = evaluate2 ? value === true || right === true : STATIC_BOOLEAN;
|
|
284
482
|
}
|
|
483
|
+
if (disjunction) this.lastChainGuards = [];
|
|
285
484
|
return value;
|
|
286
485
|
}
|
|
287
486
|
parseAnd(evaluate2) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
487
|
+
const guards = [];
|
|
488
|
+
this.guardFrames.push(guards);
|
|
489
|
+
try {
|
|
490
|
+
let value = this.parseComparison(evaluate2);
|
|
491
|
+
guards.push(...this.lastGuards);
|
|
492
|
+
while (this.peek().value === "&&") {
|
|
493
|
+
const operator = this.take();
|
|
494
|
+
assertBooleanOperand(value, operator.position);
|
|
495
|
+
if (isStaticPath(value)) this.onBooleanPath?.(value.path);
|
|
496
|
+
const evaluateRight = evaluate2 && value === true;
|
|
497
|
+
const right = this.parseComparison(evaluateRight);
|
|
498
|
+
guards.push(...this.lastGuards);
|
|
499
|
+
assertBooleanOperand(right, operator.position);
|
|
500
|
+
if (isStaticPath(right)) this.onBooleanPath?.(right.path);
|
|
501
|
+
value = evaluate2 ? value === true && right === true : STATIC_BOOLEAN;
|
|
502
|
+
}
|
|
503
|
+
this.lastChainGuards = [...guards];
|
|
504
|
+
return value;
|
|
505
|
+
} finally {
|
|
506
|
+
this.guardFrames.pop();
|
|
298
507
|
}
|
|
299
|
-
return value;
|
|
300
508
|
}
|
|
301
509
|
parseComparison(evaluate2) {
|
|
510
|
+
const group = this.peek().value === "(";
|
|
302
511
|
const left = this.parseUnary(evaluate2);
|
|
303
512
|
const token = this.peek();
|
|
304
513
|
if (token.kind !== "operator" || !["==", "!=", "<", "<=", ">", ">=", "in"].includes(String(token.value))) {
|
|
514
|
+
this.lastGuards = group ? this.lastChainGuards : [];
|
|
305
515
|
return left;
|
|
306
516
|
}
|
|
307
517
|
this.take();
|
|
308
518
|
const right = this.parseUnary(evaluate2);
|
|
309
|
-
|
|
519
|
+
const operator = String(token.value);
|
|
520
|
+
this.onComparison?.({
|
|
521
|
+
operator,
|
|
522
|
+
left: isStaticPath(left) ? { path: left.path } : { literal: left },
|
|
523
|
+
right: isStaticPath(right) ? { path: right.path } : { literal: right },
|
|
524
|
+
guards: this.guardFrames.flat()
|
|
525
|
+
});
|
|
526
|
+
this.lastGuards = operator === "==" && isStaticPath(left) && right === true ? [left.path] : [];
|
|
527
|
+
return evaluate2 ? compare(operator, left, right, token.position) : STATIC_BOOLEAN;
|
|
310
528
|
}
|
|
311
529
|
parseUnary(evaluate2) {
|
|
312
530
|
const operator = this.accept("!");
|
|
@@ -360,6 +578,21 @@ var Parser = class {
|
|
|
360
578
|
}
|
|
361
579
|
}
|
|
362
580
|
};
|
|
581
|
+
function inspectFlowExpressionComparisons(expression) {
|
|
582
|
+
const tokens = tokenize(expression);
|
|
583
|
+
if (expression.trim() === "default") return [];
|
|
584
|
+
const comparisons = [];
|
|
585
|
+
const context = { flow: { input: {} }, nodes: {} };
|
|
586
|
+
new Parser(
|
|
587
|
+
tokens,
|
|
588
|
+
context,
|
|
589
|
+
void 0,
|
|
590
|
+
void 0,
|
|
591
|
+
void 0,
|
|
592
|
+
(comparison) => comparisons.push(comparison)
|
|
593
|
+
).parse(false);
|
|
594
|
+
return comparisons;
|
|
595
|
+
}
|
|
363
596
|
function inspectFlowExpression(expression, requireBoolean = true) {
|
|
364
597
|
const tokens = tokenize(expression);
|
|
365
598
|
if (expression.trim() === "default") return [];
|
|
@@ -949,6 +1182,7 @@ var FlowDefinitionSchema = FlowDefinitionObjectSchema.superRefine((flow, context
|
|
|
949
1182
|
}
|
|
950
1183
|
}
|
|
951
1184
|
}
|
|
1185
|
+
validateClassifierRules(flow, context);
|
|
952
1186
|
const state = /* @__PURE__ */ new Map();
|
|
953
1187
|
for (const nodeId of nodeIds) {
|
|
954
1188
|
if (state.has(nodeId)) continue;
|
|
@@ -973,6 +1207,103 @@ var FlowDefinitionSchema = FlowDefinitionObjectSchema.superRefine((flow, context
|
|
|
973
1207
|
}
|
|
974
1208
|
}
|
|
975
1209
|
});
|
|
1210
|
+
var ORDERING_OPERATORS = /* @__PURE__ */ new Set(["<", "<=", ">", ">="]);
|
|
1211
|
+
function validateClassifierRules(flow, context) {
|
|
1212
|
+
const classifierIds = /* @__PURE__ */ new Set();
|
|
1213
|
+
for (const [nodeIndex, node] of flow.nodes.entries()) {
|
|
1214
|
+
const outputSchema = node.contract?.output?.fields;
|
|
1215
|
+
const path = ["nodes", nodeIndex, "contract", "output", "fields"];
|
|
1216
|
+
if (node.run.kind === "subprompt") {
|
|
1217
|
+
const check = checkClassifierShape(outputSchema);
|
|
1218
|
+
if (!check.classifier) continue;
|
|
1219
|
+
classifierIds.add(node.id);
|
|
1220
|
+
if ("issues" in check) {
|
|
1221
|
+
context.addIssue({
|
|
1222
|
+
code: "custom",
|
|
1223
|
+
path,
|
|
1224
|
+
message: `subprompt ${node.id} declares a reserved classifier field but is not classifier-shaped: ${check.issues.join("; ")}`
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
continue;
|
|
1228
|
+
}
|
|
1229
|
+
if ((node.run.kind === "agent" || node.run.kind === "sub-flow") && declaresReservedClassifierField(outputSchema)) {
|
|
1230
|
+
const names = RESERVED_CLASSIFIER_FIELDS.filter(
|
|
1231
|
+
(name) => declaredOutputProperties(outputSchema).includes(name)
|
|
1232
|
+
);
|
|
1233
|
+
context.addIssue({
|
|
1234
|
+
code: "custom",
|
|
1235
|
+
path,
|
|
1236
|
+
message: `${names.join(" and ")} ${names.length > 1 ? "are" : "is"} reserved for classifier-shaped subprompt nodes; ${node.run.kind} node ${node.id} cannot declare ${names.length > 1 ? "them" : "it"}`
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
if (classifierIds.size === 0) return;
|
|
1241
|
+
const reservedRead = (path) => {
|
|
1242
|
+
const segments = path.split(".");
|
|
1243
|
+
if (segments.length !== 5 || segments[0] !== "nodes" || segments[2] !== "output" || segments[3] !== "fields" || !classifierIds.has(segments[1]) || !RESERVED_CLASSIFIER_FIELDS.includes(segments[4])) {
|
|
1244
|
+
return void 0;
|
|
1245
|
+
}
|
|
1246
|
+
return { producer: segments[1], field: segments[4] };
|
|
1247
|
+
};
|
|
1248
|
+
const readsReserved = (expression) => {
|
|
1249
|
+
try {
|
|
1250
|
+
return inspectFlowExpression(expression, false).some(({ path }) => reservedRead(path));
|
|
1251
|
+
} catch {
|
|
1252
|
+
return false;
|
|
1253
|
+
}
|
|
1254
|
+
};
|
|
1255
|
+
const checkGuards = (expression, path) => {
|
|
1256
|
+
let comparisons;
|
|
1257
|
+
try {
|
|
1258
|
+
comparisons = inspectFlowExpressionComparisons(expression);
|
|
1259
|
+
} catch {
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
for (const comparison of comparisons) {
|
|
1263
|
+
if (!ORDERING_OPERATORS.has(comparison.operator)) continue;
|
|
1264
|
+
for (const operand of [comparison.left, comparison.right]) {
|
|
1265
|
+
if (!("path" in operand)) continue;
|
|
1266
|
+
const read = reservedRead(operand.path);
|
|
1267
|
+
if (read?.field !== "confidence") continue;
|
|
1268
|
+
const guard = `nodes.${read.producer}.output.fields.calibrated`;
|
|
1269
|
+
if (comparison.guards.includes(guard)) continue;
|
|
1270
|
+
context.addIssue({
|
|
1271
|
+
code: "custom",
|
|
1272
|
+
path,
|
|
1273
|
+
message: `${operand.path} is null when the classifier is uncalibrated, so an ordering comparison on it must be guarded: put the literal conjunct \`${guard} == true\` earlier in the same && chain, optionally parenthesized (\`true == \u2026\`, \`!= false\` and a guard inside \`||\` are not accepted)`
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
for (const [nodeIndex, node] of flow.nodes.entries()) {
|
|
1279
|
+
for (const [requireIndex, requirement] of node.contract?.requires?.entries() ?? []) {
|
|
1280
|
+
if (!readsReserved(requirement.expr)) continue;
|
|
1281
|
+
context.addIssue({
|
|
1282
|
+
code: "custom",
|
|
1283
|
+
path: ["nodes", nodeIndex, "contract", "requires", requireIndex, "expr"],
|
|
1284
|
+
message: "a contract.requires guard cannot read a classifier's confidence or calibrated; decide on a classifier's answer at a router, which has a default route"
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
for (const [bindingName2, binding] of Object.entries(node.contract?.input ?? {})) {
|
|
1288
|
+
for (const expression of collectFlowBindingExpressions(binding)) {
|
|
1289
|
+
checkGuards(expression, ["nodes", nodeIndex, "contract", "input", bindingName2]);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
if (node.run.kind !== "router") continue;
|
|
1293
|
+
const routes = node.run.routes;
|
|
1294
|
+
for (const [routeIndex, route] of routes.entries()) {
|
|
1295
|
+
checkGuards(route.when, ["nodes", nodeIndex, "run", "routes", routeIndex, "when"]);
|
|
1296
|
+
}
|
|
1297
|
+
const readsAny = routes.some((route) => readsReserved(route.when));
|
|
1298
|
+
if (readsAny && routes.at(-1)?.when.trim() !== "default") {
|
|
1299
|
+
context.addIssue({
|
|
1300
|
+
code: "custom",
|
|
1301
|
+
path: ["nodes", nodeIndex, "run", "routes"],
|
|
1302
|
+
message: `router ${node.id} reads a classifier's confidence or calibrated, so its last route must be the unconditional "default": on the uncalibrated fallback every guarded route is false, and without a default the router would settle nowhere`
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
976
1307
|
var successfullyParsedDefinitions = /* @__PURE__ */ new WeakMap();
|
|
977
1308
|
function valueFingerprint(value, ancestors) {
|
|
978
1309
|
if (value === null) return "null";
|
|
@@ -1279,6 +1610,6 @@ function parseFlowDefinition(data) {
|
|
|
1279
1610
|
return normalizeV1(data);
|
|
1280
1611
|
}
|
|
1281
1612
|
|
|
1282
|
-
export { FLOW_EXPRESSION_LIMITS, FlowDefinitionSchema, FlowExpressionError, InputSchema, collectFlowBindingExpressions, evaluate, evaluateFlowExpression, inspectFlowExpression, normalizeV1, parseFlowDefinition, resolveFlowBindings, stableFlowJson };
|
|
1283
|
-
//# sourceMappingURL=chunk-
|
|
1284
|
-
//# sourceMappingURL=chunk-
|
|
1613
|
+
export { FLOW_EXPRESSION_LIMITS, FlowDefinitionSchema, FlowExpressionError, InputSchema, RESERVED_CLASSIFIER_FIELDS, checkClassifierShape, classifierDecision, collectFlowBindingExpressions, declaresReservedClassifierField, evaluate, evaluateFlowExpression, inspectFlowExpression, inspectFlowExpressionComparisons, normalizeV1, parseFlowDefinition, resolveFlowBindings, stableFlowJson, withoutReservedClassifierFields };
|
|
1614
|
+
//# sourceMappingURL=chunk-53ORCYPJ.js.map
|
|
1615
|
+
//# sourceMappingURL=chunk-53ORCYPJ.js.map
|