@openclaw/lobster 2026.8.1-beta.2 → 2026.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +132 -119
- package/node_modules/typebox/build/format/date.d.mts +1 -1
- package/node_modules/typebox/build/format/date.mjs +1 -1
- package/node_modules/typebox/build/format/date_time.d.mts +2 -2
- package/node_modules/typebox/build/format/date_time.mjs +3 -3
- package/node_modules/typebox/build/format/email.d.mts +1 -1
- package/node_modules/typebox/build/format/email.mjs +2 -2
- package/node_modules/typebox/build/format/hostname.mjs +2 -10
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_email.mjs +3 -3
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
- package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
- package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
- package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
- package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
- package/node_modules/typebox/build/format/idna/index.mjs +2 -0
- package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
- package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
- package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
- package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
- package/node_modules/typebox/build/format/ipv4.mjs +2 -32
- package/node_modules/typebox/build/format/ipv6.mjs +2 -61
- package/node_modules/typebox/build/format/iri.d.mts +2 -2
- package/node_modules/typebox/build/format/iri.mjs +26 -8
- package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
- package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
- package/node_modules/typebox/build/format/regex.d.mts +1 -2
- package/node_modules/typebox/build/format/regex.mjs +2 -6
- package/node_modules/typebox/build/format/time.d.mts +2 -2
- package/node_modules/typebox/build/format/time.mjs +19 -14
- package/node_modules/typebox/build/format/uri.d.mts +1 -1
- package/node_modules/typebox/build/format/uri.mjs +3 -130
- package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
- package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
- package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
- package/node_modules/typebox/build/format/uri_template.mjs +4 -5
- package/node_modules/typebox/build/format/url.d.mts +3 -3
- package/node_modules/typebox/build/format/url.mjs +4 -5
- package/node_modules/typebox/build/guard/emit.d.mts +3 -1
- package/node_modules/typebox/build/guard/emit.mjs +12 -5
- package/node_modules/typebox/build/guard/guard.d.mts +8 -2
- package/node_modules/typebox/build/guard/guard.mjs +25 -4
- package/node_modules/typebox/build/guard/string.d.mts +2 -2
- package/node_modules/typebox/build/guard/string.mjs +7 -7
- package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
- package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
- package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
- package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
- package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
- package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
- package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
- package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
- package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
- package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
- package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
- package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
- package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
- package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
- package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
- package/node_modules/typebox/build/schema/types/index.mjs +0 -2
- package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
- package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
- package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
- package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
- package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
- package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
- package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
- package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
- package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
- package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
- package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
- package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
- package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
- package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
- package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
- package/node_modules/typebox/build/type/script/parser.mjs +27 -23
- package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
- package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
- package/node_modules/typebox/package.json +27 -27
- package/node_modules/typebox/readme.md +79 -82
- package/package.json +5 -5
- package/node_modules/typebox/build/format/_idna.d.mts +0 -2
- package/node_modules/typebox/build/format/_idna.mjs +0 -246
- package/node_modules/typebox/build/format/_puny.d.mts +0 -1
- package/node_modules/typebox/build/format/_puny.mjs +0 -77
- package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
- package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
- package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
- package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { stat } from "node:fs/promises";
|
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { Readable, Writable } from "node:stream";
|
|
9
9
|
import { toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
10
|
+
import { isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
|
|
10
11
|
//#region extensions/lobster/src/lobster-runner.ts
|
|
11
12
|
const workflowExts = /* @__PURE__ */ new Set([
|
|
12
13
|
".lobster",
|
|
@@ -14,19 +15,13 @@ const workflowExts = /* @__PURE__ */ new Set([
|
|
|
14
15
|
".yml",
|
|
15
16
|
".json"
|
|
16
17
|
]);
|
|
17
|
-
function normalizeForCwdSandbox(p) {
|
|
18
|
-
const normalized = path.normalize(p);
|
|
19
|
-
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
20
|
-
}
|
|
21
18
|
function resolveLobsterCwd(cwdRaw) {
|
|
22
19
|
if (typeof cwdRaw !== "string" || !cwdRaw.trim()) return process.cwd();
|
|
23
20
|
const cwd = cwdRaw.trim();
|
|
24
21
|
if (path.isAbsolute(cwd)) throw new Error("cwd must be a relative path");
|
|
25
22
|
const base = process.cwd();
|
|
26
23
|
const resolved = path.resolve(base, cwd);
|
|
27
|
-
|
|
28
|
-
if (rel === "" || rel === ".") return resolved;
|
|
29
|
-
if (rel.startsWith("..") || path.isAbsolute(rel)) throw new Error("cwd must stay within the gateway working directory");
|
|
24
|
+
if (!isPathInside(base, resolved)) throw new Error("cwd must stay within the gateway working directory");
|
|
30
25
|
return resolved;
|
|
31
26
|
}
|
|
32
27
|
function createLimitedSink(maxBytes, label) {
|
|
@@ -40,10 +35,10 @@ function createLimitedSink(maxBytes, label) {
|
|
|
40
35
|
callback();
|
|
41
36
|
} });
|
|
42
37
|
}
|
|
43
|
-
function normalizeEnvelope(envelope) {
|
|
38
|
+
function normalizeEnvelope(envelope, maxStdoutBytes) {
|
|
44
39
|
if (!envelope.ok) throw new Error(envelope.error?.message ?? "lobster runtime failed");
|
|
45
40
|
if (envelope.status === "needs_input") throw new Error("Lobster input requests are not supported by the OpenClaw Lobster tool yet");
|
|
46
|
-
|
|
41
|
+
const normalized = {
|
|
47
42
|
ok: true,
|
|
48
43
|
status: envelope.status ?? "ok",
|
|
49
44
|
output: Array.isArray(envelope.output) ? envelope.output : [],
|
|
@@ -55,6 +50,8 @@ function normalizeEnvelope(envelope) {
|
|
|
55
50
|
...envelope.requiresApproval.approvalId ? { approvalId: envelope.requiresApproval.approvalId } : {}
|
|
56
51
|
} : null
|
|
57
52
|
};
|
|
53
|
+
if (Buffer.byteLength(JSON.stringify(normalized, null, 2), "utf8") > maxStdoutBytes) throw new Error("lobster runtime result exceeded maxStdoutBytes");
|
|
54
|
+
return normalized;
|
|
58
55
|
}
|
|
59
56
|
function isMissingPathError(error) {
|
|
60
57
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
@@ -117,6 +114,7 @@ function createEmbeddedLobsterRunner(options) {
|
|
|
117
114
|
const runtime = await runtimePromise;
|
|
118
115
|
return await withTimeout(params.timeoutMs, async (signal) => {
|
|
119
116
|
const ctx = createEmbeddedToolContext(params, signal);
|
|
117
|
+
let envelope;
|
|
120
118
|
if (params.action === "run") {
|
|
121
119
|
const pipeline = params.pipeline?.trim() ?? "";
|
|
122
120
|
if (!pipeline) throw new Error("pipeline required");
|
|
@@ -129,27 +127,28 @@ function createEmbeddedLobsterRunner(options) {
|
|
|
129
127
|
} catch {
|
|
130
128
|
throw new Error("run --args-json must be valid JSON");
|
|
131
129
|
}
|
|
132
|
-
|
|
130
|
+
envelope = await runtime.runToolRequest({
|
|
133
131
|
filePath,
|
|
134
132
|
args,
|
|
135
133
|
ctx
|
|
136
|
-
})
|
|
137
|
-
}
|
|
138
|
-
return normalizeEnvelope(await runtime.runToolRequest({
|
|
134
|
+
});
|
|
135
|
+
} else envelope = await runtime.runToolRequest({
|
|
139
136
|
pipeline,
|
|
140
137
|
ctx
|
|
141
|
-
})
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
const token = params.token?.trim() ?? "";
|
|
141
|
+
const approvalId = params.approvalId?.trim() ?? "";
|
|
142
|
+
if (!token && !approvalId) throw new Error("token or approvalId required");
|
|
143
|
+
if (typeof params.approve !== "boolean") throw new Error("approve required");
|
|
144
|
+
envelope = await runtime.resumeToolRequest({
|
|
145
|
+
...token ? { token } : {},
|
|
146
|
+
...approvalId ? { approvalId } : {},
|
|
147
|
+
approved: params.approve,
|
|
148
|
+
ctx
|
|
149
|
+
});
|
|
142
150
|
}
|
|
143
|
-
|
|
144
|
-
const approvalId = params.approvalId?.trim() ?? "";
|
|
145
|
-
if (!token && !approvalId) throw new Error("token or approvalId required");
|
|
146
|
-
if (typeof params.approve !== "boolean") throw new Error("approve required");
|
|
147
|
-
return normalizeEnvelope(await runtime.resumeToolRequest({
|
|
148
|
-
...token ? { token } : {},
|
|
149
|
-
...approvalId ? { approvalId } : {},
|
|
150
|
-
approved: params.approve,
|
|
151
|
-
ctx
|
|
152
|
-
}));
|
|
151
|
+
return normalizeEnvelope(envelope, Math.max(1024, params.maxStdoutBytes));
|
|
153
152
|
});
|
|
154
153
|
} };
|
|
155
154
|
}
|
|
@@ -157,29 +156,25 @@ function createEmbeddedLobsterRunner(options) {
|
|
|
157
156
|
//#region extensions/lobster/src/lobster-taskflow.ts
|
|
158
157
|
function toJsonLike(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
159
158
|
if (value === null) return null;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
jsonObject[key] = toJsonLike(entry, seen);
|
|
177
|
-
}
|
|
178
|
-
seen.delete(value);
|
|
179
|
-
return jsonObject;
|
|
180
|
-
}
|
|
159
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : String(value);
|
|
160
|
+
if (typeof value === "bigint") return value.toString();
|
|
161
|
+
if (typeof value === "boolean" || typeof value === "string") return value;
|
|
162
|
+
if (typeof value !== "object") return null;
|
|
163
|
+
if (value instanceof Date) return value.toISOString();
|
|
164
|
+
if (seen.has(value)) return "[Circular]";
|
|
165
|
+
seen.add(value);
|
|
166
|
+
if (Array.isArray(value)) {
|
|
167
|
+
const jsonArray = value.map((item) => toJsonLike(item, seen));
|
|
168
|
+
seen.delete(value);
|
|
169
|
+
return jsonArray;
|
|
170
|
+
}
|
|
171
|
+
const jsonObject = {};
|
|
172
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
173
|
+
if (entry === void 0 || typeof entry === "function" || typeof entry === "symbol") continue;
|
|
174
|
+
jsonObject[key] = toJsonLike(entry, seen);
|
|
181
175
|
}
|
|
182
|
-
|
|
176
|
+
seen.delete(value);
|
|
177
|
+
return jsonObject;
|
|
183
178
|
}
|
|
184
179
|
function buildApprovalWaitState(envelope) {
|
|
185
180
|
const approval = envelope.requiresApproval;
|
|
@@ -191,40 +186,51 @@ function buildApprovalWaitState(envelope) {
|
|
|
191
186
|
...approval?.approvalId ? { approvalId: approval.approvalId } : {}
|
|
192
187
|
};
|
|
193
188
|
}
|
|
194
|
-
function
|
|
195
|
-
const { taskFlow, flow, envelope, waitingStep } = params;
|
|
196
|
-
const flowMutation = {
|
|
197
|
-
flowId: flow.flowId,
|
|
198
|
-
expectedRevision: flow.revision
|
|
199
|
-
};
|
|
200
|
-
if (!envelope.ok) return taskFlow.fail(flowMutation);
|
|
201
|
-
if (envelope.status === "needs_approval") return taskFlow.setWaiting({
|
|
202
|
-
...flowMutation,
|
|
203
|
-
currentStep: waitingStep,
|
|
204
|
-
waitJson: buildApprovalWaitState(envelope)
|
|
205
|
-
});
|
|
206
|
-
return taskFlow.finish(flowMutation);
|
|
207
|
-
}
|
|
208
|
-
async function executeManagedLobsterFlow(params, flow, failureFlowId = flow.flowId) {
|
|
189
|
+
async function executeManagedLobsterFlow(params, flow) {
|
|
209
190
|
try {
|
|
210
191
|
const envelope = await params.runner.run(params.runnerParams);
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
192
|
+
if (envelope.ok && envelope.status === "cancelled") try {
|
|
193
|
+
const mutation = await params.taskFlow.cancel({
|
|
194
|
+
flowId: flow.flowId,
|
|
195
|
+
cfg: params.config
|
|
196
|
+
});
|
|
197
|
+
return mutation.cancelled ? {
|
|
198
|
+
ok: true,
|
|
199
|
+
envelope,
|
|
200
|
+
flow,
|
|
201
|
+
mutation
|
|
202
|
+
} : {
|
|
203
|
+
ok: false,
|
|
204
|
+
flow,
|
|
205
|
+
mutation,
|
|
206
|
+
error: /* @__PURE__ */ new Error(`TaskFlow cancellation failed: ${mutation.reason ?? "unknown"}`)
|
|
207
|
+
};
|
|
208
|
+
} catch (error) {
|
|
209
|
+
return {
|
|
210
|
+
ok: false,
|
|
211
|
+
flow,
|
|
212
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const flowMutation = {
|
|
216
|
+
flowId: flow.flowId,
|
|
217
|
+
expectedRevision: flow.revision
|
|
218
|
+
};
|
|
217
219
|
if (!envelope.ok) return {
|
|
218
220
|
ok: false,
|
|
219
221
|
flow,
|
|
220
|
-
mutation,
|
|
222
|
+
mutation: params.taskFlow.fail(flowMutation),
|
|
221
223
|
error: new Error(envelope.error.message)
|
|
222
224
|
};
|
|
223
225
|
return {
|
|
224
226
|
ok: true,
|
|
225
227
|
envelope,
|
|
226
228
|
flow,
|
|
227
|
-
mutation
|
|
229
|
+
mutation: envelope.status === "needs_approval" ? params.taskFlow.setWaiting({
|
|
230
|
+
...flowMutation,
|
|
231
|
+
currentStep: params.waitingStep ?? "await_lobster_approval",
|
|
232
|
+
waitJson: buildApprovalWaitState(envelope)
|
|
233
|
+
}) : params.taskFlow.finish(flowMutation)
|
|
228
234
|
};
|
|
229
235
|
} catch (error) {
|
|
230
236
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
@@ -233,7 +239,7 @@ async function executeManagedLobsterFlow(params, flow, failureFlowId = flow.flow
|
|
|
233
239
|
ok: false,
|
|
234
240
|
flow,
|
|
235
241
|
mutation: params.taskFlow.fail({
|
|
236
|
-
flowId:
|
|
242
|
+
flowId: flow.flowId,
|
|
237
243
|
expectedRevision: flow.revision
|
|
238
244
|
}),
|
|
239
245
|
error: err
|
|
@@ -273,7 +279,7 @@ async function resumeManagedLobsterFlow(params) {
|
|
|
273
279
|
mutation: resumed,
|
|
274
280
|
error: /* @__PURE__ */ new Error(`TaskFlow resume failed: ${resumed.code}`)
|
|
275
281
|
};
|
|
276
|
-
return await executeManagedLobsterFlow(params, resumed.flow
|
|
282
|
+
return await executeManagedLobsterFlow(params, resumed.flow);
|
|
277
283
|
}
|
|
278
284
|
//#endregion
|
|
279
285
|
//#region extensions/lobster/src/lobster-tool.ts
|
|
@@ -305,28 +311,29 @@ function parseOptionalFlowStateJson(value) {
|
|
|
305
311
|
function isEmptyJsonObject(value) {
|
|
306
312
|
return value !== void 0 && value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0;
|
|
307
313
|
}
|
|
308
|
-
function
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
|
|
314
|
+
function parseManagedFlowParams(action, params, runnerParams) {
|
|
315
|
+
if (action === "run") {
|
|
316
|
+
const controllerId = readOptionalTrimmedString(params.flowControllerId, "flowControllerId");
|
|
317
|
+
const goal = readOptionalTrimmedString(params.flowGoal, "flowGoal");
|
|
318
|
+
const currentStep = readOptionalTrimmedString(params.flowCurrentStep, "flowCurrentStep");
|
|
319
|
+
const waitingStep = readOptionalTrimmedString(params.flowWaitingStep, "flowWaitingStep");
|
|
320
|
+
const stateJson = parseOptionalFlowStateJson(params.flowStateJson);
|
|
321
|
+
const resumeFlowId = readOptionalTrimmedString(params.flowId, "flowId");
|
|
322
|
+
const resumeRevision = readOptionalNumber(params.flowExpectedRevision, "flowExpectedRevision");
|
|
323
|
+
const stateJsonSignalsRunMode = stateJson !== void 0 && !isEmptyJsonObject(stateJson);
|
|
324
|
+
if (resumeFlowId !== void 0 || resumeRevision !== void 0 && resumeRevision !== 0) throw new Error("run action does not accept flowId or flowExpectedRevision");
|
|
325
|
+
if (controllerId === void 0 && goal === void 0 && currentStep === void 0 && waitingStep === void 0 && !stateJsonSignalsRunMode) return null;
|
|
326
|
+
if (!controllerId) throw new Error("flowControllerId required when using managed TaskFlow run mode");
|
|
327
|
+
if (!goal) throw new Error("flowGoal required when using managed TaskFlow run mode");
|
|
328
|
+
return {
|
|
329
|
+
action,
|
|
330
|
+
controllerId,
|
|
331
|
+
goal,
|
|
332
|
+
...currentStep ? { currentStep } : {},
|
|
333
|
+
...waitingStep ? { waitingStep } : {},
|
|
334
|
+
...stateJson !== void 0 ? { stateJson } : {}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
330
337
|
const flowId = readOptionalTrimmedString(params.flowId, "flowId");
|
|
331
338
|
const expectedRevision = readOptionalNumber(params.flowExpectedRevision, "flowExpectedRevision");
|
|
332
339
|
const currentStep = readOptionalTrimmedString(params.flowCurrentStep, "flowCurrentStep");
|
|
@@ -342,13 +349,21 @@ function parseResumeFlowParams(params) {
|
|
|
342
349
|
if (!(flowId !== void 0 || expectedRevision !== void 0 && expectedRevision !== 0 || currentStep !== void 0 || waitingStep !== void 0)) return null;
|
|
343
350
|
if (!flowId) throw new Error("flowId required when using managed TaskFlow resume mode");
|
|
344
351
|
if (expectedRevision === void 0) throw new Error("flowExpectedRevision required when using managed TaskFlow resume mode");
|
|
345
|
-
|
|
352
|
+
const credentialParams = token ? { token: runnerParams.token ?? token } : approvalId ? { approvalId: runnerParams.approvalId ?? approvalId } : null;
|
|
353
|
+
if (!credentialParams) throw new Error("token or approvalId required when using managed TaskFlow resume mode");
|
|
346
354
|
if (approve === void 0) throw new Error("approve required when using managed TaskFlow resume mode");
|
|
347
355
|
return {
|
|
356
|
+
action,
|
|
348
357
|
flowId,
|
|
349
358
|
expectedRevision,
|
|
350
359
|
...currentStep ? { currentStep } : {},
|
|
351
|
-
...waitingStep ? { waitingStep } : {}
|
|
360
|
+
...waitingStep ? { waitingStep } : {},
|
|
361
|
+
runnerParams: {
|
|
362
|
+
...runnerParams,
|
|
363
|
+
...credentialParams,
|
|
364
|
+
action,
|
|
365
|
+
approve
|
|
366
|
+
}
|
|
352
367
|
};
|
|
353
368
|
}
|
|
354
369
|
function resolveManagedFlowToolResult(result) {
|
|
@@ -407,30 +422,28 @@ function createLobsterTool(api, options) {
|
|
|
407
422
|
maxStdoutBytes
|
|
408
423
|
};
|
|
409
424
|
const taskFlow = options?.taskFlow;
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}));
|
|
433
|
-
}
|
|
425
|
+
const flowParams = parseManagedFlowParams(action, params, runnerParams);
|
|
426
|
+
if (flowParams?.action === "run") return resolveManagedFlowToolResult(await runManagedLobsterFlow({
|
|
427
|
+
taskFlow: requireTaskFlowRuntime(taskFlow, "run"),
|
|
428
|
+
config: api.config,
|
|
429
|
+
runner,
|
|
430
|
+
runnerParams,
|
|
431
|
+
controllerId: flowParams.controllerId,
|
|
432
|
+
goal: flowParams.goal,
|
|
433
|
+
...flowParams.stateJson !== void 0 ? { stateJson: flowParams.stateJson } : {},
|
|
434
|
+
...flowParams.currentStep ? { currentStep: flowParams.currentStep } : {},
|
|
435
|
+
...flowParams.waitingStep ? { waitingStep: flowParams.waitingStep } : {}
|
|
436
|
+
}));
|
|
437
|
+
if (flowParams?.action === "resume") return resolveManagedFlowToolResult(await resumeManagedLobsterFlow({
|
|
438
|
+
taskFlow: requireTaskFlowRuntime(taskFlow, "resume"),
|
|
439
|
+
config: api.config,
|
|
440
|
+
runner,
|
|
441
|
+
runnerParams: flowParams.runnerParams,
|
|
442
|
+
flowId: flowParams.flowId,
|
|
443
|
+
expectedRevision: flowParams.expectedRevision,
|
|
444
|
+
...flowParams.currentStep ? { currentStep: flowParams.currentStep } : {},
|
|
445
|
+
...flowParams.waitingStep ? { waitingStep: flowParams.waitingStep } : {}
|
|
446
|
+
}));
|
|
434
447
|
const envelope = await runner.run(runnerParams);
|
|
435
448
|
if (!envelope.ok) throw new Error(envelope.error.message);
|
|
436
449
|
return jsonResult(envelope);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Returns true if the value is a ISO8601 DateTime string
|
|
3
|
-
* @
|
|
3
|
+
* @specification https://datatracker.ietf.org/doc/html/rfc3339
|
|
4
4
|
* @example `2020-12-12T20:20:40+00:00`
|
|
5
5
|
*/
|
|
6
|
-
export declare function IsDateTime(value: string
|
|
6
|
+
export declare function IsDateTime(value: string): boolean;
|
|
@@ -2,10 +2,10 @@ import { IsDate } from './date.mjs';
|
|
|
2
2
|
import { IsTime } from './time.mjs';
|
|
3
3
|
/**
|
|
4
4
|
* Returns true if the value is a ISO8601 DateTime string
|
|
5
|
-
* @
|
|
5
|
+
* @specification https://datatracker.ietf.org/doc/html/rfc3339
|
|
6
6
|
* @example `2020-12-12T20:20:40+00:00`
|
|
7
7
|
*/
|
|
8
|
-
export function IsDateTime(value
|
|
8
|
+
export function IsDateTime(value) {
|
|
9
9
|
const dateTime = value.split(/T/i);
|
|
10
|
-
return dateTime.length === 2 && IsDate(dateTime[0]) && IsTime(dateTime[1]
|
|
10
|
+
return dateTime.length === 2 && IsDate(dateTime[0]) && IsTime(dateTime[1]);
|
|
11
11
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const Email = /^(
|
|
1
|
+
const Email = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[^"\\]|\\.)*")@(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*|\[(?:IPv6:[a-f0-9:]+|(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})\])$/i;
|
|
2
2
|
/**
|
|
3
3
|
* Returns true if the value is an Email
|
|
4
|
-
* @specification
|
|
4
|
+
* @specification https://datatracker.ietf.org/doc/html/rfc5322
|
|
5
5
|
*/
|
|
6
6
|
export function IsEmail(value) {
|
|
7
7
|
return Email.test(value);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as Idna from './
|
|
1
|
+
import * as Idna from './idna/index.mjs';
|
|
2
2
|
/**
|
|
3
3
|
* Returns true if the value is a valid hostname.
|
|
4
4
|
* @specification https://tools.ietf.org/html/rfc1123
|
|
@@ -6,13 +6,5 @@ import * as Idna from './_idna.mjs';
|
|
|
6
6
|
* @specification https://tools.ietf.org/html/rfc5892
|
|
7
7
|
*/
|
|
8
8
|
export function IsHostname(value) {
|
|
9
|
-
|
|
10
|
-
return false;
|
|
11
|
-
if (value.charCodeAt(value.length - 1) === 46)
|
|
12
|
-
return false;
|
|
13
|
-
for (const label of value.split('.')) {
|
|
14
|
-
if (!Idna.IsLabel(label))
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
return true;
|
|
9
|
+
return Idna.IsHostname(value);
|
|
18
10
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const IdnEmail = /^(
|
|
1
|
+
const IdnEmail = /^(?:[A-Za-z0-9!#$%&'*+\/=?^_`{|}~\u{0080}-\u{10FFFF}-]+(?:\.[A-Za-z0-9!#$%&'*+\/=?^_`{|}~\u{0080}-\u{10FFFF}-]+)*|"(?:[^"\\]|\\.)*")@[\p{L}\p{N}](?:[\p{L}\p{N}-]{0,62})(?<!-)(?:\.[\p{L}\p{N}](?:[\p{L}\p{N}-]{0,62})(?<!-))*$/iu;
|
|
2
2
|
/**
|
|
3
3
|
* Returns true if the value is an IdnEmail
|
|
4
|
-
* @specification
|
|
4
|
+
* @specification https://datatracker.ietf.org/doc/html/rfc4952
|
|
5
5
|
*/
|
|
6
6
|
export function IsIdnEmail(value) {
|
|
7
|
-
return IdnEmail.test(value);
|
|
7
|
+
return IdnEmail.test(value.normalize('NFC'));
|
|
8
8
|
}
|
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
* @specification https://tools.ietf.org/html/rfc3490
|
|
4
4
|
* @specification https://tools.ietf.org/html/rfc5891
|
|
5
5
|
* @specification https://tools.ietf.org/html/rfc5892
|
|
6
|
+
* @specification https://tools.ietf.org/html/rfc5893
|
|
6
7
|
*/
|
|
7
8
|
export declare function IsIdnHostname(value: string): boolean;
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Idna from './idna/index.mjs';
|
|
2
2
|
/**
|
|
3
3
|
* Returns true if the value is a valid internationalized (IDN) hostname.
|
|
4
4
|
* @specification https://tools.ietf.org/html/rfc3490
|
|
5
5
|
* @specification https://tools.ietf.org/html/rfc5891
|
|
6
6
|
* @specification https://tools.ietf.org/html/rfc5892
|
|
7
|
+
* @specification https://tools.ietf.org/html/rfc5893
|
|
7
8
|
*/
|
|
8
9
|
export function IsIdnHostname(value) {
|
|
9
|
-
|
|
10
|
-
return false;
|
|
11
|
-
const canonical = value.normalize('NFC').replace(/[\u002E\u3002\uFF0E\uFF61]/g, '.');
|
|
12
|
-
if (canonical.length > 253)
|
|
13
|
-
return false;
|
|
14
|
-
for (const label of canonical.split('.')) {
|
|
15
|
-
if (!IsIdnLabel(label))
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
return true;
|
|
10
|
+
return Idna.IsIdnHostname(value);
|
|
19
11
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// deno-fmt-ignore-file
|
|
2
|
+
import * as FormatPuny from './puny.mjs';
|
|
3
|
+
import * as Pattern from '../pattern/pattern.mjs';
|
|
4
|
+
// ------------------------------------------------------------------
|
|
5
|
+
// LOCAL REGEX: Allowed Bidi classes per direction (RFC 5893)
|
|
6
|
+
// ------------------------------------------------------------------
|
|
7
|
+
const RE_RTL_ALLOWED = /^(?:R|AL|AN|EN|ES|CS|ET|ON|BN|NSM)$/;
|
|
8
|
+
const RE_LTR_ALLOWED = /^(?:L|EN|ES|CS|ET|ON|BN|NSM)$/;
|
|
9
|
+
const RE_RTL_CLASSES = /^(?:R|AL|AN)$/;
|
|
10
|
+
// ------------------------------------------------------------------
|
|
11
|
+
// HasBidiChars
|
|
12
|
+
//
|
|
13
|
+
// Decodes a punycode label to its Unicode form (if it is one) and
|
|
14
|
+
// checks whether the result is an RTL label per RFC 5893 §1.4.
|
|
15
|
+
// ------------------------------------------------------------------
|
|
16
|
+
export function HasBidiChars(value) {
|
|
17
|
+
if (FormatPuny.IsAcePrefixed(value)) {
|
|
18
|
+
try {
|
|
19
|
+
return HasRightToLeftCharacters(FormatPuny.Decode(value.slice(4).toLowerCase()));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return HasRightToLeftCharacters(value);
|
|
26
|
+
}
|
|
27
|
+
// ------------------------------------------------------------------
|
|
28
|
+
// GetBidiClass
|
|
29
|
+
// ------------------------------------------------------------------
|
|
30
|
+
function GetBidiClass(codePoint) {
|
|
31
|
+
const char = String.fromCodePoint(codePoint);
|
|
32
|
+
return (Pattern.RE_EUROPEAN_NUMBER.test(char) ? 'EN' :
|
|
33
|
+
Pattern.RE_ARABIC_INDIC_DIGIT.test(char) ? 'AN' :
|
|
34
|
+
// Pattern.RE_EUROPEAN_SEPARATOR.test(char) ? 'ES' : // (no-spec-coverage)
|
|
35
|
+
// Pattern.RE_COMMON_SEPARATOR.test(char) ? 'CS' : // (no-spec-coverage)
|
|
36
|
+
Pattern.RE_MARK_NONSPACING.test(char) ? 'NSM' :
|
|
37
|
+
Pattern.RE_SCRIPT_HEBREW.test(char) ? 'R' :
|
|
38
|
+
Pattern.RE_SCRIPT_ARABIC_LETTER.test(char) ? 'AL' :
|
|
39
|
+
Pattern.RE_LETTER.test(char) ? 'L' :
|
|
40
|
+
'ON');
|
|
41
|
+
}
|
|
42
|
+
// ------------------------------------------------------------------
|
|
43
|
+
// HasRightToLeftCharacters
|
|
44
|
+
//
|
|
45
|
+
// Per RFC 5893 §1.4: "An RTL label is a label that contains at least
|
|
46
|
+
// one character of type R, AL, or AN." Used to determine whether a
|
|
47
|
+
// domain name is a "Bidi domain name" (RFC 5893 §1.4), in which case
|
|
48
|
+
// the Bidi Rule applies to every label in the domain.
|
|
49
|
+
// ------------------------------------------------------------------
|
|
50
|
+
export function HasRightToLeftCharacters(value) {
|
|
51
|
+
for (const ch of value)
|
|
52
|
+
if (RE_RTL_CLASSES.test(GetBidiClass(ch.codePointAt(0))))
|
|
53
|
+
return true;
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
// ------------------------------------------------------------------
|
|
57
|
+
// SatisfiesBidiRule
|
|
58
|
+
// ------------------------------------------------------------------
|
|
59
|
+
export function SatisfiesBidiRule(value) {
|
|
60
|
+
let isRtl = false;
|
|
61
|
+
let allowed = RE_LTR_ALLOWED;
|
|
62
|
+
let sawEN = false;
|
|
63
|
+
let sawAN = false;
|
|
64
|
+
let isFirst = true;
|
|
65
|
+
// let lastClass: string | null = null // (no-spec-coverage)
|
|
66
|
+
for (const ch of value) {
|
|
67
|
+
const bidiClass = GetBidiClass(ch.codePointAt(0));
|
|
68
|
+
if (isFirst) {
|
|
69
|
+
// 1. The first character must be a character with Bidi property L, R, or AL.
|
|
70
|
+
if (bidiClass !== 'L' && bidiClass !== 'R' && bidiClass !== 'AL')
|
|
71
|
+
return false;
|
|
72
|
+
isRtl = bidiClass === 'R' || bidiClass === 'AL';
|
|
73
|
+
allowed = isRtl ? RE_RTL_ALLOWED : RE_LTR_ALLOWED;
|
|
74
|
+
isFirst = false;
|
|
75
|
+
}
|
|
76
|
+
// 2 / 5. Only characters in the allowed set for this direction may appear.
|
|
77
|
+
if (!allowed.test(bidiClass))
|
|
78
|
+
return false;
|
|
79
|
+
if (bidiClass === 'EN')
|
|
80
|
+
sawEN = true;
|
|
81
|
+
else if (bidiClass === 'AN')
|
|
82
|
+
sawAN = true;
|
|
83
|
+
// if (bidiClass !== 'NSM') lastClass = bidiClass // (no-spec-coverage)
|
|
84
|
+
}
|
|
85
|
+
if (isRtl && sawEN && sawAN)
|
|
86
|
+
return false; // spec coverage path
|
|
87
|
+
// (no-spec-coverage)
|
|
88
|
+
// if (isRtl) {
|
|
89
|
+
// // 3. The end of the label must be R, AL, EN, or AN (ignoring trailing NSM).
|
|
90
|
+
// // if (lastClass !== 'R' && lastClass !== 'AL' && lastClass !== 'EN' && lastClass !== 'AN') return false
|
|
91
|
+
// // 4. If an EN is present, no AN may be present, and vice versa.
|
|
92
|
+
// if (sawEN && sawAN) return false
|
|
93
|
+
// } else {
|
|
94
|
+
// // 6. The end of the label must be L or EN (ignoring trailing NSM).
|
|
95
|
+
// // if (lastClass !== 'L' && lastClass !== 'EN') return false
|
|
96
|
+
// }
|
|
97
|
+
return true;
|
|
98
|
+
}
|