@todoforai/cli 0.1.42 → 0.1.43
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 +1 -1
- package/dist/todoforai-cli.js +37 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ Pick **TODOforAI** from the agent dropdown in AI Chat.
|
|
|
97
97
|
|
|
98
98
|
**VS Code** — no built-in ACP client yet; install a community ACP client extension (e.g. [`strato-space.acp-plugin`](https://marketplace.visualstudio.com/items?itemName=strato-space.acp-plugin)) and add the same `agent_servers` entry to `settings.json`.
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
`--agent`, `--project` and `--api-url` apply to `acp` as well (e.g. `"args": ["acp", "--agent", "backend"]`). If `todoforai-cli` is not on the editor's `PATH`, use its absolute path (`which todoforai-cli`).
|
|
101
101
|
|
|
102
102
|
## All Options
|
|
103
103
|
|
package/dist/todoforai-cli.js
CHANGED
|
@@ -43177,8 +43177,7 @@ class FrontendWebSocket {
|
|
|
43177
43177
|
});
|
|
43178
43178
|
this.ws.on("close", () => {
|
|
43179
43179
|
this.connected = false;
|
|
43180
|
-
|
|
43181
|
-
ev.resolve({ type: "socket:closed", payload: { todoId, status: "DISCONNECTED" }, success: false });
|
|
43180
|
+
this.settleAll();
|
|
43182
43181
|
});
|
|
43183
43182
|
this.ws.on("error", (err) => {
|
|
43184
43183
|
log("error", "WS error:", err.message);
|
|
@@ -43187,8 +43186,13 @@ class FrontendWebSocket {
|
|
|
43187
43186
|
});
|
|
43188
43187
|
});
|
|
43189
43188
|
}
|
|
43189
|
+
settleAll() {
|
|
43190
|
+
for (const [todoId, ev] of [...this.completionEvents])
|
|
43191
|
+
ev.resolve({ type: "socket:closed", payload: { todoId, status: "DISCONNECTED" }, success: false });
|
|
43192
|
+
}
|
|
43190
43193
|
async close() {
|
|
43191
43194
|
this.connected = false;
|
|
43195
|
+
this.settleAll();
|
|
43192
43196
|
this.ws?.close();
|
|
43193
43197
|
this.ws = null;
|
|
43194
43198
|
this.callbacks.clear();
|
|
@@ -43197,6 +43201,10 @@ class FrontendWebSocket {
|
|
|
43197
43201
|
this.pendingBlocks.clear();
|
|
43198
43202
|
this.lastReadyPayload.clear();
|
|
43199
43203
|
}
|
|
43204
|
+
forget(todoId) {
|
|
43205
|
+
for (const m of [this.callbacks, this.completionEvents, this.completionResults, this.pendingBlocks, this.lastReadyPayload])
|
|
43206
|
+
m.delete(todoId);
|
|
43207
|
+
}
|
|
43200
43208
|
handleMessage(data) {
|
|
43201
43209
|
const msgType = data.type || "";
|
|
43202
43210
|
const payload = data.payload || {};
|
|
@@ -43326,11 +43334,14 @@ class FrontendWebSocket {
|
|
|
43326
43334
|
if (!await this.subscribe(todoId, callback)) {
|
|
43327
43335
|
throw new Error(`Failed to subscribe to todo ${todoId}`);
|
|
43328
43336
|
}
|
|
43337
|
+
return this.completion(todoId);
|
|
43338
|
+
}
|
|
43339
|
+
completion(todoId) {
|
|
43329
43340
|
const early = this.completionResults.get(todoId);
|
|
43330
43341
|
if (early) {
|
|
43331
43342
|
this.completionResults.delete(todoId);
|
|
43332
43343
|
this.callbacks.delete(todoId);
|
|
43333
|
-
return early;
|
|
43344
|
+
return Promise.resolve(early);
|
|
43334
43345
|
}
|
|
43335
43346
|
return new Promise((resolve) => {
|
|
43336
43347
|
this.completionEvents.set(todoId, {
|
|
@@ -44429,7 +44440,7 @@ import { parseArgs } from "util";
|
|
|
44429
44440
|
// package.json
|
|
44430
44441
|
var package_default = {
|
|
44431
44442
|
name: "@todoforai/cli",
|
|
44432
|
-
version: "0.1.
|
|
44443
|
+
version: "0.1.43",
|
|
44433
44444
|
type: "module",
|
|
44434
44445
|
bin: {
|
|
44435
44446
|
"todoforai-cli": "bin/todoforai-cli.js",
|
|
@@ -52549,12 +52560,14 @@ class TodoforaiAgent {
|
|
|
52549
52560
|
api;
|
|
52550
52561
|
ws;
|
|
52551
52562
|
projectId;
|
|
52563
|
+
agentQuery;
|
|
52552
52564
|
sessions = new Map;
|
|
52553
|
-
constructor(conn, api, ws, projectId) {
|
|
52565
|
+
constructor(conn, api, ws, projectId, agentQuery) {
|
|
52554
52566
|
this.conn = conn;
|
|
52555
52567
|
this.api = api;
|
|
52556
52568
|
this.ws = ws;
|
|
52557
52569
|
this.projectId = projectId;
|
|
52570
|
+
this.agentQuery = agentQuery;
|
|
52558
52571
|
}
|
|
52559
52572
|
async initialize() {
|
|
52560
52573
|
return { protocolVersion: PROTOCOL_VERSION, agentCapabilities: { promptCapabilities: { embeddedContext: true } }, authMethods: [] };
|
|
@@ -52569,10 +52582,19 @@ class TodoforaiAgent {
|
|
|
52569
52582
|
throw RequestError.internalError("no project on this account");
|
|
52570
52583
|
return this.projectId = id;
|
|
52571
52584
|
}
|
|
52585
|
+
async resolveAgent(cwd) {
|
|
52586
|
+
if (this.agentQuery) {
|
|
52587
|
+
const { match, ambiguous } = resolveAgentMatch(await this.api.listAgentSettings(), this.agentQuery);
|
|
52588
|
+
if (!match)
|
|
52589
|
+
throw RequestError.invalidParams(`agent '${this.agentQuery}' ${ambiguous?.length ? "is ambiguous" : "not found"}`);
|
|
52590
|
+
return match;
|
|
52591
|
+
}
|
|
52592
|
+
return (await this.api.listAgentSettings({ workspacePath: cwd }))[0] ?? await autoCreateAgent(this.api, cwd);
|
|
52593
|
+
}
|
|
52572
52594
|
async newSession(p) {
|
|
52573
52595
|
const projectId = await this.resolveProject();
|
|
52574
52596
|
const cwd = realpathSync(p.cwd);
|
|
52575
|
-
const agent =
|
|
52597
|
+
const agent = await this.resolveAgent(cwd);
|
|
52576
52598
|
const todoId = crypto.randomUUID();
|
|
52577
52599
|
this.sessions.set(todoId, { todoId, projectId, agent });
|
|
52578
52600
|
log2(`session ${todoId} agent=${agent.name} cwd=${cwd}`);
|
|
@@ -52672,13 +52694,17 @@ ${b.resource.text}
|
|
|
52672
52694
|
};
|
|
52673
52695
|
try {
|
|
52674
52696
|
const msg = await this.api.addMessage(s.projectId, text, s.agent, s.todoId, undefined, NEVER_SCHEDULED_TIMESTAMP);
|
|
52675
|
-
|
|
52697
|
+
if (!await this.ws.subscribe(s.todoId, onEvent))
|
|
52698
|
+
throw new Error("subscribe failed");
|
|
52699
|
+
const done = this.ws.completion(s.todoId);
|
|
52676
52700
|
if (turn.cancelled)
|
|
52677
52701
|
return { stopReason: "cancelled" };
|
|
52678
52702
|
await this.api.updateAndStart(s.todoId, s.agent, msg.messages?.at(-1)?.id);
|
|
52679
52703
|
turn.started = true;
|
|
52680
|
-
const result = await done;
|
|
52681
52704
|
if (turn.cancelled)
|
|
52705
|
+
await this.ws.sendInterrupt(s.projectId, s.todoId);
|
|
52706
|
+
const result = await done;
|
|
52707
|
+
if (turn.cancelled || /^CANCELLED/.test(result?.payload?.status))
|
|
52682
52708
|
return { stopReason: "cancelled" };
|
|
52683
52709
|
if (!result?.success)
|
|
52684
52710
|
throw RequestError.internalError(`todo ended with status ${result?.payload?.status ?? "unknown"}`);
|
|
@@ -52689,7 +52715,7 @@ ${b.resource.text}
|
|
|
52689
52715
|
throw RequestError.internalError(String(e?.message || e));
|
|
52690
52716
|
} finally {
|
|
52691
52717
|
turn.done = true;
|
|
52692
|
-
this.ws.
|
|
52718
|
+
this.ws.forget(s.todoId);
|
|
52693
52719
|
}
|
|
52694
52720
|
}
|
|
52695
52721
|
}
|
|
@@ -52702,7 +52728,7 @@ async function runAcp(apiUrl, apiKey, opts) {
|
|
|
52702
52728
|
if (!wsOk)
|
|
52703
52729
|
throw new Error("frontend websocket connect failed");
|
|
52704
52730
|
const stream2 = ndJsonStream(Writable.toWeb(process.stdout), Readable.toWeb(process.stdin));
|
|
52705
|
-
new AgentSideConnection((conn) => new TodoforaiAgent(conn, api, ws, opts.projectId), stream2);
|
|
52731
|
+
new AgentSideConnection((conn) => new TodoforaiAgent(conn, api, ws, opts.projectId, opts.agent), stream2);
|
|
52706
52732
|
log2(`ready (${apiUrl})`);
|
|
52707
52733
|
await new Promise((resolve3) => {
|
|
52708
52734
|
process.stdin.once("end", resolve3);
|
|
@@ -52977,7 +53003,7 @@ Cancelled by user (Ctrl+C)
|
|
|
52977
53003
|
`);
|
|
52978
53004
|
process.exit(2);
|
|
52979
53005
|
}
|
|
52980
|
-
await runAcp(apiUrl, apiKey, { projectId: args.project || getEnv("PROJECT_ID") || cfgScope.data.default_project_id, noBridge: !!args["no-bridge"] });
|
|
53006
|
+
await runAcp(apiUrl, apiKey, { projectId: args.project || getEnv("PROJECT_ID") || cfgScope.data.default_project_id, agent: args.agent, noBridge: !!args["no-bridge"] });
|
|
52981
53007
|
return;
|
|
52982
53008
|
}
|
|
52983
53009
|
if (positionals[0] === "status") {
|