lua-cli 3.1.0 → 3.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +2 -5
  2. package/dist/api/marketplace.api.service.d.ts +4 -2
  3. package/dist/api/marketplace.api.service.js +6 -0
  4. package/dist/api/persona.api.service.d.ts +54 -0
  5. package/dist/api/persona.api.service.js +89 -0
  6. package/dist/api-exports.d.ts +19 -0
  7. package/dist/api-exports.js +21 -0
  8. package/dist/cli/command-definitions.js +29 -1
  9. package/dist/commands/chat.js +2 -3
  10. package/dist/commands/chatClear.d.ts +5 -1
  11. package/dist/commands/chatClear.js +19 -8
  12. package/dist/commands/compile.d.ts +4 -1
  13. package/dist/commands/compile.js +27 -4
  14. package/dist/commands/index.d.ts +1 -0
  15. package/dist/commands/index.js +1 -0
  16. package/dist/commands/init.js +4 -4
  17. package/dist/commands/marketplace.js +87 -42
  18. package/dist/commands/persona.js +7 -49
  19. package/dist/commands/push.js +3 -2
  20. package/dist/commands/sync.d.ts +29 -0
  21. package/dist/commands/sync.js +194 -0
  22. package/dist/commands/test.js +3 -5
  23. package/dist/interfaces/index.d.ts +2 -0
  24. package/dist/interfaces/lua.d.ts +26 -0
  25. package/dist/interfaces/lua.js +5 -0
  26. package/dist/interfaces/marketplace.d.ts +20 -0
  27. package/dist/interfaces/persona.d.ts +42 -0
  28. package/dist/interfaces/persona.js +5 -0
  29. package/dist/interfaces/user.d.ts +21 -0
  30. package/dist/types/index.d.ts +1 -0
  31. package/dist/types/skill.d.ts +1 -3
  32. package/dist/types/skill.js +3 -32
  33. package/dist/utils/agent-code-utils.d.ts +24 -0
  34. package/dist/utils/agent-code-utils.js +96 -0
  35. package/dist/utils/compile.js +8 -8
  36. package/dist/utils/dev-server.js +5 -4
  37. package/dist/utils/files.d.ts +1 -3
  38. package/dist/utils/files.js +1 -39
  39. package/dist/utils/init-helpers.d.ts +0 -8
  40. package/dist/utils/init-helpers.js +4 -37
  41. package/dist/utils/job-management.js +1 -2
  42. package/dist/utils/sandbox.d.ts +4 -3
  43. package/dist/utils/sandbox.js +5 -9
  44. package/dist/utils/sync-helpers.d.ts +61 -0
  45. package/dist/utils/sync-helpers.js +190 -0
  46. package/dist/utils/test-helpers.d.ts +0 -7
  47. package/dist/utils/test-helpers.js +0 -9
  48. package/package.json +3 -1
  49. package/template/README.md +1 -1
  50. package/template/lua.skill.yaml +10 -0
  51. package/template/package.json +1 -1
  52. package/dist/utils/agent-management.d.ts +0 -23
  53. package/dist/utils/agent-management.js +0 -67
package/README.md CHANGED
@@ -559,8 +559,6 @@ Central configuration file:
559
559
  agent:
560
560
  agentId: your-agent-id
561
561
  orgId: your-org-id
562
- persona: |
563
- You are a helpful AI assistant...
564
562
 
565
563
  skills:
566
564
  - name: general-skill
@@ -576,11 +574,10 @@ jobs:
576
574
  - name: daily-cleanup
577
575
  version: 1.0.0
578
576
  jobId: job-id-789
579
- schedule:
580
- type: cron
581
- pattern: "0 0 * * *"
582
577
  ```
583
578
 
579
+ State-only: YAML tracks names, IDs, and server versions. Persona, env vars, and schedules live in code (for sandbox) or on the server (for production).
580
+
584
581
  ### Environment Variables
585
582
 
586
583
  ```.env
