@innominatum/agentforge-cli 1.0.1 → 1.0.6
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/.github/workflows/publish.yml +36 -0
- package/README.md +28 -7
- package/dist/index.js +20 -18
- package/package.json +5 -2
- package/src/index.ts +20 -16
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Publish Package to npmjs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
# Alternatively, you can uncomment the following to publish whenever you push to main
|
|
7
|
+
# push:
|
|
8
|
+
# branches:
|
|
9
|
+
# - main
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build-and-publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
env:
|
|
15
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
id-token: write # Required for NPM Trusted Publishing (OIDC)
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout code
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Setup Node.js
|
|
24
|
+
uses: actions/setup-node@v4
|
|
25
|
+
with:
|
|
26
|
+
node-version: '20.x'
|
|
27
|
+
registry-url: 'https://registry.npmjs.org'
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: npm ci
|
|
31
|
+
|
|
32
|
+
- name: Build TypeScript code
|
|
33
|
+
run: npm run build
|
|
34
|
+
|
|
35
|
+
- name: Publish to NPM
|
|
36
|
+
run: npm publish --access public --provenance
|
package/README.md
CHANGED
|
@@ -8,6 +8,14 @@ A powerful command-line interface to scaffold, manage, build, and deploy AI Agen
|
|
|
8
8
|
|
|
9
9
|
## Installation & Local Development
|
|
10
10
|
|
|
11
|
+
### Global Installation (Recommended)
|
|
12
|
+
You can install the AgentForge CLI globally directly from NPM:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g @innominatum/agentforge-cli
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Local Development
|
|
11
19
|
Since you are modifying or maintaining the CLI source code, you should install and use it globally on your local machine using NPM's symlink feature:
|
|
12
20
|
|
|
13
21
|
1. Clone this repository and navigate to its folder.
|
|
@@ -63,10 +71,23 @@ If you add a new command or change how the CLI works:
|
|
|
63
71
|
|
|
64
72
|
## NPM Publishing (Maintainers)
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
### Manual Publishing
|
|
75
|
+
When this CLI is ready for a new release:
|
|
76
|
+
1. Update the `version` in `package.json` (e.g., from `"1.0.1"` to `"1.0.2"`).
|
|
77
|
+
2. Run `npm run build` to ensure the `dist/` directory is fully updated.
|
|
78
|
+
3. Login to your npm account using `npm login`.
|
|
79
|
+
4. Publish the package using `npm publish --access public` (you will be prompted for your 2FA security key).
|
|
80
|
+
|
|
81
|
+
### Automated Publishing (Trusted Publishing / OIDC)
|
|
82
|
+
To fully automate your CI/CD pipeline securely without using any hardcoded NPM tokens or bypassing 2FA, NPM provides "Trusted Publishing" with GitHub Actions:
|
|
83
|
+
|
|
84
|
+
1. Go to the NPM website and navigate to the `@innominatum/agentforge-cli` package.
|
|
85
|
+
2. Go to **Settings** > **Publishing Access**.
|
|
86
|
+
3. Under **Trusted Publishers**, click **Add Publisher** > **GitHub Actions**.
|
|
87
|
+
4. Fill in the repository details:
|
|
88
|
+
- **GitHub Organization/User:** `Innominatum-pt`
|
|
89
|
+
- **GitHub Repository:** `agentforge-cli`
|
|
90
|
+
- **Workflow file (optional):** `publish.yml`
|
|
91
|
+
5. Click **Add Publisher**.
|
|
92
|
+
|
|
93
|
+
Once configured, the `.github/workflows/publish.yml` workflow provided in this repository will automatically securely authenticate via OIDC and publish your package whenever you create a new GitHub Release.
|
package/dist/index.js
CHANGED
|
@@ -285,6 +285,19 @@ async function getConfig() {
|
|
|
285
285
|
}
|
|
286
286
|
return config;
|
|
287
287
|
}
|
|
288
|
+
async function resolveAgentId(slug, config) {
|
|
289
|
+
try {
|
|
290
|
+
const listResponse = await axios_1.default.get(`${config.goclaw.api_url}/v1/agents`, {
|
|
291
|
+
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
292
|
+
});
|
|
293
|
+
const agents = listResponse.data.agents || [];
|
|
294
|
+
const agent = agents.find((a) => a.agent_key === slug);
|
|
295
|
+
return agent ? agent.id : null;
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
288
301
|
const deployCmd = program
|
|
289
302
|
.command("deploy")
|
|
290
303
|
.description("Faz o deploy de entidades para a plataforma GoClaw");
|
|
@@ -336,7 +349,8 @@ deployCmd
|
|
|
336
349
|
}
|
|
337
350
|
}
|
|
338
351
|
});
|
|
339
|
-
async function deployContextFiles(slug, config) {
|
|
352
|
+
async function deployContextFiles(slug, config, resolvedId) {
|
|
353
|
+
const agentId = resolvedId || (await resolveAgentId(slug, config)) || slug;
|
|
340
354
|
const basePath = getWorkspaceRoot();
|
|
341
355
|
const agentPath = path_1.default.join(basePath, "agents", slug);
|
|
342
356
|
if (!(await fs_extra_1.default.pathExists(agentPath))) {
|
|
@@ -363,7 +377,7 @@ async function deployContextFiles(slug, config) {
|
|
|
363
377
|
}, ["context_files"]);
|
|
364
378
|
const form = new form_data_1.default();
|
|
365
379
|
form.append("file", fs_extra_1.default.createReadStream(tarPath));
|
|
366
|
-
const url = `${config.goclaw.api_url}/v1/agents/${
|
|
380
|
+
const url = `${config.goclaw.api_url}/v1/agents/${agentId}/import?include=context_files`;
|
|
367
381
|
await axios_1.default.post(url, form, {
|
|
368
382
|
headers: {
|
|
369
383
|
...form.getHeaders(),
|
|
@@ -417,20 +431,8 @@ deployCmd
|
|
|
417
431
|
const agentConfig = await fs_extra_1.default.readJson(agentJsonPath);
|
|
418
432
|
console.log(`🚀 Atualizando configuração do agente "${slug}"...`);
|
|
419
433
|
try {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
await axios_1.default.get(`${config.goclaw.api_url}/v1/agents/${slug}`, {
|
|
423
|
-
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
catch (e) {
|
|
427
|
-
if (e.response && e.response.status === 404) {
|
|
428
|
-
exists = false;
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
throw e;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
+
const agentId = await resolveAgentId(slug, config);
|
|
435
|
+
const exists = agentId !== null;
|
|
434
436
|
if (!exists) {
|
|
435
437
|
await axios_1.default.post(`${config.goclaw.api_url}/v1/agents`, agentConfig, {
|
|
436
438
|
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
@@ -438,13 +440,13 @@ deployCmd
|
|
|
438
440
|
console.log("✅ Agente criado com sucesso.");
|
|
439
441
|
}
|
|
440
442
|
else {
|
|
441
|
-
await axios_1.default.put(`${config.goclaw.api_url}/v1/agents/${
|
|
443
|
+
await axios_1.default.put(`${config.goclaw.api_url}/v1/agents/${agentId}`, agentConfig, {
|
|
442
444
|
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
443
445
|
});
|
|
444
446
|
console.log("✅ Configurações do agente atualizadas.");
|
|
445
447
|
}
|
|
446
448
|
console.log(`🚀 Sincronizando arquivos de contexto...`);
|
|
447
|
-
await deployContextFiles(slug, config);
|
|
449
|
+
await deployContextFiles(slug, config, agentId);
|
|
448
450
|
console.log("✅ Deploy completo concluído!");
|
|
449
451
|
}
|
|
450
452
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@innominatum/agentforge-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "A powerful command-line interface to scaffold, manage, build, and deploy AI Agents and Skills for the GoClaw platform.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
"type": "git",
|
|
17
17
|
"url": "git+https://github.com/Innominatum-pt/agentforge-cli.git"
|
|
18
18
|
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
19
22
|
"keywords": [
|
|
20
23
|
"ai",
|
|
21
24
|
"agents",
|
|
@@ -49,4 +52,4 @@
|
|
|
49
52
|
"tsx": "^4.21.0",
|
|
50
53
|
"typescript": "^6.0.3"
|
|
51
54
|
}
|
|
52
|
-
}
|
|
55
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -297,6 +297,19 @@ async function getConfig() {
|
|
|
297
297
|
return config;
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
+
async function resolveAgentId(slug: string, config: any): Promise<string | null> {
|
|
301
|
+
try {
|
|
302
|
+
const listResponse = await axios.get(`${config.goclaw.api_url}/v1/agents`, {
|
|
303
|
+
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
304
|
+
});
|
|
305
|
+
const agents = listResponse.data.agents || [];
|
|
306
|
+
const agent = agents.find((a: any) => a.agent_key === slug);
|
|
307
|
+
return agent ? agent.id : null;
|
|
308
|
+
} catch (error) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
300
313
|
const deployCmd = program
|
|
301
314
|
.command("deploy")
|
|
302
315
|
.description("Faz o deploy de entidades para a plataforma GoClaw");
|
|
@@ -354,7 +367,8 @@ deployCmd
|
|
|
354
367
|
}
|
|
355
368
|
});
|
|
356
369
|
|
|
357
|
-
async function deployContextFiles(slug: string, config: any) {
|
|
370
|
+
async function deployContextFiles(slug: string, config: any, resolvedId?: string | null) {
|
|
371
|
+
const agentId = resolvedId || (await resolveAgentId(slug, config)) || slug;
|
|
358
372
|
const basePath = getWorkspaceRoot();
|
|
359
373
|
const agentPath = path.join(basePath, "agents", slug);
|
|
360
374
|
if (!(await fs.pathExists(agentPath))) {
|
|
@@ -388,7 +402,7 @@ async function deployContextFiles(slug: string, config: any) {
|
|
|
388
402
|
const form = new FormData();
|
|
389
403
|
form.append("file", fs.createReadStream(tarPath));
|
|
390
404
|
|
|
391
|
-
const url = `${config.goclaw.api_url}/v1/agents/${
|
|
405
|
+
const url = `${config.goclaw.api_url}/v1/agents/${agentId}/import?include=context_files`;
|
|
392
406
|
await axios.post(url, form, {
|
|
393
407
|
headers: {
|
|
394
408
|
...form.getHeaders(),
|
|
@@ -446,18 +460,8 @@ deployCmd
|
|
|
446
460
|
console.log(`🚀 Atualizando configuração do agente "${slug}"...`);
|
|
447
461
|
|
|
448
462
|
try {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
await axios.get(`${config.goclaw.api_url}/v1/agents/${slug}`, {
|
|
452
|
-
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
453
|
-
});
|
|
454
|
-
} catch (e: any) {
|
|
455
|
-
if (e.response && e.response.status === 404) {
|
|
456
|
-
exists = false;
|
|
457
|
-
} else {
|
|
458
|
-
throw e;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
463
|
+
const agentId = await resolveAgentId(slug, config);
|
|
464
|
+
const exists = agentId !== null;
|
|
461
465
|
|
|
462
466
|
if (!exists) {
|
|
463
467
|
await axios.post(`${config.goclaw.api_url}/v1/agents`, agentConfig, {
|
|
@@ -465,14 +469,14 @@ deployCmd
|
|
|
465
469
|
});
|
|
466
470
|
console.log("✅ Agente criado com sucesso.");
|
|
467
471
|
} else {
|
|
468
|
-
await axios.put(`${config.goclaw.api_url}/v1/agents/${
|
|
472
|
+
await axios.put(`${config.goclaw.api_url}/v1/agents/${agentId}`, agentConfig, {
|
|
469
473
|
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
470
474
|
});
|
|
471
475
|
console.log("✅ Configurações do agente atualizadas.");
|
|
472
476
|
}
|
|
473
477
|
|
|
474
478
|
console.log(`🚀 Sincronizando arquivos de contexto...`);
|
|
475
|
-
await deployContextFiles(slug, config);
|
|
479
|
+
await deployContextFiles(slug, config, agentId);
|
|
476
480
|
|
|
477
481
|
console.log("✅ Deploy completo concluído!");
|
|
478
482
|
} catch (error: any) {
|