lua-cli 3.12.1 → 3.13.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.
Files changed (235) hide show
  1. package/dist/api/logs.api.service.d.ts +6 -3
  2. package/dist/api/logs.api.service.d.ts.map +1 -1
  3. package/dist/api/logs.api.service.js +5 -4
  4. package/dist/api/logs.api.service.js.map +1 -1
  5. package/dist/cli/command-definitions.d.ts.map +1 -1
  6. package/dist/cli/command-definitions.js +24 -2
  7. package/dist/cli/command-definitions.js.map +1 -1
  8. package/dist/commands/channels.d.ts.map +1 -1
  9. package/dist/commands/channels.js +2 -11
  10. package/dist/commands/channels.js.map +1 -1
  11. package/dist/commands/chat-log-probe.d.ts +59 -0
  12. package/dist/commands/chat-log-probe.d.ts.map +1 -0
  13. package/dist/commands/chat-log-probe.js +91 -0
  14. package/dist/commands/chat-log-probe.js.map +1 -0
  15. package/dist/commands/chat.d.ts.map +1 -1
  16. package/dist/commands/chat.js +134 -28
  17. package/dist/commands/chat.js.map +1 -1
  18. package/dist/commands/compile.d.ts +7 -0
  19. package/dist/commands/compile.d.ts.map +1 -1
  20. package/dist/commands/compile.js +32 -2
  21. package/dist/commands/compile.js.map +1 -1
  22. package/dist/commands/completion.d.ts.map +1 -1
  23. package/dist/commands/completion.js +7 -8
  24. package/dist/commands/completion.js.map +1 -1
  25. package/dist/commands/deploy.d.ts.map +1 -1
  26. package/dist/commands/deploy.js +108 -23
  27. package/dist/commands/deploy.js.map +1 -1
  28. package/dist/commands/devices.d.ts.map +1 -1
  29. package/dist/commands/devices.js +3 -2
  30. package/dist/commands/devices.js.map +1 -1
  31. package/dist/commands/env.d.ts.map +1 -1
  32. package/dist/commands/env.js +43 -20
  33. package/dist/commands/env.js.map +1 -1
  34. package/dist/commands/features.d.ts.map +1 -1
  35. package/dist/commands/features.js +2 -12
  36. package/dist/commands/features.js.map +1 -1
  37. package/dist/commands/governance.d.ts.map +1 -1
  38. package/dist/commands/governance.js +4 -8
  39. package/dist/commands/governance.js.map +1 -1
  40. package/dist/commands/index.d.ts +1 -0
  41. package/dist/commands/index.d.ts.map +1 -1
  42. package/dist/commands/index.js +1 -0
  43. package/dist/commands/index.js.map +1 -1
  44. package/dist/commands/init.d.ts.map +1 -1
  45. package/dist/commands/init.js +12 -2
  46. package/dist/commands/init.js.map +1 -1
  47. package/dist/commands/integrations.d.ts.map +1 -1
  48. package/dist/commands/integrations.js +4 -2
  49. package/dist/commands/integrations.js.map +1 -1
  50. package/dist/commands/jobs.d.ts.map +1 -1
  51. package/dist/commands/jobs.js +61 -23
  52. package/dist/commands/jobs.js.map +1 -1
  53. package/dist/commands/log-tip.d.ts +79 -0
  54. package/dist/commands/log-tip.d.ts.map +1 -0
  55. package/dist/commands/log-tip.js +91 -0
  56. package/dist/commands/log-tip.js.map +1 -0
  57. package/dist/commands/logs.d.ts.map +1 -1
  58. package/dist/commands/logs.js +97 -136
  59. package/dist/commands/logs.js.map +1 -1
  60. package/dist/commands/marketplace.d.ts.map +1 -1
  61. package/dist/commands/marketplace.js +14 -25
  62. package/dist/commands/marketplace.js.map +1 -1
  63. package/dist/commands/mcp.d.ts.map +1 -1
  64. package/dist/commands/mcp.js +17 -19
  65. package/dist/commands/mcp.js.map +1 -1
  66. package/dist/commands/models.d.ts.map +1 -1
  67. package/dist/commands/models.js +2 -1
  68. package/dist/commands/models.js.map +1 -1
  69. package/dist/commands/persona.d.ts.map +1 -1
  70. package/dist/commands/persona.js +4 -30
  71. package/dist/commands/persona.js.map +1 -1
  72. package/dist/commands/postprocessors.d.ts.map +1 -1
  73. package/dist/commands/postprocessors.js +43 -17
  74. package/dist/commands/postprocessors.js.map +1 -1
  75. package/dist/commands/preprocessors.d.ts.map +1 -1
  76. package/dist/commands/preprocessors.js +43 -17
  77. package/dist/commands/preprocessors.js.map +1 -1
  78. package/dist/commands/production.d.ts.map +1 -1
  79. package/dist/commands/production.js +2 -12
  80. package/dist/commands/production.js.map +1 -1
  81. package/dist/commands/push-helpers.d.ts +42 -0
  82. package/dist/commands/push-helpers.d.ts.map +1 -0
  83. package/dist/commands/push-helpers.js +48 -0
  84. package/dist/commands/push-helpers.js.map +1 -0
  85. package/dist/commands/push.d.ts +2 -0
  86. package/dist/commands/push.d.ts.map +1 -1
  87. package/dist/commands/push.js +269 -54
  88. package/dist/commands/push.js.map +1 -1
  89. package/dist/commands/pushBackup.d.ts.map +1 -1
  90. package/dist/commands/pushBackup.js +7 -1
  91. package/dist/commands/pushBackup.js.map +1 -1
  92. package/dist/commands/resources.d.ts.map +1 -1
  93. package/dist/commands/resources.js +2 -12
  94. package/dist/commands/resources.js.map +1 -1
  95. package/dist/commands/skills.d.ts.map +1 -1
  96. package/dist/commands/skills.js +51 -36
  97. package/dist/commands/skills.js.map +1 -1
  98. package/dist/commands/status.d.ts +14 -0
  99. package/dist/commands/status.d.ts.map +1 -0
  100. package/dist/commands/status.js +734 -0
  101. package/dist/commands/status.js.map +1 -0
  102. package/dist/commands/sync.d.ts.map +1 -1
  103. package/dist/commands/sync.js +37 -2
  104. package/dist/commands/sync.js.map +1 -1
  105. package/dist/commands/telemetry.d.ts.map +1 -1
  106. package/dist/commands/telemetry.js +4 -0
  107. package/dist/commands/telemetry.js.map +1 -1
  108. package/dist/commands/test-output.helpers.d.ts +24 -0
  109. package/dist/commands/test-output.helpers.d.ts.map +1 -0
  110. package/dist/commands/test-output.helpers.js +62 -0
  111. package/dist/commands/test-output.helpers.js.map +1 -0
  112. package/dist/commands/test.d.ts.map +1 -1
  113. package/dist/commands/test.js +236 -76
  114. package/dist/commands/test.js.map +1 -1
  115. package/dist/commands/webhooks.d.ts.map +1 -1
  116. package/dist/commands/webhooks.js +34 -21
  117. package/dist/commands/webhooks.js.map +1 -1
  118. package/dist/compiler/agent-traverser.d.ts +50 -14
  119. package/dist/compiler/agent-traverser.d.ts.map +1 -1
  120. package/dist/compiler/agent-traverser.js +191 -86
  121. package/dist/compiler/agent-traverser.js.map +1 -1
  122. package/dist/compiler/compiler.d.ts +32 -0
  123. package/dist/compiler/compiler.d.ts.map +1 -1
  124. package/dist/compiler/compiler.js +143 -18
  125. package/dist/compiler/compiler.js.map +1 -1
  126. package/dist/compiler/index.d.ts +1 -1
  127. package/dist/compiler/index.d.ts.map +1 -1
  128. package/dist/compiler/index.js +1 -1
  129. package/dist/compiler/index.js.map +1 -1
  130. package/dist/compiler/plugins/base.d.ts +21 -0
  131. package/dist/compiler/plugins/base.d.ts.map +1 -1
  132. package/dist/compiler/plugins/base.js +10 -0
  133. package/dist/compiler/plugins/base.js.map +1 -1
  134. package/dist/compiler/plugins/skill.plugin.d.ts +35 -9
  135. package/dist/compiler/plugins/skill.plugin.d.ts.map +1 -1
  136. package/dist/compiler/plugins/skill.plugin.js +131 -84
  137. package/dist/compiler/plugins/skill.plugin.js.map +1 -1
  138. package/dist/compiler/types.d.ts +33 -0
  139. package/dist/compiler/types.d.ts.map +1 -1
  140. package/dist/compiler/types.js.map +1 -1
  141. package/dist/compiler/utils/ast-helpers.d.ts +1 -16
  142. package/dist/compiler/utils/ast-helpers.d.ts.map +1 -1
  143. package/dist/compiler/utils/ast-helpers.js +2 -31
  144. package/dist/compiler/utils/ast-helpers.js.map +1 -1
  145. package/dist/compiler/utils/common.d.ts +14 -0
  146. package/dist/compiler/utils/common.d.ts.map +1 -1
  147. package/dist/compiler/utils/common.js +38 -0
  148. package/dist/compiler/utils/common.js.map +1 -1
  149. package/dist/compiler/utils/path-resolver.d.ts +67 -10
  150. package/dist/compiler/utils/path-resolver.d.ts.map +1 -1
  151. package/dist/compiler/utils/path-resolver.js +120 -24
  152. package/dist/compiler/utils/path-resolver.js.map +1 -1
  153. package/dist/compiler/utils/reference-resolver.d.ts +196 -0
  154. package/dist/compiler/utils/reference-resolver.d.ts.map +1 -0
  155. package/dist/compiler/utils/reference-resolver.js +1030 -0
  156. package/dist/compiler/utils/reference-resolver.js.map +1 -0
  157. package/dist/compiler/utils/schema-converter.d.ts +25 -0
  158. package/dist/compiler/utils/schema-converter.d.ts.map +1 -1
  159. package/dist/compiler/utils/schema-converter.js +83 -4
  160. package/dist/compiler/utils/schema-converter.js.map +1 -1
  161. package/dist/compiler/utils/workspace.d.ts +35 -0
  162. package/dist/compiler/utils/workspace.d.ts.map +1 -0
  163. package/dist/compiler/utils/workspace.js +121 -0
  164. package/dist/compiler/utils/workspace.js.map +1 -0
  165. package/dist/compiler/utils/zod-runtime.mjs +5334 -0
  166. package/dist/index.js +1 -0
  167. package/dist/index.js.map +1 -1
  168. package/dist/interfaces/backup.d.ts +19 -1
  169. package/dist/interfaces/backup.d.ts.map +1 -1
  170. package/dist/interfaces/chat.d.ts +2 -2
  171. package/dist/interfaces/chat.d.ts.map +1 -1
  172. package/dist/interfaces/logs.d.ts +7 -4
  173. package/dist/interfaces/logs.d.ts.map +1 -1
  174. package/dist/primitives/base.handler.d.ts +10 -0
  175. package/dist/primitives/base.handler.d.ts.map +1 -1
  176. package/dist/primitives/base.handler.js +73 -44
  177. package/dist/primitives/base.handler.js.map +1 -1
  178. package/dist/primitives/job.handler.d.ts +5 -0
  179. package/dist/primitives/job.handler.d.ts.map +1 -1
  180. package/dist/primitives/job.handler.js +9 -0
  181. package/dist/primitives/job.handler.js.map +1 -1
  182. package/dist/primitives/webhook.handler.d.ts +2 -1
  183. package/dist/primitives/webhook.handler.d.ts.map +1 -1
  184. package/dist/primitives/webhook.handler.js +7 -1
  185. package/dist/primitives/webhook.handler.js.map +1 -1
  186. package/dist/services/auth.d.ts +8 -0
  187. package/dist/services/auth.d.ts.map +1 -1
  188. package/dist/services/auth.js +19 -0
  189. package/dist/services/auth.js.map +1 -1
  190. package/dist/services/sandbox.service.d.ts.map +1 -1
  191. package/dist/services/sandbox.service.js +6 -2
  192. package/dist/services/sandbox.service.js.map +1 -1
  193. package/dist/utils/aliases.d.ts +7 -0
  194. package/dist/utils/aliases.d.ts.map +1 -0
  195. package/dist/utils/aliases.js +457 -0
  196. package/dist/utils/aliases.js.map +1 -0
  197. package/dist/utils/backup-helpers.d.ts +24 -0
  198. package/dist/utils/backup-helpers.d.ts.map +1 -1
  199. package/dist/utils/backup-helpers.js +94 -8
  200. package/dist/utils/backup-helpers.js.map +1 -1
  201. package/dist/utils/chat-attachments.d.ts +15 -0
  202. package/dist/utils/chat-attachments.d.ts.map +1 -0
  203. package/dist/utils/chat-attachments.js +116 -0
  204. package/dist/utils/chat-attachments.js.map +1 -0
  205. package/dist/utils/cli.d.ts +24 -6
  206. package/dist/utils/cli.d.ts.map +1 -1
  207. package/dist/utils/cli.js +23 -9
  208. package/dist/utils/cli.js.map +1 -1
  209. package/dist/utils/hints.d.ts +81 -0
  210. package/dist/utils/hints.d.ts.map +1 -0
  211. package/dist/utils/hints.js +83 -0
  212. package/dist/utils/hints.js.map +1 -0
  213. package/dist/utils/suggest.d.ts +3 -0
  214. package/dist/utils/suggest.d.ts.map +1 -0
  215. package/dist/utils/suggest.js +34 -0
  216. package/dist/utils/suggest.js.map +1 -0
  217. package/dist/utils/write-info.d.ts +9 -0
  218. package/dist/utils/write-info.d.ts.map +1 -0
  219. package/dist/utils/write-info.js +11 -0
  220. package/dist/utils/write-info.js.map +1 -0
  221. package/docs/README.md +1 -1
  222. package/node_modules/@lua/shared-types/dist/index.d.mts +64 -2
  223. package/node_modules/@lua/shared-types/dist/index.d.ts +64 -2
  224. package/node_modules/@lua/shared-types/dist/index.js +27 -0
  225. package/node_modules/@lua/shared-types/dist/index.mjs +24 -0
  226. package/node_modules/@lua/shared-types/src/channel.type.ts +1 -0
  227. package/node_modules/@lua/shared-types/src/client-tools.types.ts +47 -0
  228. package/node_modules/@lua/shared-types/src/index.ts +2 -0
  229. package/node_modules/@lua/shared-types/src/vm-execution-log.types.ts +41 -0
  230. package/package.json +10 -6
  231. package/scripts/build-vendor.mjs +53 -0
  232. package/scripts/vendor-entry.mjs +11 -0
  233. package/template/examples/skills/tools/CustomDataTool.ts +1 -5
  234. package/template/examples/skills/tools/PremiumFeatureTool.ts +18 -18
  235. package/template/package.json +1 -1
