lua-cli 3.17.6 → 3.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -144,7 +144,7 @@ var init_constants = __esm({
144
144
  API: process.env.LUA_API_URL || "https://api.heylua.ai",
145
145
  AUTH: process.env.LUA_AUTH_URL || "https://auth.heylua.ai",
146
146
  CHAT: process.env.LUA_API_URL || "https://api.heylua.ai",
147
- WEBHOOK: "https://webhook.heylua.ai",
147
+ WEBHOOK: process.env.LUA_WEBHOOK_URL || "https://webhook.heylua.ai",
148
148
  CDN: "https://cdn.heylua.ai"
149
149
  };
150
150
  CREDENTIALS_FILE = join(CLI_CONFIG_DIR, "credentials");
@@ -758,6 +758,7 @@ var init_compile_constants = __esm({
758
758
  LuaSkill: PassthroughPrimitive,
759
759
  LuaJob: PassthroughPrimitive,
760
760
  LuaWebhook: PassthroughPrimitive,
761
+ LuaTrigger: PassthroughPrimitive,
761
762
  PreProcessor: PassthroughPrimitive,
762
763
  LuaPreprocessor: PassthroughPrimitive,
763
764
  PostProcessor: PassthroughPrimitive,
@@ -768,6 +769,7 @@ var init_compile_constants = __esm({
768
769
  defineSkill: passthroughDefine,
769
770
  defineJob: passthroughDefine,
770
771
  defineWebhook: passthroughDefine,
772
+ defineTrigger: passthroughDefine,
771
773
  definePreProcessor: passthroughDefine,
772
774
  definePostProcessor: passthroughDefine,
773
775
  defineMCPServer: passthroughDefine
@@ -866,6 +868,14 @@ function aiGenerateInputFromSimplified(prompt, content) {
866
868
  ]
867
869
  };
868
870
  }
871
+ function isInteractiveChannel(channel) {
872
+ if (!channel) return true;
873
+ return !NON_INTERACTIVE_CHANNELS.includes(channel);
874
+ }
875
+ function isInteractiveTurn(turn) {
876
+ if (typeof turn.interactive === "boolean") return turn.interactive;
877
+ return isInteractiveChannel(turn.channel);
878
+ }
869
879
  function removeNavigateBlock(input) {
870
880
  return input.replace(/::: navigate[\s\S]*?:::/g, "").trim();
871
881
  }
@@ -933,7 +943,7 @@ function transformChatHistoryContentParts(parts) {
933
943
  function buildDefaultPersona(agentName) {
934
944
  return DEFAULT_PERSONA_GUIDE.replace(AGENT_NAME_TOKEN, () => agentName || "My Agent");
935
945
  }
936
- var __defProp2, __name2, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, AGENT_LOG_SOURCES, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema;
946
+ var __defProp2, __name2, NON_INTERACTIVE_CHANNELS, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, AGENT_LOG_SOURCES, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema;
937
947
  var init_dist = __esm({
938
948
  "../shared-types/dist/index.mjs"() {
939
949
  "use strict";
@@ -951,6 +961,14 @@ var init_dist = __esm({
951
961
  __name2(personaToLiteral, "personaToLiteral");
952
962
  __name(aiGenerateInputFromSimplified, "aiGenerateInputFromSimplified");
953
963
  __name2(aiGenerateInputFromSimplified, "aiGenerateInputFromSimplified");
964
+ NON_INTERACTIVE_CHANNELS = [
965
+ "trigger",
966
+ "agent-invocation"
967
+ ];
968
+ __name(isInteractiveChannel, "isInteractiveChannel");
969
+ __name2(isInteractiveChannel, "isInteractiveChannel");
970
+ __name(isInteractiveTurn, "isInteractiveTurn");
971
+ __name2(isInteractiveTurn, "isInteractiveTurn");
954
972
  __name(removeNavigateBlock, "removeNavigateBlock");
955
973
  __name2(removeNavigateBlock, "removeNavigateBlock");
956
974
  __name(transformChatHistoryContentParts, "transformChatHistoryContentParts");
@@ -1008,6 +1026,7 @@ Feel free to add, remove, or rename sections. Your persona can be a single parag
1008
1026
  "skill",
1009
1027
  "job",
1010
1028
  "webhook",
1029
+ "trigger",
1011
1030
  "preprocessor",
1012
1031
  "postprocessor",
1013
1032
  "user_message",
@@ -1207,7 +1226,15 @@ Feel free to add, remove, or rename sections. Your persona can be a single parag
1207
1226
  // to the LLM as a ToolError — fills the 2–3s gap before the LLM's own
1208
1227
  // recovery response. Persona-specific (keep it short and on-brand);
1209
1228
  // absent → no spoken fallback (the LLM's recovery is the only signal).
1210
- onToolFailureSay: z.string().min(1).max(200).optional()
1229
+ onToolFailureSay: z.string().min(1).max(200).optional(),
1230
+ // Tool names to withhold from this voice agent's session. Matches ANY
1231
+ // resolved tool: the platform base tools (searchKnowledgeBase, searchWeb,
1232
+ // geocoding, the send* structured-output family), MCP/device tools, and the
1233
+ // agent's own skill tools compiled into the artifact. Typical use is dropping
1234
+ // the on-screen send* tools (`sendPayment`, `sendListItems`, …) on a
1235
+ // screenless phone agent where they have nowhere to render. Names that match
1236
+ // nothing are ignored (warn, not error) so a typo can't fail the push.
1237
+ excludeTools: z.array(z.string().min(1)).optional()
1211
1238
  });
1212
1239
  LuaVoiceConfigSchema = LuaVoiceConfigInnerSchema.superRefine((cfg, ctx) => {
1213
1240
  const isRealtime = cfg.llm.kind === "realtime";
@@ -1270,6 +1297,7 @@ var init_types = __esm({
1270
1297
  PrimitiveKind2["SKILL"] = "skill";
1271
1298
  PrimitiveKind2["JOB"] = "job";
1272
1299
  PrimitiveKind2["WEBHOOK"] = "webhook";
1300
+ PrimitiveKind2["TRIGGER"] = "trigger";
1273
1301
  PrimitiveKind2["PREPROCESSOR"] = "preprocessor";
1274
1302
  PrimitiveKind2["POSTPROCESSOR"] = "postprocessor";
1275
1303
  PrimitiveKind2["MCP_SERVER"] = "mcp-server";
@@ -3333,6 +3361,25 @@ function extractObjectProperty(obj, propertyName) {
3333
3361
  }
3334
3362
  return void 0;
3335
3363
  }
3364
+ function extractStringArrayProperty(obj, propertyName) {
3365
+ const prop = obj.getProperty(propertyName);
3366
+ if (!prop) return void 0;
3367
+ let value;
3368
+ if (Node.isShorthandPropertyAssignment(prop)) {
3369
+ value = prop.getNameNode();
3370
+ } else if (Node.isPropertyAssignment(prop)) {
3371
+ value = prop.getInitializer();
3372
+ } else {
3373
+ return void 0;
3374
+ }
3375
+ if (!value) return void 0;
3376
+ const resolved = Node.isIdentifier(value) ? resolveIdentifier(value) : value;
3377
+ const evaluated = evaluateNode(resolved ?? value);
3378
+ if (Array.isArray(evaluated)) {
3379
+ return evaluated.filter((v) => typeof v === "string");
3380
+ }
3381
+ return void 0;
3382
+ }
3336
3383
  function extractFunctionProperty(obj, propertyName) {
3337
3384
  const prop = obj.getProperty(propertyName);
3338
3385
  if (!prop || !Node.isPropertyAssignment(prop)) return void 0;
@@ -3426,6 +3473,7 @@ var init_ast_helpers = __esm({
3426
3473
  __name(extractNestedProperty, "extractNestedProperty");
3427
3474
  __name(evaluateNodeAsObject, "evaluateNodeAsObject");
3428
3475
  __name(extractObjectProperty, "extractObjectProperty");
3476
+ __name(extractStringArrayProperty, "extractStringArrayProperty");
3429
3477
  __name(extractFunctionProperty, "extractFunctionProperty");
3430
3478
  __name(extractPolymorphicProperty, "extractPolymorphicProperty");
3431
3479
  __name(hasProperty, "hasProperty");
@@ -4682,6 +4730,169 @@ var init_webhook_plugin = __esm({
4682
4730
  }
4683
4731
  });
4684
4732
 
4733
+ // src/compiler/plugins/trigger.plugin.ts
4734
+ import { Node as Node7 } from "ts-morph";
4735
+ var TriggerPlugin;
4736
+ var init_trigger_plugin = __esm({
4737
+ "src/compiler/plugins/trigger.plugin.ts"() {
4738
+ "use strict";
4739
+ init_base();
4740
+ init_ast_helpers();
4741
+ init_class_hierarchy();
4742
+ init_schema_converter();
4743
+ TriggerPlugin = class extends BasePlugin {
4744
+ static {
4745
+ __name(this, "TriggerPlugin");
4746
+ }
4747
+ kind = "trigger";
4748
+ displayName = "Trigger";
4749
+ defineFunction = "defineTrigger";
4750
+ legacyClassNames = [
4751
+ "LuaTrigger"
4752
+ ];
4753
+ crossFileRewrite = {
4754
+ copyAllFields: true
4755
+ };
4756
+ supportsClassDefinition = true;
4757
+ /**
4758
+ * Class-definition shape: read the slot presence off the inheritance chain
4759
+ * (most-derived wins), mirroring extractFromConfig.
4760
+ */
4761
+ extractFromClassDefinition(classDecl, sourceFile) {
4762
+ const className = classDecl.getName();
4763
+ if (!className) return null;
4764
+ const isDefaultExport = classDecl.isDefaultExport();
4765
+ const exportName = isDefaultExport ? "default" : className;
4766
+ const name = readStringMember(classDecl, "name") ?? deriveNameFromClassName(className);
4767
+ const description = readStringMember(classDecl, "description") ?? "";
4768
+ return {
4769
+ kind: this.kind,
4770
+ name,
4771
+ description,
4772
+ sourcePath: sourceFile.getFilePath(),
4773
+ exportName,
4774
+ isDefaultExport,
4775
+ line: classDecl.getStartLineNumber(),
4776
+ column: 1,
4777
+ metadata: {
4778
+ pattern: "class-definition",
4779
+ hasVerify: findClassMember(classDecl, "verify", "either") !== void 0,
4780
+ hasFilter: findClassMember(classDecl, "filter", "either") !== void 0,
4781
+ hasTransform: findClassMember(classDecl, "transform", "either") !== void 0,
4782
+ hasInputSchema: findClassMember(classDecl, "inputSchema", "property") !== void 0
4783
+ }
4784
+ };
4785
+ }
4786
+ /**
4787
+ * Project the trigger class instance onto the standard primitive shape,
4788
+ * binding the optional slot methods so subclass overrides win at runtime.
4789
+ */
4790
+ getClassDefinitionPrimitiveShape(metadata) {
4791
+ return `{
4792
+ kind: 'trigger',
4793
+ name: __lua_instance__.name ?? ${JSON.stringify(metadata.name)},
4794
+ description: __lua_instance__.description ?? ${JSON.stringify(metadata.description)},
4795
+ verify: typeof __lua_instance__.verify === 'function' ? __lua_instance__.verify.bind(__lua_instance__) : undefined,
4796
+ filter: typeof __lua_instance__.filter === 'function' ? __lua_instance__.filter.bind(__lua_instance__) : undefined,
4797
+ transform: typeof __lua_instance__.transform === 'function' ? __lua_instance__.transform.bind(__lua_instance__) : undefined,
4798
+ }`;
4799
+ }
4800
+ extractFromConfig(config, exportName, sourcePath, position, pattern) {
4801
+ const common = this.extractCommonFields(config, exportName, sourcePath, position);
4802
+ if (!common) return null;
4803
+ return {
4804
+ kind: this.kind,
4805
+ ...common,
4806
+ metadata: {
4807
+ pattern,
4808
+ hasVerify: config.getProperty("verify") !== void 0,
4809
+ hasFilter: config.getProperty("filter") !== void 0,
4810
+ hasTransform: config.getProperty("transform") !== void 0,
4811
+ hasInputSchema: config.getProperty("inputSchema") !== void 0
4812
+ }
4813
+ };
4814
+ }
4815
+ validate(metadata) {
4816
+ const { errors, warnings } = this.baseValidation(metadata);
4817
+ const { hasVerify, hasFilter, hasTransform } = metadata.metadata;
4818
+ if (!hasVerify && !hasFilter && !hasTransform) {
4819
+ errors.push(validationError("Trigger must define at least one of verify, filter, or transform", {
4820
+ line: metadata.line
4821
+ }));
4822
+ }
4823
+ if (metadata.name && !/^[a-z][a-z0-9-]*$/.test(metadata.name)) {
4824
+ warnings.push(validationWarning("Trigger name should be URL-safe (lowercase, hyphens only)", {
4825
+ line: metadata.line
4826
+ }));
4827
+ }
4828
+ return {
4829
+ valid: errors.length === 0,
4830
+ errors,
4831
+ warnings
4832
+ };
4833
+ }
4834
+ /**
4835
+ * Runtime check: a published trigger bundle must expose at least one slot
4836
+ * function. (No `execute` — that's the defining feature.)
4837
+ */
4838
+ getRuntimeValidation() {
4839
+ return `
4840
+ const __slots = primitive.primitive || {};
4841
+ if (
4842
+ typeof __slots.verify !== 'function' &&
4843
+ typeof __slots.filter !== 'function' &&
4844
+ typeof __slots.transform !== 'function'
4845
+ ) {
4846
+ throw new Error('[Lua] Invalid trigger artifact: no verify/filter/transform slot');
4847
+ }`;
4848
+ }
4849
+ /** Extract the SDK `inputSchema` (typed body) → manifest `body` schema. */
4850
+ async extractSchemas(metadata, project) {
4851
+ if (!metadata.metadata.hasInputSchema) return void 0;
4852
+ const sourceFile = project.getSourceFile(metadata.sourcePath);
4853
+ if (!sourceFile) return void 0;
4854
+ const schemas = {};
4855
+ if (metadata.metadata.pattern === "class-definition") {
4856
+ const classDecl = locateClassDefinition(sourceFile, metadata.exportName);
4857
+ if (!classDecl) return void 0;
4858
+ const hit = findClassMember(classDecl, "inputSchema", "property");
4859
+ if (!hit || !Node7.isPropertyDeclaration(hit.node)) return void 0;
4860
+ const schemaNode2 = hit.node.getInitializer();
4861
+ if (!schemaNode2) return void 0;
4862
+ try {
4863
+ schemas.body = await zodToJsonSchema(schemaNode2);
4864
+ } catch (error) {
4865
+ console.warn(`Warning: Could not convert inputSchema for ${metadata.name}:`, error);
4866
+ }
4867
+ return Object.keys(schemas).length > 0 ? schemas : void 0;
4868
+ }
4869
+ const varDecl = sourceFile.getVariableDeclaration(metadata.exportName);
4870
+ const initializer = varDecl?.getInitializer();
4871
+ if (!initializer || !Node7.isCallExpression(initializer)) return void 0;
4872
+ const args2 = initializer.getArguments();
4873
+ if (args2.length === 0 || !Node7.isObjectLiteralExpression(args2[0])) return void 0;
4874
+ const schemaNode = extractSchemaProperty(args2[0], "inputSchema");
4875
+ if (schemaNode) {
4876
+ try {
4877
+ schemas.body = await zodToJsonSchema(schemaNode);
4878
+ } catch (error) {
4879
+ console.warn(`Warning: Could not convert inputSchema for ${metadata.name}:`, error);
4880
+ }
4881
+ }
4882
+ return Object.keys(schemas).length > 0 ? schemas : void 0;
4883
+ }
4884
+ toManifestEntry(compiled, _allPrimitives) {
4885
+ return {
4886
+ ...this.baseManifestFields(compiled),
4887
+ schemas: compiled.schemas ? {
4888
+ body: compiled.schemas.body
4889
+ } : void 0
4890
+ };
4891
+ }
4892
+ };
4893
+ }
4894
+ });
4895
+
4685
4896
  // src/compiler/plugins/processor-base.ts
4686
4897
  var ProcessorPluginBase;
4687
4898
  var init_processor_base = __esm({
@@ -4717,7 +4928,7 @@ var init_processor_base = __esm({
4717
4928
  });
4718
4929
 
4719
4930
  // src/compiler/plugins/preprocessor.plugin.ts
4720
- import { Node as Node7 } from "ts-morph";
4931
+ import { Node as Node8 } from "ts-morph";
4721
4932
  var PreProcessorPlugin;
4722
4933
  var init_preprocessor_plugin = __esm({
4723
4934
  "src/compiler/plugins/preprocessor.plugin.ts"() {
@@ -4752,9 +4963,9 @@ var init_preprocessor_plugin = __esm({
4752
4963
  const name = readStringMember(classDecl, "name") ?? deriveNameFromClassName(className);
4753
4964
  const description = readStringMember(classDecl, "description") ?? "";
4754
4965
  const asyncHit = findClassMember(classDecl, "async", "property");
4755
- const isAsync = asyncHit && Node7.isPropertyDeclaration(asyncHit.node) ? evaluateNodeAsBoolean(asyncHit.node.getInitializer()) ?? false : false;
4966
+ const isAsync = asyncHit && Node8.isPropertyDeclaration(asyncHit.node) ? evaluateNodeAsBoolean(asyncHit.node.getInitializer()) ?? false : false;
4756
4967
  const priorityHit = findClassMember(classDecl, "priority", "property");
4757
- const priority = priorityHit && Node7.isPropertyDeclaration(priorityHit.node) ? evaluateNodeAsNumber(priorityHit.node.getInitializer()) : void 0;
4968
+ const priority = priorityHit && Node8.isPropertyDeclaration(priorityHit.node) ? evaluateNodeAsNumber(priorityHit.node.getInitializer()) : void 0;
4758
4969
  return {
4759
4970
  kind: this.kind,
4760
4971
  name,
@@ -4803,7 +5014,7 @@ var init_preprocessor_plugin = __esm({
4803
5014
  });
4804
5015
 
4805
5016
  // src/compiler/plugins/postprocessor.plugin.ts
4806
- import { Node as Node8 } from "ts-morph";
5017
+ import { Node as Node9 } from "ts-morph";
4807
5018
  var PostProcessorPlugin;
4808
5019
  var init_postprocessor_plugin = __esm({
4809
5020
  "src/compiler/plugins/postprocessor.plugin.ts"() {
@@ -4838,7 +5049,7 @@ var init_postprocessor_plugin = __esm({
4838
5049
  const name = readStringMember(classDecl, "name") ?? deriveNameFromClassName(className);
4839
5050
  const description = readStringMember(classDecl, "description") ?? "";
4840
5051
  const priorityHit = findClassMember(classDecl, "priority", "property");
4841
- const priority = priorityHit && Node8.isPropertyDeclaration(priorityHit.node) ? evaluateNodeAsNumber(priorityHit.node.getInitializer()) : void 0;
5052
+ const priority = priorityHit && Node9.isPropertyDeclaration(priorityHit.node) ? evaluateNodeAsNumber(priorityHit.node.getInitializer()) : void 0;
4842
5053
  return {
4843
5054
  kind: this.kind,
4844
5055
  name,
@@ -4883,7 +5094,7 @@ var init_postprocessor_plugin = __esm({
4883
5094
  });
4884
5095
 
4885
5096
  // src/compiler/plugins/mcp-server.plugin.ts
4886
- import { Node as Node9 } from "ts-morph";
5097
+ import { Node as Node10 } from "ts-morph";
4887
5098
  var MCPServerPlugin;
4888
5099
  var init_mcp_server_plugin = __esm({
4889
5100
  "src/compiler/plugins/mcp-server.plugin.ts"() {
@@ -4924,10 +5135,10 @@ var init_mcp_server_plugin = __esm({
4924
5135
  let hasUrlResolver = false;
4925
5136
  let urlResolverSource;
4926
5137
  if (urlHit) {
4927
- if (Node9.isMethodDeclaration(urlHit.node)) {
5138
+ if (Node10.isMethodDeclaration(urlHit.node)) {
4928
5139
  hasUrlResolver = true;
4929
5140
  urlResolverSource = urlHit.node.getText();
4930
- } else if (Node9.isPropertyDeclaration(urlHit.node)) {
5141
+ } else if (Node10.isPropertyDeclaration(urlHit.node)) {
4931
5142
  const init = urlHit.node.getInitializer();
4932
5143
  if (init && isFunction(init)) {
4933
5144
  hasUrlResolver = true;
@@ -4941,10 +5152,10 @@ var init_mcp_server_plugin = __esm({
4941
5152
  let hasHeadersResolver = false;
4942
5153
  let headersResolverSource;
4943
5154
  if (headersHit) {
4944
- if (Node9.isMethodDeclaration(headersHit.node)) {
5155
+ if (Node10.isMethodDeclaration(headersHit.node)) {
4945
5156
  hasHeadersResolver = true;
4946
5157
  headersResolverSource = headersHit.node.getText();
4947
- } else if (Node9.isPropertyDeclaration(headersHit.node)) {
5158
+ } else if (Node10.isPropertyDeclaration(headersHit.node)) {
4948
5159
  const init = headersHit.node.getInitializer();
4949
5160
  if (init && isFunction(init)) {
4950
5161
  hasHeadersResolver = true;
@@ -5075,10 +5286,10 @@ var init_mcp_server_plugin = __esm({
5075
5286
  // ../shared-source-sync/dist/index.mjs
5076
5287
  import { createHash } from "crypto";
5077
5288
  import { extname } from "path";
5078
- import { readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync2 } from "fs";
5079
- import { join as join4, sep } from "path";
5289
+ import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync2 } from "fs";
5290
+ import { join as join5, sep } from "path";
5080
5291
  import { gunzipSync, gzipSync } from "zlib";
5081
- import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync22, statSync as statSync22, writeFileSync as writeFileSync5 } from "fs";
5292
+ import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync22, statSync as statSync22, writeFileSync as writeFileSync6 } from "fs";
5082
5293
  import { dirname as dirname3, join as join22, resolve, sep as sep2 } from "path";
5083
5294
  import { mkdirSync as mkdirSync22, readdirSync as readdirSync22, readFileSync as readFileSync32, statSync as statSync3, writeFileSync as writeFileSync22 } from "fs";
5084
5295
  import { dirname as dirname22, join as join32, sep as sep3 } from "path";
@@ -5110,7 +5321,7 @@ function walkWorkspace(rootDir, opts = {}) {
5110
5321
  const contentByHash = /* @__PURE__ */ new Map();
5111
5322
  let totalSize = 0;
5112
5323
  const visit = /* @__PURE__ */ __name3((relPrefix) => {
5113
- const absDir = relPrefix ? join4(rootDir, relPrefix) : rootDir;
5324
+ const absDir = relPrefix ? join5(rootDir, relPrefix) : rootDir;
5114
5325
  let entries;
5115
5326
  try {
5116
5327
  entries = readdirSync2(absDir, {
@@ -5129,7 +5340,7 @@ function walkWorkspace(rootDir, opts = {}) {
5129
5340
  if (!entry.isFile()) continue;
5130
5341
  if (shouldSkipFile(entry.name)) continue;
5131
5342
  const rel = (relPrefix ? `${relPrefix}${sep}${entry.name}` : entry.name).split(sep).join("/");
5132
- const abs = join4(rootDir, rel);
5343
+ const abs = join5(rootDir, rel);
5133
5344
  let stats;
5134
5345
  try {
5135
5346
  stats = statSync2(abs);
@@ -5139,7 +5350,7 @@ function walkWorkspace(rootDir, opts = {}) {
5139
5350
  if (stats.size > maxBytes) continue;
5140
5351
  let content;
5141
5352
  try {
5142
- content = readFileSync6(abs);
5353
+ content = readFileSync7(abs);
5143
5354
  } catch {
5144
5355
  continue;
5145
5356
  }
@@ -5245,7 +5456,7 @@ function restoreFromBlobs(manifest, blobs, targetDir, opts = {}) {
5245
5456
  throw new Error(`Blob not found for hash: ${file.hash} (${file.relativePath})`);
5246
5457
  }
5247
5458
  const targetPath = resolveBackupFileTarget(file, targetDir);
5248
- if (existsSync5(targetPath)) {
5459
+ if (existsSync6(targetPath)) {
5249
5460
  const sameSize = statSync22(targetPath).size === content.length;
5250
5461
  if (sameSize && readFileSync22(targetPath).equals(content)) {
5251
5462
  filesUnchanged++;
@@ -5259,7 +5470,7 @@ function restoreFromBlobs(manifest, blobs, targetDir, opts = {}) {
5259
5470
  mkdirSync5(dirname3(targetPath), {
5260
5471
  recursive: true
5261
5472
  });
5262
- writeFileSync5(targetPath, content);
5473
+ writeFileSync6(targetPath, content);
5263
5474
  filesWritten++;
5264
5475
  }
5265
5476
  return {
@@ -5678,7 +5889,7 @@ var init_path_resolver = __esm({
5678
5889
  });
5679
5890
 
5680
5891
  // src/compiler/utils/reference-resolver.ts
5681
- import { Node as Node10 } from "ts-morph";
5892
+ import { Node as Node11 } from "ts-morph";
5682
5893
  function resolveArrayRefs(expression, ctx) {
5683
5894
  if (!expression) {
5684
5895
  return {
@@ -5726,10 +5937,10 @@ function reportDeopt(result, propertyName) {
5726
5937
  const sourceFile = deopt.getSourceFile();
5727
5938
  const filePath = sourceFile.getFilePath();
5728
5939
  const { line, column } = sourceFile.getLineAndColumnAtPos(deopt.getStart());
5729
- const snippet = truncate(deopt.getText(), 60);
5940
+ const snippet2 = truncate(deopt.getText(), 60);
5730
5941
  return `[${result.ruleId}] ${filePath}:${line}:${column}
5731
5942
  could not statically resolve "${propertyName}": ${result.reason}
5732
- at: \`${snippet}\`
5943
+ at: \`${snippet2}\`
5733
5944
  hint: inline the array, export the value as a plain array literal, or add a leading /* @lua-ignore-ref */ comment to silence`;
5734
5945
  }
5735
5946
  function formatSarifWarning(args2) {
@@ -5754,14 +5965,14 @@ function warnDroppedConstructorArgs(newExpr, className) {
5754
5965
  }));
5755
5966
  }
5756
5967
  function resolveArrayExpression(node, out, state) {
5757
- if (Node10.isArrayLiteralExpression(node)) {
5968
+ if (Node11.isArrayLiteralExpression(node)) {
5758
5969
  for (const element of node.getElements()) {
5759
5970
  resolveArrayElement(element, out, state);
5760
5971
  if (state.deopt) return;
5761
5972
  }
5762
5973
  return;
5763
5974
  }
5764
- if (Node10.isIdentifier(node)) {
5975
+ if (Node11.isIdentifier(node)) {
5765
5976
  const decl = followIdentifier(node, state);
5766
5977
  if (!decl) {
5767
5978
  const defaultExpr = followDefaultImportToExpression(node, state);
@@ -5775,7 +5986,7 @@ function resolveArrayExpression(node, out, state) {
5775
5986
  };
5776
5987
  return;
5777
5988
  }
5778
- if (!Node10.isVariableDeclaration(decl)) {
5989
+ if (!Node11.isVariableDeclaration(decl)) {
5779
5990
  state.deopt = state.deopt ?? {
5780
5991
  node,
5781
5992
  reason: `identifier "${node.getText()}" resolves to a ${decl.getKindName()}, not an array`
@@ -5793,15 +6004,15 @@ function resolveArrayExpression(node, out, state) {
5793
6004
  resolveArrayExpression(init, out, state);
5794
6005
  return;
5795
6006
  }
5796
- if (Node10.isParenthesizedExpression(node)) {
6007
+ if (Node11.isParenthesizedExpression(node)) {
5797
6008
  resolveArrayExpression(node.getExpression(), out, state);
5798
6009
  return;
5799
6010
  }
5800
- if (Node10.isAsExpression(node) || Node10.isTypeAssertion(node) || Node10.isSatisfiesExpression(node)) {
6011
+ if (Node11.isAsExpression(node) || Node11.isTypeAssertion(node) || Node11.isSatisfiesExpression(node)) {
5801
6012
  resolveArrayExpression(node.getExpression(), out, state);
5802
6013
  return;
5803
6014
  }
5804
- if (Node10.isPropertyAccessExpression(node)) {
6015
+ if (Node11.isPropertyAccessExpression(node)) {
5805
6016
  const value = resolvePropertyAccess(node, state);
5806
6017
  if (!value) {
5807
6018
  state.deopt = state.deopt ?? {
@@ -5813,7 +6024,7 @@ function resolveArrayExpression(node, out, state) {
5813
6024
  resolveArrayExpression(value, out, state);
5814
6025
  return;
5815
6026
  }
5816
- if (Node10.isCallExpression(node)) {
6027
+ if (Node11.isCallExpression(node)) {
5817
6028
  state.deopt = state.deopt ?? {
5818
6029
  node,
5819
6030
  reason: `call expression "${truncate(node.getText(), 40)}" cannot be statically resolved to an array`
@@ -5827,19 +6038,19 @@ function resolveArrayExpression(node, out, state) {
5827
6038
  }
5828
6039
  function resolveArrayElement(element, out, state) {
5829
6040
  let node = element;
5830
- while (Node10.isParenthesizedExpression(node) || Node10.isAsExpression(node) || Node10.isTypeAssertion(node) || Node10.isSatisfiesExpression(node)) {
6041
+ while (Node11.isParenthesizedExpression(node) || Node11.isAsExpression(node) || Node11.isTypeAssertion(node) || Node11.isSatisfiesExpression(node)) {
5831
6042
  node = node.getExpression();
5832
6043
  }
5833
- if (Node10.isSpreadElement(node)) {
6044
+ if (Node11.isSpreadElement(node)) {
5834
6045
  resolveArrayExpression(node.getExpression(), out, state);
5835
6046
  return;
5836
6047
  }
5837
- if (Node10.isNewExpression(node)) {
6048
+ if (Node11.isNewExpression(node)) {
5838
6049
  const classExpr = node.getExpression();
5839
6050
  const className = classExpr.getText();
5840
- if (Node10.isIdentifier(classExpr)) {
6051
+ if (Node11.isIdentifier(classExpr)) {
5841
6052
  const decl = followIdentifier(classExpr, state);
5842
- if (decl && Node10.isClassDeclaration(decl)) {
6053
+ if (decl && Node11.isClassDeclaration(decl)) {
5843
6054
  const declFile = decl.getSourceFile();
5844
6055
  const isProjectFile = !declFile.isDeclarationFile() && !declFile.isInNodeModules();
5845
6056
  if (isProjectFile) {
@@ -5862,7 +6073,7 @@ function resolveArrayElement(element, out, state) {
5862
6073
  });
5863
6074
  return;
5864
6075
  }
5865
- if (Node10.isIdentifier(node)) {
6076
+ if (Node11.isIdentifier(node)) {
5866
6077
  const viaDefaultImport = isDefaultImportBinding(node);
5867
6078
  const decl = followIdentifier(node, state);
5868
6079
  if (!decl) {
@@ -5877,7 +6088,7 @@ function resolveArrayElement(element, out, state) {
5877
6088
  };
5878
6089
  return;
5879
6090
  }
5880
- if (Node10.isClassDeclaration(decl) || Node10.isFunctionDeclaration(decl)) {
6091
+ if (Node11.isClassDeclaration(decl) || Node11.isFunctionDeclaration(decl)) {
5881
6092
  out.push({
5882
6093
  identifierName: node.getText(),
5883
6094
  sourceFile: decl.getSourceFile(),
@@ -5894,15 +6105,15 @@ function resolveArrayElement(element, out, state) {
5894
6105
  };
5895
6106
  return;
5896
6107
  }
5897
- if (Node10.isArrayLiteralExpression(init)) {
6108
+ if (Node11.isArrayLiteralExpression(init)) {
5898
6109
  resolveArrayExpression(init, out, state);
5899
6110
  return;
5900
6111
  }
5901
- if (Node10.isIdentifier(init)) {
6112
+ if (Node11.isIdentifier(init)) {
5902
6113
  resolveArrayElement(init, out, state);
5903
6114
  return;
5904
6115
  }
5905
- if (Node10.isNewExpression(init)) {
6116
+ if (Node11.isNewExpression(init)) {
5906
6117
  out.push({
5907
6118
  identifierName: node.getText(),
5908
6119
  sourceFile: decl.getSourceFile(),
@@ -5912,7 +6123,7 @@ function resolveArrayElement(element, out, state) {
5912
6123
  });
5913
6124
  return;
5914
6125
  }
5915
- if (Node10.isCallExpression(init)) {
6126
+ if (Node11.isCallExpression(init)) {
5916
6127
  out.push({
5917
6128
  identifierName: node.getText(),
5918
6129
  sourceFile: decl.getSourceFile(),
@@ -5929,7 +6140,7 @@ function resolveArrayElement(element, out, state) {
5929
6140
  });
5930
6141
  return;
5931
6142
  }
5932
- if (Node10.isPropertyAccessExpression(node)) {
6143
+ if (Node11.isPropertyAccessExpression(node)) {
5933
6144
  const value = resolvePropertyAccess(node, state);
5934
6145
  if (!value) {
5935
6146
  state.deopt = state.deopt ?? {
@@ -6069,7 +6280,7 @@ function resolveDefaultInFile(sourceFile, state) {
6069
6280
  for (const assign of sourceFile.getExportAssignments()) {
6070
6281
  if (assign.isExportEquals()) continue;
6071
6282
  const expr = assign.getExpression();
6072
- if (Node10.isIdentifier(expr)) {
6283
+ if (Node11.isIdentifier(expr)) {
6073
6284
  return resolveInFile(expr.getText(), sourceFile, state);
6074
6285
  }
6075
6286
  return void 0;
@@ -6109,7 +6320,7 @@ function followSymbol(node, state) {
6109
6320
  if (!symbol) return void 0;
6110
6321
  const aliased = symbol.isAlias() ? node.getSourceFile().getProject().getTypeChecker().getAliasedSymbol(symbol) ?? symbol : symbol;
6111
6322
  for (const decl of aliased.getDeclarations()) {
6112
- if (Node10.isVariableDeclaration(decl) || Node10.isClassDeclaration(decl) || Node10.isFunctionDeclaration(decl)) {
6323
+ if (Node11.isVariableDeclaration(decl) || Node11.isClassDeclaration(decl) || Node11.isFunctionDeclaration(decl)) {
6113
6324
  return decl;
6114
6325
  }
6115
6326
  }
@@ -6125,7 +6336,7 @@ function followSymbolInFile(name, sourceFile, state) {
6125
6336
  const decls = exportedMap.get(name);
6126
6337
  if (!decls) return void 0;
6127
6338
  for (const decl of decls) {
6128
- if (Node10.isVariableDeclaration(decl) || Node10.isClassDeclaration(decl) || Node10.isFunctionDeclaration(decl)) {
6339
+ if (Node11.isVariableDeclaration(decl) || Node11.isClassDeclaration(decl) || Node11.isFunctionDeclaration(decl)) {
6129
6340
  return decl;
6130
6341
  }
6131
6342
  }
@@ -6135,31 +6346,31 @@ function followSymbolInFile(name, sourceFile, state) {
6135
6346
  return void 0;
6136
6347
  }
6137
6348
  function resolvePropertyAccess(node, state) {
6138
- if (!Node10.isPropertyAccessExpression(node)) return void 0;
6349
+ if (!Node11.isPropertyAccessExpression(node)) return void 0;
6139
6350
  const propertyName = node.getName();
6140
6351
  const objectExpr = node.getExpression();
6141
- if (Node10.isIdentifier(objectExpr)) {
6352
+ if (Node11.isIdentifier(objectExpr)) {
6142
6353
  const namespaceTarget = followNamespaceImport(objectExpr, state);
6143
6354
  if (namespaceTarget) {
6144
6355
  const decl = resolveInFile(propertyName, namespaceTarget, state);
6145
- if (decl && Node10.isVariableDeclaration(decl)) {
6356
+ if (decl && Node11.isVariableDeclaration(decl)) {
6146
6357
  return decl.getInitializer();
6147
6358
  }
6148
6359
  return void 0;
6149
6360
  }
6150
6361
  }
6151
6362
  let objectNode = objectExpr;
6152
- if (Node10.isIdentifier(objectExpr)) {
6363
+ if (Node11.isIdentifier(objectExpr)) {
6153
6364
  const decl = followIdentifier(objectExpr, state);
6154
- objectNode = decl && Node10.isVariableDeclaration(decl) ? decl.getInitializer() : void 0;
6155
- } else if (Node10.isPropertyAccessExpression(objectExpr)) {
6365
+ objectNode = decl && Node11.isVariableDeclaration(decl) ? decl.getInitializer() : void 0;
6366
+ } else if (Node11.isPropertyAccessExpression(objectExpr)) {
6156
6367
  objectNode = resolvePropertyAccess(objectExpr, state);
6157
6368
  }
6158
- if (!objectNode || !Node10.isObjectLiteralExpression(objectNode)) {
6369
+ if (!objectNode || !Node11.isObjectLiteralExpression(objectNode)) {
6159
6370
  return void 0;
6160
6371
  }
6161
6372
  const prop = objectNode.getProperty(propertyName);
6162
- if (!prop || !Node10.isPropertyAssignment(prop)) return void 0;
6373
+ if (!prop || !Node11.isPropertyAssignment(prop)) return void 0;
6163
6374
  return prop.getInitializer();
6164
6375
  }
6165
6376
  function followNamespaceImport(identifier, state) {
@@ -6249,12 +6460,12 @@ var init_reference_resolver = __esm({
6249
6460
 
6250
6461
  // src/compiler/plugins/skill.plugin.ts
6251
6462
  import fs4 from "fs/promises";
6252
- import { Node as Node11 } from "ts-morph";
6463
+ import { Node as Node12 } from "ts-morph";
6253
6464
  function findEnclosingVariableDeclaration(config) {
6254
6465
  let current = config.getParent();
6255
6466
  for (let depth = 0; depth < 5 && current; depth++) {
6256
- if (Node11.isVariableDeclaration(current)) return current;
6257
- if (Node11.isStatement(current) || Node11.isSourceFile(current)) return void 0;
6467
+ if (Node12.isVariableDeclaration(current)) return current;
6468
+ if (Node12.isStatement(current) || Node12.isSourceFile(current)) return void 0;
6258
6469
  current = current.getParent();
6259
6470
  }
6260
6471
  return void 0;
@@ -6262,14 +6473,14 @@ function findEnclosingVariableDeclaration(config) {
6262
6473
  function receiverResolvesToVarDecl(receiver, target, maxDepth = 10) {
6263
6474
  let current = receiver;
6264
6475
  for (let i = 0; i < maxDepth && current; i++) {
6265
- if (!Node11.isIdentifier(current)) return false;
6476
+ if (!Node12.isIdentifier(current)) return false;
6266
6477
  const symbol = current.getSymbol();
6267
6478
  const decls = symbol?.getDeclarations() ?? [];
6268
- const varDecl = decls.find((d) => Node11.isVariableDeclaration(d));
6479
+ const varDecl = decls.find((d) => Node12.isVariableDeclaration(d));
6269
6480
  if (!varDecl) return false;
6270
6481
  if (varDecl === target) return true;
6271
6482
  const init = varDecl.getInitializer();
6272
- if (init && Node11.isIdentifier(init)) {
6483
+ if (init && Node12.isIdentifier(init)) {
6273
6484
  current = init;
6274
6485
  continue;
6275
6486
  }
@@ -6330,7 +6541,7 @@ var init_skill_plugin = __esm({
6330
6541
  const description = readStringMember(classDecl, "description") ?? "";
6331
6542
  const contextHit = findClassMember(classDecl, "context", "property");
6332
6543
  let context;
6333
- if (contextHit && Node11.isPropertyDeclaration(contextHit.node)) {
6544
+ if (contextHit && Node12.isPropertyDeclaration(contextHit.node)) {
6334
6545
  const init = contextHit.node.getInitializer();
6335
6546
  const asString = evaluateNodeAsString(init);
6336
6547
  if (asString !== void 0) {
@@ -6341,7 +6552,7 @@ var init_skill_plugin = __esm({
6341
6552
  }
6342
6553
  }
6343
6554
  const toolsHit = findClassMember(classDecl, "tools", "property");
6344
- const toolRefsFromArray = toolsHit && Node11.isPropertyDeclaration(toolsHit.node) ? this.resolveToolRefsFromInitializer(toolsHit.node.getInitializer()) : [];
6555
+ const toolRefsFromArray = toolsHit && Node12.isPropertyDeclaration(toolsHit.node) ? this.resolveToolRefsFromInitializer(toolsHit.node.getInitializer()) : [];
6345
6556
  const methodToolRefs = this.extractToolRefsFromMethodCalls(classDecl, {
6346
6557
  ownerClass: classDecl
6347
6558
  });
@@ -6447,7 +6658,7 @@ var init_skill_plugin = __esm({
6447
6658
  */
6448
6659
  extractToolRefs(config) {
6449
6660
  const toolsProp = config.getProperty("tools");
6450
- if (!toolsProp || !Node11.isPropertyAssignment(toolsProp)) return [];
6661
+ if (!toolsProp || !Node12.isPropertyAssignment(toolsProp)) return [];
6451
6662
  const toolsValue = toolsProp.getInitializer();
6452
6663
  if (!toolsValue) return [];
6453
6664
  const project = config.getSourceFile().getProject();
@@ -6492,9 +6703,9 @@ var init_skill_plugin = __esm({
6492
6703
  const project = scope.getSourceFile().getProject();
6493
6704
  const ownerVar = "owner" in owner ? owner.owner : void 0;
6494
6705
  scope.forEachDescendant((node) => {
6495
- if (!Node11.isCallExpression(node)) return;
6706
+ if (!Node12.isCallExpression(node)) return;
6496
6707
  const expression = node.getExpression();
6497
- if (!Node11.isPropertyAccessExpression(expression)) return;
6708
+ if (!Node12.isPropertyAccessExpression(expression)) return;
6498
6709
  const property = expression.getName();
6499
6710
  if (property !== "addTools" && property !== "addTool") return;
6500
6711
  if (ownerVar && !receiverResolvesToVarDecl(expression.getExpression(), ownerVar)) return;
@@ -6516,13 +6727,13 @@ var init_skill_plugin = __esm({
6516
6727
  return;
6517
6728
  }
6518
6729
  const arg = args2[0];
6519
- if (Node11.isNewExpression(arg)) {
6730
+ if (Node12.isNewExpression(arg)) {
6520
6731
  const className = arg.getExpression().getText();
6521
6732
  warnDroppedConstructorArgs(arg, className);
6522
6733
  refs.push({
6523
6734
  className
6524
6735
  });
6525
- } else if (Node11.isIdentifier(arg)) {
6736
+ } else if (Node12.isIdentifier(arg)) {
6526
6737
  refs.push({
6527
6738
  className: arg.getText()
6528
6739
  });
@@ -6684,7 +6895,7 @@ var init_skill_plugin = __esm({
6684
6895
  });
6685
6896
 
6686
6897
  // src/compiler/plugins/agent.plugin.ts
6687
- import { Node as Node12 } from "ts-morph";
6898
+ import { Node as Node13 } from "ts-morph";
6688
6899
  function shapeModelSettings(raw) {
6689
6900
  const KNOWN_KEYS = [
6690
6901
  "temperature",
@@ -6769,7 +6980,7 @@ var init_agent_plugin = __esm({
6769
6980
  const baseDescription = readStringMember(classDecl, "description") ?? "";
6770
6981
  const personaHit = findClassMember(classDecl, "persona", "property");
6771
6982
  let persona = "";
6772
- if (personaHit && Node12.isPropertyDeclaration(personaHit.node)) {
6983
+ if (personaHit && Node13.isPropertyDeclaration(personaHit.node)) {
6773
6984
  const init = personaHit.node.getInitializer();
6774
6985
  const asString = evaluateNodeAsString(init);
6775
6986
  if (asString !== void 0) {
@@ -6783,9 +6994,9 @@ var init_agent_plugin = __esm({
6783
6994
  let hasModelResolver = false;
6784
6995
  const modelHit = findClassMember(classDecl, "model", "either");
6785
6996
  if (modelHit) {
6786
- if (Node12.isMethodDeclaration(modelHit.node)) {
6997
+ if (Node13.isMethodDeclaration(modelHit.node)) {
6787
6998
  hasModelResolver = true;
6788
- } else if (Node12.isPropertyDeclaration(modelHit.node)) {
6999
+ } else if (Node13.isPropertyDeclaration(modelHit.node)) {
6789
7000
  const init = modelHit.node.getInitializer();
6790
7001
  if (init && isFunction(init)) {
6791
7002
  hasModelResolver = true;
@@ -6795,13 +7006,13 @@ var init_agent_plugin = __esm({
6795
7006
  }
6796
7007
  }
6797
7008
  const batchingHit = findClassMember(classDecl, "batching", "property");
6798
- const batchingObj = batchingHit && Node12.isPropertyDeclaration(batchingHit.node) ? evaluateNodeAsObject(batchingHit.node.getInitializer()) : void 0;
7009
+ const batchingObj = batchingHit && Node13.isPropertyDeclaration(batchingHit.node) ? evaluateNodeAsObject(batchingHit.node.getInitializer()) : void 0;
6799
7010
  const batching = batchingObj ? this.shapeBatching(batchingObj) : void 0;
6800
7011
  const governanceHit = findClassMember(classDecl, "governance", "property");
6801
- const governanceObj = governanceHit && Node12.isPropertyDeclaration(governanceHit.node) ? evaluateNodeAsObject(governanceHit.node.getInitializer()) : void 0;
7012
+ const governanceObj = governanceHit && Node13.isPropertyDeclaration(governanceHit.node) ? evaluateNodeAsObject(governanceHit.node.getInitializer()) : void 0;
6802
7013
  const governance = governanceObj && typeof governanceObj.mode === "string" ? governanceObj : void 0;
6803
7014
  const modelSettingsHit = findClassMember(classDecl, "modelSettings", "property");
6804
- const modelSettingsObj = modelSettingsHit && Node12.isPropertyDeclaration(modelSettingsHit.node) ? evaluateNodeAsObject(modelSettingsHit.node.getInitializer()) : void 0;
7015
+ const modelSettingsObj = modelSettingsHit && Node13.isPropertyDeclaration(modelSettingsHit.node) ? evaluateNodeAsObject(modelSettingsHit.node.getInitializer()) : void 0;
6805
7016
  const modelSettings = modelSettingsObj ? shapeModelSettings(modelSettingsObj) : void 0;
6806
7017
  return {
6807
7018
  kind: this.kind,
@@ -6890,9 +7101,9 @@ var init_agent_plugin = __esm({
6890
7101
  */
6891
7102
  extractVoiceRefs(config) {
6892
7103
  const prop = config.getProperty("voices");
6893
- if (!prop || !Node12.isPropertyAssignment(prop)) return {};
7104
+ if (!prop || !Node13.isPropertyAssignment(prop)) return {};
6894
7105
  const value = prop.getInitializer();
6895
- if (!value || !Node12.isArrayLiteralExpression(value)) return {};
7106
+ if (!value || !Node13.isArrayLiteralExpression(value)) return {};
6896
7107
  const project = config.getSourceFile().getProject();
6897
7108
  const result = resolveArrayRefs(value, {
6898
7109
  project
@@ -6997,14 +7208,14 @@ var init_agent_plugin = __esm({
6997
7208
  let result = null;
6998
7209
  sourceFile.forEachDescendant((node) => {
6999
7210
  if (result) return;
7000
- if (Node12.isNewExpression(node)) {
7211
+ if (Node13.isNewExpression(node)) {
7001
7212
  const expr = node.getExpression();
7002
7213
  if (expr.getText() === "LuaAgent") {
7003
7214
  const args2 = node.getArguments();
7004
- if (args2.length > 0 && Node12.isObjectLiteralExpression(args2[0])) {
7215
+ if (args2.length > 0 && Node13.isObjectLiteralExpression(args2[0])) {
7005
7216
  const config = args2[0];
7006
7217
  const parent = node.getParent();
7007
- const exportName = parent && Node12.isVariableDeclaration(parent) ? parent.getName() : "default";
7218
+ const exportName = parent && Node13.isVariableDeclaration(parent) ? parent.getName() : "default";
7008
7219
  const pos = sourceFile.getLineAndColumnAtPos(node.getStart());
7009
7220
  const metadata = this.extractFromConfig(config, exportName, sourceFile.getFilePath(), pos, "class");
7010
7221
  if (metadata) {
@@ -7217,7 +7428,7 @@ var init_device_plugin = __esm({
7217
7428
  });
7218
7429
 
7219
7430
  // src/compiler/plugins/device-trigger.plugin.ts
7220
- import { Node as Node13 } from "ts-morph";
7431
+ import { Node as Node14 } from "ts-morph";
7221
7432
  var DeviceTriggerPlugin;
7222
7433
  var init_device_trigger_plugin = __esm({
7223
7434
  "src/compiler/plugins/device-trigger.plugin.ts"() {
@@ -7336,7 +7547,7 @@ var init_device_trigger_plugin = __esm({
7336
7547
  const classDecl = locateClassDefinition(sourceFile, metadata.exportName);
7337
7548
  if (!classDecl) return void 0;
7338
7549
  const hit = findClassMember(classDecl, "payloadSchema", "property");
7339
- if (!hit || !Node13.isPropertyDeclaration(hit.node)) return void 0;
7550
+ if (!hit || !Node14.isPropertyDeclaration(hit.node)) return void 0;
7340
7551
  const schemaNode = hit.node.getInitializer();
7341
7552
  if (!schemaNode) return void 0;
7342
7553
  try {
@@ -7349,11 +7560,11 @@ var init_device_trigger_plugin = __esm({
7349
7560
  const varDecl = sourceFile.getVariableDeclaration(metadata.exportName);
7350
7561
  if (!varDecl) return void 0;
7351
7562
  const initializer = varDecl.getInitializer();
7352
- if (!initializer || !Node13.isCallExpression(initializer)) return void 0;
7563
+ if (!initializer || !Node14.isCallExpression(initializer)) return void 0;
7353
7564
  const args2 = initializer.getArguments();
7354
7565
  if (args2.length === 0) return void 0;
7355
7566
  const config = args2[0];
7356
- if (!Node13.isObjectLiteralExpression(config)) return void 0;
7567
+ if (!Node14.isObjectLiteralExpression(config)) return void 0;
7357
7568
  if (metadata.metadata.hasPayloadSchema) {
7358
7569
  const schemaNode = extractSchemaProperty(config, "payloadSchema");
7359
7570
  if (schemaNode) {
@@ -7380,10 +7591,10 @@ var init_device_trigger_plugin = __esm({
7380
7591
  });
7381
7592
 
7382
7593
  // src/compiler/utils/primitive-rewrite.ts
7383
- import { readFileSync as readFileSync8 } from "fs";
7384
- import { Node as Node14, Project, ts as ts3 } from "ts-morph";
7594
+ import { readFileSync as readFileSync9 } from "fs";
7595
+ import { Node as Node15, Project, ts as ts3 } from "ts-morph";
7385
7596
  function rewritePrimitiveSource(metadata, opts) {
7386
- const sourceCode = readFileSync8(metadata.sourcePath, "utf-8");
7597
+ const sourceCode = readFileSync9(metadata.sourcePath, "utf-8");
7387
7598
  const localProject = new Project({
7388
7599
  useInMemoryFileSystem: true,
7389
7600
  compilerOptions: {
@@ -7394,13 +7605,13 @@ function rewritePrimitiveSource(metadata, opts) {
7394
7605
  });
7395
7606
  const sf = localProject.createSourceFile(`__rewrite_${metadata.kind}_${metadata.name}.ts`, sourceCode);
7396
7607
  const isPrimitiveCall = /* @__PURE__ */ __name((n) => {
7397
- if (Node14.isNewExpression(n)) {
7608
+ if (Node15.isNewExpression(n)) {
7398
7609
  const callee = n.getExpression();
7399
- return Node14.isIdentifier(callee) && opts.constructorNames.includes(callee.getText());
7610
+ return Node15.isIdentifier(callee) && opts.constructorNames.includes(callee.getText());
7400
7611
  }
7401
- if (Node14.isCallExpression(n)) {
7612
+ if (Node15.isCallExpression(n)) {
7402
7613
  const callee = n.getExpression();
7403
- return Node14.isIdentifier(callee) && opts.defineFunctionName !== void 0 && callee.getText() === opts.defineFunctionName;
7614
+ return Node15.isIdentifier(callee) && opts.defineFunctionName !== void 0 && callee.getText() === opts.defineFunctionName;
7404
7615
  }
7405
7616
  return false;
7406
7617
  }, "isPrimitiveCall");
@@ -7409,7 +7620,7 @@ function rewritePrimitiveSource(metadata, opts) {
7409
7620
  throw new Error(`Primitive call for export "${metadata.exportName}" (kind=${metadata.kind}) not found in ${metadata.sourcePath}`);
7410
7621
  }
7411
7622
  const arg = callNode.getArguments()[0];
7412
- if (!arg || !Node14.isObjectLiteralExpression(arg)) {
7623
+ if (!arg || !Node15.isObjectLiteralExpression(arg)) {
7413
7624
  throw new Error(`Primitive config arg is not an object literal in ${metadata.sourcePath}`);
7414
7625
  }
7415
7626
  const synthesized = opts.buildLiteral(arg, {
@@ -7441,7 +7652,7 @@ function rewriteCrossFileCallsInSourceFile(sf, specs, sdkBaseClassNames) {
7441
7652
  const spec = callNode.spec;
7442
7653
  const node = callNode.node;
7443
7654
  const arg = node.getArguments()[0];
7444
- const objArg = arg && Node14.isObjectLiteralExpression(arg) ? arg : void 0;
7655
+ const objArg = arg && Node15.isObjectLiteralExpression(arg) ? arg : void 0;
7445
7656
  node.replaceWithText(buildBareObjectLiteral(spec, objArg));
7446
7657
  progressed = true;
7447
7658
  }
@@ -7474,18 +7685,18 @@ function stripSdkExtendsClauses(sf, sdkBaseClassNames, aliasMap) {
7474
7685
  const ext = classDecl.getExtends();
7475
7686
  if (!ext) continue;
7476
7687
  const expr = ext.getExpression();
7477
- if (!Node14.isIdentifier(expr)) continue;
7688
+ if (!Node15.isIdentifier(expr)) continue;
7478
7689
  if (matchesSdkClass(expr.getText())) {
7479
7690
  classDecl.removeExtends();
7480
7691
  stripSuperCallsInConstructors(classDecl);
7481
7692
  }
7482
7693
  }
7483
7694
  sf.forEachDescendant((n) => {
7484
- if (!Node14.isClassExpression(n)) return;
7695
+ if (!Node15.isClassExpression(n)) return;
7485
7696
  const ext = n.getExtends();
7486
7697
  if (!ext) return;
7487
7698
  const expr = ext.getExpression();
7488
- if (!Node14.isIdentifier(expr)) return;
7699
+ if (!Node15.isIdentifier(expr)) return;
7489
7700
  if (matchesSdkClass(expr.getText())) {
7490
7701
  n.removeExtends();
7491
7702
  stripSuperCallsInConstructors(n);
@@ -7495,12 +7706,12 @@ function stripSdkExtendsClauses(sf, sdkBaseClassNames, aliasMap) {
7495
7706
  function stripSuperCallsInConstructors(classNode) {
7496
7707
  for (const ctor of classNode.getConstructors()) {
7497
7708
  const body = ctor.getBody();
7498
- if (!body || !Node14.isBlock(body)) continue;
7709
+ if (!body || !Node15.isBlock(body)) continue;
7499
7710
  const toRemove = [];
7500
7711
  for (const stmt of body.getStatements()) {
7501
- if (!Node14.isExpressionStatement(stmt)) continue;
7712
+ if (!Node15.isExpressionStatement(stmt)) continue;
7502
7713
  const expr = stmt.getExpression();
7503
- if (!Node14.isCallExpression(expr)) continue;
7714
+ if (!Node15.isCallExpression(expr)) continue;
7504
7715
  if (expr.getExpression().getKind() !== ts3.SyntaxKind.SuperKeyword) continue;
7505
7716
  toRemove.push(stmt);
7506
7717
  }
@@ -7513,7 +7724,7 @@ function warnRemainingSuperReferences(classNode) {
7513
7724
  classNode.forEachDescendant((n) => {
7514
7725
  if (n.getKind() !== ts3.SyntaxKind.SuperKeyword) return;
7515
7726
  const parent = n.getParent();
7516
- if (parent && Node14.isCallExpression(parent) && parent.getExpression() === n && Node14.isExpressionStatement(parent.getParent())) {
7727
+ if (parent && Node15.isCallExpression(parent) && parent.getExpression() === n && Node15.isExpressionStatement(parent.getParent())) {
7517
7728
  return;
7518
7729
  }
7519
7730
  const pos = sf.getLineAndColumnAtPos(n.getStart());
@@ -7545,7 +7756,7 @@ function buildSdkAliasMap(sf, sdkIdentifiers) {
7545
7756
  progressed = false;
7546
7757
  for (const vd of sf.getVariableDeclarations()) {
7547
7758
  const init = vd.getInitializer();
7548
- if (!init || !Node14.isIdentifier(init)) continue;
7759
+ if (!init || !Node15.isIdentifier(init)) continue;
7549
7760
  const name = vd.getName();
7550
7761
  if (map.has(name)) continue;
7551
7762
  const initText = init.getText();
@@ -7562,18 +7773,18 @@ function findFirstCrossFileSdkCall(sf, specs, aliasMap) {
7562
7773
  let found;
7563
7774
  sf.forEachDescendant((n) => {
7564
7775
  if (found) return;
7565
- if (Node14.isNewExpression(n)) {
7776
+ if (Node15.isNewExpression(n)) {
7566
7777
  const callee = n.getExpression();
7567
- if (!Node14.isIdentifier(callee)) return;
7778
+ if (!Node15.isIdentifier(callee)) return;
7568
7779
  const canonical = aliasMap.get(callee.getText()) ?? callee.getText();
7569
7780
  const spec = specs.find((s) => s.classNames.includes(canonical));
7570
7781
  if (spec) found = {
7571
7782
  node: n,
7572
7783
  spec
7573
7784
  };
7574
- } else if (Node14.isCallExpression(n)) {
7785
+ } else if (Node15.isCallExpression(n)) {
7575
7786
  const callee = n.getExpression();
7576
- if (!Node14.isIdentifier(callee)) return;
7787
+ if (!Node15.isIdentifier(callee)) return;
7577
7788
  const canonical = aliasMap.get(callee.getText()) ?? callee.getText();
7578
7789
  const spec = specs.find((s) => s.defineFunction !== void 0 && s.defineFunction === canonical);
7579
7790
  if (spec) found = {
@@ -7592,10 +7803,10 @@ function buildBareObjectLiteral(spec, arg) {
7592
7803
  const parts = [];
7593
7804
  for (const f of spec.fields) {
7594
7805
  const prop = arg.getProperty(f);
7595
- if (prop && Node14.isPropertyAssignment(prop)) {
7806
+ if (prop && Node15.isPropertyAssignment(prop)) {
7596
7807
  const init = prop.getInitializer();
7597
7808
  if (init) parts.push(`${f}: ${init.getText()}`);
7598
- } else if (prop && Node14.isShorthandPropertyAssignment(prop)) {
7809
+ } else if (prop && Node15.isShorthandPropertyAssignment(prop)) {
7599
7810
  parts.push(`${f}: ${prop.getName()}`);
7600
7811
  }
7601
7812
  }
@@ -7604,10 +7815,10 @@ function buildBareObjectLiteral(spec, arg) {
7604
7815
  function findCallByExportName(sf, metadata, isPrimitiveCall) {
7605
7816
  if (metadata.isDefaultExport) {
7606
7817
  for (const stmt of sf.getStatements()) {
7607
- if (!Node14.isExportAssignment(stmt)) continue;
7818
+ if (!Node15.isExportAssignment(stmt)) continue;
7608
7819
  const expr = stmt.getExpression();
7609
7820
  if (isPrimitiveCall(expr)) return expr;
7610
- if (Node14.isIdentifier(expr)) {
7821
+ if (Node15.isIdentifier(expr)) {
7611
7822
  const varDecl2 = sf.getVariableDeclaration(expr.getText());
7612
7823
  const init2 = varDecl2?.getInitializer();
7613
7824
  if (init2 && isPrimitiveCall(init2)) return init2;
@@ -7630,14 +7841,14 @@ function stripLuaCliImports(sf) {
7630
7841
  }
7631
7842
  function ensureDefaultExport(sf, metadata) {
7632
7843
  if (metadata.isDefaultExport) return;
7633
- const existingDefault = sf.getStatements().find(Node14.isExportAssignment);
7844
+ const existingDefault = sf.getStatements().find(Node15.isExportAssignment);
7634
7845
  if (!existingDefault) {
7635
7846
  sf.addStatements(`
7636
7847
  export default ${metadata.exportName};`);
7637
7848
  return;
7638
7849
  }
7639
7850
  const expr = existingDefault.getExpression();
7640
- const alreadyCorrect = Node14.isIdentifier(expr) && expr.getText() === metadata.exportName;
7851
+ const alreadyCorrect = Node15.isIdentifier(expr) && expr.getText() === metadata.exportName;
7641
7852
  if (!alreadyCorrect) {
7642
7853
  existingDefault.remove();
7643
7854
  sf.addStatements(`
@@ -7646,10 +7857,10 @@ export default ${metadata.exportName};`);
7646
7857
  }
7647
7858
  function getPropertyText(arg, name) {
7648
7859
  const prop = arg.getProperty(name);
7649
- if (prop && Node14.isPropertyAssignment(prop)) {
7860
+ if (prop && Node15.isPropertyAssignment(prop)) {
7650
7861
  return prop.getInitializer()?.getText();
7651
7862
  }
7652
- if (prop && Node14.isShorthandPropertyAssignment(prop)) {
7863
+ if (prop && Node15.isShorthandPropertyAssignment(prop)) {
7653
7864
  return prop.getName();
7654
7865
  }
7655
7866
  return void 0;
@@ -7723,11 +7934,11 @@ var init_cross_file_specs = __esm({
7723
7934
 
7724
7935
  // src/compiler/plugins/voice.plugin.ts
7725
7936
  import fs5 from "fs/promises";
7726
- import { Node as Node15 } from "ts-morph";
7937
+ import { Node as Node16 } from "ts-morph";
7727
7938
  function astObjectToPlain(obj) {
7728
7939
  const result = {};
7729
7940
  for (const prop of obj.getProperties()) {
7730
- if (Node15.isSpreadAssignment(prop)) {
7941
+ if (Node16.isSpreadAssignment(prop)) {
7731
7942
  const expr = prop.getExpression();
7732
7943
  const evaluated = astValueToPlain(expr);
7733
7944
  if (evaluated && typeof evaluated === "object" && !Array.isArray(evaluated)) {
@@ -7735,14 +7946,14 @@ function astObjectToPlain(obj) {
7735
7946
  }
7736
7947
  continue;
7737
7948
  }
7738
- if (Node15.isShorthandPropertyAssignment(prop)) {
7949
+ if (Node16.isShorthandPropertyAssignment(prop)) {
7739
7950
  const key2 = prop.getName();
7740
7951
  if (!key2) continue;
7741
7952
  const v2 = astValueToPlain(prop.getNameNode());
7742
7953
  if (v2 !== void 0) result[key2] = v2;
7743
7954
  continue;
7744
7955
  }
7745
- if (!Node15.isPropertyAssignment(prop)) continue;
7956
+ if (!Node16.isPropertyAssignment(prop)) continue;
7746
7957
  const key = prop.getName();
7747
7958
  if (!key) continue;
7748
7959
  const value = prop.getInitializer();
@@ -7753,16 +7964,16 @@ function astObjectToPlain(obj) {
7753
7964
  return result;
7754
7965
  }
7755
7966
  function astValueToPlain(value) {
7756
- if (Node15.isStringLiteral(value) || Node15.isNoSubstitutionTemplateLiteral(value)) {
7967
+ if (Node16.isStringLiteral(value) || Node16.isNoSubstitutionTemplateLiteral(value)) {
7757
7968
  return value.getLiteralText();
7758
7969
  }
7759
- if (Node15.isNumericLiteral(value)) {
7970
+ if (Node16.isNumericLiteral(value)) {
7760
7971
  return Number(value.getLiteralText());
7761
7972
  }
7762
- if (Node15.isTrueLiteral(value)) return true;
7763
- if (Node15.isFalseLiteral(value)) return false;
7764
- if (Node15.isObjectLiteralExpression(value)) return astObjectToPlain(value);
7765
- if (Node15.isArrayLiteralExpression(value)) {
7973
+ if (Node16.isTrueLiteral(value)) return true;
7974
+ if (Node16.isFalseLiteral(value)) return false;
7975
+ if (Node16.isObjectLiteralExpression(value)) return astObjectToPlain(value);
7976
+ if (Node16.isArrayLiteralExpression(value)) {
7766
7977
  return value.getElements().map((el) => astValueToPlain(el)).filter((x) => x !== void 0);
7767
7978
  }
7768
7979
  return void 0;
@@ -7821,10 +8032,10 @@ function stripKeys(obj, keys) {
7821
8032
  }
7822
8033
  function leftmostIdentifierName(node) {
7823
8034
  let current = node;
7824
- while (Node15.isPropertyAccessExpression(current)) {
8035
+ while (Node16.isPropertyAccessExpression(current)) {
7825
8036
  current = current.getExpression();
7826
8037
  }
7827
- return Node15.isIdentifier(current) ? current.getText() : void 0;
8038
+ return Node16.isIdentifier(current) ? current.getText() : void 0;
7828
8039
  }
7829
8040
  function resolveProviderAlias(node, localName) {
7830
8041
  const sourceFile = node.getSourceFile();
@@ -7850,7 +8061,7 @@ function resolveProviderAlias(node, localName) {
7850
8061
  function extractRealtimeFromNewExpression(newExpr, classExpr, field) {
7851
8062
  if (classExpr.getName() !== "RealtimeModel") return void 0;
7852
8063
  const realtimeNode = classExpr.getExpression();
7853
- if (!Node15.isPropertyAccessExpression(realtimeNode) || realtimeNode.getName() !== "realtime") {
8064
+ if (!Node16.isPropertyAccessExpression(realtimeNode) || realtimeNode.getName() !== "realtime") {
7854
8065
  return void 0;
7855
8066
  }
7856
8067
  if (field !== "llm") {
@@ -7881,7 +8092,7 @@ function extractRealtimeFromNewExpression(newExpr, classExpr, field) {
7881
8092
  }
7882
8093
  const optsArg = newExpr.getArguments()[0];
7883
8094
  let options = {};
7884
- if (optsArg && Node15.isObjectLiteralExpression(optsArg)) {
8095
+ if (optsArg && Node16.isObjectLiteralExpression(optsArg)) {
7885
8096
  options = astObjectToPlain(optsArg);
7886
8097
  }
7887
8098
  return {
@@ -7894,7 +8105,7 @@ function extractRealtimeFromNewExpression(newExpr, classExpr, field) {
7894
8105
  }
7895
8106
  function extractFromNewExpression(newExpr, field) {
7896
8107
  const expr = newExpr.getExpression();
7897
- if (!Node15.isPropertyAccessExpression(expr)) {
8108
+ if (!Node16.isPropertyAccessExpression(expr)) {
7898
8109
  return {
7899
8110
  error: {
7900
8111
  field,
@@ -7924,7 +8135,7 @@ function extractFromNewExpression(newExpr, field) {
7924
8135
  }
7925
8136
  const optsArg = newExpr.getArguments()[0];
7926
8137
  let options = {};
7927
- if (optsArg && Node15.isObjectLiteralExpression(optsArg)) {
8138
+ if (optsArg && Node16.isObjectLiteralExpression(optsArg)) {
7928
8139
  options = astObjectToPlain(optsArg);
7929
8140
  }
7930
8141
  if (moduleName === "inference") {
@@ -7972,7 +8183,7 @@ function extractFromNewExpression(newExpr, field) {
7972
8183
  }
7973
8184
  function unwrapType(node) {
7974
8185
  let current = node;
7975
- while (Node15.isAsExpression(current) || Node15.isSatisfiesExpression(current) || Node15.isParenthesizedExpression(current)) {
8186
+ while (Node16.isAsExpression(current) || Node16.isSatisfiesExpression(current) || Node16.isParenthesizedExpression(current)) {
7976
8187
  const inner = current.getExpression?.();
7977
8188
  if (!inner) break;
7978
8189
  current = inner;
@@ -7981,11 +8192,11 @@ function unwrapType(node) {
7981
8192
  }
7982
8193
  function extractModelField(config, field) {
7983
8194
  const prop = config.getProperty(field);
7984
- if (!prop || !Node15.isPropertyAssignment(prop)) return {};
8195
+ if (!prop || !Node16.isPropertyAssignment(prop)) return {};
7985
8196
  const initializer = prop.getInitializer();
7986
8197
  if (!initializer) return {};
7987
8198
  const value = unwrapType(initializer);
7988
- if (Node15.isStringLiteral(value) || Node15.isNoSubstitutionTemplateLiteral(value)) {
8199
+ if (Node16.isStringLiteral(value) || Node16.isNoSubstitutionTemplateLiteral(value)) {
7989
8200
  const text = value.getLiteralText();
7990
8201
  if (!text) {
7991
8202
  return {
@@ -7997,7 +8208,7 @@ function extractModelField(config, field) {
7997
8208
  }
7998
8209
  return parseDescriptor(text, field);
7999
8210
  }
8000
- if (Node15.isObjectLiteralExpression(value)) {
8211
+ if (Node16.isObjectLiteralExpression(value)) {
8001
8212
  if (field !== "tts") {
8002
8213
  return {
8003
8214
  error: {
@@ -8024,7 +8235,7 @@ function extractModelField(config, field) {
8024
8235
  model: out
8025
8236
  };
8026
8237
  }
8027
- if (Node15.isNewExpression(value)) {
8238
+ if (Node16.isNewExpression(value)) {
8028
8239
  return extractFromNewExpression(value, field);
8029
8240
  }
8030
8241
  return {
@@ -8037,22 +8248,22 @@ function extractModelField(config, field) {
8037
8248
  function hasFunctionProperty(config, propertyName) {
8038
8249
  const prop = config.getProperty(propertyName);
8039
8250
  if (!prop) return false;
8040
- if (Node15.isMethodDeclaration(prop)) return true;
8041
- if (!Node15.isPropertyAssignment(prop)) return false;
8251
+ if (Node16.isMethodDeclaration(prop)) return true;
8252
+ if (!Node16.isPropertyAssignment(prop)) return false;
8042
8253
  const value = prop.getInitializer();
8043
8254
  if (!value) return false;
8044
- if (Node15.isArrowFunction(value) || Node15.isFunctionExpression(value)) return true;
8045
- if (Node15.isIdentifier(value)) return true;
8255
+ if (Node16.isArrowFunction(value) || Node16.isFunctionExpression(value)) return true;
8256
+ if (Node16.isIdentifier(value)) return true;
8046
8257
  return false;
8047
8258
  }
8048
8259
  function hasArrayProperty(config, propertyName) {
8049
8260
  const prop = config.getProperty(propertyName);
8050
- if (!prop || !Node15.isPropertyAssignment(prop)) return false;
8261
+ if (!prop || !Node16.isPropertyAssignment(prop)) return false;
8051
8262
  const value = prop.getInitializer();
8052
8263
  if (!value) return false;
8053
- if (Node15.isArrayLiteralExpression(value)) return value.getElements().length > 0;
8054
- if (Node15.isNullLiteral(value)) return false;
8055
- if (Node15.isIdentifier(value) && value.getText() === "undefined") return false;
8264
+ if (Node16.isArrayLiteralExpression(value)) return value.getElements().length > 0;
8265
+ if (Node16.isNullLiteral(value)) return false;
8266
+ if (Node16.isIdentifier(value) && value.getText() === "undefined") return false;
8056
8267
  return true;
8057
8268
  }
8058
8269
  function normalizePronunciations(raw) {
@@ -8155,6 +8366,7 @@ var init_voice_plugin = __esm({
8155
8366
  const persistTranscript = extractBooleanProperty(config, "persistTranscript");
8156
8367
  const onToolFailureSay = extractStringProperty(config, "onToolFailureSay");
8157
8368
  const volume = extractNumberProperty(config, "volume");
8369
+ const excludeTools = extractStringArrayProperty(config, "excludeTools");
8158
8370
  const interruption = extractObjectProperty(config, "interruption");
8159
8371
  const pronunciationsRaw = extractObjectProperty(config, "pronunciations");
8160
8372
  const { map: pronunciations, droppedKeys: droppedPronunciationKeys } = normalizePronunciations(pronunciationsRaw);
@@ -8191,6 +8403,7 @@ var init_voice_plugin = __esm({
8191
8403
  krispEnabled,
8192
8404
  persistTranscript,
8193
8405
  onToolFailureSay,
8406
+ excludeTools,
8194
8407
  volume,
8195
8408
  pronunciations,
8196
8409
  backgroundAudio,
@@ -8251,6 +8464,7 @@ var init_voice_plugin = __esm({
8251
8464
  if (fields.krispEnabled !== void 0) candidate.krispEnabled = fields.krispEnabled;
8252
8465
  if (fields.persistTranscript !== void 0) candidate.persistTranscript = fields.persistTranscript;
8253
8466
  if (fields.onToolFailureSay !== void 0) candidate.onToolFailureSay = fields.onToolFailureSay;
8467
+ if (fields.excludeTools !== void 0) candidate.excludeTools = fields.excludeTools;
8254
8468
  if (fields.volume !== void 0) candidate.volume = fields.volume;
8255
8469
  if (fields.pronunciations !== void 0) candidate.pronunciations = fields.pronunciations;
8256
8470
  if (fields.backgroundAudio !== void 0) candidate.backgroundAudio = fields.backgroundAudio;
@@ -8406,6 +8620,7 @@ var init_voice_plugin = __esm({
8406
8620
  pronunciations: fields.pronunciations,
8407
8621
  persistTranscript: fields.persistTranscript,
8408
8622
  onToolFailureSay: fields.onToolFailureSay,
8623
+ excludeTools: fields.excludeTools,
8409
8624
  interruption: fields.interruption
8410
8625
  };
8411
8626
  return entry;
@@ -8428,6 +8643,7 @@ var init_registry = __esm({
8428
8643
  init_tool_plugin();
8429
8644
  init_job_plugin();
8430
8645
  init_webhook_plugin();
8646
+ init_trigger_plugin();
8431
8647
  init_preprocessor_plugin();
8432
8648
  init_postprocessor_plugin();
8433
8649
  init_mcp_server_plugin();
@@ -8445,6 +8661,7 @@ var init_registry = __esm({
8445
8661
  this.register(new ToolPlugin());
8446
8662
  this.register(new JobPlugin());
8447
8663
  this.register(new WebhookPlugin());
8664
+ this.register(new TriggerPlugin());
8448
8665
  this.register(new PreProcessorPlugin());
8449
8666
  this.register(new PostProcessorPlugin());
8450
8667
  this.register(new MCPServerPlugin());
@@ -8727,7 +8944,7 @@ export { ${exportName} as __lua_target__ };
8727
8944
  });
8728
8945
 
8729
8946
  // src/compiler/agent-traverser.ts
8730
- import { Project as Project2, Node as Node16 } from "ts-morph";
8947
+ import { Project as Project2, Node as Node17 } from "ts-morph";
8731
8948
  import path6 from "path";
8732
8949
  import fs7 from "fs";
8733
8950
  var PRIMITIVE_TYPES, AgentTraverser;
@@ -8749,6 +8966,10 @@ var init_agent_traverser = __esm({
8749
8966
  kind: "webhook",
8750
8967
  configProperty: "webhooks"
8751
8968
  },
8969
+ {
8970
+ kind: "trigger",
8971
+ configProperty: "triggers"
8972
+ },
8752
8973
  {
8753
8974
  kind: "job",
8754
8975
  configProperty: "jobs"
@@ -8950,7 +9171,7 @@ var init_agent_traverser = __esm({
8950
9171
  */
8951
9172
  extractArrayRefs(config, propName) {
8952
9173
  const prop = config.getProperty(propName);
8953
- if (!prop || !Node16.isPropertyAssignment(prop)) return [];
9174
+ if (!prop || !Node17.isPropertyAssignment(prop)) return [];
8954
9175
  const value = prop.getInitializer();
8955
9176
  if (!value) return [];
8956
9177
  const ctx = {
@@ -9035,7 +9256,7 @@ var init_agent_traverser = __esm({
9035
9256
  for (const assign of file.getExportAssignments()) {
9036
9257
  if (assign.isExportEquals()) continue;
9037
9258
  const expr = assign.getExpression();
9038
- if (!Node16.isIdentifier(expr)) continue;
9259
+ if (!Node17.isIdentifier(expr)) continue;
9039
9260
  const targetName = expr.getText();
9040
9261
  defaultMatch = detected.find((d) => d.exportName === targetName);
9041
9262
  if (defaultMatch) break;
@@ -9798,7 +10019,7 @@ var init_file_discovery = __esm({
9798
10019
  });
9799
10020
 
9800
10021
  // src/compiler/source-writer.ts
9801
- import { Project as Project4, Node as Node17 } from "ts-morph";
10022
+ import { Project as Project4, Node as Node18 } from "ts-morph";
9802
10023
  import fs11 from "fs";
9803
10024
  import path10 from "path";
9804
10025
  function resolveEntryPath(options) {
@@ -9847,14 +10068,14 @@ function updateAgentConfig(updates, options) {
9847
10068
  const sourceFile = project.addSourceFileAtPath(indexPath);
9848
10069
  let updated = false;
9849
10070
  sourceFile.forEachDescendant((node) => {
9850
- if (Node17.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
10071
+ if (Node18.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
9851
10072
  const args2 = node.getArguments();
9852
- if (args2.length > 0 && Node17.isObjectLiteralExpression(args2[0])) {
10073
+ if (args2.length > 0 && Node18.isObjectLiteralExpression(args2[0])) {
9853
10074
  const configObj = args2[0];
9854
10075
  const replacedKeys = /* @__PURE__ */ new Set();
9855
10076
  let lastReplacedIndex = -1;
9856
10077
  configObj.getProperties().forEach((prop, index) => {
9857
- if (Node17.isPropertyAssignment(prop)) {
10078
+ if (Node18.isPropertyAssignment(prop)) {
9858
10079
  const propName = prop.getName();
9859
10080
  if (Object.prototype.hasOwnProperty.call(filteredUpdates, propName)) {
9860
10081
  const newValue = filteredUpdates[propName];
@@ -9917,14 +10138,14 @@ function removeAgentConfigProperty(propertyName, options) {
9917
10138
  let foundConstructor = false;
9918
10139
  let removed = false;
9919
10140
  sourceFile.forEachDescendant((node) => {
9920
- if (Node17.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
10141
+ if (Node18.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
9921
10142
  const args2 = node.getArguments();
9922
- if (args2.length > 0 && Node17.isObjectLiteralExpression(args2[0])) {
10143
+ if (args2.length > 0 && Node18.isObjectLiteralExpression(args2[0])) {
9923
10144
  foundConstructor = true;
9924
10145
  const configObj = args2[0];
9925
10146
  const props = configObj.getProperties();
9926
10147
  for (const prop of props) {
9927
- if (Node17.isPropertyAssignment(prop) && prop.getName() === propertyName) {
10148
+ if (Node18.isPropertyAssignment(prop) && prop.getName() === propertyName) {
9928
10149
  prop.remove();
9929
10150
  removed = true;
9930
10151
  break;
@@ -12160,6 +12381,9 @@ var init_agents_api_service = __esm({
12160
12381
  } : {},
12161
12382
  ...body.threadId !== void 0 ? {
12162
12383
  threadId: body.threadId
12384
+ } : {},
12385
+ ...body.webhookPayload !== void 0 ? {
12386
+ webhookPayload: body.webhookPayload
12163
12387
  } : {}
12164
12388
  };
12165
12389
  }
@@ -12542,6 +12766,30 @@ var init_voice_api_service = __esm({
12542
12766
  });
12543
12767
  }
12544
12768
  /**
12769
+ * Create a voice room + client access token for a custom frontend
12770
+ * (standard livekit-client). The session runs under a synthetic identity;
12771
+ * pass `userId` to scope conversation memory + transcript to your own end
12772
+ * user. Wraps `POST /developer/voice/:agentId/session`.
12773
+ */
12774
+ async createSession(input = {}) {
12775
+ return this.httpPost(`/developer/voice/${this.agentId}/session`, input, {
12776
+ Authorization: `Bearer ${this.apiKey}`
12777
+ });
12778
+ }
12779
+ /**
12780
+ * Sandbox helper: throws on non-success and returns the unwrapped output.
12781
+ */
12782
+ async createSessionForSandbox(input = {}) {
12783
+ const result = await this.createSession(input);
12784
+ if (!result.success) {
12785
+ throw new Error(result.error?.message || "Voice session creation failed");
12786
+ }
12787
+ if (!result.data) {
12788
+ throw new Error("Voice session creation failed: empty response");
12789
+ }
12790
+ return result.data;
12791
+ }
12792
+ /**
12545
12793
  * Sandbox helper: throws on non-success and returns the unwrapped output.
12546
12794
  * Mirrors the shape `AgentsApiService.invokeForSandbox` exposes so the
12547
12795
  * `Voice` namespace in `api-exports.ts` stays a one-liner.
@@ -12560,6 +12808,79 @@ var init_voice_api_service = __esm({
12560
12808
  }
12561
12809
  });
12562
12810
 
12811
+ // src/api/channels-send.api.service.ts
12812
+ var ChannelsSendApiService;
12813
+ var init_channels_send_api_service = __esm({
12814
+ "src/api/channels-send.api.service.ts"() {
12815
+ "use strict";
12816
+ init_http_client();
12817
+ ChannelsSendApiService = class extends HttpClient {
12818
+ static {
12819
+ __name(this, "ChannelsSendApiService");
12820
+ }
12821
+ apiKey;
12822
+ agentId;
12823
+ constructor(baseUrl, apiKey, agentId) {
12824
+ super(baseUrl), this.apiKey = apiKey, this.agentId = agentId;
12825
+ }
12826
+ /** POST /developer/agents/:agentId/channels/send */
12827
+ async send(input) {
12828
+ return this.httpPost(`/developer/agents/${this.agentId}/channels/send`, input, {
12829
+ Authorization: `Bearer ${this.apiKey}`
12830
+ });
12831
+ }
12832
+ /** POST /developer/agents/:agentId/channels/whatsapp/template */
12833
+ async sendWhatsAppTemplate(input) {
12834
+ return this.httpPost(`/developer/agents/${this.agentId}/channels/whatsapp/template`, input, {
12835
+ Authorization: `Bearer ${this.apiKey}`
12836
+ });
12837
+ }
12838
+ /** POST /developer/agents/:agentId/channels/email/send */
12839
+ async sendEmail(input) {
12840
+ return this.httpPost(`/developer/agents/${this.agentId}/channels/email/send`, input, {
12841
+ Authorization: `Bearer ${this.apiKey}`
12842
+ });
12843
+ }
12844
+ /**
12845
+ * Sandbox helper: throws on non-success, returns unwrapped output.
12846
+ * A 200 with `persisted: false` is NOT an error — it passes through.
12847
+ */
12848
+ async sendForSandbox(input) {
12849
+ const result = await this.send(input);
12850
+ if (!result.success) {
12851
+ throw new Error(result.error?.message || "Channel send failed");
12852
+ }
12853
+ if (!result.data) {
12854
+ throw new Error("Channel send failed: empty response");
12855
+ }
12856
+ return result.data;
12857
+ }
12858
+ /** Sandbox helper for WhatsApp template sends. */
12859
+ async sendWhatsAppTemplateForSandbox(input) {
12860
+ const result = await this.sendWhatsAppTemplate(input);
12861
+ if (!result.success) {
12862
+ throw new Error(result.error?.message || "WhatsApp template send failed");
12863
+ }
12864
+ if (!result.data) {
12865
+ throw new Error("WhatsApp template send failed: empty response");
12866
+ }
12867
+ return result.data;
12868
+ }
12869
+ /** Sandbox helper for email sends. */
12870
+ async sendEmailForSandbox(input) {
12871
+ const result = await this.sendEmail(input);
12872
+ if (!result.success) {
12873
+ throw new Error(result.error?.message || "Email send failed");
12874
+ }
12875
+ if (!result.data) {
12876
+ throw new Error("Email send failed: empty response");
12877
+ }
12878
+ return result.data;
12879
+ }
12880
+ };
12881
+ }
12882
+ });
12883
+
12563
12884
  // src/api/device.api.service.ts
12564
12885
  var device_api_service_exports = {};
12565
12886
  __export(device_api_service_exports, {
@@ -12652,6 +12973,7 @@ __export(lazy_instances_exports, {
12652
12973
  getAiInstance: () => getAiInstance,
12653
12974
  getBasketsInstance: () => getBasketsInstance,
12654
12975
  getCdnInstance: () => getCdnInstance,
12976
+ getChannelsSendInstance: () => getChannelsSendInstance,
12655
12977
  getDataInstance: () => getDataInstance,
12656
12978
  getDeveloperInstance: () => getDeveloperInstance,
12657
12979
  getDeviceInstance: () => getDeviceInstance,
@@ -12762,6 +13084,13 @@ async function getVoiceInstance() {
12762
13084
  }
12763
13085
  return _voiceInstance;
12764
13086
  }
13087
+ async function getChannelsSendInstance() {
13088
+ if (!_channelsSendInstance) {
13089
+ const creds = await getCredentials();
13090
+ _channelsSendInstance = new ChannelsSendApiService(BASE_URLS.API, creds.apiKey, creds.agentId);
13091
+ }
13092
+ return _channelsSendInstance;
13093
+ }
12765
13094
  function clearAllInstances() {
12766
13095
  _userInstance = null;
12767
13096
  _dataInstance = null;
@@ -12776,8 +13105,9 @@ function clearAllInstances() {
12776
13105
  _cdnInstance = null;
12777
13106
  _developerInstance = null;
12778
13107
  _voiceInstance = null;
13108
+ _channelsSendInstance = null;
12779
13109
  }
12780
- var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _deviceInstance;
13110
+ var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _channelsSendInstance, _deviceInstance;
12781
13111
  var init_lazy_instances = __esm({
12782
13112
  "src/api/lazy-instances.ts"() {
12783
13113
  "use strict";
@@ -12796,6 +13126,7 @@ var init_lazy_instances = __esm({
12796
13126
  init_cdn_api_service();
12797
13127
  init_developer_api_service();
12798
13128
  init_voice_api_service();
13129
+ init_channels_send_api_service();
12799
13130
  _userInstance = null;
12800
13131
  _dataInstance = null;
12801
13132
  _productsInstance = null;
@@ -12809,6 +13140,7 @@ var init_lazy_instances = __esm({
12809
13140
  _cdnInstance = null;
12810
13141
  _developerInstance = null;
12811
13142
  _voiceInstance = null;
13143
+ _channelsSendInstance = null;
12812
13144
  __name(getUserInstance, "getUserInstance");
12813
13145
  __name(getDataInstance, "getDataInstance");
12814
13146
  __name(getProductsInstance, "getProductsInstance");
@@ -12824,6 +13156,7 @@ var init_lazy_instances = __esm({
12824
13156
  __name(getDeviceInstance, "getDeviceInstance");
12825
13157
  __name(getDeveloperInstance, "getDeveloperInstance");
12826
13158
  __name(getVoiceInstance, "getVoiceInstance");
13159
+ __name(getChannelsSendInstance, "getChannelsSendInstance");
12827
13160
  __name(clearAllInstances, "clearAllInstances");
12828
13161
  }
12829
13162
  });
@@ -13858,13 +14191,164 @@ __name(configureCommand, "configureCommand");
13858
14191
  init_auth();
13859
14192
  init_command_utils();
13860
14193
  init_cli();
13861
- import inquirer3 from "inquirer";
14194
+ import inquirer4 from "inquirer";
14195
+ import { writeFileSync as writeFileSync7, existsSync as existsSync8 } from "fs";
14196
+ import { join as join7 } from "path";
13862
14197
 
13863
- // src/utils/init-prompts.ts
14198
+ // src/utils/prompt-handler.ts
14199
+ init_cli();
13864
14200
  import inquirer2 from "inquirer";
14201
+ async function safePrompt(questions) {
14202
+ if (isCiModeEnabled()) {
14203
+ throw new Error("Interactive prompt required but --ci flag is set. Provide all required flags or arguments.");
14204
+ }
14205
+ if (!process.stdin.isTTY && !isCiModeEnabled()) {
14206
+ console.warn("\u26A0\uFE0F Warning: stdin is not a TTY. Interactive prompts may not work correctly.");
14207
+ console.warn("\u{1F4A1} Tip: Use --ci flag in CI/CD environments to fail loudly on missing required flags.");
14208
+ }
14209
+ try {
14210
+ await new Promise((resolve6) => setTimeout(resolve6, 10));
14211
+ const answers = await inquirer2.prompt(questions);
14212
+ return answers;
14213
+ } catch (error) {
14214
+ if (error.name === "ExitPromptError" || error.message?.includes("SIGINT")) {
14215
+ process.exit(0);
14216
+ }
14217
+ throw error;
14218
+ }
14219
+ }
14220
+ __name(safePrompt, "safePrompt");
14221
+ async function confirmAction(message) {
14222
+ const answer = await safePrompt([
14223
+ {
14224
+ type: "confirm",
14225
+ name: "confirmed",
14226
+ message,
14227
+ default: false
14228
+ }
14229
+ ]);
14230
+ return answer?.confirmed ?? false;
14231
+ }
14232
+ __name(confirmAction, "confirmAction");
14233
+
14234
+ // src/utils/governance-scaffold.ts
14235
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync5 } from "fs";
14236
+ import { join as join4 } from "path";
14237
+ function generateGovernanceFile(setup) {
14238
+ if (setup.mode === "api") {
14239
+ return `/**
14240
+ * Governance Policy (API mode)
14241
+ * Enforcement is handled remotely via the Governance Cloud.
14242
+ * Import this into your LuaAgent config.
14243
+ *
14244
+ * The API key is resolved on the platform at runtime from the
14245
+ * GOVERNANCE_API_KEY env var. Never put the raw key in source.
14246
+ */
14247
+
14248
+ export const governance = {
14249
+ mode: 'api' as const,
14250
+ serverUrl: process.env.GOVERNANCE_API_URL ?? '${setup.serverUrl}',
14251
+ };
14252
+ `;
14253
+ }
14254
+ const ruleLines = [];
14255
+ if (setup.blockTools && setup.blockTools.length > 0) {
14256
+ const list = setup.blockTools.map((t) => `'${t}'`).join(", ");
14257
+ ruleLines.push(` blockTools: [${list}],`);
14258
+ }
14259
+ if (setup.requireApproval && setup.requireApproval.length > 0) {
14260
+ const list = setup.requireApproval.map((t) => `'${t}'`).join(", ");
14261
+ ruleLines.push(` requireApproval: [${list}],`);
14262
+ }
14263
+ if (setup.tokenLimit && setup.tokenLimit > 0) {
14264
+ ruleLines.push(` tokenBudget: ${setup.tokenLimit},`);
14265
+ }
14266
+ return `/**
14267
+ * Governance Policy (SDK mode)
14268
+ * Policies are enforced locally at the platform level.
14269
+ * Import this into your LuaAgent config.
14270
+ */
14271
+
14272
+ export const governance = {
14273
+ mode: 'sdk' as const,
14274
+ rules: {
14275
+ ${ruleLines.join("\n")}
14276
+ },
14277
+ };
14278
+ `;
14279
+ }
14280
+ __name(generateGovernanceFile, "generateGovernanceFile");
14281
+ function generateGovernanceFileFromConfig(config) {
14282
+ if (config.mode === "api") {
14283
+ return generateGovernanceFile({
14284
+ mode: "api",
14285
+ serverUrl: config.serverUrl ?? "https://api.heygovernance.ai"
14286
+ });
14287
+ }
14288
+ const lines = [
14289
+ ` mode: 'sdk' as const,`
14290
+ ];
14291
+ if (config.preset) lines.push(` preset: ${JSON.stringify(config.preset)} as const,`);
14292
+ if (config.injection) lines.push(` injection: ${JSON.stringify(config.injection)},`);
14293
+ if (config.rules && Object.keys(config.rules).length > 0) {
14294
+ lines.push(` rules: ${JSON.stringify(config.rules)},`);
14295
+ }
14296
+ return `/**
14297
+ * Governance Policy (pulled from the server)
14298
+ * Reflects the governance currently enforced for this agent \u2014 e.g. an org-set baseline.
14299
+ * Edit and \`lua push\` to change it, or \`lua governance remove\` to clear it.
14300
+ */
14301
+
14302
+ export const governance = {
14303
+ ${lines.join("\n")}
14304
+ };
14305
+ `;
14306
+ }
14307
+ __name(generateGovernanceFileFromConfig, "generateGovernanceFileFromConfig");
14308
+ function writeGovernanceFileFromConfig(config, projectRoot = process.cwd()) {
14309
+ try {
14310
+ const srcDir = join4(projectRoot, "src");
14311
+ const targetDir = existsSync5(srcDir) ? srcDir : projectRoot;
14312
+ writeFileSync5(join4(targetDir, "governance.ts"), generateGovernanceFileFromConfig(config), "utf-8");
14313
+ injectGovernanceIntoAgent(join4(targetDir, "index.ts"));
14314
+ return true;
14315
+ } catch {
14316
+ return false;
14317
+ }
14318
+ }
14319
+ __name(writeGovernanceFileFromConfig, "writeGovernanceFileFromConfig");
14320
+ function injectGovernanceIntoAgent(agentSourcePath) {
14321
+ if (!existsSync5(agentSourcePath)) return false;
14322
+ let src = readFileSync6(agentSourcePath, "utf-8");
14323
+ const hasImport = /from\s+['"]\.\/governance['"]/.test(src);
14324
+ const hasField = /^\s*governance\s*[,:]/m.test(src);
14325
+ if (hasImport && hasField) return true;
14326
+ if (!hasImport) {
14327
+ if (/import\s+\{[^}]*\}\s+from\s+['"]lua-cli['"];?/.test(src)) {
14328
+ src = src.replace(/(import\s+\{[^}]*\}\s+from\s+['"]lua-cli['"];?)/, `$1
14329
+ import { governance } from './governance';`);
14330
+ } else {
14331
+ src = `import { governance } from './governance';
14332
+ ${src}`;
14333
+ }
14334
+ }
14335
+ if (!hasField) {
14336
+ if (!/new\s+LuaAgent\s*\(\s*\{/.test(src)) {
14337
+ return false;
14338
+ }
14339
+ src = src.replace(/(new\s+LuaAgent\s*\(\s*\{)/, `$1
14340
+ governance,`);
14341
+ }
14342
+ writeFileSync5(agentSourcePath, src, "utf-8");
14343
+ return true;
14344
+ }
14345
+ __name(injectGovernanceIntoAgent, "injectGovernanceIntoAgent");
14346
+
14347
+ // src/utils/init-prompts.ts
14348
+ import inquirer3 from "inquirer";
13865
14349
  import chalk from "chalk";
13866
14350
  async function promptAgentChoice() {
13867
- const { agentChoice } = await inquirer2.prompt([
14351
+ const { agentChoice } = await inquirer3.prompt([
13868
14352
  {
13869
14353
  type: "list",
13870
14354
  name: "agentChoice",
@@ -13893,7 +14377,7 @@ async function promptOrganizationSelection(orgs) {
13893
14377
  name: org.registeredName || org.name || "Unknown Organization",
13894
14378
  value: org
13895
14379
  }));
13896
- const { selectedOrg } = await inquirer2.prompt([
14380
+ const { selectedOrg } = await inquirer3.prompt([
13897
14381
  {
13898
14382
  type: "list",
13899
14383
  name: "selectedOrg",
@@ -13912,7 +14396,7 @@ async function promptAgentSelection(org) {
13912
14396
  name: agent.name,
13913
14397
  value: agent
13914
14398
  }));
13915
- const { selectedAgent } = await inquirer2.prompt([
14399
+ const { selectedAgent } = await inquirer3.prompt([
13916
14400
  {
13917
14401
  type: "list",
13918
14402
  name: "selectedAgent",
@@ -13926,7 +14410,7 @@ __name(promptAgentSelection, "promptAgentSelection");
13926
14410
  async function promptMetadataCollection(requiredFields) {
13927
14411
  const metadata = {};
13928
14412
  for (const field of requiredFields) {
13929
- const { [field]: value } = await inquirer2.prompt([
14413
+ const { [field]: value } = await inquirer3.prompt([
13930
14414
  {
13931
14415
  type: "input",
13932
14416
  name: field,
@@ -13940,7 +14424,7 @@ async function promptMetadataCollection(requiredFields) {
13940
14424
  }
13941
14425
  __name(promptMetadataCollection, "promptMetadataCollection");
13942
14426
  async function promptAgentName() {
13943
- const { agentName } = await inquirer2.prompt([
14427
+ const { agentName } = await inquirer3.prompt([
13944
14428
  {
13945
14429
  type: "input",
13946
14430
  name: "agentName",
@@ -13967,7 +14451,7 @@ async function promptModelSelection(models) {
13967
14451
  ];
13968
14452
  for (const provider of providers) {
13969
14453
  const providerModels = models.filter((m) => m.provider === provider);
13970
- choices.push(new inquirer2.Separator(` \u2500\u2500 ${provider} \u2500\u2500`));
14454
+ choices.push(new inquirer3.Separator(` \u2500\u2500 ${provider} \u2500\u2500`));
13971
14455
  for (const m of providerModels) {
13972
14456
  choices.push({
13973
14457
  name: `${chalk.bold(m.code)} ${chalk.gray(m.description)}`,
@@ -13976,7 +14460,7 @@ async function promptModelSelection(models) {
13976
14460
  });
13977
14461
  }
13978
14462
  }
13979
- const { selectedModel } = await inquirer2.prompt([
14463
+ const { selectedModel } = await inquirer3.prompt([
13980
14464
  {
13981
14465
  type: "list",
13982
14466
  name: "selectedModel",
@@ -14009,7 +14493,7 @@ __name(displayPersonaInstructions, "displayPersonaInstructions");
14009
14493
  async function promptDuplicateOptions(sourceOrg, allOrgs, sourceAgentName) {
14010
14494
  let targetOrg = sourceOrg;
14011
14495
  if (allOrgs.length > 1) {
14012
- const { sameOrg } = await inquirer2.prompt([
14496
+ const { sameOrg } = await inquirer3.prompt([
14013
14497
  {
14014
14498
  type: "list",
14015
14499
  name: "sameOrg",
@@ -14033,7 +14517,7 @@ async function promptDuplicateOptions(sourceOrg, allOrgs, sourceAgentName) {
14033
14517
  }
14034
14518
  }
14035
14519
  const defaultName = `${sourceAgentName} (Copy)`;
14036
- const { newName } = await inquirer2.prompt([
14520
+ const { newName } = await inquirer3.prompt([
14037
14521
  {
14038
14522
  type: "input",
14039
14523
  name: "newName",
@@ -14042,7 +14526,7 @@ async function promptDuplicateOptions(sourceOrg, allOrgs, sourceAgentName) {
14042
14526
  validate: /* @__PURE__ */ __name((input) => input.trim().length > 0 || "Name is required", "validate")
14043
14527
  }
14044
14528
  ]);
14045
- const { includedBuckets } = await inquirer2.prompt([
14529
+ const { includedBuckets } = await inquirer3.prompt([
14046
14530
  {
14047
14531
  type: "checkbox",
14048
14532
  name: "includedBuckets",
@@ -14086,7 +14570,7 @@ async function promptDuplicateOptions(sourceOrg, allOrgs, sourceAgentName) {
14086
14570
  console.log(chalk.white(` Including: ${includedBuckets.length > 0 ? includedBuckets.join(", ") : "core agent definition only"}`));
14087
14571
  console.log(chalk.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
14088
14572
  console.log("");
14089
- const { confirmed } = await inquirer2.prompt([
14573
+ const { confirmed } = await inquirer3.prompt([
14090
14574
  {
14091
14575
  type: "confirm",
14092
14576
  name: "confirmed",
@@ -14135,9 +14619,13 @@ var AgentApi = class extends HttpClient {
14135
14619
  * @param provider - Optional provider filter
14136
14620
  * @returns Promise resolving to an ApiResponse containing an array of ApprovedModel objects
14137
14621
  */
14138
- async getApprovedModels(provider) {
14139
- const query = provider ? `?provider=${encodeURIComponent(provider)}` : "";
14140
- return this.httpGet(`/agents/self-serve/models${query}`, {
14622
+ async getApprovedModels(provider, agentId, orgId) {
14623
+ const params = new URLSearchParams();
14624
+ if (provider) params.set("provider", provider);
14625
+ if (agentId) params.set("agentId", agentId);
14626
+ if (orgId) params.set("orgId", orgId);
14627
+ const qs = params.toString();
14628
+ return this.httpGet(`/agents/self-serve/models${qs ? `?${qs}` : ""}`, {
14141
14629
  Authorization: `Bearer ${this.apiKey}`
14142
14630
  });
14143
14631
  }
@@ -14272,8 +14760,8 @@ var AgentApi = class extends HttpClient {
14272
14760
  * });
14273
14761
  */
14274
14762
  async updateAgentFeature(agentId, featureData) {
14275
- if (featureData.active === void 0 && featureData.featureContext === void 0) {
14276
- throw new Error('At least one of "active" or "featureContext" must be provided');
14763
+ if (featureData.active === void 0 && featureData.featureContext === void 0 && featureData.config === void 0) {
14764
+ throw new Error('At least one of "active", "featureContext", or "config" must be provided');
14277
14765
  }
14278
14766
  return this.httpPut(`/admin/agents/${agentId}/features`, featureData, {
14279
14767
  Authorization: `Bearer ${this.apiKey}`
@@ -14408,20 +14896,24 @@ async function fetchExistingAgentDetails(apiKey, agentId) {
14408
14896
  return fetchAgentDetails(agentApi, agentId);
14409
14897
  }
14410
14898
  __name(fetchExistingAgentDetails, "fetchExistingAgentDetails");
14411
- async function fetchApprovedModels(apiKey) {
14899
+ async function fetchApprovedModels(apiKey, agentId, orgId) {
14412
14900
  try {
14413
14901
  const agentApi = new AgentApi(BASE_URLS.API, apiKey);
14414
- const result = await agentApi.getApprovedModels();
14415
- return result.success && result.data ? result.data : [];
14902
+ const result = await agentApi.getApprovedModels(void 0, agentId, orgId);
14903
+ if (!result.success) return null;
14904
+ return result.data ?? [];
14416
14905
  } catch {
14417
- return [];
14906
+ return null;
14418
14907
  }
14419
14908
  }
14420
14909
  __name(fetchApprovedModels, "fetchApprovedModels");
14421
14910
  function validateModelCode(models, modelCode) {
14422
- if (models.length === 0) {
14911
+ if (models === null) {
14423
14912
  return modelCode;
14424
14913
  }
14914
+ if (models.length === 0) {
14915
+ throw new Error("No models are currently available. If your organization restricts models, an admin may need to review its excluded-models list.");
14916
+ }
14425
14917
  const match = models.find((m) => m.code === modelCode);
14426
14918
  if (!match) {
14427
14919
  const available = models.map((m) => ` ${m.code} (${m.description})`).join("\n");
@@ -15872,6 +16364,14 @@ var AgentHandler = class {
15872
16364
  pullModel(serverModel) {
15873
16365
  return setAgentModel(serverModel);
15874
16366
  }
16367
+ /**
16368
+ * Pull a server-resolved governance config into a local `governance.ts` and wire the import.
16369
+ * This is what lets an org-set baseline (or any server governance) show up as code — and it
16370
+ * round-trips on the next push. Returns true if the file was written.
16371
+ */
16372
+ pullGovernance(serverGovernance) {
16373
+ return writeGovernanceFileFromConfig(serverGovernance);
16374
+ }
15875
16375
  // ===========================================================================
15876
16376
  // DRIFT DETECTION
15877
16377
  // ===========================================================================
@@ -16145,6 +16645,73 @@ async function duplicateAgentInteractive(apiKey, userData) {
16145
16645
  });
16146
16646
  }
16147
16647
  __name(duplicateAgentInteractive, "duplicateAgentInteractive");
16648
+ async function maybeScaffoldGovernanceForNewProject(projectDir) {
16649
+ try {
16650
+ const { wantGovernance } = await safePrompt([
16651
+ {
16652
+ type: "confirm",
16653
+ name: "wantGovernance",
16654
+ message: "Add governance (policy enforcement on tools & messages) to this agent?",
16655
+ default: false
16656
+ }
16657
+ ]);
16658
+ if (!wantGovernance) return;
16659
+ const { mode: govMode } = await safePrompt([
16660
+ {
16661
+ type: "list",
16662
+ name: "mode",
16663
+ message: "Governance mode:",
16664
+ choices: [
16665
+ {
16666
+ name: "SDK \u2014 local, in-memory policies (no server)",
16667
+ value: "sdk"
16668
+ },
16669
+ {
16670
+ name: "API \u2014 remote enforcement via Governance Cloud",
16671
+ value: "api"
16672
+ }
16673
+ ]
16674
+ }
16675
+ ]);
16676
+ let setup;
16677
+ if (govMode === "api") {
16678
+ const { serverUrl } = await safePrompt([
16679
+ {
16680
+ type: "input",
16681
+ name: "serverUrl",
16682
+ message: "Governance API URL:",
16683
+ default: "https://api.heygovernance.ai"
16684
+ }
16685
+ ]);
16686
+ setup = {
16687
+ mode: "api",
16688
+ serverUrl
16689
+ };
16690
+ } else {
16691
+ setup = {
16692
+ mode: "sdk",
16693
+ blockTools: [],
16694
+ requireApproval: [],
16695
+ tokenLimit: 0
16696
+ };
16697
+ }
16698
+ const srcDir = join7(projectDir, "src");
16699
+ const targetDir = existsSync8(srcDir) ? srcDir : projectDir;
16700
+ writeFileSync7(join7(targetDir, "governance.ts"), generateGovernanceFile(setup), "utf-8");
16701
+ const wired = injectGovernanceIntoAgent(join7(targetDir, "index.ts"));
16702
+ writeSuccess("\u2705 Governance scaffolded (src/governance.ts)");
16703
+ if (!wired) {
16704
+ writeInfo("\u26A0\uFE0F Couldn't auto-wire governance \u2014 import { governance } from './governance' and add `governance,` to your LuaAgent.");
16705
+ }
16706
+ if (govMode === "api") {
16707
+ writeInfo(" Set the key on the platform (never commit it): lua env set GOVERNANCE_API_KEY <key>");
16708
+ }
16709
+ writeInfo(" Refine policies after `lua compile` with `lua governance add`.");
16710
+ } catch (err) {
16711
+ writeInfo(`\u26A0\uFE0F Skipped governance setup: ${err?.message ?? "unknown error"}. Add it later with \`lua governance add\`.`);
16712
+ }
16713
+ }
16714
+ __name(maybeScaffoldGovernanceForNewProject, "maybeScaffoldGovernanceForNewProject");
16148
16715
  async function initCommand(options = {}) {
16149
16716
  const withExamples = options.withExamples ?? false;
16150
16717
  return withErrorHandling(async () => {
@@ -16177,7 +16744,7 @@ async function initCommand(options = {}) {
16177
16744
  writeError("\n\u26A0\uFE0F You don't have access to the agent in this project");
16178
16745
  writeInfo(` Agent ID: ${existingAgentId}
16179
16746
  `);
16180
- const { action } = await inquirer3.prompt([
16747
+ const { action } = await inquirer4.prompt([
16181
16748
  {
16182
16749
  type: "list",
16183
16750
  name: "action",
@@ -16214,7 +16781,7 @@ async function initCommand(options = {}) {
16214
16781
  writeInfo("\n\u{1F4CB} Found existing project configuration");
16215
16782
  writeInfo(` Current Agent ID: ${existingAgentId}
16216
16783
  `);
16217
- const { wantSwitch } = await inquirer3.prompt([
16784
+ const { wantSwitch } = await inquirer4.prompt([
16218
16785
  {
16219
16786
  type: "list",
16220
16787
  name: "wantSwitch",
@@ -16250,7 +16817,8 @@ async function initCommand(options = {}) {
16250
16817
  let isNewAgent = false;
16251
16818
  let selectedModel;
16252
16819
  if (options.model) {
16253
- const models = await fetchApprovedModels(apiKey);
16820
+ const agentHint = options.agentId ?? options.fromAgentId;
16821
+ const models = await fetchApprovedModels(apiKey, agentHint, options.orgId);
16254
16822
  selectedModel = validateModelCode(models, options.model);
16255
16823
  }
16256
16824
  if (mode.type === "existing-agent") {
@@ -16332,7 +16900,7 @@ async function initCommand(options = {}) {
16332
16900
  if (serverModel) {
16333
16901
  selectedModel = serverModel;
16334
16902
  } else if (mode.type === "interactive") {
16335
- const models = await fetchApprovedModels(apiKey);
16903
+ const models = await fetchApprovedModels(apiKey, void 0, selectedOrg.id) ?? [];
16336
16904
  if (models.length > 0) {
16337
16905
  selectedModel = await promptModelSelection(models);
16338
16906
  }
@@ -16366,6 +16934,9 @@ async function initCommand(options = {}) {
16366
16934
  writeSuccess("\u2705 LuaAgent configuration updated!");
16367
16935
  } else {
16368
16936
  const currentDir = initializeProject(selectedAgent.agentId, selectedOrg.id, persona, selectedAgent.name, withExamples, sourcesRestored, selectedModel);
16937
+ if (!sourcesRestored && mode.type === "interactive") {
16938
+ await maybeScaffoldGovernanceForNewProject(currentDir);
16939
+ }
16369
16940
  await installDependencies(currentDir);
16370
16941
  if (sourcesRestored) {
16371
16942
  writeSuccess("\u2705 Project initialized with restored sources!");
@@ -16500,7 +17071,7 @@ __name(createNewAgentNonInteractive, "createNewAgentNonInteractive");
16500
17071
  async function createNewAgentFlow(apiKey, userData, promoCode) {
16501
17072
  const agentTypes = await fetchAgentTypes(apiKey);
16502
17073
  const selectedAgentType = selectBaseAgentType(agentTypes);
16503
- const { orgChoice } = await inquirer3.prompt([
17074
+ const { orgChoice } = await inquirer4.prompt([
16504
17075
  {
16505
17076
  type: "list",
16506
17077
  name: "orgChoice",
@@ -16531,7 +17102,7 @@ async function createNewAgentFlow(apiKey, userData, promoCode) {
16531
17102
  }
16532
17103
  }
16533
17104
  if (!orgId) {
16534
- const { organizationName } = await inquirer3.prompt([
17105
+ const { organizationName } = await inquirer4.prompt([
16535
17106
  {
16536
17107
  type: "input",
16537
17108
  name: "organizationName",
@@ -16556,7 +17127,7 @@ async function createNewAgentFlow(apiKey, userData, promoCode) {
16556
17127
  const agentName = await promptAgentName();
16557
17128
  linesToClear += 1;
16558
17129
  let selectedModel;
16559
- const models = await fetchApprovedModels(apiKey);
17130
+ const models = await fetchApprovedModels(apiKey, void 0, orgId) ?? [];
16560
17131
  if (models.length > 0) {
16561
17132
  selectedModel = await promptModelSelection(models);
16562
17133
  }
@@ -16597,7 +17168,7 @@ async function handleAgentSwitch(userData, apiKey, existingYaml) {
16597
17168
  if (serverModel) {
16598
17169
  selectedModel = serverModel;
16599
17170
  } else {
16600
- const models = await fetchApprovedModels(apiKey);
17171
+ const models = await fetchApprovedModels(apiKey, void 0, selectedOrg.id) ?? [];
16601
17172
  if (models.length > 0) {
16602
17173
  selectedModel = await promptModelSelection(models);
16603
17174
  }
@@ -16658,7 +17229,7 @@ async function promptPersonaReplacement(existingYaml, newPersona) {
16658
17229
  }
16659
17230
  writeInfo("\n\u{1F4DD} Persona Configuration:");
16660
17231
  writeInfo(" Existing persona found in project");
16661
- const { replacePersona } = await inquirer3.prompt([
17232
+ const { replacePersona } = await inquirer4.prompt([
16662
17233
  {
16663
17234
  type: "confirm",
16664
17235
  name: "replacePersona",
@@ -16678,7 +17249,7 @@ async function checkAndRestoreBackup(apiKey, agentId, options) {
16678
17249
  }
16679
17250
  const conflicts = checkRestoreConflicts(manifest, targetDir);
16680
17251
  if (!options.autoRestore && conflicts.existingFiles.length > 0) {
16681
- const { confirm } = await inquirer3.prompt([
17252
+ const { confirm } = await inquirer4.prompt([
16682
17253
  {
16683
17254
  type: "confirm",
16684
17255
  name: "confirm",
@@ -16727,7 +17298,7 @@ __name(checkAndRestoreBackup, "checkAndRestoreBackup");
16727
17298
  init_auth();
16728
17299
  init_cli();
16729
17300
  init_analytics();
16730
- import inquirer4 from "inquirer";
17301
+ import inquirer5 from "inquirer";
16731
17302
  async function destroyCommand(options) {
16732
17303
  return withErrorHandling(async () => {
16733
17304
  let apiKey;
@@ -16755,7 +17326,7 @@ async function destroyCommand(options) {
16755
17326
  });
16756
17327
  return;
16757
17328
  }
16758
- const { confirm } = await inquirer4.prompt([
17329
+ const { confirm } = await inquirer5.prompt([
16759
17330
  {
16760
17331
  type: "confirm",
16761
17332
  name: "confirm",
@@ -16789,7 +17360,7 @@ __name(destroyCommand, "destroyCommand");
16789
17360
  init_auth();
16790
17361
  init_cli();
16791
17362
  init_analytics();
16792
- import inquirer5 from "inquirer";
17363
+ import inquirer6 from "inquirer";
16793
17364
  async function apiKeyCommand(options) {
16794
17365
  return withErrorHandling(async () => {
16795
17366
  let apiKey;
@@ -16811,7 +17382,7 @@ async function apiKeyCommand(options) {
16811
17382
  });
16812
17383
  return;
16813
17384
  }
16814
- const { confirm } = await inquirer5.prompt([
17385
+ const { confirm } = await inquirer6.prompt([
16815
17386
  {
16816
17387
  type: "confirm",
16817
17388
  name: "confirm",
@@ -16845,44 +17416,6 @@ init_dist();
16845
17416
  init_cli();
16846
17417
  import fs13 from "fs";
16847
17418
  import path12 from "path";
16848
-
16849
- // src/utils/prompt-handler.ts
16850
- init_cli();
16851
- import inquirer6 from "inquirer";
16852
- async function safePrompt(questions) {
16853
- if (isCiModeEnabled()) {
16854
- throw new Error("Interactive prompt required but --ci flag is set. Provide all required flags or arguments.");
16855
- }
16856
- if (!process.stdin.isTTY && !isCiModeEnabled()) {
16857
- console.warn("\u26A0\uFE0F Warning: stdin is not a TTY. Interactive prompts may not work correctly.");
16858
- console.warn("\u{1F4A1} Tip: Use --ci flag in CI/CD environments to fail loudly on missing required flags.");
16859
- }
16860
- try {
16861
- await new Promise((resolve6) => setTimeout(resolve6, 10));
16862
- const answers = await inquirer6.prompt(questions);
16863
- return answers;
16864
- } catch (error) {
16865
- if (error.name === "ExitPromptError" || error.message?.includes("SIGINT")) {
16866
- process.exit(0);
16867
- }
16868
- throw error;
16869
- }
16870
- }
16871
- __name(safePrompt, "safePrompt");
16872
- async function confirmAction(message) {
16873
- const answer = await safePrompt([
16874
- {
16875
- type: "confirm",
16876
- name: "confirmed",
16877
- message,
16878
- default: false
16879
- }
16880
- ]);
16881
- return answer?.confirmed ?? false;
16882
- }
16883
- __name(confirmAction, "confirmAction");
16884
-
16885
- // src/commands/sync.ts
16886
17419
  init_command_utils();
16887
17420
 
16888
17421
  // src/commands/log-tip.ts
@@ -17285,6 +17818,14 @@ async function executeAcceptMode(context, drift, primitiveDrift, force) {
17285
17818
  console.error("\u274C Failed to update model in code.");
17286
17819
  }
17287
17820
  }
17821
+ if (drift.governance?.serverGovernance) {
17822
+ writeProgress("\u{1F4DD} Syncing governance from server...");
17823
+ if (agentHandler.pullGovernance(drift.governance.serverGovernance)) {
17824
+ writeSuccess("\u2705 Governance synced from server (governance.ts)");
17825
+ } else {
17826
+ console.error("\u274C Failed to write governance.ts.");
17827
+ }
17828
+ }
17288
17829
  if (unresolvedCount > 0) {
17289
17830
  writeInfo(`
17290
17831
  \u26A0\uFE0F Sync partially complete \u2014 ${unresolvedCount} primitive(s) unresolved. See above.`);
@@ -17372,12 +17913,16 @@ async function executePushMode(context, drift, primitiveDrift) {
17372
17913
  }
17373
17914
  }
17374
17915
  if (drift.governance) {
17375
- writeProgress("\u{1F4E4} Pushing governance config to server...");
17376
- if (await agentHandler.pushGovernance(context, drift.governance.localGovernance)) {
17377
- writeSuccess("\u2705 Governance config pushed to server");
17916
+ if (!drift.governance.localGovernance) {
17917
+ writeInfo("\u2139\uFE0F Server has governance config not present locally \u2014 leaving it intact (run `lua governance remove` to clear it).");
17378
17918
  } else {
17379
- console.error("\u274C Failed to push governance config");
17380
- syncFullySucceeded = false;
17919
+ writeProgress("\u{1F4E4} Pushing governance config to server...");
17920
+ if (await agentHandler.pushGovernance(context, drift.governance.localGovernance)) {
17921
+ writeSuccess("\u2705 Governance config pushed to server");
17922
+ } else {
17923
+ console.error("\u274C Failed to push governance config");
17924
+ syncFullySucceeded = false;
17925
+ }
17381
17926
  }
17382
17927
  }
17383
17928
  } catch (error) {
@@ -17704,21 +18249,25 @@ async function handlePrimitiveDriftInteractive(context, primitiveDrift) {
17704
18249
  __name(handlePrimitiveDriftInteractive, "handlePrimitiveDriftInteractive");
17705
18250
  async function handleGovernanceDriftInteractive(context, drift) {
17706
18251
  showGovernanceDiff(drift.serverGovernance, drift.localGovernance);
18252
+ const choices = [];
18253
+ if (drift.localGovernance) choices.push({
18254
+ name: "\u{1F4E4} Push local to server",
18255
+ value: "push"
18256
+ });
18257
+ if (drift.serverGovernance) choices.push({
18258
+ name: "\u{1F4E5} Pull server to local (governance.ts)",
18259
+ value: "pull"
18260
+ });
18261
+ choices.push({
18262
+ name: "\u23ED\uFE0F Skip",
18263
+ value: "skip"
18264
+ });
17707
18265
  const answer = await safePrompt([
17708
18266
  {
17709
18267
  type: "list",
17710
18268
  name: "action",
17711
18269
  message: "What would you like to do with governance config?",
17712
- choices: [
17713
- {
17714
- name: "\u{1F4E4} Push local to server",
17715
- value: "push"
17716
- },
17717
- {
17718
- name: "\u23ED\uFE0F Skip",
17719
- value: "skip"
17720
- }
17721
- ]
18270
+ choices
17722
18271
  }
17723
18272
  ]);
17724
18273
  if (!answer || answer.action === "skip") {
@@ -17736,6 +18285,13 @@ async function handleGovernanceDriftInteractive(context, drift) {
17736
18285
  } catch (error) {
17737
18286
  console.error("\u274C Failed to push governance config:", error.message);
17738
18287
  }
18288
+ } else if (answer.action === "pull") {
18289
+ writeProgress("\u{1F4E5} Pulling governance config to local...");
18290
+ if (agentHandler.pullGovernance(drift.serverGovernance)) {
18291
+ writeSuccess("\u2705 Governance config written to governance.ts");
18292
+ } else {
18293
+ console.error("\u274C Failed to write governance.ts");
18294
+ }
17739
18295
  }
17740
18296
  }
17741
18297
  __name(handleGovernanceDriftInteractive, "handleGovernanceDriftInteractive");
@@ -17871,6 +18427,212 @@ var WebhookHandler = class extends BaseVersionedHandler {
17871
18427
  };
17872
18428
  var webhookHandler = new WebhookHandler();
17873
18429
 
18430
+ // src/primitives/trigger.handler.ts
18431
+ init_types();
18432
+ init_constants();
18433
+
18434
+ // src/api/trigger.api.service.ts
18435
+ init_http_client();
18436
+ var TriggerApi = class extends HttpClient {
18437
+ static {
18438
+ __name(this, "TriggerApi");
18439
+ }
18440
+ apiKey;
18441
+ agentId;
18442
+ /**
18443
+ * Creates an instance of TriggerApi
18444
+ * @param baseUrl - The base URL for the API
18445
+ * @param apiKey - The API key for authentication
18446
+ * @param agentId - The unique identifier of the agent
18447
+ */
18448
+ constructor(baseUrl, apiKey, agentId) {
18449
+ super(baseUrl);
18450
+ this.apiKey = apiKey;
18451
+ this.agentId = agentId;
18452
+ }
18453
+ /**
18454
+ * Retrieves all triggers for the agent (including dispatch URLs)
18455
+ */
18456
+ async getTriggers() {
18457
+ return this.httpGet(`/developer/triggers/${this.agentId}`, {
18458
+ Authorization: `Bearer ${this.apiKey}`
18459
+ });
18460
+ }
18461
+ /**
18462
+ * Creates a new trigger and returns it, including its pasteable dispatch URL
18463
+ */
18464
+ async createTrigger(triggerData) {
18465
+ return this.httpPost(`/developer/triggers/${this.agentId}`, triggerData, {
18466
+ Authorization: `Bearer ${this.apiKey}`
18467
+ });
18468
+ }
18469
+ /**
18470
+ * Retrieves a single trigger including its dispatch URL
18471
+ */
18472
+ async getTrigger(triggerId) {
18473
+ return this.httpGet(`/developer/triggers/${this.agentId}/${triggerId}`, {
18474
+ Authorization: `Bearer ${this.apiKey}`
18475
+ });
18476
+ }
18477
+ /**
18478
+ * Updates trigger properties (name, description, instruction)
18479
+ */
18480
+ async updateTrigger(triggerId, data) {
18481
+ return this.httpPatch(`/developer/triggers/${this.agentId}/${triggerId}`, data, {
18482
+ Authorization: `Bearer ${this.apiKey}`
18483
+ });
18484
+ }
18485
+ /**
18486
+ * Activates a trigger (enables it to receive requests)
18487
+ */
18488
+ async activateTrigger(triggerId) {
18489
+ return this.httpPost(`/developer/triggers/${this.agentId}/${triggerId}/activate`, {}, {
18490
+ Authorization: `Bearer ${this.apiKey}`
18491
+ });
18492
+ }
18493
+ /**
18494
+ * Deactivates a trigger (stops it from receiving requests)
18495
+ */
18496
+ async deactivateTrigger(triggerId) {
18497
+ return this.httpPost(`/developer/triggers/${this.agentId}/${triggerId}/deactivate`, {}, {
18498
+ Authorization: `Bearer ${this.apiKey}`
18499
+ });
18500
+ }
18501
+ /**
18502
+ * Rotates the trigger token, invalidating the previous dispatch URL.
18503
+ * Returns the trigger with its NEW url.
18504
+ */
18505
+ async rotateTriggerToken(triggerId) {
18506
+ return this.httpPost(`/developer/triggers/${this.agentId}/${triggerId}/rotate-token`, {}, {
18507
+ Authorization: `Bearer ${this.apiKey}`
18508
+ });
18509
+ }
18510
+ /**
18511
+ * Deletes a trigger. Execution history is retained until TTL expiry.
18512
+ */
18513
+ async deleteTrigger(triggerId) {
18514
+ return this.httpDelete(`/developer/triggers/${this.agentId}/${triggerId}`, {
18515
+ Authorization: `Bearer ${this.apiKey}`
18516
+ });
18517
+ }
18518
+ /**
18519
+ * Retrieves execution history for a trigger, newest first
18520
+ * @param options.limit - Max executions to return (server default: 50, cap: 200)
18521
+ * @param options.offset - Pagination offset (server default: 0)
18522
+ */
18523
+ async getTriggerExecutions(triggerId, options = {}) {
18524
+ const queryParams = new URLSearchParams();
18525
+ if (options.limit !== void 0) {
18526
+ queryParams.append("limit", String(options.limit));
18527
+ }
18528
+ if (options.offset !== void 0) {
18529
+ queryParams.append("offset", String(options.offset));
18530
+ }
18531
+ const query = queryParams.toString();
18532
+ return this.httpGet(`/developer/triggers/${this.agentId}/${triggerId}/executions${query ? `?${query}` : ""}`, {
18533
+ Authorization: `Bearer ${this.apiKey}`
18534
+ });
18535
+ }
18536
+ /**
18537
+ * Push a new SDK (defineTrigger) bundle version to the trigger (PRO-95).
18538
+ * Used by the `lua push` flow via TriggerHandler.
18539
+ */
18540
+ async pushTrigger(triggerId, versionData) {
18541
+ return this.httpPost(`/developer/triggers/${this.agentId}/${triggerId}/version`, versionData, {
18542
+ Authorization: `Bearer ${this.apiKey}`
18543
+ });
18544
+ }
18545
+ /** List the SDK versions of a trigger (newest first). */
18546
+ async getTriggerVersions(triggerId) {
18547
+ return this.httpGet(`/developer/triggers/${this.agentId}/${triggerId}/versions`, {
18548
+ Authorization: `Bearer ${this.apiKey}`
18549
+ });
18550
+ }
18551
+ /** Publish (promote to active) a trigger version. */
18552
+ async publishTriggerVersion(triggerId, version) {
18553
+ return this.httpPost(`/developer/triggers/${this.agentId}/${triggerId}/${version}/publish`, {}, {
18554
+ Authorization: `Bearer ${this.apiKey}`
18555
+ });
18556
+ }
18557
+ };
18558
+
18559
+ // src/primitives/trigger.handler.ts
18560
+ init_base_handler();
18561
+ var TriggerHandler = class extends BaseVersionedHandler {
18562
+ static {
18563
+ __name(this, "TriggerHandler");
18564
+ }
18565
+ kind = PrimitiveKind.TRIGGER;
18566
+ displayName = "trigger";
18567
+ displayNamePlural = "triggers";
18568
+ deleteCommand = "lua triggers delete";
18569
+ yamlConfig = {
18570
+ yamlKey: "triggers",
18571
+ idField: "triggerId"
18572
+ };
18573
+ getApi(apiKey, agentId) {
18574
+ return new TriggerApi(BASE_URLS.API, apiKey, agentId);
18575
+ }
18576
+ async fetchFromServer(api) {
18577
+ const response = await api.getTriggers();
18578
+ if (!response.success || !response.data?.triggers) {
18579
+ return null;
18580
+ }
18581
+ return response.data.triggers;
18582
+ }
18583
+ async createOnServer(api, primitive) {
18584
+ const response = await api.createTrigger({
18585
+ name: primitive.name,
18586
+ description: primitive.description || `A Lua trigger for ${primitive.name}`
18587
+ });
18588
+ if (!response.success || !response.data?.id) return null;
18589
+ return response.data.id;
18590
+ }
18591
+ isActive(serverItem) {
18592
+ return serverItem.active !== false;
18593
+ }
18594
+ getActiveVersion(serverItem) {
18595
+ if (serverItem.activeVersionId) {
18596
+ return serverItem.versions?.find((v) => v.id === serverItem.activeVersionId)?.version ?? null;
18597
+ }
18598
+ return serverItem.versions?.find((v) => v.active === true)?.version ?? null;
18599
+ }
18600
+ async pushToServer(apiKey, agentId, entityId, pushData) {
18601
+ const api = this.getApi(apiKey, agentId);
18602
+ const response = await api.pushTrigger(entityId, {
18603
+ ...pushData,
18604
+ triggerId: entityId
18605
+ });
18606
+ return {
18607
+ success: response.success,
18608
+ error: response.error?.message
18609
+ };
18610
+ }
18611
+ async publishVersion(apiKey, agentId, entityId, version) {
18612
+ const api = this.getApi(apiKey, agentId);
18613
+ const response = await api.publishTriggerVersion(entityId, version);
18614
+ return {
18615
+ success: response.success,
18616
+ error: response.error?.message
18617
+ };
18618
+ }
18619
+ /** Include the trigger's body schema (from the SDK inputSchema) in push data. */
18620
+ buildPushData(primitive, compressedCode, codeS3Hash) {
18621
+ const trigger = primitive;
18622
+ return {
18623
+ name: trigger.name,
18624
+ description: trigger.description,
18625
+ ...codeS3Hash ? {
18626
+ codeS3Hash
18627
+ } : {
18628
+ code: compressedCode
18629
+ },
18630
+ bodySchema: trigger.schemas?.body || void 0
18631
+ };
18632
+ }
18633
+ };
18634
+ var triggerHandler = new TriggerHandler();
18635
+
17874
18636
  // src/primitives/job.handler.ts
17875
18637
  init_types();
17876
18638
  init_constants();
@@ -18619,6 +19381,7 @@ var VoiceHandler = class extends BaseVersionedHandler {
18619
19381
  if (voice.volume !== void 0) body.volume = voice.volume;
18620
19382
  if (voice.pronunciations !== void 0) body.pronunciations = voice.pronunciations;
18621
19383
  if (voice.backgroundAudio !== void 0) body.backgroundAudio = voice.backgroundAudio;
19384
+ if (voice.excludeTools !== void 0) body.excludeTools = voice.excludeTools;
18622
19385
  const hasCode = !!(voice.hasOnEnter || voice.hasOnUserTurnCompleted || voice.hasOnExit || voice.hasTools);
18623
19386
  if (hasCode) {
18624
19387
  const artifactCode = loadArtifact(voice);
@@ -18643,6 +19406,7 @@ init_mcp_server_handler();
18643
19406
  var primitiveHandlers = {
18644
19407
  [PrimitiveKind.SKILL]: skillHandler,
18645
19408
  [PrimitiveKind.WEBHOOK]: webhookHandler,
19409
+ [PrimitiveKind.TRIGGER]: triggerHandler,
18646
19410
  [PrimitiveKind.JOB]: jobHandler,
18647
19411
  [PrimitiveKind.PREPROCESSOR]: preprocessorHandler,
18648
19412
  [PrimitiveKind.POSTPROCESSOR]: postprocessorHandler,
@@ -19951,6 +20715,30 @@ function createSandbox(options) {
19951
20715
  const voice = await getVoiceInstance2();
19952
20716
  return voice.dispatchForSandbox(input);
19953
20717
  }, "call")
20718
+ },
20719
+ // Outbound channel send (PRO-93). Proxied via the lua-cli developer
20720
+ // endpoint (Bearer auth) — keeps lua test byte-equivalent to the lua-core
20721
+ // production VM (which routes through /internal/agents/:agentId/channels/*).
20722
+ Channels: {
20723
+ send: /* @__PURE__ */ __name(async (input) => {
20724
+ const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
20725
+ const channels = await getChannelsSendInstance2();
20726
+ return channels.sendForSandbox(input);
20727
+ }, "send"),
20728
+ whatsapp: {
20729
+ sendTemplate: /* @__PURE__ */ __name(async (input) => {
20730
+ const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
20731
+ const channels = await getChannelsSendInstance2();
20732
+ return channels.sendWhatsAppTemplateForSandbox(input);
20733
+ }, "sendTemplate")
20734
+ },
20735
+ email: {
20736
+ send: /* @__PURE__ */ __name(async (input) => {
20737
+ const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
20738
+ const channels = await getChannelsSendInstance2();
20739
+ return channels.sendEmailForSandbox(input);
20740
+ }, "send")
20741
+ }
19954
20742
  }
19955
20743
  };
19956
20744
  return createBaseSandboxContext({
@@ -20317,6 +21105,7 @@ var ALIAS_MAP = {
20317
21105
  "skill",
20318
21106
  "agent",
20319
21107
  "webhook",
21108
+ "trigger",
20320
21109
  "job",
20321
21110
  "preprocessor",
20322
21111
  "postprocessor",
@@ -20337,6 +21126,7 @@ var ALIAS_MAP = {
20337
21126
  webhooks: "webhook",
20338
21127
  hook: "webhook",
20339
21128
  hooks: "webhook",
21129
+ triggers: "trigger",
20340
21130
  jobs: "job",
20341
21131
  preprocessors: "preprocessor",
20342
21132
  pre: "preprocessor",
@@ -20430,6 +21220,7 @@ var ALIAS_MAP = {
20430
21220
  canonical: [
20431
21221
  "skill",
20432
21222
  "webhook",
21223
+ "trigger",
20433
21224
  "job",
20434
21225
  "preprocessor",
20435
21226
  "postprocessor",
@@ -20440,6 +21231,7 @@ var ALIAS_MAP = {
20440
21231
  webhooks: "webhook",
20441
21232
  hook: "webhook",
20442
21233
  hooks: "webhook",
21234
+ triggers: "trigger",
20443
21235
  jobs: "job",
20444
21236
  preprocessors: "preprocessor",
20445
21237
  pre: "preprocessor",
@@ -20644,7 +21436,8 @@ var ALIAS_MAP = {
20644
21436
  "list",
20645
21437
  "enable",
20646
21438
  "disable",
20647
- "view"
21439
+ "view",
21440
+ "configure"
20648
21441
  ],
20649
21442
  aliases: lowerKeys({
20650
21443
  ls: "list",
@@ -20655,7 +21448,9 @@ var ALIAS_MAP = {
20655
21448
  deactivate: "disable",
20656
21449
  show: "view",
20657
21450
  info: "view",
20658
- status: "view"
21451
+ status: "view",
21452
+ config: "configure",
21453
+ set: "configure"
20659
21454
  })
20660
21455
  },
20661
21456
  "mcp.action": {
@@ -20708,7 +21503,8 @@ var ALIAS_MAP = {
20708
21503
  mcps: "mcp"
20709
21504
  })
20710
21505
  },
20711
- "triggers.action": {
21506
+ // Integration-trigger subactions for `lua integrations webhooks` / `lua integrations triggers`
21507
+ "integrations.webhooks.action": {
20712
21508
  canonical: [
20713
21509
  "list",
20714
21510
  "create",
@@ -20732,6 +21528,41 @@ var ALIAS_MAP = {
20732
21528
  "list-events": "events"
20733
21529
  })
20734
21530
  },
21531
+ // Platform triggers (`lua triggers`, PRO-94)
21532
+ "triggers.action": {
21533
+ canonical: [
21534
+ "list",
21535
+ "create",
21536
+ "logs",
21537
+ "activate",
21538
+ "deactivate",
21539
+ "rotate-token",
21540
+ "delete"
21541
+ ],
21542
+ aliases: lowerKeys({
21543
+ view: "list",
21544
+ show: "list",
21545
+ ls: "list",
21546
+ l: "list",
21547
+ new: "create",
21548
+ add: "create",
21549
+ history: "logs",
21550
+ executions: "logs",
21551
+ runs: "logs",
21552
+ log: "logs",
21553
+ // NB: `on`/`off` are intentionally NOT platform aliases — they resolve to
21554
+ // integration resume/pause and are redirected by triggers.ts's soft
21555
+ // landing, so an `on→activate` mapping here would be unreachable.
21556
+ enable: "activate",
21557
+ disable: "deactivate",
21558
+ rotate: "rotate-token",
21559
+ rotate_token: "rotate-token",
21560
+ rotatetoken: "rotate-token",
21561
+ rm: "delete",
21562
+ remove: "delete",
21563
+ del: "delete"
21564
+ })
21565
+ },
20735
21566
  "marketplace.role": {
20736
21567
  canonical: [
20737
21568
  "create",
@@ -22111,11 +22942,11 @@ init_cli();
22111
22942
 
22112
22943
  // src/utils/git-auth-store.ts
22113
22944
  init_constants();
22114
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
22945
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
22115
22946
  import { dirname as dirname5 } from "path";
22116
22947
  function readStore() {
22117
22948
  try {
22118
- const raw = readFileSync9(AUTH_STORAGE_FILE, "utf8");
22949
+ const raw = readFileSync10(AUTH_STORAGE_FILE, "utf8");
22119
22950
  const parsed = JSON.parse(raw);
22120
22951
  return {
22121
22952
  providers: parsed.providers ?? {}
@@ -22131,7 +22962,7 @@ function writeStore(store) {
22131
22962
  mkdirSync6(dirname5(AUTH_STORAGE_FILE), {
22132
22963
  recursive: true
22133
22964
  });
22134
- writeFileSync6(AUTH_STORAGE_FILE, JSON.stringify(store, null, 2), {
22965
+ writeFileSync8(AUTH_STORAGE_FILE, JSON.stringify(store, null, 2), {
22135
22966
  mode: 384
22136
22967
  });
22137
22968
  }
@@ -22610,6 +23441,7 @@ function getDeployHint(type) {
22610
23441
  const deployableMap = {
22611
23442
  skill: "lua deploy skill",
22612
23443
  webhook: "lua deploy webhook",
23444
+ trigger: "lua deploy trigger",
22613
23445
  job: "lua deploy job",
22614
23446
  preprocessor: "lua deploy preprocessor",
22615
23447
  postprocessor: "lua deploy postprocessor",
@@ -22934,6 +23766,8 @@ async function pushCommand(type, cmdObj) {
22934
23766
  versionedPushDeployResult = await pushVersionedPrimitive(skillHandler, options);
22935
23767
  } else if (selectedType === "webhook") {
22936
23768
  versionedPushDeployResult = await pushVersionedPrimitive(webhookHandler, options);
23769
+ } else if (selectedType === "trigger") {
23770
+ versionedPushDeployResult = await pushVersionedPrimitive(triggerHandler, options);
22937
23771
  } else if (selectedType === "job") {
22938
23772
  versionedPushDeployResult = await pushVersionedPrimitive(jobHandler, options);
22939
23773
  } else if (selectedType === "preprocessor") {
@@ -23335,6 +24169,7 @@ async function pushAllCommand(options) {
23335
24169
  const kindIcons = {
23336
24170
  skill: "\u{1F4E6}",
23337
24171
  webhook: "\u{1FA9D}",
24172
+ trigger: "\u26A1",
23338
24173
  job: "\u23F0",
23339
24174
  preprocessor: "\u{1F4E5}",
23340
24175
  postprocessor: "\u{1F4E4}",
@@ -23344,6 +24179,7 @@ async function pushAllCommand(options) {
23344
24179
  const handlers = [
23345
24180
  skillHandler,
23346
24181
  webhookHandler,
24182
+ triggerHandler,
23347
24183
  jobHandler,
23348
24184
  preprocessorHandler,
23349
24185
  postprocessorHandler,
@@ -23767,6 +24603,18 @@ var VERSIONED_DEPLOY_TYPES = [
23767
24603
  return (result.data?.versions || []).map(normalizeVersion);
23768
24604
  }, "getVersions")
23769
24605
  },
24606
+ {
24607
+ type: "trigger",
24608
+ handler: triggerHandler,
24609
+ label: "Trigger",
24610
+ emoji: "\u26A1",
24611
+ idField: "triggerId",
24612
+ getVersions: /* @__PURE__ */ __name(async (apiKey, agentId, entityId) => {
24613
+ const api = new TriggerApi(BASE_URLS.API, apiKey, agentId);
24614
+ const result = await api.getTriggerVersions(entityId);
24615
+ return (result.data?.versions || []).map(normalizeVersion);
24616
+ }, "getVersions")
24617
+ },
23770
24618
  {
23771
24619
  type: "job",
23772
24620
  handler: jobHandler,
@@ -24383,11 +25231,11 @@ init_cli();
24383
25231
 
24384
25232
  // src/utils/sandbox-storage.ts
24385
25233
  init_constants();
24386
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "fs";
25234
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, mkdirSync as mkdirSync7 } from "fs";
24387
25235
  import { dirname as dirname6 } from "path";
24388
25236
  function readStore2() {
24389
25237
  try {
24390
- const raw = readFileSync10(SANDBOX_STORAGE_FILE, "utf8");
25238
+ const raw = readFileSync11(SANDBOX_STORAGE_FILE, "utf8");
24391
25239
  const parsed = JSON.parse(raw);
24392
25240
  return {
24393
25241
  skills: parsed.skills ?? {},
@@ -24410,7 +25258,7 @@ function writeStore2(store) {
24410
25258
  mkdirSync7(dirname6(SANDBOX_STORAGE_FILE), {
24411
25259
  recursive: true
24412
25260
  });
24413
- writeFileSync7(SANDBOX_STORAGE_FILE, JSON.stringify(store, null, 2), "utf8");
25261
+ writeFileSync9(SANDBOX_STORAGE_FILE, JSON.stringify(store, null, 2), "utf8");
24414
25262
  } catch {
24415
25263
  }
24416
25264
  }
@@ -30731,8 +31579,9 @@ init_auth();
30731
31579
  init_auth_api_service();
30732
31580
  init_files();
30733
31581
  init_artifact_loader();
30734
- import { existsSync as existsSync7, readFileSync as readFileSync11 } from "fs";
30735
- import { join as join6 } from "path";
31582
+ import chalk3 from "chalk";
31583
+ import { existsSync as existsSync9, readFileSync as readFileSync12 } from "fs";
31584
+ import { join as join8 } from "path";
30736
31585
  import { performance } from "perf_hooks";
30737
31586
  import * as os from "os";
30738
31587
  init_semver();
@@ -30899,7 +31748,7 @@ function gatherProject(config) {
30899
31748
  };
30900
31749
  }
30901
31750
  const rootDir = process.cwd();
30902
- const configPath = join6(rootDir, COMPILE_FILES.LUA_SKILL_YAML);
31751
+ const configPath = join8(rootDir, COMPILE_FILES.LUA_SKILL_YAML);
30903
31752
  const agentId = config.agent?.agentId != null ? String(config.agent.agentId) : null;
30904
31753
  let agentName = null;
30905
31754
  let manifestFound = false;
@@ -31081,8 +31930,8 @@ function gatherTelemetry() {
31081
31930
  ].includes(envVal.toLowerCase());
31082
31931
  } else {
31083
31932
  try {
31084
- if (existsSync7(TELEMETRY_FILE)) {
31085
- const raw = readFileSync11(TELEMETRY_FILE, "utf8");
31933
+ if (existsSync9(TELEMETRY_FILE)) {
31934
+ const raw = readFileSync12(TELEMETRY_FILE, "utf8");
31086
31935
  const cfg = JSON.parse(raw);
31087
31936
  if (typeof cfg.enabled === "boolean") enabled = cfg.enabled;
31088
31937
  }
@@ -31109,12 +31958,12 @@ function deriveHints(report) {
31109
31958
  reason: "Authenticate for full server comparison"
31110
31959
  });
31111
31960
  }
31112
- for (const section of report.primitives) {
31113
- for (const orphan of section.orphans) {
31961
+ for (const section2 of report.primitives) {
31962
+ for (const orphan of section2.orphans) {
31114
31963
  if (!orphan.cleanupCommand) continue;
31115
31964
  hints.push({
31116
31965
  command: orphan.cleanupCommand,
31117
- reason: orphan.critical ? `Remove orphan ${section.displayName} "${orphan.name}" (causes errors)` : `Remove orphan ${section.displayName} "${orphan.name}"`
31966
+ reason: orphan.critical ? `Remove orphan ${section2.displayName} "${orphan.name}" (causes errors)` : `Remove orphan ${section2.displayName} "${orphan.name}"`
31118
31967
  });
31119
31968
  }
31120
31969
  }
@@ -31137,129 +31986,170 @@ function pad(s, n) {
31137
31986
  return s.length >= n ? s : s + " ".repeat(n - s.length);
31138
31987
  }
31139
31988
  __name(pad, "pad");
31989
+ function truncate2(s, n) {
31990
+ return s.length <= n ? s : s.slice(0, Math.max(0, n - 1)) + "\u2026";
31991
+ }
31992
+ __name(truncate2, "truncate");
31140
31993
  function printJson(report) {
31141
31994
  console.log(JSON.stringify(report));
31142
31995
  }
31143
31996
  __name(printJson, "printJson");
31144
- function printHuman(report) {
31145
- const lines = [];
31146
- lines.push("");
31147
- lines.push("== lua status ==");
31148
- lines.push("");
31997
+ var TICK = chalk3.green("\u2713");
31998
+ var WARN = chalk3.yellow("!");
31999
+ var CROSS = chalk3.red("\u2717");
32000
+ var row = /* @__PURE__ */ __name((text, dim = false) => ({
32001
+ text,
32002
+ dim
32003
+ }), "row");
32004
+ function section(title, rows) {
32005
+ const out = [
32006
+ chalk3.bold(title)
32007
+ ];
32008
+ if (rows.length === 0) {
32009
+ out.push(chalk3.dim("\u2514\u2500 (none)"));
32010
+ return out;
32011
+ }
32012
+ rows.forEach((r, i) => {
32013
+ const connector = chalk3.dim(i === rows.length - 1 ? "\u2514\u2500" : "\u251C\u2500");
32014
+ const body = r.dim ? chalk3.dim(r.text) : r.text;
32015
+ out.push(`${connector} ${body}`);
32016
+ });
32017
+ return out;
32018
+ }
32019
+ __name(section, "section");
32020
+ function renderHuman(report) {
32021
+ const blocks = [];
31149
32022
  const env = report.environment;
31150
- lines.push("Environment");
31151
- lines.push(` CLI version ${env.cliVersion} (channel: ${env.channel})`);
31152
- lines.push(` Node ${env.nodeVersion}`);
31153
- lines.push(` OS ${env.platform} ${env.osRelease} (${env.arch})`);
31154
- lines.push(` Install method ${env.installMethod}`);
31155
- lines.push(` Exec path ${env.execPath}`);
31156
- lines.push(` Config dir ${env.configDir}`);
31157
- lines.push(` API base ${env.apiBase}`);
31158
- lines.push(` Auth base ${env.authBase}`);
31159
32023
  const overrides = env.envOverrides;
31160
- const overridesStr = [
31161
- `LUA_API_URL: ${overrides.LUA_API_URL ?? "not set"}`,
31162
- `LUA_AUTH_URL: ${overrides.LUA_AUTH_URL ?? "not set"}`,
31163
- `LUA_API_KEY: ${overrides.LUA_API_KEY}`,
31164
- `LUA_TELEMETRY: ${overrides.LUA_TELEMETRY ?? "not set"}`,
31165
- `LUA_NO_HINTS: ${overrides.LUA_NO_HINTS ?? "not set"}`
31166
- ].join(", ");
31167
- lines.push(` Env overrides ${overridesStr}`);
31168
- lines.push("");
32024
+ const setOverrides = [
32025
+ overrides.LUA_API_URL !== null ? `LUA_API_URL=${overrides.LUA_API_URL}` : null,
32026
+ overrides.LUA_AUTH_URL !== null ? `LUA_AUTH_URL=${overrides.LUA_AUTH_URL}` : null,
32027
+ overrides.LUA_API_KEY === "set" ? `LUA_API_KEY=set` : null,
32028
+ overrides.LUA_TELEMETRY !== null ? `LUA_TELEMETRY=${overrides.LUA_TELEMETRY}` : null,
32029
+ overrides.LUA_NO_HINTS !== null ? `LUA_NO_HINTS=${overrides.LUA_NO_HINTS}` : null
32030
+ ].filter((x) => x !== null);
32031
+ blocks.push(section("Environment", [
32032
+ row(`CLI version: ${env.cliVersion} (channel: ${env.channel})`),
32033
+ row(`Node: ${env.nodeVersion}`),
32034
+ row(`OS: ${env.platform} ${env.osRelease} (${env.arch})`),
32035
+ row(`Install method: ${env.installMethod}`),
32036
+ row(`API base: ${env.apiBase}`),
32037
+ row(`Auth base: ${env.authBase}`),
32038
+ row(`Config dir: ${env.configDir}`, true),
32039
+ row(`Exec path: ${env.execPath}`, true),
32040
+ ...setOverrides.map((o) => row(o, true))
32041
+ ]));
31169
32042
  const u = report.updates;
31170
- lines.push("Updates");
31171
- lines.push(` Current ${u.current}`);
31172
- lines.push(` Latest published ${u.latest ?? "unknown"}`);
31173
- lines.push(` Status ${u.available ? "update available \u2014 run `lua update`" : "up to date"}`);
32043
+ const updateRows = [
32044
+ row(`Current: ${u.current}`),
32045
+ row(`Latest: ${u.latest ?? "unknown"}`),
32046
+ row(u.available ? `${WARN} update available \u2014 run \`lua update\`` : `${TICK} up to date`)
32047
+ ];
31174
32048
  if (u.lastCheckedAt) {
31175
- lines.push(` Last checked ${u.lastCheckedAt}${u.fromCache ? " (cache)" : ""}`);
32049
+ updateRows.push(row(`Last checked: ${u.lastCheckedAt}${u.fromCache ? " (cache)" : ""}`, true));
31176
32050
  }
31177
- lines.push("");
32051
+ blocks.push(section("Updates", updateRows));
31178
32052
  const a = report.auth;
31179
- lines.push("Auth");
32053
+ const authRows = [];
31180
32054
  if (a.source) {
31181
- lines.push(` Key source ${a.source}`);
31182
32055
  if (a.authenticated) {
31183
- lines.push(` Email ${a.email ?? "unknown"}`);
31184
- lines.push(` User ID ${a.userId ?? "unknown"}`);
32056
+ authRows.push(row(`${TICK} authenticated${a.reachabilityMs !== null ? ` (${a.reachabilityMs}ms)` : ""}`));
32057
+ authRows.push(row(`Key source: ${a.source}`));
32058
+ authRows.push(row(`Email: ${a.email ?? "unknown"}`));
31185
32059
  if (a.organizations.length > 0) {
31186
- const orgNames = a.organizations.map((o) => o.name || o.id).filter(Boolean).join(", ");
31187
- lines.push(` Organizations ${a.organizations.length} (${orgNames})`);
32060
+ const orgNames = a.organizations.map((o) => o.name || o.id).filter(Boolean);
32061
+ const shown = orgNames.slice(0, 4).join(", ");
32062
+ const more = orgNames.length > 4 ? `, ${chalk3.dim(`+${orgNames.length - 4} more`)}` : "";
32063
+ authRows.push(row(`Organizations: ${a.organizations.length} (${shown}${more})`));
31188
32064
  } else {
31189
- lines.push(` Organizations 0`);
32065
+ authRows.push(row(`Organizations: 0`));
31190
32066
  }
31191
- lines.push(` Status authenticated${a.reachabilityMs !== null ? ` (${a.reachabilityMs}ms)` : ""}`);
32067
+ authRows.push(row(`User ID: ${a.userId ?? "unknown"}`, true));
31192
32068
  } else if (a.serverReachable) {
31193
- lines.push(` Status key rejected by server${a.reachabilityMs !== null ? ` (${a.reachabilityMs}ms)` : ""}`);
32069
+ authRows.push(row(`${CROSS} key rejected by server${a.reachabilityMs !== null ? ` (${a.reachabilityMs}ms)` : ""}`));
32070
+ authRows.push(row(`Key source: ${a.source}`));
31194
32071
  } else {
31195
- lines.push(` Status key found, server unreachable`);
32072
+ authRows.push(row(`${WARN} key found, server unreachable`));
32073
+ authRows.push(row(`Key source: ${a.source}`));
31196
32074
  }
31197
32075
  } else {
31198
- lines.push(` Status no API key configured \u2014 run \`lua auth configure\``);
32076
+ authRows.push(row(`${WARN} no API key \u2014 run \`lua auth configure\``));
31199
32077
  if (a.serverReachable !== null) {
31200
- lines.push(` Server ${a.serverReachable ? "reachable" : "unreachable"}${a.reachabilityMs !== null ? ` (${a.reachabilityMs}ms)` : ""}`);
32078
+ const ms = a.reachabilityMs !== null ? ` (${a.reachabilityMs}ms)` : "";
32079
+ authRows.push(row(`Server: ${a.serverReachable ? "reachable" : "unreachable"}${ms}`, true));
31201
32080
  }
31202
32081
  }
31203
- lines.push("");
32082
+ blocks.push(section("Auth", authRows));
31204
32083
  const p = report.project;
31205
- lines.push("Project");
31206
32084
  if (p.inProject) {
31207
- lines.push(` Path ${p.rootDir}`);
31208
- lines.push(` Config ${p.configPath} (found)`);
31209
- lines.push(` Agent ${p.agentName ?? "unnamed"}${p.agentId ? ` (${p.agentId.substring(0, 8)})` : ""}`);
31210
- if (p.manifest.found) {
31211
- lines.push(` Manifest dist-v2/manifest.json (compiled, ${p.manifest.primitiveCount} primitives)`);
31212
- } else {
31213
- lines.push(` Manifest (never compiled)`);
31214
- }
32085
+ blocks.push(section("Project", [
32086
+ row(`Agent: ${p.agentName ?? "unnamed"}${p.agentId ? ` (${p.agentId.substring(0, 8)})` : ""}`),
32087
+ row(p.manifest.found ? `${TICK} compiled (${p.manifest.primitiveCount} primitives)` : `${WARN} never compiled \u2014 run \`lua compile\``),
32088
+ row(`Config: ${p.configPath}`, true),
32089
+ row(`Path: ${p.rootDir}`, true)
32090
+ ]));
31215
32091
  } else {
31216
- lines.push(` (not in a lua project)`);
31217
- }
31218
- lines.push("");
31219
- for (const section of report.primitives) {
31220
- const label = section.displayName.charAt(0).toUpperCase() + section.displayName.slice(1);
31221
- const localCount = section.local.length;
31222
- const serverCount = section.server.length;
31223
- lines.push(`${pad(label, 22)}${localCount} local ${serverCount} server`);
31224
- if (localCount === 0 && section.orphans.length === 0) {
31225
- lines.push(" (none)");
31226
- lines.push("");
31227
- continue;
31228
- }
31229
- lines.push(` ${pad("name", 22)}${pad("local", 10)}${pad("server", 10)}status`);
31230
- lines.push("");
31231
- for (const diff of section.diffs) {
32092
+ blocks.push(section("Project", [
32093
+ row(chalk3.dim("not inside a lua project"))
32094
+ ]));
32095
+ }
32096
+ const NAME_MAX = 32;
32097
+ for (const sec of report.primitives) {
32098
+ const label = sec.displayName.charAt(0).toUpperCase() + sec.displayName.slice(1);
32099
+ const title2 = `${label} ${chalk3.dim(`(${sec.local.length} local \xB7 ${sec.server.length} server)`)}`;
32100
+ const entries = [];
32101
+ for (const diff of sec.diffs) {
31232
32102
  const sv = diff.serverVersion ?? "--";
31233
- lines.push(` ${pad(diff.name, 22)}${pad(diff.localVersion, 10)}${pad(sv, 10)}${diff.status}`);
32103
+ const badge = diff.status === "synced" ? `${TICK} synced` : diff.status === "ahead" ? `${WARN} ahead` : diff.status === "behind" ? `${WARN} behind` : `${WARN} not deployed`;
32104
+ entries.push({
32105
+ name: diff.name,
32106
+ ver: `${diff.localVersion} \u2192 ${sv}`,
32107
+ badge
32108
+ });
31234
32109
  }
31235
- for (const orphan of section.orphans) {
31236
- const serverEntry = section.server.find((s) => s.name === orphan.name);
32110
+ for (const orphan of sec.orphans) {
32111
+ const serverEntry = sec.server.find((s) => s.name === orphan.name);
31237
32112
  const sv = serverEntry?.activeVersion ?? "--";
31238
- lines.push(` ${pad(orphan.name, 22)}${pad("--", 10)}${pad(sv, 10)}server only${orphan.critical ? " \u26A0 causes errors" : ""}`);
32113
+ const note = orphan.critical ? `${CROSS} server only (causes errors)` : `${WARN} server only`;
32114
+ entries.push({
32115
+ name: orphan.name,
32116
+ ver: `-- \u2192 ${sv}`,
32117
+ badge: note
32118
+ });
31239
32119
  }
31240
- lines.push("");
31241
- }
31242
- const personaLabel = report.persona.status === "synced" ? "[synced]" : report.persona.status === "drift" ? "[drift detected] Local differs from server" : "[unknown]";
31243
- lines.push(`Persona ${personaLabel}`);
31244
- const backupLabel = report.backup.status === "synced" ? "[synced]" : report.backup.status === "out-of-sync" ? "[out of sync] Source files changed since last push" : report.backup.status === "never-compiled" ? "[never-compiled] Run `lua compile` first" : "[unknown]";
31245
- lines.push(`Backup ${backupLabel}`);
31246
- lines.push(`Telemetry ${report.telemetry.enabled ? "enabled" : "disabled"}${report.telemetry.envOverride ? " (LUA_TELEMETRY override)" : ""}`);
31247
- lines.push("");
32120
+ const nameW = Math.min(NAME_MAX, entries.reduce((m, e) => Math.max(m, e.name.length), 0));
32121
+ const verW = entries.reduce((m, e) => Math.max(m, e.ver.length), 0);
32122
+ const rows = entries.map((e) => row(`${pad(truncate2(e.name, nameW), nameW)} ${pad(e.ver, verW)} ${e.badge}`));
32123
+ blocks.push(section(title2, rows));
32124
+ }
32125
+ const personaRow = report.persona.status === "synced" ? row(`Persona: ${TICK} synced`) : report.persona.status === "drift" ? row(`Persona: ${WARN} drift \u2014 local differs from server`) : row(`Persona: ${chalk3.dim("unknown")}`);
32126
+ const backupRow = report.backup.status === "synced" ? row(`Backup: ${TICK} synced`) : report.backup.status === "out-of-sync" ? row(`Backup: ${WARN} out of sync \u2014 source changed since last push`) : report.backup.status === "never-compiled" ? row(`Backup: ${WARN} never compiled \u2014 run \`lua compile\``) : row(`Backup: ${chalk3.dim("unknown")}`);
32127
+ blocks.push(section("State", [
32128
+ personaRow,
32129
+ backupRow,
32130
+ row(`Telemetry: ${report.telemetry.enabled ? "enabled" : "disabled"}${report.telemetry.envOverride ? " (LUA_TELEMETRY override)" : ""}`)
32131
+ ]));
31248
32132
  if (report.warnings.length > 0) {
31249
- lines.push("Warnings");
31250
- for (const w of report.warnings) {
31251
- lines.push(` - ${w}`);
31252
- }
31253
- lines.push("");
32133
+ blocks.push(section(chalk3.yellow("Warnings"), report.warnings.map((w) => row(chalk3.yellow(w)))));
31254
32134
  }
31255
32135
  if (report.hints.length > 0) {
31256
- lines.push("Next steps");
31257
- for (const h of report.hints) {
31258
- lines.push(` - ${h.reason}: \`${h.command}\``);
31259
- }
31260
- lines.push("");
32136
+ blocks.push(section("Next steps", report.hints.map((h) => row(`${h.reason}: ${chalk3.cyan(h.command)}`))));
31261
32137
  }
31262
- console.log(lines.join("\n"));
32138
+ const title = chalk3.bold("lua status");
32139
+ return [
32140
+ "",
32141
+ title,
32142
+ "",
32143
+ ...blocks.flatMap((b) => [
32144
+ ...b,
32145
+ ""
32146
+ ]),
32147
+ ""
32148
+ ].join("\n");
32149
+ }
32150
+ __name(renderHuman, "renderHuman");
32151
+ function printHuman(report) {
32152
+ console.log(renderHuman(report));
31263
32153
  }
31264
32154
  __name(printHuman, "printHuman");
31265
32155
  async function statusCommand(options) {
@@ -32157,6 +33047,696 @@ async function deleteWebhookInteractive(context, config) {
32157
33047
  }
32158
33048
  __name(deleteWebhookInteractive, "deleteWebhookInteractive");
32159
33049
 
33050
+ // src/commands/triggers.ts
33051
+ init_cli();
33052
+ init_constants();
33053
+ init_command_utils();
33054
+ init_analytics();
33055
+ var ACCEPTED_TIMEOUT_MS = 12e4;
33056
+ var DEFAULT_LOGS_LIMIT = 20;
33057
+ function parseLimitOption(raw) {
33058
+ if (raw === void 0 || raw === null || raw === "") return void 0;
33059
+ const n = Number.parseInt(String(raw), 10);
33060
+ return Number.isFinite(n) && n > 0 ? n : void 0;
33061
+ }
33062
+ __name(parseLimitOption, "parseLimitOption");
33063
+ function isLegacyIntegrationAction(action) {
33064
+ if (!action) return false;
33065
+ const normalized = normalizeArg("integrations.webhooks.action", action);
33066
+ if (!normalized) return false;
33067
+ return getCanonicalValues("integrations.webhooks.action").includes(normalized) && !getCanonicalValues("triggers.action").includes(normalized);
33068
+ }
33069
+ __name(isLegacyIntegrationAction, "isLegacyIntegrationAction");
33070
+ async function triggersCommand(action, cmdObj) {
33071
+ return withErrorHandling(async () => {
33072
+ const hasIntegrationFlags = !!(cmdObj?.webhookId || cmdObj?.connectionId || cmdObj?.connection);
33073
+ if (isLegacyIntegrationAction(action) || hasIntegrationFlags) {
33074
+ console.log("\u2139\uFE0F Integration triggers now live at `lua integrations webhooks <action>` (also reachable as `lua integrations triggers <action>`).");
33075
+ trackEvent("cli_triggers_integration_redirect", {
33076
+ action: action || null,
33077
+ has_integration_flags: hasIntegrationFlags
33078
+ });
33079
+ return;
33080
+ }
33081
+ const options = {
33082
+ name: cmdObj?.name || void 0,
33083
+ description: cmdObj?.description || void 0,
33084
+ instruction: cmdObj?.instruction || void 0,
33085
+ trigger: cmdObj?.trigger || void 0,
33086
+ limit: parseLimitOption(cmdObj?.limit),
33087
+ json: cmdObj?.json === true,
33088
+ force: cmdObj?.force === true
33089
+ };
33090
+ const { agentId, apiKey } = await initializeCommand();
33091
+ const context = {
33092
+ agentId,
33093
+ apiKey
33094
+ };
33095
+ if (action) {
33096
+ await executeNonInteractive6(context, action, options);
33097
+ } else {
33098
+ await manageTriggersInteractive(context);
33099
+ }
33100
+ }, "triggers");
33101
+ }
33102
+ __name(triggersCommand, "triggersCommand");
33103
+ function triggerApiFor(context) {
33104
+ return new TriggerApi(BASE_URLS.API, context.apiKey, context.agentId);
33105
+ }
33106
+ __name(triggerApiFor, "triggerApiFor");
33107
+ function triggerType(trigger) {
33108
+ return trigger.activeVersionId ? "SDK" : "URL";
33109
+ }
33110
+ __name(triggerType, "triggerType");
33111
+ async function fetchTriggersCore(context) {
33112
+ const triggerApi = triggerApiFor(context);
33113
+ const response = await triggerApi.getTriggers();
33114
+ if (!response.success || !response.data) {
33115
+ console.error(`\u274C Failed to fetch triggers: ${response.error?.message || "Unknown error"}`);
33116
+ return null;
33117
+ }
33118
+ return response.data.triggers || [];
33119
+ }
33120
+ __name(fetchTriggersCore, "fetchTriggersCore");
33121
+ function resolveTrigger(triggers, ref) {
33122
+ const trigger = triggers.find((t) => t.id === ref || t.name === ref);
33123
+ if (!trigger) {
33124
+ console.error(`\u274C Trigger "${ref}" not found`);
33125
+ console.log("\nAvailable triggers:");
33126
+ triggers.forEach((t) => console.log(` - ${t.name} (${t.id})`));
33127
+ return null;
33128
+ }
33129
+ return trigger;
33130
+ }
33131
+ __name(resolveTrigger, "resolveTrigger");
33132
+ function displayTriggersCore(triggers, json) {
33133
+ trackEvent("cli_triggers_list", {
33134
+ triggers_count: triggers.length,
33135
+ json_output: json
33136
+ });
33137
+ if (json) {
33138
+ console.log(JSON.stringify(triggers.map((t) => ({
33139
+ id: t.id,
33140
+ name: t.name,
33141
+ description: t.description,
33142
+ instruction: t.instruction,
33143
+ type: triggerType(t),
33144
+ active: t.active,
33145
+ url: t.url,
33146
+ createdAt: t.createdAt
33147
+ })), null, 2));
33148
+ return;
33149
+ }
33150
+ console.log("\n" + "=".repeat(60));
33151
+ console.log("\u26A1 Triggers");
33152
+ console.log("=".repeat(60) + "\n");
33153
+ if (triggers.length === 0) {
33154
+ console.log("\u2139\uFE0F No triggers found.");
33155
+ console.log("\u{1F4A1} Create one with 'lua triggers create --name <name>'.\n");
33156
+ console.log("=".repeat(60));
33157
+ return;
33158
+ }
33159
+ for (const trigger of triggers) {
33160
+ console.log(`\u26A1 ${trigger.name}`);
33161
+ console.log(` Trigger ID: ${trigger.id}`);
33162
+ console.log(` Type: ${triggerType(trigger)}`);
33163
+ console.log(` Status: ${trigger.active ? "\u2705 active" : "\u{1F6AB} inactive"}`);
33164
+ if (trigger.instruction) {
33165
+ console.log(` Instruction: ${trigger.instruction}`);
33166
+ }
33167
+ console.log(` URL: ${trigger.url}`);
33168
+ console.log(` Created: ${new Date(trigger.createdAt).toLocaleString()}`);
33169
+ console.log();
33170
+ }
33171
+ console.log("=".repeat(60));
33172
+ }
33173
+ __name(displayTriggersCore, "displayTriggersCore");
33174
+ async function createTriggerCore(context, name, description, instruction) {
33175
+ writeProgress(`\u{1F504} Creating trigger "${name}"...`);
33176
+ const triggerApi = triggerApiFor(context);
33177
+ const response = await triggerApi.createTrigger({
33178
+ name,
33179
+ description,
33180
+ instruction
33181
+ });
33182
+ trackEvent("cli_triggers_create", {
33183
+ trigger_name: name,
33184
+ has_description: !!description,
33185
+ has_instruction: !!instruction,
33186
+ success: !!response.success
33187
+ });
33188
+ if (!response.success || !response.data) {
33189
+ console.error(`\u274C Failed to create trigger: ${response.error?.message || "Unknown error"}`);
33190
+ return false;
33191
+ }
33192
+ const trigger = response.data;
33193
+ writeSuccess(`\u2705 Trigger "${trigger.name}" created`);
33194
+ if (trigger.instruction) {
33195
+ writeInfo(`\u{1F4DD} Instruction sent to the agent on each fire: ${trigger.instruction}`);
33196
+ }
33197
+ console.log("\n" + "=".repeat(60));
33198
+ console.log("\u{1F517} Trigger URL (paste it anywhere):");
33199
+ console.log(`
33200
+ ${trigger.url}
33201
+ `);
33202
+ console.log("=".repeat(60));
33203
+ writeHintBlock({
33204
+ headline: "Trigger is live. Fire it, then inspect executions:",
33205
+ lines: [
33206
+ {
33207
+ label: "Fire:",
33208
+ command: `curl -X POST ${trigger.url} -H 'Content-Type: application/json' -d '{"hello":"world"}'`
33209
+ },
33210
+ {
33211
+ label: "Inspect:",
33212
+ command: `lua triggers logs --trigger ${trigger.name}`
33213
+ }
33214
+ ],
33215
+ when: "success"
33216
+ });
33217
+ writeInfo(`\u{1F4A1} If this URL leaks, run 'lua triggers rotate-token --trigger ${trigger.name}' to invalidate it and mint a new one.`);
33218
+ return true;
33219
+ }
33220
+ __name(createTriggerCore, "createTriggerCore");
33221
+ function executionStatusDisplay(execution) {
33222
+ switch (execution.status) {
33223
+ case "completed":
33224
+ return {
33225
+ emoji: "\u2705",
33226
+ label: "COMPLETED"
33227
+ };
33228
+ case "failed":
33229
+ return {
33230
+ emoji: "\u274C",
33231
+ label: "FAILED"
33232
+ };
33233
+ case "skipped_inactive":
33234
+ return {
33235
+ emoji: "\u{1F6AB}",
33236
+ label: "SKIPPED (trigger inactive)"
33237
+ };
33238
+ case "rejected_unverified":
33239
+ return {
33240
+ emoji: "\u26D4",
33241
+ label: "REJECTED (verify failed \u2192 401)"
33242
+ };
33243
+ case "skipped_filtered":
33244
+ return {
33245
+ emoji: "\u{1F507}",
33246
+ label: "SKIPPED (filtered out)"
33247
+ };
33248
+ case "accepted": {
33249
+ const age = Date.now() - new Date(execution.receivedAt).getTime();
33250
+ if (age > ACCEPTED_TIMEOUT_MS) {
33251
+ return {
33252
+ emoji: "\u23F3",
33253
+ label: "TIMED OUT (no completion recorded)"
33254
+ };
33255
+ }
33256
+ return {
33257
+ emoji: "\u{1F504}",
33258
+ label: "ACCEPTED (in flight)"
33259
+ };
33260
+ }
33261
+ default:
33262
+ return {
33263
+ emoji: "\u2753",
33264
+ label: String(execution.status).toUpperCase()
33265
+ };
33266
+ }
33267
+ }
33268
+ __name(executionStatusDisplay, "executionStatusDisplay");
33269
+ function snippet(value, maxLength = 100) {
33270
+ const text = typeof value === "string" ? value : JSON.stringify(value);
33271
+ if (text === void 0) return "";
33272
+ return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
33273
+ }
33274
+ __name(snippet, "snippet");
33275
+ async function fetchAndDisplayLogsCore(context, trigger, limit, json) {
33276
+ const triggerApi = triggerApiFor(context);
33277
+ const response = await triggerApi.getTriggerExecutions(trigger.id, {
33278
+ limit
33279
+ });
33280
+ trackEvent("cli_triggers_logs", {
33281
+ trigger_name: trigger.name,
33282
+ limit,
33283
+ json_output: json,
33284
+ success: !!response.success
33285
+ });
33286
+ if (!response.success || !response.data) {
33287
+ console.error(`\u274C Failed to fetch executions: ${response.error?.message || "Unknown error"}`);
33288
+ return false;
33289
+ }
33290
+ const { executions = [], total } = response.data;
33291
+ if (json) {
33292
+ console.log(JSON.stringify(response.data, null, 2));
33293
+ return true;
33294
+ }
33295
+ if (executions.length === 0) {
33296
+ console.log(`\u2139\uFE0F No executions found for ${trigger.name}.`);
33297
+ console.log(`\u{1F4A1} Fire it: curl -X POST ${trigger.url} -H 'Content-Type: application/json' -d '{"hello":"world"}'`);
33298
+ return true;
33299
+ }
33300
+ console.log("\n" + "=".repeat(60));
33301
+ console.log(`\u{1F4CA} Executions for ${trigger.name}`);
33302
+ if (trigger.instruction) {
33303
+ console.log(`\u{1F4DD} Instruction: ${trigger.instruction}`);
33304
+ }
33305
+ console.log("=".repeat(60) + "\n");
33306
+ executions.forEach((execution, index) => {
33307
+ const { emoji, label } = executionStatusDisplay(execution);
33308
+ console.log(`${index + 1}. ${emoji} ${label}`);
33309
+ console.log(` Execution ID: ${execution.id}`);
33310
+ console.log(` Received: ${new Date(execution.receivedAt).toLocaleString()}`);
33311
+ if (execution.duration !== void 0) {
33312
+ console.log(` Duration: ${Math.round(execution.duration / 1e3)}s`);
33313
+ }
33314
+ if (execution.payload !== void 0) {
33315
+ console.log(` Payload: ${snippet(execution.payload)}`);
33316
+ }
33317
+ if (execution.responseText) {
33318
+ console.log(` Response: ${snippet(execution.responseText)}`);
33319
+ }
33320
+ if (execution.toolsUsed && execution.toolsUsed.length > 0) {
33321
+ console.log(` Tools: ${execution.toolsUsed.join(", ")}`);
33322
+ }
33323
+ if (execution.error) {
33324
+ console.log(` Error: ${execution.error}`);
33325
+ }
33326
+ console.log();
33327
+ });
33328
+ console.log("=".repeat(60));
33329
+ console.log(`Showing ${executions.length} of ${total} executions`);
33330
+ return true;
33331
+ }
33332
+ __name(fetchAndDisplayLogsCore, "fetchAndDisplayLogsCore");
33333
+ async function activateTriggerCore(context, trigger) {
33334
+ writeProgress(`\u{1F504} Activating trigger "${trigger.name}"...`);
33335
+ const triggerApi = triggerApiFor(context);
33336
+ const response = await triggerApi.activateTrigger(trigger.id);
33337
+ trackEvent("cli_triggers_activate", {
33338
+ trigger_name: trigger.name,
33339
+ success: !!response.success
33340
+ });
33341
+ if (response.success) {
33342
+ writeSuccess(`\u2705 Trigger "${trigger.name}" activated successfully`);
33343
+ writeInfo("\u{1F4A1} The trigger is now enabled and can receive requests.");
33344
+ return true;
33345
+ } else {
33346
+ console.error(`\u274C Failed to activate trigger: ${response.error?.message || "Unknown error"}`);
33347
+ return false;
33348
+ }
33349
+ }
33350
+ __name(activateTriggerCore, "activateTriggerCore");
33351
+ async function deactivateTriggerCore(context, trigger) {
33352
+ writeProgress(`\u{1F504} Deactivating trigger "${trigger.name}"...`);
33353
+ const triggerApi = triggerApiFor(context);
33354
+ const response = await triggerApi.deactivateTrigger(trigger.id);
33355
+ trackEvent("cli_triggers_deactivate", {
33356
+ trigger_name: trigger.name,
33357
+ success: !!response.success
33358
+ });
33359
+ if (response.success) {
33360
+ writeSuccess(`\u2705 Trigger "${trigger.name}" deactivated successfully`);
33361
+ writeInfo("\u{1F4A1} Incoming requests will be recorded as skipped until you reactivate it.");
33362
+ return true;
33363
+ } else {
33364
+ console.error(`\u274C Failed to deactivate trigger: ${response.error?.message || "Unknown error"}`);
33365
+ return false;
33366
+ }
33367
+ }
33368
+ __name(deactivateTriggerCore, "deactivateTriggerCore");
33369
+ async function rotateTriggerTokenCore(context, trigger) {
33370
+ writeProgress(`\u{1F504} Rotating token for trigger "${trigger.name}"...`);
33371
+ const triggerApi = triggerApiFor(context);
33372
+ const response = await triggerApi.rotateTriggerToken(trigger.id);
33373
+ trackEvent("cli_triggers_rotate_token", {
33374
+ trigger_name: trigger.name,
33375
+ success: !!response.success
33376
+ });
33377
+ if (!response.success || !response.data) {
33378
+ console.error(`\u274C Failed to rotate token: ${response.error?.message || "Unknown error"}`);
33379
+ return false;
33380
+ }
33381
+ writeSuccess(`\u2705 Token rotated for "${trigger.name}" \u2014 the old URL no longer works`);
33382
+ console.log("\n" + "=".repeat(60));
33383
+ console.log("\u{1F517} New trigger URL (update it everywhere it was pasted):");
33384
+ console.log(`
33385
+ ${response.data.url}
33386
+ `);
33387
+ console.log("=".repeat(60));
33388
+ return true;
33389
+ }
33390
+ __name(rotateTriggerTokenCore, "rotateTriggerTokenCore");
33391
+ async function deleteTriggerCore(context, trigger) {
33392
+ writeProgress(`\u{1F5D1}\uFE0F Deleting trigger "${trigger.name}"...`);
33393
+ const triggerApi = triggerApiFor(context);
33394
+ const response = await triggerApi.deleteTrigger(trigger.id);
33395
+ trackEvent("cli_triggers_delete", {
33396
+ trigger_name: trigger.name,
33397
+ success: !!response.success
33398
+ });
33399
+ if (!response.success || !response.data) {
33400
+ console.error(`\u274C Delete Error: ${response.error?.message || "Unknown error"}`);
33401
+ return false;
33402
+ }
33403
+ if (response.data.deactivated) {
33404
+ writeSuccess(`\u2705 Trigger "${trigger.name}" deactivated`);
33405
+ writeInfo("\u{1F4A1} It has deployed versions, so it was deactivated instead of deleted. Its URL no longer fires.");
33406
+ return true;
33407
+ }
33408
+ writeSuccess(`\u2705 Trigger "${trigger.name}" deleted successfully`);
33409
+ writeInfo("\u{1F4A1} Its URL is dead. Execution history is retained until TTL expiry.");
33410
+ return true;
33411
+ }
33412
+ __name(deleteTriggerCore, "deleteTriggerCore");
33413
+ async function promptTriggerSelection(triggers, message) {
33414
+ const answer = await safePrompt([
33415
+ {
33416
+ type: "list",
33417
+ name: "selectedTrigger",
33418
+ message,
33419
+ choices: triggers.map((trigger) => ({
33420
+ name: `${trigger.name} (${trigger.id})${trigger.active ? "" : " [inactive]"}`,
33421
+ value: trigger
33422
+ }))
33423
+ }
33424
+ ]);
33425
+ return answer?.selectedTrigger || null;
33426
+ }
33427
+ __name(promptTriggerSelection, "promptTriggerSelection");
33428
+ async function executeNonInteractive6(context, action, options) {
33429
+ const normalizedAction = validateOrSuggest("triggers.action", action);
33430
+ if (normalizedAction === "list") {
33431
+ const triggers2 = await fetchTriggersCore(context);
33432
+ if (!triggers2) throw new Error("Failed to fetch triggers");
33433
+ displayTriggersCore(triggers2, options.json);
33434
+ return;
33435
+ }
33436
+ if (normalizedAction === "create") {
33437
+ if (!options.name) {
33438
+ console.error("\u274C --name is required for create action");
33439
+ console.log('\nUsage: lua triggers create --name order-created [--description "Fires on new orders"] [--instruction "Reply with the current date and time"]');
33440
+ throw new Error("--name is required for create action");
33441
+ }
33442
+ const success2 = await createTriggerCore(context, options.name, options.description, options.instruction);
33443
+ if (!success2) throw new Error("Failed to create trigger");
33444
+ return;
33445
+ }
33446
+ if (!options.trigger) {
33447
+ console.error(`\u274C --trigger is required for action "${normalizedAction}"`);
33448
+ console.log(`
33449
+ Usage: lua triggers ${normalizedAction} --trigger <name|id>`);
33450
+ throw new Error(`--trigger is required for action "${normalizedAction}"`);
33451
+ }
33452
+ const triggers = await fetchTriggersCore(context);
33453
+ if (!triggers) throw new Error("Failed to fetch triggers");
33454
+ const selectedTrigger = resolveTrigger(triggers, options.trigger);
33455
+ if (!selectedTrigger) throw new Error(`Trigger "${options.trigger}" not found`);
33456
+ switch (normalizedAction) {
33457
+ case "logs": {
33458
+ const success2 = await fetchAndDisplayLogsCore(context, selectedTrigger, options.limit ?? DEFAULT_LOGS_LIMIT, options.json);
33459
+ if (!success2) throw new Error("Failed to fetch trigger executions");
33460
+ break;
33461
+ }
33462
+ case "activate": {
33463
+ const success2 = await activateTriggerCore(context, selectedTrigger);
33464
+ if (!success2) throw new Error("Failed to activate trigger");
33465
+ break;
33466
+ }
33467
+ case "deactivate": {
33468
+ const success2 = await deactivateTriggerCore(context, selectedTrigger);
33469
+ if (!success2) throw new Error("Failed to deactivate trigger");
33470
+ break;
33471
+ }
33472
+ case "rotate-token": {
33473
+ const success2 = await rotateTriggerTokenCore(context, selectedTrigger);
33474
+ if (!success2) throw new Error("Failed to rotate trigger token");
33475
+ break;
33476
+ }
33477
+ case "delete": {
33478
+ if (!options.force) {
33479
+ const confirmAnswer = await safePrompt([
33480
+ {
33481
+ type: "confirm",
33482
+ name: "confirm",
33483
+ message: `Are you sure you want to delete "${selectedTrigger.name}"? Its URL will stop working immediately.`,
33484
+ default: false
33485
+ }
33486
+ ]);
33487
+ if (!confirmAnswer || !confirmAnswer.confirm) {
33488
+ console.log("\n\u274C Deletion cancelled.\n");
33489
+ return;
33490
+ }
33491
+ }
33492
+ const success2 = await deleteTriggerCore(context, selectedTrigger);
33493
+ if (!success2) throw new Error("Failed to delete trigger");
33494
+ break;
33495
+ }
33496
+ }
33497
+ }
33498
+ __name(executeNonInteractive6, "executeNonInteractive");
33499
+ async function manageTriggersInteractive(context) {
33500
+ let continueManaging = true;
33501
+ while (continueManaging) {
33502
+ console.log("\n" + "=".repeat(60));
33503
+ console.log("\u26A1 Triggers");
33504
+ console.log("=".repeat(60) + "\n");
33505
+ const actionAnswer = await safePrompt([
33506
+ {
33507
+ type: "list",
33508
+ name: "action",
33509
+ message: "What would you like to do?",
33510
+ choices: [
33511
+ {
33512
+ name: "\u{1F441}\uFE0F View triggers",
33513
+ value: "list"
33514
+ },
33515
+ {
33516
+ name: "\u2795 Create a trigger",
33517
+ value: "create"
33518
+ },
33519
+ {
33520
+ name: "\u{1F4CA} View execution logs",
33521
+ value: "logs"
33522
+ },
33523
+ {
33524
+ name: "\u2705 Activate a trigger",
33525
+ value: "activate"
33526
+ },
33527
+ {
33528
+ name: "\u{1F6AB} Deactivate a trigger",
33529
+ value: "deactivate"
33530
+ },
33531
+ {
33532
+ name: "\u{1F501} Rotate a trigger token",
33533
+ value: "rotate-token"
33534
+ },
33535
+ {
33536
+ name: "\u{1F5D1}\uFE0F Delete a trigger",
33537
+ value: "delete"
33538
+ },
33539
+ {
33540
+ name: "\u274C Exit",
33541
+ value: "exit"
33542
+ }
33543
+ ]
33544
+ }
33545
+ ]);
33546
+ if (!actionAnswer) return;
33547
+ const { action } = actionAnswer;
33548
+ switch (action) {
33549
+ case "list":
33550
+ await viewTriggersInteractive(context);
33551
+ break;
33552
+ case "create":
33553
+ await createTriggerInteractive(context);
33554
+ break;
33555
+ case "logs":
33556
+ await viewLogsInteractive(context);
33557
+ break;
33558
+ case "activate":
33559
+ await activateTriggerInteractive(context);
33560
+ break;
33561
+ case "deactivate":
33562
+ await deactivateTriggerInteractive(context);
33563
+ break;
33564
+ case "rotate-token":
33565
+ await rotateTriggerTokenInteractive(context);
33566
+ break;
33567
+ case "delete":
33568
+ await deleteTriggerInteractive(context);
33569
+ break;
33570
+ case "exit":
33571
+ continueManaging = false;
33572
+ console.log("\n\u{1F44B} Goodbye!\n");
33573
+ break;
33574
+ }
33575
+ }
33576
+ }
33577
+ __name(manageTriggersInteractive, "manageTriggersInteractive");
33578
+ async function viewTriggersInteractive(context) {
33579
+ writeProgress("\u{1F504} Loading triggers...");
33580
+ const triggers = await fetchTriggersCore(context);
33581
+ if (triggers) {
33582
+ displayTriggersCore(triggers, false);
33583
+ console.log();
33584
+ }
33585
+ await safePrompt([
33586
+ {
33587
+ type: "input",
33588
+ name: "continue",
33589
+ message: "Press Enter to continue..."
33590
+ }
33591
+ ]);
33592
+ }
33593
+ __name(viewTriggersInteractive, "viewTriggersInteractive");
33594
+ async function createTriggerInteractive(context) {
33595
+ const answers = await safePrompt([
33596
+ {
33597
+ type: "input",
33598
+ name: "name",
33599
+ message: "Trigger name:",
33600
+ validate: /* @__PURE__ */ __name((input) => input.trim().length > 0 ? true : "Name is required", "validate")
33601
+ },
33602
+ {
33603
+ type: "input",
33604
+ name: "description",
33605
+ message: "Description (optional):"
33606
+ },
33607
+ {
33608
+ type: "input",
33609
+ name: "instruction",
33610
+ message: "Instruction sent to the agent on each fire (optional):"
33611
+ }
33612
+ ]);
33613
+ if (!answers || !answers.name?.trim()) return;
33614
+ await createTriggerCore(context, answers.name.trim(), answers.description?.trim() || void 0, answers.instruction?.trim() || void 0);
33615
+ await safePrompt([
33616
+ {
33617
+ type: "input",
33618
+ name: "continue",
33619
+ message: "Press Enter to continue..."
33620
+ }
33621
+ ]);
33622
+ }
33623
+ __name(createTriggerInteractive, "createTriggerInteractive");
33624
+ async function viewLogsInteractive(context) {
33625
+ const triggers = await fetchTriggersCore(context);
33626
+ if (!triggers || triggers.length === 0) {
33627
+ console.log("\n\u2139\uFE0F No triggers found.\n");
33628
+ return;
33629
+ }
33630
+ const selectedTrigger = await promptTriggerSelection(triggers, "Select a trigger to view executions:");
33631
+ if (!selectedTrigger) return;
33632
+ writeProgress(`\u{1F504} Loading executions for ${selectedTrigger.name}...`);
33633
+ await fetchAndDisplayLogsCore(context, selectedTrigger, DEFAULT_LOGS_LIMIT, false);
33634
+ await safePrompt([
33635
+ {
33636
+ type: "input",
33637
+ name: "continue",
33638
+ message: "Press Enter to continue..."
33639
+ }
33640
+ ]);
33641
+ }
33642
+ __name(viewLogsInteractive, "viewLogsInteractive");
33643
+ async function activateTriggerInteractive(context) {
33644
+ const triggers = await fetchTriggersCore(context);
33645
+ if (!triggers || triggers.length === 0) {
33646
+ console.log("\n\u2139\uFE0F No triggers found.\n");
33647
+ return;
33648
+ }
33649
+ const selectedTrigger = await promptTriggerSelection(triggers, "Select a trigger to activate:");
33650
+ if (!selectedTrigger) return;
33651
+ await activateTriggerCore(context, selectedTrigger);
33652
+ }
33653
+ __name(activateTriggerInteractive, "activateTriggerInteractive");
33654
+ async function deactivateTriggerInteractive(context) {
33655
+ const triggers = await fetchTriggersCore(context);
33656
+ if (!triggers || triggers.length === 0) {
33657
+ console.log("\n\u2139\uFE0F No triggers found.\n");
33658
+ return;
33659
+ }
33660
+ const selectedTrigger = await promptTriggerSelection(triggers, "Select a trigger to deactivate:");
33661
+ if (!selectedTrigger) return;
33662
+ const confirmAnswer = await safePrompt([
33663
+ {
33664
+ type: "confirm",
33665
+ name: "confirm",
33666
+ message: `Are you sure you want to deactivate "${selectedTrigger.name}"? It will stop receiving requests.`,
33667
+ default: false
33668
+ }
33669
+ ]);
33670
+ if (!confirmAnswer || !confirmAnswer.confirm) {
33671
+ console.log("\n\u274C Deactivation cancelled.\n");
33672
+ return;
33673
+ }
33674
+ await deactivateTriggerCore(context, selectedTrigger);
33675
+ }
33676
+ __name(deactivateTriggerInteractive, "deactivateTriggerInteractive");
33677
+ async function rotateTriggerTokenInteractive(context) {
33678
+ const triggers = await fetchTriggersCore(context);
33679
+ if (!triggers || triggers.length === 0) {
33680
+ console.log("\n\u2139\uFE0F No triggers found.\n");
33681
+ return;
33682
+ }
33683
+ const selectedTrigger = await promptTriggerSelection(triggers, "Select a trigger to rotate its token:");
33684
+ if (!selectedTrigger) return;
33685
+ const confirmAnswer = await safePrompt([
33686
+ {
33687
+ type: "confirm",
33688
+ name: "confirm",
33689
+ message: `Rotate the token for "${selectedTrigger.name}"? The current URL will stop working immediately.`,
33690
+ default: false
33691
+ }
33692
+ ]);
33693
+ if (!confirmAnswer || !confirmAnswer.confirm) {
33694
+ console.log("\n\u274C Rotation cancelled.\n");
33695
+ return;
33696
+ }
33697
+ await rotateTriggerTokenCore(context, selectedTrigger);
33698
+ await safePrompt([
33699
+ {
33700
+ type: "input",
33701
+ name: "continue",
33702
+ message: "Press Enter to continue..."
33703
+ }
33704
+ ]);
33705
+ }
33706
+ __name(rotateTriggerTokenInteractive, "rotateTriggerTokenInteractive");
33707
+ async function deleteTriggerInteractive(context) {
33708
+ const triggers = await fetchTriggersCore(context);
33709
+ if (!triggers || triggers.length === 0) {
33710
+ console.log("\n\u2139\uFE0F No triggers found.\n");
33711
+ return;
33712
+ }
33713
+ const selectedTrigger = await promptTriggerSelection(triggers, "Select a trigger to delete:");
33714
+ if (!selectedTrigger) return;
33715
+ console.log("\n\u26A0\uFE0F WARNING: You are about to delete a trigger!");
33716
+ console.log("\u26A0\uFE0F Its URL will stop working immediately.\n");
33717
+ const confirmAnswer = await safePrompt([
33718
+ {
33719
+ type: "confirm",
33720
+ name: "confirm",
33721
+ message: `Are you sure you want to delete "${selectedTrigger.name}"?`,
33722
+ default: false
33723
+ }
33724
+ ]);
33725
+ if (!confirmAnswer || !confirmAnswer.confirm) {
33726
+ console.log("\n\u274C Deletion cancelled.\n");
33727
+ return;
33728
+ }
33729
+ await deleteTriggerCore(context, selectedTrigger);
33730
+ await safePrompt([
33731
+ {
33732
+ type: "input",
33733
+ name: "continue",
33734
+ message: "Press Enter to continue..."
33735
+ }
33736
+ ]);
33737
+ }
33738
+ __name(deleteTriggerInteractive, "deleteTriggerInteractive");
33739
+
32160
33740
  // src/commands/devices.ts
32161
33741
  init_cli();
32162
33742
  init_constants();
@@ -32465,7 +34045,7 @@ async function jobsCommand(action, cmdObj) {
32465
34045
  hideVersions
32466
34046
  };
32467
34047
  if (action) {
32468
- await executeNonInteractive6(context, config, action, options);
34048
+ await executeNonInteractive7(context, config, action, options);
32469
34049
  } else {
32470
34050
  await manageProductionJobs(context, config);
32471
34051
  }
@@ -32760,7 +34340,7 @@ async function promptVersionSelection4(versions, activeVersionId) {
32760
34340
  return versionAnswer?.selectedVersion || null;
32761
34341
  }
32762
34342
  __name(promptVersionSelection4, "promptVersionSelection");
32763
- async function executeNonInteractive6(context, config, action, options) {
34343
+ async function executeNonInteractive7(context, config, action, options) {
32764
34344
  const normalizedAction = validateOrSuggest("jobs.action", action);
32765
34345
  const jobs = config.jobs || [];
32766
34346
  if (normalizedAction === "view") {
@@ -32861,7 +34441,7 @@ Usage: lua jobs ${normalizedAction} --job-name <name>`);
32861
34441
  }
32862
34442
  }
32863
34443
  }
32864
- __name(executeNonInteractive6, "executeNonInteractive");
34444
+ __name(executeNonInteractive7, "executeNonInteractive");
32865
34445
  async function manageProductionJobs(context, config) {
32866
34446
  let continueManaging = true;
32867
34447
  while (continueManaging) {
@@ -33249,7 +34829,8 @@ init_analytics();
33249
34829
  async function featuresCommand(action, cmdObj) {
33250
34830
  return withErrorHandling(async () => {
33251
34831
  const options = {
33252
- featureName: cmdObj?.featureName || null
34832
+ featureName: cmdObj?.featureName || null,
34833
+ recipientScope: cmdObj?.recipientScope || void 0
33253
34834
  };
33254
34835
  const { agentId, apiKey } = await initializeCommand();
33255
34836
  const agentApi = new AgentApi(BASE_URLS.API, apiKey);
@@ -33259,7 +34840,7 @@ async function featuresCommand(action, cmdObj) {
33259
34840
  agentApi
33260
34841
  };
33261
34842
  if (action) {
33262
- await executeNonInteractive7(context, action, options);
34843
+ await executeNonInteractive8(context, action, options);
33263
34844
  } else {
33264
34845
  await manageFeaturesInteractive(context);
33265
34846
  }
@@ -33312,6 +34893,13 @@ function viewFeatureCore(feature) {
33312
34893
  console.log("\nContext/Instructions:");
33313
34894
  console.log("\u2500".repeat(60));
33314
34895
  console.log(feature.context);
34896
+ if (feature.config && Object.keys(feature.config).length > 0) {
34897
+ console.log("\nConfig:");
34898
+ console.log("\u2500".repeat(60));
34899
+ for (const [key, value] of Object.entries(feature.config)) {
34900
+ console.log(` ${key}: ${JSON.stringify(value)}`);
34901
+ }
34902
+ }
33315
34903
  console.log("=".repeat(60));
33316
34904
  }
33317
34905
  __name(viewFeatureCore, "viewFeatureCore");
@@ -33353,6 +34941,33 @@ async function disableFeatureCore(context, feature) {
33353
34941
  }
33354
34942
  }
33355
34943
  __name(disableFeatureCore, "disableFeatureCore");
34944
+ async function configureFeatureCore(context, feature, options) {
34945
+ const scope = options.recipientScope;
34946
+ if (!scope) {
34947
+ console.error("\u274C --recipient-scope is required for configure (current_user | anyone)");
34948
+ return false;
34949
+ }
34950
+ if (scope !== "current_user" && scope !== "anyone") {
34951
+ console.error(`\u274C Invalid --recipient-scope "${scope}". Use "current_user" or "anyone".`);
34952
+ return false;
34953
+ }
34954
+ writeProgress(`\u{1F504} Configuring "${feature.title}"...`);
34955
+ try {
34956
+ await context.agentApi.updateAgentFeature(context.agentId, {
34957
+ featureName: feature.name,
34958
+ active: feature.active,
34959
+ config: {
34960
+ recipientScope: scope
34961
+ }
34962
+ });
34963
+ writeSuccess(`\u2705 ${feature.title}: recipientScope = ${scope}`);
34964
+ return true;
34965
+ } catch (error) {
34966
+ console.error(`\u274C Failed to configure feature: ${error}`);
34967
+ return false;
34968
+ }
34969
+ }
34970
+ __name(configureFeatureCore, "configureFeatureCore");
33356
34971
  function findFeature(features, featureId) {
33357
34972
  const normalizedId = featureId.toLowerCase();
33358
34973
  return features.find((f) => f.name.toLowerCase() === normalizedId || f.title.toLowerCase() === normalizedId) || null;
@@ -33373,7 +34988,7 @@ async function promptFeatureSelection(features, message) {
33373
34988
  return answer?.selectedFeature || null;
33374
34989
  }
33375
34990
  __name(promptFeatureSelection, "promptFeatureSelection");
33376
- async function executeNonInteractive7(context, action, options) {
34991
+ async function executeNonInteractive8(context, action, options) {
33377
34992
  const normalizedAction = validateOrSuggest("features.action", action);
33378
34993
  writeProgress("\u{1F504} Loading features...");
33379
34994
  const features = await fetchFeaturesCore(context);
@@ -33413,9 +35028,14 @@ Usage: lua features ${normalizedAction} --feature-name <name>`);
33413
35028
  if (!success2) throw new Error("Operation failed");
33414
35029
  break;
33415
35030
  }
35031
+ case "configure": {
35032
+ const success2 = await configureFeatureCore(context, selectedFeature, options);
35033
+ if (!success2) throw new Error("Operation failed");
35034
+ break;
35035
+ }
33416
35036
  }
33417
35037
  }
33418
- __name(executeNonInteractive7, "executeNonInteractive");
35038
+ __name(executeNonInteractive8, "executeNonInteractive");
33419
35039
  async function manageFeaturesInteractive(context) {
33420
35040
  let continueManaging = true;
33421
35041
  while (continueManaging) {
@@ -33719,7 +35339,7 @@ async function preprocessorsCommand(action, cmdObj) {
33719
35339
  hideVersions
33720
35340
  };
33721
35341
  if (action) {
33722
- await executeNonInteractive8(context, config, action, options);
35342
+ await executeNonInteractive9(context, config, action, options);
33723
35343
  } else {
33724
35344
  await managePreProcessorsInteractive(context, config);
33725
35345
  }
@@ -33921,7 +35541,7 @@ async function promptVersionSelection5(versions, activeVersionId) {
33921
35541
  return answer?.selectedVersion || null;
33922
35542
  }
33923
35543
  __name(promptVersionSelection5, "promptVersionSelection");
33924
- async function executeNonInteractive8(context, config, action, options) {
35544
+ async function executeNonInteractive9(context, config, action, options) {
33925
35545
  const normalizedAction = validateOrSuggest("preprocessors.action", action);
33926
35546
  const preprocessors = config.preprocessors || [];
33927
35547
  if (normalizedAction === "view") {
@@ -34009,7 +35629,7 @@ Usage: lua preprocessors ${normalizedAction} --preprocessor-name <name>`);
34009
35629
  }
34010
35630
  }
34011
35631
  }
34012
- __name(executeNonInteractive8, "executeNonInteractive");
35632
+ __name(executeNonInteractive9, "executeNonInteractive");
34013
35633
  async function managePreProcessorsInteractive(context, config) {
34014
35634
  let continueManaging = true;
34015
35635
  while (continueManaging) {
@@ -34306,7 +35926,7 @@ async function postprocessorsCommand(action, cmdObj) {
34306
35926
  hideVersions
34307
35927
  };
34308
35928
  if (action) {
34309
- await executeNonInteractive9(context, config, action, options);
35929
+ await executeNonInteractive10(context, config, action, options);
34310
35930
  } else {
34311
35931
  await managePostProcessorsInteractive(context, config);
34312
35932
  }
@@ -34508,7 +36128,7 @@ async function promptVersionSelection6(versions, activeVersionId) {
34508
36128
  return answer?.selectedVersion || null;
34509
36129
  }
34510
36130
  __name(promptVersionSelection6, "promptVersionSelection");
34511
- async function executeNonInteractive9(context, config, action, options) {
36131
+ async function executeNonInteractive10(context, config, action, options) {
34512
36132
  const normalizedAction = validateOrSuggest("postprocessors.action", action);
34513
36133
  const postprocessors = config.postprocessors || [];
34514
36134
  if (normalizedAction === "view") {
@@ -34596,7 +36216,7 @@ Usage: lua postprocessors ${normalizedAction} --postprocessor-name <name>`);
34596
36216
  }
34597
36217
  }
34598
36218
  }
34599
- __name(executeNonInteractive9, "executeNonInteractive");
36219
+ __name(executeNonInteractive10, "executeNonInteractive");
34600
36220
  async function managePostProcessorsInteractive(context, config) {
34601
36221
  let continueManaging = true;
34602
36222
  while (continueManaging) {
@@ -37079,7 +38699,7 @@ async function mcpCommand(action, serverNamePositional, cmdObj) {
37079
38699
  developerApi
37080
38700
  };
37081
38701
  if (action) {
37082
- await executeNonInteractive10(context, action, options);
38702
+ await executeNonInteractive11(context, action, options);
37083
38703
  } else {
37084
38704
  await interactiveMCPManagement(context);
37085
38705
  }
@@ -37240,7 +38860,7 @@ async function promptServerSelection(servers, message) {
37240
38860
  return answer?.server || null;
37241
38861
  }
37242
38862
  __name(promptServerSelection, "promptServerSelection");
37243
- async function executeNonInteractive10(context, action, options) {
38863
+ async function executeNonInteractive11(context, action, options) {
37244
38864
  const resolvedAction = validateOrSuggest("mcp.action", action);
37245
38865
  writeProgress("\u{1F504} Loading MCP servers...");
37246
38866
  const servers = await fetchServersCore(context);
@@ -37286,7 +38906,7 @@ Usage: lua mcp ${resolvedAction} --server-name <name>`);
37286
38906
  }
37287
38907
  }
37288
38908
  }
37289
- __name(executeNonInteractive10, "executeNonInteractive");
38909
+ __name(executeNonInteractive11, "executeNonInteractive");
37290
38910
  async function interactiveMCPManagement(context) {
37291
38911
  let continueManaging = true;
37292
38912
  while (continueManaging) {
@@ -37745,7 +39365,7 @@ async function integrationsCommand(action, subaction, cmdObj) {
37745
39365
  subaction
37746
39366
  ] : []
37747
39367
  };
37748
- await executeNonInteractive11(context, action, enhancedCmdObj);
39368
+ await executeNonInteractive12(context, action, enhancedCmdObj);
37749
39369
  } else {
37750
39370
  await interactiveIntegrationsManagement(context);
37751
39371
  }
@@ -37758,7 +39378,7 @@ async function integrationsCommand(action, subaction, cmdObj) {
37758
39378
  }, "integrations");
37759
39379
  }
37760
39380
  __name(integrationsCommand, "integrationsCommand");
37761
- async function executeNonInteractive11(context, action, cmdOptions) {
39381
+ async function executeNonInteractive12(context, action, cmdOptions) {
37762
39382
  const normalizedAction = validateOrSuggest("integrations.action", action);
37763
39383
  const options = {
37764
39384
  integration: cmdOptions?.integration,
@@ -37820,7 +39440,7 @@ async function executeNonInteractive11(context, action, cmdOptions) {
37820
39440
  throw new Error("Invalid action:");
37821
39441
  }
37822
39442
  }
37823
- __name(executeNonInteractive11, "executeNonInteractive");
39443
+ __name(executeNonInteractive12, "executeNonInteractive");
37824
39444
  async function interactiveIntegrationsManagement(context) {
37825
39445
  let continueManaging = true;
37826
39446
  while (continueManaging) {
@@ -38926,7 +40546,7 @@ Available scopes for ${selectedIntegration.name}:`);
38926
40546
  __name(updateConnectionFlow, "updateConnectionFlow");
38927
40547
  async function webhooksSubcommand(context, cmdOptions) {
38928
40548
  const rawSubAction = cmdOptions?._?.[0] || "";
38929
- const subAction = rawSubAction ? validateOrSuggest("triggers.action", rawSubAction) : "";
40549
+ const subAction = rawSubAction ? validateOrSuggest("integrations.webhooks.action", rawSubAction) : "";
38930
40550
  const options = {
38931
40551
  connectionId: cmdOptions?.connection || cmdOptions?.connectionId,
38932
40552
  webhookId: cmdOptions?.webhookId,
@@ -40293,8 +41913,8 @@ __name(telemetryCommand, "telemetryCommand");
40293
41913
  init_cli();
40294
41914
  init_command_utils();
40295
41915
  init_analytics();
40296
- import { writeFileSync as writeFileSync8, existsSync as existsSync8, unlinkSync as unlinkSync2 } from "fs";
40297
- import { resolve as resolve4, join as join7 } from "path";
41916
+ import { writeFileSync as writeFileSync10, existsSync as existsSync10, unlinkSync as unlinkSync2 } from "fs";
41917
+ import { resolve as resolve4, join as join9 } from "path";
40298
41918
  init_artifact_loader();
40299
41919
  init_types();
40300
41920
  function getProjectToolNames() {
@@ -40307,50 +41927,6 @@ function getProjectToolNames() {
40307
41927
  }
40308
41928
  }
40309
41929
  __name(getProjectToolNames, "getProjectToolNames");
40310
- function generateFile(setup) {
40311
- if (setup.mode === "api") {
40312
- return `/**
40313
- * Governance Policy (API mode)
40314
- * Enforcement is handled remotely via the Governance Cloud.
40315
- * Import this into your LuaAgent config.
40316
- *
40317
- * The API key is resolved on the platform at runtime from the
40318
- * GOVERNANCE_API_KEY env var. Never put the raw key in source.
40319
- */
40320
-
40321
- export const governance = {
40322
- mode: 'api' as const,
40323
- serverUrl: process.env.GOVERNANCE_API_URL ?? '${setup.serverUrl}',
40324
- };
40325
- `;
40326
- }
40327
- const ruleLines = [];
40328
- if (setup.blockTools && setup.blockTools.length > 0) {
40329
- const list = setup.blockTools.map((t) => `'${t}'`).join(", ");
40330
- ruleLines.push(` blockTools: [${list}],`);
40331
- }
40332
- if (setup.requireApproval && setup.requireApproval.length > 0) {
40333
- const list = setup.requireApproval.map((t) => `'${t}'`).join(", ");
40334
- ruleLines.push(` requireApproval: [${list}],`);
40335
- }
40336
- if (setup.tokenLimit && setup.tokenLimit > 0) {
40337
- ruleLines.push(` tokenBudget: ${setup.tokenLimit},`);
40338
- }
40339
- return `/**
40340
- * Governance Policy (SDK mode)
40341
- * Policies are enforced locally at the platform level.
40342
- * Import this into your LuaAgent config.
40343
- */
40344
-
40345
- export const governance = {
40346
- mode: 'sdk' as const,
40347
- rules: {
40348
- ${ruleLines.join("\n")}
40349
- },
40350
- };
40351
- `;
40352
- }
40353
- __name(generateFile, "generateFile");
40354
41930
  async function governanceCommand(action) {
40355
41931
  return withErrorHandling(async () => {
40356
41932
  if (action) {
@@ -40361,9 +41937,9 @@ async function governanceCommand(action) {
40361
41937
  return;
40362
41938
  }
40363
41939
  const srcDir = resolve4(process.cwd(), "src");
40364
- const targetDir = existsSync8(srcDir) ? srcDir : process.cwd();
40365
- const filePath = join7(targetDir, "governance.ts");
40366
- if (existsSync8(filePath)) {
41940
+ const targetDir = existsSync10(srcDir) ? srcDir : process.cwd();
41941
+ const filePath = join9(targetDir, "governance.ts");
41942
+ if (existsSync10(filePath)) {
40367
41943
  const { overwrite } = await safePrompt([
40368
41944
  {
40369
41945
  type: "confirm",
@@ -40453,8 +42029,8 @@ async function governanceCommand(action) {
40453
42029
  };
40454
42030
  }
40455
42031
  }
40456
- const content = generateFile(setup);
40457
- writeFileSync8(filePath, content, "utf-8");
42032
+ const content = generateGovernanceFile(setup);
42033
+ writeFileSync10(filePath, content, "utf-8");
40458
42034
  const relativePath = filePath.replace(process.cwd() + "/", "");
40459
42035
  writeSuccess(`Created ${relativePath}`);
40460
42036
  console.log("");
@@ -40492,9 +42068,9 @@ async function governanceCommand(action) {
40492
42068
  __name(governanceCommand, "governanceCommand");
40493
42069
  async function governanceRemove() {
40494
42070
  const srcDir = resolve4(process.cwd(), "src");
40495
- const targetDir = existsSync8(srcDir) ? srcDir : process.cwd();
40496
- const filePath = join7(targetDir, "governance.ts");
40497
- const hasLocal = existsSync8(filePath);
42071
+ const targetDir = existsSync10(srcDir) ? srcDir : process.cwd();
42072
+ const filePath = join9(targetDir, "governance.ts");
42073
+ const hasLocal = existsSync10(filePath);
40498
42074
  const { confirm } = await safePrompt([
40499
42075
  {
40500
42076
  type: "confirm",
@@ -40550,7 +42126,7 @@ __name(governanceRemove, "governanceRemove");
40550
42126
  init_cli();
40551
42127
  init_auth();
40552
42128
  init_files();
40553
- import chalk3 from "chalk";
42129
+ import chalk4 from "chalk";
40554
42130
  init_compiler2();
40555
42131
  init_artifact_loader();
40556
42132
  init_analytics();
@@ -40579,28 +42155,28 @@ async function listModels(models, currentModel, opts) {
40579
42155
  console.log("============================================================");
40580
42156
  console.log("");
40581
42157
  if (currentModel) {
40582
- console.log(` Current model: ${chalk3.bold.cyan(currentModel)}`);
42158
+ console.log(` Current model: ${chalk4.bold.cyan(currentModel)}`);
40583
42159
  } else {
40584
- console.log(` Current model: ${chalk3.gray("(platform default)")}`);
42160
+ console.log(` Current model: ${chalk4.gray("(platform default)")}`);
40585
42161
  }
40586
42162
  console.log("");
40587
42163
  for (const provider of providers) {
40588
42164
  const providerModels = models.filter((m) => m.provider === provider);
40589
- console.log(chalk3.yellow(` \u2500\u2500 ${provider} \u2500\u2500`));
42165
+ console.log(chalk4.yellow(` \u2500\u2500 ${provider} \u2500\u2500`));
40590
42166
  for (const m of providerModels) {
40591
42167
  const isCurrent = m.code === currentModel;
40592
- const code = isCurrent ? chalk3.bold.cyan(m.code.padEnd(30)) : m.code.padEnd(30);
40593
- const desc = chalk3.gray(m.description);
40594
- const marker = isCurrent ? chalk3.bold.green(" \u2190 current") : "";
42168
+ const code = isCurrent ? chalk4.bold.cyan(m.code.padEnd(30)) : m.code.padEnd(30);
42169
+ const desc = chalk4.gray(m.description);
42170
+ const marker = isCurrent ? chalk4.bold.green(" \u2190 current") : "";
40595
42171
  console.log(` ${code} ${desc}${marker}`);
40596
42172
  }
40597
42173
  console.log("");
40598
42174
  }
40599
42175
  console.log("============================================================");
40600
42176
  if (!currentModel) {
40601
- console.log(` \u{1F4A1} Run ${chalk3.cyan("lua models set")} to choose a model for your agent`);
42177
+ console.log(` \u{1F4A1} Run ${chalk4.cyan("lua models set")} to choose a model for your agent`);
40602
42178
  } else {
40603
- console.log(` \u{1F4A1} Run ${chalk3.cyan("lua models set")} to change your model`);
42179
+ console.log(` \u{1F4A1} Run ${chalk4.cyan("lua models set")} to change your model`);
40604
42180
  }
40605
42181
  console.log("============================================================");
40606
42182
  console.log("");
@@ -40614,12 +42190,21 @@ async function modelsCommand(action, opts) {
40614
42190
  const agentId = config?.agent?.agentId;
40615
42191
  if (resolvedAction === "list") {
40616
42192
  writeProgress("\u{1F504} Fetching available models...");
40617
- const models = await fetchApprovedModels(apiKey);
42193
+ const models = await fetchApprovedModels(apiKey, agentId);
40618
42194
  writeProgress("");
40619
- if (models.length === 0) {
42195
+ if (models === null) {
40620
42196
  writeError("\u274C Could not fetch models from the server. Check your connection and API key.");
40621
42197
  return;
40622
42198
  }
42199
+ if (models.length === 0) {
42200
+ writeInfo("\u2139\uFE0F No models are currently available. If your organization restricts models, an admin may need to review its excluded-models list.");
42201
+ trackEvent("cli_models_listed", {
42202
+ models_count: 0,
42203
+ has_current_model: false,
42204
+ json_output: opts.json ?? false
42205
+ });
42206
+ return;
42207
+ }
40623
42208
  const currentModel = agentId ? await resolveCurrentModel(apiKey, agentId) : null;
40624
42209
  await listModels(models, currentModel, opts);
40625
42210
  trackEvent("cli_models_listed", {
@@ -40635,11 +42220,14 @@ async function modelsCommand(action, opts) {
40635
42220
  process.exit(1);
40636
42221
  }
40637
42222
  writeProgress("\u{1F504} Fetching available models...");
40638
- const models = await fetchApprovedModels(apiKey);
42223
+ const models = await fetchApprovedModels(apiKey, agentId);
40639
42224
  writeProgress("");
40640
- if (models.length === 0) {
42225
+ if (models === null) {
40641
42226
  writeError("\u274C Could not fetch models from the server. Check your connection and API key.");
40642
42227
  process.exit(1);
42228
+ } else if (models.length === 0) {
42229
+ writeError("\u274C No models are currently available. If your organization restricts models, an admin may need to review its excluded-models list.");
42230
+ process.exit(1);
40643
42231
  }
40644
42232
  let selectedModel;
40645
42233
  if (opts.model) {
@@ -40647,7 +42235,7 @@ async function modelsCommand(action, opts) {
40647
42235
  } else {
40648
42236
  const currentModel = await resolveCurrentModel(apiKey, agentId);
40649
42237
  if (!opts.json) {
40650
- writeInfo(` Current model: ${currentModel ? chalk3.bold.cyan(currentModel) : chalk3.gray("(platform default)")}
42238
+ writeInfo(` Current model: ${currentModel ? chalk4.bold.cyan(currentModel) : chalk4.gray("(platform default)")}
40651
42239
  `);
40652
42240
  }
40653
42241
  selectedModel = await promptModelSelection(models);
@@ -40658,15 +42246,23 @@ async function modelsCommand(action, opts) {
40658
42246
  }
40659
42247
  const localWriteOk = setAgentModel(selectedModel);
40660
42248
  if (localWriteOk) {
40661
- writeSuccess(`\u2705 Model written to source: ${chalk3.bold(selectedModel)}`);
42249
+ writeSuccess(`\u2705 Model written to source: ${chalk4.bold(selectedModel)}`);
40662
42250
  } else {
40663
42251
  writeInfo(`\u26A0\uFE0F Could not write model to source file (no LuaAgent constructor found). You can set it manually in your code.`);
40664
42252
  }
40665
42253
  try {
40666
42254
  await updateAgentModel(apiKey, agentId, selectedModel);
40667
- writeSuccess(`\u2705 Model pushed to server: ${chalk3.bold(selectedModel)}`);
42255
+ writeSuccess(`\u2705 Model pushed to server: ${chalk4.bold(selectedModel)}`);
40668
42256
  } catch (err) {
40669
- writeInfo(`\u26A0\uFE0F Could not push model to server: ${err.message}. Run \`lua push agent\` to retry.`);
42257
+ const msg = err?.message || "Unknown error";
42258
+ const isPolicyRejection = /isn'?t available for your organization|not available for your organization|not approved/i.test(msg);
42259
+ if (isPolicyRejection) {
42260
+ writeError(`\u274C ${msg}`);
42261
+ writeInfo(` Run ${chalk4.cyan("lua models list")} to see the models allowed for your organization.`);
42262
+ writeInfo(` The model was written to your local source but NOT applied on the server \u2014 pick an allowed model to keep them in sync.`);
42263
+ } else {
42264
+ writeInfo(`\u26A0\uFE0F Could not push model to server: ${msg}. Run \`lua push agent\` to retry.`);
42265
+ }
40670
42266
  }
40671
42267
  trackEvent("cli_models_set", {
40672
42268
  model: selectedModel,
@@ -40685,7 +42281,7 @@ async function modelsCommand(action, opts) {
40685
42281
  writeInfo("\u2139\uFE0F No model is currently set \u2014 the platform default is already in use.");
40686
42282
  return;
40687
42283
  }
40688
- writeInfo(` Current model: ${chalk3.bold.cyan(currentModel)}`);
42284
+ writeInfo(` Current model: ${chalk4.bold.cyan(currentModel)}`);
40689
42285
  writeInfo(` This will remove the model and let the Lua platform use its default.
40690
42286
  `);
40691
42287
  const localRemoveOk = removeAgentModel();
@@ -40719,8 +42315,8 @@ init_command_utils();
40719
42315
  init_artifact_loader();
40720
42316
  init_types();
40721
42317
  import { spawn as spawn3 } from "child_process";
40722
- import { existsSync as existsSync9, readdirSync as readdirSync3, statSync as statSync4 } from "fs";
40723
- import { join as join8, relative, resolve as resolve5 } from "path";
42318
+ import { existsSync as existsSync11, readdirSync as readdirSync3, statSync as statSync4 } from "fs";
42319
+ import { join as join10, relative, resolve as resolve5 } from "path";
40724
42320
  init_voice_api_service();
40725
42321
  init_constants();
40726
42322
 
@@ -41308,8 +42904,8 @@ function escapeRegex(s) {
41308
42904
  }
41309
42905
  __name(escapeRegex, "escapeRegex");
41310
42906
  function detectRunner(cwd) {
41311
- const pkgPath = join8(cwd, "package.json");
41312
- if (!existsSync9(pkgPath)) return null;
42907
+ const pkgPath = join10(cwd, "package.json");
42908
+ if (!existsSync11(pkgPath)) return null;
41313
42909
  try {
41314
42910
  const pkg2 = JSON.parse(__require("fs").readFileSync(pkgPath, "utf8"));
41315
42911
  const deps = {
@@ -41681,7 +43277,7 @@ function findVoiceTestFiles(root) {
41681
43277
  return;
41682
43278
  }
41683
43279
  for (const entry of entries) {
41684
- const full = join8(dir, entry);
43280
+ const full = join10(dir, entry);
41685
43281
  let s;
41686
43282
  try {
41687
43283
  s = statSync4(full);
@@ -41994,6 +43590,7 @@ async function versionShowCommand(versionArg, options = {}) {
41994
43590
  console.log(` Snapshot:`);
41995
43591
  console.log(` Skills: ${v.snapshot.skills.length}`);
41996
43592
  console.log(` Webhooks: ${v.snapshot.webhooks.length}`);
43593
+ console.log(` Triggers: ${(v.snapshot.triggers ?? []).length}`);
41997
43594
  console.log(` Jobs: ${v.snapshot.jobs.length}`);
41998
43595
  console.log(` Preprocessors: ${v.snapshot.preprocessors.length}`);
41999
43596
  console.log(` Postprocessors: ${v.snapshot.postprocessors.length}`);
@@ -42049,6 +43646,16 @@ async function versionDiffCommand(fromArg, toArg, options = {}) {
42049
43646
  name: "Postprocessors",
42050
43647
  entry: diff.postprocessors,
42051
43648
  key: "id"
43649
+ },
43650
+ // `?? {…}` — older servers (pre-PRO-95) omit triggers from the diff.
43651
+ {
43652
+ name: "Triggers",
43653
+ entry: diff.triggers ?? {
43654
+ added: [],
43655
+ removed: [],
43656
+ changed: []
43657
+ },
43658
+ key: "triggerId"
42052
43659
  }
42053
43660
  ];
42054
43661
  for (const { name, entry, key } of sections) {
@@ -42896,19 +44503,21 @@ Examples:
42896
44503
  $ lua jobs versions -i myJob View job versions
42897
44504
  $ lua jobs history -i myJob View execution history
42898
44505
  `).action(jobsCommand);
42899
- program2.command("features [action]").description("\u{1F3AF} Manage agent features (RAG, webSearch, inquiry)").option("--feature-name <name>", "Feature name").addHelpText("after", `
44506
+ program2.command("features [action]").description("\u{1F3AF} Manage agent features (RAG, webSearch, inquiry, outboundChannels)").option("--feature-name <name>", "Feature name").option("--recipient-scope <scope>", "For configure: outboundChannels recipient scope (current_user | anyone)").addHelpText("after", `
42900
44507
  Arguments:
42901
- action Optional: 'list', 'enable', 'disable', 'view' (prompts if not provided)
44508
+ action Optional: 'list', 'enable', 'disable', 'view', 'configure' (prompts if not provided)
42902
44509
 
42903
44510
  Options:
42904
- --feature-name <name> Feature name (required for enable/disable/view actions)
44511
+ --feature-name <name> Feature name (required for enable/disable/view/configure actions)
44512
+ --recipient-scope <scope> For configure: outboundChannels recipient scope (current_user | anyone)
42905
44513
 
42906
44514
  Examples:
42907
44515
  $ lua features Interactive management
42908
44516
  $ lua features list List all features
42909
- $ lua features enable --feature-name rag Enable a feature
44517
+ $ lua features enable --feature-name rag Enable a feature
42910
44518
  $ lua features disable --feature-name rag Disable a feature
42911
44519
  $ lua features view --feature-name webSearch View feature details
44520
+ $ lua features configure --feature-name outboundChannels --recipient-scope anyone
42912
44521
  `).action(featuresCommand);
42913
44522
  program2.command("preprocessors [action]").description("\u{1F4E5} Manage message preprocessors").option("--preprocessor-name <name>", "PreProcessor name").option("--preprocessor-version <version>", "Version for deploy action (or 'latest')").addHelpText("after", `
42914
44523
  Arguments:
@@ -42964,9 +44573,10 @@ Examples:
42964
44573
  `).action(mcpCommand);
42965
44574
  program2.command("integrations [action] [subaction]").description("\u{1F517} Connect third-party integrations via Unified.to").option("--integration <type>", "Integration type (e.g., linear, googlecalendar)").option("--auth-method <method>", "Authentication method: 'oauth' or 'token'").option("--scopes <scopes>", "Comma-separated OAuth scopes (or 'all' for all scopes)").option("--hide-sensitive <bool>", "Hide sensitive data from MCP tools (default: true)").option("--connection-id <id>", "Connection ID to disconnect or pause/resume").option("--connection <id>", "Connection ID for trigger").option("--webhook-id <id>", "Trigger ID to delete/pause/resume").option("--object <type>", "Object type for webhook (e.g., task_task, calendar_event)").option("--event <type>", "Event type for webhook: created, updated, or deleted").option("--hook-url <url>", "Custom webhook URL (default: agent trigger)").option("--interval <minutes>", "Polling interval for virtual webhooks (60, 120, 240, 480, 720, 1440, 2880)").option("--triggers <events>", "Comma-separated triggers (e.g., task_task.created,task_task.updated)").option("--custom-webhook", "Use custom webhook URL instead of agent trigger").option("--json", "Output as JSON (for info and webhooks events commands)").option("--reason <text>", "Optional reason for pausing a trigger").addHelpText("after", `
42966
44575
  Arguments:
42967
- action Optional: 'connect', 'update', 'list', 'available', 'info', 'disconnect', 'webhooks', or 'mcp'
44576
+ action Optional: 'connect', 'update', 'list', 'available', 'info', 'disconnect', 'webhooks'
44577
+ (alias: 'triggers'), or 'mcp'
42968
44578
  subaction For info: <integration-type>
42969
- For webhooks: 'list', 'events', 'create', or 'delete'
44579
+ For webhooks/triggers: 'list', 'events', 'create', 'delete', 'pause', or 'resume'
42970
44580
  For mcp: 'list', 'activate', or 'deactivate'
42971
44581
 
42972
44582
  Options:
@@ -43002,8 +44612,9 @@ Examples:
43002
44612
  $ lua integrations info linear --json Output as JSON (for scripting)
43003
44613
  $ lua integrations disconnect --connection-id abc123 Disconnect an integration
43004
44614
 
43005
- Webhook/Trigger Examples:
44615
+ Webhook/Trigger Examples ('triggers' is an alias for 'webhooks'):
43006
44616
  $ lua integrations webhooks list List all triggers
44617
+ $ lua integrations triggers list Same, via the 'triggers' alias
43007
44618
  $ lua integrations webhooks events --integration linear List available events
43008
44619
  $ lua integrations webhooks create Create trigger (interactive)
43009
44620
  $ lua integrations webhooks delete --webhook-id wh_xyz789
@@ -43017,27 +44628,37 @@ MCP Server Examples:
43017
44628
  $ lua integrations mcp activate --connection abc123 Activate MCP server for a connection
43018
44629
  $ lua integrations mcp deactivate --connection abc123 Deactivate MCP server for a connection
43019
44630
  `).action(integrationsCommand);
43020
- program2.command("triggers [action]").description("\u26A1 Manage integration triggers (alias for: lua integrations webhooks)").option("--connection-id <id>", "Connection ID to pause/resume all triggers").option("--connection <id>", "Connection ID for creating a trigger").option("--webhook-id <id>", "Trigger ID to delete/pause/resume").option("--object <type>", "Object type for webhook (e.g., task_task, calendar_event)").option("--event <type>", "Event type: created, updated, or deleted").option("--hook-url <url>", "Custom webhook URL (default: agent trigger)").option("--interval <minutes>", "Polling interval for virtual webhooks").option("--json", "Output as JSON").option("--reason <text>", "Optional reason for pausing").addHelpText("after", `
43021
- This is a shortcut for: lua integrations webhooks <action>
44631
+ program2.command("triggers [action]").description("\u26A1 Manage agent triggers (paste-anywhere URLs that invoke your agent)").option("--name <name>", "Trigger name (for create)").option("--description <text>", "Trigger description (for create)").option("--instruction <text>", "Instruction sent to the agent each time this trigger fires").option("--trigger <nameOrId>", "Trigger name or ID").option("--limit <n>", "Max executions to show for logs (default: 20, max: 200)").option("--json", "Output as JSON (for list and logs)").option("--force", "Skip confirmation prompts (for delete)").option("--webhook-id <id>", "(moved) integration trigger ID \u2014 use: lua integrations webhooks").option("--connection-id <id>", "(moved) integration connection ID \u2014 use: lua integrations webhooks").option("--connection <id>", "(moved) integration connection ID \u2014 use: lua integrations webhooks").addHelpText("after", `
44632
+ Arguments:
44633
+ action Optional: 'list', 'create', 'logs', 'activate', 'deactivate',
44634
+ 'rotate-token', 'delete' (prompts if not provided)
43022
44635
 
43023
- Actions: list, create, delete, pause, resume, events
44636
+ Options:
44637
+ --name <name> Trigger name (required for create)
44638
+ --description <text> Trigger description (optional, for create)
44639
+ --instruction <text> Instruction sent to the agent each time this trigger fires (optional, for create)
44640
+ --trigger <nameOrId> Trigger name or ID (required for logs/activate/deactivate/rotate-token/delete)
44641
+ --limit <n> Max executions to show for logs (default: 20, max: 200)
44642
+ --json Output as JSON (for list and logs)
44643
+ --force Skip confirmation prompts (for delete)
43024
44644
 
43025
44645
  Examples:
43026
- $ lua triggers Interactive trigger management
43027
- $ lua triggers list List all triggers
43028
- $ lua triggers list --json Output as JSON
43029
- $ lua triggers create Create trigger (interactive)
43030
- $ lua triggers pause --webhook-id <id> Pause a trigger
43031
- $ lua triggers pause --connection-id <id> Pause all triggers for a connection
43032
- $ lua triggers resume --webhook-id <id> Resume a trigger
43033
- $ lua triggers resume --connection-id <id> Resume all triggers for a connection
43034
- $ lua triggers delete --webhook-id <id> Delete a trigger
43035
- `).action((action, cmdOptions) => {
43036
- const opts = {
43037
- ...cmdOptions || {}
43038
- };
43039
- return integrationsCommand("webhooks", action || "", opts);
43040
- });
44646
+ $ lua triggers Interactive management
44647
+ $ lua triggers list List all triggers
44648
+ $ lua triggers list --json Output as JSON
44649
+ $ lua triggers create --name order-created Create a trigger (prints the pasteable URL)
44650
+ $ lua triggers create --name order-created --description "Fires on new orders"
44651
+ $ lua triggers create --name daily-time --instruction "Reply with the current date and time"
44652
+ $ lua triggers logs --trigger order-created View execution history
44653
+ $ lua triggers logs --trigger order-created --limit 5 --json
44654
+ $ lua triggers activate --trigger order-created Enable a trigger
44655
+ $ lua triggers deactivate --trigger order-created Disable a trigger
44656
+ $ lua triggers rotate-token --trigger order-created Invalidate the old URL, print the new one
44657
+ $ lua triggers delete --trigger order-created --force Delete without confirmation
44658
+
44659
+ Looking for integration triggers (Linear, HubSpot, ...)? They moved:
44660
+ $ lua integrations webhooks <action> (also reachable as: lua integrations triggers <action>)
44661
+ `).action(triggersCommand);
43041
44662
  program2.command("completion [shell]").description("\u{1F3AF} Generate shell completion script").addHelpText("after", `
43042
44663
  Arguments:
43043
44664
  shell Optional: 'bash', 'zsh', or 'fish' (shows instructions if not provided)