local-commander-agent-linux-x64 0.3.47 → 0.3.49

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.47",
3
+ "version": "0.3.49",
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
@@ -27945,11 +27945,16 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
27945
27945
  if (process.platform !== "win32") for (const name2 of ["owner-key.json", "owner-key.dat", "owner-key.lock"]) approved.add(name2);
27946
27946
  if (names.length && !names.includes(MARKER)) throw fail2("STORE_DIRECTORY_UNKNOWN");
27947
27947
  const memoryFile = (name2) => name2 === "host-memory.json" || /^host-memory\.json\.[1-9][0-9]{0,9}\.tmp$/.test(name2);
27948
- if (names.some((name2) => !approved.has(name2) && !memoryFile(name2))) throw fail2("STORE_DIRECTORY_UNKNOWN");
27948
+ const switchFile = (name2) => name2 === "screenshot-acceptance-enabled" || name2 === "screenshot-disabled-by-owner";
27949
+ if (names.some((name2) => !approved.has(name2) && !memoryFile(name2) && !switchFile(name2))) throw fail2("STORE_DIRECTORY_UNKNOWN");
27949
27950
  for (const name2 of names.filter(memoryFile)) {
27950
27951
  const stat2 = await lstat4(path10.join(absolute2, name2));
27951
27952
  if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > 32768) throw fail2("STORE_DIRECTORY_INVALID");
27952
27953
  }
