lua-cli 3.1.0 → 3.2.0-alpha.2
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/README.md +2 -5
- package/dist/api/marketplace.api.service.d.ts +4 -2
- package/dist/api/marketplace.api.service.js +6 -0
- package/dist/api/persona.api.service.d.ts +54 -0
- package/dist/api/persona.api.service.js +89 -0
- package/dist/api-exports.d.ts +19 -0
- package/dist/api-exports.js +21 -0
- package/dist/cli/command-definitions.js +29 -1
- package/dist/commands/chat.js +2 -3
- package/dist/commands/chatClear.d.ts +5 -1
- package/dist/commands/chatClear.js +19 -8
- package/dist/commands/compile.d.ts +4 -1
- package/dist/commands/compile.js +27 -4
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.js +1 -0
- package/dist/commands/init.js +4 -4
- package/dist/commands/marketplace.js +87 -42
- package/dist/commands/persona.js +7 -49
- package/dist/commands/push.js +3 -2
- package/dist/commands/sync.d.ts +29 -0
- package/dist/commands/sync.js +194 -0
- package/dist/commands/test.js +3 -5
- package/dist/interfaces/index.d.ts +2 -0
- package/dist/interfaces/lua.d.ts +26 -0
- package/dist/interfaces/lua.js +5 -0
- package/dist/interfaces/marketplace.d.ts +20 -0
- package/dist/interfaces/persona.d.ts +42 -0
- package/dist/interfaces/persona.js +5 -0
- package/dist/interfaces/user.d.ts +21 -0
- package/dist/types/compile.types.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/skill.d.ts +1 -3
- package/dist/types/skill.js +3 -32
- package/dist/utils/agent-code-utils.d.ts +24 -0
- package/dist/utils/agent-code-utils.js +96 -0
- package/dist/utils/compile.js +11 -11
- package/dist/utils/deployment.js +4 -8
- package/dist/utils/dev-server.js +5 -4
- package/dist/utils/files.d.ts +1 -3
- package/dist/utils/files.js +1 -39
- package/dist/utils/init-helpers.d.ts +0 -8
- package/dist/utils/init-helpers.js +4 -37
- package/dist/utils/job-management.js +1 -2
- package/dist/utils/sandbox.d.ts +4 -3
- package/dist/utils/sandbox.js +5 -9
- package/dist/utils/sync-helpers.d.ts +61 -0
- package/dist/utils/sync-helpers.js +190 -0
- package/dist/utils/test-helpers.d.ts +0 -7
- package/dist/utils/test-helpers.js +0 -9
- package/package.json +3 -1
- package/template/README.md +1 -1
- package/template/lua.skill.yaml +10 -0
- package/template/package.json +1 -1
- package/dist/utils/agent-management.d.ts +0 -23
- package/dist/utils/agent-management.js +0 -67
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Helpers
|
|
3
|
+
* Utilities for detecting drift between server state and local code
|
|
4
|
+
*/
|
|
5
|
+
import { diffLines } from 'diff';
|
|
6
|
+
import { BASE_URLS } from '../config/constants.js';
|
|
7
|
+
import { loadPersonaFromCode, loadNameFromCode } from './agent-code-utils.js';
|
|
8
|
+
import PersonaApi from '../api/persona.api.service.js';
|
|
9
|
+
import AgentApi from '../api/agent.api.service.js';
|
|
10
|
+
// ANSI color codes
|
|
11
|
+
const colors = {
|
|
12
|
+
red: '\x1b[31m',
|
|
13
|
+
green: '\x1b[32m',
|
|
14
|
+
gray: '\x1b[90m',
|
|
15
|
+
reset: '\x1b[0m',
|
|
16
|
+
bold: '\x1b[1m',
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Fetch the latest published persona version from the server.
|
|
20
|
+
* Returns null if no persona is published or on error.
|
|
21
|
+
*
|
|
22
|
+
* Note: This returns the most recently published version, NOT the current/active one.
|
|
23
|
+
* The current version might be an older rollback, but code should match the latest push.
|
|
24
|
+
* Drafts are excluded since they haven't been deployed yet.
|
|
25
|
+
*/
|
|
26
|
+
export async function fetchServerPersona(apiKey, agentId) {
|
|
27
|
+
try {
|
|
28
|
+
const personaApi = new PersonaApi(BASE_URLS.API, apiKey, agentId);
|
|
29
|
+
const latestPublished = await personaApi.getLatestPublishedVersion();
|
|
30
|
+
if (latestPublished && latestPublished.persona) {
|
|
31
|
+
return {
|
|
32
|
+
persona: latestPublished.persona,
|
|
33
|
+
version: latestPublished.version,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// Silently fail - network issues shouldn't block compilation
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Compare server persona with local persona.
|
|
45
|
+
* Returns true if they differ (drift detected).
|
|
46
|
+
*/
|
|
47
|
+
export function comparePersona(serverPersona, localPersona) {
|
|
48
|
+
if (serverPersona === null) {
|
|
49
|
+
return false; // No server state to compare against
|
|
50
|
+
}
|
|
51
|
+
// Normalize whitespace for comparison
|
|
52
|
+
const normalizedServer = serverPersona.trim();
|
|
53
|
+
const normalizedLocal = localPersona.trim();
|
|
54
|
+
return normalizedServer !== normalizedLocal;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check for persona drift between server and local code.
|
|
58
|
+
* Returns drift info if drift detected, null otherwise.
|
|
59
|
+
*/
|
|
60
|
+
export async function checkPersonaDrift(apiKey, agentId) {
|
|
61
|
+
const localPersona = loadPersonaFromCode();
|
|
62
|
+
const serverData = await fetchServerPersona(apiKey, agentId);
|
|
63
|
+
const hasDrift = comparePersona(serverData?.persona || null, localPersona);
|
|
64
|
+
if (!hasDrift) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
hasDrift: true,
|
|
69
|
+
serverPersona: serverData?.persona || null,
|
|
70
|
+
localPersona,
|
|
71
|
+
serverVersion: serverData?.version,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Display a colored diff between two strings.
|
|
76
|
+
*/
|
|
77
|
+
export function showColoredDiff(oldText, newText, oldLabel = 'Server', newLabel = 'Local') {
|
|
78
|
+
if (!oldText && !newText) {
|
|
79
|
+
console.log(colors.gray + '(both empty)' + colors.reset);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (!oldText) {
|
|
83
|
+
console.log(colors.green + `+ (${newLabel} only - no ${oldLabel} content)` + colors.reset);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (!newText) {
|
|
87
|
+
console.log(colors.red + `- (${oldLabel} only - no ${newLabel} content)` + colors.reset);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const diff = diffLines(oldText, newText);
|
|
91
|
+
diff.forEach(part => {
|
|
92
|
+
if (part.added) {
|
|
93
|
+
// Added in local (green)
|
|
94
|
+
const lines = part.value.split('\n').filter(l => l);
|
|
95
|
+
lines.forEach(line => {
|
|
96
|
+
console.log(colors.green + '+ ' + line + colors.reset);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
else if (part.removed) {
|
|
100
|
+
// Removed from server (red)
|
|
101
|
+
const lines = part.value.split('\n').filter(l => l);
|
|
102
|
+
lines.forEach(line => {
|
|
103
|
+
console.log(colors.red + '- ' + line + colors.reset);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Unchanged - show abbreviated context
|
|
108
|
+
const lines = part.value.split('\n').filter(l => l);
|
|
109
|
+
if (lines.length <= 6) {
|
|
110
|
+
lines.forEach(line => {
|
|
111
|
+
console.log(colors.gray + ' ' + line + colors.reset);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// Show first 3 and last 3 lines
|
|
116
|
+
lines.slice(0, 3).forEach(line => {
|
|
117
|
+
console.log(colors.gray + ' ' + line + colors.reset);
|
|
118
|
+
});
|
|
119
|
+
console.log(colors.gray + ` ... (${lines.length - 6} unchanged lines) ...` + colors.reset);
|
|
120
|
+
lines.slice(-3).forEach(line => {
|
|
121
|
+
console.log(colors.gray + ' ' + line + colors.reset);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Display a diff between server and local persona.
|
|
129
|
+
*/
|
|
130
|
+
export function showPersonaDiff(serverPersona, localPersona) {
|
|
131
|
+
console.log('\n' + '='.repeat(60));
|
|
132
|
+
console.log(colors.bold + 'PERSONA DIFF' + colors.reset);
|
|
133
|
+
console.log(colors.red + '- Server (deployed)' + colors.reset + ' ' + colors.green + '+ Local (code)' + colors.reset);
|
|
134
|
+
console.log('='.repeat(60) + '\n');
|
|
135
|
+
showColoredDiff(serverPersona || '', localPersona, 'Server', 'Local');
|
|
136
|
+
console.log('\n' + '='.repeat(60) + '\n');
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Display a compact drift warning for compile flow.
|
|
140
|
+
*/
|
|
141
|
+
export function showDriftWarning(drift) {
|
|
142
|
+
console.log('\n⚠️ Persona drift detected!');
|
|
143
|
+
console.log(` Server version ${drift.serverVersion || 'unknown'} differs from local code.`);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Fetch the agent name from the server.
|
|
147
|
+
*/
|
|
148
|
+
export async function fetchServerName(apiKey, agentId) {
|
|
149
|
+
try {
|
|
150
|
+
const agentApi = new AgentApi(BASE_URLS.API, apiKey);
|
|
151
|
+
const response = await agentApi.getAgent(agentId);
|
|
152
|
+
if (response.success && response.data?.name) {
|
|
153
|
+
return response.data.name;
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check for name drift between server and local code.
|
|
163
|
+
*/
|
|
164
|
+
export async function checkNameDrift(apiKey, agentId) {
|
|
165
|
+
const localName = loadNameFromCode();
|
|
166
|
+
const serverName = await fetchServerName(apiKey, agentId);
|
|
167
|
+
if (serverName === null) {
|
|
168
|
+
return null; // No server state to compare against
|
|
169
|
+
}
|
|
170
|
+
const hasDrift = serverName.trim() !== localName.trim();
|
|
171
|
+
if (!hasDrift) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
hasDrift: true,
|
|
176
|
+
serverName,
|
|
177
|
+
localName,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Display name drift info.
|
|
182
|
+
*/
|
|
183
|
+
export function showNameDiff(serverName, localName) {
|
|
184
|
+
console.log('\n' + '='.repeat(60));
|
|
185
|
+
console.log(colors.bold + 'NAME DIFF' + colors.reset);
|
|
186
|
+
console.log('='.repeat(60));
|
|
187
|
+
console.log(colors.red + `- Server: "${serverName || '(none)'}"` + colors.reset);
|
|
188
|
+
console.log(colors.green + `+ Local: "${localName || '(none)'}"` + colors.reset);
|
|
189
|
+
console.log('='.repeat(60) + '\n');
|
|
190
|
+
}
|
|
@@ -31,10 +31,3 @@ export declare function extractToolsFromDeployData(deployData: any): ToolData[];
|
|
|
31
31
|
* @returns True if .env file exists
|
|
32
32
|
*/
|
|
33
33
|
export declare function hasEnvFile(): boolean;
|
|
34
|
-
/**
|
|
35
|
-
* Checks if config has environment variables defined.
|
|
36
|
-
*
|
|
37
|
-
* @param config - Skill configuration
|
|
38
|
-
* @returns True if config has environment variables
|
|
39
|
-
*/
|
|
40
|
-
export declare function hasConfigEnvVars(config: any): boolean;
|
|
@@ -81,12 +81,3 @@ export function extractToolsFromDeployData(deployData) {
|
|
|
81
81
|
export function hasEnvFile() {
|
|
82
82
|
return fs.existsSync(path.join(process.cwd(), '.env'));
|
|
83
83
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Checks if config has environment variables defined.
|
|
86
|
-
*
|
|
87
|
-
* @param config - Skill configuration
|
|
88
|
-
* @returns True if config has environment variables
|
|
89
|
-
*/
|
|
90
|
-
export function hasConfigEnvVars(config) {
|
|
91
|
-
return config?.skill?.env && Object.keys(config.skill.env).length > 0;
|
|
92
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lua-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0-alpha.2",
|
|
4
4
|
"description": "Build, test, and deploy AI agents with custom tools, webhooks, and scheduled jobs. Features LuaAgent unified configuration, streaming chat, and batch deployment.",
|
|
5
5
|
"readmeFilename": "README.md",
|
|
6
6
|
"main": "dist/api-exports.js",
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"autoprefixer": "^10.4.21",
|
|
68
68
|
"chalk": "^5.3.0",
|
|
69
69
|
"commander": "^14.0.1",
|
|
70
|
+
"diff": "^8.0.2",
|
|
70
71
|
"dotenv": "^17.2.3",
|
|
71
72
|
"esbuild": "^0.25.10",
|
|
72
73
|
"inquirer": "^12.9.6",
|
|
@@ -84,6 +85,7 @@
|
|
|
84
85
|
"zod-to-json-schema": "^3.24.6"
|
|
85
86
|
},
|
|
86
87
|
"devDependencies": {
|
|
88
|
+
"@types/diff": "^7.0.2",
|
|
87
89
|
"@types/inquirer": "^9.0.9",
|
|
88
90
|
"@types/jest": "^29.5.8",
|
|
89
91
|
"@types/js-yaml": "^4.0.9",
|
package/template/README.md
CHANGED
|
@@ -21,7 +21,7 @@ lua push all --force --auto-deploy
|
|
|
21
21
|
your-project/
|
|
22
22
|
├── src/
|
|
23
23
|
│ └── index.ts # Your agent configuration
|
|
24
|
-
├── lua.skill.yaml #
|
|
24
|
+
├── lua.skill.yaml # State manifest (IDs + versions only; auto-managed)
|
|
25
25
|
├── package.json # Dependencies
|
|
26
26
|
└── tsconfig.json # TypeScript config
|
|
27
27
|
```
|
package/template/lua.skill.yaml
CHANGED
package/template/package.json
CHANGED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Management Utilities
|
|
3
|
-
* Handles LuaAgent persona synchronization with lua.skill.yaml
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Syncs the agent's name and persona with lua.skill.yaml.
|
|
7
|
-
* This ensures the YAML configuration reflects the agent definition in code.
|
|
8
|
-
*
|
|
9
|
-
* @param agentMetadata - Agent metadata extracted from LuaAgent
|
|
10
|
-
*/
|
|
11
|
-
export declare function syncAgentPersonaWithYaml(agentMetadata: {
|
|
12
|
-
name: string;
|
|
13
|
-
persona: string;
|
|
14
|
-
}): Promise<void>;
|
|
15
|
-
/**
|
|
16
|
-
* Reads the agent persona from lua.skill.yaml.
|
|
17
|
-
* This can be used to ensure the code and YAML are in sync.
|
|
18
|
-
*
|
|
19
|
-
* @returns Agent persona from YAML, or null if not found
|
|
20
|
-
*/
|
|
21
|
-
export declare function readAgentPersonaFromYaml(): {
|
|
22
|
-
persona?: string;
|
|
23
|
-
} | null;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Management Utilities
|
|
3
|
-
* Handles LuaAgent persona synchronization with lua.skill.yaml
|
|
4
|
-
*/
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import path from "path";
|
|
7
|
-
import yaml from "js-yaml";
|
|
8
|
-
import { COMPILE_FILES, YAML_FORMAT } from '../config/compile.constants.js';
|
|
9
|
-
/**
|
|
10
|
-
* Syncs the agent's name and persona with lua.skill.yaml.
|
|
11
|
-
* This ensures the YAML configuration reflects the agent definition in code.
|
|
12
|
-
*
|
|
13
|
-
* @param agentMetadata - Agent metadata extracted from LuaAgent
|
|
14
|
-
*/
|
|
15
|
-
export async function syncAgentPersonaWithYaml(agentMetadata) {
|
|
16
|
-
const yamlPath = path.join(process.cwd(), COMPILE_FILES.LUA_SKILL_YAML);
|
|
17
|
-
// Read existing YAML config
|
|
18
|
-
let config = {};
|
|
19
|
-
if (fs.existsSync(yamlPath)) {
|
|
20
|
-
const yamlContent = fs.readFileSync(yamlPath, 'utf8');
|
|
21
|
-
config = yaml.load(yamlContent);
|
|
22
|
-
}
|
|
23
|
-
// Update agent section with persona
|
|
24
|
-
config.agent = {
|
|
25
|
-
...config.agent,
|
|
26
|
-
persona: agentMetadata.persona
|
|
27
|
-
};
|
|
28
|
-
// Store agent name as a comment or in metadata (YAML doesn't have an agentName field)
|
|
29
|
-
// The agent name is primarily for the LuaAgent in code
|
|
30
|
-
// Write updated YAML with consistent formatting
|
|
31
|
-
const yamlContent = yaml.dump(config, {
|
|
32
|
-
indent: YAML_FORMAT.INDENT,
|
|
33
|
-
lineWidth: YAML_FORMAT.LINE_WIDTH,
|
|
34
|
-
noRefs: YAML_FORMAT.NO_REFS,
|
|
35
|
-
replacer: (key, value) => {
|
|
36
|
-
// Replace undefined values with empty strings
|
|
37
|
-
return value === undefined ? '' : value;
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
fs.writeFileSync(yamlPath, yamlContent);
|
|
41
|
-
console.log(`✅ Synced agent configuration to lua.skill.yaml`);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Reads the agent persona from lua.skill.yaml.
|
|
45
|
-
* This can be used to ensure the code and YAML are in sync.
|
|
46
|
-
*
|
|
47
|
-
* @returns Agent persona from YAML, or null if not found
|
|
48
|
-
*/
|
|
49
|
-
export function readAgentPersonaFromYaml() {
|
|
50
|
-
const yamlPath = path.join(process.cwd(), COMPILE_FILES.LUA_SKILL_YAML);
|
|
51
|
-
if (!fs.existsSync(yamlPath)) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
const yamlContent = fs.readFileSync(yamlPath, 'utf8');
|
|
56
|
-
const config = yaml.load(yamlContent);
|
|
57
|
-
if (config.agent) {
|
|
58
|
-
return {
|
|
59
|
-
persona: config.agent.persona
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
console.warn(`Warning: Could not read agent persona from lua.skill.yaml: ${error}`);
|
|
65
|
-
}
|
|
66
|
-
return null;
|
|
67
|
-
}
|