@@ -4,10 +4,11 @@
4
4
  */
5
5
  import { compileCommand } from './compile.js';
6
6
  import { readYamlConfig, } from '../utils/files.js';
7
- import { withErrorHandling, writeProgress, writeSuccess, writeInfo, clearPromptLines } from '../utils/cli.js';
7
+ import { withErrorHandling, writeProgress, writeSuccess, writeInfo, clearPromptLines, writeNextStep, writeHintBlock, writeTip } from '../utils/cli.js';
8
8
  import { requireAuthOrExit } from '../utils/command-utils.js';
9
9
  import { safePrompt } from '../utils/prompt-handler.js';
10
10
  import { incrementPatchVersion, maxSemver } from '../utils/semver.js';
11
+ import { AuthenticationError } from '../errors/auth.error.js';
11
12
  import { BASE_URLS } from '../config/constants.js';
12
13
  import PersonaApi from '../api/persona.api.service.js';
13
14
  import { loadManifest, getPrimitivesByKind } from '../utils/artifact-loader.js';
@@ -15,7 +16,30 @@ import { PrimitiveKind } from '../compiler/types.js';
15
16
  import { agentHandler } from '../primitives/agent.handler.js';
16
17
  import { skillHandler as skillH, webhookHandler as webhookH, jobHandler as jobH, preprocessorHandler as preprocessorH, postprocessorHandler as postprocessorH, deviceHandler as deviceH, deviceTriggerHandler as deviceTriggerH, } from '../primitives/index.js';
