@sideboard-ai/core 0.1.262 → 0.1.264

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 (55) hide show
  1. package/dist/{abletime-OQ4PC52L.js → abletime-6AOJI2YZ.js} +4 -4
  2. package/dist/{abletime-CDGINDXG.js → abletime-U75ZGDIX.js} +5 -5
  3. package/dist/{abletime-oauth-KX2TDFTE.js → abletime-oauth-LOAHGG4X.js} +3 -3
  4. package/dist/{abletime-oauth-5A5EOH2A.js → abletime-oauth-TA2YDCYX.js} +4 -4
  5. package/dist/{abletime-rest-UEHOBLXD.js → abletime-rest-CTA5WV26.js} +4 -4
  6. package/dist/{abletime-rest-PUGKYTRR.js → abletime-rest-YZPFM6IY.js} +3 -3
  7. package/dist/agents/claude-runner.cjs +463 -0
  8. package/dist/agents/claude-runner.d.cts +1 -0
  9. package/dist/agents/claude-runner.d.ts +1 -0
  10. package/dist/agents/claude-runner.js +134 -0
  11. package/dist/agents/cursor-runner.cjs +393 -8
  12. package/dist/agents/cursor-runner.js +39 -8
  13. package/dist/{agents-J2P4KNEY.js → agents-3TUMFSMH.js} +10 -9
  14. package/dist/{agents-IKVUGW5H.js → agents-6FWDRVA2.js} +4 -4
  15. package/dist/{app-settings-OM7H64YM.js → app-settings-MVZPM6WW.js} +1 -1
  16. package/dist/{app-settings-VQEUCONM.js → app-settings-RKFFUIFQ.js} +2 -2
  17. package/dist/{chunk-6PFZ6XO7.js → chunk-2QUQH2SZ.js} +81 -6
  18. package/dist/{chunk-VIC6TDYT.js → chunk-36FOBJBF.js} +76 -3
  19. package/dist/{chunk-ABPNIYRS.js → chunk-3H7O27X2.js} +389 -102
  20. package/dist/{chunk-FSZ7YYFQ.js → chunk-4ALDX5IO.js} +5 -3
  21. package/dist/{chunk-5OKJDCBK.js → chunk-5PK53SAP.js} +5 -5
  22. package/dist/{chunk-U3AOJLH3.js → chunk-5ZPT5YAV.js} +8 -6
  23. package/dist/{chunk-YFTO7U2A.js → chunk-6YOXQVJ7.js} +3 -3
  24. package/dist/{chunk-J6ONZP74.js → chunk-6YY7XPPL.js} +5 -5
  25. package/dist/{chunk-WV7KJH2E.js → chunk-A5SAYFJ4.js} +1 -0
  26. package/dist/{chunk-B6XFBNYM.js → chunk-BOMSJUXW.js} +2 -2
  27. package/dist/{chunk-S7VDDJ34.js → chunk-CEOTK5GZ.js} +3 -3
  28. package/dist/{chunk-4F7J6UWD.js → chunk-EK3KVT7I.js} +515 -139
  29. package/dist/{chunk-HHEKVR6C.js → chunk-F5MFNUAA.js} +40 -2
  30. package/dist/{chunk-KVQX62XI.js → chunk-K7B25HO4.js} +3 -3
  31. package/dist/{chunk-JTNY5CK4.js → chunk-L5WGAIL2.js} +46 -46
  32. package/dist/chunk-NYBFYFK7.js +415 -0
  33. package/dist/{chunk-GIZQAOHZ.js → chunk-QX6QUZVD.js} +121 -91
  34. package/dist/{chunk-X2OTZ36G.js → chunk-RKPBIB2U.js} +52 -52
  35. package/dist/{chunk-W5PWGEKS.js → chunk-T3AYRQJZ.js} +107 -77
  36. package/dist/{chunk-D554YCHG.js → chunk-YKYEHDMX.js} +2 -2
  37. package/dist/connected-teams-RU6VATCM.js +1 -1
  38. package/dist/{coordinator-prompt-VQHQ3RIX.js → coordinator-prompt-HZCQZ6C5.js} +6 -6
  39. package/dist/{coordinator-prompt-TU6656OK.js → coordinator-prompt-J7DKHOCH.js} +3 -3
  40. package/dist/{global-workspace-PHF2MOGW.js → global-workspace-6LDUZ2NF.js} +3 -3
  41. package/dist/{global-workspace-47NZVA44.js → global-workspace-TI26K25J.js} +6 -6
  42. package/dist/index.cjs +1712 -721
  43. package/dist/index.d.cts +181 -41
  44. package/dist/index.d.ts +181 -41
  45. package/dist/index.js +693 -285
  46. package/dist/mcp/run-stdio.cjs +10469 -9896
  47. package/dist/mcp/run-stdio.js +193 -168
  48. package/dist/{orchestrator-VLTO5JBR.js → orchestrator-4JSG7BWC.js} +5 -5
  49. package/dist/{orchestrator-OCG4QVA5.js → orchestrator-5YU46YNS.js} +11 -10
  50. package/dist/{workspaces-I7TWFTJM.js → workspaces-QJ3XIPUJ.js} +6 -6
  51. package/dist/{workspaces-2XTDS7N2.js → workspaces-WOQHJFRQ.js} +3 -3
  52. package/dist/{worktree-DDDF3WHV.js → worktree-6U2FA5LO.js} +2 -2
  53. package/dist/{worktree-YASFE65H.js → worktree-KQA4ON2G.js} +5 -5
  54. package/package.json +4 -3
  55. /package/dist/{chunk-LDXSAVWO.js → chunk-GWFVCCJZ.js} +0 -0
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ AGENT_RPC_CLAUDE_SDK_SERVER,
4
+ PILOT_TOOL_DESCRIPTIONS,
5
+ createPilotRpcExecutors
6
+ } from "../chunk-NYBFYFK7.js";
7
+ import {
8
+ dropNestedElectronEnvFromProcess
9
+ } from "../chunk-4TR3HZFT.js";
10
+ import "../chunk-EHT2DRT4.js";
11
+
12
+ // src/agents/claude-runner.ts
13
+ import { createInterface } from "readline";
14
+
15
+ // src/agents/claude-sdk-tools.ts
16
+ import { z } from "zod";
17
+ function textResult(text) {
18
+ return { content: [{ type: "text", text }] };
19
+ }
20
+ function createClaudePilotSdkServer(createSdkMcpServer, tool, opts) {
21
+ const exec = createPilotRpcExecutors(opts);
22
+ const server = createSdkMcpServer({
23
+ name: AGENT_RPC_CLAUDE_SDK_SERVER,
24
+ version: "1.0.0",
25
+ timeout: 18e4,
26
+ tools: [
27
+ tool(
28
+ "present_artifact",
29
+ PILOT_TOOL_DESCRIPTIONS.present_artifact,
30
+ {
31
+ title: z.string(),
32
+ type: z.enum(["html", "svg", "markdown", "react", "log"]),
33
+ content: z.string(),
34
+ artifact_id: z.string().optional(),
35
+ status: z.enum(["running", "ok", "failed", "idle"]).optional(),
36
+ phase: z.string().optional(),
37
+ mode: z.enum(["append", "replace"]).optional()
38
+ },
39
+ async (args) => textResult(await exec.present_artifact(args))
40
+ ),
41
+ tool(
42
+ "wait_for_job",
43
+ PILOT_TOOL_DESCRIPTIONS.wait_for_job,
44
+ { id: z.string() },
45
+ async (args) => textResult(await exec.wait_for_job(args))
46
+ ),
47
+ tool(
48
+ "stop_job",
49
+ PILOT_TOOL_DESCRIPTIONS.stop_job,
50
+ { id: z.string(), reason: z.string().optional() },
51
+ async (args) => textResult(await exec.stop_job(args))
52
+ )
53
+ ]
54
+ });
55
+ return { server, exec };
56
+ }
57
+
58
+ // src/agents/claude-runner.ts
59
+ dropNestedElectronEnvFromProcess();
60
+ function emit(value) {
61
+ process.stdout.write(`${JSON.stringify(value)}
62
+ `);
63
+ }
64
+ async function readStdin() {
65
+ const rl = createInterface({ input: process.stdin, crlfDelay: Infinity });
66
+ const chunks = [];
67
+ for await (const line of rl) chunks.push(line);
68
+ return chunks.join("\n").trim();
69
+ }
70
+ async function main() {
71
+ const raw = await readStdin();
72
+ if (!raw) {
73
+ emit({ type: "stderr", data: "claude-runner: empty stdin" });
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+ const req = JSON.parse(raw);
78
+ if (!req.prompt || !req.cwd || !req.agentRpc || !req.claudePath) {
79
+ emit({ type: "stderr", data: "claude-runner: prompt, cwd, claudePath, and agentRpc are required" });
80
+ process.exitCode = 1;
81
+ return;
82
+ }
83
+ let sdk;
84
+ try {
85
+ sdk = await import("@anthropic-ai/claude-agent-sdk");
86
+ } catch (err) {
87
+ const message = err instanceof Error ? err.message : String(err);
88
+ emit({
89
+ type: "stderr",
90
+ data: `claude-runner: @anthropic-ai/claude-agent-sdk is required (${message})`
91
+ });
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+ const { server, exec } = createClaudePilotSdkServer(
96
+ sdk.createSdkMcpServer,
97
+ sdk.tool,
98
+ { cwd: req.cwd, rpc: req.agentRpc }
99
+ );
100
+ const mcpServers = {
101
+ [AGENT_RPC_CLAUDE_SDK_SERVER]: server
102
+ };
103
+ for (const [name, spec] of Object.entries(req.mcpServers ?? {})) {
104
+ mcpServers[name] = spec;
105
+ }
106
+ try {
107
+ const options = {
108
+ cwd: req.cwd,
109
+ pathToClaudeCodeExecutable: req.claudePath,
110
+ permissionMode: req.permissionMode,
111
+ allowedTools: req.allowedTools,
112
+ mcpServers,
113
+ includePartialMessages: true
114
+ };
115
+ if (req.sessionId) options.resume = req.sessionId;
116
+ if (req.model) options.model = req.model;
117
+ if (req.systemPrompt) options.appendSystemPrompt = req.systemPrompt;
118
+ if (req.effort) options.effort = req.effort;
119
+ if (req.chrome) options.chrome = true;
120
+ options.settingSources = [];
121
+ for await (const message of sdk.query({ prompt: req.prompt, options })) {
122
+ emit(message);
123
+ }
124
+ } finally {
125
+ exec.close();
126
+ }
127
+ }
128
+ main().catch((err) => {
129
+ emit({
130
+ type: "stderr",
131
+ data: err instanceof Error ? err.message : String(err)
132
+ });
133
+ process.exitCode = 1;
134
+ });
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/agents/cursor-runner.ts
27
- var import_node_fs16 = require("fs");
27
+ var import_node_fs17 = require("fs");
28
28
  var import_node_readline2 = require("readline");
29
29
 
30
30
  // src/hook/nested-electron-env.ts
@@ -716,9 +716,365 @@ function slicedReadCustomToolConfig(cwd) {
716
716
  };
717
717
  }
718
718
 
719
- // src/agents/tool-result-clip.ts
719
+ // src/agent-rpc/client.ts
720
+ var import_ws = require("ws");
721
+
722
+ // src/agent-rpc/protocol.ts
723
+ var AGENT_RPC_PROTOCOL_VERSION = 1;
724
+ var AGENT_RPC_TOKEN_QUERY = "authToken";
725
+ function isJsonRpcNotification(value) {
726
+ if (!value || typeof value !== "object") return false;
727
+ const rec = value;
728
+ if (rec.jsonrpc !== "2.0") return false;
729
+ if (typeof rec.method !== "string" || !rec.method.trim()) return false;
730
+ if ("id" in rec && rec.id !== void 0) return false;
731
+ if ("error" in rec || "result" in rec) return false;
732
+ return true;
733
+ }
734
+ function parseRpcFrame(raw) {
735
+ try {
736
+ return JSON.parse(raw);
737
+ } catch {
738
+ return void 0;
739
+ }
740
+ }
741
+
742
+ // src/agent-rpc/metadata.ts
720
743
  var import_node_fs15 = require("fs");
721
744
  var import_node_path17 = require("path");
745
+ function agentRuntimeMetadataPath() {
746
+ return (0, import_node_path17.join)(appDataDir(), "agent-runtime.json");
747
+ }
748
+ function readAgentRuntimeMetadata() {
749
+ try {
750
+ const raw = JSON.parse((0, import_node_fs15.readFileSync)(agentRuntimeMetadataPath(), "utf8"));
751
+ if (!raw || typeof raw !== "object") return null;
752
+ const rec = raw;
753
+ if (typeof rec.runtimeId !== "string" || !rec.runtimeId.trim()) return null;
754
+ if (typeof rec.authToken !== "string" || !rec.authToken.trim()) return null;
755
+ const pid = Number(rec.pid);
756
+ if (!Number.isInteger(pid) || pid <= 0) return null;
757
+ const transports = Array.isArray(rec.transports) ? rec.transports : [];
758
+ const ws = transports.filter((t) => {
759
+ if (!t || typeof t !== "object") return false;
760
+ const row = t;
761
+ return row.kind === "websocket" && typeof row.url === "string" && Boolean(row.url.trim());
762
+ });
763
+ return {
764
+ runtimeId: rec.runtimeId.trim(),
765
+ pid,
766
+ protocolVersion: Number(rec.protocolVersion) || AGENT_RPC_PROTOCOL_VERSION,
767
+ authToken: rec.authToken,
768
+ startedAt: Number(rec.startedAt) || 0,
769
+ transports: ws
770
+ };
771
+ } catch {
772
+ return null;
773
+ }
774
+ }
775
+ function websocketUrlFromMetadata(meta) {
776
+ const url = meta?.transports.find((t) => t.kind === "websocket")?.url?.trim();
777
+ return url || null;
778
+ }
779
+ function agentRpcConnectFromMetadata(meta = readAgentRuntimeMetadata()) {
780
+ if (!agentRuntimeLooksLive(meta)) return null;
781
+ const url = websocketUrlFromMetadata(meta);
782
+ const authToken = meta?.authToken;
783
+ if (!url || !authToken) return null;
784
+ return { url, authToken };
785
+ }
786
+ function pidAlive(pid) {
787
+ try {
788
+ process.kill(pid, 0);
789
+ return true;
790
+ } catch {
791
+ return false;
792
+ }
793
+ }
794
+ function agentRuntimeLooksLive(meta = readAgentRuntimeMetadata()) {
795
+ if (!meta) return false;
796
+ return pidAlive(meta.pid);
797
+ }
798
+
799
+ // src/agent-rpc/client.ts
800
+ var AgentRpcClient = class {
801
+ ws = null;
802
+ pending = /* @__PURE__ */ new Map();
803
+ nextId = 1;
804
+ url;
805
+ authToken;
806
+ notifyListeners = /* @__PURE__ */ new Set();
807
+ constructor(opts = {}) {
808
+ const connect = opts.url && opts.authToken ? { url: opts.url, authToken: opts.authToken } : agentRpcConnectFromMetadata();
809
+ if (!connect) throw new Error("Agent RPC runtime is not running (no live agent-runtime.json)");
810
+ this.url = connect.url;
811
+ this.authToken = connect.authToken;
812
+ }
813
+ onNotify(fn) {
814
+ this.notifyListeners.add(fn);
815
+ return () => this.notifyListeners.delete(fn);
816
+ }
817
+ async call(method, params) {
818
+ const ws = await this.ensureSocket();
819
+ const id = this.nextId;
820
+ this.nextId += 1;
821
+ const key = String(id);
822
+ const payload = {
823
+ jsonrpc: "2.0",
824
+ id,
825
+ method,
826
+ params,
827
+ authToken: this.authToken
828
+ };
829
+ return new Promise((resolve2, reject) => {
830
+ this.pending.set(key, { resolve: resolve2, reject });
831
+ try {
832
+ ws.send(JSON.stringify(payload));
833
+ } catch (err) {
834
+ this.pending.delete(key);
835
+ reject(err instanceof Error ? err : new Error(String(err)));
836
+ }
837
+ });
838
+ }
839
+ socketUrl() {
840
+ const url = new URL(this.url);
841
+ url.searchParams.set(AGENT_RPC_TOKEN_QUERY, this.authToken);
842
+ return url.toString();
843
+ }
844
+ async ensureSocket() {
845
+ if (this.ws && this.ws.readyState === import_ws.WebSocket.OPEN) return this.ws;
846
+ const ws = new import_ws.WebSocket(this.socketUrl());
847
+ this.ws = ws;
848
+ ws.on("message", (data) => this.onFrame(data.toString()));
849
+ ws.on("error", (err) => this.drop(ws, err));
850
+ ws.on("close", () => this.drop(ws, new Error("Agent RPC socket closed")));
851
+ ws.on("unexpected-response", (_req, res) => {
852
+ res.resume();
853
+ this.drop(
854
+ ws,
855
+ new Error(
856
+ res.statusCode === 401 ? "Unauthorized" : `Unexpected server response: ${res.statusCode}`
857
+ )
858
+ );
859
+ });
860
+ await new Promise((resolve2, reject) => {
861
+ const fail = (err) => {
862
+ const message = err.message.includes("401") ? "Unauthorized" : err.message;
863
+ reject(message === err.message ? err : new Error(message));
864
+ };
865
+ ws.once("unexpected-response", (_req, res) => {
866
+ fail(
867
+ new Error(
868
+ res.statusCode === 401 ? "Unauthorized" : `Unexpected server response: ${res.statusCode}`
869
+ )
870
+ );
871
+ });
872
+ ws.once("error", fail);
873
+ ws.once("open", () => {
874
+ ws.off("error", fail);
875
+ resolve2();
876
+ });
877
+ });
878
+ return ws;
879
+ }
880
+ drop(ws, err) {
881
+ if (this.ws === ws) this.ws = null;
882
+ if (this.pending.size === 0) return;
883
+ this.failAll(err);
884
+ }
885
+ onFrame(raw) {
886
+ const parsed = parseRpcFrame(raw);
887
+ if (parsed === void 0) return;
888
+ if (isJsonRpcNotification(parsed)) {
889
+ for (const fn of this.notifyListeners) fn(parsed);
890
+ return;
891
+ }
892
+ if (!parsed || typeof parsed !== "object") return;
893
+ const rec = parsed;
894
+ if (rec.id === void 0 || rec.id === null) return;
895
+ const key = String(rec.id);
896
+ const waiter = this.pending.get(key);
897
+ if (!waiter) return;
898
+ this.pending.delete(key);
899
+ if (rec.error && typeof rec.error === "object") {
900
+ const err = rec.error;
901
+ waiter.reject(new Error(err.message || "Agent RPC error"));
902
+ return;
903
+ }
904
+ waiter.resolve(rec.result);
905
+ }
906
+ failAll(err) {
907
+ for (const waiter of this.pending.values()) waiter.reject(err);
908
+ this.pending.clear();
909
+ }
910
+ close() {
911
+ const ws = this.ws;
912
+ this.ws = null;
913
+ this.failAll(new Error("Agent RPC client closed"));
914
+ if (ws) {
915
+ try {
916
+ ws.close();
917
+ } catch {
918
+ }
919
+ }
920
+ }
921
+ };
922
+
923
+ // src/agent-rpc/pilot-tools.ts
924
+ var PILOT_TOOL_DESCRIPTIONS = {
925
+ present_artifact: "Show a document or live log in Sideboard\u2019s side column. For html/svg/markdown/react, pass the FULL document and do not also fence that same body in chat. For type=log, pass only NEW lines (same artifact_id appends). Prefer type=log for long-running job output \u2014 do not resend HTML. type=react is a single default-export component (JSX/TSX); only react/react-dom imports.",
926
+ wait_for_job: "Wait until a detached long job (tests, pack, deploy, connector CLI) finishes. This call stays open for up to ~2 minutes. stillRunning true means the runtime hit the max hold; call wait_for_job again immediately. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead. Do not end the turn or tell the user you will let them know later.",
927
+ stop_job: "Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress."
928
+ };
929
+ var WAIT_FOR_TURN_DESCRIPTION = "Wait until the chat finishes its current/queued turn, or return early with a live progress snapshot. This call stays open for up to ~2 minutes. taskState is the A2A-style lifecycle: submitted (queued, not started), working, input-required (ask_user), completed, failed, canceled. stillRunning is true only for submitted/working. If stillRunning, text and usage are empty (they would be the previous turn) \u2014 read progress and call wait_for_turn again. Do not send_to_chat a check-in (that steers / interrupts). On failed, lastError/text is the failure. On canceled, the child did not finish \u2014 resume with send_to_chat or tell the user. On input-required, wait for the user in that chat. When finished, text is this turn\u2019s assistant reply and usage is that turn\u2019s tokens + costUsd (this turn, not the Claude session total; sessionCostUsd is the provider session total when present). lastActivityAt is the latest transcript/live stamp \u2014 present after the turn completes, not only while it is running.";
930
+ var WAIT_FOR_TURN_SCHEMA = {
931
+ type: "object",
932
+ properties: {
933
+ ref: {
934
+ type: "string",
935
+ description: "Worktree thread id or ref to wait on (not the orchestrator)"
936
+ },
937
+ timeoutMs: {
938
+ type: "number",
939
+ description: "Optional cap for this hold (ms). Ignored above the runtime max (~2 minutes)."
940
+ }
941
+ },
942
+ required: ["ref"]
943
+ };
944
+ var PILOT_TOOL_SCHEMAS = {
945
+ present_artifact: {
946
+ type: "object",
947
+ properties: {
948
+ title: {
949
+ type: "string",
950
+ description: "Short title shown in the artifact pane header"
951
+ },
952
+ type: {
953
+ type: "string",
954
+ enum: ["html", "svg", "markdown", "react", "log"],
955
+ description: "html/svg/markdown/react replace the pane. log appends content to the same artifact_id (new lines only)."
956
+ },
957
+ content: {
958
+ type: "string",
959
+ description: "html/svg/markdown/react: full document. log: only the new lines since the last call (empty is ok for a status-only update)."
960
+ },
961
+ artifact_id: {
962
+ type: "string",
963
+ description: "Stable id. Required for type=log so later calls append to the same pane."
964
+ },
965
+ status: {
966
+ type: "string",
967
+ enum: ["running", "ok", "failed", "idle"]
968
+ },
969
+ phase: { type: "string" },
970
+ mode: { type: "string", enum: ["append", "replace"] }
971
+ },
972
+ required: ["title", "type", "content"]
973
+ },
974
+ wait_for_job: {
975
+ type: "object",
976
+ properties: {
977
+ id: {
978
+ type: "string",
979
+ description: "Detached job id (same kebab-case id passed to detached-job.cjs start)"
980
+ }
981
+ },
982
+ required: ["id"]
983
+ },
984
+ stop_job: {
985
+ type: "object",
986
+ properties: {
987
+ id: {
988
+ type: "string",
989
+ description: "Detached job id (same kebab-case id passed to detached-job.cjs start)"
990
+ },
991
+ reason: { type: "string" }
992
+ },
993
+ required: ["id"]
994
+ }
995
+ };
996
+ function jsonToolResult(value) {
997
+ return JSON.stringify(value);
998
+ }
999
+ function jsonToolError(err) {
1000
+ const message = err instanceof Error ? err.message : String(err);
1001
+ return jsonToolResult({ ok: false, error: message });
1002
+ }
1003
+ function createPilotRpcExecutors(opts) {
1004
+ const client = new AgentRpcClient(opts.rpc);
1005
+ let waitToolCallId;
1006
+ if (opts.onProgress) {
1007
+ const onProgress = opts.onProgress;
1008
+ client.onNotify((msg) => {
1009
+ if (msg.method === "runtime.progress") onProgress(msg.params, waitToolCallId);
1010
+ });
1011
+ }
1012
+ const call = async (method, args) => {
1013
+ try {
1014
+ return jsonToolResult(await client.call(method, args));
1015
+ } catch (err) {
1016
+ return jsonToolError(err);
1017
+ }
1018
+ };
1019
+ const callJob = (method, args) => call(method, { ...args, cwd: opts.cwd });
1020
+ return {
1021
+ present_artifact: (args) => call("ui.presentArtifact", args),
1022
+ wait_for_job: async (args, context) => {
1023
+ const prev = waitToolCallId;
1024
+ waitToolCallId = typeof context?.toolCallId === "string" ? context.toolCallId : void 0;
1025
+ try {
1026
+ return await callJob("job.wait", args);
1027
+ } finally {
1028
+ waitToolCallId = prev;
1029
+ }
1030
+ },
1031
+ stop_job: (args) => callJob("job.stop", args),
1032
+ wait_for_turn: async (args, context) => {
1033
+ const prev = waitToolCallId;
1034
+ waitToolCallId = typeof context?.toolCallId === "string" ? context.toolCallId : void 0;
1035
+ try {
1036
+ return await call("turn.wait", args);
1037
+ } finally {
1038
+ waitToolCallId = prev;
1039
+ }
1040
+ },
1041
+ close: () => client.close()
1042
+ };
1043
+ }
1044
+
1045
+ // src/agent-rpc/cursor-tools.ts
1046
+ function sideboardCursorRpcTools(opts) {
1047
+ const exec = createPilotRpcExecutors(opts);
1048
+ const tools = {
1049
+ present_artifact: {
1050
+ description: PILOT_TOOL_DESCRIPTIONS.present_artifact,
1051
+ inputSchema: PILOT_TOOL_SCHEMAS.present_artifact,
1052
+ execute: exec.present_artifact
1053
+ },
1054
+ wait_for_job: {
1055
+ description: PILOT_TOOL_DESCRIPTIONS.wait_for_job,
1056
+ inputSchema: PILOT_TOOL_SCHEMAS.wait_for_job,
1057
+ execute: exec.wait_for_job
1058
+ },
1059
+ stop_job: {
1060
+ description: PILOT_TOOL_DESCRIPTIONS.stop_job,
1061
+ inputSchema: PILOT_TOOL_SCHEMAS.stop_job,
1062
+ execute: exec.stop_job
1063
+ }
1064
+ };
1065
+ if (opts.includeWaitForTurn) {
1066
+ tools.wait_for_turn = {
1067
+ description: WAIT_FOR_TURN_DESCRIPTION,
1068
+ inputSchema: WAIT_FOR_TURN_SCHEMA,
1069
+ execute: exec.wait_for_turn
1070
+ };
1071
+ }
1072
+ return tools;
1073
+ }
1074
+
1075
+ // src/agents/tool-result-clip.ts
1076
+ var import_node_fs16 = require("fs");
1077
+ var import_node_path18 = require("path");
722
1078
 
723
1079
  // src/paths/workspace-scratch.ts
724
1080
  var CLI_DIR = ".context/cli";
@@ -727,15 +1083,15 @@ var CLI_DIR = ".context/cli";
727
1083
  function spillPath(cwd, prefix) {
728
1084
  const stamp = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
729
1085
  const safe = prefix.replace(/[^a-zA-Z0-9_-]+/g, "-").slice(0, 40) || "tool";
730
- return (0, import_node_path17.join)(cwd, CLI_DIR, `${safe}-${stamp}.txt`);
1086
+ return (0, import_node_path18.join)(cwd, CLI_DIR, `${safe}-${stamp}.txt`);
731
1087
  }
732
1088
  function spillToolResultToCli(content, opts) {
733
1089
  const cwd = opts?.cwd?.trim();
734
1090
  if (!cwd || !content) return null;
735
1091
  const file = spillPath(cwd, opts?.prefix ?? "tool-result");
736
1092
  try {
737
- (0, import_node_fs15.mkdirSync)((0, import_node_path17.join)(cwd, CLI_DIR), { recursive: true });
738
- (0, import_node_fs15.writeFileSync)(file, content, "utf8");
1093
+ (0, import_node_fs16.mkdirSync)((0, import_node_path18.join)(cwd, CLI_DIR), { recursive: true });
1094
+ (0, import_node_fs16.writeFileSync)(file, content, "utf8");
739
1095
  return file;
740
1096
  } catch {
741
1097
  return null;
@@ -1062,11 +1418,18 @@ function cursorDeltaToEvents(update) {
1062
1418
  function buildCursorModelSelection(model, opts) {
1063
1419
  const raw = model && model.trim() || "";
1064
1420
  const id = !raw || raw.toLowerCase() === "auto" || raw.toLowerCase() === "default" ? "default" : raw;
1421
+ const isGrok47 = /^grok-4\.7(?:$|-)/i.test(id);
1065
1422
  const params = [];
1423
+ if (isGrok47) {
1424
+ params.push({ id: "context", value: "256k" });
1425
+ }
1066
1426
  const effort = (opts.effort ?? "").trim().toLowerCase();
1067
1427
  const normalized = effort === "normal" ? "medium" : effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max" ? effort : "";
1068
1428
  if (normalized) {
1069
- params.push({ id: "effort", value: normalized });
1429
+ params.push({
1430
+ id: isGrok47 ? "reasoning_effort" : "effort",
1431
+ value: isGrok47 && normalized === "max" ? "xhigh" : normalized
1432
+ });
1070
1433
  }
1071
1434
  params.push({ id: "fast", value: opts.fast ? "true" : "false" });
1072
1435
  return { id, params };
@@ -1139,7 +1502,7 @@ function emit(event) {
1139
1502
  }
1140
1503
  function localAgentStore(Store, threadId) {
1141
1504
  const root = cursorSdkStoreDir(threadId);
1142
- (0, import_node_fs16.mkdirSync)(root, { recursive: true });
1505
+ (0, import_node_fs17.mkdirSync)(root, { recursive: true });
1143
1506
  return new Store(root);
1144
1507
  }
1145
1508
  async function cancelStaleLocalRuns(Agent, agentId, opts) {
@@ -1210,8 +1573,29 @@ async function main() {
1210
1573
  const mode = req.planMode ? "plan" : "agent";
1211
1574
  const store = localAgentStore(JsonlLocalAgentStore, req.threadId);
1212
1575
  const isolateSources = [];
1576
+ let onRpcProgress = () => {
1577
+ };
1578
+ const rpcTools = req.agentRpc ? sideboardCursorRpcTools({
1579
+ cwd: req.cwd,
1580
+ rpc: req.agentRpc,
1581
+ includeWaitForTurn: Boolean(req.rpcWaitForTurn),
1582
+ onProgress: (params, toolCallId) => {
1583
+ onRpcProgress();
1584
+ if (!toolCallId) return;
1585
+ try {
1586
+ emit({
1587
+ type: "tool_result",
1588
+ id: toolCallId,
1589
+ content: JSON.stringify(params),
1590
+ partial: true
1591
+ });
1592
+ } catch {
1593
+ }
1594
+ }
1595
+ }) : {};
1213
1596
  const customTools = {
1214
- read: slicedReadCustomToolConfig(req.cwd)
1597
+ read: slicedReadCustomToolConfig(req.cwd),
1598
+ ...rpcTools
1215
1599
  };
1216
1600
  const local = withCursorLocalHangGuards({
1217
1601
  cwd: req.cwd,
@@ -1306,6 +1690,7 @@ async function main() {
1306
1690
  const bump = () => {
1307
1691
  activity.at = Date.now();
1308
1692
  };
1693
+ onRpcProgress = bump;
1309
1694
  let usageBefore = null;
1310
1695
  try {
1311
1696
  usageBefore = await agent.getUsage();
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- clipAgentEventForEmit
4
- } from "../chunk-HHEKVR6C.js";
3
+ clipAgentEventForEmit,
4
+ sideboardCursorRpcTools
5
+ } from "../chunk-F5MFNUAA.js";
5
6
  import {
6
7
  createAgentStreamCoalescer
7
8
  } from "../chunk-AXQ4ZWHK.js";
@@ -19,15 +20,16 @@ import {
19
20
  importCursorSdk,
20
21
  looksLikeCursorHttp2StreamClose,
21
22
  resolveCursorSdkRoot
22
- } from "../chunk-WV7KJH2E.js";
23
+ } from "../chunk-A5SAYFJ4.js";
23
24
  import "../chunk-6K64FJDD.js";
25
+ import {
26
+ cursorSdkStoreDir
27
+ } from "../chunk-UWQ6UCIB.js";
24
28
  import "../chunk-QVN2WOKJ.js";
29
+ import "../chunk-NYBFYFK7.js";
25
30
  import {
26
31
  dropNestedElectronEnvFromProcess
27
32
  } from "../chunk-4TR3HZFT.js";
28
- import {
29
- cursorSdkStoreDir
30
- } from "../chunk-UWQ6UCIB.js";
31
33
  import "../chunk-EHT2DRT4.js";
32
34
 
33
35
  // src/agents/cursor-runner.ts
@@ -275,11 +277,18 @@ function slicedReadCustomToolConfig(cwd) {
275
277
  function buildCursorModelSelection(model, opts) {
276
278
  const raw = model && model.trim() || "";
277
279
  const id = !raw || raw.toLowerCase() === "auto" || raw.toLowerCase() === "default" ? "default" : raw;
280
+ const isGrok47 = /^grok-4\.7(?:$|-)/i.test(id);
278
281
  const params = [];
282
+ if (isGrok47) {
283
+ params.push({ id: "context", value: "256k" });
284
+ }
279
285
  const effort = (opts.effort ?? "").trim().toLowerCase();
280
286
  const normalized = effort === "normal" ? "medium" : effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max" ? effort : "";
281
287
  if (normalized) {
282
- params.push({ id: "effort", value: normalized });
288
+ params.push({
289
+ id: isGrok47 ? "reasoning_effort" : "effort",
290
+ value: isGrok47 && normalized === "max" ? "xhigh" : normalized
291
+ });
283
292
  }
284
293
  params.push({ id: "fast", value: opts.fast ? "true" : "false" });
285
294
  return { id, params };
@@ -364,8 +373,29 @@ async function main() {
364
373
  const mode = req.planMode ? "plan" : "agent";
365
374
  const store = localAgentStore(JsonlLocalAgentStore, req.threadId);
366
375
  const isolateSources = [];
376
+ let onRpcProgress = () => {
377
+ };
378
+ const rpcTools = req.agentRpc ? sideboardCursorRpcTools({
379
+ cwd: req.cwd,
380
+ rpc: req.agentRpc,
381
+ includeWaitForTurn: Boolean(req.rpcWaitForTurn),
382
+ onProgress: (params, toolCallId) => {
383
+ onRpcProgress();
384
+ if (!toolCallId) return;
385
+ try {
386
+ emit({
387
+ type: "tool_result",
388
+ id: toolCallId,
389
+ content: JSON.stringify(params),
390
+ partial: true
391
+ });
392
+ } catch {
393
+ }
394
+ }
395
+ }) : {};
367
396
  const customTools = {
368
- read: slicedReadCustomToolConfig(req.cwd)
397
+ read: slicedReadCustomToolConfig(req.cwd),
398
+ ...rpcTools
369
399
  };
370
400
  const local = withCursorLocalHangGuards({
371
401
  cwd: req.cwd,
@@ -460,6 +490,7 @@ async function main() {
460
490
  const bump = () => {
461
491
  activity.at = Date.now();
462
492
  };
493
+ onRpcProgress = bump;
463
494
  let usageBefore = null;
464
495
  try {
465
496
  usageBefore = await agent.getUsage();