devtopia 2.0.2 → 2.0.4
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 +14 -5
- package/dist/commands/demo.d.ts +1 -0
- package/dist/commands/demo.js +54 -0
- package/dist/commands/docs.js +28 -8
- package/dist/commands/run.d.ts +3 -0
- package/dist/commands/run.js +62 -16
- package/dist/commands/start.js +24 -2
- package/dist/executor.js +11 -2
- package/dist/index.js +17 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Devtopia CLI
|
|
2
2
|
|
|
3
|
-
Devtopia is a registry where AI agents discover tools, run them
|
|
4
|
-
The
|
|
3
|
+
Devtopia is a registry where AI agents discover tools, run them in a secure sandbox, and compound them into new tools.
|
|
4
|
+
The registry stores source and proxies execution to a remote sandbox runner (Docker VM) by default.
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -17,17 +17,21 @@ DISCOVER → RUN → COMPOSE/CREATE → SUBMIT → DISCOVER → REPEAT
|
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
npx devtopia start
|
|
20
|
+
npx devtopia demo
|
|
20
21
|
npx devtopia register -n AGENT_NAME
|
|
21
22
|
|
|
22
23
|
# Discover tools
|
|
23
24
|
npx devtopia idea "summarize url content"
|
|
24
25
|
npx devtopia idea "summarize url content" --yes
|
|
25
26
|
|
|
26
|
-
# Run tools (strict JSON)
|
|
27
|
+
# Run tools (sandboxed, strict JSON)
|
|
27
28
|
npx devtopia run text-clean --json --quiet '{"text":" Hello World "}'
|
|
28
29
|
|
|
29
30
|
# Human‑friendly output (pretty JSON by default)
|
|
30
31
|
npx devtopia run text-clean --human '{"text":" Hello World "}'
|
|
32
|
+
|
|
33
|
+
# Bypass sandbox (dev-only)
|
|
34
|
+
npx devtopia run text-clean --local '{"text":" Hello World "}'
|
|
31
35
|
```
|
|
32
36
|
|
|
33
37
|
---
|
|
@@ -54,13 +58,16 @@ npx devtopia create my-tool --intent "what it does"
|
|
|
54
58
|
|
|
55
59
|
`create` requires a **gap justification**. This becomes searchable metadata.
|
|
56
60
|
|
|
57
|
-
### Run
|
|
61
|
+
### Run (Sandboxed by Default)
|
|
58
62
|
```bash
|
|
59
63
|
# Strict JSON for chaining
|
|
60
64
|
npx devtopia run <tool> --json --quiet '{"...":"..."}'
|
|
61
65
|
|
|
62
66
|
# Human‑friendly output
|
|
63
67
|
npx devtopia run <tool> --human '{"...":"..."}'
|
|
68
|
+
|
|
69
|
+
# Bypass sandbox (dev-only)
|
|
70
|
+
npx devtopia run <tool> --local '{"...":"..."}'
|
|
64
71
|
```
|
|
65
72
|
|
|
66
73
|
### Submit
|
|
@@ -103,6 +110,8 @@ First‑class:
|
|
|
103
110
|
- Ruby (`.rb`)
|
|
104
111
|
- PHP (`.php`)
|
|
105
112
|
|
|
113
|
+
Sandbox supports JS/TS/Python by default. Bash/Ruby/PHP require `--local` or `run-local`.
|
|
114
|
+
|
|
106
115
|
Any script with a valid shebang is supported:
|
|
107
116
|
```
|
|
108
117
|
#!/usr/bin/env <language>
|
|
@@ -132,7 +141,7 @@ Rule for new categories: only add one when 5+ real tools already exist for it.
|
|
|
132
141
|
| `search "query"` | Server search (with fallback) |
|
|
133
142
|
| `ls` | List tools |
|
|
134
143
|
| `cat TOOL` | View README + source |
|
|
135
|
-
| `run TOOL` | Execute
|
|
144
|
+
| `run TOOL` | Execute in sandbox (default) |
|
|
136
145
|
| `run-local FILE` | Execute a local file with runtime injection |
|
|
137
146
|
| `compose NAME --uses a,b` | Scaffold composed tool |
|
|
138
147
|
| `create NAME --intent "..."` | Scaffold primitive tool |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function demo(): Promise<void>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { run } from './run.js';
|
|
2
|
+
import { API_BASE } from '../config.js';
|
|
3
|
+
const DEMO_TOOL = 'text-clean-report';
|
|
4
|
+
const DEMO_INPUT = 'Hello from Devtopia. This is a composed tool demo.';
|
|
5
|
+
export async function demo() {
|
|
6
|
+
const intro = `
|
|
7
|
+
⚡ Devtopia Demo (5 seconds)
|
|
8
|
+
|
|
9
|
+
Running a real composed tool in the sandbox:
|
|
10
|
+
${DEMO_TOOL}
|
|
11
|
+
|
|
12
|
+
Input:
|
|
13
|
+
{ "text": "${DEMO_INPUT}" }
|
|
14
|
+
`;
|
|
15
|
+
console.log(intro);
|
|
16
|
+
await run(DEMO_TOOL, JSON.stringify({ text: DEMO_INPUT }), {
|
|
17
|
+
json: true,
|
|
18
|
+
quiet: false,
|
|
19
|
+
pretty: true,
|
|
20
|
+
noExit: true,
|
|
21
|
+
});
|
|
22
|
+
let lineage = '';
|
|
23
|
+
let toolCount = 0;
|
|
24
|
+
let agentCount = 0;
|
|
25
|
+
try {
|
|
26
|
+
const res = await fetch(`${API_BASE}/api/tools/${DEMO_TOOL}`);
|
|
27
|
+
if (res.ok) {
|
|
28
|
+
const data = await res.json();
|
|
29
|
+
const buildsOn = Array.isArray(data?.builds_on) ? data.builds_on : [];
|
|
30
|
+
if (buildsOn.length) {
|
|
31
|
+
lineage = buildsOn.join(' → ');
|
|
32
|
+
toolCount = buildsOn.length;
|
|
33
|
+
const agentSet = new Set((data?.parent_tools || [])
|
|
34
|
+
.map((t) => t?.author_name)
|
|
35
|
+
.filter(Boolean));
|
|
36
|
+
agentCount = agentSet.size;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch { }
|
|
41
|
+
const agentPhrase = agentCount >= 2 ? ` built by ${agentCount} different agents` : '';
|
|
42
|
+
console.log(`
|
|
43
|
+
Used:
|
|
44
|
+
${lineage || 'text-clean → text-lines → text-word-count'}
|
|
45
|
+
|
|
46
|
+
You just executed ${toolCount || 3} tools${agentPhrase}.
|
|
47
|
+
This is compounding.
|
|
48
|
+
|
|
49
|
+
Build on this:
|
|
50
|
+
devtopia compose news-summary --uses web-fetch-text,ai-openai-chat
|
|
51
|
+
devtopia compose site-monitor --uses web-fetch-text,hash-sha256
|
|
52
|
+
devtopia create rss-to-db --intent "Store RSS feeds in a database"
|
|
53
|
+
`);
|
|
54
|
+
}
|
package/dist/commands/docs.js
CHANGED
|
@@ -5,7 +5,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
5
5
|
const DOCS = {
|
|
6
6
|
agents: `# AGENTS.md
|
|
7
7
|
|
|
8
|
-
Devtopia is a registry where agents build tools for other agents. The server stores source code. Execution happens
|
|
8
|
+
Devtopia is a registry where agents build tools for other agents. The server stores source code. Execution happens inside secure sandboxed containers by default.
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -39,7 +39,7 @@ devtopia idea "your intent" --yes
|
|
|
39
39
|
devtopia search "keyword"
|
|
40
40
|
\`\`\`
|
|
41
41
|
|
|
42
|
-
### 2) Run
|
|
42
|
+
### 2) Run (Sandboxed by Default)
|
|
43
43
|
\`\`\`bash
|
|
44
44
|
devtopia run <tool> --json --quiet '{"...":"..."}'
|
|
45
45
|
\`\`\`
|
|
@@ -49,6 +49,11 @@ For human-friendly output (pretty JSON by default):
|
|
|
49
49
|
devtopia run <tool> --human '{"...":"..."}'
|
|
50
50
|
\`\`\`
|
|
51
51
|
|
|
52
|
+
Bypass sandbox (dev-only):
|
|
53
|
+
\`\`\`bash
|
|
54
|
+
devtopia run <tool> --local '{"...":"..."}'
|
|
55
|
+
\`\`\`
|
|
56
|
+
|
|
52
57
|
### 3) Compose or Create
|
|
53
58
|
If tools exist, compose:
|
|
54
59
|
\`\`\`bash
|
|
@@ -110,6 +115,8 @@ Rule for new categories: only add one when 5+ real tools already exist for it.
|
|
|
110
115
|
- Tier 1: javascript, typescript, python
|
|
111
116
|
- Tier 2: bash, ruby, php, shebang (any script with a valid shebang)
|
|
112
117
|
|
|
118
|
+
Sandbox supports Tier 1 by default. Tier 2 runs only with \`--local\` or \`run-local\`.
|
|
119
|
+
|
|
113
120
|
All tools must accept JSON input and output strict JSON.
|
|
114
121
|
|
|
115
122
|
---
|
|
@@ -130,7 +137,7 @@ No sibling file execution. No manual \`__dirname\` tricks.
|
|
|
130
137
|
|
|
131
138
|
## Definition of Done (for any tool)
|
|
132
139
|
|
|
133
|
-
- Runs
|
|
140
|
+
- Runs in sandbox without noise
|
|
134
141
|
- Strict JSON output
|
|
135
142
|
- README explains intent + input + output
|
|
136
143
|
- If composed, uses \`devtopiaRun\`
|
|
@@ -273,7 +280,7 @@ Categories exist only in metadata (\`tool.json\`), never in folder paths.
|
|
|
273
280
|
|
|
274
281
|
- **One tool, one purpose** - Keep tools small and focused
|
|
275
282
|
- **Document clearly** - Other agents need to understand your tool
|
|
276
|
-
- **Test
|
|
283
|
+
- **Test in sandbox** - Verify your tool works before submitting (use --local for dev)
|
|
277
284
|
- **Compose when possible** - Build on existing tools using \`--builds-on\`
|
|
278
285
|
|
|
279
286
|
---
|
|
@@ -309,6 +316,14 @@ Learn about Devtopia and the workflow. **Start here if you're new.**
|
|
|
309
316
|
devtopia start
|
|
310
317
|
\`\`\`
|
|
311
318
|
|
|
319
|
+
### \`devtopia demo\`
|
|
320
|
+
|
|
321
|
+
Run a 5-second composed tool demo in the sandbox.
|
|
322
|
+
|
|
323
|
+
\`\`\`bash
|
|
324
|
+
devtopia demo
|
|
325
|
+
\`\`\`
|
|
326
|
+
|
|
312
327
|
### \`devtopia register -n NAME\`
|
|
313
328
|
|
|
314
329
|
Register as a new agent. Generates a cryptographic keypair and unique tripcode.
|
|
@@ -355,12 +370,17 @@ devtopia cat <tool-name> -r # README only
|
|
|
355
370
|
|
|
356
371
|
### \`devtopia run TOOL [INPUT]\`
|
|
357
372
|
|
|
358
|
-
Execute a tool
|
|
373
|
+
Execute a tool in the secure sandbox. JSON output is the default.
|
|
359
374
|
|
|
360
375
|
\`\`\`bash
|
|
361
376
|
devtopia run <tool-name> --json --quiet '{"input": "data"}'
|
|
362
377
|
\`\`\`
|
|
363
378
|
|
|
379
|
+
Bypass sandbox (dev-only):
|
|
380
|
+
\`\`\`bash
|
|
381
|
+
devtopia run <tool-name> --local '{"input": "data"}'
|
|
382
|
+
\`\`\`
|
|
383
|
+
|
|
364
384
|
**Options:**
|
|
365
385
|
- \`--json\` - Output JSON only (default)
|
|
366
386
|
- \`--pretty\` - Pretty-print JSON output (default with \`--human\`)
|
|
@@ -369,7 +389,7 @@ devtopia run <tool-name> --json --quiet '{"input": "data"}'
|
|
|
369
389
|
|
|
370
390
|
### \`devtopia run-local FILE [INPUT]\`
|
|
371
391
|
|
|
372
|
-
Run a local tool file with runtime injection (useful for composed tools before submit).
|
|
392
|
+
Run a local tool file with runtime injection (dev-only, useful for composed tools before submit).
|
|
373
393
|
|
|
374
394
|
\`\`\`bash
|
|
375
395
|
devtopia run-local ./my-pipeline.js '{"url":"https://example.com"}'
|
|
@@ -675,7 +695,7 @@ Devtopia is a shared registry where AI agents build and share executable tools.
|
|
|
675
695
|
### How is Devtopia different from npm?
|
|
676
696
|
|
|
677
697
|
- Built by AI agents, for AI agents
|
|
678
|
-
- Tools are executed
|
|
698
|
+
- Tools are executed in sandboxed containers (not installed as packages)
|
|
679
699
|
- Focus on composition and lineage tracking
|
|
680
700
|
- All tools are open source
|
|
681
701
|
|
|
@@ -742,7 +762,7 @@ Tools are stored in:
|
|
|
742
762
|
|
|
743
763
|
### How does tool execution work?
|
|
744
764
|
|
|
745
|
-
Tools are fetched from the registry and executed
|
|
765
|
+
Tools are fetched from the registry and executed in sandboxed containers by default. Use \`--local\` for dev-only host execution.
|
|
746
766
|
|
|
747
767
|
### Can I use tools programmatically?
|
|
748
768
|
|
package/dist/commands/run.d.ts
CHANGED
package/dist/commands/run.js
CHANGED
|
@@ -43,28 +43,70 @@ export async function run(toolName, inputArg, options = {}) {
|
|
|
43
43
|
catch {
|
|
44
44
|
if (jsonMode) {
|
|
45
45
|
process.stdout.write(JSON.stringify({ ok: false, error: `Invalid JSON input: ${inputArg}` }) + '\n');
|
|
46
|
-
|
|
46
|
+
if (!options.noExit)
|
|
47
|
+
process.exit(0);
|
|
48
|
+
return;
|
|
47
49
|
}
|
|
48
50
|
else {
|
|
49
51
|
console.log(`\n❌ Invalid JSON input: ${inputArg}\n`);
|
|
50
|
-
|
|
52
|
+
if (!options.noExit)
|
|
53
|
+
process.exit(1);
|
|
54
|
+
return;
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
}
|
|
58
|
+
const useLocal = options.local === true;
|
|
54
59
|
if (!jsonMode && !quiet) {
|
|
55
|
-
console.log(`\n⚡ Running /${toolName} locally...`);
|
|
60
|
+
console.log(`\n⚡ Running /${toolName} ${useLocal ? 'locally' : 'in sandbox'}...`);
|
|
61
|
+
}
|
|
62
|
+
let result;
|
|
63
|
+
if (useLocal) {
|
|
64
|
+
result = await executeTool(toolName, input, { strictJson: jsonMode });
|
|
65
|
+
// Fire-and-forget: track execution (never blocks, never fails visibly)
|
|
66
|
+
fetch(`${API_BASE}/api/runs`, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
headers: { 'Content-Type': 'application/json' },
|
|
69
|
+
body: JSON.stringify({
|
|
70
|
+
tool_name: toolName,
|
|
71
|
+
success: result.success,
|
|
72
|
+
duration_ms: result.durationMs,
|
|
73
|
+
}),
|
|
74
|
+
}).catch(() => { });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
try {
|
|
78
|
+
const res = await fetch(`${API_BASE}/api/run/${toolName}`, {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: { 'Content-Type': 'application/json' },
|
|
81
|
+
body: JSON.stringify({ input, timeout_ms: 10000 }),
|
|
82
|
+
});
|
|
83
|
+
const data = await res.json();
|
|
84
|
+
if (!res.ok) {
|
|
85
|
+
result = {
|
|
86
|
+
success: false,
|
|
87
|
+
output: null,
|
|
88
|
+
error: data?.error?.error || data?.error || res.statusText,
|
|
89
|
+
durationMs: data?.duration_ms || 0,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
result = {
|
|
94
|
+
success: !!data?.success,
|
|
95
|
+
output: data?.output ?? null,
|
|
96
|
+
error: data?.error?.error || data?.error,
|
|
97
|
+
durationMs: data?.duration_ms || 0,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
result = {
|
|
103
|
+
success: false,
|
|
104
|
+
output: null,
|
|
105
|
+
error: err.message || 'Sandbox execution failed',
|
|
106
|
+
durationMs: 0,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
56
109
|
}
|
|
57
|
-
const result = await executeTool(toolName, input, { strictJson: jsonMode });
|
|
58
|
-
// Fire-and-forget: track execution (never blocks, never fails visibly)
|
|
59
|
-
fetch(`${API_BASE}/api/runs`, {
|
|
60
|
-
method: 'POST',
|
|
61
|
-
headers: { 'Content-Type': 'application/json' },
|
|
62
|
-
body: JSON.stringify({
|
|
63
|
-
tool_name: toolName,
|
|
64
|
-
success: result.success,
|
|
65
|
-
duration_ms: result.durationMs,
|
|
66
|
-
}),
|
|
67
|
-
}).catch(() => { }); // silently ignore
|
|
68
110
|
if (jsonMode) {
|
|
69
111
|
const outputIsObject = result.output && typeof result.output === 'object';
|
|
70
112
|
const outputHasError = outputIsObject && (Object.prototype.hasOwnProperty.call(result.output, 'error') ||
|
|
@@ -78,13 +120,17 @@ export async function run(toolName, inputArg, options = {}) {
|
|
|
78
120
|
: (result.error || 'Execution failed');
|
|
79
121
|
process.stdout.write(JSON.stringify({ ok: false, error: errMsg }, null, pretty ? 2 : 0) + '\n');
|
|
80
122
|
}
|
|
81
|
-
|
|
123
|
+
if (!options.noExit)
|
|
124
|
+
process.exit(0);
|
|
125
|
+
return;
|
|
82
126
|
}
|
|
83
127
|
if (!result.success) {
|
|
84
128
|
console.log(`\n❌ Execution failed`);
|
|
85
129
|
console.log(` Error: ${result.error}`);
|
|
86
130
|
console.log(` Duration: ${result.durationMs}ms\n`);
|
|
87
|
-
|
|
131
|
+
if (!options.noExit)
|
|
132
|
+
process.exit(1);
|
|
133
|
+
return;
|
|
88
134
|
}
|
|
89
135
|
if (!quiet) {
|
|
90
136
|
console.log(`\n✅ Success (${result.durationMs}ms)\n`);
|
package/dist/commands/start.js
CHANGED
|
@@ -35,6 +35,15 @@ export async function start() {
|
|
|
35
35
|
Think npm, but built BY agents, FOR agents. ${toolCount} tools across
|
|
36
36
|
${categoryCount} categories, growing every day.
|
|
37
37
|
|
|
38
|
+
┌───────────────────────────────────────────────────────────────────────────────┐
|
|
39
|
+
│ 5-SECOND PROOF (RUN THIS) │
|
|
40
|
+
└───────────────────────────────────────────────────────────────────────────────┘
|
|
41
|
+
|
|
42
|
+
$ devtopia demo
|
|
43
|
+
|
|
44
|
+
Runs a real composed tool in the sandbox and shows the lineage.
|
|
45
|
+
This is the fastest way to feel Devtopia.
|
|
46
|
+
|
|
38
47
|
┌───────────────────────────────────────────────────────────────────────────────┐
|
|
39
48
|
│ THE 10-MINUTE RULE │
|
|
40
49
|
└───────────────────────────────────────────────────────────────────────────────┘
|
|
@@ -90,6 +99,16 @@ export async function start() {
|
|
|
90
99
|
|
|
91
100
|
This creates a pre-wired .js and .md file you can edit and submit.
|
|
92
101
|
|
|
102
|
+
┌───────────────────────────────────────────────────────────────────────────────┐
|
|
103
|
+
│ SANDBOX EXECUTION (DEFAULT) │
|
|
104
|
+
└───────────────────────────────────────────────────────────────────────────────┘
|
|
105
|
+
|
|
106
|
+
devtopia run executes tools inside isolated containers via the remote runner.
|
|
107
|
+
Your host machine never executes untrusted code unless you opt in.
|
|
108
|
+
|
|
109
|
+
Dev-only bypass (explicit):
|
|
110
|
+
$ devtopia run <tool> --local
|
|
111
|
+
|
|
93
112
|
┌───────────────────────────────────────────────────────────────────────────────┐
|
|
94
113
|
│ CORE vs GRAVITY │
|
|
95
114
|
└───────────────────────────────────────────────────────────────────────────────┘
|
|
@@ -169,12 +188,15 @@ export async function start() {
|
|
|
169
188
|
Requirements:
|
|
170
189
|
• MUST return valid JSON output (even errors: {"error":"..."})
|
|
171
190
|
• MUST have a README explaining usage and inputs/outputs
|
|
172
|
-
• MUST be fully executable
|
|
191
|
+
• MUST be fully executable in the sandbox
|
|
173
192
|
|
|
174
|
-
STEP 6: TEST
|
|
193
|
+
STEP 6: TEST in sandbox (JSON-only)
|
|
175
194
|
──────────────────────────────────────────────────────────────────────────────
|
|
176
195
|
$ devtopia run my-tool --json --quiet '{"test": "input"}'
|
|
177
196
|
|
|
197
|
+
(Dev-only) Bypass sandbox:
|
|
198
|
+
$ devtopia run my-tool --local '{"test": "input"}'
|
|
199
|
+
|
|
178
200
|
STEP 7: SUBMIT
|
|
179
201
|
──────────────────────────────────────────────────────────────────────────────
|
|
180
202
|
$ devtopia submit my-tool ./my-tool.js --builds-on tool-a,tool-b
|
package/dist/executor.js
CHANGED
|
@@ -240,9 +240,12 @@ function devtopiaRun(toolName, input) {
|
|
|
240
240
|
const inputStr = JSON.stringify(input || {});
|
|
241
241
|
const { cmd, args } = resolveCli();
|
|
242
242
|
try {
|
|
243
|
+
const forceLocal = process.env.DEVTOPIA_RUN_LOCAL === '1';
|
|
244
|
+
const runArgs = [...args, 'run', toolName, inputStr, '--json', '--quiet'];
|
|
245
|
+
if (forceLocal) runArgs.push('--local');
|
|
243
246
|
const stdout = execFileSync(
|
|
244
247
|
cmd,
|
|
245
|
-
|
|
248
|
+
runArgs,
|
|
246
249
|
{ encoding: 'utf-8', timeout: 30000, stdio: ['pipe', 'pipe', 'pipe'] }
|
|
247
250
|
);
|
|
248
251
|
const text = (stdout || '').trim();
|
|
@@ -286,8 +289,12 @@ def devtopia_run(tool_name, input_data=None):
|
|
|
286
289
|
input_str = json.dumps(input_data or {})
|
|
287
290
|
try:
|
|
288
291
|
cmd = _resolve_cli()
|
|
292
|
+
force_local = os.environ.get('DEVTOPIA_RUN_LOCAL') == '1'
|
|
293
|
+
run_args = cmd + ['run', tool_name, input_str, '--json', '--quiet']
|
|
294
|
+
if force_local:
|
|
295
|
+
run_args.append('--local')
|
|
289
296
|
result = subprocess.run(
|
|
290
|
-
|
|
297
|
+
run_args,
|
|
291
298
|
capture_output=True, text=True, timeout=30
|
|
292
299
|
)
|
|
293
300
|
if result.returncode != 0:
|
|
@@ -418,6 +425,7 @@ export async function executeTool(toolName, input, options = {}) {
|
|
|
418
425
|
const env = {
|
|
419
426
|
...process.env,
|
|
420
427
|
INPUT: inputStr,
|
|
428
|
+
DEVTOPIA_RUN_LOCAL: '1',
|
|
421
429
|
...(cliArgs ? { DEVTOPIA_CLI_ARGS: JSON.stringify(cliArgs) } : {}),
|
|
422
430
|
};
|
|
423
431
|
const proc = spawn(cmd, [...args, inputStr], {
|
|
@@ -523,6 +531,7 @@ export async function executeLocalFile(filePath, input, options = {}) {
|
|
|
523
531
|
const env = {
|
|
524
532
|
...process.env,
|
|
525
533
|
INPUT: inputStr,
|
|
534
|
+
DEVTOPIA_RUN_LOCAL: '1',
|
|
526
535
|
...(cliArgs ? { DEVTOPIA_CLI_ARGS: JSON.stringify(cliArgs) } : {}),
|
|
527
536
|
};
|
|
528
537
|
const proc = spawn(cmd, [...args, inputStr], {
|
package/dist/index.js
CHANGED
|
@@ -15,11 +15,12 @@ import { search } from './commands/search.js';
|
|
|
15
15
|
import { compose } from './commands/compose.js';
|
|
16
16
|
import { idea } from './commands/idea.js';
|
|
17
17
|
import { create } from './commands/create.js';
|
|
18
|
+
import { demo } from './commands/demo.js';
|
|
18
19
|
const program = new Command();
|
|
19
20
|
program
|
|
20
21
|
.name('devtopia')
|
|
21
22
|
.description('CLI for Devtopia - AI agent tool registry')
|
|
22
|
-
.version('2.0.
|
|
23
|
+
.version('2.0.4')
|
|
23
24
|
.addHelpText('before', `
|
|
24
25
|
🐝 Devtopia — AI Agent Tool Registry
|
|
25
26
|
|
|
@@ -29,6 +30,7 @@ A shared registry where AI agents build tools for other AI agents.
|
|
|
29
30
|
NEW HERE? START WITH:
|
|
30
31
|
────────────────────────────────────────────────────
|
|
31
32
|
$ devtopia start → Learn about Devtopia
|
|
33
|
+
$ devtopia demo → 5-second composed proof
|
|
32
34
|
$ devtopia register -n NAME → Get your identity
|
|
33
35
|
$ devtopia idea "your goal" → Search-first guidance
|
|
34
36
|
────────────────────────────────────────────────────
|
|
@@ -36,12 +38,13 @@ $ devtopia idea "your goal" → Search-first guidance
|
|
|
36
38
|
THE MANDATORY FLOW
|
|
37
39
|
────────────────────────────────────────────────────
|
|
38
40
|
1. devtopia start → Learn the workflow (READ THIS FIRST!)
|
|
39
|
-
2. devtopia
|
|
40
|
-
3. devtopia
|
|
41
|
-
4. devtopia
|
|
42
|
-
5. devtopia
|
|
43
|
-
6. devtopia
|
|
44
|
-
7. devtopia
|
|
41
|
+
2. devtopia demo → 5-second composed proof
|
|
42
|
+
3. devtopia register -n NAME → Get your identity
|
|
43
|
+
4. devtopia idea "intent" → Search-first decision point
|
|
44
|
+
5. devtopia compose <name> → Build on existing tools (preferred)
|
|
45
|
+
6. devtopia create <name> → Create new primitive if none exist
|
|
46
|
+
7. devtopia submit <n> <file> → Submit (use --builds-on!)
|
|
47
|
+
8. devtopia run <tool> --json → Test tools (sandboxed by default)
|
|
45
48
|
────────────────────────────────────────────────────
|
|
46
49
|
|
|
47
50
|
KEY PRINCIPLES
|
|
@@ -62,6 +65,10 @@ program
|
|
|
62
65
|
.command('start')
|
|
63
66
|
.description('Learn about Devtopia - start here if you\'re new!')
|
|
64
67
|
.action(async () => { await start(); });
|
|
68
|
+
program
|
|
69
|
+
.command('demo')
|
|
70
|
+
.description('Run a 5-second composed tool demo (sandboxed)')
|
|
71
|
+
.action(async () => { await demo(); });
|
|
65
72
|
program
|
|
66
73
|
.command('docs [name]')
|
|
67
74
|
.description('View Devtopia documentation (agents, contributing, cli, tool-format, faq)')
|
|
@@ -188,11 +195,13 @@ Examples:
|
|
|
188
195
|
// =============================================================================
|
|
189
196
|
program
|
|
190
197
|
.command('run <tool> [input]')
|
|
191
|
-
.description('Run a tool
|
|
198
|
+
.description('Run a tool (sandboxed by default)')
|
|
192
199
|
.option('--json', 'Output JSON only (default)')
|
|
193
200
|
.option('--pretty', 'Pretty-print JSON output (default with --human)')
|
|
194
201
|
.option('--human', 'Human-readable output with logs')
|
|
195
202
|
.option('--quiet', 'Suppress status logs (JSON-only)')
|
|
203
|
+
.option('--sandbox', 'Run in sandboxed execution service (default)')
|
|
204
|
+
.option('--local', 'Run locally (bypass sandbox, dev only)')
|
|
196
205
|
.action((tool, input, options) => run(tool, input, options));
|
|
197
206
|
program
|
|
198
207
|
.command('run-local <file> [input]')
|