@alan-ai-hq/agent-manager 0.1.96 → 0.1.97

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 (2) hide show
  1. package/dist/index.cjs +210 -19
  2. package/package.json +3 -3
package/dist/index.cjs CHANGED
@@ -14583,6 +14583,15 @@ var import_node_os = require("os");
14583
14583
  var import_node_path = require("path");
14584
14584
 
14585
14585
  // ../sandbox-runtime-spec/dist/index.js
14586
+ var SANDBOX_AGENT_BROWSER_PACKAGE = "agent-browser";
14587
+ var SANDBOX_AGENT_BROWSER_VERSION_POLICY = ">=0.37.1 <1.0.0";
14588
+ var SANDBOX_AGENT_BROWSER_NPM_SPEC = `${SANDBOX_AGENT_BROWSER_PACKAGE}@${SANDBOX_AGENT_BROWSER_VERSION_POLICY}`;
14589
+ var SANDBOX_DESKTOP_BROWSER_ENV = Object.freeze({
14590
+ DISPLAY: ":0",
14591
+ AGENT_BROWSER_HEADED: "true",
14592
+ AGENT_BROWSER_NO_XVFB: "1",
14593
+ AGENT_BROWSER_EXECUTABLE_PATH: "/usr/bin/google-chrome-stable"
14594
+ });
14586
14595
  var definitions = [
14587
14596
  {
14588
14597
  id: "claude",
@@ -15451,7 +15460,7 @@ function describeError(error61) {
15451
15460
  }
15452
15461
 
15453
15462
  // src/version.ts
15454
- var AGENT_VERSION = "0.1.96";
15463
+ var AGENT_VERSION = "0.1.97";
15455
15464
 
15456
15465
  // src/daemon-worktree.ts
15457
15466
  var import_node_child_process3 = require("child_process");
@@ -20292,9 +20301,9 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
20292
20301
  }`;
20293
20302
  doc.write(`const input = payload.value;`);
20294
20303
  const ids = /* @__PURE__ */ Object.create(null);
20295
- let counter = 0;
20304
+ let counter2 = 0;
20296
20305
  for (const key of normalized.allKeys) {
20297
- ids[key] = `key_${counter++}`;
20306
+ ids[key] = `key_${counter2++}`;
20298
20307
  }
20299
20308
  doc.write(memo4 ? `const newResult = memo.alloc(inst, payload, {}, ctx);` : `const newResult = {};`);
20300
20309
  for (const key of normalized.allKeys) {
@@ -74429,6 +74438,14 @@ var skillVersionIdSchema = external_exports.uuid().transform((value2) => value2)
74429
74438
  var runtimeIdSchema = external_exports.uuid().transform((value2) => value2);
74430
74439
  var skillPreviewIdSchema = external_exports.uuid().transform((value2) => value2);
74431
74440
  var skillCommandIdSchema = external_exports.uuid().transform((value2) => value2);
74441
+ var skillPackageFileSchema = defineWireSchema()(external_exports.object({
74442
+ path: external_exports.string().min(1),
74443
+ kind: external_exports.enum(["instructions", "script", "reference", "asset", "license", "other"]),
74444
+ size: external_exports.number().int().nonnegative(),
74445
+ mode: external_exports.union([external_exports.literal(420), external_exports.literal(493)]),
74446
+ sha256: sha256Schema,
74447
+ preview: external_exports.enum(["markdown", "text", "code", "image", "binary"])
74448
+ }));
74432
74449
  var skillInvocationSchema = defineWireSchema()(external_exports.discriminatedUnion("kind", [
74433
74450
  external_exports.object({
74434
74451
  kind: external_exports.literal("skill_version"),
@@ -74530,6 +74547,7 @@ function projectSkillFrontmatter(admitted) {
74530
74547
  };
74531
74548
  const license = optionalText("license", 1024);
74532
74549
  const compatibility = optionalText("compatibility", 500);
74550
+ const version2 = optionalText("version", 64);
74533
74551
  const allowedTools = optionalToolList("allowed-tools", 1024);
74534
74552
  const metadata = {};
74535
74553
  const rawMetadata = raw.metadata;
@@ -74578,6 +74596,7 @@ function projectSkillFrontmatter(admitted) {
74578
74596
  description: admitted.description,
74579
74597
  ...license ? { license } : {},
74580
74598
  ...compatibility ? { compatibility } : {},
74599
+ ...version2 ? { version: version2 } : {},
74581
74600
  metadata,
74582
74601
  ...allowedTools ? { allowedTools } : {}
74583
74602
  },
@@ -95976,7 +95995,7 @@ function decodeResumeFallbackContext(encoded) {
95976
95995
  }
95977
95996
 
95978
95997
  // src/sandbox.ts
95979
- var import_node_os18 = require("os");
95998
+ var import_node_os19 = require("os");
95980
95999
 
95981
96000
  // src/execution-activity-tracker.ts
95982
96001
  var ExecutionActivityTracker = class {
@@ -96572,6 +96591,34 @@ var agentRunStateSchema = external_exports.object({
96572
96591
  /** Run ids currently executing (cloud sandbox agent runs one at a time, but keep it a list). */
96573
96592
  activeRunIds: external_exports.array(external_exports.string()).default([])
96574
96593
  });
96594
+ var AGENT_RESOURCE_SAMPLE_INTERVAL_MS = 6e4;
96595
+ var resourceCounter = external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
96596
+ var resourceMeasurement = external_exports.number().nonnegative().max(Number.MAX_SAFE_INTEGER);
96597
+ var pressurePercentage = external_exports.number().min(0).max(100);
96598
+ var agentResourceDiagnosticsSchema = external_exports.object({
96599
+ sampledAtMs: resourceCounter,
96600
+ memoryTotalBytes: resourceCounter,
96601
+ memoryFreeBytes: resourceCounter,
96602
+ /** Linux MemAvailable includes reclaimable memory; free memory alone does not. */
96603
+ memoryAvailableBytes: resourceCounter.optional(),
96604
+ swapTotalBytes: resourceCounter.optional(),
96605
+ swapFreeBytes: resourceCounter.optional(),
96606
+ processRssBytes: resourceCounter,
96607
+ cpuCount: external_exports.number().int().positive().max(65536),
96608
+ /** Omitted on Windows, where os.loadavg() always returns zero. */
96609
+ loadAverage1m: resourceMeasurement.optional(),
96610
+ eventLoopDelayMaxMs: resourceMeasurement.optional(),
96611
+ eventLoopDelayP99Ms: resourceMeasurement.optional(),
96612
+ memoryPressureSomeAvg10: pressurePercentage.optional(),
96613
+ memoryPressureFullAvg10: pressurePercentage.optional(),
96614
+ cpuPressureSomeAvg10: pressurePercentage.optional(),
96615
+ ioPressureSomeAvg10: pressurePercentage.optional(),
96616
+ /** Counters for the agent's current cgroup v2, including its child workload. */
96617
+ cgroupMemoryCurrentBytes: resourceCounter.optional(),
96618
+ cgroupMemoryLimitBytes: resourceCounter.optional(),
96619
+ cgroupMemoryOomEvents: resourceCounter.optional(),
96620
+ cgroupMemoryOomKillEvents: resourceCounter.optional()
96621
+ });
96575
96622
  var agentHeartbeatSchema = external_exports.object({
96576
96623
  /** Stable id for this agent OS process; changes only on a fresh agent start. */
96577
96624
  agentSessionId: external_exports.string().min(1),
@@ -96580,7 +96627,9 @@ var agentHeartbeatSchema = external_exports.object({
96580
96627
  /** Capability marker — presence is what distinguishes a new agent from a legacy one. */
96581
96628
  protocolVersion: external_exports.number().int().positive(),
96582
96629
  runState: agentRunStateSchema,
96583
- agentVersion: external_exports.string().optional()
96630
+ agentVersion: external_exports.string().optional(),
96631
+ // Bad optional diagnostics must never discard otherwise valid liveness evidence.
96632
+ resources: agentResourceDiagnosticsSchema.optional().catch(void 0)
96584
96633
  });
96585
96634
  var agentProbeAckSchema = external_exports.object({
96586
96635
  agentSessionId: external_exports.string().min(1),
@@ -96588,9 +96637,147 @@ var agentProbeAckSchema = external_exports.object({
96588
96637
  protocolVersion: external_exports.number().int().positive().optional()
96589
96638
  });
96590
96639
 
96640
+ // src/resource-diagnostics.ts
96641
+ var import_node_fs28 = require("fs");
96642
+ var import_node_os18 = require("os");
96643
+ var import_node_path30 = require("path");
96644
+ var import_node_perf_hooks = require("perf_hooks");
96645
+ var MAX_RESOURCE_FILE_BYTES = 16384;
96646
+ var RESOURCE_READ_TIMEOUT_MS = 500;
96647
+ async function readResourceFile(path2) {
96648
+ try {
96649
+ const stream = (0, import_node_fs28.createReadStream)(path2, {
96650
+ encoding: "utf8",
96651
+ start: 0,
96652
+ end: MAX_RESOURCE_FILE_BYTES,
96653
+ signal: AbortSignal.timeout(RESOURCE_READ_TIMEOUT_MS)
96654
+ });
96655
+ let text = "";
96656
+ for await (const chunk of stream) {
96657
+ text += chunk;
96658
+ if (text.length > MAX_RESOURCE_FILE_BYTES) return void 0;
96659
+ }
96660
+ return text;
96661
+ } catch {
96662
+ return void 0;
96663
+ }
96664
+ }
96665
+ function counter(value2) {
96666
+ if (!value2 || !/^\d+$/.test(value2)) return void 0;
96667
+ const parsed = Number(value2);
96668
+ return Number.isSafeInteger(parsed) ? parsed : void 0;
96669
+ }
96670
+ function pressure(text, kind) {
96671
+ const value2 = text?.match(new RegExp(`^${kind} avg10=(\\d+(?:\\.\\d+)?) `, "m"))?.[1];
96672
+ if (value2 === void 0) return void 0;
96673
+ const parsed = Number(value2);
96674
+ return Number.isFinite(parsed) && parsed <= 100 ? parsed : void 0;
96675
+ }
96676
+ function meminfoBytes(text, field) {
96677
+ const kb = counter(text?.match(new RegExp(`^${field}:\\s+(\\d+) kB$`, "m"))?.[1]);
96678
+ return kb !== void 0 && Number.isSafeInteger(kb * 1024) ? kb * 1024 : void 0;
96679
+ }
96680
+ function cgroupDirectory(text) {
96681
+ const path2 = text?.match(/^0::(\/[^\n]*)$/m)?.[1];
96682
+ if (!path2 || path2.split("/").includes("..")) return void 0;
96683
+ return import_node_path30.posix.join("/sys/fs/cgroup", path2);
96684
+ }
96685
+ async function collectAgentResourceDiagnostics(options = {}) {
96686
+ const platform6 = options.platform ?? process.platform;
96687
+ const readFile7 = async (path2) => {
96688
+ try {
96689
+ return await (options.readFile ?? readResourceFile)(path2);
96690
+ } catch {
96691
+ return void 0;
96692
+ }
96693
+ };
96694
+ const sample = {
96695
+ sampledAtMs: Date.now(),
96696
+ memoryTotalBytes: (0, import_node_os18.totalmem)(),
96697
+ memoryFreeBytes: (0, import_node_os18.freemem)(),
96698
+ processRssBytes: process.memoryUsage.rss(),
96699
+ cpuCount: (0, import_node_os18.availableParallelism)(),
96700
+ ...platform6 === "win32" ? {} : { loadAverage1m: (0, import_node_os18.loadavg)()[0] }
96701
+ };
96702
+ if (platform6 !== "linux") return sample;
96703
+ const [meminfo, memoryPsi, cpuPsi, ioPsi, cgroup] = await Promise.all([
96704
+ readFile7("/proc/meminfo"),
96705
+ readFile7("/proc/pressure/memory"),
96706
+ readFile7("/proc/pressure/cpu"),
96707
+ readFile7("/proc/pressure/io"),
96708
+ readFile7("/proc/self/cgroup")
96709
+ ]);
96710
+ sample.memoryAvailableBytes = meminfoBytes(meminfo, "MemAvailable");
96711
+ sample.swapTotalBytes = meminfoBytes(meminfo, "SwapTotal");
96712
+ sample.swapFreeBytes = meminfoBytes(meminfo, "SwapFree");
96713
+ sample.memoryPressureSomeAvg10 = pressure(memoryPsi, "some");
96714
+ sample.memoryPressureFullAvg10 = pressure(memoryPsi, "full");
96715
+ sample.cpuPressureSomeAvg10 = pressure(cpuPsi, "some");
96716
+ sample.ioPressureSomeAvg10 = pressure(ioPsi, "some");
96717
+ const directory = cgroupDirectory(cgroup);
96718
+ if (!directory) return sample;
96719
+ const [current, limit, events] = await Promise.all([
96720
+ readFile7(`${directory}/memory.current`),
96721
+ readFile7(`${directory}/memory.max`),
96722
+ readFile7(`${directory}/memory.events`)
96723
+ ]);
96724
+ sample.cgroupMemoryCurrentBytes = counter(current?.trim());
96725
+ sample.cgroupMemoryLimitBytes = counter(limit?.trim());
96726
+ sample.cgroupMemoryOomEvents = counter(events?.match(/^oom (\d+)$/m)?.[1]);
96727
+ sample.cgroupMemoryOomKillEvents = counter(events?.match(/^oom_kill (\d+)$/m)?.[1]);
96728
+ return sample;
96729
+ }
96730
+ var AgentResourceSampler = class {
96731
+ constructor(collect = collectAgentResourceDiagnostics) {
96732
+ this.collect = collect;
96733
+ }
96734
+ delay = (0, import_node_perf_hooks.monitorEventLoopDelay)({ resolution: 20 });
96735
+ timer;
96736
+ inFlight = false;
96737
+ generation = 0;
96738
+ sample;
96739
+ start() {
96740
+ if (this.timer) return;
96741
+ this.generation += 1;
96742
+ this.delay.reset();
96743
+ this.delay.enable();
96744
+ this.timer = setInterval(() => void this.refresh(), AGENT_RESOURCE_SAMPLE_INTERVAL_MS);
96745
+ this.timer.unref();
96746
+ void this.refresh();
96747
+ }
96748
+ stop() {
96749
+ this.generation += 1;
96750
+ if (this.timer) clearInterval(this.timer);
96751
+ this.timer = void 0;
96752
+ this.delay.disable();
96753
+ this.sample = void 0;
96754
+ }
96755
+ latest() {
96756
+ return this.sample;
96757
+ }
96758
+ async refresh() {
96759
+ if (this.inFlight) return;
96760
+ this.inFlight = true;
96761
+ const generation = this.generation;
96762
+ const delay3 = this.delay.count > 0 ? {
96763
+ eventLoopDelayMaxMs: this.delay.max / 1e6,
96764
+ eventLoopDelayP99Ms: this.delay.percentile(99) / 1e6
96765
+ } : {};
96766
+ this.delay.reset();
96767
+ try {
96768
+ const sample = await this.collect();
96769
+ if (generation === this.generation) this.sample = { ...sample, ...delay3 };
96770
+ } catch {
96771
+ if (generation === this.generation) this.sample = void 0;
96772
+ } finally {
96773
+ this.inFlight = false;
96774
+ }
96775
+ }
96776
+ };
96777
+
96591
96778
  // src/sandbox-outbox.ts
96592
96779
  var import_node_crypto23 = require("crypto");
96593
- var import_node_fs28 = require("fs");
96780
+ var import_node_fs29 = require("fs");
96594
96781
  function deriveSandboxOutboxKey(sessionToken) {
96595
96782
  if (!sessionToken) {
96596
96783
  throw new Error("sandbox event outbox requires ALAN_SESSION_TOKEN for key derivation");
@@ -96611,24 +96798,24 @@ function assertValidOutboxKey(key, path2) {
96611
96798
  }
96612
96799
  function loadOrCreateSandboxOutboxKey(input2) {
96613
96800
  const keyPath = sandboxOutboxKeyPath(input2.spoolPath);
96614
- if ((0, import_node_fs28.existsSync)(keyPath)) {
96615
- (0, import_node_fs28.chmodSync)(keyPath, 384);
96616
- return assertValidOutboxKey((0, import_node_fs28.readFileSync)(keyPath, "utf8").trim(), keyPath);
96801
+ if ((0, import_node_fs29.existsSync)(keyPath)) {
96802
+ (0, import_node_fs29.chmodSync)(keyPath, 384);
96803
+ return assertValidOutboxKey((0, import_node_fs29.readFileSync)(keyPath, "utf8").trim(), keyPath);
96617
96804
  }
96618
96805
  const initialKey = deriveSandboxOutboxKey(input2.sessionToken);
96619
96806
  try {
96620
- (0, import_node_fs28.writeFileSync)(keyPath, initialKey, { encoding: "utf8", flag: "wx", mode: 384 });
96807
+ (0, import_node_fs29.writeFileSync)(keyPath, initialKey, { encoding: "utf8", flag: "wx", mode: 384 });
96621
96808
  return initialKey;
96622
96809
  } catch (error61) {
96623
96810
  if (error61.code !== "EEXIST") throw error61;
96624
- (0, import_node_fs28.chmodSync)(keyPath, 384);
96625
- return assertValidOutboxKey((0, import_node_fs28.readFileSync)(keyPath, "utf8").trim(), keyPath);
96811
+ (0, import_node_fs29.chmodSync)(keyPath, 384);
96812
+ return assertValidOutboxKey((0, import_node_fs29.readFileSync)(keyPath, "utf8").trim(), keyPath);
96626
96813
  }
96627
96814
  }
96628
96815
  function quarantineUnusableOutbox(path2) {
96629
96816
  const suffix = `corrupt-${Date.now()}-${process.pid}`;
96630
96817
  for (const candidate of [path2, eventJournalDir(path2)]) {
96631
- if ((0, import_node_fs28.existsSync)(candidate)) (0, import_node_fs28.renameSync)(candidate, `${candidate}.${suffix}`);
96818
+ if ((0, import_node_fs29.existsSync)(candidate)) (0, import_node_fs29.renameSync)(candidate, `${candidate}.${suffix}`);
96632
96819
  }
96633
96820
  }
96634
96821
  function createSandboxEventOutbox(input2) {
@@ -96776,6 +96963,7 @@ var WSClient = class {
96776
96963
  /** Monotonic heartbeat sequence — advances on every hello + heartbeat. */
96777
96964
  heartbeatSeq = 0;
96778
96965
  heartbeatTimer = null;
96966
+ resourceSampler = new AgentResourceSampler();
96779
96967
  supervisedReconnectTimer = null;
96780
96968
  supervisedReconnectAttempt = 0;
96781
96969
  connectionDirective = null;
@@ -96824,11 +97012,13 @@ var WSClient = class {
96824
97012
  seq: this.heartbeatSeq,
96825
97013
  protocolVersion: AGENT_LIVENESS_PROTOCOL_VERSION,
96826
97014
  runState: this.currentRunState(),
96827
- agentVersion: this.agentVersion || void 0
97015
+ agentVersion: this.agentVersion || void 0,
97016
+ resources: this.resourceSampler.latest()
96828
97017
  };
96829
97018
  }
96830
97019
  /** Emit `agent.hello` on (re)connect and (re)start the heartbeat interval. */
96831
97020
  startHeartbeat() {
97021
+ this.resourceSampler.start();
96832
97022
  if (this.socket.connected) {
96833
97023
  this.socket.emit("agent.hello", this.buildHeartbeat());
96834
97024
  }
@@ -96840,6 +97030,7 @@ var WSClient = class {
96840
97030
  this.heartbeatTimer.unref?.();
96841
97031
  }
96842
97032
  stopHeartbeat() {
97033
+ this.resourceSampler.stop();
96843
97034
  if (this.heartbeatTimer) {
96844
97035
  clearInterval(this.heartbeatTimer);
96845
97036
  this.heartbeatTimer = null;
@@ -97304,7 +97495,7 @@ async function runSandbox(config2) {
97304
97495
  }
97305
97496
  const presenter = new WebPresenter(wsClient, config2.sessionId, config2.projectPath);
97306
97497
  presenter.setSuppressSessionLifecycle(true);
97307
- const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0, import_node_os18.homedir)() });
97498
+ const runtimeSkillManager = await RuntimeSkillManager.open({ homeDirectory: (0, import_node_os19.homedir)() });
97308
97499
  let lastProviderSessionId = config2.providerSessionId;
97309
97500
  let resumeFallbackContext = config2.resumeFallbackContext;
97310
97501
  let activeBackendKind = config2.backendKind || "claude_cli";
@@ -97605,11 +97796,11 @@ async function runSandbox(config2) {
97605
97796
 
97606
97797
  // src/skills/skill-cli.ts
97607
97798
  var import_promises6 = require("fs/promises");
97608
- var import_node_os19 = require("os");
97609
- var import_node_path30 = require("path");
97799
+ var import_node_os20 = require("os");
97800
+ var import_node_path31 = require("path");
97610
97801
  async function runSkillsCommand(args) {
97611
97802
  const [subcommand, ...options] = args;
97612
- const homeDirectory2 = option(options, "--home") ?? (0, import_node_os19.homedir)();
97803
+ const homeDirectory2 = option(options, "--home") ?? (0, import_node_os20.homedir)();
97613
97804
  const manager = await RuntimeSkillManager.open({ homeDirectory: homeDirectory2 });
97614
97805
  if (subcommand === "scan") {
97615
97806
  const inputPath = option(options, "--input");
@@ -97650,7 +97841,7 @@ async function defaultScanInput(homeDirectory2) {
97650
97841
  });
97651
97842
  }
97652
97843
  async function readProtectedJson(path2) {
97653
- const absolutePath = (0, import_node_path30.resolve)(path2);
97844
+ const absolutePath = (0, import_node_path31.resolve)(path2);
97654
97845
  const stat2 = await (0, import_promises6.lstat)(absolutePath);
97655
97846
  if (!stat2.isFile()) throw new Error(`Skill input is not a regular file: ${absolutePath}`);
97656
97847
  if (process.platform !== "win32" && (stat2.mode & 63) !== 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alan-ai-hq/agent-manager",
3
- "version": "0.1.96",
3
+ "version": "0.1.97",
4
4
  "type": "module",
5
5
  "description": "Alan agent runtime — cloud sandbox and local daemon (alan-agent CLI)",
6
6
  "bin": {
@@ -27,8 +27,8 @@
27
27
  "tsx": "^4.19.0",
28
28
  "typescript": "~5.9.3",
29
29
  "@alan-ai/agent-core": "0.1.0",
30
- "@alan-ai/sandbox-runtime-spec": "0.1.0",
31
- "@alan-ai/shared": "0.1.0"
30
+ "@alan-ai/shared": "0.1.0",
31
+ "@alan-ai/sandbox-runtime-spec": "0.1.0"
32
32
  },
33
33
  "scripts": {
34
34
  "build": "tsup",