27954
+ for (const name2 of names.filter(switchFile)) {
27955
+ const stat2 = await lstat4(path10.join(absolute2, name2));
27956
+ if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > 4096) throw fail2("STORE_DIRECTORY_INVALID");
27957
+ }
27953
27958
  for (const name2 of ["agent-process.json", "optimization", ".local-commander"]) {
27954
27959
  if (!names.includes(name2)) continue;
27955
27960
  const filename = path10.join(absolute2, name2), stat2 = await lstat4(filename);
@@ -31113,7 +31118,7 @@ var NativeTools = class {
31113
31118
  if (call.name === "command_run") {
31114
31119
  if (!["win32", "linux", "darwin"].includes(process.platform)) fail3("COMMAND_NOT_ALLOWED");
31115
31120
  const cwd2 = await resolve(call.args.cwd, true), program = await this.resolveProgram(call.args.command, workspace2, call.args.args);
31116
- const claims2 = writeClaim(cwd2);
31121
+ const claims2 = call.args.cwd === void 0 ? [{ path: cwd2, namespace: "process", mode: "read" }] : writeClaim(cwd2);
31117
31122
  return { call, claims: claims2, execution: { ...program, cwd: cwd2 }, run: async (signal, onStarted, onOutput, onSupervisor) => {
31118
31123
  let r;
31119
31124
  try {
@@ -31381,7 +31386,10 @@ var NativeScheduler = class {
31381
31386
  } catch {
31382
31387
  }
31383
31388
  }
31384
- 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) {
31385
31393
  if (!this.accepting) return Promise.reject(Error("AGENT_PAUSED"));
31386
31394
  if (!id2 || id2.length > 100 || this.active.has(id2) || this.waiting.some((j) => j.id === id2)) return Promise.reject(Error("DUPLICATE_SCHEDULED_EXECUTION"));
31387
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"));
@@ -31402,6 +31410,12 @@ var NativeScheduler = class {
31402
31410
  };
31403
31411
  job.aborted = () => remove("CANCELLED_BEFORE_ACCEPTANCE");
31404
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
+ }
31405
31419
  signal?.addEventListener("abort", job.aborted, { once: true });
31406
31420
  this.waiting.push(job);
31407
31421
  this.observe({ kind: "queued", executionId: id2, deadlineAt: deadline });
@@ -31410,8 +31424,21 @@ var NativeScheduler = class {
31410
31424
  }
31411
31425
  cleanup(job) {
31412
31426
  clearTimeout(job.timer);
31427
+ clearTimeout(job.lockTimer);
31413
31428
  if (job.aborted) job.signal?.removeEventListener("abort", job.aborted);
31414
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
+ }
31415
31442
  pump() {
31416
31443
  for (let i = 0; i < this.waiting.length && this.active.size < this.safeSlots; ) {
31417
31444
  const job = this.waiting[i];
@@ -32114,6 +32141,7 @@ var knownCodes = /* @__PURE__ */ new Set([
32114
32141
  "WORKSPACE_CHANGED",
32115
32142
  "WORKSPACE_UNAVAILABLE",
32116
32143
  "RESOURCE_BUSY",
32144
+ "RESOURCE_LOCKED",
32117
32145
  "AGENT_PAUSED",
32118
32146
  "CANCELLED_BEFORE_ACCEPTANCE",
32119
32147
  "ADMISSION_DEADLINE_EXPIRED",
@@ -32128,6 +32156,7 @@ var knownCodes = /* @__PURE__ */ new Set([
32128
32156
  "SCREEN_ENCODER_UNAVAILABLE",
32129
32157
  "SCREEN_RECORDING_PERMISSION_REQUIRED"
32130
32158
  ]);
32159
+ var LOCK_WAIT_MS = 2e4;
32131
32160
  function safeCode(error62) {
32132
32161
  const code = error62 instanceof NativeToolError ? error62.code : error62 instanceof Error ? error62.message : "";
32133
32162
  return knownCodes.has(code) || /^GUARD_[A-Z_]{1,30}$/.test(code) ? code : "TOOL_FAILED";
@@ -32339,7 +32368,7 @@ var NativeRuntime = class {
32339
32368
  const final = await this.options.journal.finish(binding2.executionId, image === void 0 ? journalOutput : { ...journalOutput, stdout: screenshotMetadata(image) }, resultCode);
32340
32369
  const outbound = await outboundResult(runnable.call, journalResult(final.result, resultCode), binding2, this.optionalTelemetry, this.options.efficiencyLedger);
32341
32370
  this.send({ type: "result", version: 1, binding: binding2, result: image === void 0 ? outbound : { ...outbound, stdout: image } });
32342
- }, abort.signal);
32371
+ }, abort.signal, LOCK_WAIT_MS);
32343
32372
  context.task = work.catch(async (error62) => {
32344
32373
  if (!context.accepted) {
32345
32374
  if (context.guardPermit) await this.options.guard.rejected(context.guardPermit, safeCode(error62)).catch(() => {
@@ -48992,7 +49021,7 @@ var NativeEventBuffer = class {
48992
49021
 
48993
49022
  // agent/src/native-event-supervisor.ts
48994
49023
  var eventKinds = /* @__PURE__ */ new Set(["queued", "admitted", "released", "queue_rejected", "prepared", "accepted", "running", "result", "not_accepted", "connected", "disconnected", "mailbox_expired"]);
48995
- 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"]);
48996
49025
  var NativeEventSupervisor = class {
48997
49026
  constructor(onChange) {
48998
49027
  this.onChange = onChange;
@@ -50824,7 +50853,7 @@ async function restoreContentAudit(input2, output2, key) {
50824
50853
  }
50825
50854
 
50826
50855
  // agent/src/main.ts
50827
- var AGENT_VERSION2 = true ? "0.3.47" : "0.3.2";
50856
+ var AGENT_VERSION2 = true ? "0.3.49" : "0.3.2";
50828
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" : "";
50829
50858
  var AI_CONNECTION_SHIPPED = false;
50830
50859
  function processAlive(pid) {
@@ -1,17 +1,17 @@
1
1
  {
2
- "version": "0.3.47",
2
+ "version": "0.3.49",
3
3
  "experimental": true,
4
4
  "platform": "linux",
5
5
  "arch": "x64",
6
6
  "node": "v22.23.3",
7
- "source": "df3c7268691268bf4d9c7ad1fd0225cfd3e4e25f",
8
- "sourceTreeSha256": "55d2835bd5fd435a09d78cb5bb890b69c37127c6fac02077d2c2280642e596dc",
7
+ "source": "c473bc0482280326f04aae47f14ad36ffb6a848f",
8
+ "sourceTreeSha256": "321301eb91adbbe3cd81cce7a68ff1713a13a5df7dcf31071ab8df98a2189d2e",
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": "54343afee2c12f7a4b4ac46e3bebe1ee2fde4af58305b22a286b64773faab453",
14
+ "agent.mjs": "466cdcf16ffe5e7e639fef07a87faba8ea6f91e28ed9512cb03a228ed4e5cfd1",
15
15
  "job-host.mjs": "54ab42fa00a53dfd4df6c93fd9e6692d5e03a0870aba8bf501f398905694b72d",
16
16
  "lifecycle.mjs": "ebed6bac75115ef1df34aff9fef211c9f710a524b2b614115b6bc80ef57b464b",
17
17
  "node": "fde6a4bf8d0562f7751d1a2d6cb9b417c4cfe107bbcb0aa3e9a24e125e348f48",