@liberseek/boft-cli-win32-arm64 0.7.1 → 0.7.3

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.
package/README.md CHANGED
@@ -7,7 +7,7 @@ BOFT CLI runs Pi and other external harnesses inside Codex Desktop.
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- npm install -g @liberseek/boft-cli@0.7.1
10
+ npm install -g @liberseek/boft-cli@0.7.3
11
11
  ```
12
12
 
13
13
  Do not install this package directly. npm selects it through the optional dependencies of `@liberseek/boft-cli`.
@@ -1 +1 @@
1
- {"schemaVersion":1,"version":"0.7.1","distribution":"npm","target":"windows-arm64"}
1
+ {"schemaVersion":1,"version":"0.7.3","distribution":"npm","target":"windows-arm64"}
@@ -29,6 +29,7 @@ async function startControllerAttachmentServer(options) {
29
29
  throw new Error("attachment nonce must be 32 lowercase hexadecimal characters");
30
30
  }
31
31
  const sockets = /* @__PURE__ */ new Set();
32
+ let attachment;
32
33
  const server = createServer((socket) => {
33
34
  sockets.add(socket);
34
35
  socket.once("close", () => sockets.delete(socket));
@@ -49,10 +50,19 @@ async function startControllerAttachmentServer(options) {
49
50
  handled = true;
50
51
  const line = request.slice(0, newline).replace(/\r$/, "");
51
52
  if (line === `ATTACH ${options.nonce}`) {
52
- void options.attach().then(
53
+ if (attachment) {
54
+ respond(socket, "busy");
55
+ return;
56
+ }
57
+ socket.setTimeout(0);
58
+ const current = Promise.resolve().then(() => options.attach());
59
+ attachment = current;
60
+ void current.then(
53
61
  () => respond(socket, "ready"),
54
62
  () => respond(socket, "failed")
55
- );
63
+ ).finally(() => {
64
+ if (attachment === current) attachment = void 0;
65
+ });
56
66
  return;
57
67
  }
58
68
  respond(socket, "rejected");
@@ -81,12 +91,6 @@ async function startControllerAttachmentServer(options) {
81
91
  function isRecord(value) {
82
92
  return typeof value === "object" && value !== null && !Array.isArray(value);
83
93
  }
84
- function nonEmptyString(value, field) {
85
- if (typeof value !== "string" || value.length === 0) {
86
- throw new Error(`CDP target '${field}' must be non-empty text`);
87
- }
88
- return value;
89
- }
90
94
  function loopbackUrl(value, protocols) {
91
95
  const url = new URL(value);
92
96
  if (!protocols.includes(url.protocol)) {
@@ -97,17 +101,24 @@ function loopbackUrl(value, protocols) {
97
101
  }
98
102
  return url;
99
103
  }
104
+ function optionalText(value) {
105
+ return typeof value === "string" && value.length > 0 ? value : null;
106
+ }
100
107
  function parseTarget(value) {
101
108
  if (!isRecord(value)) throw new Error("CDP target must be an object");
102
- const target = {
103
- id: nonEmptyString(value.id, "id"),
104
- type: nonEmptyString(value.type, "type"),
109
+ const id = optionalText(value.id);
110
+ const type = optionalText(value.type);
111
+ const url = optionalText(value.url);
112
+ const webSocketDebuggerUrl = optionalText(value.webSocketDebuggerUrl);
113
+ if (webSocketDebuggerUrl) loopbackUrl(webSocketDebuggerUrl, ["ws:", "wss:"]);
114
+ if (!id || !type || !url || !webSocketDebuggerUrl) return null;
115
+ return {
116
+ id,
117
+ type,
105
118
  title: typeof value.title === "string" ? value.title : "",
106
- url: nonEmptyString(value.url, "url"),
107
- webSocketDebuggerUrl: nonEmptyString(value.webSocketDebuggerUrl, "webSocketDebuggerUrl")
119
+ url,
120
+ webSocketDebuggerUrl
108
121
  };
109
- loopbackUrl(target.webSocketDebuggerUrl, ["ws:", "wss:"]);
110
- return target;
111
122
  }
112
123
  function defaultFetch(url) {
113
124
  return fetch(url);
@@ -144,7 +155,7 @@ async function listCdpTargets(endpoint, fetchImpl = defaultFetch) {
144
155
  if (!response.ok) throw new Error(`CDP target discovery failed with HTTP ${response.status}`);
145
156
  const value = await response.json();
146
157
  if (!Array.isArray(value)) throw new Error("CDP target discovery did not return an array");
147
- return value.map(parseTarget);
158
+ return value.map(parseTarget).filter((target) => target !== null);
148
159
  }
149
160
  var CdpClient = class _CdpClient {
150
161
  #commandTimeoutMs;
@@ -788,9 +799,26 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewarm
788
799
  }
789
800
  return shouldUseBridge(method, routedParameters) ? sendBridged() : sendDirect();
790
801
  };
802
+ const publishDraftWorkspace = (parameters) => {
803
+ if (!isRecord3(parameters) || parameters.ephemeral === true) return;
804
+ const cwd = parameters.cwd;
805
+ if (typeof cwd !== "string" || cwd.length === 0) return;
806
+ const drafts = isRecord3(target.__codexhostDraftWorkspacesV1) ? target.__codexhostDraftWorkspacesV1 : {};
807
+ drafts[hostId] = cwd;
808
+ Object.defineProperty(target, "__codexhostDraftWorkspacesV1", {
809
+ configurable: true,
810
+ value: drafts
811
+ });
812
+ if (typeof target.dispatchEvent === "function" && typeof CustomEvent === "function") {
813
+ target.dispatchEvent(
814
+ new CustomEvent("codexhost:draft-workspace", { detail: { hostId, cwd } })
815
+ );
816
+ }
817
+ };
791
818
  const routedPrewarm = (parameters, options) => {
792
819
  const routedParameters = routeThreadStart(parameters);
793
820
  const generation = prewarmGeneration;
821
+ publishDraftWorkspace(routedParameters);
794
822
  const pending = shouldUseBridge("thread/start", routedParameters) ? routedSend("thread/start", routedParameters, options) : options === void 0 ? originalPrewarm.call(bridge, routedParameters) : originalPrewarm.call(bridge, routedParameters, options);
795
823
  if (isRecord3(parameters) && parameters.ephemeral === true || typeof pending !== "object" && typeof pending !== "function" || pending === null || typeof Reflect.get(pending, "then") !== "function") {
796
824
  return pending;
@@ -799,6 +827,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewarm
799
827
  if (disposed || generation !== prewarmGeneration) {
800
828
  throw new Error("Renderer draft prewarm was invalidated by a configuration change");
801
829
  }
830
+ publishDraftWorkspace(routedParameters);
802
831
  return result;
803
832
  });
804
833
  };
@@ -1160,7 +1189,8 @@ function sleep(milliseconds) {
1160
1189
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
1161
1190
  }
1162
1191
  function sameAgents(actual, expected) {
1163
- return actual.length === expected.length && actual.every((agent, index) => agent === expected[index]);
1192
+ const expectedSet = new Set(expected);
1193
+ return actual.length === expected.length && new Set(actual).size === actual.length && actual.every((agent) => expectedSet.has(agent));
1164
1194
  }
1165
1195
  function isPrimaryRendererUrl(value) {
1166
1196
  try {
@@ -1573,7 +1603,8 @@ ${rendererSource}`,
1573
1603
  "workbuddy",
1574
1604
  "cursor-cli",
1575
1605
  "qoder",
1576
- "qoder-cn"
1606
+ "qoder-cn",
1607
+ "kimi-code"
1577
1608
  ],
1578
1609
  timeoutMs: PRODUCTION_INSTALL_TIMEOUT_MS
1579
1610
  },