@crewx/workflow 0.3.22-rc.192 → 0.3.22-rc.194
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/cli.d.ts +1 -1
- package/dist/cli.js +17 -1190
- package/dist/src/card-state.d.ts +1 -1
- package/dist/src/card-state.js +1 -121
- package/dist/src/engine.d.ts +1 -1
- package/dist/src/engine.js +1 -379
- package/dist/src/failure.d.ts +1 -1
- package/dist/src/failure.js +1 -122
- package/dist/src/file-lock.d.ts +1 -1
- package/dist/src/file-lock.js +1 -97
- package/dist/src/list-view.d.ts +1 -1
- package/dist/src/list-view.js +3 -188
- package/dist/src/mermaid.d.ts +1 -1
- package/dist/src/mermaid.js +2 -133
- package/dist/src/parent-task-sync.d.ts +1 -1
- package/dist/src/parent-task-sync.js +1 -445
- package/dist/src/retry-policy.d.ts +1 -1
- package/dist/src/retry-policy.js +1 -140
- package/dist/src/run-manager.d.ts +1 -1
- package/dist/src/run-manager.js +4 -2165
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.js +1 -5
- package/dist/src/utils/output-format.d.ts +1 -1
- package/dist/src/utils/output-format.js +12 -206
- package/dist/src/utils/shell-security.d.ts +1 -1
- package/dist/src/utils/shell-security.js +1 -138
- package/dist/src/workflow-persistence.d.ts +1 -1
- package/dist/src/workflow-persistence.js +1 -224
- package/package.json +4 -4
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/src/card-state.d.ts.map +0 -1
- package/dist/src/card-state.js.map +0 -1
- package/dist/src/engine.d.ts.map +0 -1
- package/dist/src/engine.js.map +0 -1
- package/dist/src/failure.d.ts.map +0 -1
- package/dist/src/failure.js.map +0 -1
- package/dist/src/file-lock.d.ts.map +0 -1
- package/dist/src/file-lock.js.map +0 -1
- package/dist/src/list-view.d.ts.map +0 -1
- package/dist/src/list-view.js.map +0 -1
- package/dist/src/mermaid.d.ts.map +0 -1
- package/dist/src/mermaid.js.map +0 -1
- package/dist/src/parent-task-sync.d.ts.map +0 -1
- package/dist/src/parent-task-sync.js.map +0 -1
- package/dist/src/retry-policy.d.ts.map +0 -1
- package/dist/src/retry-policy.js.map +0 -1
- package/dist/src/run-manager.d.ts.map +0 -1
- package/dist/src/run-manager.js.map +0 -1
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js.map +0 -1
- package/dist/src/utils/output-format.d.ts.map +0 -1
- package/dist/src/utils/output-format.js.map +0 -1
- package/dist/src/utils/shell-security.d.ts.map +0 -1
- package/dist/src/utils/shell-security.js.map +0 -1
- package/dist/src/workflow-persistence.d.ts.map +0 -1
- package/dist/src/workflow-persistence.js.map +0 -1
package/dist/src/types.d.ts
CHANGED
package/dist/src/types.js
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NEVER_RETRYABLE = void 0;
|
|
4
|
-
exports.NEVER_RETRYABLE = ['CANCELLED', 'CONFIG_INVALID'];
|
|
5
|
-
//# sourceMappingURL=types.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.NEVER_RETRYABLE=void 0;exports.NEVER_RETRYABLE=["CANCELLED","CONFIG_INVALID"];
|
|
@@ -15,4 +15,4 @@ export declare function buildJsonOutputSuffix(schema?: JsonSchema, strict?: bool
|
|
|
15
15
|
export declare function extractJson(text: string): string;
|
|
16
16
|
export declare function validateJsonSchema(value: unknown, schema: JsonSchema): Promise<void>;
|
|
17
17
|
export declare function toOpenAIStrictSchema(schema: JsonSchema): JsonSchema;
|
|
18
|
-
|
|
18
|
+
|
|
@@ -1,53 +1,8 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.WORKFLOW_SIGNAL_KEY = void 0;
|
|
37
|
-
exports.buildWorkflowPreamble = buildWorkflowPreamble;
|
|
38
|
-
exports.detectWorkflowSignal = detectWorkflowSignal;
|
|
39
|
-
exports.buildJsonOutputSuffix = buildJsonOutputSuffix;
|
|
40
|
-
exports.extractJson = extractJson;
|
|
41
|
-
exports.validateJsonSchema = validateJsonSchema;
|
|
42
|
-
exports.toOpenAIStrictSchema = toOpenAIStrictSchema;
|
|
43
|
-
const node_crypto_1 = require("node:crypto");
|
|
44
|
-
exports.WORKFLOW_SIGNAL_KEY = 'workflow_signal';
|
|
45
|
-
function buildWorkflowPreamble(ctx) {
|
|
46
|
-
return `<crewx.workflow>
|
|
1
|
+
"use strict";var y=exports&&exports.__createBinding||(Object.create?(function(n,e,r,t){if(t===void 0)t=r;var o=Object.getOwnPropertyDescriptor(e,r);if(!o||("get"in o?!e.__esModule:o.writable||o.configurable)){o={enumerable:true,get:function(){return e[r]}}}Object.defineProperty(n,t,o)}):(function(n,e,r,t){if(t===void 0)t=r;n[t]=e[r]}));var _=exports&&exports.__setModuleDefault||(Object.create?(function(n,e){Object.defineProperty(n,"default",{enumerable:true,value:e})}):function(n,e){n["default"]=e});var v=exports&&exports.__importStar||(function(){var n=function(e){n=Object.getOwnPropertyNames||function(r){var t=[];for(var o in r)if(Object.prototype.hasOwnProperty.call(r,o))t[t.length]=o;return t};return n(e)};return function(e){if(e&&e.__esModule)return e;var r={};if(e!=null){for(var t=n(e),o=0;o<t.length;o++)if(t[o]!=="default")y(r,e,t[o])}_(r,e);return r}})();Object.defineProperty(exports,"__esModule",{value:true});exports.WORKFLOW_SIGNAL_KEY=void 0;exports.buildWorkflowPreamble=j;exports.detectWorkflowSignal=E;exports.buildJsonOutputSuffix=P;exports.extractJson=O;exports.validateJsonSchema=W;exports.toOpenAIStrictSchema=S;const N=require("node:crypto");exports.WORKFLOW_SIGNAL_KEY="workflow_signal";function j(n){return`<crewx.workflow>
|
|
47
2
|
## Execution Context
|
|
48
|
-
You are running headless as node "${
|
|
3
|
+
You are running headless as node "${n.nodeId}" of workflow "${n.workflowId}" (run ${n.execId}).
|
|
49
4
|
- No human is watching this session. NEVER ask clarifying questions or wait for
|
|
50
|
-
confirmation
|
|
5
|
+
confirmation \u2014 state your assumptions and proceed, or report failure.
|
|
51
6
|
- Your output is consumed verbatim by downstream nodes. Output the result only;
|
|
52
7
|
skip greetings, progress notes, and meta commentary.
|
|
53
8
|
- If the task cannot be completed (broken precondition, missing data, failed
|
|
@@ -57,167 +12,18 @@ You are running headless as node "${ctx.nodeId}" of workflow "${ctx.workflowId}"
|
|
|
57
12
|
The engine will halt the workflow at this node and record the reason.
|
|
58
13
|
</crewx.workflow>
|
|
59
14
|
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) &&
|
|
67
|
-
parsed[exports.WORKFLOW_SIGNAL_KEY] === 'fail') {
|
|
68
|
-
const reason = parsed['reason'];
|
|
69
|
-
return { signal: 'fail', ...(typeof reason === 'string' && reason ? { reason } : {}) };
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
};
|
|
73
|
-
try {
|
|
74
|
-
const signal = toSignal(JSON.parse(extractJson(output)));
|
|
75
|
-
if (signal)
|
|
76
|
-
return signal;
|
|
77
|
-
}
|
|
78
|
-
catch { }
|
|
79
|
-
const inline = output.match(new RegExp(`\\{[^{}]*"${exports.WORKFLOW_SIGNAL_KEY}"\\s*:\\s*"fail"[^{}]*\\}`));
|
|
80
|
-
if (inline) {
|
|
81
|
-
try {
|
|
82
|
-
return toSignal(JSON.parse(inline[0]));
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
return { signal: 'fail' };
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
function buildJsonOutputSuffix(schema, strict = false) {
|
|
91
|
-
const finalSchema = strict && schema ? toOpenAIStrictSchema(schema) : schema;
|
|
92
|
-
const schemaStr = finalSchema ? `JSON Schema:\n${JSON.stringify(finalSchema, null, 2)}\n` : '';
|
|
93
|
-
return `\n\n<crewx.workflow>
|
|
94
|
-
## ⚠️ Output Format (read first — drives branch evaluation)
|
|
15
|
+
`}function E(n){if(!n.includes(`"${exports.WORKFLOW_SIGNAL_KEY}"`))return null;const e=t=>{if(typeof t==="object"&&t!==null&&!Array.isArray(t)&&t[exports.WORKFLOW_SIGNAL_KEY]==="fail"){const o=t["reason"];return{signal:"fail",...typeof o==="string"&&o?{reason:o}:{}}}return null};try{const t=e(JSON.parse(O(n)));if(t)return t}catch{}const r=n.match(new RegExp(`\\{[^{}]*"${exports.WORKFLOW_SIGNAL_KEY}"\\s*:\\s*"fail"[^{}]*\\}`));if(r){try{return e(JSON.parse(r[0]))}catch{return{signal:"fail"}}}return null}function P(n,e=false){const r=e&&n?S(n):n;const t=r?`JSON Schema:
|
|
16
|
+
${JSON.stringify(r,null,2)}
|
|
17
|
+
`:"";return`
|
|
18
|
+
|
|
19
|
+
<crewx.workflow>
|
|
20
|
+
## \u26A0\uFE0F Output Format (read first \u2014 drives branch evaluation)
|
|
95
21
|
|
|
96
22
|
**The first character of your output MUST be \`{\`. The last character MUST be \`}\`.**
|
|
97
23
|
No other text is permitted (no explanations, greetings, progress notes, or analysis remarks).
|
|
98
24
|
**NEVER use markdown code fences (\`\`\`json ... \`\`\`).** Do not output even a single backtick.
|
|
99
|
-
Branch evaluation calls \`JSON.parse(state.<output>)\` directly
|
|
25
|
+
Branch evaluation calls \`JSON.parse(state.<output>)\` directly \u2014
|
|
100
26
|
even one non-JSON character at start or end will halt the workflow.
|
|
101
27
|
|
|
102
|
-
${
|
|
103
|
-
</crewx.workflow
|
|
104
|
-
}
|
|
105
|
-
function extractJson(text) {
|
|
106
|
-
let trimmed = text.trim();
|
|
107
|
-
const fenceMatch = trimmed.match(/^```(?:json|JSON)?\s*\n?([\s\S]*?)\n?```\s*$/);
|
|
108
|
-
if (fenceMatch && fenceMatch[1] !== undefined) {
|
|
109
|
-
trimmed = fenceMatch[1].trim();
|
|
110
|
-
}
|
|
111
|
-
const collectSpans = (s, open, close) => {
|
|
112
|
-
const spans = [];
|
|
113
|
-
let inString = false;
|
|
114
|
-
let escape = false;
|
|
115
|
-
let depth = 0;
|
|
116
|
-
let spanStart = -1;
|
|
117
|
-
for (let i = 0; i < s.length; i++) {
|
|
118
|
-
const ch = s[i];
|
|
119
|
-
if (escape) {
|
|
120
|
-
escape = false;
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (inString) {
|
|
124
|
-
if (ch === '\\') {
|
|
125
|
-
escape = true;
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
if (ch === '"') {
|
|
129
|
-
inString = false;
|
|
130
|
-
}
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
if (ch === '"') {
|
|
134
|
-
inString = true;
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
if (ch === open) {
|
|
138
|
-
if (depth === 0)
|
|
139
|
-
spanStart = i;
|
|
140
|
-
depth++;
|
|
141
|
-
}
|
|
142
|
-
else if (ch === close) {
|
|
143
|
-
if (depth > 0) {
|
|
144
|
-
depth--;
|
|
145
|
-
if (depth === 0 && spanStart !== -1) {
|
|
146
|
-
spans.push({ text: s.slice(spanStart, i + 1), start: spanStart, end: i });
|
|
147
|
-
spanStart = -1;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return spans;
|
|
153
|
-
};
|
|
154
|
-
const objSpans = collectSpans(trimmed, '{', '}');
|
|
155
|
-
const arrSpans = collectSpans(trimmed, '[', ']');
|
|
156
|
-
const candidates = [...objSpans, ...arrSpans].sort((a, b) => b.end - a.end);
|
|
157
|
-
for (const candidate of candidates) {
|
|
158
|
-
try {
|
|
159
|
-
JSON.parse(candidate.text);
|
|
160
|
-
return candidate.text;
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return trimmed;
|
|
166
|
-
}
|
|
167
|
-
async function validateJsonSchema(value, schema) {
|
|
168
|
-
const { registerSchema, validate } = await Promise.resolve().then(() => __importStar(require('@hyperjump/json-schema/draft-2020-12')));
|
|
169
|
-
const uri = `urn:crewx:schema:${(0, node_crypto_1.randomUUID)()}`;
|
|
170
|
-
registerSchema({ $schema: 'https://json-schema.org/draft/2020-12/schema', ...schema }, uri);
|
|
171
|
-
const result = await validate(uri, value);
|
|
172
|
-
if (!result.valid) {
|
|
173
|
-
const errors = (result.errors ?? [])
|
|
174
|
-
.map((e) => e.instanceLocation)
|
|
175
|
-
.join('; ');
|
|
176
|
-
throw new Error(`Schema validation failed: ${errors || 'unknown error'}`);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
function toOpenAIStrictSchema(schema) {
|
|
180
|
-
return transformStrict(schema);
|
|
181
|
-
}
|
|
182
|
-
const OPENAI_UNSUPPORTED_KEYWORDS = new Set([
|
|
183
|
-
'default', 'format', 'pattern', 'minLength', 'maxLength',
|
|
184
|
-
'minimum', 'maximum', 'not',
|
|
185
|
-
]);
|
|
186
|
-
function transformStrict(schema) {
|
|
187
|
-
const result = {};
|
|
188
|
-
for (const [key, value] of Object.entries(schema)) {
|
|
189
|
-
if (OPENAI_UNSUPPORTED_KEYWORDS.has(key))
|
|
190
|
-
continue;
|
|
191
|
-
if (key === 'properties' && isRecord(value)) {
|
|
192
|
-
const transformed = {};
|
|
193
|
-
for (const [propKey, propVal] of Object.entries(value)) {
|
|
194
|
-
transformed[propKey] = transformStrict(propVal);
|
|
195
|
-
}
|
|
196
|
-
result['properties'] = transformed;
|
|
197
|
-
result['required'] = Object.keys(transformed);
|
|
198
|
-
result['additionalProperties'] = false;
|
|
199
|
-
}
|
|
200
|
-
else if (key === 'items' && isRecord(value)) {
|
|
201
|
-
result['items'] = transformStrict(value);
|
|
202
|
-
}
|
|
203
|
-
else if (key === 'required') {
|
|
204
|
-
if (!('properties' in schema)) {
|
|
205
|
-
result['required'] = value;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
else if (key === 'additionalProperties') {
|
|
209
|
-
result['additionalProperties'] = false;
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
result[key] = value;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (result['type'] === 'object' && !('additionalProperties' in result)) {
|
|
216
|
-
result['additionalProperties'] = false;
|
|
217
|
-
}
|
|
218
|
-
return result;
|
|
219
|
-
}
|
|
220
|
-
function isRecord(val) {
|
|
221
|
-
return typeof val === 'object' && val !== null && !Array.isArray(val);
|
|
222
|
-
}
|
|
223
|
-
//# sourceMappingURL=output-format.js.map
|
|
28
|
+
${t}Execute the task, then output **exactly one JSON object** matching the schema above. Nothing else.
|
|
29
|
+
</crewx.workflow>`}function O(n){let e=n.trim();const r=e.match(/^```(?:json|JSON)?\s*\n?([\s\S]*?)\n?```\s*$/);if(r&&r[1]!==void 0){e=r[1].trim()}const t=(i,d,b)=>{const w=[];let h=false;let p=false;let l=0;let u=-1;for(let s=0;s<i.length;s++){const f=i[s];if(p){p=false;continue}if(h){if(f==="\\"){p=true;continue}if(f==='"'){h=false}continue}if(f==='"'){h=true;continue}if(f===d){if(l===0)u=s;l++}else if(f===b){if(l>0){l--;if(l===0&&u!==-1){w.push({text:i.slice(u,s+1),start:u,end:s});u=-1}}}}return w};const o=t(e,"{","}");const a=t(e,"[","]");const c=[...o,...a].sort((i,d)=>d.end-i.end);for(const i of c){try{JSON.parse(i.text);return i.text}catch{}}return e}async function W(n,e){const{registerSchema:r,validate:t}=await Promise.resolve().then(()=>v(require("@hyperjump/json-schema/draft-2020-12")));const o=`urn:crewx:schema:${(0,N.randomUUID)()}`;r({$schema:"https://json-schema.org/draft/2020-12/schema",...e},o);const a=await t(o,n);if(!a.valid){const c=(a.errors??[]).map(i=>i.instanceLocation).join("; ");throw new Error(`Schema validation failed: ${c||"unknown error"}`)}}function S(n){return m(n)}const J=new Set(["default","format","pattern","minLength","maxLength","minimum","maximum","not"]);function m(n){const e={};for(const[r,t]of Object.entries(n)){if(J.has(r))continue;if(r==="properties"&&g(t)){const o={};for(const[a,c]of Object.entries(t)){o[a]=m(c)}e["properties"]=o;e["required"]=Object.keys(o);e["additionalProperties"]=false}else if(r==="items"&&g(t)){e["items"]=m(t)}else if(r==="required"){if(!("properties"in n)){e["required"]=t}}else if(r==="additionalProperties"){e["additionalProperties"]=false}else{e[r]=t}}if(e["type"]==="object"&&!("additionalProperties"in e)){e["additionalProperties"]=false}return e}function g(n){return typeof n==="object"&&n!==null&&!Array.isArray(n)}
|
|
@@ -15,4 +15,4 @@ export interface CwdCheck {
|
|
|
15
15
|
}
|
|
16
16
|
export declare function normalizeCwd(cwd: string | undefined, projectRoot: string): CwdCheck;
|
|
17
17
|
export declare function buildShellEnv(nodeEnv: Record<string, string> | undefined, parentEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
18
|
-
|
|
18
|
+
|
|
@@ -1,138 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.DANGEROUS_ENV_KEYS = exports.INLINE_CODE_INTERPRETERS = exports.SHELL_DENYLIST = exports.SKILL_NAME_RE = void 0;
|
|
37
|
-
exports.validateShellCommand = validateShellCommand;
|
|
38
|
-
exports.validateEnvKeys = validateEnvKeys;
|
|
39
|
-
exports.normalizeCwd = normalizeCwd;
|
|
40
|
-
exports.buildShellEnv = buildShellEnv;
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const fs = __importStar(require("fs"));
|
|
43
|
-
exports.SKILL_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
44
|
-
exports.SHELL_DENYLIST = new Set([
|
|
45
|
-
'bash', 'sh', 'zsh', 'dash', 'fish',
|
|
46
|
-
'cmd', 'cmd.exe', 'powershell', 'powershell.exe', 'pwsh', 'pwsh.exe',
|
|
47
|
-
]);
|
|
48
|
-
exports.INLINE_CODE_INTERPRETERS = new Set([
|
|
49
|
-
'python', 'python3', 'node', 'nodejs', 'deno', 'perl', 'ruby', 'php',
|
|
50
|
-
]);
|
|
51
|
-
const INLINE_CODE_FLAGS = new Set(['-c', '-e', '--eval', '--exec']);
|
|
52
|
-
exports.DANGEROUS_ENV_KEYS = new Set([
|
|
53
|
-
'LD_PRELOAD', 'LD_LIBRARY_PATH', 'LD_AUDIT',
|
|
54
|
-
'DYLD_INSERT_LIBRARIES', 'DYLD_LIBRARY_PATH', 'DYLD_FRAMEWORK_PATH',
|
|
55
|
-
'NODE_OPTIONS',
|
|
56
|
-
]);
|
|
57
|
-
function baseName(cmd) {
|
|
58
|
-
return path.basename(cmd).toLowerCase();
|
|
59
|
-
}
|
|
60
|
-
function validateShellCommand(command) {
|
|
61
|
-
if (!Array.isArray(command)) {
|
|
62
|
-
return { ok: false, error: 'shell_task.command must be an array of strings (argv), not a string' };
|
|
63
|
-
}
|
|
64
|
-
if (command.length === 0) {
|
|
65
|
-
return { ok: false, error: 'shell_task.command must not be empty' };
|
|
66
|
-
}
|
|
67
|
-
if (!command.every((c) => typeof c === 'string')) {
|
|
68
|
-
return { ok: false, error: 'shell_task.command must contain only strings' };
|
|
69
|
-
}
|
|
70
|
-
const bin = baseName(command[0]);
|
|
71
|
-
const binNoExt = bin.replace(/\.exe$/, '');
|
|
72
|
-
if (exports.SHELL_DENYLIST.has(bin) || exports.SHELL_DENYLIST.has(binNoExt)) {
|
|
73
|
-
return { ok: false, error: `shell_task.command[0] "${command[0]}" is a blocked shell interpreter` };
|
|
74
|
-
}
|
|
75
|
-
if (exports.INLINE_CODE_INTERPRETERS.has(binNoExt)) {
|
|
76
|
-
const hasInlineFlag = command
|
|
77
|
-
.slice(1)
|
|
78
|
-
.some((arg) => INLINE_CODE_FLAGS.has(String(arg)));
|
|
79
|
-
if (hasInlineFlag) {
|
|
80
|
-
return {
|
|
81
|
-
ok: false,
|
|
82
|
-
error: `shell_task.command "${binNoExt} ${command[1]}" uses an inline-code flag (escape vector blocked)`,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return { ok: true };
|
|
87
|
-
}
|
|
88
|
-
function validateEnvKeys(env) {
|
|
89
|
-
if (!env)
|
|
90
|
-
return { ok: true };
|
|
91
|
-
for (const key of Object.keys(env)) {
|
|
92
|
-
if (exports.DANGEROUS_ENV_KEYS.has(key)) {
|
|
93
|
-
return { ok: false, error: `shell_task.env key "${key}" is not allowed` };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return { ok: true };
|
|
97
|
-
}
|
|
98
|
-
function normalizeCwd(cwd, projectRoot) {
|
|
99
|
-
let root;
|
|
100
|
-
try {
|
|
101
|
-
root = fs.realpathSync(projectRoot);
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
return { ok: false, error: `project root "${projectRoot}" is not accessible: ${error.message}` };
|
|
105
|
-
}
|
|
106
|
-
if (cwd === undefined || cwd === '') {
|
|
107
|
-
return { ok: true, resolved: root };
|
|
108
|
-
}
|
|
109
|
-
const candidate = path.resolve(root, cwd);
|
|
110
|
-
let resolved;
|
|
111
|
-
try {
|
|
112
|
-
resolved = fs.realpathSync(candidate);
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
return { ok: false, error: `cwd "${cwd}" is not accessible: ${error.message}` };
|
|
116
|
-
}
|
|
117
|
-
if (resolved !== root && !resolved.startsWith(root + path.sep)) {
|
|
118
|
-
return { ok: false, error: `cwd "${cwd}" resolves outside the project root` };
|
|
119
|
-
}
|
|
120
|
-
return { ok: true, resolved };
|
|
121
|
-
}
|
|
122
|
-
function buildShellEnv(nodeEnv, parentEnv = process.env) {
|
|
123
|
-
const allowlist = process.platform === 'win32'
|
|
124
|
-
? ['PATH', 'Path', 'SystemRoot', 'COMSPEC', 'TEMP', 'TMP']
|
|
125
|
-
: ['PATH', 'HOME', 'LANG', 'TMPDIR'];
|
|
126
|
-
const env = {};
|
|
127
|
-
for (const key of allowlist) {
|
|
128
|
-
if (parentEnv[key] !== undefined)
|
|
129
|
-
env[key] = parentEnv[key];
|
|
130
|
-
}
|
|
131
|
-
if (nodeEnv) {
|
|
132
|
-
for (const [key, value] of Object.entries(nodeEnv)) {
|
|
133
|
-
env[key] = value;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return env;
|
|
137
|
-
}
|
|
138
|
-
//# sourceMappingURL=shell-security.js.map
|
|
1
|
+
"use strict";var u=exports&&exports.__createBinding||(Object.create?(function(e,r,n,s){if(s===void 0)s=n;var t=Object.getOwnPropertyDescriptor(r,n);if(!t||("get"in t?!r.__esModule:t.writable||t.configurable)){t={enumerable:true,get:function(){return r[n]}}}Object.defineProperty(e,s,t)}):(function(e,r,n,s){if(s===void 0)s=n;e[s]=r[n]}));var f=exports&&exports.__setModuleDefault||(Object.create?(function(e,r){Object.defineProperty(e,"default",{enumerable:true,value:r})}):function(e,r){e["default"]=r});var l=exports&&exports.__importStar||(function(){var e=function(r){e=Object.getOwnPropertyNames||function(n){var s=[];for(var t in n)if(Object.prototype.hasOwnProperty.call(n,t))s[s.length]=t;return s};return e(r)};return function(r){if(r&&r.__esModule)return r;var n={};if(r!=null){for(var s=e(r),t=0;t<s.length;t++)if(s[t]!=="default")u(n,r,s[t])}f(n,r);return n}})();Object.defineProperty(exports,"__esModule",{value:true});exports.DANGEROUS_ENV_KEYS=exports.INLINE_CODE_INTERPRETERS=exports.SHELL_DENYLIST=exports.SKILL_NAME_RE=void 0;exports.validateShellCommand=E;exports.validateEnvKeys=h;exports.normalizeCwd=d;exports.buildShellEnv=S;const a=l(require("path"));const i=l(require("fs"));exports.SKILL_NAME_RE=/^[a-z0-9][a-z0-9-]*$/;exports.SHELL_DENYLIST=new Set(["bash","sh","zsh","dash","fish","cmd","cmd.exe","powershell","powershell.exe","pwsh","pwsh.exe"]);exports.INLINE_CODE_INTERPRETERS=new Set(["python","python3","node","nodejs","deno","perl","ruby","php"]);const c=new Set(["-c","-e","--eval","--exec"]);exports.DANGEROUS_ENV_KEYS=new Set(["LD_PRELOAD","LD_LIBRARY_PATH","LD_AUDIT","DYLD_INSERT_LIBRARIES","DYLD_LIBRARY_PATH","DYLD_FRAMEWORK_PATH","NODE_OPTIONS"]);function _(e){return a.basename(e).toLowerCase()}function E(e){if(!Array.isArray(e)){return{ok:false,error:"shell_task.command must be an array of strings (argv), not a string"}}if(e.length===0){return{ok:false,error:"shell_task.command must not be empty"}}if(!e.every(s=>typeof s==="string")){return{ok:false,error:"shell_task.command must contain only strings"}}const r=_(e[0]);const n=r.replace(/\.exe$/,"");if(exports.SHELL_DENYLIST.has(r)||exports.SHELL_DENYLIST.has(n)){return{ok:false,error:`shell_task.command[0] "${e[0]}" is a blocked shell interpreter`}}if(exports.INLINE_CODE_INTERPRETERS.has(n)){const s=e.slice(1).some(t=>c.has(String(t)));if(s){return{ok:false,error:`shell_task.command "${n} ${e[1]}" uses an inline-code flag (escape vector blocked)`}}}return{ok:true}}function h(e){if(!e)return{ok:true};for(const r of Object.keys(e)){if(exports.DANGEROUS_ENV_KEYS.has(r)){return{ok:false,error:`shell_task.env key "${r}" is not allowed`}}}return{ok:true}}function d(e,r){let n;try{n=i.realpathSync(r)}catch(o){return{ok:false,error:`project root "${r}" is not accessible: ${o.message}`}}if(e===void 0||e===""){return{ok:true,resolved:n}}const s=a.resolve(n,e);let t;try{t=i.realpathSync(s)}catch(o){return{ok:false,error:`cwd "${e}" is not accessible: ${o.message}`}}if(t!==n&&!t.startsWith(n+a.sep)){return{ok:false,error:`cwd "${e}" resolves outside the project root`}}return{ok:true,resolved:t}}function S(e,r=process.env){const n=process.platform==="win32"?["PATH","Path","SystemRoot","COMSPEC","TEMP","TMP"]:["PATH","HOME","LANG","TMPDIR"];const s={};for(const t of n){if(r[t]!==void 0)s[t]=r[t]}if(e){for(const[t,o]of Object.entries(e)){s[t]=o}}return s}
|
|
@@ -45,4 +45,4 @@ export interface WorkflowPersistenceProjectionOptions {
|
|
|
45
45
|
export type WorkflowPersistenceProjection = (run: RunExecution) => WorkflowPersistenceProjectionResult;
|
|
46
46
|
export declare function createWorkflowPersistenceProjection(options: WorkflowPersistenceProjectionOptions): WorkflowPersistenceProjection;
|
|
47
47
|
export declare function previewWorkflowPersistenceProjection(options: WorkflowPersistenceProjectionPreviewOptions, run: RunExecution): WorkflowPersistenceProjectionPreview;
|
|
48
|
-
|
|
48
|
+
|
|
@@ -1,224 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createWorkflowPersistenceProjection = createWorkflowPersistenceProjection;
|
|
4
|
-
exports.previewWorkflowPersistenceProjection = previewWorkflowPersistenceProjection;
|
|
5
|
-
const card_state_js_1 = require("./card-state.js");
|
|
6
|
-
const parent_task_sync_js_1 = require("./parent-task-sync.js");
|
|
7
|
-
function errorMessage(error) {
|
|
8
|
-
return error instanceof Error ? error.message : String(error);
|
|
9
|
-
}
|
|
10
|
-
function asJsonObject(state) {
|
|
11
|
-
return state;
|
|
12
|
-
}
|
|
13
|
-
function canonicalJson(value) {
|
|
14
|
-
if (Array.isArray(value))
|
|
15
|
-
return `[${value.map((item) => canonicalJson(item)).join(',')}]`;
|
|
16
|
-
if (value !== null && typeof value === 'object') {
|
|
17
|
-
const record = value;
|
|
18
|
-
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(',')}}`;
|
|
19
|
-
}
|
|
20
|
-
return JSON.stringify(value) ?? 'null';
|
|
21
|
-
}
|
|
22
|
-
function sameJson(left, right) {
|
|
23
|
-
return canonicalJson(left) === canonicalJson(right);
|
|
24
|
-
}
|
|
25
|
-
function buildResult(runId, parent) {
|
|
26
|
-
return {
|
|
27
|
-
runId,
|
|
28
|
-
changedParentTaskIds: [...parent.changedParentTaskIds],
|
|
29
|
-
projectedAuditInstanceIds: [],
|
|
30
|
-
errors: [],
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
function createWorkflowPersistenceProjection(options) {
|
|
34
|
-
const parentSinkOptions = {
|
|
35
|
-
taskRepo: options.taskRepo,
|
|
36
|
-
workspaceId: options.workspaceId,
|
|
37
|
-
...(options.parentKinds ? { parentKinds: options.parentKinds } : {}),
|
|
38
|
-
};
|
|
39
|
-
const parentSink = (0, parent_task_sync_js_1.createWorkflowParentPersistSink)(parentSinkOptions);
|
|
40
|
-
const warn = options.warn ?? ((message) => console.warn(message));
|
|
41
|
-
return (run) => {
|
|
42
|
-
let parent;
|
|
43
|
-
try {
|
|
44
|
-
parent = parentSink(run);
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
const message = `workflow persistence parent projection failed for ${run.id}: ${errorMessage(error)}`;
|
|
48
|
-
warn(message);
|
|
49
|
-
return {
|
|
50
|
-
runId: run.id,
|
|
51
|
-
changedParentTaskIds: [],
|
|
52
|
-
projectedAuditInstanceIds: [],
|
|
53
|
-
errors: [message],
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
const result = buildResult(run.id, parent);
|
|
57
|
-
const addError = (stage, error) => {
|
|
58
|
-
const message = `workflow persistence ${stage} failed for ${run.id}: ${errorMessage(error)}`;
|
|
59
|
-
result.errors.push(message);
|
|
60
|
-
warn(message);
|
|
61
|
-
};
|
|
62
|
-
const instanceIds = [...new Set(parent.linkedAuditInstanceIds)];
|
|
63
|
-
if (instanceIds.length > 0) {
|
|
64
|
-
let spec;
|
|
65
|
-
try {
|
|
66
|
-
spec = options.resolveWorkflowSpec(run);
|
|
67
|
-
if (!spec)
|
|
68
|
-
throw new Error(`workflow spec not found for ${run.workflow_id}`);
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
addError('spec resolution', error);
|
|
72
|
-
}
|
|
73
|
-
if (spec) {
|
|
74
|
-
let state = null;
|
|
75
|
-
try {
|
|
76
|
-
state = (0, card_state_js_1.buildWorkflowApprovalState)(run, spec);
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
addError('audit state build', error);
|
|
80
|
-
}
|
|
81
|
-
if (state) {
|
|
82
|
-
const updatedAt = Date.parse(run.updated_at);
|
|
83
|
-
if (!Number.isSafeInteger(updatedAt) || updatedAt < 0) {
|
|
84
|
-
addError('audit snapshot', new Error(`invalid run updated_at: ${run.updated_at}`));
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
let store = options.uiInstanceStore;
|
|
88
|
-
if (!store && options.getUiInstanceStore) {
|
|
89
|
-
try {
|
|
90
|
-
store = options.getUiInstanceStore();
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
addError('audit store creation', error);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (!store) {
|
|
97
|
-
addError('audit snapshot', new Error('no UiInstanceStore was provided'));
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
for (const instanceId of instanceIds) {
|
|
101
|
-
try {
|
|
102
|
-
const instance = store.get(instanceId);
|
|
103
|
-
const domainRunId = instance?.domainRef?.workflowRunId;
|
|
104
|
-
if (!instance
|
|
105
|
-
|| instance.workspaceId !== options.workspaceId
|
|
106
|
-
|| domainRunId !== run.id) {
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
const beforeState = canonicalJson(instance.state);
|
|
110
|
-
const beforeUpdatedAt = instance.updatedAt;
|
|
111
|
-
const updatedInstance = store.updateAuditSnapshot({
|
|
112
|
-
instanceId,
|
|
113
|
-
workspaceId: options.workspaceId,
|
|
114
|
-
updatedAt,
|
|
115
|
-
state: asJsonObject(state),
|
|
116
|
-
});
|
|
117
|
-
if (updatedInstance
|
|
118
|
-
&& (canonicalJson(updatedInstance.state) !== beforeState
|
|
119
|
-
|| updatedInstance.updatedAt !== beforeUpdatedAt)) {
|
|
120
|
-
result.projectedAuditInstanceIds.push(instanceId);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
addError(`audit snapshot ${instanceId}`, error);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if ((result.changedParentTaskIds.length > 0 || result.projectedAuditInstanceIds.length > 0)
|
|
133
|
-
&& options.onChanged) {
|
|
134
|
-
try {
|
|
135
|
-
options.onChanged(result);
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
addError('change callback', error);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return result;
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
function previewWorkflowPersistenceProjection(options, run) {
|
|
145
|
-
const parent = (0, parent_task_sync_js_1.previewWorkflowParentRepair)({
|
|
146
|
-
taskRepo: options.taskRepo,
|
|
147
|
-
run,
|
|
148
|
-
workspaceId: options.workspaceId,
|
|
149
|
-
...(options.parentKinds ? { parentKinds: options.parentKinds } : {}),
|
|
150
|
-
});
|
|
151
|
-
const result = {
|
|
152
|
-
runId: run.id,
|
|
153
|
-
runStatus: parent.runStatus,
|
|
154
|
-
parentChanges: [...parent.changes],
|
|
155
|
-
auditSnapshotChanges: [],
|
|
156
|
-
errors: [],
|
|
157
|
-
};
|
|
158
|
-
const addError = (stage, error) => {
|
|
159
|
-
result.errors.push(`workflow persistence preview ${stage} failed for ${run.id}: ${errorMessage(error)}`);
|
|
160
|
-
};
|
|
161
|
-
const instanceIds = [...new Set(parent.linkedAuditInstanceIds)];
|
|
162
|
-
if (instanceIds.length === 0)
|
|
163
|
-
return result;
|
|
164
|
-
let spec;
|
|
165
|
-
try {
|
|
166
|
-
spec = options.resolveWorkflowSpec(run);
|
|
167
|
-
if (!spec)
|
|
168
|
-
throw new Error(`workflow spec not found for ${run.workflow_id}`);
|
|
169
|
-
}
|
|
170
|
-
catch (error) {
|
|
171
|
-
addError('spec resolution', error);
|
|
172
|
-
}
|
|
173
|
-
if (!spec)
|
|
174
|
-
return result;
|
|
175
|
-
let state;
|
|
176
|
-
try {
|
|
177
|
-
state = (0, card_state_js_1.buildWorkflowApprovalState)(run, spec);
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
addError('audit state build', error);
|
|
181
|
-
return result;
|
|
182
|
-
}
|
|
183
|
-
const updatedAt = Date.parse(run.updated_at);
|
|
184
|
-
if (!Number.isSafeInteger(updatedAt) || updatedAt < 0) {
|
|
185
|
-
addError('audit snapshot', new Error(`invalid run updated_at: ${run.updated_at}`));
|
|
186
|
-
return result;
|
|
187
|
-
}
|
|
188
|
-
let store = options.uiInstanceStore;
|
|
189
|
-
if (!store && options.getUiInstanceStore) {
|
|
190
|
-
try {
|
|
191
|
-
store = options.getUiInstanceStore();
|
|
192
|
-
}
|
|
193
|
-
catch (error) {
|
|
194
|
-
addError('audit store creation', error);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
if (!store) {
|
|
198
|
-
addError('audit snapshot', new Error('no UiInstanceStore was provided'));
|
|
199
|
-
return result;
|
|
200
|
-
}
|
|
201
|
-
for (const instanceId of instanceIds) {
|
|
202
|
-
try {
|
|
203
|
-
const instance = store.get(instanceId);
|
|
204
|
-
if (!instance
|
|
205
|
-
|| instance.workspaceId !== options.workspaceId
|
|
206
|
-
|| instance.domainRef.workflowRunId !== run.id) {
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
if (!sameJson(instance.state, state)) {
|
|
210
|
-
result.auditSnapshotChanges.push({
|
|
211
|
-
instanceId,
|
|
212
|
-
before: instance.state,
|
|
213
|
-
after: state,
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
catch (error) {
|
|
218
|
-
addError(`audit snapshot ${instanceId}`, error);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
void updatedAt;
|
|
222
|
-
return result;
|
|
223
|
-
}
|
|
224
|
-
//# sourceMappingURL=workflow-persistence.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.createWorkflowPersistenceProjection=b;exports.previewWorkflowPersistenceProjection=m;const g=require("./card-state.js");const S=require("./parent-task-sync.js");function h(e){return e instanceof Error?e.message:String(e)}function _(e){return e}function w(e){if(Array.isArray(e))return`[${e.map(r=>w(r)).join(",")}]`;if(e!==null&&typeof e==="object"){const r=e;return`{${Object.keys(r).sort().map(i=>`${JSON.stringify(i)}:${w(r[i])}`).join(",")}}`}return JSON.stringify(e)??"null"}function A(e,r){return w(e)===w(r)}function P(e,r){return{runId:e,changedParentTaskIds:[...r.changedParentTaskIds],projectedAuditInstanceIds:[],errors:[]}}function b(e){const r={taskRepo:e.taskRepo,workspaceId:e.workspaceId,...e.parentKinds?{parentKinds:e.parentKinds}:{}};const i=(0,S.createWorkflowParentPersistSink)(r);const o=e.warn??(n=>console.warn(n));return n=>{let u;try{u=i(n)}catch(s){const t=`workflow persistence parent projection failed for ${n.id}: ${h(s)}`;o(t);return{runId:n.id,changedParentTaskIds:[],projectedAuditInstanceIds:[],errors:[t]}}const c=P(n.id,u);const d=(s,t)=>{const a=`workflow persistence ${s} failed for ${n.id}: ${h(t)}`;c.errors.push(a);o(a)};const p=[...new Set(u.linkedAuditInstanceIds)];if(p.length>0){let s;try{s=e.resolveWorkflowSpec(n);if(!s)throw new Error(`workflow spec not found for ${n.workflow_id}`)}catch(t){d("spec resolution",t)}if(s){let t=null;try{t=(0,g.buildWorkflowApprovalState)(n,s)}catch(a){d("audit state build",a)}if(t){const a=Date.parse(n.updated_at);if(!Number.isSafeInteger(a)||a<0){d("audit snapshot",new Error(`invalid run updated_at: ${n.updated_at}`))}else{let I=e.uiInstanceStore;if(!I&&e.getUiInstanceStore){try{I=e.getUiInstanceStore()}catch(l){d("audit store creation",l)}}if(!I){d("audit snapshot",new Error("no UiInstanceStore was provided"))}else{for(const l of p){try{const f=I.get(l);const $=f?.domainRef?.workflowRunId;if(!f||f.workspaceId!==e.workspaceId||$!==n.id){continue}const j=w(f.state);const y=f.updatedAt;const k=I.updateAuditSnapshot({instanceId:l,workspaceId:e.workspaceId,updatedAt:a,state:_(t)});if(k&&(w(k.state)!==j||k.updatedAt!==y)){c.projectedAuditInstanceIds.push(l)}}catch(f){d(`audit snapshot ${l}`,f)}}}}}}}if((c.changedParentTaskIds.length>0||c.projectedAuditInstanceIds.length>0)&&e.onChanged){try{e.onChanged(c)}catch(s){d("change callback",s)}}return c}}function m(e,r){const i=(0,S.previewWorkflowParentRepair)({taskRepo:e.taskRepo,run:r,workspaceId:e.workspaceId,...e.parentKinds?{parentKinds:e.parentKinds}:{}});const o={runId:r.id,runStatus:i.runStatus,parentChanges:[...i.changes],auditSnapshotChanges:[],errors:[]};const n=(t,a)=>{o.errors.push(`workflow persistence preview ${t} failed for ${r.id}: ${h(a)}`)};const u=[...new Set(i.linkedAuditInstanceIds)];if(u.length===0)return o;let c;try{c=e.resolveWorkflowSpec(r);if(!c)throw new Error(`workflow spec not found for ${r.workflow_id}`)}catch(t){n("spec resolution",t)}if(!c)return o;let d;try{d=(0,g.buildWorkflowApprovalState)(r,c)}catch(t){n("audit state build",t);return o}const p=Date.parse(r.updated_at);if(!Number.isSafeInteger(p)||p<0){n("audit snapshot",new Error(`invalid run updated_at: ${r.updated_at}`));return o}let s=e.uiInstanceStore;if(!s&&e.getUiInstanceStore){try{s=e.getUiInstanceStore()}catch(t){n("audit store creation",t)}}if(!s){n("audit snapshot",new Error("no UiInstanceStore was provided"));return o}for(const t of u){try{const a=s.get(t);if(!a||a.workspaceId!==e.workspaceId||a.domainRef.workflowRunId!==r.id){continue}if(!A(a.state,d)){o.auditSnapshotChanges.push({instanceId:t,before:a.state,after:d})}}catch(a){n(`audit snapshot ${t}`,a)}}void p;return o}
|