@@ -1,4 +1,4 @@
1
- import { MarketplaceSkillWithVersionsResponse, MarketplaceVersionResponse, SkillResponse, UnpublishVersionResponse, UnlistSkillResponse } from "../interfaces/marketplace.js";
1
+ import { MarketplaceSkillWithVersionsResponse, MarketplaceVersionResponse, SkillResponse, UnpublishVersionResponse, UnlistSkillResponse, PaginatedMarketplaceSkillsResponse } from "../interfaces/marketplace.js";
2
2
  export declare class MarketplaceApiService {
3
3
  private apiKey;
4
4
  private baseUrl;
@@ -15,7 +15,9 @@ export declare class MarketplaceApiService {
15
15
  name?: string;
16
16
  creatorId?: string;
17
17
  publishedVersionsOnly?: boolean;
18
- }): Promise<MarketplaceSkillWithVersionsResponse[]>;
18
+ page?: number;
19
+ limit?: number;
20
+ }): Promise<PaginatedMarketplaceSkillsResponse>;
19
21
  getSkillById(marketplaceSkillId: string): Promise<MarketplaceSkillWithVersionsResponse>;
20
22
  getSkillVersions(marketplaceSkillId: string): Promise<MarketplaceVersionResponse[]>;
21
23
  installSkill(marketplaceSkillId: string, agentId: string, data: any): Promise<SkillResponse>;
@@ -74,6 +74,12 @@ export class MarketplaceApiService {
74
74
  if (filters?.publishedVersionsOnly !== undefined) {
75
75
  params.append("publishedVersionsOnly", String(filters.publishedVersionsOnly));
76
76
  }
77
+ if (filters?.page !== undefined) {
78
+ params.append("page", String(filters.page));
79
+ }
80
+ if (filters?.limit !== undefined) {
81
+ params.append("limit", String(filters.limit));
82
+ }
77
83
  return this._fetch(`/marketplace/skills?${params.toString()}`);
78
84
  }
