local-commander-agent-linux-x64 0.3.48 → 0.3.50

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-commander-agent-linux-x64",
3
- "version": "0.3.48",
3
+ "version": "0.3.50",
4
4
  "description": "Local Commander runtime for Linux x64. Installed automatically by local-commander-agent; run npx local-commander-agent@latest instead.",
5
5
  "os": [
6
6
  "linux"
package/runtime/agent.mjs CHANGED
@@ -31118,7 +31118,7 @@ var NativeTools = class {
31118
31118
  if (call.name === "command_run") {
31119
31119
  if (!["win32", "linux", "darwin"].includes(process.platform)) fail3("COMMAND_NOT_ALLOWED");
31120
31120
  const cwd2 = await resolve(call.args.cwd, true), program = await this.resolveProgram(call.args.command, workspace2, call.args.args);
31121
- const claims2 = writeClaim(cwd2);
31121
+ const claims2 = call.args.cwd === void 0 ? [{ path: cwd2, namespace: "process", mode: "read" }] : writeClaim(cwd2);
31122
31122
  return { call, claims: claims2, execution: { ...program, cwd: cwd2 }, run: async (signal, onStarted, onOutput, onSupervisor) => {
31123
31123
  let r;
31124
31124
  try {
@@ -31386,7 +31386,10 @@ var NativeScheduler = class {
31386
31386
  } catch {
31387
31387
  }
31388
31388
  }
31389
- schedule(id2, claims, deadlineAt, run2, signal) {
31389
+ /** lockWaitMs: how long a job may wait behind a conflicting claim before it is refused with
31390
+ * RESOURCE_LOCKED (proved not started), so the caller hears back inside its relay window
31391
+ * instead of timing out (#504). Waiting only for a free slot still lasts until the deadline. */
31392
+ schedule(id2, claims, deadlineAt, run2, signal, lockWaitMs) {
31390
31393
  if (!this.accepting) return Promise.reject(Error("AGENT_PAUSED"));
31391
31394
  if (!id2 || id2.length > 100 || this.active.has(id2) || this.waiting.some((j) => j.id === id2)) return Promise.reject(Error("DUPLICATE_SCHEDULED_EXECUTION"));
31392
31395
  if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !path19.isAbsolute(c.path) || !["read", "write"].includes(c.mode))) return Promise.reject(Error("INVALID_RESOURCE_CLAIM"));
@@ -31407,6 +31410,12 @@ var NativeScheduler = class {
31407
31410
  };
31408
31411
  job.aborted = () => remove("CANCELLED_BEFORE_ACCEPTANCE");
31409
31412
  job.timer = setTimeout(() => remove("ADMISSION_DEADLINE_EXPIRED"), Math.min(2147483647, Math.max(1, deadline - Date.now())));
31413
+ if (lockWaitMs !== void 0 && Number.isFinite(lockWaitMs) && lockWaitMs >= 0) {
31414
+ const lockIn = Math.min(lockWaitMs, deadline - Date.now() - 1e3);
31415
+ if (lockIn > 0) job.lockTimer = setTimeout(() => {
31416
+ if (this.lockBlocked(job)) remove("RESOURCE_LOCKED");
31417
+ }, lockIn);
31418
+ }
31410
31419
  signal?.addEventListener("abort", job.aborted, { once: true });
31411
31420
  this.waiting.push(job);
31412
31421
  this.observe({ kind: "queued", executionId: id2, deadlineAt: deadline });
@@ -31415,8 +31424,21 @@ var NativeScheduler = class {
31415
31424
  }
31416
31425
  cleanup(job) {
31417
31426
  clearTimeout(job.timer);
31427
+ clearTimeout(job.lockTimer);
31418
31428
  if (job.aborted) job.signal?.removeEventListener("abort", job.aborted);
31419
31429
  }
31430
+ /** True when a waiting job is held by a conflicting claim: a running job, or an earlier conflicting
31431
+ * waiter that is itself lock-blocked. A wait that is only for a free slot is never a lock. */
31432
+ lockBlocked(job) {
31433
+ const index = this.waiting.indexOf(job);
31434
+ if (index < 0) return false;
31435
+ const blocked2 = [];
31436
+ for (let i = 0; i <= index; i++) {
31437
+ const current2 = this.waiting[i];
31438
+ blocked2[i] = [...this.active.values()].some((claims) => claimsConflict(claims, current2.claims)) || this.waiting.slice(0, i).some((older, j) => blocked2[j] === true && claimsConflict(older.claims, current2.claims));
31439
+ }
31440
+ return blocked2[index] === true;
31441
+ }
31420
31442
  pump() {
31421
31443
  for (let i = 0; i < this.waiting.length && this.active.size < this.safeSlots; ) {
31422
31444
  const job = this.waiting[i];
@@ -32119,6 +32141,7 @@ var knownCodes = /* @__PURE__ */ new Set([
32119
32141
  "WORKSPACE_CHANGED",
32120
32142
  "WORKSPACE_UNAVAILABLE",
32121
32143
  "RESOURCE_BUSY",
32144
+ "RESOURCE_LOCKED",
32122
32145
  "AGENT_PAUSED",
32123
32146
  "CANCELLED_BEFORE_ACCEPTANCE",
32124
32147
  "ADMISSION_DEADLINE_EXPIRED",
@@ -32133,6 +32156,7 @@ var knownCodes = /* @__PURE__ */ new Set([
32133
32156
  "SCREEN_ENCODER_UNAVAILABLE",
32134
32157
  "SCREEN_RECORDING_PERMISSION_REQUIRED"
32135
32158
  ]);
32159
+ var LOCK_WAIT_MS = 2e4;
32136
32160
  function safeCode(error62) {
32137
32161
  const code = error62 instanceof NativeToolError ? error62.code : error62 instanceof Error ? error62.message : "";
32138
32162
  return knownCodes.has(code) || /^GUARD_[A-Z_]{1,30}$/.test(code) ? code : "TOOL_FAILED";
@@ -32344,7 +32368,7 @@ var NativeRuntime = class {
32344
32368
  const final = await this.options.journal.finish(binding2.executionId, image === void 0 ? journalOutput : { ...journalOutput, stdout: screenshotMetadata(image) }, resultCode);
32345
32369
  const outbound = await outboundResult(runnable.call, journalResult(final.result, resultCode), binding2, this.optionalTelemetry, this.options.efficiencyLedger);
32346
32370
  this.send({ type: "result", version: 1, binding: binding2, result: image === void 0 ? outbound : { ...outbound, stdout: image } });
32347
- }, abort.signal);
32371
+ }, abort.signal, LOCK_WAIT_MS);
32348
32372
  context.task = work.catch(async (error62) => {
32349
32373
  if (!context.accepted) {
32350
32374
  if (context.guardPermit) await this.options.guard.rejected(context.guardPermit, safeCode(error62)).catch(() => {
@@ -47399,9 +47423,9 @@ function waitForMessage(socket, maxBytes, timeoutMs2, timeoutCode) {
47399
47423
  cleanup();
47400
47424
  reject(new RelayClientError(error62.code === "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH" ? "RELAY_FRAME_TOO_LARGE" : "RELAY_SOCKET_FAILED"));
47401
47425
  };
47402
- const onClose = () => {
47426
+ const onClose = (code, reason) => {
47403
47427
  cleanup();
47404
- reject(new RelayClientError("RELAY_SOCKET_CLOSED"));
47428
+ reject(new RelayClientError(code === 1008 && reason.toString("utf8") === "device_quarantined" ? "RELAY_DEVICE_QUARANTINED" : "RELAY_SOCKET_CLOSED"));
47405
47429
  };
47406
47430
  socket.once("message", onMessage);
47407
47431
  socket.once("error", onError);
@@ -48997,7 +49021,7 @@ var NativeEventBuffer = class {
48997
49021
 
48998
49022
  // agent/src/native-event-supervisor.ts
48999
49023
  var eventKinds = /* @__PURE__ */ new Set(["queued", "admitted", "released", "queue_rejected", "prepared", "accepted", "running", "result", "not_accepted", "connected", "disconnected", "mailbox_expired"]);
49000
- var codes = /* @__PURE__ */ new Set(["SUCCESS", "EXECUTION_UNKNOWN", "AGENT_RESTARTED", "ADMISSION_DEADLINE_EXPIRED", "CANCELLED_BEFORE_ACCEPTANCE", "RESOURCE_BUSY", "AGENT_PAUSED", "PREPARATION_EXPIRED", "CANCELLED", "TIMEOUT", "USER_PROGRAM_FAILED", "TOOL_FAILED", "MAILBOX_EXPIRED"]);
49024
+ var codes = /* @__PURE__ */ new Set(["SUCCESS", "EXECUTION_UNKNOWN", "AGENT_RESTARTED", "ADMISSION_DEADLINE_EXPIRED", "CANCELLED_BEFORE_ACCEPTANCE", "RESOURCE_BUSY", "RESOURCE_LOCKED", "AGENT_PAUSED", "PREPARATION_EXPIRED", "CANCELLED", "TIMEOUT", "USER_PROGRAM_FAILED", "TOOL_FAILED", "MAILBOX_EXPIRED"]);
49001
49025
  var NativeEventSupervisor = class {
49002
49026
  constructor(onChange) {
49003
49027
  this.onChange = onChange;
@@ -50829,9 +50853,10 @@ async function restoreContentAudit(input2, output2, key) {
50829
50853
  }
50830
50854
 
50831
50855
  // agent/src/main.ts
50832
- var AGENT_VERSION2 = true ? "0.3.48" : "0.3.2";
50856
+ var AGENT_VERSION2 = true ? "0.3.50" : "0.3.2";
50833
50857
  var NETWORK_PUBLIC_KEY = true ? "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvmu+81vWtJBQDZNHcAIW\nzCSxpG+R9RBsum2df5mP2cOW+wyUDTpnYquFge1qgI5YYTF96j0xCyXL8B9FeNWs\n939opWNmv53j+CQlS4cEIQhBbZSCu0eC4icsVEzBhvf68MB+E668SOtZBcVTEnyh\n96PTcupxS10rQJBWDinbKBXRC2gvGYeu01rWa/nsrndy4vAYP5t3yQtdOC8e8mr0\n+2Mg2Qhiq+KiTCtDd+L9oXvoLqqJYbzUIveNGha25AWxF1Weblp0gOM87hell5gV\nK7q4ZLUq/wBRGYNmQRdLyV7/WRE1FFPSW21/SBZQ/5aU4UqJU/MjMcrJUrnRKngz\nYKmo0czkxS3N7Q2KVxomgR1AQSuQFKMrboZYKjShADp9RIYUxzs7cYg51Of5PnHh\n6Ax+VevDGfzjMD+yHuyxYZqCtX4OwgolJxz63UQbzKlris+8xb5lLYTbIuz90Pss\nn6HK/F5May25c6oMmS3nh/NsiZopL1OvdtWKTt1L4WlRAgMBAAE=\n-----END PUBLIC KEY-----\n" : "";
50834
50858
  var AI_CONNECTION_SHIPPED = false;
50859
+ var QUARANTINE_RETRY_MS = 6e4;
50835
50860
  function processAlive(pid) {
50836
50861
  if (!Number.isInteger(pid) || pid <= 0) return false;
50837
50862
  try {
@@ -50977,7 +51002,7 @@ async function runAgent(options) {
50977
51002
  try {
50978
51003
  while (!options.signal.aborted) {
50979
51004
  computerName = await readComputerName();
50980
- let ready;
51005
+ let ready, wait = delay4;
50981
51006
  const readyPromise = new Promise((resolve) => {
50982
51007
  ready = resolve;
50983
51008
  });
@@ -51066,6 +51091,8 @@ async function runAgent(options) {
51066
51091
  ready();
51067
51092
  monitor(() => options.monitor?.connectionFailed(error62));
51068
51093
  if (error62 instanceof RelayClientError && ["RELAY_CONNECT_FAILED", "RELAY_CONNECT_CLOSED", "RELAY_CONNECT_TIMEOUT", "RELAY_HANDSHAKE_TIMEOUT"].includes(error62.code)) {
51094
+ } else if (error62 instanceof RelayClientError && error62.code === "RELAY_DEVICE_QUARANTINED") {
51095
+ wait = Math.max(delay4, QUARANTINE_RETRY_MS);
51069
51096
  } else throw error62;
51070
51097
  } finally {
51071
51098
  connectivity?.close();
@@ -51083,7 +51110,7 @@ async function runAgent(options) {
51083
51110
  await bridge.disconnected();
51084
51111
  connection = null;
51085
51112
  }
51086
- if (!options.signal.aborted) await aborted2(options.signal, delay4);
51113
+ if (!options.signal.aborted) await aborted2(options.signal, wait);
51087
51114
  }
51088
51115
  } finally {
51089
51116
  try {
@@ -1,17 +1,17 @@
1
1
  {
2
- "version": "0.3.48",
2
+ "version": "0.3.50",
3
3
  "experimental": true,
4
4
  "platform": "linux",
5
5
  "arch": "x64",
6
6
  "node": "v22.23.3",
7
- "source": "6d64c886f4cb5a4393a855a2ed7fa16a395399dc",
8
- "sourceTreeSha256": "4f75f63d2380ac2ae9f53678bf71ece1f38df62642ea43e48dbb38bdc244efb9",
7
+ "source": "846ebe4409172d55c88aa8611a90b1098bbe36b0",
8
+ "sourceTreeSha256": "2615d6cb62edfb9bd628788a813147cecbf898a7062e4b3e08f3d0623bbe4343",
9
9
  "qualification": "unqualified",
10
10
  "lifecycleVersion": 1,
11
11
  "packaging": "npm platform package runtime",
12
12
  "files": {
13
13
  "NODE-LICENSE.txt": "c738ae413cf561f174e34f6961f8ca458aae2369a73640dda6234c629b98bcc4",
14
- "agent.mjs": "b238ee5cfe6bbeeda7804c37b41b2748076402dd0af423a5f6f20b2ea9d36a67",
14
+ "agent.mjs": "49ce9d10658ebc80227eeeedc0fd21faa931f390ccbd39171892658276dfb429",
15
15
  "job-host.mjs": "54ab42fa00a53dfd4df6c93fd9e6692d5e03a0870aba8bf501f398905694b72d",
16
16
  "lifecycle.mjs": "ebed6bac75115ef1df34aff9fef211c9f710a524b2b614115b6bc80ef57b464b",
17
17
  "node": "fde6a4bf8d0562f7751d1a2d6cb9b417c4cfe107bbcb0aa3e9a24e125e348f48",