17
18
  import { pushBackupCommand } from './pushBackup.js';
19
+ import { buildLogsCommand } from './log-tip.js';
18
20
  import { trackEvent } from '../services/analytics.js';
21
+ import { validateOrSuggest } from '../utils/aliases.js';
22
+ export { pickPushAllNextStepVariant, formatPushFailureSummary } from './push-helpers.js';
23
+ import { pickPushAllNextStepVariant, formatPushFailureSummary } from './push-helpers.js';
24
+ /**
25
+ * Maps push target type to a valid `lua deploy …` follow-up (or null when
26
+ * there is no deploy CLI surface for that type — e.g. mcp, device, backup).
27
+ */
28
+ function getDeployHint(type) {
29
+ const deployableMap = {
30
+ skill: 'lua deploy skill',
31
+ webhook: 'lua deploy webhook',
32
+ job: 'lua deploy job',
33
+ preprocessor: 'lua deploy preprocessor',
34
+ postprocessor: 'lua deploy postprocessor',
35
+ agent: 'lua deploy persona',
36
+ persona: 'lua deploy persona',
37
+ };
38
+ const cmd = deployableMap[type];
39
+ if (!cmd)
40
+ return null;
41
+ return { label: 'Deploy:', command: cmd };
42
+ }
19
43
  // ============================================================================
