lua-cli 3.40.0 → 3.42.0-beta.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.
@@ -59,10 +59,11 @@ export declare interface AgentStepOptions {
59
59
  /**
60
60
  * EM-WS3: pin a plugin step's Lua-API proxy (and its key) to ANOTHER agent instead of this workflow's own. Legal only
61
61
  * beside `plugins`. Refused at run time (`target_not_granted`) unless the platform's plugin-target switch is on AND
62
- * this workflow's agent holds a `supervision:act` or `supervision:release` grant on the target.
62
+ * this workflow's agent holds a `supervision:act` or `supervision:release` grant on the target. EM-WS3 × EM-WS2: the
63
+ * id may be `template('${initData.<path>}')`, rendered from the run input at dispatch (a per-run target).
63
64
  */
64
65
  target?: {
65
- agentId: string;
66
+ agentId: string | TemplateBinding;
66
67
  };
67
68
  /**
68
69
  * What this step DOES: `classify` | `extract` | `transform` | `draft` | `research` | `reason` | `code` |
@@ -339,7 +340,7 @@ export declare type LuaWorkflowBuildCode = 'duplicate-step-id' | 'unknown-step-r
339
340
  */
340
341
  | 'workspace-not-declared' | 'workspace-inherit-without-parent-workspace' | 'workspace-inherit-conflict' | 'harness-requires-job-tier' | 'max-turns-requires-job-tier' | 'max-turns-invalid'
341
342
  /** EM-WS3: a step's `plugins` outside the allowlist, repeated, or off the Job tier. */
342
- | 'plugins-invalid' | 'cap-exceeded' | 'chunk-size-invalid' | 'rate-limit-invalid' | 'backoff-invalid' | 'loop-interval-out-of-range' | 'mapping-placement' | 'container-arm-empty'
343
+ | 'plugins-invalid' | 'target-invalid' | 'lua-api-invalid' | 'cap-exceeded' | 'chunk-size-invalid' | 'rate-limit-invalid' | 'backoff-invalid' | 'loop-interval-out-of-range' | 'mapping-placement' | 'container-arm-empty'
343
344
  /**
344
345
  * @deprecated LUA-684 — the builder no longer throws it: an `approval` / `waitForSignal` IS a container arm
345
346
  * (`parallel(['approve', …])`). Where the engine cannot run one — a `loop` body, the step of a `[map, step]`
@@ -488,6 +489,21 @@ export declare interface LuaWorkflowStep<TIn extends ZodType = ZodType, TOut ext
488
489
  workspace?: WorkflowStepWorkspace;
489
490
  jobResources?: WorkflowJobResources;
490
491
  jobTools?: WorkflowJobToolId[];
492
+ /**
493
+ * EM-WS3 × EM-WS2: let this `tier:'job'` step run `lua` (`ctx.exec('lua', [...])`, `` ctx.$`lua push …` ``) against the
494
+ * Lua API through the platform's staging-only proxy, with a short-lived key for ONE agent: this workflow's agent, or
495
+ * `target`. It is the same proxy and the same deny rules as a plugin agent step: deploy, promote, publish,
496
+ * activate, env, chat and runtime calls are refused.
497
+ */
498
+ luaApi?: true;
499
+ /**
500
+ * EM-WS3: pin the `luaApi` proxy (and its key) to ANOTHER agent. The id may be static or
501
+ * `template('${initData.<path>}')`, rendered from the run input at dispatch. The same flag and supervision-grant
502
+ * rules apply as on a plugin agent step.
503
+ */
504
+ target?: {
505
+ agentId: string | TemplateBinding;
506
+ };
491
507
  /** default { maxAttempts: 1 } */
492
508
  retry?: RetryPolicy;
493
509
  /** default 'none'; 'external' ⇒ park on platform-fault reclaim. */
@@ -68,17 +68,125 @@ function workflowJobPluginsProblem(plugins) {
68
68
  }
69
69
  __name(workflowJobPluginsProblem, "workflowJobPluginsProblem");
70
70
  __name2(workflowJobPluginsProblem, "workflowJobPluginsProblem");
71
- function workflowJobTargetProblem(target, plugins) {
71
+ var WORKFLOW_JOB_TARGET_TEMPLATE_RE = /^\$\{\s*initData\.([A-Za-z0-9_.\-[\]]+)\s*\}$/;
72
+ var TARGET_PATH_SEGMENT_RE = /^[A-Za-z0-9_-]+(?:\[(?:0|[1-9]\d*)\])*$/;
73
+ function workflowJobTargetTemplatePath(binding) {
74
+ if (!binding || typeof binding !== "object" || Array.isArray(binding)) return null;
75
+ const keys = Object.keys(binding);
76
+ const tpl = binding.template;
77
+ if (keys.length !== 1 || typeof tpl !== "string" || tpl.length > 512) return null;
78
+ const m = WORKFLOW_JOB_TARGET_TEMPLATE_RE.exec(tpl.trim());
79
+ if (!m) return null;
80
+ const names = m[1].split(".").map((seg) => seg.replace(/\[(?:0|[1-9]\d*)\]/g, ""));
81
+ if (names.some((n2) => n2 === "__proto__" || n2 === "prototype" || n2 === "constructor")) return null;
82
+ return m[1].split(".").every((seg) => TARGET_PATH_SEGMENT_RE.test(seg)) ? m[1] : null;
83
+ }
84
+ __name(workflowJobTargetTemplatePath, "workflowJobTargetTemplatePath");
85
+ __name2(workflowJobTargetTemplatePath, "workflowJobTargetTemplatePath");
86
+ function isWorkflowJobTargetTemplate(target) {
87
+ const agentId = target?.agentId;
88
+ return !!agentId && typeof agentId === "object";
89
+ }
90
+ __name(isWorkflowJobTargetTemplate, "isWorkflowJobTargetTemplate");
91
+ __name2(isWorkflowJobTargetTemplate, "isWorkflowJobTargetTemplate");
92
+ function workflowJobLuaApiProblem(luaApi, nodeType, tier) {
93
+ if (luaApi === void 0) return null;
94
+ if (luaApi !== true) return "`luaApi` must be exactly true";
95
+ if (nodeType !== "code") return "`luaApi` is legal on code steps only (an agent step uses `plugins`)";
96
+ if (tier !== "job") return "`luaApi` requires tier:'job'";
97
+ return null;
98
+ }
99
+ __name(workflowJobLuaApiProblem, "workflowJobLuaApiProblem");
100
+ __name2(workflowJobLuaApiProblem, "workflowJobLuaApiProblem");
101
+ function workflowJobUsesLuaApi(step3) {
102
+ return Array.isArray(step3.plugins) && step3.plugins.length > 0 || step3.kind === "code" && step3.luaApi === true;
103
+ }
104
+ __name(workflowJobUsesLuaApi, "workflowJobUsesLuaApi");
105
+ __name2(workflowJobUsesLuaApi, "workflowJobUsesLuaApi");
106
+ function workflowJobTargetProblem(target, plugins, luaApi) {
72
107
  if (target === void 0) return null;
73
108
  if (!target || typeof target !== "object" || Array.isArray(target)) return "target must be { agentId }";
74
109
  const keys = Object.keys(target);
75
110
  const agentId = target.agentId;
76
- if (keys.length !== 1 || typeof agentId !== "string" || !agentId.trim() || agentId.length > 256) return "target must be exactly { agentId: <non-empty string> }";
77
- if (!Array.isArray(plugins) || plugins.length === 0) return "`target` is legal only beside `plugins`";
111
+ if (keys.length !== 1 || !("agentId" in target)) return "target must be exactly { agentId }";
112
+ if (typeof agentId === "string") {
113
+ if (!agentId.trim() || agentId.length > 256) return "target must be exactly { agentId: <non-empty string> }";
114
+ if (agentId.includes("${")) return "a run-input target is written template('${initData.<path>}'), never a string with ${\u2026}";
115
+ } else if (workflowJobTargetTemplatePath(agentId) === null) {
116
+ return "target.agentId must be a static id or template('${initData.<path>}') \u2014 exactly one initData placeholder, no default";
117
+ }
118
+ const hasPlugins = Array.isArray(plugins) && plugins.length > 0;
119
+ if (!hasPlugins && luaApi !== true) return "`target` is legal only beside `plugins` or `luaApi: true`";
78
120
  return null;
79
121
  }
80
122
  __name(workflowJobTargetProblem, "workflowJobTargetProblem");
81
123
  __name2(workflowJobTargetProblem, "workflowJobTargetProblem");
124
+ function readInitDataPath(root, path) {
125
+ let cur = root;
126
+ for (const seg of path.split(".")) {
127
+ const name = seg.replace(/\[(?:0|[1-9]\d*)\]/g, "");
128
+ const indexes = [
129
+ ...seg.matchAll(/\[(0|[1-9]\d*)\]/g)
130
+ ].map((x) => Number(x[1]));
131
+ if (cur === null || typeof cur !== "object" || !Object.prototype.hasOwnProperty.call(cur, name)) return void 0;
132
+ cur = cur[name];
133
+ for (const i of indexes) {
134
+ if (!Array.isArray(cur) || i >= cur.length) return void 0;
135
+ cur = cur[i];
136
+ }
137
+ }
138
+ return cur;
139
+ }
140
+ __name(readInitDataPath, "readInitDataPath");
141
+ __name2(readInitDataPath, "readInitDataPath");
142
+ function renderWorkflowJobTarget(target, initData) {
143
+ const agentId = target?.agentId;
144
+ if (target === void 0 || target === null || agentId === void 0) return {
145
+ ok: true,
146
+ agentId: void 0,
147
+ templated: false
148
+ };
149
+ if (typeof agentId === "string") {
150
+ if (!agentId.trim() || agentId.includes("${")) return {
151
+ ok: false,
152
+ reason: "invalid",
153
+ message: "target.agentId is invalid"
154
+ };
155
+ return {
156
+ ok: true,
157
+ agentId,
158
+ templated: false
159
+ };
160
+ }
161
+ const path = workflowJobTargetTemplatePath(agentId);
162
+ if (path === null) return {
163
+ ok: false,
164
+ reason: "invalid",
165
+ message: "target.agentId is not a valid initData template"
166
+ };
167
+ const value3 = readInitDataPath(initData, path);
168
+ if (value3 === void 0 || value3 === null) {
169
+ return {
170
+ ok: false,
171
+ reason: "unbound",
172
+ message: `target_unresolved: the run input has no initData.${path}`
173
+ };
174
+ }
175
+ if (typeof value3 !== "string" || !value3.trim() || value3.length > 256 || /\s/.test(value3.trim())) {
176
+ return {
177
+ ok: false,
178
+ reason: "empty",
179
+ message: `target_unresolved: initData.${path} is not a non-empty agent id`
180
+ };
181
+ }
182
+ return {
183
+ ok: true,
184
+ agentId: value3.trim(),
185
+ templated: true
186
+ };
187
+ }
188
+ __name(renderWorkflowJobTarget, "renderWorkflowJobTarget");
189
+ __name2(renderWorkflowJobTarget, "renderWorkflowJobTarget");
82
190
 
83
191
  // src/types/workflow.ts
84
192
  import { zodToJsonSchema } from "zod-to-json-schema";
@@ -244,7 +352,8 @@ var REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST = [
244
352
  "sendWebchatMessage",
245
353
  "sendTeamsMessage",
246
354
  "sendInstagramMessage",
247
- "sendMessengerMessage"
355
+ "sendMessengerMessage",
356
+ "sendSlackMessage"
248
357
  ];
249
358
  function isAllowedReviewableExecuteTool(tool) {
250
359
  return REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST.includes(tool);
@@ -4529,6 +4638,24 @@ var onboardingTemplateSectionSchema = z4.object({
4529
4638
  label: copy(100),
4530
4639
  body: onboardingRichTextSchema
4531
4640
  }).strict();
4641
+ var onboardingInstallScreenSchema = z4.object({
4642
+ title: onboardingHeadingSchema,
4643
+ subtitle: copy(240),
4644
+ ctaLabel: copy(80),
4645
+ ctaHelperText: onboardingRichTextSchema
4646
+ }).strict();
4647
+ var onboardingResultScreenSchema = z4.object({
4648
+ title: onboardingHeadingSchema,
4649
+ subheader: copy(240),
4650
+ inputPlaceholder: copy(120)
4651
+ }).strict();
4652
+ var onboardingConnectScreenSchema = z4.object({
4653
+ title: onboardingHeadingSchema,
4654
+ description: onboardingRichTextSchema,
4655
+ ctaLabel: copy(80),
4656
+ neverLine: copy(120),
4657
+ footnote: copy(240)
4658
+ }).strict();
4532
4659
  var onboardingTemplateContentSchema = z4.object({
4533
4660
  id,
4534
4661
  templateId: copy(160),
@@ -4541,7 +4668,10 @@ var onboardingTemplateContentSchema = z4.object({
4541
4668
  artwork: onboardingArtworkSchema,
4542
4669
  hireButtonLabel: copy(80),
4543
4670
  changeRoleButtonLabel: copy(80),
4544
- nextStepText: onboardingRichTextSchema
4671
+ nextStepText: onboardingRichTextSchema,
4672
+ install: onboardingInstallScreenSchema.optional(),
4673
+ result: onboardingResultScreenSchema.optional(),
4674
+ connect: onboardingConnectScreenSchema.optional()
4545
4675
  }).strict();
4546
4676
  var onboardingUnavailableOutcomeSchema = z4.object({
4547
4677
  id,
@@ -4762,6 +4892,8 @@ function isWebRouteInput(value3) {
4762
4892
  }
4763
4893
  __name(isWebRouteInput, "isWebRouteInput");
4764
4894
  __name3(isWebRouteInput, "isWebRouteInput");
4895
+ var WEB_APP_ENTRY_HTML_MAX_CHARS = 256 * 1024;
4896
+ var WEB_APP_MAX_ASSET_BYTES = 8 * 1024 * 1024;
4765
4897
  var EVIDENCE_SESSION_IDLE_MS = 30 * 6e4;
4766
4898
  var EVIDENCE_MIN_CONVERSATIONS = 20;
4767
4899
  var EVIDENCE_LOW_CONFIDENCE_N = 5;
@@ -5161,6 +5293,17 @@ function sortVerdictReasons(reasons) {
5161
5293
  }
5162
5294
  __name(sortVerdictReasons, "sortVerdictReasons");
5163
5295
  __name3(sortVerdictReasons, "sortVerdictReasons");
5296
+ var ENV_TEMPLATE_SECRET_KEY_RE = /(SECRET|TOKEN|KEY|PASSWORD)$/;
5297
+ function envTemplatePlaceholder(key) {
5298
+ if (ENV_TEMPLATE_SECRET_KEY_RE.test(key)) {
5299
+ throw new Error(`env-template-secret-key: \`${key}\` looks like a secret \u2014 read it with env('${key}') inside execute instead`);
5300
+ }
5301
+ return {
5302
+ __envRef: key
5303
+ };
5304
+ }
5305
+ __name(envTemplatePlaceholder, "envTemplatePlaceholder");
5306
+ __name3(envTemplatePlaceholder, "envTemplatePlaceholder");
5164
5307
 
5165
5308
  // ../workflow-graph/dist/index.mjs
5166
5309
  import { createHash } from "crypto";
@@ -5829,6 +5972,17 @@ function liftRenderedApprover(row, rendered) {
5829
5972
  }
5830
5973
  __name(liftRenderedApprover, "liftRenderedApprover");
5831
5974
  __name4(liftRenderedApprover, "liftRenderedApprover");
5975
+ function approverUsersOf(users) {
5976
+ if (Array.isArray(users)) {
5977
+ if (users.length === 0 || users.length > APPROVER_SPEC_MAX_USERS) return null;
5978
+ return users.every((m) => typeof m === "string" && m.length > 0 && m.length <= 128) ? users : null;
5979
+ }
5980
+ if (typeof users !== "string") return null;
5981
+ const lifted = liftRenderedApprover("users", users);
5982
+ return lifted && "users" in lifted ? lifted.users : null;
5983
+ }
5984
+ __name(approverUsersOf, "approverUsersOf");
5985
+ __name4(approverUsersOf, "approverUsersOf");
5832
5986
  var WORKSPACE_TEMPLATE_EXPR_RE = /^\$\{\s*(?:initData|input)\.([^}]+?)\s*\}$/;
5833
5987
  function workspaceTemplatePath(template22) {
5834
5988
  const key = template22.trim();
@@ -6395,8 +6549,13 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
6395
6549
  }
6396
6550
  const plugins = node.plugins;
6397
6551
  const target = node.target;
6552
+ const luaApi = node.luaApi;
6553
+ if (luaApi !== void 0) {
6554
+ const problem = workflowJobLuaApiProblem(luaApi, node.type === "step" ? "code" : node.type, isJobTier(node) ? "job" : node.tier);
6555
+ if (problem) err("lua-api-invalid", problem, `${path}.luaApi`, id2);
6556
+ }
6398
6557
  if (target !== void 0) {
6399
- const problem = workflowJobTargetProblem(target, plugins);
6558
+ const problem = workflowJobTargetProblem(target, plugins, luaApi);
6400
6559
  if (problem) err("target-invalid", problem, `${path}.target`, id2);
6401
6560
  }
6402
6561
  if (plugins !== void 0) {
@@ -9729,7 +9888,9 @@ function stepNodeOf(s) {
9729
9888
  tier,
9730
9889
  workspace: s.workspace,
9731
9890
  jobResources: s.jobResources,
9732
- jobTools: s.jobTools
9891
+ jobTools: s.jobTools,
9892
+ luaApi: s.luaApi,
9893
+ target: s.target
9733
9894
  });
9734
9895
  }
9735
9896
  __name(stepNodeOf, "stepNodeOf");
@@ -9814,6 +9975,14 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
9814
9975
  const tier = s.tier ?? (s.workspace ? "job" : void 0);
9815
9976
  if (s.workspace && s.tier !== void 0 && s.tier !== "job") throw new LuaWorkflowBuildError("workspace-requires-job-tier", `"${s.id}": a step mounting a workspace must be tier:'job'`);
9816
9977
  if (s.jobTools && tier !== "job") throw new LuaWorkflowBuildError("cap-exceeded", `"${s.id}": jobTools require tier:'job' (job-tools-require-job-tier)`);
9978
+ if (s.luaApi !== void 0) {
9979
+ const problem = workflowJobLuaApiProblem(s.luaApi, "code", tier);
9980
+ if (problem) throw new LuaWorkflowBuildError("lua-api-invalid", `"${s.id}": ${problem}`);
9981
+ }
9982
+ if (s.target !== void 0) {
9983
+ const problem = workflowJobTargetProblem(s.target, void 0, s.luaApi);
9984
+ if (problem) throw new LuaWorkflowBuildError("target-invalid", `"${s.id}": ${problem}`);
9985
+ }
9817
9986
  assertTimeout({
9818
9987
  id: s.id,
9819
9988
  timeoutSeconds: s.timeoutSeconds,
@@ -10070,7 +10239,7 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
10070
10239
  }
10071
10240
  if (opts.target !== void 0) {
10072
10241
  const problem = workflowJobTargetProblem(opts.target, opts.plugins);
10073
- if (problem) throw new LuaWorkflowBuildError("plugins-invalid", `"${id2}": ${problem}`);
10242
+ if (problem) throw new LuaWorkflowBuildError("target-invalid", `"${id2}": ${problem}`);
10074
10243
  }
10075
10244
  assertTimeout({
10076
10245
  id: id2,