api-to-cli 0.1.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.
- package/LICENSE +21 -0
- package/PROJECT_BRIEF.md +65 -0
- package/README.md +130 -0
- package/SPEC.md +99 -0
- package/bin/api-to-cli.js +5 -0
- package/examples/trello/api-to-cli.config.js +60 -0
- package/examples/trello/trelloapi-agent/README.md +11 -0
- package/examples/trello/trelloapi-agent/agentbridge.manifest.json +68 -0
- package/examples/trello/trelloapi-agent/cli/README.md +25 -0
- package/examples/trello/trelloapi-agent/cli/bin/trelloapi.js +37 -0
- package/examples/trello/trelloapi-agent/cli/commands/get-board.js +41 -0
- package/examples/trello/trelloapi-agent/cli/commands/list-board-lists.js +41 -0
- package/examples/trello/trelloapi-agent/cli/commands/list-list-cards.js +41 -0
- package/examples/trello/trelloapi-agent/cli/lib/client.js +90 -0
- package/examples/trello/trelloapi-agent/cli/lib/output.js +21 -0
- package/examples/trello/trelloapi-agent/cli/package.json +16 -0
- package/examples/trello/trelloapi-agent/skill/SKILL.md +34 -0
- package/examples/trello/trelloapi-cli/README.md +25 -0
- package/examples/trello/trelloapi-cli/bin/trelloapi.js +37 -0
- package/examples/trello/trelloapi-cli/commands/get-board.js +41 -0
- package/examples/trello/trelloapi-cli/commands/list-board-lists.js +41 -0
- package/examples/trello/trelloapi-cli/commands/list-list-cards.js +41 -0
- package/examples/trello/trelloapi-cli/lib/client.js +90 -0
- package/examples/trello/trelloapi-cli/lib/output.js +21 -0
- package/examples/trello/trelloapi-cli/package.json +16 -0
- package/package.json +48 -0
- package/src/commands/generate.js +36 -0
- package/src/commands/scaffold.js +110 -0
- package/src/commands/validate.js +30 -0
- package/src/index.js +92 -0
- package/src/lib/config-utils.js +21 -0
- package/src/lib/generate-cli.js +295 -0
- package/src/lib/generate-manifest.js +51 -0
- package/src/lib/generate-skill.js +50 -0
- package/src/lib/load-config.js +120 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
async function request(command, options) {
|
|
2
|
+
const auth = {
|
|
3
|
+
"credentials": [
|
|
4
|
+
{
|
|
5
|
+
"envVar": "TRELLO_KEY",
|
|
6
|
+
"in": "query",
|
|
7
|
+
"name": "key"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"envVar": "TRELLO_TOKEN",
|
|
11
|
+
"in": "query",
|
|
12
|
+
"name": "token"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
};
|
|
16
|
+
const params = new URLSearchParams();
|
|
17
|
+
const commandParams = command.params || {};
|
|
18
|
+
let resolvedPath = command.path;
|
|
19
|
+
const headers = {
|
|
20
|
+
accept: 'application/json'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
(auth.credentials || []).forEach((credential) => {
|
|
24
|
+
const envValue = process.env[credential.envVar];
|
|
25
|
+
|
|
26
|
+
if (!envValue) {
|
|
27
|
+
throw new Error(`Missing required auth environment variable: ${credential.envVar}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const authValue = credential.prefix ? `${credential.prefix}${envValue}` : envValue;
|
|
31
|
+
|
|
32
|
+
if (credential.in === 'header') {
|
|
33
|
+
headers[credential.name] = authValue;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
params.append(credential.name, authValue);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
Object.entries(commandParams).forEach(([name, schema]) => {
|
|
41
|
+
const value = options[name];
|
|
42
|
+
|
|
43
|
+
if ((value === undefined || value === null || value === '') && schema.required) {
|
|
44
|
+
throw new Error(`Missing required parameter: --${name}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (value === undefined || value === null || value === '') {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const token = `{${name}}`;
|
|
52
|
+
|
|
53
|
+
if (resolvedPath.includes(token)) {
|
|
54
|
+
resolvedPath = resolvedPath.replaceAll(token, encodeURIComponent(String(value)));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
params.append(name, String(value));
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const query = params.toString();
|
|
62
|
+
const url = 'https://api.trello.com/1' + resolvedPath + (query ? '?' + query : '');
|
|
63
|
+
|
|
64
|
+
const response = await fetch(url, {
|
|
65
|
+
method: command.method,
|
|
66
|
+
headers
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const text = await response.text();
|
|
70
|
+
let body = text;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
body = text ? JSON.parse(text) : null;
|
|
74
|
+
} catch (_err) {
|
|
75
|
+
body = text;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
const error = new Error(`HTTP ${response.status}`);
|
|
80
|
+
error.statusCode = response.status;
|
|
81
|
+
error.responseBody = body;
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return body;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
request
|
|
90
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function json(data, pretty) {
|
|
2
|
+
const text = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
3
|
+
process.stdout.write(text + '\n');
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function error(payload, pretty) {
|
|
7
|
+
const envelope = {
|
|
8
|
+
error: true,
|
|
9
|
+
code: payload.code || 'REQUEST_FAILED',
|
|
10
|
+
message: payload.message || 'Request failed',
|
|
11
|
+
details: payload.details || {}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const text = pretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope);
|
|
15
|
+
process.stderr.write(text + '\n');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
json,
|
|
20
|
+
error
|
|
21
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "trelloapi-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "trelloapi CLI generated by AgentBridge",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"trelloapi": "./bin/trelloapi.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node ./bin/trelloapi.js"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"commander": "^12.1.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# trelloapi CLI Skill
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Use the generated trelloapi CLI from AgentBridge. Always prefer JSON output for machine parsing.
|
|
5
|
+
|
|
6
|
+
## Location
|
|
7
|
+
- CLI project: ./cli
|
|
8
|
+
- Binary name: trelloapi
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
1. cd ./cli
|
|
12
|
+
2. npm install
|
|
13
|
+
3. npm link
|
|
14
|
+
|
|
15
|
+
## Auth
|
|
16
|
+
- export TRELLO_KEY="<value>"
|
|
17
|
+
- export TRELLO_TOKEN="<value>"
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
- get-board: Get a board by ID
|
|
21
|
+
- --board-id <value> (required)
|
|
22
|
+
- example: trelloapi get-board --board-id <value>
|
|
23
|
+
- list-board-lists: List lists on a board
|
|
24
|
+
- --board-id <value> (required)
|
|
25
|
+
- example: trelloapi list-board-lists --board-id <value>
|
|
26
|
+
- list-list-cards: List cards in a list
|
|
27
|
+
- --list-id <value> (required)
|
|
28
|
+
- example: trelloapi list-list-cards --list-id <value>
|
|
29
|
+
|
|
30
|
+
## Rules
|
|
31
|
+
- Do not echo or log auth secrets.
|
|
32
|
+
- Do not pass credentials as command flags.
|
|
33
|
+
- Parse command stdout as JSON.
|
|
34
|
+
- Treat non-zero exits as failure and read stderr JSON envelope.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# trelloapi CLI
|
|
2
|
+
|
|
3
|
+
Generated by AgentBridge (api-to-cli).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm link
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Auth
|
|
13
|
+
|
|
14
|
+
Set required environment variables before running commands:
|
|
15
|
+
|
|
16
|
+
- `TRELLO_KEY`
|
|
17
|
+
- `TRELLO_TOKEN`
|
|
18
|
+
|
|
19
|
+
Do not pass secrets as command flags.
|
|
20
|
+
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
- `trelloapi get-board` - Get a board by ID
|
|
24
|
+
- `trelloapi list-board-lists` - List lists on a board
|
|
25
|
+
- `trelloapi list-list-cards` - List cards in a list
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Command } = require('commander');
|
|
4
|
+
|
|
5
|
+
const cmd0 = require('../commands/get-board');
|
|
6
|
+
const cmd1 = require('../commands/list-board-lists');
|
|
7
|
+
const cmd2 = require('../commands/list-list-cards');
|
|
8
|
+
|
|
9
|
+
const program = new Command();
|
|
10
|
+
|
|
11
|
+
program
|
|
12
|
+
.name('trelloapi')
|
|
13
|
+
.description('trelloapi CLI generated by AgentBridge')
|
|
14
|
+
.version('1.0.0');
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.command('get-board')
|
|
18
|
+
.description('Get a board by ID')
|
|
19
|
+
.option('--board-id <value>', 'Trello board ID')
|
|
20
|
+
.option('--pretty', 'Pretty-print JSON')
|
|
21
|
+
.action((options) => cmd0.run(options));
|
|
22
|
+
|
|
23
|
+
program
|
|
24
|
+
.command('list-board-lists')
|
|
25
|
+
.description('List lists on a board')
|
|
26
|
+
.option('--board-id <value>', 'Trello board ID')
|
|
27
|
+
.option('--pretty', 'Pretty-print JSON')
|
|
28
|
+
.action((options) => cmd1.run(options));
|
|
29
|
+
|
|
30
|
+
program
|
|
31
|
+
.command('list-list-cards')
|
|
32
|
+
.description('List cards in a list')
|
|
33
|
+
.option('--list-id <value>', 'Trello list ID')
|
|
34
|
+
.option('--pretty', 'Pretty-print JSON')
|
|
35
|
+
.action((options) => cmd2.run(options));
|
|
36
|
+
|
|
37
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const { request } = require('../lib/client');
|
|
2
|
+
const output = require('../lib/output');
|
|
3
|
+
|
|
4
|
+
const command = {
|
|
5
|
+
"name": "get-board",
|
|
6
|
+
"description": "Get a board by ID",
|
|
7
|
+
"method": "GET",
|
|
8
|
+
"path": "/boards/{boardId}",
|
|
9
|
+
"params": {
|
|
10
|
+
"boardId": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"required": true,
|
|
13
|
+
"description": "Trello board ID"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
async function getBoard(options) {
|
|
19
|
+
try {
|
|
20
|
+
const data = await request(command, options);
|
|
21
|
+
output.json(data, Boolean(options.pretty));
|
|
22
|
+
} catch (error) {
|
|
23
|
+
output.error(
|
|
24
|
+
{
|
|
25
|
+
code: error.statusCode ? 'HTTP_ERROR' : 'REQUEST_FAILED',
|
|
26
|
+
message: error.message,
|
|
27
|
+
details: {
|
|
28
|
+
statusCode: error.statusCode || null,
|
|
29
|
+
command: command.name
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
Boolean(options.pretty)
|
|
33
|
+
);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
run: getBoard,
|
|
40
|
+
command
|
|
41
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const { request } = require('../lib/client');
|
|
2
|
+
const output = require('../lib/output');
|
|
3
|
+
|
|
4
|
+
const command = {
|
|
5
|
+
"name": "list-board-lists",
|
|
6
|
+
"description": "List lists on a board",
|
|
7
|
+
"method": "GET",
|
|
8
|
+
"path": "/boards/{boardId}/lists",
|
|
9
|
+
"params": {
|
|
10
|
+
"boardId": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"required": true,
|
|
13
|
+
"description": "Trello board ID"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
async function listBoardLists(options) {
|
|
19
|
+
try {
|
|
20
|
+
const data = await request(command, options);
|
|
21
|
+
output.json(data, Boolean(options.pretty));
|
|
22
|
+
} catch (error) {
|
|
23
|
+
output.error(
|
|
24
|
+
{
|
|
25
|
+
code: error.statusCode ? 'HTTP_ERROR' : 'REQUEST_FAILED',
|
|
26
|
+
message: error.message,
|
|
27
|
+
details: {
|
|
28
|
+
statusCode: error.statusCode || null,
|
|
29
|
+
command: command.name
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
Boolean(options.pretty)
|
|
33
|
+
);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
run: listBoardLists,
|
|
40
|
+
command
|
|
41
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const { request } = require('../lib/client');
|
|
2
|
+
const output = require('../lib/output');
|
|
3
|
+
|
|
4
|
+
const command = {
|
|
5
|
+
"name": "list-list-cards",
|
|
6
|
+
"description": "List cards in a list",
|
|
7
|
+
"method": "GET",
|
|
8
|
+
"path": "/lists/{listId}/cards",
|
|
9
|
+
"params": {
|
|
10
|
+
"listId": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"required": true,
|
|
13
|
+
"description": "Trello list ID"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
async function listListCards(options) {
|
|
19
|
+
try {
|
|
20
|
+
const data = await request(command, options);
|
|
21
|
+
output.json(data, Boolean(options.pretty));
|
|
22
|
+
} catch (error) {
|
|
23
|
+
output.error(
|
|
24
|
+
{
|
|
25
|
+
code: error.statusCode ? 'HTTP_ERROR' : 'REQUEST_FAILED',
|
|
26
|
+
message: error.message,
|
|
27
|
+
details: {
|
|
28
|
+
statusCode: error.statusCode || null,
|
|
29
|
+
command: command.name
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
Boolean(options.pretty)
|
|
33
|
+
);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
run: listListCards,
|
|
40
|
+
command
|
|
41
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
async function request(command, options) {
|
|
2
|
+
const auth = {
|
|
3
|
+
"credentials": [
|
|
4
|
+
{
|
|
5
|
+
"envVar": "TRELLO_KEY",
|
|
6
|
+
"in": "query",
|
|
7
|
+
"name": "key"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"envVar": "TRELLO_TOKEN",
|
|
11
|
+
"in": "query",
|
|
12
|
+
"name": "token"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
};
|
|
16
|
+
const params = new URLSearchParams();
|
|
17
|
+
const commandParams = command.params || {};
|
|
18
|
+
let resolvedPath = command.path;
|
|
19
|
+
const headers = {
|
|
20
|
+
accept: 'application/json'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
(auth.credentials || []).forEach((credential) => {
|
|
24
|
+
const envValue = process.env[credential.envVar];
|
|
25
|
+
|
|
26
|
+
if (!envValue) {
|
|
27
|
+
throw new Error(`Missing required auth environment variable: ${credential.envVar}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const authValue = credential.prefix ? `${credential.prefix}${envValue}` : envValue;
|
|
31
|
+
|
|
32
|
+
if (credential.in === 'header') {
|
|
33
|
+
headers[credential.name] = authValue;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
params.append(credential.name, authValue);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
Object.entries(commandParams).forEach(([name, schema]) => {
|
|
41
|
+
const value = options[name];
|
|
42
|
+
|
|
43
|
+
if ((value === undefined || value === null || value === '') && schema.required) {
|
|
44
|
+
throw new Error(`Missing required parameter: --${name}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (value === undefined || value === null || value === '') {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const token = `{${name}}`;
|
|
52
|
+
|
|
53
|
+
if (resolvedPath.includes(token)) {
|
|
54
|
+
resolvedPath = resolvedPath.replaceAll(token, encodeURIComponent(String(value)));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
params.append(name, String(value));
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const query = params.toString();
|
|
62
|
+
const url = 'https://api.trello.com/1' + resolvedPath + (query ? '?' + query : '');
|
|
63
|
+
|
|
64
|
+
const response = await fetch(url, {
|
|
65
|
+
method: command.method,
|
|
66
|
+
headers
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const text = await response.text();
|
|
70
|
+
let body = text;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
body = text ? JSON.parse(text) : null;
|
|
74
|
+
} catch (_err) {
|
|
75
|
+
body = text;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
const error = new Error(`HTTP ${response.status}`);
|
|
80
|
+
error.statusCode = response.status;
|
|
81
|
+
error.responseBody = body;
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return body;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
request
|
|
90
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function json(data, pretty) {
|
|
2
|
+
const text = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
3
|
+
process.stdout.write(text + '\n');
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function error(payload, pretty) {
|
|
7
|
+
const envelope = {
|
|
8
|
+
error: true,
|
|
9
|
+
code: payload.code || 'REQUEST_FAILED',
|
|
10
|
+
message: payload.message || 'Request failed',
|
|
11
|
+
details: payload.details || {}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const text = pretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope);
|
|
15
|
+
process.stderr.write(text + '\n');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
json,
|
|
20
|
+
error
|
|
21
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "trelloapi-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "trelloapi CLI generated by AgentBridge",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"trelloapi": "./bin/trelloapi.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node ./bin/trelloapi.js"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"commander": "^12.1.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "api-to-cli",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Generate AI-agent-friendly CLIs, skills, and manifests from API configs",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"api-to-cli": "./bin/api-to-cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"src",
|
|
13
|
+
"examples",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"PROJECT_BRIEF.md",
|
|
17
|
+
"SPEC.md"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/RandyVentures/AgentBridge.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/RandyVentures/AgentBridge/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/RandyVentures/AgentBridge#readme",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"cli",
|
|
32
|
+
"api",
|
|
33
|
+
"ai-agent",
|
|
34
|
+
"generator",
|
|
35
|
+
"mcp",
|
|
36
|
+
"developer-tools"
|
|
37
|
+
],
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"validate:trello": "node ./bin/api-to-cli.js validate --config ./examples/trello/api-to-cli.config.js",
|
|
43
|
+
"generate:trello": "node ./bin/api-to-cli.js generate --config ./examples/trello/api-to-cli.config.js --output ./examples/trello/trelloapi-cli",
|
|
44
|
+
"scaffold:trello": "node ./bin/api-to-cli.js scaffold --config ./examples/trello/api-to-cli.config.js --output ./examples/trello/trelloapi-agent",
|
|
45
|
+
"test:smoke": "npm run validate:trello && npm run generate:trello && npm run scaffold:trello",
|
|
46
|
+
"pack:check": "npm pack --dry-run"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { loadConfig } = require('../lib/load-config');
|
|
3
|
+
const { generateCliProject } = require('../lib/generate-cli');
|
|
4
|
+
|
|
5
|
+
async function generate(flags) {
|
|
6
|
+
if (!flags.config) {
|
|
7
|
+
throw new Error('Missing required flag: --config <path>');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (!flags.output) {
|
|
11
|
+
throw new Error('Missing required flag: --output <dir>');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const configPath = path.resolve(process.cwd(), String(flags.config));
|
|
15
|
+
const outputPath = path.resolve(process.cwd(), String(flags.output));
|
|
16
|
+
|
|
17
|
+
const config = loadConfig(configPath);
|
|
18
|
+
|
|
19
|
+
generateCliProject({
|
|
20
|
+
config,
|
|
21
|
+
outputPath
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
console.log(
|
|
25
|
+
JSON.stringify({
|
|
26
|
+
ok: true,
|
|
27
|
+
command: 'generate',
|
|
28
|
+
outputPath,
|
|
29
|
+
generatedCommands: config.commands.map((command) => command.name)
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
generate
|
|
36
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { loadConfig } = require('../lib/load-config');
|
|
4
|
+
const { generateCliProject } = require('../lib/generate-cli');
|
|
5
|
+
const { writeSkillPackage } = require('../lib/generate-skill');
|
|
6
|
+
const { buildManifest, writeManifest } = require('../lib/generate-manifest');
|
|
7
|
+
|
|
8
|
+
function hasOwn(obj, key) {
|
|
9
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function resolveArtifactFlags(flags) {
|
|
13
|
+
const hasSkill = hasOwn(flags, 'with-skill');
|
|
14
|
+
const hasManifest = hasOwn(flags, 'with-manifest');
|
|
15
|
+
|
|
16
|
+
if (!hasSkill && !hasManifest) {
|
|
17
|
+
return {
|
|
18
|
+
withSkill: true,
|
|
19
|
+
withManifest: true
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
withSkill: Boolean(flags['with-skill']),
|
|
25
|
+
withManifest: Boolean(flags['with-manifest'])
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function writeScaffoldReadme(outputPath, data) {
|
|
30
|
+
const lines = [
|
|
31
|
+
'# AgentBridge Scaffold Output',
|
|
32
|
+
'',
|
|
33
|
+
'## Contents',
|
|
34
|
+
`- CLI project: ${data.cliProjectPath}`
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
if (data.skillPath) {
|
|
38
|
+
lines.push(`- Skill file: ${data.skillPath}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (data.manifestPath) {
|
|
42
|
+
lines.push(`- Manifest: ${data.manifestPath}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
lines.push('', '## Next Steps', '1. cd ./cli', '2. npm install', '3. npm link');
|
|
46
|
+
|
|
47
|
+
fs.writeFileSync(path.join(outputPath, 'README.md'), `${lines.join('\n')}\n`, 'utf8');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function scaffold(flags) {
|
|
51
|
+
if (!flags.config) {
|
|
52
|
+
throw new Error('Missing required flag: --config <path>');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!flags.output) {
|
|
56
|
+
throw new Error('Missing required flag: --output <dir>');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const { withSkill, withManifest } = resolveArtifactFlags(flags);
|
|
60
|
+
const cliRelativePath = './cli';
|
|
61
|
+
const skillRelativePath = './skill/SKILL.md';
|
|
62
|
+
const manifestRelativePath = './agentbridge.manifest.json';
|
|
63
|
+
|
|
64
|
+
const configPath = path.resolve(process.cwd(), String(flags.config));
|
|
65
|
+
const outputPath = path.resolve(process.cwd(), String(flags.output));
|
|
66
|
+
const cliProjectPath = path.join(outputPath, 'cli');
|
|
67
|
+
|
|
68
|
+
const config = loadConfig(configPath);
|
|
69
|
+
fs.mkdirSync(outputPath, { recursive: true });
|
|
70
|
+
|
|
71
|
+
generateCliProject({
|
|
72
|
+
config,
|
|
73
|
+
outputPath: cliProjectPath
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
let skillPath = null;
|
|
77
|
+
if (withSkill) {
|
|
78
|
+
writeSkillPackage(outputPath, config, cliRelativePath);
|
|
79
|
+
skillPath = skillRelativePath;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let manifestPath = null;
|
|
83
|
+
if (withManifest) {
|
|
84
|
+
const manifest = buildManifest(config, cliRelativePath, skillPath);
|
|
85
|
+
writeManifest(outputPath, manifest);
|
|
86
|
+
manifestPath = manifestRelativePath;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
writeScaffoldReadme(outputPath, {
|
|
90
|
+
cliProjectPath: cliRelativePath,
|
|
91
|
+
skillPath,
|
|
92
|
+
manifestPath
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
console.log(
|
|
96
|
+
JSON.stringify({
|
|
97
|
+
ok: true,
|
|
98
|
+
command: 'scaffold',
|
|
99
|
+
outputPath,
|
|
100
|
+
cliProjectPath: cliRelativePath,
|
|
101
|
+
skillPath,
|
|
102
|
+
manifestPath,
|
|
103
|
+
generatedCommands: config.commands.map((command) => command.name)
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
scaffold
|
|
110
|
+
};
|