20
44
  // Core Push Helpers (shared by all push functions)
21
45
  // ============================================================================
@@ -128,8 +152,6 @@ async function resolveVersionOrFail(currentVersion, options, highestKnownVersion
128
152
  // Otherwise, prompt interactively
129
153
  return await promptVersionConfirmOrUpdate(currentVersion);
130
154
  }
131
- /**
132
-
133
155
  /**
134
156
  * Determines if we should deploy after push based on options or prompt
135
157
  */
@@ -206,16 +228,29 @@ async function pushVersionedPrimitive(handler, options = {}) {
206
228
  writeProgress(`\nšŸš€ Pushing ${selected.name} v${confirmedVersion} to server...`);
207
229
  const result = await handler.pushToServer(apiKey, agentId, entityId, { ...pushData, version: confirmedVersion });
208
230
  if (!result.success) {
231
+ const isVersionConflict = result.error?.toLowerCase().includes('already exists');
232
+ if (isVersionConflict) {
233
+ writeHintBlock({
234
+ headline: 'Version conflict — this version already exists on the server.',
235
+ lines: [
236
+ { label: 'Auto-bump:', command: `lua push ${handler.kind} --force` },
237
+ { label: 'Or push all:', command: 'lua push all --force' },
238
+ ],
239
+ when: 'error',
240
+ });
241
+ }
242
+ // Push rejected — the reason is already on screen in the error above.
243
+ // No lua logs hint here: the push never ran, so no execution logs exist.
209
244
  throw new Error(`Push Error: ${result.error || 'Unknown error'}`);
210
245
  }
211
246
  writeSuccess(`\nāœ… Successfully pushed ${selected.name} v${confirmedVersion}\n`);
212
247
  // Step 8: Deploy if requested
213
248
  if (await shouldDeployAfterPush(options)) {
214
- await genericDeployAfterPush(handler, apiKey, agentId, entityId, selected.name, confirmedVersion, options.autoDeploy || false);
215
- }
216
- else {
217
- writeInfo(`šŸ’” You can deploy later using: lua ${handler.displayNamePlural} production`);
249
+ const deployedOk = await genericDeployAfterPush(handler, apiKey, agentId, entityId, selected.name, confirmedVersion, options.autoDeploy || false);
250
+ return { productionDeploySucceeded: deployedOk };
218
251
  }
252
+ return { productionDeploySucceeded: false };
253
+ // Staging vs deployed hints run in pushCommand — avoid duplicates here (H8).
219
254
  }
220
255
  catch (error) {
221
256
  throw error;
@@ -237,21 +272,33 @@ async function genericDeployAfterPush(handler, apiKey, agentId, entityId, entity
237
272
  }]);
238
273
  if (!confirmAnswer || !confirmAnswer.confirm) {
239
274
  console.log("\nāŒ Deployment cancelled. Version pushed but not deployed.\n");
240
- return;
275
+ return false;
241
276
  }
242
277
  }
243
278
  writeProgress(`šŸ”„ Publishing ${handler.displayName} version...`);
244
- const result = await handler.publishVersion(apiKey, agentId, entityId, version);
245
- if (!result.success) {
246
- console.error(`\nāŒ Deploy Error: ${result.error || 'Unknown error'}\n`);
247
- return;
279
+ writeInfo('ā±ļø Waiting for server to process the new version (3 seconds)...');
280
+ await new Promise(resolve => setTimeout(resolve, 3000));
281
+ const deployed = await retryDeploy(async () => {
282
+ const result = await handler.publishVersion(apiKey, agentId, entityId, version);
283
+ if (!result.success)
284
+ throw new Error(result.error || 'Deploy failed');
285
+ }, entityName, version, 3);
286
+ if (!deployed) {
287
+ console.error(`\nāŒ Deploy Error: failed after retries\n`);
288
+ // Deploy is a management operation — no execution logs exist for a failed deploy.
289
+ // Suggest retrying via the deploy command.
290
+ writeTip(`Deploy later with: lua deploy ${handler.kind}`);
291
+ return false;
248
292
  }
249
293
  writeSuccess(`\nāœ… ${entityName} v${version} deployed to production\n`);
250
294
  writeInfo(`šŸ’” The new ${handler.displayName} version is now active.`);
295
+ return true;
251
296
  }
