lua-cli 3.18.0 → 3.20.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
@@ -868,6 +868,15 @@ function aiGenerateInputFromSimplified(prompt, content) {
868
868
  ]
869
869
  };
870
870
  }
871
+ function isAllowedReviewableExecuteTool(tool) {
872
+ return REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST.includes(tool);
873
+ }
874
+ function isReviewableMcpSendTool(tool) {
875
+ return tool.length > REVIEWABLE_MCP_SEND_TOOL_SUFFIX.length && tool.endsWith(REVIEWABLE_MCP_SEND_TOOL_SUFFIX);
876
+ }
877
+ function isReviewableExecuteTool(tool) {
878
+ return isAllowedReviewableExecuteTool(tool) || isReviewableMcpSendTool(tool);
879
+ }
871
880
  function isInteractiveChannel(channel) {
872
881
  if (!channel) return true;
873
882
  return !NON_INTERACTIVE_CHANNELS.includes(channel);
@@ -883,6 +892,85 @@ function transformChatHistoryContentParts(parts) {
883
892
  const content = [];
884
893
  for (const rawPart of parts ?? []) {
885
894
  const part = rawPart;
895
+ if (part?.type === "reasoning") {
896
+ const detailsText = Array.isArray(part.details) ? part.details.filter((d) => d?.type === "text" && typeof d.text === "string").map((d) => d.text).join("") : "";
897
+ const reasoningText = [
898
+ part.reasoning,
899
+ detailsText,
900
+ part.text
901
+ ].find((v) => typeof v === "string" && v.trim().length > 0) ?? "";
902
+ if (reasoningText) content.push({
903
+ type: "reasoning",
904
+ text: reasoningText
905
+ });
906
+ continue;
907
+ }
908
+ if (part?.type === "tool-invocation") {
909
+ const inv = part.toolInvocation;
910
+ if (typeof inv?.toolName === "string" && inv.toolName.length > 0) {
911
+ content.push({
912
+ type: "tool",
913
+ toolName: inv.toolName,
914
+ toolCallId: inv.toolCallId,
915
+ input: inv.args,
916
+ output: inv.result,
917
+ toolState: inv.state
918
+ });
919
+ }
920
+ continue;
921
+ }
922
+ if (part?.type === "source") {
923
+ const src = part.source;
924
+ if (src?.sourceType === "document") {
925
+ content.push({
926
+ type: "source-document",
927
+ sourceId: src.id,
928
+ mediaType: src.mediaType,
929
+ title: src.title,
930
+ filename: src.filename,
931
+ providerMetadata: src.providerMetadata
932
+ });
933
+ } else if (typeof src?.url === "string" && src.url.length > 0) {
934
+ content.push({
935
+ type: "source-url",
936
+ sourceId: src.id,
937
+ url: src.url,
938
+ title: src.title,
939
+ providerMetadata: src.providerMetadata
940
+ });
941
+ }
942
+ continue;
943
+ }
944
+ if (part?.type === "source-url") {
945
+ if (typeof part.url === "string" && part.url.length > 0) {
946
+ content.push({
947
+ type: "source-url",
948
+ sourceId: part.sourceId,
949
+ url: part.url,
950
+ title: part.title,
951
+ providerMetadata: part.providerMetadata
952
+ });
953
+ }
954
+ continue;
955
+ }
956
+ if (part?.type === "source-document") {
957
+ content.push({
958
+ type: "source-document",
959
+ sourceId: part.sourceId,
960
+ mediaType: part.mediaType,
961
+ title: part.title,
962
+ filename: part.filename,
963
+ providerMetadata: part.providerMetadata
964
+ });
965
+ continue;
966
+ }
967
+ if (typeof part?.type === "string" && part.type.startsWith("data-lua-")) {
968
+ content.push({
969
+ type: part.type,
970
+ payload: rawPart.data
971
+ });
972
+ continue;
973
+ }
886
974
  if (part?.type !== "text" && part?.type !== "file") continue;
887
975
  if (part.type === "text" && typeof part.text === "string") {
888
976
  const rawText = part.text || "";
@@ -940,10 +1028,92 @@ function transformChatHistoryContentParts(parts) {
940
1028
  }
941
1029
  return content;
942
1030
  }
1031
+ function isSyntheticSideRow(id) {
1032
+ return id.startsWith(SCREENSHOT_MESSAGE_ID_PREFIX) || id.startsWith(RICH_PARTS_MESSAGE_ID_PREFIX);
1033
+ }
1034
+ function mergeRichPartMirrorMessages(messages, sameTurnGroup) {
1035
+ const merged = [];
1036
+ for (const message of messages) {
1037
+ if (message.role === "assistant" && message.id.startsWith(RICH_PARTS_MESSAGE_ID_PREFIX)) {
1038
+ let folded = false;
1039
+ for (let i = merged.length - 1; i >= 0; i--) {
1040
+ const target = merged[i];
1041
+ if (sameTurnGroup && !sameTurnGroup(target, message)) continue;
1042
+ if (isSyntheticSideRow(target.id)) continue;
1043
+ if (target.role !== "assistant") break;
1044
+ const seen = /* @__PURE__ */ new Set();
1045
+ for (const part of target.content) {
1046
+ for (const key of citationDedupeKeys(part)) seen.add(key);
1047
+ }
1048
+ const incoming = [];
1049
+ for (const part of message.content) {
1050
+ const keys = citationDedupeKeys(part);
1051
+ if (keys.length > 0 && keys.some((k) => seen.has(k))) continue;
1052
+ for (const key of keys) seen.add(key);
1053
+ incoming.push(part);
1054
+ }
1055
+ merged[i] = {
1056
+ ...target,
1057
+ content: [
1058
+ ...target.content,
1059
+ ...incoming
1060
+ ]
1061
+ };
1062
+ folded = true;
1063
+ break;
1064
+ }
1065
+ if (folded) continue;
1066
+ }
1067
+ merged.push(message);
1068
+ }
1069
+ return merged;
1070
+ }
1071
+ function citationDedupeKeys(part) {
1072
+ if (part.type !== "source-url" && part.type !== "source-document") return [];
1073
+ const keys = [];
1074
+ if (typeof part.sourceId === "string" && part.sourceId.length > 0) keys.push(`id:${part.sourceId}`);
1075
+ if (typeof part.url === "string" && part.url.length > 0) keys.push(`url:${part.url}`);
1076
+ return keys;
1077
+ }
1078
+ function foldRichPartsIntoMessages(messages, records, makeMessage, sameTurnGroup) {
1079
+ if (messages.length === 0 || records.length === 0) return messages;
1080
+ const messageTime = /* @__PURE__ */ __name2((m) => m.createdAt ? new Date(m.createdAt).getTime() : Number.NEGATIVE_INFINITY, "messageTime");
1081
+ const finiteTimes = messages.map(messageTime).filter(Number.isFinite);
1082
+ const oldest = finiteTimes.length > 0 ? Math.min(...finiteTimes) : Number.NEGATIVE_INFINITY;
1083
+ const synthetic = [];
1084
+ for (const record of records) {
1085
+ const time = new Date(record.createdAt).getTime();
1086
+ if (!Number.isFinite(time) || time < oldest) continue;
1087
+ const content = transformChatHistoryContentParts(record.parts);
1088
+ if (content.length === 0) continue;
1089
+ synthetic.push({
1090
+ time,
1091
+ message: makeMessage({
1092
+ id: `${RICH_PARTS_MESSAGE_ID_PREFIX}${record.threadId}:${record.messageId}`,
1093
+ role: "assistant",
1094
+ createdAt: new Date(time).toISOString(),
1095
+ content
1096
+ }, record)
1097
+ });
1098
+ }
1099
+ if (synthetic.length === 0) return messages;
1100
+ synthetic.sort((a, b) => a.time - b.time);
1101
+ const combined = [];
1102
+ let next = 0;
1103
+ for (const message of messages) {
1104
+ const time = messageTime(message);
1105
+ while (next < synthetic.length && synthetic[next].time < time) {
1106
+ combined.push(synthetic[next++].message);
1107
+ }
1108
+ combined.push(message);
1109
+ }
1110
+ while (next < synthetic.length) combined.push(synthetic[next++].message);
1111
+ return mergeRichPartMirrorMessages(combined, sameTurnGroup);
1112
+ }
943
1113
  function buildDefaultPersona(agentName) {
944
1114
  return DEFAULT_PERSONA_GUIDE.replace(AGENT_NAME_TOKEN, () => agentName || "My Agent");
945
1115
  }
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;
1116
+ var __defProp2, __name2, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, REASONING_EFFORT_VALUES, 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;
947
1117
  var init_dist = __esm({
948
1118
  "../shared-types/dist/index.mjs"() {
949
1119
  "use strict";
@@ -961,6 +1131,24 @@ var init_dist = __esm({
961
1131
  __name2(personaToLiteral, "personaToLiteral");
962
1132
  __name(aiGenerateInputFromSimplified, "aiGenerateInputFromSimplified");
963
1133
  __name2(aiGenerateInputFromSimplified, "aiGenerateInputFromSimplified");
1134
+ REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST = [
1135
+ "sendChannelMessage",
1136
+ "sendWhatsappTemplate",
1137
+ "sendEmail",
1138
+ "sendWhatsappMessage",
1139
+ "sendSms",
1140
+ "sendWebchatMessage",
1141
+ "sendTeamsMessage",
1142
+ "sendInstagramMessage",
1143
+ "sendMessengerMessage"
1144
+ ];
1145
+ __name(isAllowedReviewableExecuteTool, "isAllowedReviewableExecuteTool");
1146
+ __name2(isAllowedReviewableExecuteTool, "isAllowedReviewableExecuteTool");
1147
+ REVIEWABLE_MCP_SEND_TOOL_SUFFIX = "_create_messaging_message";
1148
+ __name(isReviewableMcpSendTool, "isReviewableMcpSendTool");
1149
+ __name2(isReviewableMcpSendTool, "isReviewableMcpSendTool");
1150
+ __name(isReviewableExecuteTool, "isReviewableExecuteTool");
1151
+ __name2(isReviewableExecuteTool, "isReviewableExecuteTool");
964
1152
  NON_INTERACTIVE_CHANNELS = [
965
1153
  "trigger",
966
1154
  "agent-invocation"
@@ -973,6 +1161,231 @@ var init_dist = __esm({
973
1161
  __name2(removeNavigateBlock, "removeNavigateBlock");
974
1162
  __name(transformChatHistoryContentParts, "transformChatHistoryContentParts");
975
1163
  __name2(transformChatHistoryContentParts, "transformChatHistoryContentParts");
1164
+ RICH_PARTS_MESSAGE_ID_PREFIX = "rich-parts:";
1165
+ SCREENSHOT_MESSAGE_ID_PREFIX = "screenshot:";
1166
+ __name(isSyntheticSideRow, "isSyntheticSideRow");
1167
+ __name2(isSyntheticSideRow, "isSyntheticSideRow");
1168
+ __name(mergeRichPartMirrorMessages, "mergeRichPartMirrorMessages");
1169
+ __name2(mergeRichPartMirrorMessages, "mergeRichPartMirrorMessages");
1170
+ __name(citationDedupeKeys, "citationDedupeKeys");
1171
+ __name2(citationDedupeKeys, "citationDedupeKeys");
1172
+ __name(foldRichPartsIntoMessages, "foldRichPartsIntoMessages");
1173
+ __name2(foldRichPartsIntoMessages, "foldRichPartsIntoMessages");
1174
+ BROWSER_COMMANDS = [
1175
+ // health + lifecycle / navigation
1176
+ {
1177
+ name: "health",
1178
+ description: "Check the local browser engine is installed and responsive."
1179
+ },
1180
+ {
1181
+ name: "session_open",
1182
+ description: "Open/attach a browser session (its own cookies/auth). Args: url?, headed?, profile?, confirmActions?."
1183
+ },
1184
+ {
1185
+ name: "navigate",
1186
+ description: "Navigate the session to a URL. Args: url, waitUntil?."
1187
+ },
1188
+ {
1189
+ name: "back",
1190
+ description: "Go back in history."
1191
+ },
1192
+ {
1193
+ name: "forward",
1194
+ description: "Go forward in history."
1195
+ },
1196
+ {
1197
+ name: "reload",
1198
+ description: "Reload the current page."
1199
+ },
1200
+ {
1201
+ name: "pushstate",
1202
+ description: "SPA client-side navigation. Args: url."
1203
+ },
1204
+ {
1205
+ name: "close",
1206
+ description: "Close the session\u2019s browser."
1207
+ },
1208
+ // perception
1209
+ {
1210
+ name: "snapshot",
1211
+ description: "Accessibility-tree snapshot with element refs (@e1\u2026) \u2014 see what to click/fill. Args: interactiveOnly?, selector?, urls?, compact?, depth?."
1212
+ },
1213
+ {
1214
+ name: "get",
1215
+ description: "Read from the page. Args: what(text|html|value|attr|title|url|count|box|styles), selector?, attr?."
1216
+ },
1217
+ {
1218
+ name: "is",
1219
+ description: "Check element state. Args: check(visible|enabled|checked), selector."
1220
+ },
1221
+ // interaction
1222
+ {
1223
+ name: "click",
1224
+ description: "Click an element. Args: selector(@eN or CSS), newTab?."
1225
+ },
1226
+ {
1227
+ name: "dblclick",
1228
+ description: "Double-click an element. Args: selector."
1229
+ },
1230
+ {
1231
+ name: "fill",
1232
+ description: "Clear and fill a field. Args: selector, text."
1233
+ },
1234
+ {
1235
+ name: "type",
1236
+ description: "Type into an element. Args: selector, text."
1237
+ },
1238
+ {
1239
+ name: "press",
1240
+ description: "Press a key/chord (Enter, Control+a). Args: key."
1241
+ },
1242
+ {
1243
+ name: "hover",
1244
+ description: "Hover an element. Args: selector."
1245
+ },
1246
+ {
1247
+ name: "focus",
1248
+ description: "Focus an element. Args: selector."
1249
+ },
1250
+ {
1251
+ name: "select",
1252
+ description: "Select a dropdown option. Args: selector, value."
1253
+ },
1254
+ {
1255
+ name: "check",
1256
+ description: "Check a checkbox. Args: selector."
1257
+ },
1258
+ {
1259
+ name: "uncheck",
1260
+ description: "Uncheck a checkbox. Args: selector."
1261
+ },
1262
+ {
1263
+ name: "scroll",
1264
+ description: "Scroll. Args: direction(up|down|left|right), px?, selector?."
1265
+ },
1266
+ {
1267
+ name: "scrollintoview",
1268
+ description: "Scroll an element into view. Args: selector."
1269
+ },
1270
+ {
1271
+ name: "drag",
1272
+ description: "Drag and drop. Args: source, target."
1273
+ },
1274
+ {
1275
+ name: "upload",
1276
+ description: "Upload local file(s) to a file input. Args: selector, files[]."
1277
+ },
1278
+ {
1279
+ name: "find",
1280
+ description: "Act by semantic locator. Args: by(role|text|label|placeholder|alt|title|testid), query, action(click|fill|type|hover|focus|check|uncheck|text), value?, name?, exact?."
1281
+ },
1282
+ // AI fallbacks
1283
+ {
1284
+ name: "act",
1285
+ description: "Act on the page: ref+action (deterministic) or natural-language instruction (engine AI). Args: ref?, action?, value?, instruction?."
1286
+ },
1287
+ {
1288
+ name: "extract",
1289
+ description: "Extract data by natural-language instruction (engine AI). Args: instruction."
1290
+ },
1291
+ // wait
1292
+ {
1293
+ name: "wait",
1294
+ description: "Wait for a condition. Provide one of: selector(+state), ms, text, url, load, fn."
1295
+ },
1296
+ // tabs / frames
1297
+ {
1298
+ name: "tab",
1299
+ description: "Manage tabs. Args: action(list|new|switch|close), target?, url?, label?."
1300
+ },
1301
+ {
1302
+ name: "window_new",
1303
+ description: "Open a new browser window. Args: url?."
1304
+ },
1305
+ {
1306
+ name: "frame",
1307
+ description: 'Switch frame context. Args: target(@eN | CSS | "main").'
1308
+ },
1309
+ // capture
1310
+ {
1311
+ name: "screenshot",
1312
+ description: "Screenshot the page. Args: fullPage?, path?."
1313
+ },
1314
+ {
1315
+ name: "pdf",
1316
+ description: "Save the page as PDF. Args: path."
1317
+ },
1318
+ // state
1319
+ {
1320
+ name: "cookies",
1321
+ description: "Manage cookies. Args: action(get|set|clear), name?, value?."
1322
+ },
1323
+ {
1324
+ name: "storage",
1325
+ description: "Manage web storage. Args: area(local|session), action(get|set|clear), key?, value?."
1326
+ },
1327
+ {
1328
+ name: "set",
1329
+ description: "Configure the browser. Args: setting(viewport|device|geo|headers|credentials|media), args[]."
1330
+ },
1331
+ // files / clipboard
1332
+ {
1333
+ name: "download",
1334
+ description: "Download a file (click a selector to trigger, or wait for one). Args: selector?, path?."
1335
+ },
1336
+ {
1337
+ name: "clipboard",
1338
+ description: "Clipboard. Args: action(read|write|copy|paste), text?."
1339
+ },
1340
+ // auth (use-only)
1341
+ {
1342
+ name: "auth",
1343
+ description: "Use a saved login profile. Args: action(login|list|show), name?. (Credentials are saved via the desktop, never the agent.)"
1344
+ },
1345
+ // confirmation gate
1346
+ {
1347
+ name: "confirm",
1348
+ description: "Approve a pending confirmation_required action. Args: id."
1349
+ },
1350
+ {
1351
+ name: "deny",
1352
+ description: "Reject a pending confirmation_required action. Args: id."
1353
+ },
1354
+ // network / debug / input / state-files
1355
+ {
1356
+ name: "network",
1357
+ description: "Inspect/control network. Args: action(route|unroute|requests|har) + relevant fields."
1358
+ },
1359
+ {
1360
+ name: "console",
1361
+ description: "View browser console messages. Args: clear?."
1362
+ },
1363
+ {
1364
+ name: "errors",
1365
+ description: "View uncaught page JS errors. Args: clear?."
1366
+ },
1367
+ {
1368
+ name: "mouse",
1369
+ description: "Low-level mouse. Args: action(move|down|up|wheel), x?, y?, button?, dy?, dx?."
1370
+ },
1371
+ {
1372
+ name: "keyboard",
1373
+ description: "Low-level keyboard at focus. Args: action(type|inserttext|keydown|keyup), text?, key?."
1374
+ },
1375
+ {
1376
+ name: "state",
1377
+ description: "Persist/restore storage+auth state to a file. Args: action(save|load|list|clear), path?."
1378
+ }
1379
+ ];
1380
+ BROWSER_COMMAND_NAMES = BROWSER_COMMANDS.map((c) => c.name);
1381
+ REASONING_EFFORT_VALUES = [
1382
+ "off",
1383
+ "minimal",
1384
+ "low",
1385
+ "medium",
1386
+ "high",
1387
+ "max"
1388
+ ];
976
1389
  AGENT_NAME_TOKEN = "[Your Agent Name]";
977
1390
  DEFAULT_PERSONA_GUIDE = `# ${AGENT_NAME_TOKEN} - Persona
978
1391
 
@@ -2542,7 +2955,8 @@ var init_skill_handler = __esm({
2542
2955
  const response = await api.publishSkillVersion(entityId, version);
2543
2956
  return {
2544
2957
  success: response.success,
2545
- error: response.error?.message
2958
+ error: response.error?.message,
2959
+ agentVersion: response.data?.agentVersion
2546
2960
  };
2547
2961
  }
2548
2962
  prepareForPush(manifest, name, projectPath = process.cwd(), bundleAccumulator) {
@@ -6896,6 +7310,18 @@ var init_skill_plugin = __esm({
6896
7310
 
6897
7311
  // src/compiler/plugins/agent.plugin.ts
6898
7312
  import { Node as Node13 } from "ts-morph";
7313
+ function shapeReasoningSetting(value) {
7314
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
7315
+ const raw = value;
7316
+ const result = {};
7317
+ if (typeof raw.effort === "string" && REASONING_EFFORT_VALUES.includes(raw.effort)) {
7318
+ result.effort = raw.effort;
7319
+ }
7320
+ if (typeof raw.show === "boolean") {
7321
+ result.show = raw.show;
7322
+ }
7323
+ return Object.keys(result).length > 0 ? result : void 0;
7324
+ }
6899
7325
  function shapeModelSettings(raw) {
6900
7326
  const KNOWN_KEYS = [
6901
7327
  "temperature",
@@ -6905,7 +7331,8 @@ function shapeModelSettings(raw) {
6905
7331
  "presencePenalty",
6906
7332
  "frequencyPenalty",
6907
7333
  "stopSequences",
6908
- "seed"
7334
+ "seed",
7335
+ "reasoning"
6909
7336
  ];
6910
7337
  const result = {};
6911
7338
  for (const key of KNOWN_KEYS) {
@@ -6915,6 +7342,9 @@ function shapeModelSettings(raw) {
6915
7342
  if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
6916
7343
  result[key] = value;
6917
7344
  }
7345
+ } else if (key === "reasoning") {
7346
+ const shaped = shapeReasoningSetting(value);
7347
+ if (shaped) result[key] = shaped;
6918
7348
  } else if (typeof value === "number" && Number.isFinite(value)) {
6919
7349
  result[key] = value;
6920
7350
  }
@@ -6954,7 +7384,8 @@ var init_agent_plugin = __esm({
6954
7384
  "description",
6955
7385
  "persona",
6956
7386
  "model",
6957
- "modelSettings"
7387
+ "modelSettings",
7388
+ "browser"
6958
7389
  ]
6959
7390
  };
6960
7391
  supportsClassDefinition = true;
@@ -7011,6 +7442,8 @@ var init_agent_plugin = __esm({
7011
7442
  const governanceHit = findClassMember(classDecl, "governance", "property");
7012
7443
  const governanceObj = governanceHit && Node13.isPropertyDeclaration(governanceHit.node) ? evaluateNodeAsObject(governanceHit.node.getInitializer()) : void 0;
7013
7444
  const governance = governanceObj && typeof governanceObj.mode === "string" ? governanceObj : void 0;
7445
+ const browserHit = findClassMember(classDecl, "browser", "property");
7446
+ const browser = browserHit && Node13.isPropertyDeclaration(browserHit.node) ? this.shapeBrowserNode(browserHit.node.getInitializer()) : void 0;
7014
7447
  const modelSettingsHit = findClassMember(classDecl, "modelSettings", "property");
7015
7448
  const modelSettingsObj = modelSettingsHit && Node13.isPropertyDeclaration(modelSettingsHit.node) ? evaluateNodeAsObject(modelSettingsHit.node.getInitializer()) : void 0;
7016
7449
  const modelSettings = modelSettingsObj ? shapeModelSettings(modelSettingsObj) : void 0;
@@ -7030,7 +7463,8 @@ var init_agent_plugin = __esm({
7030
7463
  hasModelResolver,
7031
7464
  modelSettings,
7032
7465
  batching,
7033
- governance
7466
+ governance,
7467
+ browser
7034
7468
  }
7035
7469
  };
7036
7470
  }
@@ -7061,6 +7495,7 @@ var init_agent_plugin = __esm({
7061
7495
  const modelSettings = this.extractModelSettings(config);
7062
7496
  const batching = this.extractBatchingInfo(config);
7063
7497
  const governance = this.extractGovernanceInfo(config);
7498
+ const browser = this.extractBrowserInfo(config);
7064
7499
  const { voiceRefNames, voiceRefSourcePaths } = this.extractVoiceRefs(config);
7065
7500
  return {
7066
7501
  kind: this.kind,
@@ -7078,12 +7513,34 @@ var init_agent_plugin = __esm({
7078
7513
  modelSettings,
7079
7514
  batching,
7080
7515
  governance,
7516
+ browser,
7081
7517
  voiceRefNames,
7082
7518
  voiceRefSourcePaths
7083
7519
  }
7084
7520
  };
7085
7521
  }
7086
7522
  /**
7523
+ * Extract the `browser` switch (LuaBrowser). `true` → true; an object → its
7524
+ * evaluated shape; `false`/absent → undefined (off by default).
7525
+ */
7526
+ extractBrowserInfo(config) {
7527
+ const prop = config.getProperty("browser");
7528
+ if (!prop || !Node13.isPropertyAssignment(prop)) return void 0;
7529
+ return this.shapeBrowserNode(prop.getInitializer());
7530
+ }
7531
+ /**
7532
+ * Normalize a `browser` initializer (config-literal or class-member) to the
7533
+ * switch value: `true` → true; `false`/absent → undefined; an object → its
7534
+ * evaluated shape. A resolution failure leaves the switch OFF (undefined) —
7535
+ * mirroring `governance`, never silently "enabled with default policy".
7536
+ */
7537
+ shapeBrowserNode(init) {
7538
+ if (!init) return void 0;
7539
+ const obj = evaluateNodeAsObject(init);
7540
+ if (obj) return obj;
7541
+ return evaluateNodeAsBoolean(init) === true ? true : void 0;
7542
+ }
7543
+ /**
7087
7544
  * Read the `voices` array property and return both the identifiers and
7088
7545
  * the resolver-discovered source file for each.
7089
7546
  *
@@ -7241,6 +7698,7 @@ var init_agent_plugin = __esm({
7241
7698
  modelSettings: agentMeta.modelSettings,
7242
7699
  batching: agentMeta.batching,
7243
7700
  governance: agentMeta.governance,
7701
+ browser: agentMeta.browser,
7244
7702
  voiceRefs
7245
7703
  };
7246
7704
  }
@@ -7300,6 +7758,7 @@ var init_agent_plugin = __esm({
7300
7758
  return rest;
7301
7759
  }
7302
7760
  };
7761
+ __name(shapeReasoningSetting, "shapeReasoningSetting");
7303
7762
  __name(shapeModelSettings, "shapeModelSettings");
7304
7763
  agentPlugin = new AgentPlugin();
7305
7764
  }
@@ -12384,6 +12843,9 @@ var init_agents_api_service = __esm({
12384
12843
  } : {},
12385
12844
  ...body.webhookPayload !== void 0 ? {
12386
12845
  webhookPayload: body.webhookPayload
12846
+ } : {},
12847
+ ...body.clientContext !== void 0 ? {
12848
+ clientContext: body.clientContext
12387
12849
  } : {}
12388
12850
  };
12389
12851
  }
@@ -12835,6 +13297,12 @@ var init_channels_send_api_service = __esm({
12835
13297
  Authorization: `Bearer ${this.apiKey}`
12836
13298
  });
12837
13299
  }
13300
+ /** POST /developer/agents/:agentId/channels/whatsapp/reaction */
13301
+ async sendWhatsAppReaction(input) {
13302
+ return this.httpPost(`/developer/agents/${this.agentId}/channels/whatsapp/reaction`, input, {
13303
+ Authorization: `Bearer ${this.apiKey}`
13304
+ });
13305
+ }
12838
13306
  /** POST /developer/agents/:agentId/channels/email/send */
12839
13307
  async sendEmail(input) {
12840
13308
  return this.httpPost(`/developer/agents/${this.agentId}/channels/email/send`, input, {
@@ -12866,6 +13334,17 @@ var init_channels_send_api_service = __esm({
12866
13334
  }
12867
13335
  return result.data;
12868
13336
  }
13337
+ /** Sandbox helper for WhatsApp reaction sends. */
13338
+ async sendWhatsAppReactionForSandbox(input) {
13339
+ const result = await this.sendWhatsAppReaction(input);
13340
+ if (!result.success) {
13341
+ throw new Error(result.error?.message || "WhatsApp reaction send failed");
13342
+ }
13343
+ if (!result.data) {
13344
+ throw new Error("WhatsApp reaction send failed: empty response");
13345
+ }
13346
+ return result.data;
13347
+ }
12869
13348
  /** Sandbox helper for email sends. */
12870
13349
  async sendEmailForSandbox(input) {
12871
13350
  const result = await this.sendEmail(input);
@@ -12881,6 +13360,44 @@ var init_channels_send_api_service = __esm({
12881
13360
  }
12882
13361
  });
12883
13362
 
13363
+ // src/api/directory.api.service.ts
13364
+ var DirectoryApiService;
13365
+ var init_directory_api_service = __esm({
13366
+ "src/api/directory.api.service.ts"() {
13367
+ "use strict";
13368
+ init_http_client();
13369
+ DirectoryApiService = class extends HttpClient {
13370
+ static {
13371
+ __name(this, "DirectoryApiService");
13372
+ }
13373
+ apiKey;
13374
+ agentId;
13375
+ constructor(baseUrl, apiKey, agentId) {
13376
+ super(baseUrl), this.apiKey = apiKey, this.agentId = agentId;
13377
+ }
13378
+ /** POST /developer/agents/:agentId/directory/resolve */
13379
+ async resolve(name) {
13380
+ return this.httpPost(`/developer/agents/${this.agentId}/directory/resolve`, {
13381
+ name
13382
+ }, {
13383
+ Authorization: `Bearer ${this.apiKey}`
13384
+ });
13385
+ }
13386
+ /** Sandbox helper: throws on non-success, returns unwrapped result. */
13387
+ async resolveForSandbox(name) {
13388
+ const result = await this.resolve(name);
13389
+ if (!result.success) {
13390
+ throw new Error(result.error?.message || "Directory resolve failed");
13391
+ }
13392
+ if (!result.data) {
13393
+ throw new Error("Directory resolve failed: empty response");
13394
+ }
13395
+ return result.data;
13396
+ }
13397
+ };
13398
+ }
13399
+ });
13400
+
12884
13401
  // src/api/device.api.service.ts
12885
13402
  var device_api_service_exports = {};
12886
13403
  __export(device_api_service_exports, {
@@ -12977,6 +13494,7 @@ __export(lazy_instances_exports, {
12977
13494
  getDataInstance: () => getDataInstance,
12978
13495
  getDeveloperInstance: () => getDeveloperInstance,
12979
13496
  getDeviceInstance: () => getDeviceInstance,
13497
+ getDirectoryInstance: () => getDirectoryInstance,
12980
13498
  getJobInstance: () => getJobInstance,
12981
13499
  getOrderInstance: () => getOrderInstance,
12982
13500
  getProductsInstance: () => getProductsInstance,
@@ -13091,6 +13609,13 @@ async function getChannelsSendInstance() {
13091
13609
  }
13092
13610
  return _channelsSendInstance;
13093
13611
  }
13612
+ async function getDirectoryInstance() {
13613
+ if (!_directoryInstance) {
13614
+ const creds = await getCredentials();
13615
+ _directoryInstance = new DirectoryApiService(BASE_URLS.API, creds.apiKey, creds.agentId);
13616
+ }
13617
+ return _directoryInstance;
13618
+ }
13094
13619
  function clearAllInstances() {
13095
13620
  _userInstance = null;
13096
13621
  _dataInstance = null;
@@ -13106,8 +13631,9 @@ function clearAllInstances() {
13106
13631
  _developerInstance = null;
13107
13632
  _voiceInstance = null;
13108
13633
  _channelsSendInstance = null;
13634
+ _directoryInstance = null;
13109
13635
  }
13110
- var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _channelsSendInstance, _deviceInstance;
13636
+ var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _channelsSendInstance, _directoryInstance, _deviceInstance;
13111
13637
  var init_lazy_instances = __esm({
13112
13638
  "src/api/lazy-instances.ts"() {
13113
13639
  "use strict";
@@ -13127,6 +13653,7 @@ var init_lazy_instances = __esm({
13127
13653
  init_developer_api_service();
13128
13654
  init_voice_api_service();
13129
13655
  init_channels_send_api_service();
13656
+ init_directory_api_service();
13130
13657
  _userInstance = null;
13131
13658
  _dataInstance = null;
13132
13659
  _productsInstance = null;
@@ -13141,6 +13668,7 @@ var init_lazy_instances = __esm({
13141
13668
  _developerInstance = null;
13142
13669
  _voiceInstance = null;
13143
13670
  _channelsSendInstance = null;
13671
+ _directoryInstance = null;
13144
13672
  __name(getUserInstance, "getUserInstance");
13145
13673
  __name(getDataInstance, "getDataInstance");
13146
13674
  __name(getProductsInstance, "getProductsInstance");
@@ -13157,6 +13685,7 @@ var init_lazy_instances = __esm({
13157
13685
  __name(getDeveloperInstance, "getDeveloperInstance");
13158
13686
  __name(getVoiceInstance, "getVoiceInstance");
13159
13687
  __name(getChannelsSendInstance, "getChannelsSendInstance");
13688
+ __name(getDirectoryInstance, "getDirectoryInstance");
13160
13689
  __name(clearAllInstances, "clearAllInstances");
13161
13690
  }
13162
13691
  });
@@ -16216,6 +16745,28 @@ var AgentHandler = class {
16216
16745
  success: false
16217
16746
  };
16218
16747
  }
16748
+ const browser = agent?.browser ?? null;
16749
+ writeProgress("\n\u{1F310} Pushing browser switch...");
16750
+ try {
16751
+ const success2 = await this.pushBrowser({
16752
+ apiKey,
16753
+ agentId
16754
+ }, browser);
16755
+ result.browser = {
16756
+ success: success2
16757
+ };
16758
+ if (success2) {
16759
+ writeSuccess(browser ? " \u2705 Browser switch pushed" : " \u2705 Browser switch off (default)");
16760
+ } else {
16761
+ console.error(" \u274C Failed to push browser switch");
16762
+ }
16763
+ } catch (error) {
16764
+ if (AuthenticationError.isAuthenticationError(error)) throw error;
16765
+ console.error(` \u274C Failed to push browser switch: ${error.message}`);
16766
+ result.browser = {
16767
+ success: false
16768
+ };
16769
+ }
16219
16770
  const voiceRefNames = agent?.voiceRefs?.map((v) => v.name) ?? [];
16220
16771
  let voicesLinkPayload = [];
16221
16772
  let skipVoicesPush = false;
@@ -16337,6 +16888,13 @@ var AgentHandler = class {
16337
16888
  });
16338
16889
  return result.success;
16339
16890
  }
16891
+ async pushBrowser(ctx, browser) {
16892
+ const agentApi = new AgentApi(BASE_URLS.API, ctx.apiKey);
16893
+ const result = await agentApi.updateAgent(ctx.agentId, {
16894
+ browser
16895
+ });
16896
+ return result.success;
16897
+ }
16340
16898
  async pushVoices(ctx, voices) {
16341
16899
  const agentApi = new AgentApi(BASE_URLS.API, ctx.apiKey);
16342
16900
  const result = await agentApi.updateAgent(ctx.agentId, {
@@ -18403,7 +18961,8 @@ var WebhookHandler = class extends BaseVersionedHandler {
18403
18961
  const response = await api.publishWebhookVersion(entityId, version);
18404
18962
  return {
18405
18963
  success: response.success,
18406
- error: response.error?.message
18964
+ error: response.error?.message,
18965
+ agentVersion: response.data?.agentVersion
18407
18966
  };
18408
18967
  }
18409
18968
  /**
@@ -18613,7 +19172,8 @@ var TriggerHandler = class extends BaseVersionedHandler {
18613
19172
  const response = await api.publishTriggerVersion(entityId, version);
18614
19173
  return {
18615
19174
  success: response.success,
18616
- error: response.error?.message
19175
+ error: response.error?.message,
19176
+ agentVersion: response.data?.agentVersion
18617
19177
  };
18618
19178
  }
18619
19179
  /** Include the trigger's body schema (from the SDK inputSchema) in push data. */
@@ -18723,7 +19283,8 @@ var JobHandler = class extends BaseVersionedHandler {
18723
19283
  const response = await api.publishJobVersion(entityId, version);
18724
19284
  return {
18725
19285
  success: response.success,
18726
- error: response.error?.message
19286
+ error: response.error?.message,
19287
+ agentVersion: response.data?.agentVersion
18727
19288
  };
18728
19289
  }
18729
19290
  /**
@@ -18798,7 +19359,8 @@ var PreprocessorHandler = class extends BaseVersionedHandler {
18798
19359
  const response = await api.publishPreProcessorVersion(entityId, version);
18799
19360
  return {
18800
19361
  success: response.success,
18801
- error: response.error?.message
19362
+ error: response.error?.message,
19363
+ agentVersion: response.data?.agentVersion
18802
19364
  };
18803
19365
  }
18804
19366
  /**
@@ -18874,7 +19436,8 @@ var PostprocessorHandler = class extends BaseVersionedHandler {
18874
19436
  const response = await api.publishPostProcessorVersion(entityId, version);
18875
19437
  return {
18876
19438
  success: response.success,
18877
- error: response.error?.message
19439
+ error: response.error?.message,
19440
+ agentVersion: response.data?.agentVersion
18878
19441
  };
18879
19442
  }
18880
19443
  /**
@@ -20730,7 +21293,12 @@ function createSandbox(options) {
20730
21293
  const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
20731
21294
  const channels = await getChannelsSendInstance2();
20732
21295
  return channels.sendWhatsAppTemplateForSandbox(input);
20733
- }, "sendTemplate")
21296
+ }, "sendTemplate"),
21297
+ sendReaction: /* @__PURE__ */ __name(async (input) => {
21298
+ const { getChannelsSendInstance: getChannelsSendInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
21299
+ const channels = await getChannelsSendInstance2();
21300
+ return channels.sendWhatsAppReactionForSandbox(input);
21301
+ }, "sendReaction")
20734
21302
  },
20735
21303
  email: {
20736
21304
  send: /* @__PURE__ */ __name(async (input) => {
@@ -20739,6 +21307,17 @@ function createSandbox(options) {
20739
21307
  return channels.sendEmailForSandbox(input);
20740
21308
  }, "send")
20741
21309
  }
21310
+ },
21311
+ // Workspace directory. Resolve a teammate by name within the agent's org and
21312
+ // get the channel handles they opted to share — feed the result straight into
21313
+ // `Channels.send`. Proxied via the lua-cli developer endpoint (Bearer auth),
21314
+ // byte-equivalent to the lua-core production VM.
21315
+ Team: {
21316
+ findMember: /* @__PURE__ */ __name(async (name) => {
21317
+ const { getDirectoryInstance: getDirectoryInstance2 } = await Promise.resolve().then(() => (init_lazy_instances(), lazy_instances_exports));
21318
+ const directory = await getDirectoryInstance2();
21319
+ return directory.resolveForSandbox(name);
21320
+ }, "findMember")
20742
21321
  }
20743
21322
  };
20744
21323
  return createBaseSandboxContext({
@@ -24398,6 +24977,9 @@ Until the backup catches up, \`lua init\` for this agent will restore an older s
24398
24977
  }
24399
24978
  }
24400
24979
  writeSuccess("\n\u2705 Push All Complete!\n");
24980
+ if (options.autoDeployNoopWarned) {
24981
+ writeInfo("\u26A0\uFE0F --auto-deploy was ignored (agent versioning is on). To deploy, run `lua version create` then `lua version promote <version>`.\n");
24982
+ }
24401
24983
  const byKind = /* @__PURE__ */ new Map();
24402
24984
  for (const r of allResults) {
24403
24985
  const kind = r.handler.displayNamePlural;
@@ -24560,6 +25142,14 @@ async function confirmDeployment() {
24560
25142
  return confirmed;
24561
25143
  }
24562
25144
  __name(confirmDeployment, "confirmDeployment");
25145
+ function formatDeploySuccess(params) {
25146
+ const { label, name, version, agentVersion } = params;
25147
+ if (agentVersion != null) {
25148
+ return `\u2714 deployed ${name}@${version} \u2014 agent version ${agentVersion} promoted`;
25149
+ }
25150
+ return `\u2705 ${label} "${name}" v${version} deployed successfully`;
25151
+ }
25152
+ __name(formatDeploySuccess, "formatDeploySuccess");
24563
25153
 
24564
25154
  // src/commands/deploy.ts
24565
25155
  init_constants();
@@ -24723,7 +25313,7 @@ async function deployCommand(type, cmdObj) {
24723
25313
  selectedType = answer.type;
24724
25314
  }
24725
25315
  const apiKey = await requireAuthOrExit();
24726
- writeInfo("\u26A0\uFE0F `lua deploy` is deprecated when agent versioning is on. Use `lua version promote <version>` for instant, atomic promotion.");
25316
+ writeInfo("\u2139\uFE0F For agents under versioning, `lua deploy` creates and promotes a new agent version scoped to this primitive; otherwise it goes live directly. For multi-primitive releases, `lua version promote <version>` remains the recommended flow.");
24727
25317
  let personaDeployed = false;
24728
25318
  let versionedOutcome = null;
24729
25319
  if (selectedType === "persona") {
@@ -24737,7 +25327,7 @@ async function deployCommand(type, cmdObj) {
24737
25327
  force_mode: options.force || false,
24738
25328
  entity_selected_by_name: !!options.name,
24739
25329
  version_selected_by_flag: !!options.version,
24740
- granular_deprecation_warned: true
25330
+ scoped_promote_notice: true
24741
25331
  });
24742
25332
  const deployed = selectedType === "persona" ? personaDeployed : versionedOutcome?.deployed ?? false;
24743
25333
  const hintPrintedAlready = selectedType !== "persona" && !!versionedOutcome?.hintPrinted;
@@ -24877,9 +25467,14 @@ Available ${deployConfig.label}s:`);
24877
25467
  writeProgress("\u{1F504} Publishing version...");
24878
25468
  const result = await deployConfig.handler.publishVersion(apiKey, agentId, entityId, selectedVersion);
24879
25469
  if (!result.success) {
24880
- throw new Error(`Failed to deploy: ${result.error || "Unknown error"}`);
25470
+ throw new Error(result.error || "Failed to deploy");
24881
25471
  }
24882
- writeSuccess(`\u2705 ${deployConfig.label} "${selectedEntity.name}" v${selectedVersion} deployed successfully`);
25472
+ writeSuccess(formatDeploySuccess({
25473
+ label: deployConfig.label,
25474
+ name: selectedEntity.name,
25475
+ version: selectedVersion,
25476
+ agentVersion: result.agentVersion
25477
+ }));
24883
25478
  if (selectedVersion !== selectedEntity.version) {
24884
25479
  writeInfo(`\u{1F4DD} Updating YAML with deployed version: ${selectedVersion}`);
24885
25480
  deployConfig.handler.updateVersionInYaml(selectedEntity.name, selectedVersion);
@@ -24979,6 +25574,7 @@ async function deployAllCommand(_options) {
24979
25574
  validateSkillConfig(config);
24980
25575
  const apiKey = await requireAuthOrExit();
24981
25576
  const agentId = config.agent.agentId;
25577
+ writeInfo("\u2139\uFE0F For agents under versioning, each deploy below creates and promotes an agent version scoped to that primitive. To switch everything atomically in one version instead, use `lua version create` + `lua version promote`.");
24982
25578
  let deployedCount = 0;
24983
25579
  let failedCount = 0;
24984
25580
  const failedItems = [];
@@ -25000,7 +25596,12 @@ async function deployAllCommand(_options) {
25000
25596
  const latestVersion = sortVersionsByDate(versions)[0].version;
25001
25597
  const result = await deployConfig.handler.publishVersion(apiKey, agentId, entityId, latestVersion);
25002
25598
  if (result.success) {
25003
- writeSuccess(` \u2705 ${deployConfig.label} "${entity.name}" v${latestVersion} deployed`);
25599
+ writeSuccess(` ${formatDeploySuccess({
25600
+ label: deployConfig.label,
25601
+ name: entity.name,
25602
+ version: latestVersion,
25603
+ agentVersion: result.agentVersion
25604
+ })}`);
25004
25605
  if (latestVersion !== entity.version) {
25005
25606
  deployConfig.handler.updateVersionInYaml(entity.name, latestVersion);
25006
25607
  }
@@ -26414,6 +27015,10 @@ function stopTypingIndicator(interval) {
26414
27015
  process.stdout.write("\r\x1B[K");
26415
27016
  }
26416
27017
  __name(stopTypingIndicator, "stopTypingIndicator");
27018
+ function getClientTimeZone() {
27019
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
27020
+ }
27021
+ __name(getClientTimeZone, "getClientTimeZone");
26417
27022
  async function sendSandboxMessageStream(chatEnv, messages, callbacks) {
26418
27023
  if (!chatEnv.yamlConfig) {
26419
27024
  throw new Error("Sandbox environment not properly initialized.");
@@ -26424,7 +27029,10 @@ async function sendSandboxMessageStream(chatEnv, messages, callbacks) {
26424
27029
  navigate: true,
26425
27030
  skillOverride: allSkillOverrides,
26426
27031
  preprocessorOverride: chatEnv.preprocessorOverrides || [],
26427
- postprocessorOverride: chatEnv.postprocessorOverrides || []
27032
+ postprocessorOverride: chatEnv.postprocessorOverrides || [],
27033
+ clientContext: {
27034
+ timezone: getClientTimeZone()
27035
+ }
26428
27036
  };
26429
27037
  if (chatEnv.persona) {
26430
27038
  chatRequest.personaOverride = chatEnv.persona;
@@ -26445,7 +27053,10 @@ async function sendProductionMessageStream(chatEnv, messages, callbacks) {
26445
27053
  navigate: true,
26446
27054
  skillOverride: [],
26447
27055
  preprocessorOverride: [],
26448
- postprocessorOverride: []
27056
+ postprocessorOverride: [],
27057
+ clientContext: {
27058
+ timezone: getClientTimeZone()
27059
+ }
26449
27060
  };
26450
27061
  if (chatEnv.threadId) {
26451
27062
  chatRequest.threadId = chatEnv.threadId;
@@ -43416,6 +44027,7 @@ init_cli();
43416
44027
  init_command_utils();
43417
44028
  init_analytics();
43418
44029
  init_files();
44030
+ init_semver();
43419
44031
  init_constants();
43420
44032
 
43421
44033
  // src/utils/parse-version.ts
@@ -43471,6 +44083,11 @@ async function versionCreateCommand(options = {}) {
43471
44083
  commitHash: options.commitHash
43472
44084
  });
43473
44085
  if (!result.success || !result.data) {
44086
+ const errCode = result.error?.code;
44087
+ if (errCode === "NO_STAGED_CHANGES") {
44088
+ writeInfo("\u2139\uFE0F No changes since the latest version, so there is nothing to snapshot. Make and push your changes (`lua push`), then run `lua version create`.");
44089
+ return;
44090
+ }
43474
44091
  throw new Error(result.error?.message ?? "Failed to create version");
43475
44092
  }
43476
44093
  writeInfo(`\u2713 Created v${result.data.version} (staged). Run \`lua version promote v${result.data.version}\` to deploy.`);
@@ -43692,6 +44309,7 @@ async function versionDiffCommand(fromArg, toArg, options = {}) {
43692
44309
  console.log(`Persona: ${diff.persona.from} \u2192 ${diff.persona.to}`);
43693
44310
  }
43694
44311
  console.log(`Model: ${diff.model ? `${diff.model.from} \u2192 ${diff.model.to}` : "(unchanged)"}`);
44312
+ console.log(`Voice: ${diff.voice ? `${diff.voice.from ?? "(none)"} \u2192 ${diff.voice.to ?? "(none)"}` : "(unchanged)"}`);
43695
44313
  }
43696
44314
  trackEvent("cli_version_diff_completed", {
43697
44315
  from_to_distance: Math.abs(to - from)
@@ -43790,6 +44408,202 @@ async function versionDeleteCommand(versionArg, options = {}) {
43790
44408
  }, "version delete");
43791
44409
  }
43792
44410
  __name(versionDeleteCommand, "versionDeleteCommand");
44411
+ function buildVersionStatusRows(inputs) {
44412
+ const rows = [];
44413
+ for (const { type, localItems, pinned } of inputs) {
44414
+ for (const item of localItems) {
44415
+ const match = (item.id ? pinned.find((p) => p.id === item.id) : void 0) ?? pinned.find((p) => p.name != null && p.name === item.name);
44416
+ const pinnedVersion = match ? match.version : null;
44417
+ const mismatch = pinnedVersion == null || pinnedVersion !== item.version;
44418
+ const localBehind = pinnedVersion != null && mismatch && compareVersions(item.version, pinnedVersion) < 0;
44419
+ rows.push({
44420
+ type,
44421
+ name: item.name,
44422
+ pinnedVersion,
44423
+ localVersion: item.version,
44424
+ mismatch,
44425
+ localBehind
44426
+ });
44427
+ }
44428
+ }
44429
+ return rows;
44430
+ }
44431
+ __name(buildVersionStatusRows, "buildVersionStatusRows");
44432
+ function formatVersionStatusTable(rows) {
44433
+ const header = {
44434
+ flag: " ",
44435
+ type: "TYPE",
44436
+ name: "NAME",
44437
+ active: "ACTIVE VERSION",
44438
+ local: "LOCAL"
44439
+ };
44440
+ const display = rows.map((r) => ({
44441
+ flag: r.mismatch ? "\u26A0" : " ",
44442
+ type: r.type,
44443
+ name: r.name,
44444
+ active: r.pinnedVersion != null ? `v${r.pinnedVersion}` : "\u2014 not in active version",
44445
+ local: `v${r.localVersion}`
44446
+ }));
44447
+ const cols = [
44448
+ "flag",
44449
+ "type",
44450
+ "name",
44451
+ "active",
44452
+ "local"
44453
+ ];
44454
+ const widths = {};
44455
+ for (const c of cols) {
44456
+ widths[c] = Math.max(header[c].length, ...display.map((r) => r[c].length));
44457
+ }
44458
+ const fmt = /* @__PURE__ */ __name((r) => cols.map((c) => r[c].padEnd(widths[c])).join(" ").trimEnd(), "fmt");
44459
+ return [
44460
+ fmt(header),
44461
+ ...display.map(fmt)
44462
+ ];
44463
+ }
44464
+ __name(formatVersionStatusTable, "formatVersionStatusTable");
44465
+ async function versionStatusCommand() {
44466
+ return withErrorHandling(async () => {
44467
+ const { apiKey, agentId } = await initializeCommand();
44468
+ const config = readYamlConfig();
44469
+ const api = new AgentVersionApi(BASE_URLS.API, apiKey, agentId);
44470
+ const listResponse = await api.listVersions({
44471
+ all: true
44472
+ });
44473
+ if (!listResponse.success || !listResponse.data) {
44474
+ throw new Error(listResponse.error?.message ?? "Failed to fetch versions");
44475
+ }
44476
+ const versions = listResponse.data;
44477
+ if (versions.length === 0) {
44478
+ writeInfo("This agent has no versions. Per-primitive deploys (`lua deploy`) go live immediately for agents that are not under versioning.");
44479
+ trackEvent("cli_version_status_completed", {
44480
+ has_versions: false,
44481
+ has_active: false,
44482
+ mismatches: 0
44483
+ });
44484
+ return;
44485
+ }
44486
+ const active = versions.find((v) => v.status === "active");
44487
+ if (!active) {
44488
+ writeInfo("This agent has versions but none is active yet. Run `lua version promote <version>` to make one live.");
44489
+ trackEvent("cli_version_status_completed", {
44490
+ has_versions: true,
44491
+ has_active: false,
44492
+ mismatches: 0
44493
+ });
44494
+ return;
44495
+ }
44496
+ const versionResponse = await api.getVersion(active.version);
44497
+ if (!versionResponse.success || !versionResponse.data) {
44498
+ throw new Error(versionResponse.error?.message ?? `Failed to fetch v${active.version}`);
44499
+ }
44500
+ const snapshot = versionResponse.data.snapshot;
44501
+ const inputs = [
44502
+ {
44503
+ type: "skill",
44504
+ localItems: skillHandler.getFromYaml(config).map((i) => ({
44505
+ name: i.name,
44506
+ version: i.version,
44507
+ id: i.skillId
44508
+ })),
44509
+ pinned: snapshot.skills.map((p) => ({
44510
+ id: p.skillId,
44511
+ version: p.version,
44512
+ name: p.name
44513
+ }))
44514
+ },
44515
+ {
44516
+ type: "webhook",
44517
+ localItems: webhookHandler.getFromYaml(config).map((i) => ({
44518
+ name: i.name,
44519
+ version: i.version,
44520
+ id: i.webhookId
44521
+ })),
44522
+ pinned: snapshot.webhooks.map((p) => ({
44523
+ id: p.webhookId,
44524
+ version: p.version,
44525
+ name: p.name
44526
+ }))
44527
+ },
44528
+ {
44529
+ type: "job",
44530
+ localItems: jobHandler.getFromYaml(config).map((i) => ({
44531
+ name: i.name,
44532
+ version: i.version,
44533
+ id: i.jobId
44534
+ })),
44535
+ pinned: snapshot.jobs.map((p) => ({
44536
+ id: p.jobId,
44537
+ version: p.version,
44538
+ name: p.name
44539
+ }))
44540
+ },
44541
+ {
44542
+ type: "preprocessor",
44543
+ localItems: preprocessorHandler.getFromYaml(config).map((i) => ({
44544
+ name: i.name,
44545
+ version: i.version,
44546
+ id: i.preprocessorId
44547
+ })),
44548
+ pinned: snapshot.preprocessors.map((p) => ({
44549
+ id: p.id,
44550
+ version: p.version,
44551
+ name: p.name
44552
+ }))
44553
+ },
44554
+ {
44555
+ type: "postprocessor",
44556
+ localItems: postprocessorHandler.getFromYaml(config).map((i) => ({
44557
+ name: i.name,
44558
+ version: i.version,
44559
+ id: i.postprocessorId
44560
+ })),
44561
+ pinned: snapshot.postprocessors.map((p) => ({
44562
+ id: p.id,
44563
+ version: p.version,
44564
+ name: p.name
44565
+ }))
44566
+ },
44567
+ {
44568
+ type: "trigger",
44569
+ localItems: triggerHandler.getFromYaml(config).map((i) => ({
44570
+ name: i.name,
44571
+ version: i.version,
44572
+ id: i.triggerId
44573
+ })),
44574
+ pinned: (snapshot.triggers ?? []).map((p) => ({
44575
+ id: p.triggerId,
44576
+ version: p.version,
44577
+ name: p.name
44578
+ }))
44579
+ }
44580
+ ];
44581
+ const rows = buildVersionStatusRows(inputs);
44582
+ const mismatches = rows.filter((r) => r.mismatch).length;
44583
+ console.log(`Active agent version: v${active.version}`);
44584
+ if (rows.length === 0) {
44585
+ writeInfo("(no local primitives found in lua.skill.yaml)");
44586
+ } else {
44587
+ for (const line of formatVersionStatusTable(rows)) {
44588
+ console.log(line);
44589
+ }
44590
+ const behind = rows.filter((r) => r.localBehind).length;
44591
+ const ahead = mismatches - behind;
44592
+ if (ahead > 0) {
44593
+ writeInfo(`\u26A0 ${ahead} primitive(s) are ahead of the active version (see rows marked above). Run \`lua version create\` then \`lua version promote\` to make them live, or \`lua deploy <type>\` for a single primitive.`);
44594
+ }
44595
+ if (behind > 0) {
44596
+ writeInfo(`\u26A0 ${behind} primitive(s) have a local version OLDER than what's live \u2014 deploying them would roll production back. Run \`lua sync\` to update your local files instead.`);
44597
+ }
44598
+ }
44599
+ trackEvent("cli_version_status_completed", {
44600
+ has_versions: true,
44601
+ has_active: true,
44602
+ mismatches
44603
+ });
44604
+ }, "version status");
44605
+ }
44606
+ __name(versionStatusCommand, "versionStatusCommand");
43793
44607
 
43794
44608
  // src/commands/git.ts
43795
44609
  init_cli();
@@ -44773,6 +45587,10 @@ Examples:
44773
45587
  $ lua version promote 3 Promote v3 to the active version
44774
45588
  $ lua version promote v3 Same (v-prefix accepted)
44775
45589
  `).action((version) => versionPromoteCommand(version));
45590
+ versionGroup.command("status").description("Compare local primitives against the active agent version (what is pushed vs. live)").addHelpText("after", `
45591
+ Examples:
45592
+ $ lua version status Show which local primitives differ from the active version
45593
+ `).action(() => versionStatusCommand());
44776
45594
  versionGroup.command("delete <version>").description("Soft-delete a version").option("--force", "Skip confirmation prompt").addHelpText("after", `
44777
45595
  Examples:
44778
45596
  $ lua version delete 3 Delete v3 (confirms first)