@sesamespace/hivemind 0.8.4 → 0.8.6

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.
Files changed (41) hide show
  1. package/.pnpmrc.json +1 -0
  2. package/DASHBOARD-PLAN.md +206 -0
  3. package/TOOL-USE-DESIGN.md +173 -0
  4. package/config/default.toml +6 -1
  5. package/dist/{chunk-3CQJQUY3.js → chunk-AYHCHIM2.js} +2 -2
  6. package/dist/{chunk-CSYDOZE6.js → chunk-CJ4Y2BCE.js} +2 -2
  7. package/dist/{chunk-66KRRXVF.js → chunk-K7YQY253.js} +3 -3
  8. package/dist/{chunk-DODOQGIL.js → chunk-LSLF7AGW.js} +42 -13
  9. package/dist/chunk-LSLF7AGW.js.map +1 -0
  10. package/dist/{chunk-6S5UKFTZ.js → chunk-S4QRR3ZJ.js} +917 -48
  11. package/dist/chunk-S4QRR3ZJ.js.map +1 -0
  12. package/dist/{chunk-HNXCZPSX.js → chunk-WIJHKLB3.js} +3 -3
  13. package/dist/commands/fleet.js +3 -4
  14. package/dist/commands/init.js +3 -2
  15. package/dist/commands/start.js +3 -4
  16. package/dist/commands/watchdog.js +3 -4
  17. package/dist/index.js +5 -4
  18. package/dist/main.js +6 -7
  19. package/dist/main.js.map +1 -1
  20. package/dist/start.js +1 -2
  21. package/dist/start.js.map +1 -1
  22. package/docs/TOOL-PARITY-PLAN.md +191 -0
  23. package/package.json +22 -25
  24. package/dist/chunk-6S5UKFTZ.js.map +0 -1
  25. package/dist/chunk-DODOQGIL.js.map +0 -1
  26. package/dist/chunk-GPI4RU7N.js +0 -624
  27. package/dist/chunk-GPI4RU7N.js.map +0 -1
  28. package/install.sh +0 -131
  29. package/packages/memory/Cargo.lock +0 -6480
  30. package/packages/memory/Cargo.toml +0 -21
  31. package/packages/memory/src/src/context.rs +0 -179
  32. package/packages/memory/src/src/embeddings.rs +0 -51
  33. package/packages/memory/src/src/main.rs +0 -626
  34. package/packages/memory/src/src/promotion.rs +0 -637
  35. package/packages/memory/src/src/scoring.rs +0 -131
  36. package/packages/memory/src/src/store.rs +0 -460
  37. package/packages/memory/src/src/tasks.rs +0 -321
  38. /package/dist/{chunk-3CQJQUY3.js.map → chunk-AYHCHIM2.js.map} +0 -0
  39. /package/dist/{chunk-CSYDOZE6.js.map → chunk-CJ4Y2BCE.js.map} +0 -0
  40. /package/dist/{chunk-66KRRXVF.js.map → chunk-K7YQY253.js.map} +0 -0
  41. /package/dist/{chunk-HNXCZPSX.js.map → chunk-WIJHKLB3.js.map} +0 -0
@@ -1,20 +1,123 @@
1
- import {
2
- SesameClient
3
- } from "./chunk-GPI4RU7N.js";
4
-
5
1
  // packages/runtime/src/llm-client.ts
2
+ import { execSync } from "child_process";
3
+ function convertMessagesForAnthropic(messages) {
4
+ let system = "";
5
+ const converted = [];
6
+ for (const msg of messages) {
7
+ if (msg.role === "system") {
8
+ system = msg.content ?? "";
9
+ continue;
10
+ }
11
+ if (msg.role === "tool") {
12
+ converted.push({
13
+ role: "user",
14
+ content: [{
15
+ type: "tool_result",
16
+ tool_use_id: msg.tool_call_id,
17
+ content: msg.content ?? ""
18
+ }]
19
+ });
20
+ continue;
21
+ }
22
+ if (msg.role === "assistant" && msg.tool_calls) {
23
+ const content = [];
24
+ if (msg.content) content.push({ type: "text", text: msg.content });
25
+ for (const tc of msg.tool_calls) {
26
+ content.push({
27
+ type: "tool_use",
28
+ id: tc.id,
29
+ name: tc.function.name,
30
+ input: JSON.parse(tc.function.arguments)
31
+ });
32
+ }
33
+ converted.push({ role: "assistant", content });
34
+ continue;
35
+ }
36
+ converted.push({ role: msg.role, content: msg.content ?? "" });
37
+ }
38
+ return { system, messages: converted };
39
+ }
40
+ function convertToolsForAnthropic(tools) {
41
+ return tools.map((t) => ({
42
+ name: t.function.name,
43
+ description: t.function.description,
44
+ input_schema: t.function.parameters
45
+ }));
46
+ }
47
+ function parseAnthropicResponse(data) {
48
+ let textContent = "";
49
+ const toolCalls = [];
50
+ for (const block of data.content) {
51
+ if (block.type === "text") textContent += block.text;
52
+ if (block.type === "tool_use") {
53
+ toolCalls.push({
54
+ id: block.id,
55
+ type: "function",
56
+ function: {
57
+ name: block.name,
58
+ arguments: JSON.stringify(block.input)
59
+ }
60
+ });
61
+ }
62
+ }
63
+ return {
64
+ content: textContent,
65
+ model: data.model,
66
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
67
+ finish_reason: data.stop_reason === "tool_use" ? "tool_calls" : "stop",
68
+ usage: data.usage ? {
69
+ prompt_tokens: data.usage.input_tokens,
70
+ completion_tokens: data.usage.output_tokens,
71
+ total_tokens: data.usage.input_tokens + data.usage.output_tokens
72
+ } : void 0
73
+ };
74
+ }
75
+ function getClaudeCodeOAuthToken() {
76
+ try {
77
+ const raw = execSync(
78
+ 'security find-generic-password -s "Claude Code-credentials" -w',
79
+ { encoding: "utf-8", timeout: 5e3 }
80
+ ).trim();
81
+ const data = JSON.parse(raw);
82
+ const oauth = data?.claudeAiOauth;
83
+ if (!oauth?.accessToken) return null;
84
+ if (oauth.expiresAt && Date.now() > oauth.expiresAt) {
85
+ console.warn("[llm] Claude Code OAuth token expired. Run: claude auth login");
86
+ return null;
87
+ }
88
+ return oauth.accessToken;
89
+ } catch {
90
+ return null;
91
+ }
92
+ }
6
93
  var LLMClient = class {
7
94
  baseUrl;
8
95
  model;
9
96
  maxTokens;
10
97
  temperature;
11
98
  apiKey;
99
+ provider;
12
100
  constructor(config) {
13
101
  this.baseUrl = config.base_url;
14
102
  this.model = config.model;
15
103
  this.maxTokens = config.max_tokens;
16
104
  this.temperature = config.temperature;
17
105
  this.apiKey = config.api_key ?? "";
106
+ this.provider = config.provider ?? "openai";
107
+ if (this.provider === "anthropic" && !this.apiKey) {
108
+ const token = getClaudeCodeOAuthToken();
109
+ if (token) {
110
+ this.apiKey = token;
111
+ if (!this.baseUrl || this.baseUrl.includes("openrouter")) {
112
+ this.baseUrl = "https://api.anthropic.com";
113
+ }
114
+ console.log("[llm] Auth: Claude Max OAuth (from macOS Keychain)");
115
+ } else {
116
+ console.warn("[llm] Auth: No API key found for Anthropic provider");
117
+ }
118
+ } else if (this.provider === "anthropic") {
119
+ console.log("[llm] Auth: Anthropic API key (from config/env)");
120
+ }
18
121
  }
19
122
  /**
20
123
  * Simple chat completion (no tools). Backwards compatible.
@@ -27,6 +130,13 @@ var LLMClient = class {
27
130
  * Returns tool_calls if the model wants to use tools.
28
131
  */
29
132
  async chatWithTools(messages, tools) {
133
+ if (this.provider === "anthropic") {
134
+ return this.chatAnthropic(messages, tools);
135
+ }
136
+ return this.chatOpenAI(messages, tools);
137
+ }
138
+ // --- OpenAI-compatible path (OpenRouter, etc.) ---
139
+ async chatOpenAI(messages, tools) {
30
140
  const body = {
31
141
  model: this.model,
32
142
  messages,
@@ -75,6 +185,54 @@ var LLMClient = class {
75
185
  }
76
186
  throw lastError ?? new Error("LLM request failed after retries");
77
187
  }
188
+ // --- Anthropic Messages API path ---
189
+ async chatAnthropic(messages, tools) {
190
+ const { system, messages: convertedMessages } = convertMessagesForAnthropic(messages);
191
+ const body = {
192
+ model: this.model,
193
+ max_tokens: this.maxTokens,
194
+ temperature: this.temperature,
195
+ messages: convertedMessages
196
+ };
197
+ if (system) {
198
+ body.system = system;
199
+ }
200
+ if (tools && tools.length > 0) {
201
+ body.tools = convertToolsForAnthropic(tools);
202
+ body.tool_choice = { type: "auto" };
203
+ }
204
+ const RETRYABLE_CODES = [429, 500, 502, 503, 529];
205
+ const MAX_RETRIES = 3;
206
+ let lastError = null;
207
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
208
+ if (attempt > 0) {
209
+ const delayMs = Math.pow(2, attempt) * 1e3;
210
+ console.log(`[llm] Retry ${attempt}/${MAX_RETRIES} after ${delayMs}ms...`);
211
+ await new Promise((r) => setTimeout(r, delayMs));
212
+ }
213
+ const resp = await fetch(`${this.baseUrl}/v1/messages`, {
214
+ method: "POST",
215
+ headers: {
216
+ "Content-Type": "application/json",
217
+ "x-api-key": this.apiKey,
218
+ "anthropic-version": "2023-06-01"
219
+ },
220
+ body: JSON.stringify(body)
221
+ });
222
+ if (!resp.ok) {
223
+ const text = await resp.text();
224
+ lastError = new Error(`Anthropic request failed: ${resp.status} ${text}`);
225
+ if (RETRYABLE_CODES.includes(resp.status) && attempt < MAX_RETRIES) {
226
+ console.warn(`[llm] Retryable error ${resp.status}: ${text.slice(0, 200)}`);
227
+ continue;
228
+ }
229
+ throw lastError;
230
+ }
231
+ const data = await resp.json();
232
+ return parseAnthropicResponse(data);
233
+ }
234
+ throw lastError ?? new Error("Anthropic request failed after retries");
235
+ }
78
236
  };