79
85
  async getSkillById(marketplaceSkillId) {
@@ -0,0 +1,54 @@
1
+ import { HttpClient } from "../common/http.client.js";
2
+ import { ApiResponse } from "../interfaces/common.js";
3
+ import { PersonaVersion, PersonaVersionsResponse, CreatePersonaVersionResponse, SetPersonaVersionResponse } from "../interfaces/persona.js";
4
+ /**
5
+ * Persona API Service
6
+ * Handles all persona-related API calls
7
+ */
8
+ export default class PersonaApi extends HttpClient {
9
+ apiKey: string;
10
+ agentId: string;
11
+ /**
12
+ * Creates an instance of PersonaApi
13
+ * @param baseUrl - The base URL for the API
14
+ * @param apiKey - The API key for authentication
15
+ * @param agentId - The unique identifier of the agent
16
+ */
17
+ constructor(baseUrl: string, apiKey: string, agentId: string);
18
+ /**
19
+ * Retrieves all persona versions for the agent
20
+ * @param status - Filter by status: 'draft', 'published', or 'all' (default)
21
+ * @returns Promise resolving to an ApiResponse containing persona versions response
22
+ */
23
+ getVersions(status?: 'draft' | 'published' | 'all'): Promise<ApiResponse<PersonaVersionsResponse>>;
24
+ /**
25
+ * Creates a new persona version
26
+ * @param persona - The persona content
27
+ * @returns Promise resolving to an ApiResponse with the created version
28
+ */
29
+ createVersion(persona: string): Promise<ApiResponse<CreatePersonaVersionResponse>>;
30
+ /**
31
+ * Deploys/activates a persona version to production
32
+ * @param version - The version number to deploy
33
+ * @returns Promise resolving to an ApiResponse with confirmation
34
+ */
35
+ deployVersion(version: number): Promise<ApiResponse<SetPersonaVersionResponse>>;
36
+ /**
37
+ * Gets the latest persona version (sorted by createdDate, includes drafts)
38
+ * @returns Promise resolving to the latest PersonaVersion or null if none exist
39
+ */
40
+ getLatestVersion(): Promise<PersonaVersion | null>;
41
+ /**
42
+ * Gets the latest published persona version (excludes drafts)
43
+ * This is the most recently pushed version, regardless of whether it's currently active.
44
+ * Use this for sync - code should match the latest push, not a rollback.
45
+ * @returns Promise resolving to the latest published PersonaVersion or null if none exist
46
+ */
47
+ getLatestPublishedVersion(): Promise<PersonaVersion | null>;
48
+ /**
49
+ * Gets the currently deployed/active persona version
50
+ * Note: This might be an older rollback version, not the latest push.
51
+ * @returns Promise resolving to the current PersonaVersion or null if none deployed
52
+ */
53
+ getCurrentVersion(): Promise<PersonaVersion | null>;
54
+ }
@@ -0,0 +1,89 @@
1
+ import { HttpClient } from "../common/http.client.js";
2
+ /**
3
+ * Persona API Service
4
+ * Handles all persona-related API calls
5
+ */
6
+ export default class PersonaApi extends HttpClient {
7
+ /**
8
+ * Creates an instance of PersonaApi
9
+ * @param baseUrl - The base URL for the API
10
+ * @param apiKey - The API key for authentication
11
+ * @param agentId - The unique identifier of the agent
12
+ */
13
+ constructor(baseUrl, apiKey, agentId) {
14
+ super(baseUrl);
15
+ this.apiKey = apiKey;
16
+ this.agentId = agentId;
17
+ }
18
+ /**
19
+ * Retrieves all persona versions for the agent
20
+ * @param status - Filter by status: 'draft', 'published', or 'all' (default)
21
+ * @returns Promise resolving to an ApiResponse containing persona versions response
22
+ */
23
+ async getVersions(status = 'all') {
24
+ const statusParam = status !== 'all' ? `?status=${status}` : '';
25
+ return this.httpGet(`/developer/agents/${this.agentId}/persona/versions${statusParam}`, {
26
+ Authorization: `Bearer ${this.apiKey}`,
27
+ });
28
+ }
29
+ /**
30
+ * Creates a new persona version
31
+ * @param persona - The persona content
32
+ * @returns Promise resolving to an ApiResponse with the created version
33
+ */
34
+ async createVersion(persona) {
35
+ return this.httpPost(`/developer/agents/${this.agentId}/persona/version`, { persona }, {
36
+ Authorization: `Bearer ${this.apiKey}`,
37
+ });
38
+ }
39
+ /**
40
+ * Deploys/activates a persona version to production
41
+ * @param version - The version number to deploy
42
+ * @returns Promise resolving to an ApiResponse with confirmation
43
+ */
44
+ async deployVersion(version) {
45
+ return this.httpPost(`/developer/agents/${this.agentId}/persona/version/${version}`, {}, {
46
+ Authorization: `Bearer ${this.apiKey}`,
47
+ });
48
+ }
49
+ /**
50
+ * Gets the latest persona version (sorted by createdDate, includes drafts)
51
+ * @returns Promise resolving to the latest PersonaVersion or null if none exist
52
+ */
53
+ async getLatestVersion() {
54
+ const response = await this.getVersions();
55
+ if (!response.success || !response.data?.versions || response.data.versions.length === 0) {
56
+ return null;
57
+ }
58
+ // Sort by createdDate descending to get the latest
59
+ const sorted = response.data.versions.sort((a, b) => b.createdDate - a.createdDate);
60
+ return sorted[0];
61
+ }
62
+ /**
63
+ * Gets the latest published persona version (excludes drafts)
64
+ * This is the most recently pushed version, regardless of whether it's currently active.
65
+ * Use this for sync - code should match the latest push, not a rollback.
66
+ * @returns Promise resolving to the latest published PersonaVersion or null if none exist
67
+ */
68
+ async getLatestPublishedVersion() {
69
+ const response = await this.getVersions('published');
70
+ if (!response.success || !response.data?.versions || response.data.versions.length === 0) {
71
+ return null;
72
+ }
73
+ // Sort by createdDate descending to get the latest published
74
+ const sorted = response.data.versions.sort((a, b) => b.createdDate - a.createdDate);
75
+ return sorted[0];
76
+ }
77
+ /**
78
+ * Gets the currently deployed/active persona version
79
+ * Note: This might be an older rollback version, not the latest push.
80
+ * @returns Promise resolving to the current PersonaVersion or null if none deployed
81
+ */
82
+ async getCurrentVersion() {
83
+ const response = await this.getVersions();
84
+ if (!response.success || !response.data?.versions || response.data.versions.length === 0) {
85
+ return null;
86
+ }
87
+ return response.data.versions.find(v => v.isCurrent) || null;
88
+ }
89
+ }
@@ -547,7 +547,26 @@ export declare const CDN: {
547
547
  */
548
548
  get(fileId: string): Promise<File>;
549
549
  };
550
+ import { LuaRuntime } from "./interfaces/lua.js";
551
+ /**
552
+ * Lua Runtime API
553
+ * Access request-level runtime information in your tools, conditions, and processors.
554
+ *
555
+ * @example
556
+ * ```typescript
557
+ * import { Lua } from 'lua-cli';
558
+ *
559
+ * // Access the current channel
560
+ * const channel = Lua.request.channel;
561
+ *
562
+ * if (channel === 'whatsapp') {
563
+ * // WhatsApp-specific logic
564
+ * }
565
+ * ```
566
+ */
567
+ export declare const Lua: LuaRuntime;
550
568
  export { LuaSkill, LuaTool, LuaWebhook, LuaWebhookConfig, LuaJob, LuaJobConfig, JobSchedule, PreProcessor, PreProcessorConfig, PreProcessorAction, PreProcessorResult, PreProcessorBlockResponse, PreProcessorProceedResponse, PostProcessor, PostProcessorConfig, PostProcessorResponse, LuaAgent, LuaAgentConfig, LuaMCPServer, LuaMCPServerConfig, MCPStdioServerConfig, MCPSSEServerConfig, MCPTransport, MCPServerBaseConfig, BasketStatus, OrderStatus, env };
551
569
  export { JobInstance, UserDataInstance, DataEntryInstance, ProductInstance, BasketInstance, OrderInstance };
552
570
  export { ChatHistoryMessage, ChatHistoryContent, ChatMessage, TextMessage, ImageMessage, FileMessage, PreProcessorOverride, PostProcessorOverride };
553
571
  export { WhatsAppTemplate, PaginatedTemplatesResponse, ListTemplatesOptions, SendTemplateData, SendTemplateResponse, WhatsAppTemplateCategory, WhatsAppTemplateStatus, WhatsAppTemplateComponent, SendTemplateValues } from "./interfaces/whatsapp-templates.js";
572
+ export { Channel, LuaRuntime, LuaRequest } from "./interfaces/lua.js";
@@ -696,6 +696,27 @@ export const CDN = {
696
696
  return instance.get(fileId);
697
697
  }
698
698
  };
