@oxygen-agent/cli 1.696.2 → 1.717.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/README.md +1 -1
- package/dist/help.js +2 -0
- package/dist/http-client.js +11 -1
- package/dist/index.js +524 -86
- package/dist/transcript.js +2 -2
- package/node_modules/@oxygen/recipe-sdk/dist/index.d.ts +4 -0
- package/node_modules/@oxygen/shared/dist/billing.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/billing.js +7 -6
- package/node_modules/@oxygen/shared/dist/dnc-identities.d.ts +53 -0
- package/node_modules/@oxygen/shared/dist/dnc-identities.js +175 -0
- package/node_modules/@oxygen/shared/dist/file-import.d.ts +36 -1
- package/node_modules/@oxygen/shared/dist/file-import.js +80 -1
- package/node_modules/@oxygen/shared/dist/image-sniff.d.ts +39 -0
- package/node_modules/@oxygen/shared/dist/image-sniff.js +75 -0
- package/node_modules/@oxygen/shared/dist/import-limits.d.ts +28 -0
- package/node_modules/@oxygen/shared/dist/import-limits.js +30 -0
- package/node_modules/@oxygen/shared/dist/index.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/index.js +2 -0
- package/node_modules/@oxygen/shared/dist/mailbox-import.d.ts +10 -4
- package/node_modules/@oxygen/shared/dist/mailbox-import.js +18 -10
- package/node_modules/@oxygen/shared/dist/member-columns.d.ts +64 -0
- package/node_modules/@oxygen/shared/dist/member-columns.js +111 -0
- package/node_modules/@oxygen/shared/dist/microsoft-consent-url.js +1 -1
- package/node_modules/@oxygen/shared/dist/object-storage.d.ts +65 -0
- package/node_modules/@oxygen/shared/dist/object-storage.js +100 -0
- package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +2 -1
- package/node_modules/@oxygen/shared/dist/plan-limits.js +12 -2
- package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +9 -0
- package/node_modules/@oxygen/shared/dist/spend-safety.js +10 -0
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +1 -1
- package/node_modules/@oxygen/shared/package.json +20 -0
- package/node_modules/@oxygen/workflows/dist/graph/lint.js +79 -11
- package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +679 -0
- package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.js +80 -1
- package/node_modules/@oxygen/workflows/dist/graph/remap.js +8 -1
- package/node_modules/@oxygen/workflows/dist/graph/types.d.ts +72 -3
- package/node_modules/@oxygen/workflows/dist/graph/types.js +12 -0
- package/node_modules/@oxygen/workflows/dist/index.d.ts +16 -0
- package/node_modules/@oxygen/workflows/dist/index.js +45 -3
- package/node_modules/@oxygen/workflows/dist/portable.d.ts +43 -0
- package/node_modules/@oxygen/workflows/dist/portable.js +319 -0
- package/node_modules/@oxygen/workflows/dist/usage-estimate.js +18 -4
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// why ./index.ts (the "@oxygen/workflows/graph" entry) does not re-export this
|
|
8
8
|
// module — the editor lints through the API, not in the bundle.
|
|
9
9
|
import { validateFormulaExpression } from "@oxygen/formula";
|
|
10
|
-
import { isWorkflowToolRejected, validateOptionalMaxCredits, validatePureFunctionSource, validateTrigger, } from "../index.js";
|
|
10
|
+
import { isWorkflowToolRejected, lintRecipeManifest, validateOptionalMaxCredits, validatePureFunctionSource, validateTrigger, } from "../index.js";
|
|
11
11
|
import { UNARY_COMPARE_OPS, WORKFLOW_COMPARE_OPS, compileConditionPattern, parseScopePath, SCOPE_PATH_ROOTS, } from "./expression.js";
|
|
12
12
|
import { missingToolParams, unknownToolParams } from "./params.js";
|
|
13
13
|
import { danglingEdges, findIllegalCycles, loopBodyNodeIds, reachableNodeIds } from "./topology.js";
|
|
@@ -254,14 +254,7 @@ node, path, add, scope, options) {
|
|
|
254
254
|
lintApprovalNode(node, path, add, scope);
|
|
255
255
|
return;
|
|
256
256
|
case "code":
|
|
257
|
-
|
|
258
|
-
// they clear the same purity scan; every issue it raises is re-labelled to
|
|
259
|
-
// the v2 code so callers match on one code for "this source is not safe".
|
|
260
|
-
if (typeof node.run_source !== "string") {
|
|
261
|
-
add(`${path}.run_source`, "unsafe_code_source", "Code node run_source is required.");
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
validatePureFunctionSource(node.run_source, `${path}.run_source`, (issuePath, _code, message) => add(issuePath, "unsafe_code_source", message));
|
|
257
|
+
lintCodeNode(node, path, add, scope, options);
|
|
265
258
|
return;
|
|
266
259
|
case "workflow":
|
|
267
260
|
if (!isNonEmptyString(node.workflow_id)) {
|
|
@@ -280,7 +273,67 @@ node, path, add, scope, options) {
|
|
|
280
273
|
return;
|
|
281
274
|
}
|
|
282
275
|
}
|
|
276
|
+
function lintCodeNode(node, path, add, scope, options) {
|
|
277
|
+
const hasSource = typeof node.run_source === "string";
|
|
278
|
+
const hasRecipe = isRecord(node.recipe);
|
|
279
|
+
if (hasSource === hasRecipe) {
|
|
280
|
+
add(path, "ambiguous_code_runtime", "A code node must declare exactly one executable runtime: run_source or recipe.");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (hasSource) {
|
|
284
|
+
// v2 source nodes run through the same sandbox as v1 transform steps, so
|
|
285
|
+
// they clear the same purity scan; every issue it raises is re-labelled to
|
|
286
|
+
// the v2 code so callers match on one code for "this source is not safe".
|
|
287
|
+
validatePureFunctionSource(node.run_source, `${path}.run_source`, (issuePath, _code, message) => add(issuePath, "unsafe_code_source", message));
|
|
288
|
+
validateLegacyContext(node, path, add);
|
|
289
|
+
if (node.configuration !== undefined) {
|
|
290
|
+
add(`${path}.configuration`, "unexpected_recipe_configuration", "Source code nodes cannot declare recipe configuration.");
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
// The graph owns configuration as value refs, which are resolved only at run
|
|
295
|
+
// time. The standalone recipe linter validates concrete JSON values, so lint
|
|
296
|
+
// the executable envelope without its literal configuration and validate the
|
|
297
|
+
// graph binding shape/required keys below instead.
|
|
298
|
+
const { configuration_schema: _configurationSchema, configuration: _configuration, ...recipeEnvelope } = node.recipe;
|
|
299
|
+
const recipeResult = lintRecipeManifest(recipeEnvelope, options);
|
|
300
|
+
for (const issue of recipeResult.issues) {
|
|
301
|
+
const suffix = issue.path === "$" ? "" : issue.path.slice(1);
|
|
302
|
+
add(`${path}.recipe${suffix}`, issue.code, issue.message);
|
|
303
|
+
}
|
|
304
|
+
validateValueRefRecord(node.configuration, `${path}.configuration`, add, scope);
|
|
305
|
+
if (node.legacy_context !== undefined) {
|
|
306
|
+
add(`${path}.legacy_context`, "unexpected_legacy_context", "Durable recipe nodes do not use legacy_context.");
|
|
307
|
+
}
|
|
308
|
+
const rawSchema = node.recipe.configuration_schema;
|
|
309
|
+
if (rawSchema !== undefined && !isRecord(rawSchema)) {
|
|
310
|
+
add(`${path}.recipe.configuration_schema`, "invalid_configuration_schema", "Recipe configuration_schema must be a JSON Schema object.");
|
|
311
|
+
}
|
|
312
|
+
const schema = isRecord(rawSchema)
|
|
313
|
+
? node.recipe.configuration_schema
|
|
314
|
+
: null;
|
|
315
|
+
if (!schema)
|
|
316
|
+
return;
|
|
317
|
+
const configuration = isRecord(node.configuration) ? node.configuration : {};
|
|
318
|
+
const properties = isRecord(schema.properties) ? schema.properties : {};
|
|
319
|
+
const required = Array.isArray(schema.required)
|
|
320
|
+
? schema.required.filter((name) => typeof name === "string")
|
|
321
|
+
: [];
|
|
322
|
+
for (const name of required) {
|
|
323
|
+
if (!Object.hasOwn(configuration, name)) {
|
|
324
|
+
add(`${path}.configuration`, "incomplete_recipe_configuration", `Durable recipe configuration still needs '${name}'.`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (schema.additionalProperties === false) {
|
|
328
|
+
for (const name of Object.keys(configuration)) {
|
|
329
|
+
if (!Object.hasOwn(properties, name)) {
|
|
330
|
+
add(`${path}.configuration.${name}`, "unknown_recipe_configuration", `Durable recipe configuration has no field called '${name}'.`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
283
335
|
function lintToolNode(node, path, add, scope, options) {
|
|
336
|
+
const hasPayloadSource = typeof node.payload_source === "string";
|
|
284
337
|
if (!isNonEmptyString(node.tool)) {
|
|
285
338
|
add(`${path}.tool`, "missing_tool", "Tool node tool id is required.");
|
|
286
339
|
}
|
|
@@ -296,7 +349,7 @@ function lintToolNode(node, path, add, scope, options) {
|
|
|
296
349
|
// refused an unconfigured node while apply accepted the identical manifest, and
|
|
297
350
|
// a CLI-authored one was never checked at all — a guarantee the GUI enforces
|
|
298
351
|
// alone is not a guarantee.
|
|
299
|
-
if (isNonEmptyString(node.tool) && options.resolveToolParamFields) {
|
|
352
|
+
if (!hasPayloadSource && isNonEmptyString(node.tool) && options.resolveToolParamFields) {
|
|
300
353
|
const resolved = options.resolveToolParamFields(node.tool);
|
|
301
354
|
// Array.isArray does not narrow a `readonly T[]` union, so normalize once.
|
|
302
355
|
const bag = resolved == null
|
|
@@ -341,7 +394,7 @@ function lintToolNode(node, path, add, scope, options) {
|
|
|
341
394
|
if (resolveEffect) {
|
|
342
395
|
const canonicalEffect = resolveEffect(node.tool);
|
|
343
396
|
if (canonicalEffect !== null && node.effect !== canonicalEffect) {
|
|
344
|
-
add(`${path}.effect`, "tool_effect_mismatch", `Tool '${node.tool}' has canonical effect '${canonicalEffect}', not '${String(node.effect)}'.`);
|
|
397
|
+
add(`${path}.effect`, "tool_effect_mismatch", `Tool '${node.tool}' has canonical effect '${canonicalEffect}', not '${String(node.effect)}'. Set node.effect to '${canonicalEffect}'.`);
|
|
345
398
|
}
|
|
346
399
|
}
|
|
347
400
|
}
|
|
@@ -353,6 +406,21 @@ function lintToolNode(node, path, add, scope, options) {
|
|
|
353
406
|
}
|
|
354
407
|
validateOptionalMaxCredits(node.max_credits, `${path}.max_credits`, add);
|
|
355
408
|
validateValueRefRecord(node.params, `${path}.params`, add, scope);
|
|
409
|
+
if (hasPayloadSource) {
|
|
410
|
+
validatePureFunctionSource(node.payload_source, `${path}.payload_source`, (issuePath, _code, message) => add(issuePath, "unsafe_payload_source", message));
|
|
411
|
+
if (isRecord(node.params) && Object.keys(node.params).length > 0) {
|
|
412
|
+
add(`${path}.params`, "ambiguous_tool_inputs", "A tool node cannot use mapped params and payload_source at the same time.");
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
else if (node.payload_source !== undefined) {
|
|
416
|
+
add(`${path}.payload_source`, "unsafe_payload_source", "Tool payload_source must be a string.");
|
|
417
|
+
}
|
|
418
|
+
validateLegacyContext(node, path, add);
|
|
419
|
+
}
|
|
420
|
+
function validateLegacyContext(node, path, add) {
|
|
421
|
+
if (node.legacy_context !== undefined && node.legacy_context !== "v1") {
|
|
422
|
+
add(`${path}.legacy_context`, "invalid_legacy_context", "Imported node legacy_context must be 'v1'.");
|
|
423
|
+
}
|
|
356
424
|
}
|
|
357
425
|
function lintSwitchNode(node, path, add, scope) {
|
|
358
426
|
const cases = asArray(node.cases);
|