79
237
 
80
238
  // packages/runtime/src/memory-client.ts
@@ -2336,6 +2494,26 @@ function loadConfig(path) {
2336
2494
  if (process.env.LLM_API_KEY) {
2337
2495
  parsed.llm.api_key = process.env.LLM_API_KEY;
2338
2496
  }
2497
+ if (process.env.ANTHROPIC_API_KEY && !parsed.llm.api_key) {
2498
+ parsed.llm.api_key = process.env.ANTHROPIC_API_KEY;
2499
+ if (!parsed.llm.provider) parsed.llm.provider = "anthropic";
2500
+ if (!process.env.LLM_BASE_URL && parsed.llm.base_url.includes("openrouter")) {
2501
+ parsed.llm.base_url = "https://api.anthropic.com";
2502
+ }
2503
+ }
2504
+ if (parsed.llm.provider === "anthropic" && !parsed.llm.api_key) {
2505
+ const oauthToken = getClaudeCodeOAuthToken();
2506
+ if (oauthToken) {
2507
+ parsed.llm.api_key = oauthToken;
2508
+ if (!process.env.LLM_BASE_URL && parsed.llm.base_url.includes("openrouter")) {
2509
+ parsed.llm.base_url = "https://api.anthropic.com";
2510
+ }
2511
+ console.log("[config] Auth: Claude Max OAuth (from macOS Keychain)");
2512
+ }
2513
+ }
2514
+ if (process.env.LLM_PROVIDER) {
2515
+ parsed.llm.provider = process.env.LLM_PROVIDER;
2516
+ }
2339
2517
  if (process.env.LLM_BASE_URL) {
2340
2518
  parsed.llm.base_url = process.env.LLM_BASE_URL;
2341
2519
  }
@@ -2380,6 +2558,626 @@ function loadConfig(path) {
2380
2558
  return parsed;
2381
2559
  }
2382
2560
 
2561
+ // node_modules/.pnpm/@sesamespace+sdk@0.1.6/node_modules/@sesamespace/sdk/dist/client.js
2562
+ import WebSocket from "ws";
2563
+
2564
+ // node_modules/.pnpm/@sesamespace+sdk@0.1.6/node_modules/@sesamespace/sdk/dist/auth.js
2565
+ import { sign } from "crypto";
2566
+ function createAuthSignature(handle, privateKeyBase64url) {
2567
+ const timestamp = Date.now();
2568
+ const message = `AUTH:${handle}:${timestamp}`;
2569
+ const privateKeyDer = Buffer.from(privateKeyBase64url, "base64url");
2570
+ const privateKey = {
2571
+ key: privateKeyDer,
2572
+ format: "der",
2573
+ type: "pkcs8"
2574
+ };
2575
+ const sig = sign(null, Buffer.from(message), privateKey);
2576
+ return {
2577
+ signature: sig.toString("base64url"),
2578
+ timestamp
2579
+ };
2580
+ }
2581
+
2582
+ // node_modules/.pnpm/@sesamespace+sdk@0.1.6/node_modules/@sesamespace/sdk/dist/client.js
2583
+ var SesameClient = class {
2584
+ config;
2585
+ ws = null;
2586
+ eventHandlers = /* @__PURE__ */ new Map();
2587
+ reconnectAttempts = 0;
2588
+ reconnectTimer = null;
2589
+ heartbeatTimer = null;
2590
+ cursors = /* @__PURE__ */ new Map();
2591
+ authenticated = false;
2592
+ constructor(config) {
2593
+ this.config = {
2594
+ autoReconnect: true,
2595
+ maxReconnectAttempts: 10,
2596
+ ...config
2597
+ };
2598
+ }
2599
+ // ── HTTP Methods ──
2600
+ async fetch(path, options = {}) {
2601
+ const headers = {
2602
+ "Content-Type": "application/json",
2603
+ ...options.headers ?? {}
2604
+ };
2605
+ if (this.config.apiKey) {
2606
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
2607
+ } else if (this.config.token) {
2608
+ headers["Authorization"] = `Bearer ${this.config.token}`;
2609
+ } else if (this.config.agent) {
2610
+ const { signature, timestamp } = createAuthSignature(this.config.agent.handle, this.config.agent.privateKey);
2611
+ headers["Authorization"] = `Signature ${this.config.agent.handle}.${signature}.${timestamp}`;
2612
+ }
2613
+ const response = await globalThis.fetch(`${this.config.apiUrl}${path}`, {
2614
+ ...options,
2615
+ headers
2616
+ });
2617
+ if (!response.ok) {
2618
+ const error = await response.json().catch(() => ({ error: response.statusText }));
2619
+ throw new SesameApiError(response.status, error.error ?? "Request failed");
2620
+ }
2621
+ return response.json();
2622
+ }
2623
+ get(path) {
2624
+ return this.fetch(path);
2625
+ }
2626
+ post(path, body) {
2627
+ return this.fetch(path, {
2628
+ method: "POST",
2629
+ body: body ? JSON.stringify(body) : void 0
2630
+ });
2631
+ }
2632
+ patch(path, body) {
2633
+ return this.fetch(path, {
2634
+ method: "PATCH",
2635
+ body: JSON.stringify(body)
2636
+ });
2637
+ }
2638
+ del(path) {
2639
+ return this.fetch(path, { method: "DELETE" });
2640
+ }
2641
+ // ── Auth ──
2642
+ async login(email, password) {
2643
+ const result = await this.post("/api/v1/auth/login", { email, password });
2644
+ this.config.token = result.accessToken;
2645
+ return result;
2646
+ }
2647
+ // ── Channels ──
2648
+ async listChannels() {
2649
+ const result = await this.get("/api/v1/channels");
2650
+ const channels = result.data ?? result.channels ?? result;
2651
+ return { channels: Array.isArray(channels) ? channels : [] };
2652
+ }
2653
+ async getChannel(id) {
2654
+ const result = await this.get(`/api/v1/channels/${id}`);
2655
+ const channel = result.data ?? result.channel ?? result;
2656
+ return { channel };
2657
+ }
2658
+ async createChannel(data) {
2659
+ const result = await this.post("/api/v1/channels", data);
2660
+ const channel = result.data ?? result.channel ?? result;
2661
+ return { channel };
2662
+ }
2663
+ async getOrCreateDM(principalId) {
2664
+ const result = await this.post("/api/v1/channels/dm", { principalId });
2665
+ const channel = result.data ?? result.channel ?? result;
2666
+ return { channel };
2667
+ }
2668
+ async getUnread() {
2669
+ return this.get("/api/v1/channels/unread");
2670
+ }
2671
+ // ── Messages ──
2672
+ async sendMessage(channelId, options) {
2673
+ const result = await this.post(`/api/v1/channels/${channelId}/messages`, options);
2674
+ const message = this.normalizeMessage(result.data ?? result.message ?? result);
2675
+ if (message.seq) {
2676
+ this.cursors.set(channelId, message.seq);
2677
+ }
2678
+ return { message };
2679
+ }
2680
+ async getMessages(channelId, options) {
2681
+ const params = new URLSearchParams();
2682
+ if (options?.cursor)
2683
+ params.set("cursor", options.cursor.toString());
2684
+ if (options?.limit)
2685
+ params.set("limit", options.limit.toString());
2686
+ if (options?.direction)
2687
+ params.set("direction", options.direction);
2688
+ if (options?.threadRootId)
2689
+ params.set("threadRootId", options.threadRootId);
2690
+ const qs = params.toString();
2691
+ const result = await this.get(`/api/v1/channels/${channelId}/messages${qs ? `?${qs}` : ""}`);
2692
+ const messages = (result.data ?? result.messages ?? []).map((m) => this.normalizeMessage(m));
2693
+ if (messages.length > 0) {
2694
+ const maxSeq = Math.max(...messages.map((m) => m.seq));
2695
+ const current = this.cursors.get(channelId) ?? 0;
2696
+ if (maxSeq > current)
2697
+ this.cursors.set(channelId, maxSeq);
2698
+ }
2699
+ return {
2700
+ messages,
2701
+ cursor: result.pagination?.cursor ? Number(result.pagination.cursor) : 0,
2702
+ hasMore: result.pagination?.hasMore ?? false
2703
+ };
2704
+ }
2705
+ async editMessage(channelId, messageId, content) {
2706
+ const result = await this.patch(`/api/v1/channels/${channelId}/messages/${messageId}`, { content });
2707
+ const message = this.normalizeMessage(result.data ?? result.message ?? result);
2708
+ return { message };
2709
+ }
2710
+ async deleteMessage(channelId, messageId) {
2711
+ await this.del(`/api/v1/channels/${channelId}/messages/${messageId}`);
2712
+ }
2713
+ async markRead(channelId, seq) {
2714
+ await this.post(`/api/v1/channels/${channelId}/messages/read`, { seq });
2715
+ }
2716
+ async addReaction(channelId, messageId, emoji) {
2717
+ await this.post(`/api/v1/channels/${channelId}/messages/${messageId}/reactions`, { emoji });
2718
+ }
2719
+ async removeReaction(channelId, messageId, emoji) {
2720
+ await this.del(`/api/v1/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`);
2721
+ }
2722
+ // ── Vault ──
2723
+ async listVaults() {
2724
+ return this.get("/api/v1/vault/vaults");
2725
+ }
2726
+ async listVaultItems(vaultId) {
2727
+ const qs = vaultId ? `?vaultId=${vaultId}` : "";
2728
+ return this.get(`/api/v1/vault/items${qs}`);
2729
+ }
2730
+ async getVaultItem(id) {
2731
+ return this.get(`/api/v1/vault/items/${id}`);
2732
+ }
2733
+ async createVaultItem(options) {
2734
+ return this.post("/api/v1/vault/items", options);
2735
+ }
2736
+ async revealItem(id, fields) {
2737
+ return this.post(`/api/v1/vault/items/${id}/reveal`, fields ? { fields } : void 0);
2738
+ }
2739
+ async shareItem(itemId, principalId, options) {
2740
+ await this.post(`/api/v1/vault/items/${itemId}/share`, {
2741
+ principalId,
2742
+ ...options
2743
+ });
2744
+ }
2745
+ async revokeShare(itemId, principalId) {
2746
+ await this.del(`/api/v1/vault/items/${itemId}/share/${principalId}`);
2747
+ }
2748
+ async getWallet() {
2749
+ return this.get("/api/v1/vault/wallet");
2750
+ }
2751
+ // ── Leases ──
2752
+ async requestLease(options) {
2753
+ return this.post("/api/v1/vault/leases/request", options);
2754
+ }
2755
+ async approveLease(leaseId, options) {
2756
+ return this.post(`/api/v1/vault/leases/${leaseId}/approve`, options ?? {});
2757
+ }
2758
+ async denyLease(leaseId) {
2759
+ return this.post(`/api/v1/vault/leases/${leaseId}/deny`, {});
2760
+ }
2761
+ async useSecret(leaseId) {
2762
+ return this.post(`/api/v1/vault/leases/${leaseId}/use`, {});
2763
+ }
2764
+ async revokeLease(leaseId) {
2765
+ await this.del(`/api/v1/vault/leases/${leaseId}`);
2766
+ }
2767
+ // ── HTTP helper: PUT ──
2768
+ put(path, body) {
2769
+ return this.fetch(path, {
2770
+ method: "PUT",
2771
+ body: body ? JSON.stringify(body) : void 0
2772
+ });
2773
+ }
2774
+ // ── Agents ──
2775
+ async listAgents() {
2776
+ return this.get("/api/v1/agents");
2777
+ }
2778
+ async provisionAgent(data) {
2779
+ return this.post("/api/v1/agents", data);
2780
+ }
2781
+ async generateApiKey(agentId, label) {
2782
+ const res = await this.post(`/api/v1/agents/${agentId}/api-keys`, { label });
2783
+ return res.data ?? res;
2784
+ }
2785
+ // ── Capabilities ──
2786
+ async registerCapabilities(capabilities) {
2787
+ const agentId = this.getAgentId();
2788
+ const result = await this.put(`/api/v1/agents/${agentId}/capabilities`, { capabilities });
2789
+ return { capabilities: result.data ?? result };
2790
+ }
2791
+ async addCapability(capability) {
2792
+ const agentId = this.getAgentId();
2793
+ const result = await this.post(`/api/v1/agents/${agentId}/capabilities`, capability);
2794
+ return { capability: result.data ?? result };
2795
+ }
2796
+ async getCapabilities(agentId) {
2797
+ const id = agentId ?? this.getAgentId();
2798
+ const result = await this.get(`/api/v1/agents/${id}/capabilities`);
2799
+ return { capabilities: result.data ?? result };
2800
+ }
2801
+ async removeCapability(capabilityId) {
2802
+ const agentId = this.getAgentId();
2803
+ await this.del(`/api/v1/agents/${agentId}/capabilities/${capabilityId}`);
2804
+ }
2805
+ // ── Discovery ──
2806
+ async discoverAgents(query = {}) {
2807
+ const params = new URLSearchParams();
2808
+ if (query.namespace)
2809
+ params.set("namespace", query.namespace);
2810
+ if (query.name)
2811
+ params.set("name", query.name);
2812
+ if (query.capability) {
2813
+ const caps = Array.isArray(query.capability) ? query.capability : [query.capability];
2814
+ for (const cap of caps) {
2815
+ params.append("capability", cap);
2816
+ }
2817
+ }
2818
+ if (query.active !== void 0)
2819
+ params.set("active", String(query.active));
2820
+ const qs = params.toString();
2821
+ const result = await this.get(`/api/v1/agents/discover${qs ? `?${qs}` : ""}`);
2822
+ return { agents: result.data ?? result };
2823
+ }
2824
+ // ── Manifest & Context ──
2825
+ async getManifest() {
2826
+ if (!this._principalId) {
2827
+ const me = await this.get("/api/v1/auth/me");
2828
+ this.setPrincipalId(me.data?.id ?? me.id);
2829
+ }
2830
+ const agentId = this.getAgentId();
2831
+ const result = await this.get(`/api/v1/agents/${agentId}/manifest`);
2832
+ return result.data ?? result;
2833
+ }
2834
+ async getChannelContext(channelId, options) {
2835
+ const agentId = this.getAgentId();
2836
+ const params = new URLSearchParams();
2837
+ if (options?.strategy)
2838
+ params.set("strategy", options.strategy);
2839
+ if (options?.window)
2840
+ params.set("window", String(options.window));
2841
+ const qs = params.toString();
2842
+ const result = await this.get(`/api/v1/agents/${agentId}/channels/${channelId}/context${qs ? `?${qs}` : ""}`);
2843
+ return result.data ?? result;
2844
+ }
2845
+ // ── Channel Config ──
2846
+ async setChannelConfig(channelId, config) {
2847
+ const agentId = this.getAgentId();
2848
+ const result = await this.put(`/api/v1/agents/${agentId}/channels/${channelId}/config`, config);
2849
+ return result.data ?? result;
2850
+ }
2851
+ async getChannelConfig(channelId) {
2852
+ const agentId = this.getAgentId();
2853
+ const result = await this.get(`/api/v1/agents/${agentId}/channels/${channelId}/config`);
2854
+ return result.data ?? result;
2855
+ }
2856
+ async deleteChannelConfig(channelId) {
2857
+ const agentId = this.getAgentId();
2858
+ await this.del(`/api/v1/agents/${agentId}/channels/${channelId}/config`);
2859
+ }
2860
+ // ── Collaboration ──
2861
+ async createCollaborationChannel(options) {
2862
+ const result = await this.createChannel({
2863
+ kind: "topic",
2864
+ name: options.name,
2865
+ description: options.description,
2866
+ memberIds: options.memberIds
2867
+ });
2868
+ const channel = result.data ?? result.channel ?? result;
2869
+ const channelId = channel.id;
2870
+ if (options.context) {
2871
+ await this.put(`/api/v1/channels/${channelId}/context`, { context: options.context });
2872
+ }
2873
+ if (options.visibility) {
2874
+ await this.patch(`/api/v1/channels/${channelId}`, { visibility: options.visibility });
2875
+ }
2876
+ if (options.coordinationMode) {
2877
+ await this.put(`/api/v1/channels/${channelId}/coordination`, {
2878
+ mode: options.coordinationMode
2879
+ });
2880
+ }
2881
+ return { channel };
2882
+ }
2883
+ // ── Tasks ──
2884
+ async createTask(channelId, options) {
2885
+ const result = await this.post(`/api/v1/channels/${channelId}/tasks`, options);
2886
+ return { task: result.data ?? result };
2887
+ }
2888
+ async listTasks(channelId, filters) {
2889
+ const params = new URLSearchParams();
2890
+ if (filters?.status)
2891
+ params.set("status", filters.status);
2892
+ if (filters?.priority)
2893
+ params.set("priority", filters.priority);
2894
+ if (filters?.assigneeId)
2895
+ params.set("assigneeId", filters.assigneeId);
2896
+ const qs = params.toString();
2897
+ const result = await this.get(`/api/v1/channels/${channelId}/tasks${qs ? `?${qs}` : ""}`);
2898
+ return { tasks: result.data ?? result };
2899
+ }
2900
+ async updateTask(channelId, taskId, updates) {
2901
+ const result = await this.patch(`/api/v1/channels/${channelId}/tasks/${taskId}`, updates);
2902
+ return { task: result.data ?? result };
2903
+ }
2904
+ async claimTask(channelId, taskId) {
2905
+ const result = await this.post(`/api/v1/channels/${channelId}/tasks/${taskId}/claim`);
2906
+ return { task: result.data ?? result };
2907
+ }
2908
+ async addTaskAssignee(channelId, taskId, principalId, role) {
2909
+ const result = await this.post(`/api/v1/channels/${channelId}/tasks/${taskId}/assignees`, { principalId, role });
2910
+ return { task: result.data ?? result };
2911
+ }
2912
+ async removeTaskAssignee(channelId, taskId, principalId) {
2913
+ const result = await this.del(`/api/v1/channels/${channelId}/tasks/${taskId}/assignees/${principalId}`);
2914
+ return { task: result.data ?? result };
2915
+ }
2916
+ async createTaskChannel(channelId, taskId, options) {
2917
+ const result = await this.post(`/api/v1/channels/${channelId}/tasks/${taskId}/channel`, options ?? {});
2918
+ return result.data ?? result;
2919
+ }
2920
+ // ── Webhooks ──
2921
+ async createWebhook(options) {
2922
+ const agentId = this.getAgentId();
2923
+ const result = await this.post(`/api/v1/agents/${agentId}/webhooks`, options);
2924
+ return { webhook: result.data ?? result };
2925
+ }
2926
+ async listWebhooks() {
2927
+ const agentId = this.getAgentId();
2928
+ const result = await this.get(`/api/v1/agents/${agentId}/webhooks`);
2929
+ return { webhooks: result.data ?? result };
2930
+ }
2931
+ async updateWebhook(webhookId, updates) {
2932
+ const agentId = this.getAgentId();
2933
+ const result = await this.patch(`/api/v1/agents/${agentId}/webhooks/${webhookId}`, updates);
2934
+ return { webhook: result.data ?? result };
2935
+ }
2936
+ async deleteWebhook(webhookId) {
2937
+ const agentId = this.getAgentId();
2938
+ await this.del(`/api/v1/agents/${agentId}/webhooks/${webhookId}`);
2939
+ }
2940
+ async rotateWebhookSecret(webhookId) {
2941
+ const agentId = this.getAgentId();
2942
+ const result = await this.post(`/api/v1/agents/${agentId}/webhooks/${webhookId}/rotate-secret`);
2943
+ return result.data ?? result;
2944
+ }
2945
+ async listWebhookDeliveries(webhookId, options) {
2946
+ const agentId = this.getAgentId();
2947
+ const params = new URLSearchParams();
2948
+ if (options?.limit)
2949
+ params.set("limit", String(options.limit));
2950
+ if (options?.status)
2951
+ params.set("status", options.status);
2952
+ const qs = params.toString();
2953
+ const result = await this.get(`/api/v1/agents/${agentId}/webhooks/${webhookId}/deliveries${qs ? `?${qs}` : ""}`);
2954
+ return { deliveries: result.data ?? result };
2955
+ }
2956
+ // ── Profile ──
2957
+ async setReadReceiptEmoji(emoji) {
2958
+ const agentId = this.getAgentId();
2959
+ const result = await this.put(`/api/v1/agents/${agentId}/read-receipt-emoji`, { emoji });
2960
+ return { emoji: result.data?.emoji ?? emoji };
2961
+ }
2962
+ async getReadReceiptEmoji() {
2963
+ const agentId = this.getAgentId();
2964
+ const result = await this.get(`/api/v1/agents/${agentId}/read-receipt-emoji`);
2965
+ return { emoji: result.data?.emoji ?? "\u{1F440}" };
2966
+ }
2967
+ // ── Internal helpers ──
2968
+ normalizeMessage(msg) {
2969
+ return {
2970
+ ...msg,
2971
+ content: msg.content ?? msg.plaintext ?? null
2972
+ };
2973
+ }
2974
+ getAgentId() {
2975
+ const principal = this._principalId;
2976
+ if (principal)
2977
+ return principal;
2978
+ throw new SesameApiError(400, "Agent ID not resolved. Call boot() or setPrincipalId(id) first.");
2979
+ }
2980
+ /**
2981
+ * Set the current agent's principal ID (resolved after auth).
2982
+ */
2983
+ setPrincipalId(id) {
2984
+ this._principalId = id;
2985
+ }
2986
+ /**
2987
+ * Bootstrap the agent: resolves identity via /auth/me and loads manifest.
2988
+ */
2989
+ async boot() {
2990
+ const me = await this.get("/api/v1/auth/me");
2991
+ const principal = me.data ?? me;
2992
+ this.setPrincipalId(principal.id);
2993
+ const manifest = await this.getManifest();
2994
+ return manifest;
2995
+ }
2996
+ // ── WebSocket ──
2997
+ /**
2998
+ * Connect to the real-time WebSocket gateway.
2999
+ */
3000
+ connect() {
3001
+ return new Promise((resolve20, reject) => {
3002
+ try {
3003
+ this.ws = new WebSocket(`${this.config.wsUrl}/v1/connect`);
3004
+ this.ws.on("open", () => {
3005
+ this.reconnectAttempts = 0;
3006
+ this.sendAuth();
3007
+ });
3008
+ this.ws.on("message", (data) => {
3009
+ try {
3010
+ const event = JSON.parse(data.toString());
3011
+ if (event.type === "authenticated") {
3012
+ this.authenticated = true;
3013
+ this.startHeartbeat(event.heartbeatIntervalMs ?? 3e4);
3014
+ this.sendReplay();
3015
+ resolve20();
3016
+ return;
3017
+ }
3018
+ if (event.type === "pong")
3019
+ return;
3020
+ if (event.type === "error") {
3021
+ console.error("WS error:", event.message);
3022
+ return;
3023
+ }
3024
+ if (event.type === "message" && event.data) {
3025
+ event.data = this.normalizeMessage(event.data);
3026
+ const seq = event.data.seq;
3027
+ if (seq) {
3028
+ const channelId = event.data.channelId;
3029
+ const current = this.cursors.get(channelId) ?? 0;
3030
+ if (seq > current)
3031
+ this.cursors.set(channelId, seq);
3032
+ }
3033
+ }
3034
+ this.emit(event);
3035
+ } catch {
3036
+ }
3037
+ });
3038
+ this.ws.on("close", () => {
3039
+ this.authenticated = false;
3040
+ this.stopHeartbeat();
3041
+ if (this.config.autoReconnect) {
3042
+ this.scheduleReconnect();
3043
+ }
3044
+ });
3045
+ this.ws.on("error", (err) => {
3046
+ if (!this.authenticated) {
3047
+ reject(err);
3048
+ }
3049
+ });
3050
+ } catch (err) {
3051
+ reject(err);
3052
+ }
3053
+ });
3054
+ }
3055
+ /**
3056
+ * Disconnect from the WebSocket gateway.
3057
+ */
3058
+ disconnect() {
3059
+ this.config.autoReconnect = false;
3060
+ this.stopHeartbeat();
3061
+ if (this.reconnectTimer) {
3062
+ clearTimeout(this.reconnectTimer);
3063
+ this.reconnectTimer = null;
3064
+ }
3065
+ if (this.ws) {
3066
+ this.ws.close();
3067
+ this.ws = null;
3068
+ }
3069
+ }
3070
+ /**
3071
+ * Subscribe to WebSocket events.
3072
+ */
3073
+ on(eventType, handler) {
3074
+ if (!this.eventHandlers.has(eventType)) {
3075
+ this.eventHandlers.set(eventType, /* @__PURE__ */ new Set());
3076
+ }
3077
+ this.eventHandlers.get(eventType).add(handler);
3078
+ return () => {
3079
+ this.eventHandlers.get(eventType)?.delete(handler);
3080
+ };
3081
+ }
3082
+ /**
3083
+ * Subscribe to all events.
3084
+ */
3085
+ onAny(handler) {
3086
+ return this.on("*", handler);
3087
+ }
3088
+ emit(event) {
3089
+ this.eventHandlers.get(event.type)?.forEach((h) => h(event));
3090
+ this.eventHandlers.get("*")?.forEach((h) => h(event));
3091
+ }
3092
+ sendAuth() {
3093
+ if (!this.ws)
3094
+ return;
3095
+ if (this.config.apiKey) {
3096
+ this.ws.send(JSON.stringify({ type: "auth", apiKey: this.config.apiKey }));
3097
+ } else if (this.config.token) {
3098
+ this.ws.send(JSON.stringify({ type: "auth", token: this.config.token }));
3099
+ } else if (this.config.agent) {
3100
+ const { signature, timestamp } = createAuthSignature(this.config.agent.handle, this.config.agent.privateKey);
3101
+ this.ws.send(JSON.stringify({
3102
+ type: "auth",
3103
+ signature: {
3104
+ handle: this.config.agent.handle,
3105
+ sig: signature,
3106
+ timestamp
3107
+ }
3108
+ }));
3109
+ }
3110
+ }
3111
+ sendReplay() {
3112
+ if (!this.ws || this.cursors.size === 0)
3113
+ return;
3114
+ const cursors = {};
3115
+ this.cursors.forEach((seq, channelId) => {
3116
+ cursors[channelId] = seq;
3117
+ });
3118
+ this.ws.send(JSON.stringify({ type: "replay", cursors }));
3119
+ }
3120
+ startHeartbeat(intervalMs) {
3121
+ this.stopHeartbeat();
3122
+ this.heartbeatTimer = setInterval(() => {
3123
+ if (this.ws?.readyState === WebSocket.OPEN) {
3124
+ this.ws.send(JSON.stringify({ type: "ping" }));
3125
+ }
3126
+ }, intervalMs);
3127
+ }
3128
+ stopHeartbeat() {
3129
+ if (this.heartbeatTimer) {
3130
+ clearInterval(this.heartbeatTimer);
3131
+ this.heartbeatTimer = null;
3132
+ }
3133
+ }
3134
+ scheduleReconnect() {
3135
+ if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {
3136
+ console.error("Max reconnect attempts reached");
3137
+ return;
3138
+ }
3139
+ const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);
3140
+ this.reconnectAttempts++;
3141
+ this.reconnectTimer = setTimeout(() => {
3142
+ this.connect().catch(() => {
3143
+ this.scheduleReconnect();
3144
+ });
3145
+ }, delay);
3146
+ }
3147
+ /**
3148
+ * Send a typing indicator for a channel.
3149
+ */
3150
+ sendTyping(channelId) {
3151
+ if (this.ws?.readyState === WebSocket.OPEN) {
3152
+ this.ws.send(JSON.stringify({ type: "typing", channelId }));
3153
+ }
3154
+ }
3155
+ /**
3156
+ * Send a message via WebSocket (alternative to HTTP).
3157
+ */
3158
+ sendWsMessage(channelId, content, options) {
3159
+ if (this.ws?.readyState === WebSocket.OPEN) {
3160
+ this.ws.send(JSON.stringify({
3161
+ type: "send",
3162
+ channelId,
3163
+ content,
3164
+ ...options
3165
+ }));
3166
+ }
3167
+ }
3168
+ };
3169
+ var SesameApiError = class extends Error {
3170
+ status;
3171
+ constructor(status, message) {
3172
+ super(message);
3173
+ this.status = status;
3174
+ this.name = "SesameApiError";
3175
+ }
3176
+ };
3177
+
3178
+ // node_modules/.pnpm/@sesamespace+sdk@0.1.6/node_modules/@sesamespace/sdk/dist/verify-webhook.js
3179
+ import { createHmac, timingSafeEqual } from "crypto";
3180
+
2383
3181
  // packages/runtime/src/sesame.ts
