intella 0.0.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/README.md +303 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +79 -0
- package/scripts/postinstall.cjs +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# Intella AI
|
|
2
|
+
|
|
3
|
+
**Intella** is a universal SDK for running durable AI agents inside isolated sandboxes and delegating tasks to them from your app. It orchestrates multiple agents (Claude, Codex, OpenCode) and runs them across sandbox providers (E2B, Daytona, Modal, Vercel, or your local machine). You can use it to automate tasks like code review, data analysis, docs generation and many more.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
bun add intella
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
or
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install intella
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
or
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
yarn add intella
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Supported Agents
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
| Agent | Description |
|
|
29
|
+
|----------------|-------------|
|
|
30
|
+
| **Claude Code** | Claude via `claude` CLI; auth via `claude login` or `ANTHROPIC_API_KEY`. Default model: sonnet. |
|
|
31
|
+
| **Codex** | Codex CLI; uses OpenAI API key. Default model: gpt-5.2-codex. |
|
|
32
|
+
| **OpenCode** | OpenCode SDK; auth via `opencode login` or `OPENAI_API_KEY` and `ANTHROPIC_API_KEY`. Default model: anthropic/claude-sonnet-4-5-20250929. |
|
|
33
|
+
| **GeminiCode** | Gemini CLI SDK; `In Progress` |
|
|
34
|
+
| **OpenClaw** | ClawdBot API; `In Progress` |
|
|
35
|
+
|
|
36
|
+
See [examples/agents/README.md](./examples/agents/README.md).
|
|
37
|
+
|
|
38
|
+
## Supported sandboxes
|
|
39
|
+
|
|
40
|
+
| Sandbox | Features |
|
|
41
|
+
|----------------------|----------|
|
|
42
|
+
| **E2B** | Code interpreter, template-based sandboxes, Python and JavaScript execution. |
|
|
43
|
+
| **Daytona** | Language-oriented sandboxes (Python, TypeScript, Go, Rust). |
|
|
44
|
+
| **Modal** | Registry image support, secret management. |
|
|
45
|
+
| **Vercel** | Vercel-based sandbox environment. |
|
|
46
|
+
| **Local** | Runs on the current machine; uses current directory as workspace. |
|
|
47
|
+
| **Cloudflare** | Cloudflare sandbox; `In Progress` |
|
|
48
|
+
| **Docker/Firecracker** | Docker/Firecracker sandbox; `In Progress` |
|
|
49
|
+
See [examples/sandbox/README.md](./examples/sandbox/README.md).
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
## Key features
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
- **Multi-agent orchestration** – Run tasks with sequential, parallel, or conditional strategies across agents.
|
|
56
|
+
- **Streaming** – Stream agent responses in real time.
|
|
57
|
+
- **Sandbox lifecycle** – Create, attach to, and close sandboxes; run commands and code inside them.
|
|
58
|
+
- **Sandbox setup** – Install packages (apt, npm, pip, etc.), clone repos, and run setup commands on init.
|
|
59
|
+
- **File operations** – Read, write, upload, and manage files inside sandboxes.
|
|
60
|
+
- **Sessions** – Create and manage sessions; execution history can be persisted for durability.
|
|
61
|
+
- **Durable task delivery** – Task queues and results are durable so work survives restarts.
|
|
62
|
+
|
|
63
|
+
## Durable Agents using Redis Streams
|
|
64
|
+
|
|
65
|
+
Intella uses Redis Streams as the transport layer for task execution and streaming output. Streams provide durable, resumable delivery of commands and results.
|
|
66
|
+
|
|
67
|
+
- **Durable delivery** – Commands and results are persisted in Redis, so work is not lost if a sandbox or daemon restarts.
|
|
68
|
+
- **Resumable processing** – Consumers can resume from the last acknowledged message, enabling reliable recovery.
|
|
69
|
+
- **Scalable fan-out** – Multiple sandboxes can consume work independently without losing ordering within each stream.
|
|
70
|
+
- **Continuous streaming** – Agent output is published incrementally, so clients can stream results in real time.
|
|
71
|
+
_ **Agent executions** – Agents task requests and executions are automatically persisted in Redis and synced back locally if the sandbox is restarted or need to resume sessions.
|
|
72
|
+
|
|
73
|
+
This architecture gives you durable, resumable agent execution with live streaming, backed by Redis.
|
|
74
|
+
|
|
75
|
+
## Using SandboxAgent
|
|
76
|
+
|
|
77
|
+
**SandboxAgent** combines **sandbox** and optional **session** in one flow. Use it when you want a single entry point to create a sandbox and optionally a session (with post-create setup like `runCmd`, `gitClone`, `npmInstall`).
|
|
78
|
+
|
|
79
|
+
**Prerequisites:** `REDIS_URL` (e.g. `redis://localhost:6379`). For local sandbox no API keys; for E2B set `E2B_API_KEY`; for session/agent set `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` as needed.
|
|
80
|
+
|
|
81
|
+
### API overview
|
|
82
|
+
|
|
83
|
+
| Method | Purpose |
|
|
84
|
+
|--------|--------|
|
|
85
|
+
| `SandboxAgent.createSandboxAgent(options)` | Create and initialize a sandbox only. Returns `ISandboxProvider`. |
|
|
86
|
+
| `SandboxAgent.connect(options)` | Create sandbox + optional session; returns a `SandboxAgent` instance with `sandbox`, `session` (and optionally `agent`) set. |
|
|
87
|
+
| `instance.endSession()` | End the current session if any. |
|
|
88
|
+
| `instance.close()` | Close sandbox and clear references. |
|
|
89
|
+
|
|
90
|
+
Options: **redisUrl**, **sandbox** `{ provider, config? }`, **agent** (optional) `{ type: AgentType, config? }`, **session** (optional) `{ sessionId?, postCreate?: SessionInitSetup }` for setup (runCmd, gitClone, npmInstall, etc.).
|
|
91
|
+
|
|
92
|
+
### Sandbox only
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { SandboxAgent, SandboxProviderType } from 'intella';
|
|
96
|
+
|
|
97
|
+
const sandbox = await SandboxAgent.createSandboxAgent({
|
|
98
|
+
redisUrl: process.env.REDIS_URL!,
|
|
99
|
+
sandbox: { provider: SandboxProviderType.LOCAL, config: { env: {} } },
|
|
100
|
+
});
|
|
101
|
+
await sandbox.executeCommand('echo hi');
|
|
102
|
+
await sandbox.close();
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Sandbox + session
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { SandboxAgent, SandboxProviderType, AgentType } from 'intella';
|
|
109
|
+
|
|
110
|
+
const sa = await SandboxAgent.connect({
|
|
111
|
+
redisUrl: process.env.REDIS_URL!,
|
|
112
|
+
sandbox: {
|
|
113
|
+
provider: SandboxProviderType.LOCAL,
|
|
114
|
+
config: { env: { REDIS_URL: process.env.REDIS_URL }, templateId: 'intella-sdk' },
|
|
115
|
+
},
|
|
116
|
+
agent: { type: AgentType.CLAUDE, config: { model: 'sonnet' } },
|
|
117
|
+
session: {
|
|
118
|
+
sessionId: 'my-session',
|
|
119
|
+
postCreate: { runCmd: [{ command: 'echo "ready"' }] },
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
console.log(sa.session?.id);
|
|
123
|
+
await sa.endSession();
|
|
124
|
+
await sa.close();
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Streaming with streamEvents
|
|
128
|
+
|
|
129
|
+
Use `sandbox.streamEvents(StreamEventType.Session, sessionId, options)` to consume agent text chunks from the session stream, or `streamEvents(StreamEventType.Sandbox, sandboxId, { commandId, ... })` for command results from the sandbox results stream.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { SandboxAgent, SandboxProviderType, AgentType, StreamEventType } from 'intella';
|
|
133
|
+
|
|
134
|
+
const sa = await SandboxAgent.connect({ /* redisUrl, sandbox, agent, session */ });
|
|
135
|
+
const sandbox = sa.sandbox!;
|
|
136
|
+
const sessionId = sa.session!.id;
|
|
137
|
+
|
|
138
|
+
// Publish a command, then stream session chunks
|
|
139
|
+
await sandbox.publishCommand({ type: 'agent:execute', sessionId, data: taskRequest, ... }, redisUrl);
|
|
140
|
+
for await (const chunk of sandbox.streamEvents(StreamEventType.Session, sessionId, { redisUrl })) {
|
|
141
|
+
if (chunk.chunk) process.stdout.write(chunk.chunk);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
For full examples (basic-usage, local-usage, with-session-and-setup, stream-events-usage), see the **SandboxAgent** examples in the Intella SDK: `packages/intella-sdk/examples/sandbox-agent/`.
|
|
146
|
+
|
|
147
|
+
### Using sandbox.createSession()
|
|
148
|
+
|
|
149
|
+
Once you have a sandbox (from `Intella.initializeSandbox()` or `SandboxAgent.createSandboxAgent()` / `SandboxAgent.connect()`), create a session with `sandbox.createSession()`. The session runs inside the sandbox and is used for agent execution (e.g. `sandbox.executeAgent()` or `sandbox.publishCommand()` + `streamEvents()`).
|
|
150
|
+
|
|
151
|
+
**Options:** `sessionId?`, `agentType`, `model?`, `metadata?`, `setup?` (`SessionInitSetup`: `runCmd`, `gitClone`, `npmInstall`, etc.).
|
|
152
|
+
|
|
153
|
+
**Minimal:**
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { Intella, SandboxProviderType, AgentType } from 'intella';
|
|
157
|
+
|
|
158
|
+
const intella = new Intella();
|
|
159
|
+
const sandbox = await intella.initializeSandbox(SandboxProviderType.LOCAL, {
|
|
160
|
+
config: { env: { REDIS_URL: process.env.REDIS_URL } },
|
|
161
|
+
});
|
|
162
|
+
await sandbox.ensureDaemonRunning?.();
|
|
163
|
+
|
|
164
|
+
const session = await sandbox.createSession({
|
|
165
|
+
agentType: AgentType.CLAUDE,
|
|
166
|
+
model: 'sonnet',
|
|
167
|
+
});
|
|
168
|
+
console.log('Session:', session.id, session.status);
|
|
169
|
+
|
|
170
|
+
// Later: end session and close sandbox
|
|
171
|
+
await sandbox.endSession(session.id);
|
|
172
|
+
await intella.closeSandbox();
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**With setup (gitClone, runCmd):**
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const session = await sandbox.createSession({
|
|
179
|
+
sessionId: 'my-session',
|
|
180
|
+
agentType: AgentType.CLAUDE,
|
|
181
|
+
model: 'sonnet',
|
|
182
|
+
setup: {
|
|
183
|
+
gitClone: [
|
|
184
|
+
{
|
|
185
|
+
url: 'https://github.com/user/project.git',
|
|
186
|
+
options: { path: '/workspace', branch: 'main', autoInstall: true },
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
runCmd: [
|
|
190
|
+
{ command: 'npm install', options: { path: '/workspace/project' } },
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
metadata: { project: 'my-project' },
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The returned session has a `.close()` method you can call instead of `sandbox.endSession(session.id)`. Related: `sandbox.getSession(sessionId)`, `sandbox.endSession(sessionId)`, `sandbox.runSessionSetup(sessionId, setup)`.
|
|
198
|
+
|
|
199
|
+
## Demo: create a sandbox, clone a repo, run a command
|
|
200
|
+
|
|
201
|
+
Use sandbox setup to clone a repo and run a command:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { Intella, SandboxProviderType } from 'intella';
|
|
205
|
+
|
|
206
|
+
const sdk = new Intella();
|
|
207
|
+
const sandbox = await sdk.initializeSandbox(SandboxProviderType.E2B, {
|
|
208
|
+
templateId: 'base',
|
|
209
|
+
gitClone: [
|
|
210
|
+
{
|
|
211
|
+
url: 'https://github.com/user/project.git',
|
|
212
|
+
options: { path: '/workspace', autoInstall: true },
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
runCmd: [{ command: 'npm test', options: { path: '/workspace/project' } }],
|
|
216
|
+
});
|
|
217
|
+
await sandbox.close();
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Demo: create a session and delegate a task
|
|
221
|
+
|
|
222
|
+
Create a session inside the sandbox and stream agent output with `sandbox.createSession` and `sandbox.executeAgent`:
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { IntellaSDK, SandboxProviderType } from 'intella';
|
|
226
|
+
|
|
227
|
+
const sdk = new IntellaSDK();
|
|
228
|
+
const sandbox = await sdk.initializeSandbox(SandboxProviderType.E2B, {
|
|
229
|
+
templateId: 'base',
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const session = await sandbox.createSession({
|
|
233
|
+
agentType: 'claude',
|
|
234
|
+
model: 'sonnet',
|
|
235
|
+
setup: {
|
|
236
|
+
gitClone: [
|
|
237
|
+
{ url: 'https://github.com/user/project.git', options: { path: '/workspace' } },
|
|
238
|
+
],
|
|
239
|
+
runCmd: [{ command: 'npm install', options: { path: '/workspace/project' } }],
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
for await (const chunk of sandbox.executeAgent(
|
|
244
|
+
{ prompt: 'Summarize the repo and suggest next steps.', sessionId: session.id },
|
|
245
|
+
'claude'
|
|
246
|
+
)) {
|
|
247
|
+
process.stdout.write(chunk.chunk ?? '');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
await sandbox.close();
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Demo: file operations
|
|
254
|
+
|
|
255
|
+
Assuming you already have a `sandbox` instance:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// Create directories and write files
|
|
259
|
+
await sandbox.createDirectory('/workspace/data');
|
|
260
|
+
await sandbox.writeFile('/workspace/data/input.txt', 'hello');
|
|
261
|
+
|
|
262
|
+
// Read and list files
|
|
263
|
+
const text = await sandbox.readFile('/workspace/data/input.txt');
|
|
264
|
+
const files = await sandbox.listFiles('/workspace/data');
|
|
265
|
+
|
|
266
|
+
// Delete a file
|
|
267
|
+
await sandbox.deleteFile('/workspace/data/input.txt');
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Demo: git operations
|
|
271
|
+
|
|
272
|
+
Assuming you already have a `sandbox` instance:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
await sandbox.git.clone('https://github.com/user/project.git', '/workspace', {
|
|
276
|
+
branch: 'main',
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const status = await sandbox.git.status('/workspace/project');
|
|
280
|
+
const branches = await sandbox.git.branches('/workspace/project');
|
|
281
|
+
|
|
282
|
+
await sandbox.git.createBranch('/workspace/project', 'feature/demo');
|
|
283
|
+
await sandbox.git.checkoutBranch('/workspace/project', 'feature/demo');
|
|
284
|
+
await sandbox.git.add('/workspace/project', ['README.md']);
|
|
285
|
+
await sandbox.git.commit(
|
|
286
|
+
'/workspace/project',
|
|
287
|
+
'Update README',
|
|
288
|
+
'Your Name',
|
|
289
|
+
'you@example.com'
|
|
290
|
+
);
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Demo: code operations
|
|
294
|
+
|
|
295
|
+
Assuming you already have a `sandbox` instance:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
const codeResult = await sandbox.runCode('print(2 + 2)', {
|
|
299
|
+
language: 'python3',
|
|
300
|
+
timeout: 30_000,
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,eAAO,MAAM,OAAO,mBAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "intella",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Universal SDK for delegating tasks to durable agents in sandboxes.",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "hi@mielto.com",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/mielto/intellaai.git",
|
|
10
|
+
"directory": "packages/intellaai"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"intella",
|
|
14
|
+
"ai",
|
|
15
|
+
"sdk",
|
|
16
|
+
"agent",
|
|
17
|
+
"sandbox",
|
|
18
|
+
"orchestrator",
|
|
19
|
+
"openai",
|
|
20
|
+
"anthropic",
|
|
21
|
+
"claude",
|
|
22
|
+
"codex",
|
|
23
|
+
"opencode",
|
|
24
|
+
"claude-code"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"module": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"require": "./dist/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./types": {
|
|
37
|
+
"import": "./dist/types.js",
|
|
38
|
+
"types": "./dist/types.d.ts",
|
|
39
|
+
"require": "./dist/types.js"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"README.md",
|
|
45
|
+
"scripts/postinstall.cjs"
|
|
46
|
+
],
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc -p tsconfig.build.json",
|
|
49
|
+
"clean": "rm -rf dist",
|
|
50
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
51
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
52
|
+
"example:basic": "tsx examples/basic-usage.ts",
|
|
53
|
+
"example:local-sandbox": "tsx examples/local-sandbox.ts",
|
|
54
|
+
"example:session": "tsx examples/session-and-agent.ts",
|
|
55
|
+
"example:claude": "tsx examples/agents/claude-agent.ts",
|
|
56
|
+
"example:codex": "tsx examples/agents/codex-agent.ts",
|
|
57
|
+
"example:opencode": "tsx examples/agents/opencode-agent.ts",
|
|
58
|
+
"example:e2b": "tsx examples/sandbox/e2b-usage.ts",
|
|
59
|
+
"example:daytona": "tsx examples/sandbox/daytona-usage.ts",
|
|
60
|
+
"example:modal": "tsx examples/sandbox/modal-usage.ts",
|
|
61
|
+
"example:vercel": "tsx examples/sandbox/vercel-usage.ts",
|
|
62
|
+
"example:local": "tsx examples/sandbox/local-usage.ts"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@intella/sdk": "0.0.8"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@types/bun": "latest",
|
|
69
|
+
"dotenv": "^16.0.0",
|
|
70
|
+
"tsx": "^4.0.0",
|
|
71
|
+
"typescript": "^5.0.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"typescript": "^5.0.0"
|
|
75
|
+
},
|
|
76
|
+
"engines": {
|
|
77
|
+
"node": ">=18.0.0"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
const { spawnSync } = require('node:child_process');
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const os = require('node:os');
|
|
6
|
+
|
|
7
|
+
const CLI_COMMAND = 'intella';
|
|
8
|
+
const CLI_PACKAGE = 'intella-cli';
|
|
9
|
+
|
|
10
|
+
const run = (command, args, options = {}) =>
|
|
11
|
+
spawnSync(command, args, { stdio: 'inherit', ...options });
|
|
12
|
+
|
|
13
|
+
const isCliAvailable = () => {
|
|
14
|
+
const result = spawnSync(CLI_COMMAND, ['--version'], { stdio: 'ignore' });
|
|
15
|
+
return result.status === 0;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const installGlobal = (targetPath) => {
|
|
19
|
+
if (targetPath) {
|
|
20
|
+
return run('npm', ['install', '-g', targetPath]).status === 0;
|
|
21
|
+
}
|
|
22
|
+
return run('npm', ['install', '-g', CLI_PACKAGE]).status === 0;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const installFromTemp = () => {
|
|
26
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'intellaai-cli-'));
|
|
27
|
+
const installResult = run('npm', ['install', CLI_PACKAGE], { cwd: tempDir });
|
|
28
|
+
if (installResult.status !== 0) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const cliPath = path.join(tempDir, 'node_modules', CLI_PACKAGE);
|
|
33
|
+
if (!fs.existsSync(cliPath)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return installGlobal(cliPath);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (isCliAvailable()) {
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('[intellaai] intella CLI not found. Installing globally...');
|
|
45
|
+
|
|
46
|
+
const installed = installGlobal() || installFromTemp();
|
|
47
|
+
if (!installed) {
|
|
48
|
+
console.warn(
|
|
49
|
+
'[intellaai] Failed to install intella CLI automatically. You can try:',
|
|
50
|
+
);
|
|
51
|
+
console.warn(' npm install -g intella-cli');
|
|
52
|
+
}
|