@sesamespace/hivemind 0.8.5 → 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.
@@ -1,8 +1,5 @@
1
- import {
2
- SesameClient
3
- } from "./chunk-GPI4RU7N.js";
4
-
5
1
  // packages/runtime/src/llm-client.ts
2
+ import { execSync } from "child_process";
6
3
  function convertMessagesForAnthropic(messages) {
7
4
  let system = "";
8
5
  const converted = [];
@@ -75,6 +72,24 @@ function parseAnthropicResponse(data) {
75
72
  } : void 0
76
73
  };
77
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
+ }
78
93
  var LLMClient = class {
79
94
  baseUrl;
80
95
  model;
@@ -89,6 +104,20 @@ var LLMClient = class {
89
104
  this.temperature = config.temperature;
90
105
  this.apiKey = config.api_key ?? "";
91
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
+ }
92
121
  }
93
122
  /**
94
123
  * Simple chat completion (no tools). Backwards compatible.
@@ -2472,6 +2501,16 @@ function loadConfig(path) {
2472
2501
  parsed.llm.base_url = "https://api.anthropic.com";
2473
2502
  }
2474
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
+ }
2475
2514
  if (process.env.LLM_PROVIDER) {
2476
2515
  parsed.llm.provider = process.env.LLM_PROVIDER;
2477
2516
  }
@@ -2519,6 +2558,626 @@ function loadConfig(path) {
2519
2558
  return parsed;
2520
2559
  }
2521
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
+
2522
3181
  // packages/runtime/src/sesame.ts
2523
3182
  import { readFileSync as readFileSync5 } from "fs";
2524
3183
  import { resolve as resolve4, dirname as dirname3 } from "path";
@@ -2688,7 +3347,7 @@ var SesameClient2 = class {
2688
3347
  };
2689
3348
 
2690
3349
  // packages/runtime/src/skills.ts
2691
- import { execSync } from "child_process";
3350
+ import { execSync as execSync2 } from "child_process";
2692
3351
  import { existsSync as existsSync5, readFileSync as readFileSync6, readdirSync as readdirSync3, watch as watch2, mkdirSync as mkdirSync3 } from "fs";
2693
3352
  import { resolve as resolve5 } from "path";
2694
3353
  function shellEscape(value) {
@@ -2757,7 +3416,7 @@ var SkillsEngine = class {
2757
3416
  const setupPath = resolve5(skillDir, "setup.sh");
2758
3417
  if (existsSync5(setupPath)) {
2759
3418
  try {
2760
- execSync("bash setup.sh", { cwd: skillDir, timeout: 3e4, stdio: "pipe" });
3419
+ execSync2("bash setup.sh", { cwd: skillDir, timeout: 3e4, stdio: "pipe" });
2761
3420
  console.log(`[skills] Ran setup.sh for "${name}"`);
2762
3421
  } catch (err) {
2763
3422
  console.warn(`[skills] setup.sh failed for "${name}":`, err.message);
@@ -2782,7 +3441,7 @@ var SkillsEngine = class {
2782
3441
  async (params) => {
2783
3442
  const cmd = renderCommand(commandTemplate, params, skillDir, this.workspaceDir);
2784
3443
  try {
2785
- const output = execSync(cmd, {
3444
+ const output = execSync2(cmd, {
2786
3445
  cwd: skillDir,
2787
3446
  timeout: 6e4,
2788
3447
  encoding: "utf-8",
@@ -2821,7 +3480,7 @@ var SkillsEngine = class {
2821
3480
  const teardownPath = resolve5(skill.path, "teardown.sh");
2822
3481
  if (existsSync5(teardownPath)) {
2823
3482
  try {
2824
- execSync("bash teardown.sh", { cwd: skill.path, timeout: 3e4, stdio: "pipe" });
3483
+ execSync2("bash teardown.sh", { cwd: skill.path, timeout: 3e4, stdio: "pipe" });
2825
3484
  console.log(`[skills] Ran teardown.sh for "${skill.name}"`);
2826
3485
  } catch (err) {
2827
3486
  console.warn(`[skills] teardown.sh failed for "${skill.name}":`, err.message);
@@ -3217,7 +3876,7 @@ var ToolRegistry = class {
3217
3876
  };
3218
3877
 
3219
3878
  // packages/runtime/src/tools/shell.ts
3220
- import { execSync as execSync2 } from "child_process";
3879
+ import { execSync as execSync3 } from "child_process";
3221
3880
  import { resolve as resolve7 } from "path";
3222
3881
  var MAX_OUTPUT = 5e4;
3223
3882
  function registerShellTool(registry, workspaceDir) {
@@ -3247,7 +3906,7 @@ function registerShellTool(registry, workspaceDir) {
3247
3906
  const timeout = (params.timeout || 30) * 1e3;
3248
3907
  const cwd = params.workdir ? resolve7(workspaceDir, params.workdir) : workspaceDir;
3249
3908
  try {
3250
- const output = execSync2(command, {
3909
+ const output = execSync3(command, {
3251
3910
  cwd,
3252
3911
  timeout,
3253
3912
  encoding: "utf-8",
@@ -4120,7 +4779,7 @@ function registerVisionTools(registry) {
4120
4779
  }
4121
4780
 
4122
4781
  // packages/runtime/src/tools/git.ts
4123
- import { execSync as execSync3 } from "child_process";
4782
+ import { execSync as execSync4 } from "child_process";
4124
4783
  import { resolve as resolve10, normalize } from "path";
4125
4784
  function resolveRepoPath(workspaceDir, repoPath) {
4126
4785
  if (!repoPath) return workspaceDir;
@@ -4133,7 +4792,7 @@ function resolveRepoPath(workspaceDir, repoPath) {
4133
4792
  return resolved;
4134
4793
  }
4135
4794
  function runGit(args, cwd) {
4136
- const output = execSync3(`git ${args}`, {
4795
+ const output = execSync4(`git ${args}`, {
4137
4796
  cwd,
4138
4797
  timeout: 3e4,
4139
4798
  encoding: "utf-8",
@@ -4540,7 +5199,7 @@ function registerBrowserTools(registry, workspaceDir) {
4540
5199
  }
4541
5200
 
4542
5201
  // packages/runtime/src/tools/system.ts
4543
- import { execSync as execSync4 } from "child_process";
5202
+ import { execSync as execSync5 } from "child_process";
4544
5203
  import * as os from "os";
4545
5204
  var MAX_OUTPUT3 = 5e4;
4546
5205
  function truncate(output) {
@@ -4551,7 +5210,7 @@ function truncate(output) {
4551
5210
  return output;
4552
5211
  }
4553
5212
  function exec(cmd, timeoutS = 10) {
4554
- return execSync4(cmd, {
5213
+ return execSync5(cmd, {
4555
5214
  encoding: "utf-8",
4556
5215
  timeout: timeoutS * 1e3,
4557
5216
  maxBuffer: 10 * 1024 * 1024,
@@ -5142,13 +5801,13 @@ ${lines.join("\n")}`;
5142
5801
  }
5143
5802
 
5144
5803
  // packages/runtime/src/tools/macos.ts
5145
- import { execSync as execSync5 } from "child_process";
5804
+ import { execSync as execSync6 } from "child_process";
5146
5805
  import { resolve as resolve14, normalize as normalize2 } from "path";
5147
5806
  import { mkdirSync as mkdirSync10, existsSync as existsSync13 } from "fs";
5148
5807
  import { randomUUID as randomUUID7 } from "crypto";
5149
5808
  var MAX_OUTPUT4 = 5e4;
5150
5809
  function shellExec(command, timeoutMs) {
5151
- return execSync5(command, {
5810
+ return execSync6(command, {
5152
5811
  timeout: timeoutMs,
5153
5812
  encoding: "utf-8",
5154
5813
  maxBuffer: 10 * 1024 * 1024,
@@ -5259,7 +5918,7 @@ ${output || err.message}`;
5259
5918
  async (params) => {
5260
5919
  const content = params.content;
5261
5920
  try {
5262
- execSync5("pbcopy", {
5921
+ execSync6("pbcopy", {
5263
5922
  input: content,
5264
5923
  timeout: 5e3,
5265
5924
  encoding: "utf-8",
@@ -5359,12 +6018,12 @@ function escapeAppleString(s) {
5359
6018
  }
5360
6019
 
5361
6020
  // packages/runtime/src/tools/data.ts
5362
- import { execSync as execSync6 } from "child_process";
6021
+ import { execSync as execSync7 } from "child_process";
5363
6022
  import { resolve as resolve15, normalize as normalize3, extname as extname2 } from "path";
5364
6023
  import { mkdirSync as mkdirSync11, existsSync as existsSync14 } from "fs";
5365
6024
  var MAX_OUTPUT5 = 5e4;
5366
6025
  function shellExec2(command, cwd, timeoutMs) {
5367
- return execSync6(command, {
6026
+ return execSync7(command, {
5368
6027
  cwd,
5369
6028
  timeout: timeoutMs,
5370
6029
  encoding: "utf-8",
@@ -5605,7 +6264,7 @@ function truncate2(text) {
5605
6264
  }
5606
6265
 
5607
6266
  // packages/runtime/src/tools/coding-agent.ts
5608
- import { execSync as execSync7 } from "child_process";
6267
+ import { execSync as execSync8 } from "child_process";
5609
6268
  import { resolve as resolve16 } from "path";
5610
6269
  var MAX_OUTPUT6 = 5e4;
5611
6270
  function registerCodingAgentTools(registry, workspaceDir) {
@@ -5635,14 +6294,14 @@ function registerCodingAgentTools(registry, workspaceDir) {
5635
6294
  const timeoutSeconds = params.timeout || 300;
5636
6295
  const cwd = params.workdir ? resolve16(workspaceDir, params.workdir) : workspaceDir;
5637
6296
  try {
5638
- execSync7("which claude", { stdio: "ignore" });
6297
+ execSync8("which claude", { stdio: "ignore" });
5639
6298
  } catch {
5640
6299
  return "Error: 'claude' CLI not found. Install Claude Code first: https://docs.anthropic.com/en/docs/claude-code";
5641
6300
  }
5642
6301
  const escapedTask = task.replace(/'/g, "'\\''");
5643
6302
  const command = `claude --dangerously-skip-permissions -p '${escapedTask}'`;
5644
6303
  try {
5645
- const output = execSync7(command, {
6304
+ const output = execSync8(command, {
5646
6305
  cwd,
5647
6306
  timeout: timeoutSeconds * 1e3,
5648
6307
  encoding: "utf-8",
@@ -6656,6 +7315,7 @@ async function startWorker(config) {
6656
7315
  }
6657
7316
 
6658
7317
  export {
7318
+ getClaudeCodeOAuthToken,
6659
7319
  LLMClient,
6660
7320
  MemoryClient,
6661
7321
  ContextManager,
@@ -6671,7 +7331,8 @@ export {
6671
7331
  EventsWatcher,
6672
7332
  defaultSentinelConfig,
6673
7333
  loadConfig,
6674
- SesameClient2 as SesameClient,
7334
+ SesameClient,
7335
+ SesameClient2,
6675
7336
  HEALTH_PATH,
6676
7337
  SkillsEngine,
6677
7338
  startPipeline,
@@ -6723,4 +7384,4 @@ smol-toml/dist/index.js:
6723
7384
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6724
7385
  *)
6725
7386
  */
6726
- //# sourceMappingURL=chunk-Q5ZO5WXM.js.map
7387
+ //# sourceMappingURL=chunk-S4QRR3ZJ.js.map