aibroker 0.1.0 → 0.2.0

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.
@@ -1,10 +1,8 @@
1
1
  /**
2
- * backend/api.ts — APIBackend: direct HTTP API calls to AI providers.
2
+ * backend/api.ts — APIBackend: Claude Agent SDK subprocess bridge.
3
3
  *
4
- * Stub for Phase 9. Will implement:
5
- * - Anthropic API (Claude)
6
- * - OpenAI API (ChatGPT)
7
- * - Ollama API (local models)
4
+ * Spawns a Claude Code subprocess via the Agent SDK's query() function.
5
+ * Returns the assistant's response synchronously — no iTerm2 required.
8
6
  */
9
7
  import type { Backend, APIBackendConfig } from "../types/backend.js";
10
8
  export declare class APIBackend implements Backend {
@@ -12,9 +10,10 @@ export declare class APIBackend implements Backend {
12
10
  readonly type: "api";
13
11
  readonly provider: APIBackendConfig["provider"];
14
12
  readonly model: string;
13
+ private readonly config;
15
14
  constructor(config: APIBackendConfig & {
16
15
  name?: string;
17
16
  });
18
- deliver(message: string, _sessionId?: string): Promise<string | undefined>;
17
+ deliver(message: string, sessionId?: string): Promise<string | undefined>;
19
18
  }
20
19
  //# sourceMappingURL=api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/backend/api.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGrE,qBAAa,UAAW,YAAW,OAAO;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,MAAM,EAAE,gBAAgB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAMlD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAOjF"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/backend/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAOrE,qBAAa,UAAW,YAAW,OAAO;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;gBAE9B,MAAM,EAAE,gBAAgB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAOlD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CA8EhF"}
@@ -1,26 +1,95 @@
1
1
  /**
2
- * backend/api.ts — APIBackend: direct HTTP API calls to AI providers.
2
+ * backend/api.ts — APIBackend: Claude Agent SDK subprocess bridge.
3
3
  *
4
- * Stub for Phase 9. Will implement:
5
- * - Anthropic API (Claude)
6
- * - OpenAI API (ChatGPT)
7
- * - Ollama API (local models)
4
+ * Spawns a Claude Code subprocess via the Agent SDK's query() function.
5
+ * Returns the assistant's response synchronously — no iTerm2 required.
8
6
  */
9
7
  import { log } from "../core/log.js";
8
+ import { homedir } from "os";
9
+ /** Session IDs for multi-turn conversations keyed by external session ID */
10
+ const claudeSessionMap = new Map();
10
11
  export class APIBackend {
11
12
  name;
12
13
  type = "api";
13
14
  provider;
14
15
  model;
16
+ config;
15
17
  constructor(config) {
16
18
  this.name = config.name ?? `${config.provider}/${config.model}`;
17
19
  this.provider = config.provider;
18
20
  this.model = config.model;
21
+ this.config = config;
19
22
  }
20
- async deliver(message, _sessionId) {
21
- log(`APIBackend: not yet implemented (provider=${this.provider}, model=${this.model})`);
22
- throw new Error(`APIBackend is not yet implemented. Use SessionBackend for now. ` +
23
- `(provider=${this.provider}, model=${this.model})`);
23
+ async deliver(message, sessionId) {
24
+ if (this.provider !== "anthropic") {
25
+ log(`APIBackend: provider '${this.provider}' not yet supported, only 'anthropic'`);
26
+ return `Error: provider '${this.provider}' is not yet implemented. Use provider 'anthropic'.`;
27
+ }
28
+ try {
29
+ // Dynamic import — avoid loading the SDK at module level for consumers that don't use API mode
30
+ const { query } = await import("@anthropic-ai/claude-agent-sdk");
31
+ const resumeId = sessionId ? claudeSessionMap.get(sessionId) : undefined;
32
+ log(`APIBackend: delivering to ${this.model} (session=${sessionId ?? "none"}, resume=${resumeId ?? "new"})`);
33
+ const chunks = [];
34
+ let claudeSessionId;
35
+ // Must unset CLAUDECODE env var to allow nested Claude subprocess
36
+ const cleanEnv = { ...process.env };
37
+ delete cleanEnv.CLAUDECODE;
38
+ for await (const event of query({
39
+ prompt: message,
40
+ options: {
41
+ model: this.config.model,
42
+ cwd: this.config.cwd ?? homedir(),
43
+ systemPrompt: this.config.systemPrompt,
44
+ permissionMode: this.config.permissionMode ?? "acceptEdits",
45
+ allowedTools: this.config.allowedTools,
46
+ maxTurns: this.config.maxTurns ?? 30,
47
+ maxBudgetUsd: this.config.maxBudgetUsd ?? 1.0,
48
+ ...(resumeId ? { resume: resumeId } : {}),
49
+ spawnClaudeCodeProcess: ({ args, signal }) => {
50
+ const { spawn } = require("child_process");
51
+ return spawn("claude", args, {
52
+ env: cleanEnv,
53
+ stdio: ["pipe", "pipe", "pipe"],
54
+ signal,
55
+ });
56
+ },
57
+ },
58
+ })) {
59
+ if (event.type === "system") {
60
+ // Capture the Claude session ID for multi-turn resume
61
+ const sysEvent = event;
62
+ if (typeof sysEvent.session_id === "string") {
63
+ claudeSessionId = sysEvent.session_id;
64
+ }
65
+ }
66
+ else if (event.type === "assistant") {
67
+ // Extract text content from assistant messages
68
+ const msg = event;
69
+ const message = msg.message;
70
+ const content = message?.content;
71
+ if (Array.isArray(content)) {
72
+ for (const block of content) {
73
+ if (block && typeof block === "object" && "type" in block && block.type === "text" && "text" in block) {
74
+ chunks.push(block.text);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+ // Store Claude session ID for future resume
81
+ if (sessionId && claudeSessionId) {
82
+ claudeSessionMap.set(sessionId, claudeSessionId);
83
+ }
84
+ const response = chunks.join("\n").trim();
85
+ log(`APIBackend: got response (${response.length} chars, session=${claudeSessionId ?? "unknown"})`);
86
+ return response || undefined;
87
+ }
88
+ catch (err) {
89
+ const msg = err instanceof Error ? err.message : String(err);
90
+ log(`APIBackend: error — ${msg}`);
91
+ return `Error from Claude subprocess: ${msg}`;
92
+ }
24
93
  }
25
94
  }
26
95
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/backend/api.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,MAAM,OAAO,UAAU;IACZ,IAAI,CAAS;IACb,IAAI,GAAG,KAAc,CAAC;IACtB,QAAQ,CAA+B;IACvC,KAAK,CAAS;IAEvB,YAAY,MAA4C;QACtD,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChE,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,UAAmB;QAChD,GAAG,CAAC,6CAA6C,IAAI,CAAC,QAAQ,WAAW,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACxF,MAAM,IAAI,KAAK,CACb,iEAAiE;YACjE,aAAa,IAAI,CAAC,QAAQ,WAAW,IAAI,CAAC,KAAK,GAAG,CACnD,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/backend/api.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,18 @@ export interface APIBackendConfig {
20
20
  model: string;
21
21
  baseUrl?: string;
22
22
  apiKey?: string;
23
+ /** System prompt for the Claude subprocess */
24
+ systemPrompt?: string;
25
+ /** Working directory for the subprocess (default: $HOME) */
26
+ cwd?: string;
27
+ /** Max conversation turns per message (default: 30) */
28
+ maxTurns?: number;
29
+ /** Max USD spend per deliver() call (default: 1.00) */
30
+ maxBudgetUsd?: number;
31
+ /** Permission mode: "default" | "acceptEdits" | "bypassPermissions" | "plan" | "dontAsk" */
32
+ permissionMode?: string;
33
+ /** Whitelist of allowed tools */
34
+ allowedTools?: string[];
23
35
  }
24
36
  export type BackendConfig = SessionBackendConfig | APIBackendConfig;
25
37
  //# sourceMappingURL=backend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/types/backend.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CAAC;IACjC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,gBAAgB,CAAC"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/types/backend.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CAAC;IACjC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,gBAAgB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aibroker",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Platform-agnostic AI message broker — routes between user channels and AI backends",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,6 +26,7 @@
26
26
  "node": ">=18.0.0"
27
27
  },
28
28
  "dependencies": {
29
+ "@anthropic-ai/claude-agent-sdk": "^0.1.0",
29
30
  "kokoro-js": "^1.2.1"
30
31
  },
31
32
  "devDependencies": {