@h-rig/pi-rig 0.0.6-alpha.67 → 0.0.6-alpha.68

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.
@@ -119,6 +119,8 @@ function requireServerUrl(context) {
119
119
  }
120
120
  return context.serverUrl;
121
121
  }
122
+ var BRIDGE_REQUEST_TIMEOUT_MS = 30000;
123
+ var PROTOCOL_CHECK_TIMEOUT_MS = 1e4;
122
124
 
123
125
  class RigBridgeClient {
124
126
  context;
@@ -127,22 +129,26 @@ class RigBridgeClient {
127
129
  this.context = input.context;
128
130
  this.fetchImpl = input.fetchImpl ?? fetch;
129
131
  }
130
- async request(pathname, init) {
132
+ async request(pathname, init, timeoutMs = BRIDGE_REQUEST_TIMEOUT_MS) {
131
133
  const headers = new Headers(init?.headers);
132
134
  if (this.context.authToken && !headers.has("authorization")) {
133
135
  headers.set("authorization", `Bearer ${this.context.authToken}`);
134
136
  }
135
- const response = await this.fetchImpl(joinUrl(requireServerUrl(this.context), pathname), { ...init, headers });
137
+ if (this.context.projectRoot && !headers.has("x-rig-project-root")) {
138
+ headers.set("x-rig-project-root", this.context.projectRoot);
139
+ }
140
+ const signal = init?.signal ?? (timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined);
141
+ const response = await this.fetchImpl(joinUrl(requireServerUrl(this.context), pathname), { ...init, headers, signal });
136
142
  return readJsonResponse(response);
137
143
  }
138
- async status() {
139
- const payload = await this.request("/api/server/status");
144
+ async status(timeoutMs) {
145
+ const payload = await this.request("/api/server/status", undefined, timeoutMs);
140
146
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
141
147
  }
142
148
  async checkProtocolCompatibility() {
143
149
  let payload;
144
150
  try {
145
- payload = await this.status();
151
+ payload = await this.status(PROTOCOL_CHECK_TIMEOUT_MS);
146
152
  } catch (error) {
147
153
  return {
148
154
  status: "indeterminate",
@@ -424,5 +430,7 @@ export {
424
430
  buildRigWebSocketUrl,
425
431
  RigBridgeSocket,
426
432
  RigBridgeClient,
427
- RIG_PROTOCOL_VERSION
433
+ RIG_PROTOCOL_VERSION,
434
+ PROTOCOL_CHECK_TIMEOUT_MS,
435
+ BRIDGE_REQUEST_TIMEOUT_MS
428
436
  };
package/dist/src/index.js CHANGED
@@ -119,6 +119,8 @@ function requireServerUrl(context) {
119
119
  }
120
120
  return context.serverUrl;
121
121
  }
122
+ var BRIDGE_REQUEST_TIMEOUT_MS = 30000;
123
+ var PROTOCOL_CHECK_TIMEOUT_MS = 1e4;
122
124
 
123
125
  class RigBridgeClient {
124
126
  context;
@@ -127,22 +129,26 @@ class RigBridgeClient {
127
129
  this.context = input.context;
128
130
  this.fetchImpl = input.fetchImpl ?? fetch;
129
131
  }
130
- async request(pathname, init) {
132
+ async request(pathname, init, timeoutMs = BRIDGE_REQUEST_TIMEOUT_MS) {
131
133
  const headers = new Headers(init?.headers);
132
134
  if (this.context.authToken && !headers.has("authorization")) {
133
135
  headers.set("authorization", `Bearer ${this.context.authToken}`);
134
136
  }
135
- const response = await this.fetchImpl(joinUrl(requireServerUrl(this.context), pathname), { ...init, headers });
137
+ if (this.context.projectRoot && !headers.has("x-rig-project-root")) {
138
+ headers.set("x-rig-project-root", this.context.projectRoot);
139
+ }
140
+ const signal = init?.signal ?? (timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined);
141
+ const response = await this.fetchImpl(joinUrl(requireServerUrl(this.context), pathname), { ...init, headers, signal });
136
142
  return readJsonResponse(response);
137
143
  }
138
- async status() {
139
- const payload = await this.request("/api/server/status");
144
+ async status(timeoutMs) {
145
+ const payload = await this.request("/api/server/status", undefined, timeoutMs);
140
146
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
141
147
  }
142
148
  async checkProtocolCompatibility() {
143
149
  let payload;
144
150
  try {
145
- payload = await this.status();
151
+ payload = await this.status(PROTOCOL_CHECK_TIMEOUT_MS);
146
152
  } catch (error) {
147
153
  return {
148
154
  status: "indeterminate",
@@ -608,7 +614,11 @@ function createBridgeGate(state) {
608
614
  return async (ctx) => {
609
615
  if (!state.active || !state.serverUrl)
610
616
  return { allowed: true, message: null, status: "indeterminate" };
611
- pending ??= state.client.checkProtocolCompatibility();
617
+ pending ??= state.client.checkProtocolCompatibility().then((check2) => {
618
+ if (check2.status === "indeterminate")
619
+ pending = null;
620
+ return check2;
621
+ });
612
622
  const check = await pending;
613
623
  if (check.status !== "mismatch")
614
624
  return { allowed: true, message: null, status: check.status };
@@ -880,8 +890,18 @@ function createPiRigExtension(pi, options = {}) {
880
890
  client: state.client,
881
891
  notify: (message, level) => notify(globalThis, message, level)
882
892
  });
893
+ const tryRegister = (label, register) => {
894
+ try {
895
+ register();
896
+ } catch (error) {
897
+ const message = error instanceof Error ? error.message : String(error);
898
+ if (/conflict|already|duplicate/i.test(message))
899
+ return;
900
+ throw error;
901
+ }
902
+ };
883
903
  for (const [name, command] of Object.entries(commands)) {
884
- pi.registerCommand?.(name, {
904
+ tryRegister(`command:${name}`, () => pi.registerCommand?.(name, {
885
905
  description: command.description,
886
906
  handler: async (args, ctx) => {
887
907
  const gateResult = await gate(ctx);
@@ -896,11 +916,11 @@ function createPiRigExtension(pi, options = {}) {
896
916
  });
897
917
  await nextCommands.rig.handler(args, ctx);
898
918
  }
899
- });
919
+ }));
900
920
  }
901
921
  if (state.active && state.runId) {
902
922
  for (const tool of createRigTools({ context: state, client: state.client })) {
903
- pi.registerTool?.({
923
+ tryRegister(`tool:${String(tool.name ?? "rig-tool")}`, () => pi.registerTool?.({
904
924
  ...tool,
905
925
  execute: async (toolCallId, params) => {
906
926
  const gateResult = await gate(globalThis);
@@ -909,7 +929,7 @@ function createPiRigExtension(pi, options = {}) {
909
929
  }
910
930
  return tool.execute(toolCallId, params);
911
931
  }
912
- });
932
+ }));
913
933
  }
914
934
  startSteeringBridge(pi, state, globalThis, gate, deliveredSteeringIds);
915
935
  }
@@ -917,9 +937,20 @@ function createPiRigExtension(pi, options = {}) {
917
937
  pi.on?.("session_start", async (_event, ctx) => {
918
938
  if (!state.active || !state.runId)
919
939
  return;
940
+ setStatus(ctx, "rig", `Rig ${state.runId} \xB7 connecting\u2026`);
941
+ if (state.operatorSession) {
942
+ setFooter(ctx, `Rig ${state.runId} \xB7 connecting to ${state.serverUrl ?? "Rig server"}\u2026`);
943
+ setWidget(ctx, "rig-run", [`Rig ${state.runId} \xB7 connecting\u2026`]);
944
+ }
920
945
  const gateResult = await gate(ctx);
921
- if (!gateResult.allowed)
946
+ if (!gateResult.allowed) {
947
+ if (state.operatorSession) {
948
+ const message = gateResult.message ?? "Rig bridge disabled (protocol mismatch).";
949
+ setFooter(ctx, `Rig ${state.runId} \xB7 bridge disabled (protocol mismatch)`);
950
+ setWidget(ctx, "rig-run", [message]);
951
+ }
922
952
  return;
953
+ }
923
954
  setStatus(ctx, "rig", `Rig ${state.runId}`);
924
955
  const live = gateResult.status === "compatible" ? startOperatorBridge(state, ctx) : undefined;
925
956
  startOperatorRunWidget(state, ctx, live);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/pi-rig",
3
- "version": "0.0.6-alpha.67",
3
+ "version": "0.0.6-alpha.68",
4
4
  "type": "module",
5
5
  "description": "Rig package",
6
6
  "license": "UNLICENSED",
@@ -33,7 +33,7 @@
33
33
  ]
34
34
  },
35
35
  "dependencies": {
36
- "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.67"
36
+ "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.68"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@earendil-works/pi-coding-agent": ">=0.79.0",