252
297
  catch (error) {
253
298
  console.error(`\nāŒ Error deploying ${handler.displayName}:`, error);
254
- console.log(`šŸ’” You can deploy later using: lua ${handler.displayNamePlural} production\n`);
299
+ // Deploy is a management operation — no execution logs exist for a failed deploy.
300
+ writeTip(`Deploy later with: lua deploy ${handler.kind}`);
301
+ return false;
255
302
  }
256
303
  }
257
304
  /**
@@ -274,7 +321,15 @@ export async function pushCommand(type, cmdObj) {
274
321
  entityName: cmdObj?.name || null,
275
322
  version: cmdObj?.setVersion || null
276
323
  };
324
+ let agentOutcome;
277
325
  let selectedType;
326
+ /** Present only after a versioned-primitive route; indicates production publish success after optional deploy. */
327
+ let versionedPushDeployResult;
328
+ // Normalize alias first (e.g. 'everything' → 'all', 'skills' → 'skill')
329
+ // so that the early 'all' guard below can catch aliases like 'everything'
330
+ if (type) {
331
+ type = validateOrSuggest('push.type', type, { allowAll: true });
332
+ }
278
333
  // Handle 'all' type with force flag
279
334
  if (type === 'all') {
280
335
  if (!options.force) {
@@ -292,27 +347,7 @@ export async function pushCommand(type, cmdObj) {
292
347
  console.log(' lua push webhook --name myWebhook --set-version 2.0.0 Push specific webhook');
293
348
  throw new Error('Type must be specified when using the --name option.');
294
349
  }
295
- // Step 1: Check if type was provided as argument
296
350
  if (type) {
297
- // Validate the provided type
298
- const validTypes = ['skill', 'agent', 'persona', 'webhook', 'job', 'preprocessor', 'postprocessor', 'mcp', 'device', 'device-trigger', 'backup'];
299
- if (!validTypes.includes(type)) {
300
- console.log('\nUsage:');
301
- console.log(' lua push - Interactive selection');
302
- console.log(' lua push skill - Push a skill directly');
303
- console.log(' lua push agent - Push agent config (persona, model)');
304
- console.log(' lua push webhook - Push a webhook directly');
305
- console.log(' lua push job - Push a job directly');
306
- console.log(' lua push preprocessor - Push a preprocessor directly');
307
- console.log(' lua push postprocessor - Push a postprocessor directly');
308
- console.log(' lua push mcp - Push an MCP server directly');
309
- console.log(' lua push backup - Push project source backup');
310
- console.log(' lua push all --force - Push all components without prompts');
311
- throw new Error(`Invalid type: "${type}". Must be one of: ${validTypes.join(', ')}, or "all".`);
312
- }
313
- // 'persona' is an alias for 'agent' (backward compatibility)
314
- if (type === 'persona')
315
- type = 'agent';
316
351
  selectedType = type;
317
352
  }
318
353
  else {
@@ -344,34 +379,39 @@ export async function pushCommand(type, cmdObj) {
344
379
  }
345
380
  // Step 3: Route to appropriate function
346
381
  if (selectedType === 'skill') {
347
- await pushVersionedPrimitive(skillH, options);
382
+ versionedPushDeployResult = await pushVersionedPrimitive(skillH, options);
348
383
  }
349
384
  else if (selectedType === 'webhook') {
350
- await pushVersionedPrimitive(webhookH, options);
385
+ versionedPushDeployResult = await pushVersionedPrimitive(webhookH, options);
351
386
  }
352
387
  else if (selectedType === 'job') {
353
- await pushVersionedPrimitive(jobH, options);
388
+ versionedPushDeployResult = await pushVersionedPrimitive(jobH, options);
354
389
  }
355
390
  else if (selectedType === 'preprocessor') {
356
- await pushVersionedPrimitive(preprocessorH, options);
391
+ versionedPushDeployResult = await pushVersionedPrimitive(preprocessorH, options);
357
392
  }
358
393
  else if (selectedType === 'postprocessor') {
359
- await pushVersionedPrimitive(postprocessorH, options);
394
+ versionedPushDeployResult = await pushVersionedPrimitive(postprocessorH, options);
360
395
  }
361
396
  else if (selectedType === 'device') {
362
- await pushVersionedPrimitive(deviceH, options);
397
+ versionedPushDeployResult = await pushVersionedPrimitive(deviceH, options);
363
398
  }
364
399
  else if (selectedType === 'device-trigger') {
365
- await pushVersionedPrimitive(deviceTriggerH, options);
400
+ versionedPushDeployResult = await pushVersionedPrimitive(deviceTriggerH, options);
366
401
  }
367
402
  else if (selectedType === 'mcp') {
368
- await pushMCPServer(options);
403
+ const mcpActivated = await pushMCPServer(options);
404
+ // B10: thread activation status so the final hint knows whether MCP is live.
405
+ versionedPushDeployResult = { productionDeploySucceeded: mcpActivated };
369
406
  }
370
407
  else if (selectedType === 'backup') {
371
408
  await pushBackupCommand({ force: options.force });
372
409
  }
373
410
  else if (selectedType === 'agent') {
374
- await pushAgentVersion(options);
411
+ agentOutcome = await pushAgentVersion(options);
412
+ }
413
+ if (agentOutcome?.cancelled) {
414
+ return;
375
415
  }
376
416
  trackEvent('cli_push_completed', {
377
417
  primitive_type: selectedType,
@@ -381,6 +421,74 @@ export async function pushCommand(type, cmdObj) {
381
421
  type_selected_by_arg: !!type,
382
422
  version_specified: !!options.version,
383
423
  });
424
+ const productionDeployedActually = versionedPushDeployResult?.productionDeploySucceeded === true ||
425
+ (!!agentOutcome &&
426
+ !agentOutcome.cancelled &&
427
+ agentOutcome.productionDeployedWithAutoDeploy);
428
+ const personaAutoDeployRanAndFailed = selectedType === 'agent' &&
429
+ options.autoDeploy &&
430
+ !!agentOutcome &&
431
+ !agentOutcome.cancelled &&
432
+ 'personaAutoDeployFailed' in agentOutcome &&
433
+ agentOutcome.personaAutoDeployFailed;
434
+ if (productionDeployedActually) {
435
+ writeHintBlock({
436
+ headline: 'Deployed to production. Generate test traffic first:',
437
+ lines: [
438
+ { label: 'Test:', command: `lua chat -e production -m "your test message"` },
439
+ { label: 'Inspect:', command: buildLogsCommand({ primitiveType: selectedType }) },
440
+ ],
441
+ when: 'success',
442
+ });
443
+ }
444
+ else {
445
+ const deployHint = getDeployHint(selectedType);
446
+ if (personaAutoDeployRanAndFailed) {
447
+ const lines = [];
448
+ if (deployHint) {
449
+ lines.push(deployHint);
450
+ }
451
+ else if (selectedType === 'mcp') {
452
+ lines.push({
453
+ label: 'Activate:',
454
+ command: 'use the Lua dashboard or: lua push mcp --force --auto-deploy (requires --name when multiple MCP servers)',
455
+ });
456
+ }
457
+ lines.push({
458
+ label: 'Or re-push:',
459
+ command: selectedType === 'mcp'
460
+ ? 'lua push mcp --force --auto-deploy'
461
+ : `lua push ${selectedType} --force --auto-deploy`,
462
+ });
463
+ writeHintBlock({
464
+ headline: 'Push completed — production persona deploy did not succeed. Try:',
465
+ lines,
466
+ when: 'partial',
467
+ });
468
+ }
469
+ else if (selectedType === 'backup') {
470
+ // Backup is not a "live" primitive; skip staged-vs-live framing.
471
+ }
472
+ else if (deployHint) {
473
+ writeHintBlock({
474
+ headline: 'Staged but NOT live yet. To make it active:',
475
+ lines: [
476
+ deployHint,
477
+ { label: 'Or re-push:', command: `lua push ${selectedType} --force --auto-deploy` },
478
+ ],
479
+ when: 'success',
480
+ });
481
+ }
482
+ else {
483
+ writeNextStep({
484
+ command: selectedType === 'mcp'
485
+ ? 'lua push mcp --force --auto-deploy'
486
+ : `lua push ${selectedType} --force --auto-deploy`,
487
+ rationale: 'to re-push with auto-activation',
488
+ when: 'success',
489
+ });
490
+ }
491
+ }
384
492
  }, "push");
385
493
  }
386
494
  /**
@@ -433,7 +541,7 @@ async function pushAgentVersion(options = {}) {
433
541
  ]);
434
542
  if (!confirmAnswer || !confirmAnswer.confirm) {
435
543
  console.log("\nāŒ Push cancelled.\n");
436
- return;
544
+ return { cancelled: true };
437
545
  }
438
546
  }
439
547
  // Authenticate
@@ -441,15 +549,23 @@ async function pushAgentVersion(options = {}) {
441
549
  writeProgress("āœ… Authenticated");
442
550
  // Push via agentHandler
443
551
  const result = await agentHandler.pushAgentConfig(apiKey, agentId, manifest);
444
- // Deploy persona if requested and was pushed
445
- if (result.persona?.success && result.persona.version) {
446
- if (await shouldDeployAfterPush(options)) {
447
- await deployPersonaVersionAfterPush(apiKey, agentId, result.persona.version, options.autoDeploy || false);
552
+ let productionDeployedWithAutoDeploy = false;
553
+ let personaDeployWasAttempted = false;
554
+ const personaDeployEligible = !!(result.persona?.success && result.persona.version);
555
+ // B4: only ask about deploy when a persona was actually pushed — avoid the prompt
556
+ // when push failed or was a model-only push with no persona version created.
557
+ if (personaDeployEligible) {
558
+ const shouldDeploy = await shouldDeployAfterPush(options);
559
+ if (shouldDeploy) {
560
+ personaDeployWasAttempted = true;
561
+ productionDeployedWithAutoDeploy = await deployPersonaVersionAfterPush(apiKey, agentId, result.persona.version, options.autoDeploy || false);
448
562
  }
449
563
  else {
450
564
  writeInfo("šŸ’” You can deploy the persona version later using: lua deploy");
451
565
  }
452
566
  }
567
+ const personaAutoDeployFailed = Boolean(options.autoDeploy && personaDeployEligible && personaDeployWasAttempted && !productionDeployedWithAutoDeploy);
568
+ return { cancelled: false, productionDeployedWithAutoDeploy, personaAutoDeployFailed };
453
569
  }
454
570
  /**
455
571
  * Deploy a persona version immediately after pushing
@@ -471,7 +587,7 @@ async function deployPersonaVersionAfterPush(apiKey, agentId, versionNum, skipCo
471
587
  ]);
472
588
  if (!confirmAnswer || !confirmAnswer.confirm) {
473
589
  console.log("\nāŒ Deployment cancelled. Persona version created but not deployed.\n");
474
- return;
590
+ return false;
475
591
  }
476
592
  }
477
593
  writeProgress("šŸ”„ Deploying persona version...");
@@ -479,14 +595,18 @@ async function deployPersonaVersionAfterPush(apiKey, agentId, versionNum, skipCo
479
595
  const deployResult = await personaApi.deployVersion(versionNum);
480
596
  if (!deployResult.success) {
481
597
  console.error(`\nāŒ Deploy Error: ${deployResult.error?.message || 'Unknown error'}\n`);
598
+ // Persona deploy is a management operation — no execution logs exist.
599
+ writeTip('Retry with: lua push agent');
482
600
  throw new Error(deployResult.error?.message || 'Failed to deploy persona version');
483
601
  }
484
602
  writeSuccess(`\nāœ… Persona version ${versionNum} deployed successfully to production\n`);
485
603
  writeInfo("šŸ’” The new persona is now active for all users.");
604
+ return true;
486
605
  }
487
606
  catch (error) {
488
607
  console.error('\nāŒ Error deploying persona version:', error);
489
- console.log('šŸ’” You can deploy later using: lua persona\n');
608
+ writeTip('Retry with: lua push agent');
609
+ return false;
490
610
  }
491
611
  }
492
612
  /**
@@ -520,19 +640,25 @@ async function pushMCPServer(options = {}) {
520
640
  // upsertOnServer persists the returned id into lua.skill.yaml on success.
521
641
  const result = await mcpServerHandler.upsertOnServer(apiKey, agentId, selectedServer);
522
642
  if (!result.success) {
643
+ // Push rejected — reason already on screen; no execution logs exist for a failed push.
523
644
  throw new Error(`Failed: ${result.error}`);
524
645
  }
525
646
  writeSuccess(`\nāœ… MCP server "${selectedServer.name}" pushed successfully\n`);
647
+ let activated = false;
526
648
  if (result.id && await shouldDeployAfterPush(options)) {
527
649
  writeProgress("šŸ”„ Activating MCP server...");
528
650
  const activateResult = await mcpServerHandler.activate(apiKey, agentId, result.id);
529
- if (activateResult.success)
651
+ if (activateResult.success) {
530
652
  writeSuccess(`āœ… MCP server activated\n`);
653
+ activated = true;
654
+ }
531
655
  }
656
+ return activated;
532
657
  }
533
658
  catch (error) {
534
659
  throw error;
535
660
  }
661
+ return false; // unreachable — catch always rethrows
536
662
  }
537
663
  /**
538
664
  * Push all command - Pushes all components (skills, webhooks, jobs, processors) without prompts
@@ -572,6 +698,11 @@ async function pushAllCommand(options) {
572
698
  // Track results and deploy queue per handler
573
699
  const allResults = [];
574
700
  const toDeploy = [];
701
+ // Per-item failures collected across all push surfaces (versioned
702
+ // primitives + MCP). Drives the post-run aggregate `āš ļø N component(s)
703
+ // failed` block and the final partial/error writeNextStep variant.
704
+ const failedItems = [];
705
+ let deployFailedCount = 0;
575
706
  let personaPushResult = null;
576
707
  let backupSuccess = false;
577
708
  // Icons per kind for display
@@ -624,12 +755,29 @@ async function pushAllCommand(options) {
624
755
  // Auto-bump version (use pre-fetched server version to avoid conflicts)
625
756
  const serverHighest = handlerVersions?.get(entityId) ?? null;
626
757
  const baseVersion = serverHighest ? maxSemver(item.version, serverHighest) : item.version;
627
- const newVersion = incrementPatchVersion(baseVersion);
758
+ let newVersion = incrementPatchVersion(baseVersion);
628
759
  writeInfo(` šŸ“ ${item.name}: ${item.version} → ${newVersion}`);
629
760
  // Push
630
- const result = await handler.pushToServer(apiKey, agentId, entityId, { ...pushData, version: newVersion });
761
+ let result = await handler.pushToServer(apiKey, agentId, entityId, { ...pushData, version: newVersion });
762
+ // On version collision, re-fetch the server's current highest version
763
+ // and try once more. The pre-fetch in step 4 is racey against
764
+ // concurrent pushes by the same/another user; a single re-bump
765
+ // resolves the dominant collision pattern observed in production.
766
+ if (!result.success && result.error?.toLowerCase().includes('already exists')) {
767
+ console.log(` āš ļø Version collision on ${item.name}, refetching server state and retrying...`);
768
+ const freshHighest = await handler.getHighestServerVersion(apiKey, agentId, entityId);
769
+ if (freshHighest) {
770
+ const retryVersion = incrementPatchVersion(freshHighest);
771
+ writeInfo(` šŸ“ ${item.name}: re-bumped ${newVersion} → ${retryVersion} after collision`);
772
+ result = await handler.pushToServer(apiKey, agentId, entityId, { ...pushData, version: retryVersion });
773
+ if (result.success) {
774
+ newVersion = retryVersion;
775
+ }
776
+ }
777
+ }
631
778
  if (!result.success) {
632
779
  console.error(` āŒ Failed to push ${item.name}: ${result.error}`);
780
+ failedItems.push({ kind: handler.kind, name: item.name, error: result.error || 'Unknown error' });
633
781
  continue;
634
782
  }
635
783
  handler.updateVersionInYaml(item.name, newVersion, { silent: true });
@@ -640,7 +788,14 @@ async function pushAllCommand(options) {
640
788
  }
641
789
  }
642
790
  catch (error) {
791
+ // Auth errors must propagate so withErrorHandling treats them as
792
+ // fatal, otherwise the loop continues against a known-broken auth
793
+ // state. Matches the re-throw pattern in batchGetHighestVersions /
794
+ // getHighestServerVersion.
795
+ if (AuthenticationError.isAuthenticationError(error))
796
+ throw error;
643
797
  console.error(` āŒ Failed to push ${item.name}: ${error.message}`);
798
+ failedItems.push({ kind: handler.kind, name: item.name, error: error.message || 'Unknown error' });
644
799
  }
645
800
  }
646
801
  }
@@ -650,9 +805,11 @@ async function pushAllCommand(options) {
650
805
  // when --auto-deploy is set. Here we only print the summary.
651
806
  const { mcpServerHandler: mcpH } = await import('../primitives/mcp-server.handler.js');
652
807
  const bundledMcp = mcpH.loadBundledItems();
808
+ let mcpPushedCount = 0; // tracks actual successes, not just attempts (B2)
653
809
  if (bundledMcp.length > 0) {
654
810
  writeProgress(`\nšŸ”Œ Pushing ${bundledMcp.length} MCP server(s)...`);
655
811
  const mcpResult = await mcpH.pushAll(bundledMcp, apiKey, agentId, { autoDeploy: options.autoDeploy });
812
+ mcpPushedCount = mcpResult.pushed.length;
656
813
  for (const name of mcpResult.pushed) {
657
814
  writeSuccess(` āœ… ${name}`);
658
815
  if (mcpResult.activated.includes(name))
@@ -660,8 +817,17 @@ async function pushAllCommand(options) {
660
817
  }
661
818
  for (const { name, error } of mcpResult.failed) {
662
819
  console.error(` āŒ Failed to push ${name}: ${error}`);
820
+ failedItems.push({ kind: 'mcp', name, error: error || 'Unknown error' });
663
821
  }
664
822
  }
823
+ // Aggregate failure block: emit a single grouped summary with a per-item
824
+ // `lua logs` diagnose hint so users can jump straight to the failing
825
+ // component's logs without scrolling back through interleaved push output.
826
+ // Printed before agent config push so the user sees component failures
827
+ // alongside the persona/backup status that follows.
828
+ if (failedItems.length > 0) {
829
+ console.error(formatPushFailureSummary(failedItems));
830
+ }
665
831
  // Step 6.5: Push agent config (persona, model/modelResolver)
666
832
  const agentPushResult = await agentHandler.pushAgentConfig(apiKey, agentId, manifest);
667
833
  if (agentPushResult.persona?.success) {
@@ -691,6 +857,7 @@ async function pushAllCommand(options) {
691
857
  }
692
858
  else {
693
859
  console.warn(` āš ļø ${item.name} deployment failed`);
860
+ deployFailedCount++;
694
861
  }
695
862
  }
696
863
  }
@@ -707,6 +874,7 @@ async function pushAllCommand(options) {
707
874
  }
708
875
  else {
709
876
  console.warn(` āš ļø Persona deployment failed`);
877
+ deployFailedCount++;
710
878
  }
711
879
  }
712
880
  // Step 7.5: Push source backup (independent storage concern)
@@ -758,11 +926,58 @@ async function pushAllCommand(options) {
758
926
  auto_deploy: options.autoDeploy || false,
759
927
  primitives_pushed_count: allResults.length,
760
928
  primitives_by_kind: kindCounts,
761
- mcp_servers_pushed: bundledMcp.length,
929
+ mcp_servers_pushed: mcpPushedCount,
762
930
  persona_pushed: !!personaPushResult,
763
931
  backup_pushed: backupSuccess,
764
932
  });
765
- console.log('');
933
+ // B2: use actual successful MCP pushes, not attempt count, to determine pushedSomething.
934
+ const pushedSomething = allResults.length > 0 || mcpPushedCount > 0 || !!personaPushResult || backupSuccess;
935
+ // Pick the right hint variant based on the run outcome. We deliberately
936
+ // ungate the tip from `pushedSomething` for the all-failed case so a
937
+ // 100%-failed `lua push all --force` still surfaces a `lua logs` nudge
938
+ // (previously it was silent, leaving users to guess what to do next).
939
+ const variant = pickPushAllNextStepVariant({
940
+ pushedSomething,
941
+ failedCount: failedItems.length + deployFailedCount,
942
+ });
943
+ if (variant === 'success') {
944
+ console.log('');
945
+ if (options.autoDeploy) {
946
+ writeHintBlock({
947
+ headline: 'All deployed. Generate test traffic first, then inspect:',
948
+ lines: [
949
+ { label: 'Test:', command: 'lua chat -e production -m "your test message"' },
950
+ { label: 'Inspect:', command: buildLogsCommand({ limit: 10 }) },
951
+ ],
952
+ when: 'success',
953
+ });
954
+ }
955
+ else {
956
+ writeHintBlock({
957
+ headline: 'Code staged but NOT live. Make it active:',
958
+ lines: [
959
+ { label: 'Deploy all:', command: 'lua deploy all --force' },
960
+ { label: 'Or re-push:', command: 'lua push all --force --auto-deploy' },
961
+ ],
962
+ when: 'success',
963
+ });
964
+ }
965
+ }
966
+ else if (variant === 'partial') {
967
+ console.log('');
968
+ // Some components pushed, some failed. Suggest re-pushing the failures.
969
+ // No lua logs hint: failed pushes produce no execution logs.
970
+ writeNextStep({
971
+ command: 'lua push all --force',
972
+ rationale: 'to re-attempt the failed components',
973
+ when: 'partial',
974
+ });
975
+ }
976
+ else if (variant === 'error') {
977
+ console.log('');
978
+ // Total failure — nothing pushed, no execution logs exist.
979
+ // No hint: the errors are already shown above.
980
+ }
766
981
  }
767
982
  /**
768
983
  * Retry deployment with exponential backoff