2384
3182
  import { readFileSync as readFileSync5 } from "fs";
2385
3183
  import { resolve as resolve4, dirname as dirname3 } from "path";
@@ -2549,7 +3347,7 @@ var SesameClient2 = class {
2549
3347
  };
2550
3348
 
2551
3349
  // packages/runtime/src/skills.ts
2552
- import { execSync } from "child_process";
3350
+ import { execSync as execSync2 } from "child_process";
2553
3351
  import { existsSync as existsSync5, readFileSync as readFileSync6, readdirSync as readdirSync3, watch as watch2, mkdirSync as mkdirSync3 } from "fs";
2554
3352
  import { resolve as resolve5 } from "path";
2555
3353
  function shellEscape(value) {
@@ -2618,7 +3416,7 @@ var SkillsEngine = class {
2618
3416
  const setupPath = resolve5(skillDir, "setup.sh");
2619
3417
  if (existsSync5(setupPath)) {
2620
3418
  try {
2621
- execSync("bash setup.sh", { cwd: skillDir, timeout: 3e4, stdio: "pipe" });
3419
+ execSync2("bash setup.sh", { cwd: skillDir, timeout: 3e4, stdio: "pipe" });
2622
3420
  console.log(`[skills] Ran setup.sh for "${name}"`);
2623
3421
  } catch (err) {
2624
3422
  console.warn(`[skills] setup.sh failed for "${name}":`, err.message);
@@ -2643,7 +3441,7 @@ var SkillsEngine = class {
2643
3441
  async (params) => {
2644
3442
  const cmd = renderCommand(commandTemplate, params, skillDir, this.workspaceDir);
2645
3443
  try {
2646
- const output = execSync(cmd, {
3444
+ const output = execSync2(cmd, {
2647
3445
  cwd: skillDir,
2648
3446
  timeout: 6e4,
2649
3447
  encoding: "utf-8",
@@ -2682,7 +3480,7 @@ var SkillsEngine = class {
2682
3480
  const teardownPath = resolve5(skill.path, "teardown.sh");
2683
3481
  if (existsSync5(teardownPath)) {
2684
3482
  try {
2685
- execSync("bash teardown.sh", { cwd: skill.path, timeout: 3e4, stdio: "pipe" });
3483
+ execSync2("bash teardown.sh", { cwd: skill.path, timeout: 3e4, stdio: "pipe" });
2686
3484
  console.log(`[skills] Ran teardown.sh for "${skill.name}"`);
2687
3485
  } catch (err) {
2688
3486
  console.warn(`[skills] teardown.sh failed for "${skill.name}":`, err.message);
@@ -3078,7 +3876,7 @@ var ToolRegistry = class {
3078
3876
  };
3079
3877
 
3080
3878
  // packages/runtime/src/tools/shell.ts
3081
- import { execSync as execSync2 } from "child_process";
3879
+ import { execSync as execSync3 } from "child_process";
3082
3880
  import { resolve as resolve7 } from "path";
3083
3881
  var MAX_OUTPUT = 5e4;
3084
3882
  function registerShellTool(registry, workspaceDir) {
@@ -3108,7 +3906,7 @@ function registerShellTool(registry, workspaceDir) {
3108
3906
  const timeout = (params.timeout || 30) * 1e3;
3109
3907
  const cwd = params.workdir ? resolve7(workspaceDir, params.workdir) : workspaceDir;
3110
3908
  try {
3111
- const output = execSync2(command, {
3909
+ const output = execSync3(command, {
3112
3910
  cwd,
3113
3911
  timeout,
3114
3912
  encoding: "utf-8",
@@ -3981,7 +4779,7 @@ function registerVisionTools(registry) {
3981
4779
  }
3982
4780
 
3983
4781
  // packages/runtime/src/tools/git.ts
3984
- import { execSync as execSync3 } from "child_process";
4782
+ import { execSync as execSync4 } from "child_process";
3985
4783
  import { resolve as resolve10, normalize } from "path";
3986
4784
  function resolveRepoPath(workspaceDir, repoPath) {
3987
4785
  if (!repoPath) return workspaceDir;
@@ -3994,7 +4792,7 @@ function resolveRepoPath(workspaceDir, repoPath) {
3994
4792
  return resolved;
3995
4793
  }
3996
4794
  function runGit(args, cwd) {
3997
- const output = execSync3(`git ${args}`, {
4795
+ const output = execSync4(`git ${args}`, {
3998
4796
  cwd,
3999
4797
  timeout: 3e4,
4000
4798
  encoding: "utf-8",
@@ -4401,7 +5199,7 @@ function registerBrowserTools(registry, workspaceDir) {
4401
5199
  }
4402
5200
 
4403
5201
  // packages/runtime/src/tools/system.ts
4404
- import { execSync as execSync4 } from "child_process";
5202
+ import { execSync as execSync5 } from "child_process";
4405
5203
  import * as os from "os";
4406
5204
  var MAX_OUTPUT3 = 5e4;
4407
5205
  function truncate(output) {
@@ -4412,7 +5210,7 @@ function truncate(output) {
4412
5210
  return output;
4413
5211
  }
4414
5212
  function exec(cmd, timeoutS = 10) {
4415
- return execSync4(cmd, {
5213
+ return execSync5(cmd, {
4416
5214
  encoding: "utf-8",
4417
5215
  timeout: timeoutS * 1e3,
4418
5216
  maxBuffer: 10 * 1024 * 1024,
@@ -5003,13 +5801,13 @@ ${lines.join("\n")}`;
5003
5801
  }
5004
5802
 
5005
5803
  // packages/runtime/src/tools/macos.ts
5006
- import { execSync as execSync5 } from "child_process";
5804
+ import { execSync as execSync6 } from "child_process";
5007
5805
  import { resolve as resolve14, normalize as normalize2 } from "path";
5008
5806
  import { mkdirSync as mkdirSync10, existsSync as existsSync13 } from "fs";
5009
5807
  import { randomUUID as randomUUID7 } from "crypto";
5010
5808
  var MAX_OUTPUT4 = 5e4;
5011
5809
  function shellExec(command, timeoutMs) {
5012
- return execSync5(command, {
5810
+ return execSync6(command, {
5013
5811
  timeout: timeoutMs,
5014
5812
  encoding: "utf-8",
5015
5813
  maxBuffer: 10 * 1024 * 1024,
@@ -5120,7 +5918,7 @@ ${output || err.message}`;
5120
5918
  async (params) => {
5121
5919
  const content = params.content;
5122
5920
  try {
5123
- execSync5("pbcopy", {
5921
+ execSync6("pbcopy", {
5124
5922
  input: content,
5125
5923
  timeout: 5e3,
5126
5924
  encoding: "utf-8",
@@ -5220,12 +6018,12 @@ function escapeAppleString(s) {
5220
6018
  }
5221
6019
 
5222
6020
  // packages/runtime/src/tools/data.ts
5223
- import { execSync as execSync6 } from "child_process";
6021
+ import { execSync as execSync7 } from "child_process";
5224
6022
  import { resolve as resolve15, normalize as normalize3, extname as extname2 } from "path";
5225
6023
  import { mkdirSync as mkdirSync11, existsSync as existsSync14 } from "fs";
5226
6024
  var MAX_OUTPUT5 = 5e4;
5227
6025
  function shellExec2(command, cwd, timeoutMs) {
5228
- return execSync6(command, {
6026
+ return execSync7(command, {
5229
6027
  cwd,
5230
6028
  timeout: timeoutMs,
5231
6029
  encoding: "utf-8",
@@ -5465,15 +6263,83 @@ function truncate2(text) {
5465
6263
  return text;
5466
6264
  }
5467
6265
 
5468
- // packages/runtime/src/tools/register.ts
6266
+ // packages/runtime/src/tools/coding-agent.ts
6267
+ import { execSync as execSync8 } from "child_process";
5469
6268
  import { resolve as resolve16 } from "path";
6269
+ var MAX_OUTPUT6 = 5e4;
6270
+ function registerCodingAgentTools(registry, workspaceDir) {
6271
+ registry.register(
6272
+ "coding_agent",
6273
+ "Spawn Claude Code CLI to perform a coding task. Use for writing code, debugging, refactoring, or any task that benefits from an AI coding assistant with full filesystem access. Requires the 'claude' CLI to be installed.",
6274
+ {
6275
+ type: "object",
6276
+ properties: {
6277
+ task: {
6278
+ type: "string",
6279
+ description: "The coding task or prompt to send to Claude Code"
6280
+ },
6281
+ workdir: {
6282
+ type: "string",
6283
+ description: "Working directory (relative to workspace). Defaults to workspace root."
6284
+ },
6285
+ timeout: {
6286
+ type: "number",
6287
+ description: "Timeout in seconds. Default: 300"
6288
+ }
6289
+ },
6290
+ required: ["task"]
6291
+ },
6292
+ async (params) => {
6293
+ const task = params.task;
6294
+ const timeoutSeconds = params.timeout || 300;
6295
+ const cwd = params.workdir ? resolve16(workspaceDir, params.workdir) : workspaceDir;
6296
+ try {
6297
+ execSync8("which claude", { stdio: "ignore" });
6298
+ } catch {
6299
+ return "Error: 'claude' CLI not found. Install Claude Code first: https://docs.anthropic.com/en/docs/claude-code";
6300
+ }
6301
+ const escapedTask = task.replace(/'/g, "'\\''");
6302
+ const command = `claude --dangerously-skip-permissions -p '${escapedTask}'`;
6303
+ try {
6304
+ const output = execSync8(command, {
6305
+ cwd,
6306
+ timeout: timeoutSeconds * 1e3,
6307
+ encoding: "utf-8",
6308
+ maxBuffer: 10 * 1024 * 1024,
6309
+ // 10MB
6310
+ shell: "/bin/sh",
6311
+ env: {
6312
+ ...process.env,
6313
+ PATH: `/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:${process.env.PATH}`
6314
+ }
6315
+ });
6316
+ const trimmed = output.length > MAX_OUTPUT6 ? output.slice(0, MAX_OUTPUT6) + `
6317
+ ... (truncated, ${output.length} total chars)` : output;
6318
+ return trimmed || "(no output)";
6319
+ } catch (err) {
6320
+ if (err.killed) {
6321
+ return `Error: Claude Code timed out after ${timeoutSeconds}s`;
6322
+ }
6323
+ const stderr = err.stderr?.toString() || "";
6324
+ const stdout = err.stdout?.toString() || "";
6325
+ const output = (stdout + "\n" + stderr).trim();
6326
+ const code = err.status ?? "unknown";
6327
+ return `Claude Code failed (exit code ${code}):
6328
+ ${output || err.message}`;
6329
+ }
6330
+ }
6331
+ );
6332
+ }
6333
+
6334
+ // packages/runtime/src/tools/register.ts
6335
+ import { resolve as resolve17 } from "path";
5470
6336
  import { mkdirSync as mkdirSync12, existsSync as existsSync15 } from "fs";
5471
6337
  function registerAllTools(hivemindHome, config) {
5472
6338
  const registry = new ToolRegistry();
5473
6339
  if (config?.enabled === false) {
5474
6340
  return registry;
5475
6341
  }
5476
- const workspaceDir = resolve16(hivemindHome, config?.workspace || "workspace");
6342
+ const workspaceDir = resolve17(hivemindHome, config?.workspace || "workspace");
5477
6343
  if (!existsSync15(workspaceDir)) {
5478
6344
  mkdirSync12(workspaceDir, { recursive: true });
5479
6345
  }
@@ -5481,7 +6347,7 @@ function registerAllTools(hivemindHome, config) {
5481
6347
  registerFileTools(registry, workspaceDir);
5482
6348
  registerWebTools(registry, { braveApiKey: config?.braveApiKey });
5483
6349
  registerMemoryTools(registry, config?.memoryDaemonUrl || "http://localhost:3434");
5484
- const dataDir = resolve16(hivemindHome, "data");
6350
+ const dataDir = resolve17(hivemindHome, "data");
5485
6351
  registerEventTools(registry, dataDir);
5486
6352
  if (config?.configPath && !process.env.SPAWN_TASK) {
5487
6353
  registerSpawnTools(registry, hivemindHome, dataDir, config.configPath);
@@ -5494,6 +6360,7 @@ function registerAllTools(hivemindHome, config) {
5494
6360
  registerWatchTools(registry, workspaceDir, dataDir);
5495
6361
  registerMacOSTools(registry, workspaceDir);
5496
6362
  registerDataTools(registry, workspaceDir);
6363
+ registerCodingAgentTools(registry, workspaceDir);
5497
6364
  return registry;
5498
6365
  }
5499
6366
 
@@ -5531,9 +6398,9 @@ function registerMessagingTools(registry, sesame) {
5531
6398
 
5532
6399
  // packages/runtime/src/tools/skills-tools.ts
5533
6400
  import { existsSync as existsSync16, mkdirSync as mkdirSync13, writeFileSync as writeFileSync6, rmSync } from "fs";
5534
- import { resolve as resolve17 } from "path";
6401
+ import { resolve as resolve18 } from "path";
5535
6402
  function registerSkillsTools(registry, skillsEngine, workspaceDir) {
5536
- const skillsDir = resolve17(workspaceDir, "skills");
6403
+ const skillsDir = resolve18(workspaceDir, "skills");
5537
6404
  registry.register(
5538
6405
  "skill_list",
5539
6406
  "List all loaded skills with their registered tools and status.",
@@ -5600,7 +6467,7 @@ ${lines.join("\n\n")}`;
5600
6467
  const name = params.name;
5601
6468
  const description = params.description;
5602
6469
  const tools = params.tools;
5603
- const skillDir = resolve17(skillsDir, name);
6470
+ const skillDir = resolve18(skillsDir, name);
5604
6471
  if (existsSync16(skillDir)) {
5605
6472
  return `Error: Skill directory "${name}" already exists. Use skill_reload to update it.`;
5606
6473
  }
@@ -5614,7 +6481,7 @@ description: "${description}"
5614
6481
 
5615
6482
  ${description}
5616
6483
  `;
5617
- writeFileSync6(resolve17(skillDir, "SKILL.md"), skillMd);
6484
+ writeFileSync6(resolve18(skillDir, "SKILL.md"), skillMd);
5618
6485
  if (tools && tools.length > 0) {
5619
6486
  const toolsDef = {
5620
6487
  tools: tools.map((t) => ({
@@ -5624,7 +6491,7 @@ ${description}
5624
6491
  command: t.command
5625
6492
  }))
5626
6493
  };
5627
- writeFileSync6(resolve17(skillDir, "tools.json"), JSON.stringify(toolsDef, null, 2) + "\n");
6494
+ writeFileSync6(resolve18(skillDir, "tools.json"), JSON.stringify(toolsDef, null, 2) + "\n");
5628
6495
  }
5629
6496
  try {
5630
6497
  await skillsEngine.loadSkill(name);
@@ -5677,7 +6544,7 @@ Path: ${skillDir}`;
5677
6544
  },
5678
6545
  async (params) => {
5679
6546
  const name = params.name;
5680
- const skillDir = resolve17(skillsDir, name);
6547
+ const skillDir = resolve18(skillsDir, name);
5681
6548
  if (!existsSync16(skillDir)) {
5682
6549
  return `Error: Skill directory "${name}" does not exist.`;
5683
6550
  }
@@ -5698,12 +6565,12 @@ Path: ${skillDir}`;
5698
6565
 
5699
6566
  // packages/runtime/src/pipeline.ts
5700
6567
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, unlinkSync as unlinkSync3 } from "fs";
5701
- import { resolve as resolve18, dirname as dirname7 } from "path";
6568
+ import { resolve as resolve19, dirname as dirname7 } from "path";
5702
6569
  import { fileURLToPath as fileURLToPath3 } from "url";
5703
6570
  var PACKAGE_VERSION = "unknown";
5704
6571
  try {
5705
6572
  const __dirname2 = dirname7(fileURLToPath3(import.meta.url));
5706
- const pkg = JSON.parse(readFileSync12(resolve18(__dirname2, "../package.json"), "utf-8"));
6573
+ const pkg = JSON.parse(readFileSync12(resolve19(__dirname2, "../package.json"), "utf-8"));
5707
6574
  PACKAGE_VERSION = pkg.version ?? "unknown";
5708
6575
  } catch {
5709
6576
  }
@@ -5775,11 +6642,11 @@ async function startPipeline(configPath) {
5775
6642
  console.log("[hivemind] Global context already exists in memory daemon");
5776
6643
  }
5777
6644
  }
5778
- const requestLogger = new RequestLogger(resolve18(dirname7(configPath), "data", "dashboard.db"));
6645
+ const requestLogger = new RequestLogger(resolve19(dirname7(configPath), "data", "dashboard.db"));
5779
6646
  startDashboardServer(requestLogger, config.memory);
5780
6647
  const agent = new Agent(config);
5781
6648
  agent.setRequestLogger(requestLogger);
5782
- const hivemindHome = process.env.HIVEMIND_HOME || resolve18(process.env.HOME || "/root", "hivemind");
6649
+ const hivemindHome = process.env.HIVEMIND_HOME || resolve19(process.env.HOME || "/root", "hivemind");
5783
6650
  const toolRegistry = registerAllTools(hivemindHome, {
5784
6651
  enabled: true,
5785
6652
  workspace: config.agent.workspace || "workspace",
@@ -5787,7 +6654,7 @@ async function startPipeline(configPath) {
5787
6654
  memoryDaemonUrl: config.memory.daemon_url,
5788
6655
  configPath
5789
6656
  });
5790
- const workspaceDir = resolve18(hivemindHome, config.agent.workspace || "workspace");
6657
+ const workspaceDir = resolve19(hivemindHome, config.agent.workspace || "workspace");
5791
6658
  const skillsEngine = new SkillsEngine(workspaceDir, toolRegistry);
5792
6659
  await skillsEngine.loadAll();
5793
6660
  registerSkillsTools(toolRegistry, skillsEngine, workspaceDir);
@@ -5795,7 +6662,7 @@ async function startPipeline(configPath) {
5795
6662
  process.on("exit", () => skillsEngine.stopWatching());
5796
6663
  agent.setToolRegistry(toolRegistry);
5797
6664
  console.log(`[hivemind] Context manager initialized (active: ${agent.getActiveContext()})`);
5798
- const dataDir = resolve18(hivemindHome, "data");
6665
+ const dataDir = resolve19(hivemindHome, "data");
5799
6666
  if (config.sesame.api_key) {
5800
6667
  await startSesameLoop(config, agent, toolRegistry, dataDir);
5801
6668
  } else {
@@ -5969,8 +6836,8 @@ ${response.content}
5969
6836
  console.error("Error:", err.message);
5970
6837
  }
5971
6838
  });
5972
- return new Promise((resolve19) => {
5973
- rl.on("close", resolve19);
6839
+ return new Promise((resolve20) => {
6840
+ rl.on("close", resolve20);
5974
6841
  });
5975
6842
  }
5976
6843
  async function runSpawnTask(config, configPath) {
@@ -5981,7 +6848,7 @@ async function runSpawnTask(config, configPath) {
5981
6848
  const spawnDir = process.env.SPAWN_DIR;
5982
6849
  console.log(`[spawn] Sub-agent starting (id: ${spawnId}, context: ${context})`);
5983
6850
  const agent = new Agent(config, context);
5984
- const hivemindHome = process.env.HIVEMIND_HOME || resolve18(process.env.HOME || "/root", "hivemind");
6851
+ const hivemindHome = process.env.HIVEMIND_HOME || resolve19(process.env.HOME || "/root", "hivemind");
5985
6852
  const toolRegistry = registerAllTools(hivemindHome, {
5986
6853
  enabled: true,
5987
6854
  workspace: config.agent.workspace || "workspace",
@@ -5994,7 +6861,7 @@ async function runSpawnTask(config, configPath) {
5994
6861
  const result = response.content;
5995
6862
  console.log(`[spawn] Task completed (context: ${response.context})`);
5996
6863
  if (spawnDir) {
5997
- writeFileSync7(resolve18(spawnDir, "result.txt"), result);
6864
+ writeFileSync7(resolve19(spawnDir, "result.txt"), result);
5998
6865
  }
5999
6866
  if (channelId && config.sesame.api_key) {
6000
6867
  try {
@@ -6011,7 +6878,7 @@ async function runSpawnTask(config, configPath) {
6011
6878
  const errorMsg = `[SPAWN ERROR] ${err.message}`;
6012
6879
  console.error(`[spawn] ${errorMsg}`);
6013
6880
  if (spawnDir) {
6014
- writeFileSync7(resolve18(spawnDir, "result.txt"), errorMsg);
6881
+ writeFileSync7(resolve19(spawnDir, "result.txt"), errorMsg);
6015
6882
  }
6016
6883
  process.exitCode = 1;
6017
6884
  }
@@ -6042,20 +6909,20 @@ var WorkerServer = class {
6042
6909
  }
6043
6910
  /** Start listening. */
6044
6911
  async start() {
6045
- return new Promise((resolve19, reject) => {
6912
+ return new Promise((resolve20, reject) => {
6046
6913
  this.server = createServer4((req, res) => this.handleRequest(req, res));
6047
6914
  this.server.on("error", reject);
6048
- this.server.listen(this.port, () => resolve19());
6915
+ this.server.listen(this.port, () => resolve20());
6049
6916
  });
6050
6917
  }
6051
6918
  /** Stop the server. */
6052
6919
  async stop() {
6053
- return new Promise((resolve19) => {
6920
+ return new Promise((resolve20) => {
6054
6921
  if (!this.server) {
6055
- resolve19();
6922
+ resolve20();
6056
6923
  return;
6057
6924
  }
6058
- this.server.close(() => resolve19());
6925
+ this.server.close(() => resolve20());
6059
6926
  });
6060
6927
  }
6061
6928
  getPort() {
@@ -6178,10 +7045,10 @@ var WorkerServer = class {
6178
7045
  }
6179
7046
  };
6180
7047
  function readBody(req) {
6181
- return new Promise((resolve19, reject) => {
7048
+ return new Promise((resolve20, reject) => {
6182
7049
  const chunks = [];
6183
7050
  req.on("data", (chunk) => chunks.push(chunk));
6184
- req.on("end", () => resolve19(Buffer.concat(chunks).toString("utf-8")));
7051
+ req.on("end", () => resolve20(Buffer.concat(chunks).toString("utf-8")));
6185
7052
  req.on("error", reject);
6186
7053
  });
6187
7054
  }
@@ -6448,6 +7315,7 @@ async function startWorker(config) {
6448
7315
  }
6449
7316
 
6450
7317
  export {
7318
+ getClaudeCodeOAuthToken,
6451
7319
  LLMClient,
6452
7320
  MemoryClient,
6453
7321
  ContextManager,
@@ -6463,7 +7331,8 @@ export {
6463
7331
  EventsWatcher,
6464
7332
  defaultSentinelConfig,
6465
7333
  loadConfig,
6466
- SesameClient2 as SesameClient,
7334
+ SesameClient,
7335
+ SesameClient2,
6467
7336
  HEALTH_PATH,
6468
7337
  SkillsEngine,
6469
7338
  startPipeline,
@@ -6515,4 +7384,4 @@ smol-toml/dist/index.js:
6515
7384
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6516
7385
  *)
6517
7386
  */
6518
- //# sourceMappingURL=chunk-6S5UKFTZ.js.map
7387
+ //# sourceMappingURL=chunk-S4QRR3ZJ.js.map