699
+ /**
700
+ * Lua Runtime API
701
+ * Access request-level runtime information in your tools, conditions, and processors.
702
+ *
703
+ * @example
704
+ * ```typescript
705
+ * import { Lua } from 'lua-cli';
706
+ *
707
+ * // Access the current channel
708
+ * const channel = Lua.request.channel;
709
+ *
710
+ * if (channel === 'whatsapp') {
711
+ * // WhatsApp-specific logic
712
+ * }
713
+ * ```
714
+ */
715
+ export const Lua = {
716
+ request: {
717
+ channel: 'unknown',
718
+ },
719
+ };
699
720
  // ============================================================================
700
721
  // EXPORTS
701
722
  // ============================================================================
@@ -2,7 +2,7 @@
2
2
  * Command Definitions
3
3
  * Centralized command structure for the CLI
4
4
  */
5
- import { configureCommand, initCommand, destroyCommand, apiKeyCommand, compileCommand, testCommand, pushCommand, deployCommand, devCommand, chatCommand, chatClearCommand, envCommand, personaCommand, productionCommand, resourcesCommand, adminCommand, evalsCommand, docsCommand, channelsCommand, logsCommand, completionCommand, skillsCommand, webhooksCommand, jobsCommand, featuresCommand, preprocessorsCommand, postprocessorsCommand, marketplaceCommand, mcpCommand } from "../commands/index.js";
5
+ import { configureCommand, initCommand, destroyCommand, apiKeyCommand, compileCommand, testCommand, pushCommand, deployCommand, devCommand, chatCommand, chatClearCommand, envCommand, personaCommand, productionCommand, resourcesCommand, adminCommand, evalsCommand, docsCommand, channelsCommand, logsCommand, completionCommand, skillsCommand, webhooksCommand, jobsCommand, featuresCommand, preprocessorsCommand, postprocessorsCommand, marketplaceCommand, mcpCommand, syncCommand } from "../commands/index.js";
6
6
  /**
7
7
  * Sets up authentication-related commands.
8
8
  *
@@ -77,7 +77,23 @@ export function setupSkillCommands(program) {
77
77
  .command("compile")
78
78
  .description("šŸ“¦ Compile skill to deployable format")
79
79
  .option("--debug", "Enable debug mode with verbose logging and temp file preservation")
80
+ .option("--no-sync", "Skip drift detection check")
81
+ .option("--force-sync", "Auto-accept server state if drift detected")
80
82
  .action(compileCommand);
83
+ program
84
+ .command("sync")
85
+ .description("šŸ”„ Sync local code with server state")
86
+ .addHelpText('after', `
87
+ Detects drift between server-deployed state and local code.
88
+ Allows updating local code from the server to stay in sync.
89
+
90
+ Currently syncs:
91
+ • Persona - Agent persona from LuaAgent definition
92
+
93
+ Examples:
94
+ $ lua sync Check for drift and sync interactively
95
+ `)
96
+ .action(syncCommand);
81
97
  program
82
98
  .command("test [type]")
83
99
  .description("🧪 Test skills, webhooks, or jobs interactively")
@@ -138,6 +154,18 @@ Examples:
138
154
  chatCmd
139
155
  .command("clear")
140
156
  .description("Clear conversation history")
157
+ .option("--user <identifier>", "User ID, email, or mobile number of the user whose history to clear")
158
+ .addHelpText('after', `
159
+ Examples:
160
+ $ lua chat clear Clear history
161
+ $ lua chat clear --user <userId> Clear user's history by user ID
162
+ $ lua chat clear --user <email> Clear user's history by email
163
+ $ lua chat clear --user <mobile> Clear user's history by mobile number
164
+
165
+ Notes:
166
+ - User identifier can be UUID, email address, or mobile number
167
+ - Mobile numbers should be in international format without + (e.g., 919876543210)
168
+ `)
141
169
  .action(chatClearCommand);
142
170
  // Configuration Commands
143
171
  program
@@ -13,6 +13,7 @@ import { getAllSandboxSkillIds, getAllSandboxPreProcessorIds, getAllSandboxPostP
13
13
  import ChatApi from '../api/chat.api.service.js';
14
14
  import { BASE_URLS } from '../config/constants.js';
15
15
  import { readDeployJson, validateConfig, validateDeployData, validateAgentConfig, } from '../utils/dev-helpers.js';
16
+ import { loadPersonaFromCode } from '../utils/agent-code-utils.js';
16
17
  /**
17
18
  * Main chat command - starts interactive chat session
18
19
  *
@@ -110,9 +111,7 @@ async function setupSandboxEnvironment(chatEnv, config) {
110
111
  chatEnv.preprocessorOverrides = await getAllSandboxPreProcessorIds(config);
111
112
  chatEnv.postprocessorOverrides = await getAllSandboxPostProcessorIds(config);
112
113
  // Check for persona in config
113
- if (config.agent?.persona) {
114
- chatEnv.persona = config.agent.persona;
115
- }
114
+ chatEnv.persona = loadPersonaFromCode();
116
115
  }
117
116
  /**
118
117
  * Starts the interactive chat loop
@@ -9,7 +9,11 @@
9
9
  * - Warning message about data loss
10
10
  * - Confirmation prompt
11
11
  * - Calls DELETE endpoint to clear history
12
+ * - Optional: clear user's history by identifier
12
13
  *
14
+ * @param options - Command options including optional user identifier
13
15
  * @returns Promise that resolves when history is cleared
14
16
  */
