heyatlas 1.2.3 → 1.3.5
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/dist/cli.js +396 -58
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -4815,6 +4815,15 @@ async function pollForToken(deviceCode, interval) {
|
|
|
4815
4815
|
}
|
|
4816
4816
|
}
|
|
4817
4817
|
async function login() {
|
|
4818
|
+
const envToken = process.env.HEYATLAS_ACCESS_TOKEN;
|
|
4819
|
+
const envUserId = process.env.HEYATLAS_USER_ID;
|
|
4820
|
+
if (envToken && envUserId) {
|
|
4821
|
+
return {
|
|
4822
|
+
accessToken: envToken,
|
|
4823
|
+
userId: envUserId,
|
|
4824
|
+
email: "sandbox@heyatlas.app"
|
|
4825
|
+
};
|
|
4826
|
+
}
|
|
4818
4827
|
const existing = loadCredentials();
|
|
4819
4828
|
if (existing) {
|
|
4820
4829
|
return existing;
|
|
@@ -5496,7 +5505,7 @@ var DEFAULT_HOST = "agent.heyatlas.app";
|
|
|
5496
5505
|
class AtlasTunnel {
|
|
5497
5506
|
client = null;
|
|
5498
5507
|
options;
|
|
5499
|
-
agentId = "
|
|
5508
|
+
agentId = "local";
|
|
5500
5509
|
currentUserId = null;
|
|
5501
5510
|
seenTaskIds = new Set;
|
|
5502
5511
|
taskCallback = null;
|
|
@@ -52114,9 +52123,9 @@ _a153 = symbol153;
|
|
|
52114
52123
|
// agents/acp-provider.ts
|
|
52115
52124
|
var ACP_COMMANDS = {
|
|
52116
52125
|
opencode: { command: "opencode", args: ["acp"] },
|
|
52117
|
-
claude: { command: "claude-code-acp", args: [] },
|
|
52126
|
+
"claude-code": { command: "claude-code-acp", args: [] },
|
|
52118
52127
|
goose: { command: "goose", args: ["acp"] },
|
|
52119
|
-
gemini: { command: "gemini", args: ["--experimental-acp"] },
|
|
52128
|
+
"gemini-code": { command: "gemini", args: ["--experimental-acp"] },
|
|
52120
52129
|
codex: { command: "npx", args: ["@zed-industries/codex-acp"] },
|
|
52121
52130
|
kimi: { command: "kimi", args: ["--acp"] },
|
|
52122
52131
|
vibe: { command: "vibe-acp", args: [] },
|
|
@@ -52199,17 +52208,354 @@ class ACPProviderAgent {
|
|
|
52199
52208
|
}
|
|
52200
52209
|
}
|
|
52201
52210
|
|
|
52211
|
+
// agents/config.ts
|
|
52212
|
+
function isSmith(agent) {
|
|
52213
|
+
return agent === "smith";
|
|
52214
|
+
}
|
|
52215
|
+
|
|
52216
|
+
// agents/smith.ts
|
|
52217
|
+
import { spawn as spawn2 } from "child_process";
|
|
52218
|
+
var SANDBOX_BUNDLE_PATH = "/home/user/agents/agent-smith.cjs";
|
|
52219
|
+
var SMITH_CONFIG = {
|
|
52220
|
+
port: 3141,
|
|
52221
|
+
agentId: "workflow-orchestrator",
|
|
52222
|
+
healthPath: "/agents",
|
|
52223
|
+
chatPath: "/agents/workflow-orchestrator/chat",
|
|
52224
|
+
command: "npx",
|
|
52225
|
+
args: ["tsx", "src/index.ts"],
|
|
52226
|
+
cwd: "smith",
|
|
52227
|
+
sandboxCommand: "node",
|
|
52228
|
+
sandboxArgs: [SANDBOX_BUNDLE_PATH]
|
|
52229
|
+
};
|
|
52230
|
+
|
|
52231
|
+
class Smith {
|
|
52232
|
+
options;
|
|
52233
|
+
baseUrl;
|
|
52234
|
+
process = null;
|
|
52235
|
+
constructor(options = {}) {
|
|
52236
|
+
this.options = options;
|
|
52237
|
+
this.baseUrl = `http://localhost:${SMITH_CONFIG.port}`;
|
|
52238
|
+
}
|
|
52239
|
+
get name() {
|
|
52240
|
+
return "smith";
|
|
52241
|
+
}
|
|
52242
|
+
get agentId() {
|
|
52243
|
+
return SMITH_CONFIG.agentId;
|
|
52244
|
+
}
|
|
52245
|
+
get port() {
|
|
52246
|
+
return SMITH_CONFIG.port;
|
|
52247
|
+
}
|
|
52248
|
+
async isRunning() {
|
|
52249
|
+
try {
|
|
52250
|
+
const response = await fetch(`${this.baseUrl}${SMITH_CONFIG.healthPath}`, {
|
|
52251
|
+
method: "GET",
|
|
52252
|
+
signal: AbortSignal.timeout(2000)
|
|
52253
|
+
});
|
|
52254
|
+
return response.ok;
|
|
52255
|
+
} catch {
|
|
52256
|
+
return false;
|
|
52257
|
+
}
|
|
52258
|
+
}
|
|
52259
|
+
async isAvailable() {
|
|
52260
|
+
try {
|
|
52261
|
+
const { promisify } = await import("node:util");
|
|
52262
|
+
const exec = promisify((await import("node:child_process")).exec);
|
|
52263
|
+
await exec("which npx || where npx");
|
|
52264
|
+
return true;
|
|
52265
|
+
} catch {
|
|
52266
|
+
return false;
|
|
52267
|
+
}
|
|
52268
|
+
}
|
|
52269
|
+
async isSandboxMode() {
|
|
52270
|
+
try {
|
|
52271
|
+
const fs = await import("node:fs/promises");
|
|
52272
|
+
await fs.access(SANDBOX_BUNDLE_PATH);
|
|
52273
|
+
return true;
|
|
52274
|
+
} catch {
|
|
52275
|
+
return false;
|
|
52276
|
+
}
|
|
52277
|
+
}
|
|
52278
|
+
async start() {
|
|
52279
|
+
if (await this.isRunning()) {
|
|
52280
|
+
console.log(`[smith] Server already running on port ${SMITH_CONFIG.port}`);
|
|
52281
|
+
return;
|
|
52282
|
+
}
|
|
52283
|
+
const isSandbox = await this.isSandboxMode();
|
|
52284
|
+
let command;
|
|
52285
|
+
let args;
|
|
52286
|
+
let cwd;
|
|
52287
|
+
if (isSandbox) {
|
|
52288
|
+
command = SMITH_CONFIG.sandboxCommand;
|
|
52289
|
+
args = SMITH_CONFIG.sandboxArgs;
|
|
52290
|
+
cwd = "/home/user/agents";
|
|
52291
|
+
console.log(`[smith] Running in sandbox mode with pre-built bundle`);
|
|
52292
|
+
} else {
|
|
52293
|
+
const baseCwd = this.options.cwd || process.cwd();
|
|
52294
|
+
const path = await import("node:path");
|
|
52295
|
+
const fs = await import("node:fs/promises");
|
|
52296
|
+
let smithPath = path.join(baseCwd, SMITH_CONFIG.cwd);
|
|
52297
|
+
try {
|
|
52298
|
+
await fs.access(smithPath);
|
|
52299
|
+
} catch {
|
|
52300
|
+
smithPath = path.join(baseCwd, "..", SMITH_CONFIG.cwd);
|
|
52301
|
+
}
|
|
52302
|
+
command = SMITH_CONFIG.command;
|
|
52303
|
+
args = SMITH_CONFIG.args;
|
|
52304
|
+
cwd = smithPath;
|
|
52305
|
+
console.log(`[smith] Running in development mode from: ${cwd}`);
|
|
52306
|
+
}
|
|
52307
|
+
const env = {
|
|
52308
|
+
...process.env,
|
|
52309
|
+
PORT: String(SMITH_CONFIG.port)
|
|
52310
|
+
};
|
|
52311
|
+
this.process = spawn2(command, args, {
|
|
52312
|
+
cwd,
|
|
52313
|
+
env,
|
|
52314
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
52315
|
+
shell: true
|
|
52316
|
+
});
|
|
52317
|
+
this.process.stdout?.on("data", (data) => {
|
|
52318
|
+
console.log(`[smith] ${data.toString().trim()}`);
|
|
52319
|
+
});
|
|
52320
|
+
this.process.stderr?.on("data", (data) => {
|
|
52321
|
+
console.error(`[smith] ${data.toString().trim()}`);
|
|
52322
|
+
});
|
|
52323
|
+
this.process.on("error", (err) => {
|
|
52324
|
+
console.error(`[smith] Process error:`, err.message);
|
|
52325
|
+
});
|
|
52326
|
+
await this.waitForReady();
|
|
52327
|
+
}
|
|
52328
|
+
async waitForReady(maxAttempts = 60) {
|
|
52329
|
+
const delay2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
52330
|
+
for (let i = 0;i < maxAttempts; i++) {
|
|
52331
|
+
if (await this.isRunning()) {
|
|
52332
|
+
return;
|
|
52333
|
+
}
|
|
52334
|
+
await delay2(1000);
|
|
52335
|
+
}
|
|
52336
|
+
throw new Error(`Smith failed to start after ${maxAttempts}s`);
|
|
52337
|
+
}
|
|
52338
|
+
stop() {
|
|
52339
|
+
if (this.process) {
|
|
52340
|
+
this.process.kill("SIGTERM");
|
|
52341
|
+
this.process = null;
|
|
52342
|
+
}
|
|
52343
|
+
}
|
|
52344
|
+
async* streamChat(prompt) {
|
|
52345
|
+
const response = await fetch(`${this.baseUrl}${SMITH_CONFIG.chatPath}`, {
|
|
52346
|
+
method: "POST",
|
|
52347
|
+
headers: { "Content-Type": "application/json" },
|
|
52348
|
+
body: JSON.stringify({
|
|
52349
|
+
messages: [{ role: "user", content: prompt }]
|
|
52350
|
+
})
|
|
52351
|
+
});
|
|
52352
|
+
if (!response.ok) {
|
|
52353
|
+
throw new Error(`Chat request failed: ${response.statusText}`);
|
|
52354
|
+
}
|
|
52355
|
+
const reader = response.body?.getReader();
|
|
52356
|
+
if (!reader) {
|
|
52357
|
+
throw new Error("No response body");
|
|
52358
|
+
}
|
|
52359
|
+
const decoder = new TextDecoder;
|
|
52360
|
+
let buffer = "";
|
|
52361
|
+
while (true) {
|
|
52362
|
+
const { done, value } = await reader.read();
|
|
52363
|
+
if (done)
|
|
52364
|
+
break;
|
|
52365
|
+
buffer += decoder.decode(value, { stream: true });
|
|
52366
|
+
const lines = buffer.split(`
|
|
52367
|
+
`);
|
|
52368
|
+
buffer = lines.pop() || "";
|
|
52369
|
+
for (const line of lines) {
|
|
52370
|
+
const trimmed = line.trim();
|
|
52371
|
+
if (!trimmed)
|
|
52372
|
+
continue;
|
|
52373
|
+
let jsonStr = null;
|
|
52374
|
+
if (trimmed.startsWith("data: ")) {
|
|
52375
|
+
jsonStr = trimmed.slice(6);
|
|
52376
|
+
} else if (/^\d+:/.test(trimmed)) {
|
|
52377
|
+
const colonIndex = trimmed.indexOf(":");
|
|
52378
|
+
jsonStr = trimmed.slice(colonIndex + 1);
|
|
52379
|
+
}
|
|
52380
|
+
if (jsonStr && jsonStr !== "[DONE]") {
|
|
52381
|
+
try {
|
|
52382
|
+
const event = JSON.parse(jsonStr);
|
|
52383
|
+
yield event;
|
|
52384
|
+
} catch {}
|
|
52385
|
+
}
|
|
52386
|
+
}
|
|
52387
|
+
}
|
|
52388
|
+
}
|
|
52389
|
+
}
|
|
52390
|
+
|
|
52202
52391
|
// commands/connect.ts
|
|
52203
52392
|
async function connect(agentType, options = {}) {
|
|
52204
52393
|
const credentials = await login();
|
|
52205
|
-
if (
|
|
52206
|
-
|
|
52207
|
-
|
|
52394
|
+
if (isSmith(agentType)) {
|
|
52395
|
+
return connectSmith(credentials, options);
|
|
52396
|
+
}
|
|
52397
|
+
if (isACPAgent(agentType)) {
|
|
52398
|
+
return connectACPAgent(agentType, credentials, options);
|
|
52399
|
+
}
|
|
52400
|
+
console.error(`Error: Unknown agent type '${agentType}'`);
|
|
52401
|
+
process.exit(1);
|
|
52402
|
+
}
|
|
52403
|
+
async function connectSmith(credentials, options) {
|
|
52404
|
+
const agent = new Smith({ cwd: process.cwd() });
|
|
52405
|
+
const available = await agent.isAvailable();
|
|
52406
|
+
if (!available) {
|
|
52407
|
+
console.error("Error: npx not found. Install Node.js to use smith");
|
|
52408
|
+
process.exit(1);
|
|
52409
|
+
}
|
|
52410
|
+
console.log("Agent: smith");
|
|
52411
|
+
try {
|
|
52412
|
+
console.log("Starting smith server...");
|
|
52413
|
+
await agent.start();
|
|
52414
|
+
console.log(`Smith server running on port ${agent.port}`);
|
|
52415
|
+
} catch (error87) {
|
|
52416
|
+
console.error(`Failed to start agent: ${error87}`);
|
|
52208
52417
|
process.exit(1);
|
|
52209
52418
|
}
|
|
52210
|
-
const
|
|
52211
|
-
|
|
52419
|
+
const tunnel = new AtlasTunnel({
|
|
52420
|
+
host: process.env.ATLAS_AGENT_HOST || "agent.heyatlas.app",
|
|
52421
|
+
token: credentials.accessToken,
|
|
52422
|
+
interactive: true
|
|
52423
|
+
});
|
|
52424
|
+
tunnel.onNewTask(async (task) => {
|
|
52425
|
+
const { prompt, latestUserMessage } = buildPromptWithContext(task);
|
|
52426
|
+
const isNewTask = task.state === "new";
|
|
52427
|
+
console.log(`${isNewTask ? "New" : "Continue"}: ${latestUserMessage.slice(0, 50)}...`);
|
|
52428
|
+
await tunnel.updateTask(task.id, { state: "in-progress" });
|
|
52429
|
+
await tunnel.appendContext(task.id, [
|
|
52430
|
+
{
|
|
52431
|
+
type: "message",
|
|
52432
|
+
timestamp: Date.now(),
|
|
52433
|
+
data: { role: "user", content: latestUserMessage }
|
|
52434
|
+
}
|
|
52435
|
+
]);
|
|
52436
|
+
try {
|
|
52437
|
+
const parts = [];
|
|
52438
|
+
const toolCalls = new Map;
|
|
52439
|
+
const activeReasoningParts = new Map;
|
|
52440
|
+
for await (const chunk of agent.streamChat(prompt)) {
|
|
52441
|
+
await tunnel.broadcastTaskEvent(task.id, {
|
|
52442
|
+
type: "ui_stream_chunk",
|
|
52443
|
+
timestamp: Date.now(),
|
|
52444
|
+
data: chunk
|
|
52445
|
+
});
|
|
52446
|
+
switch (chunk.type) {
|
|
52447
|
+
case "text-delta": {
|
|
52448
|
+
const existingText = parts.find((p) => p.type === "text");
|
|
52449
|
+
if (existingText && "text" in existingText) {
|
|
52450
|
+
existingText.text += chunk.delta || "";
|
|
52451
|
+
} else {
|
|
52452
|
+
parts.push({ type: "text", text: chunk.delta || "" });
|
|
52453
|
+
}
|
|
52454
|
+
break;
|
|
52455
|
+
}
|
|
52456
|
+
case "reasoning-start": {
|
|
52457
|
+
const reasoningPart = {
|
|
52458
|
+
type: "reasoning",
|
|
52459
|
+
text: "",
|
|
52460
|
+
state: "streaming"
|
|
52461
|
+
};
|
|
52462
|
+
activeReasoningParts.set(chunk.id || "default", reasoningPart);
|
|
52463
|
+
parts.push(reasoningPart);
|
|
52464
|
+
break;
|
|
52465
|
+
}
|
|
52466
|
+
case "reasoning-delta":
|
|
52467
|
+
case "reasoning": {
|
|
52468
|
+
const id = chunk.id || "default";
|
|
52469
|
+
let reasoningPart = activeReasoningParts.get(id);
|
|
52470
|
+
if (!reasoningPart) {
|
|
52471
|
+
reasoningPart = { type: "reasoning", text: "", state: "streaming" };
|
|
52472
|
+
activeReasoningParts.set(id, reasoningPart);
|
|
52473
|
+
parts.push(reasoningPart);
|
|
52474
|
+
}
|
|
52475
|
+
reasoningPart.text += chunk.delta || chunk.text || "";
|
|
52476
|
+
break;
|
|
52477
|
+
}
|
|
52478
|
+
case "reasoning-end": {
|
|
52479
|
+
const id = chunk.id || "default";
|
|
52480
|
+
const reasoningPart = activeReasoningParts.get(id);
|
|
52481
|
+
if (reasoningPart) {
|
|
52482
|
+
reasoningPart.state = "done";
|
|
52483
|
+
activeReasoningParts.delete(id);
|
|
52484
|
+
}
|
|
52485
|
+
break;
|
|
52486
|
+
}
|
|
52487
|
+
case "tool-input-available": {
|
|
52488
|
+
const input = chunk.input;
|
|
52489
|
+
const realToolName = input?.toolName || chunk.toolName || "tool";
|
|
52490
|
+
const realArgs = input?.args || input || {};
|
|
52491
|
+
toolCalls.set(chunk.toolCallId || "", {
|
|
52492
|
+
type: "dynamic-tool",
|
|
52493
|
+
toolCallId: chunk.toolCallId,
|
|
52494
|
+
toolName: realToolName,
|
|
52495
|
+
state: "input-available",
|
|
52496
|
+
input: realArgs,
|
|
52497
|
+
subAgentName: chunk.subAgentName
|
|
52498
|
+
});
|
|
52499
|
+
parts.push(toolCalls.get(chunk.toolCallId || ""));
|
|
52500
|
+
break;
|
|
52501
|
+
}
|
|
52502
|
+
case "tool-output-available": {
|
|
52503
|
+
const existing = toolCalls.get(chunk.toolCallId || "");
|
|
52504
|
+
if (existing) {
|
|
52505
|
+
const updated = { ...existing, state: "output-available", output: chunk.output };
|
|
52506
|
+
toolCalls.set(chunk.toolCallId || "", updated);
|
|
52507
|
+
const idx = parts.findIndex((p) => p.type === "dynamic-tool" && p.toolCallId === chunk.toolCallId);
|
|
52508
|
+
if (idx >= 0)
|
|
52509
|
+
parts[idx] = updated;
|
|
52510
|
+
}
|
|
52511
|
+
break;
|
|
52512
|
+
}
|
|
52513
|
+
}
|
|
52514
|
+
}
|
|
52515
|
+
if (parts.length > 0) {
|
|
52516
|
+
await tunnel.appendContext(task.id, [
|
|
52517
|
+
{
|
|
52518
|
+
type: "ui_message",
|
|
52519
|
+
timestamp: Date.now(),
|
|
52520
|
+
data: { id: crypto.randomUUID(), role: "assistant", parts }
|
|
52521
|
+
}
|
|
52522
|
+
]);
|
|
52523
|
+
}
|
|
52524
|
+
await tunnel.updateTask(task.id, { state: "completed", result: "end_turn" });
|
|
52525
|
+
console.log("Task completed");
|
|
52526
|
+
} catch (error87) {
|
|
52527
|
+
console.error(`Task failed: ${error87}`);
|
|
52528
|
+
await tunnel.updateTask(task.id, { state: "failed", result: String(error87) });
|
|
52529
|
+
}
|
|
52530
|
+
});
|
|
52531
|
+
await tunnel.connect(credentials.userId, "smith");
|
|
52532
|
+
console.log("Tunnel established");
|
|
52533
|
+
const voiceUrl = `${process.env.HEYATLAS_API || "https://heyatlas.app"}/chat`;
|
|
52534
|
+
if (options.openBrowser !== false) {
|
|
52535
|
+
try {
|
|
52536
|
+
const { execSync } = await import("child_process");
|
|
52537
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? 'start ""' : "xdg-open";
|
|
52538
|
+
execSync(`${cmd} "${voiceUrl}"`, { stdio: "ignore" });
|
|
52539
|
+
} catch {}
|
|
52540
|
+
}
|
|
52541
|
+
console.log(`
|
|
52542
|
+
HeyAtlas connected to smith`);
|
|
52543
|
+
console.log(`Continue here: ${voiceUrl}`);
|
|
52544
|
+
console.log(`
|
|
52545
|
+
Press Ctrl+C to disconnect
|
|
52546
|
+
`);
|
|
52547
|
+
process.on("SIGINT", async () => {
|
|
52548
|
+
console.log(`
|
|
52549
|
+
Disconnecting...
|
|
52550
|
+
`);
|
|
52551
|
+
agent.stop();
|
|
52552
|
+
await tunnel.disconnect();
|
|
52553
|
+
process.exit(0);
|
|
52212
52554
|
});
|
|
52555
|
+
await new Promise(() => {});
|
|
52556
|
+
}
|
|
52557
|
+
async function connectACPAgent(agentType, credentials, options) {
|
|
52558
|
+
const agent = new ACPProviderAgent(agentType, { cwd: process.cwd() });
|
|
52213
52559
|
const available = await agent.isAvailable();
|
|
52214
52560
|
if (!available) {
|
|
52215
52561
|
const cmd = getACPCommand(agentType);
|
|
@@ -52220,7 +52566,7 @@ async function connect(agentType, options = {}) {
|
|
|
52220
52566
|
console.log(`Agent: ${agentType} (via ACP AI Provider)`);
|
|
52221
52567
|
try {
|
|
52222
52568
|
await agent.init();
|
|
52223
|
-
console.log(
|
|
52569
|
+
console.log("ACP provider initialized");
|
|
52224
52570
|
} catch (error87) {
|
|
52225
52571
|
console.error(`Failed to initialize agent: ${error87}`);
|
|
52226
52572
|
process.exit(1);
|
|
@@ -52269,49 +52615,56 @@ async function connect(agentType, options = {}) {
|
|
|
52269
52615
|
text: "",
|
|
52270
52616
|
state: "streaming"
|
|
52271
52617
|
};
|
|
52272
|
-
activeReasoningParts.set(chunk.id, reasoningPart);
|
|
52618
|
+
activeReasoningParts.set(chunk.id || "default", reasoningPart);
|
|
52273
52619
|
parts.push(reasoningPart);
|
|
52274
52620
|
break;
|
|
52275
52621
|
}
|
|
52276
|
-
case "reasoning-delta":
|
|
52277
|
-
|
|
52278
|
-
|
|
52279
|
-
|
|
52622
|
+
case "reasoning-delta":
|
|
52623
|
+
case "reasoning": {
|
|
52624
|
+
const id = chunk.id || "default";
|
|
52625
|
+
let reasoningPart = activeReasoningParts.get(id);
|
|
52626
|
+
if (!reasoningPart) {
|
|
52627
|
+
reasoningPart = { type: "reasoning", text: "", state: "streaming" };
|
|
52628
|
+
activeReasoningParts.set(id, reasoningPart);
|
|
52629
|
+
parts.push(reasoningPart);
|
|
52280
52630
|
}
|
|
52631
|
+
reasoningPart.text += chunk.delta || chunk.text || "";
|
|
52281
52632
|
break;
|
|
52282
52633
|
}
|
|
52283
52634
|
case "reasoning-end": {
|
|
52284
|
-
const
|
|
52635
|
+
const id = chunk.id || "default";
|
|
52636
|
+
const reasoningPart = activeReasoningParts.get(id);
|
|
52285
52637
|
if (reasoningPart) {
|
|
52286
52638
|
reasoningPart.state = "done";
|
|
52287
|
-
activeReasoningParts.delete(
|
|
52639
|
+
activeReasoningParts.delete(id);
|
|
52288
52640
|
}
|
|
52289
52641
|
break;
|
|
52290
52642
|
}
|
|
52291
|
-
case "tool-input-available":
|
|
52643
|
+
case "tool-input-available": {
|
|
52644
|
+
const input = chunk.input;
|
|
52645
|
+
const realToolName = input?.toolName || chunk.toolName;
|
|
52646
|
+
const realArgs = input?.args || input || {};
|
|
52292
52647
|
toolCalls.set(chunk.toolCallId, {
|
|
52293
52648
|
type: "dynamic-tool",
|
|
52294
52649
|
toolCallId: chunk.toolCallId,
|
|
52295
|
-
toolName:
|
|
52650
|
+
toolName: realToolName,
|
|
52296
52651
|
state: "input-available",
|
|
52297
|
-
input:
|
|
52652
|
+
input: realArgs
|
|
52298
52653
|
});
|
|
52299
52654
|
parts.push(toolCalls.get(chunk.toolCallId));
|
|
52300
52655
|
break;
|
|
52301
|
-
|
|
52656
|
+
}
|
|
52657
|
+
case "tool-output-available": {
|
|
52302
52658
|
const existing = toolCalls.get(chunk.toolCallId);
|
|
52303
52659
|
if (existing) {
|
|
52304
|
-
const updated = {
|
|
52305
|
-
...existing,
|
|
52306
|
-
state: "output-available",
|
|
52307
|
-
output: chunk.output
|
|
52308
|
-
};
|
|
52660
|
+
const updated = { ...existing, state: "output-available", output: chunk.output };
|
|
52309
52661
|
toolCalls.set(chunk.toolCallId, updated);
|
|
52310
52662
|
const idx = parts.findIndex((p) => p.type === "dynamic-tool" && p.toolCallId === chunk.toolCallId);
|
|
52311
52663
|
if (idx >= 0)
|
|
52312
52664
|
parts[idx] = updated;
|
|
52313
52665
|
}
|
|
52314
52666
|
break;
|
|
52667
|
+
}
|
|
52315
52668
|
}
|
|
52316
52669
|
}
|
|
52317
52670
|
if (parts.length > 0) {
|
|
@@ -52319,29 +52672,19 @@ async function connect(agentType, options = {}) {
|
|
|
52319
52672
|
{
|
|
52320
52673
|
type: "ui_message",
|
|
52321
52674
|
timestamp: Date.now(),
|
|
52322
|
-
data: {
|
|
52323
|
-
id: crypto.randomUUID(),
|
|
52324
|
-
role: "assistant",
|
|
52325
|
-
parts
|
|
52326
|
-
}
|
|
52675
|
+
data: { id: crypto.randomUUID(), role: "assistant", parts }
|
|
52327
52676
|
}
|
|
52328
52677
|
]);
|
|
52329
52678
|
}
|
|
52330
|
-
await tunnel.updateTask(task.id, {
|
|
52331
|
-
|
|
52332
|
-
result: "end_turn"
|
|
52333
|
-
});
|
|
52334
|
-
console.log(`Task completed`);
|
|
52679
|
+
await tunnel.updateTask(task.id, { state: "completed", result: "end_turn" });
|
|
52680
|
+
console.log("Task completed");
|
|
52335
52681
|
} catch (error87) {
|
|
52336
52682
|
console.error(`Task failed: ${error87}`);
|
|
52337
|
-
await tunnel.updateTask(task.id, {
|
|
52338
|
-
state: "failed",
|
|
52339
|
-
result: String(error87)
|
|
52340
|
-
});
|
|
52683
|
+
await tunnel.updateTask(task.id, { state: "failed", result: String(error87) });
|
|
52341
52684
|
}
|
|
52342
52685
|
});
|
|
52343
52686
|
await tunnel.connect(credentials.userId, agentType);
|
|
52344
|
-
console.log(
|
|
52687
|
+
console.log("Tunnel established");
|
|
52345
52688
|
const voiceUrl = `${process.env.HEYATLAS_API || "https://heyatlas.app"}/chat`;
|
|
52346
52689
|
if (options.openBrowser !== false) {
|
|
52347
52690
|
try {
|
|
@@ -52386,10 +52729,7 @@ function buildPromptWithContext(task) {
|
|
|
52386
52729
|
} else if (e.type === "message" && e.data) {
|
|
52387
52730
|
const data = e.data;
|
|
52388
52731
|
if (data.role && data.content) {
|
|
52389
|
-
messages.push({
|
|
52390
|
-
role: String(data.role),
|
|
52391
|
-
content: String(data.content)
|
|
52392
|
-
});
|
|
52732
|
+
messages.push({ role: String(data.role), content: String(data.content) });
|
|
52393
52733
|
}
|
|
52394
52734
|
} else if (e.role && e.content) {
|
|
52395
52735
|
messages.push({ role: String(e.role), content: String(e.content) });
|
|
@@ -52421,11 +52761,11 @@ Please continue based on the above context.`;
|
|
|
52421
52761
|
}
|
|
52422
52762
|
|
|
52423
52763
|
// index.ts
|
|
52424
|
-
var
|
|
52764
|
+
var ACP_AGENTS = [
|
|
52425
52765
|
"opencode",
|
|
52426
|
-
"claude",
|
|
52766
|
+
"claude-code",
|
|
52427
52767
|
"goose",
|
|
52428
|
-
"gemini",
|
|
52768
|
+
"gemini-code",
|
|
52429
52769
|
"codex",
|
|
52430
52770
|
"kimi",
|
|
52431
52771
|
"vibe",
|
|
@@ -52434,6 +52774,8 @@ var SUPPORTED_AGENTS = [
|
|
|
52434
52774
|
"openhands",
|
|
52435
52775
|
"cagent"
|
|
52436
52776
|
];
|
|
52777
|
+
var SMITH_AGENTS = ["smith"];
|
|
52778
|
+
var SUPPORTED_AGENTS = [...ACP_AGENTS, ...SMITH_AGENTS];
|
|
52437
52779
|
var { positionals, values } = parseArgs({
|
|
52438
52780
|
args: process.argv.slice(2),
|
|
52439
52781
|
options: {
|
|
@@ -52445,27 +52787,23 @@ var { positionals, values } = parseArgs({
|
|
|
52445
52787
|
});
|
|
52446
52788
|
function printHelp() {
|
|
52447
52789
|
console.log(`
|
|
52448
|
-
heyatlas - Tunnel local AI agents to the cloud
|
|
52790
|
+
heyatlas - Tunnel local AI agents to the cloud
|
|
52449
52791
|
|
|
52450
52792
|
Usage:
|
|
52451
|
-
heyatlas connect <agent> Connect agent to Atlas
|
|
52793
|
+
heyatlas connect <agent> Connect agent to Atlas
|
|
52452
52794
|
|
|
52453
|
-
|
|
52454
|
-
${
|
|
52795
|
+
Supported Agents:
|
|
52796
|
+
ACP Agents: ${ACP_AGENTS.join(", ")}
|
|
52797
|
+
Smith: ${SMITH_AGENTS.join(", ")}
|
|
52455
52798
|
|
|
52456
52799
|
Options:
|
|
52457
52800
|
-h, --help Show this help message
|
|
52458
52801
|
-v, --version Show version
|
|
52459
52802
|
--no-browser Don't open browser automatically
|
|
52460
52803
|
|
|
52461
|
-
Prerequisites:
|
|
52462
|
-
- The agent must be installed and support ACP mode
|
|
52463
|
-
- Agent-specific setup (API keys, etc.)
|
|
52464
|
-
|
|
52465
52804
|
Examples:
|
|
52466
|
-
heyatlas connect opencode
|
|
52467
|
-
heyatlas connect
|
|
52468
|
-
heyatlas connect claude Connect Claude Code via ACP
|
|
52805
|
+
heyatlas connect opencode Connect OpenCode via ACP
|
|
52806
|
+
heyatlas connect smith Connect Smith
|
|
52469
52807
|
`);
|
|
52470
52808
|
}
|
|
52471
52809
|
async function main() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "heyatlas",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"description": "Tunnel local AI agents to the cloud for voice-powered interactions",
|
|
5
5
|
"author": "Bishwendu Kundu <bishwenduk029@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,4 +50,4 @@
|
|
|
50
50
|
"engines": {
|
|
51
51
|
"node": ">=18.0.0"
|
|
52
52
|
}
|
|
53
|
-
}
|
|
53
|
+
}
|