15
- export declare function chatClearCommand(): Promise<void>;
17
+ export declare function chatClearCommand(options?: {
18
+ user?: string;
19
+ }): Promise<void>;
@@ -15,10 +15,12 @@ import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
15
15
  * - Warning message about data loss
16
16
  * - Confirmation prompt
17
17
  * - Calls DELETE endpoint to clear history
18
+ * - Optional: clear user's history by identifier
18
19
  *
20
+ * @param options - Command options including optional user identifier
19
21
  * @returns Promise that resolves when history is cleared
20
22
  */
21
- export async function chatClearCommand() {
23
+ export async function chatClearCommand(options) {
22
24
  return withErrorHandling(async () => {
23
25
  // Step 1: Load configuration
24
26
  const config = readSkillConfig();
@@ -33,14 +35,19 @@ export async function chatClearCommand() {
33
35
  }
34
36
  await checkApiKey(apiKey);
35
37
  writeProgress("āœ… Authenticated");
36
- // Step 3: Show warning and confirm
37
- console.log("\nāš ļø WARNING: This will clear ALL conversation history!");
38
+ // Step 3: Prepare target user info (if --user flag provided)
39
+ const targetIdentifier = options?.user;
40
+ const userContext = targetIdentifier
41
+ ? `for user ${targetIdentifier}`
42
+ : "";
43
+ // Step 4: Show warning and confirm
44
+ console.log(`\nāš ļø WARNING: This will clear ALL conversation history ${userContext}!`);
38
45
  console.log("āš ļø This action cannot be undone.\n");
39
46
  const confirmAnswer = await safePrompt([
40
47
  {
41
48
  type: 'confirm',
42
49
  name: 'confirm',
43
- message: 'Are you sure you want to clear the conversation history?',
50
+ message: `Are you sure you want to clear the conversation history ${userContext}?`,
44
51
  default: false
45
52
  }
46
53
  ]);
@@ -48,10 +55,14 @@ export async function chatClearCommand() {
48
55
  // console.log("\nāŒ Operation cancelled. History not cleared.\n");
49
56
  return;
50
57
  }
51
- // Step 4: Clear history via API
58
+ // Step 5: Clear history via API
52
59
  writeProgress("šŸ”„ Clearing conversation history...");
53
60
  try {
54
- const response = await fetch(`${BASE_URLS.API}/chat/history/${agentId}`, {
61
+ // Construct URL with optional targetIdentifier query parameter
62
+ const url = targetIdentifier
63
+ ? `${BASE_URLS.API}/chat/history/${agentId}?targetIdentifier=${encodeURIComponent(targetIdentifier)}`
64
+ : `${BASE_URLS.API}/chat/history/${agentId}`;
65
+ const response = await fetch(url, {
55
66
  method: 'DELETE',
56
67
  headers: {
57
68
  'accept': '*/*',
@@ -62,8 +73,8 @@ export async function chatClearCommand() {
62
73
  const errorText = await response.text();
63
74
  throw new Error(`HTTP error! status: ${response.status} - ${errorText}`);
64
75
  }
65
- writeSuccess("āœ… Conversation history cleared successfully");
66
- console.log("šŸ’” The chat history has been completely removed.\n");
76
+ writeSuccess(`āœ… Conversation history cleared successfully ${userContext}`);
77
+ console.log(`šŸ’” The chat history has been completely removed ${userContext}.\n`);
67
78
  }
68
79
  catch (error) {
69
80
  console.error('āŒ Error clearing conversation history:', error);
@@ -27,9 +27,12 @@
27
27
  * - Skills deleted from code are removed from YAML
28
28
  * - Skills not in YAML are deleted from server (or deactivated if they have versions)
29
29
  *
30
- * @param options - Command options including debug flag
30
+ * @param options - Command options including debug, noSync, and forceSync flags
31
31
  * @returns Promise that resolves when compilation is complete
32
32
  */
33
33
  export declare function compileCommand(options?: {
34
34
  debug?: boolean;
35
+ noSync?: boolean;
36
+ forceSync?: boolean;
37
+ sync?: boolean;
35
38
  }): Promise<void>;
@@ -18,7 +18,8 @@ import { ensurePostProcessorsExistInYaml, syncServerPostProcessorsWithYaml } fro
18
18
  import { ensureMCPServersExistInYaml, syncServerMCPServersWithYaml } from '../utils/mcp-server-management.js';
19
19
  import { readSkillConfig } from '../utils/files.js';
20
20
  import { COMPILE_DIRS, COMPILE_FILES } from '../config/compile.constants.js';
21
- import { syncAgentPersonaWithYaml } from '../utils/agent-management.js';
21
+ import { loadApiKey } from '../services/auth.js';
22
+ import { runSyncCheck } from './sync.js';
22
23
  /**
23
24
  * Main compile command - orchestrates the entire skill compilation process.
24
25
  *
@@ -44,18 +45,42 @@ import { syncAgentPersonaWithYaml } from '../utils/agent-management.js';
44
45
  * - Skills deleted from code are removed from YAML
45
46
  * - Skills not in YAML are deleted from server (or deactivated if they have versions)
46
47
  *
47
- * @param options - Command options including debug flag
48
+ * @param options - Command options including debug, noSync, and forceSync flags
48
49
  * @returns Promise that resolves when compilation is complete
49
50
  */
50
51
  export async function compileCommand(options) {
51
52
  return withErrorHandling(async () => {
52
53
  const debugMode = options?.debug || process.env.LUA_DEBUG === 'true';
54
+ // Commander uses --no-sync which sets sync=false, so we check for sync !== false
55
+ const noSync = options?.noSync || options?.sync === false;
56
+ const forceSync = options?.forceSync || false;
53
57
  if (debugMode) {
54
58
  console.log('šŸ› Debug mode enabled');
55
59
  console.log(' - Verbose logging: ON');
56
60
  console.log(' - Temp file preservation: ON');
57
61
  console.log(' - Full error stacks: ON\n');
58
62
  }
63
+ // Step 0: Run sync check (unless --no-sync is set)
64
+ if (!noSync) {
65
+ try {
66
+ const config = readSkillConfig();
67
+ const agentId = config?.agent?.agentId;
68
+ const apiKey = await loadApiKey();
69
+ if (apiKey && agentId) {
70
+ const shouldContinue = await runSyncCheck(apiKey, agentId, { noSync, forceSync });
71
+ if (!shouldContinue) {
72
+ return; // User cancelled due to unresolved drift
73
+ }
74
+ }
75
+ // If no API key or agentId, skip sync silently (sandbox-only development)
76
+ }
77
+ catch (error) {
78
+ // Sync check failed, continue with compilation anyway
79
+ if (debugMode) {
80
+ console.warn('āš ļø Sync check failed, continuing with compilation:', error);
81
+ }
82
+ }
83
+ }
59
84
  writeProgress("šŸ”Ø Compiling Lua skill...");
60
85
  // Track compilation issues
61
86
  const compilationWarnings = [];
@@ -90,8 +115,6 @@ export async function compileCommand(options) {
90
115
  if (agentMetadata) {
91
116
  writeProgress(`✨ Found LuaAgent: ${agentMetadata.name}`);
92
117
  writeProgress(` Using new unified agent configuration approach`);
93
- // Sync persona and welcome message with YAML
94
- await syncAgentPersonaWithYaml(agentMetadata);
95
118
  // Resolve references to get actual metadata for all components
96
119
  resolvedAgentData = resolveLuaAgentReferences(agentMetadata, indexFile, project);
97
120
  // Get file paths where skills are defined so we can scan them for tools
@@ -27,3 +27,4 @@ export { preprocessorsCommand } from "./preprocessors.js";
27
27
  export { postprocessorsCommand } from "./postprocessors.js";
28
28
  export { marketplaceCommand } from "./marketplace.js";
29
29
  export { mcpCommand } from "./mcp.js";
30
+ export { syncCommand } from "./sync.js";
@@ -27,3 +27,4 @@ export { preprocessorsCommand } from "./preprocessors.js";
27
27
  export { postprocessorsCommand } from "./postprocessors.js";
28
28
  export { marketplaceCommand } from "./marketplace.js";
29
29
  export { mcpCommand } from "./mcp.js";
30
+ export { syncCommand } from "./sync.js";
@@ -133,9 +133,9 @@ export async function initCommand(options = {}) {
133
133
  if (yamlExists) {
134
134
  // Update existing YAML and LuaAgent in index.ts
135
135
  writeInfo("šŸ“ Updating existing lua.skill.yaml with new agent...");
136
- updateYamlAgent(selectedAgent.agentId, selectedOrg.id, persona);
136
+ updateYamlAgent(selectedAgent.agentId, selectedOrg.id);
137
137
  // Also update LuaAgent in index.ts if it exists
138
- const { updateLuaAgentInIndexFile } = await import("../utils/init-helpers.js");
138
+ const { updateLuaAgentInIndexFile } = await import("../utils/agent-code-utils.js");
139
139
  updateLuaAgentInIndexFile(process.cwd(), selectedAgent.name, persona);
140
140
  writeSuccess("āœ… lua.skill.yaml updated successfully!");
141
141
  writeSuccess("āœ… LuaAgent configuration updated!");
@@ -299,9 +299,9 @@ async function handleAgentSwitch(userData, apiKey, existingYaml) {
299
299
  const finalPersona = await promptPersonaReplacement(existingYaml, persona);
300
300
  // Update existing YAML file with new agent
301
301
  writeInfo("\nšŸ“ Updating lua.skill.yaml with new agent...");
302
- updateYamlAgent(selectedAgent.agentId, selectedOrg.id, finalPersona);
302
+ updateYamlAgent(selectedAgent.agentId, selectedOrg.id);
303
303
  // Also update LuaAgent in index.ts if it exists
304
- const { updateLuaAgentInIndexFile } = await import("../utils/init-helpers.js");
304
+ const { updateLuaAgentInIndexFile } = await import("../utils/agent-code-utils.js");
305
305
  updateLuaAgentInIndexFile(process.cwd(), selectedAgent.name, finalPersona);
306
306
  writeSuccess("āœ… lua.skill.yaml updated successfully!");
307
307
  writeSuccess("āœ… LuaAgent configuration updated!");