@rosthq/cli 0.7.65 → 0.7.67

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.
@@ -1 +1 @@
1
- {"version":3,"file":"command-manifest.d.ts","sourceRoot":"","sources":["../../src/generated/command-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,eAAO,MAAM,gBAAgB,EAAE,SAAS,oBAAoB,EAyO3D,CAAC"}
1
+ {"version":3,"file":"command-manifest.d.ts","sourceRoot":"","sources":["../../src/generated/command-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,eAAO,MAAM,gBAAgB,EAAE,SAAS,oBAAoB,EA0O3D,CAAC"}
@@ -0,0 +1,23 @@
1
+ export type HostResourceTelemetry = {
2
+ load_avg_1m: number | null;
3
+ memory_available_mb: number | null;
4
+ swap_used_mb: number | null;
5
+ swap_total_mb: number | null;
6
+ };
7
+ export declare function parseLinuxMeminfoSwap(meminfo: string): {
8
+ swap_used_mb: number;
9
+ swap_total_mb: number;
10
+ } | null;
11
+ export declare function parseDarwinSwapusage(output: string): {
12
+ swap_used_mb: number;
13
+ swap_total_mb: number;
14
+ } | null;
15
+ export type HostResourceDeps = {
16
+ platform: () => string;
17
+ loadAvg: () => number[];
18
+ freeMemBytes: () => number;
19
+ readLinuxMeminfo: () => string;
20
+ readDarwinSwapusage: () => string;
21
+ };
22
+ export declare function detectHostResource(deps?: HostResourceDeps): HostResourceTelemetry;
23
+ //# sourceMappingURL=host-resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-resource.d.ts","sourceRoot":"","sources":["../src/host-resource.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAGF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS7G;AAGD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAmB3G;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,MAAM,CAAC;IAC/B,mBAAmB,EAAE,MAAM,MAAM,CAAC;CACnC,CAAC;AAUF,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,gBAA8B,GAAG,qBAAqB,CAiC9F"}
package/dist/index.js CHANGED
@@ -38266,6 +38266,23 @@ var CATALOG_ENTRIES = [
38266
38266
  // `agent.script_run` account entitlement gates availability on top of this.
38267
38267
  default_access_policy: "always_ask"
38268
38268
  },
38269
+ {
38270
+ id: "secret.broker",
38271
+ title: "Call an authenticated API (brokered)",
38272
+ provider: "rost",
38273
+ description: "Call this to make ONE authenticated request to a pre-approved third-party API on the agent's behalf. You supply only the grant key, method, path, and query/body \u2014 never a credential. A server-side broker injects the secret, calls the single allowlisted host/path/method the grant permits, and returns a size-capped, secret-scrubbed result (response bodies that echo credential-shaped material are redacted wholesale). The secret never enters your context or the sandbox. Read requests run directly; any write (POST/PUT/PATCH/DELETE) is HELD for human approval before it is sent. Every attempt is audited.",
38274
+ // A write goes out over the network with a real credential — the broadest tier.
38275
+ // Reads on the same grant self-select the read behaviour at call time; the
38276
+ // catalog tier is the ceiling (a write is held-with-approval).
38277
+ default_scope_tier: "write_with_approval",
38278
+ scope_tiers: ["read", "write_with_approval"],
38279
+ // The broker resolves a vault ref per grant and injects it server-side.
38280
+ credential_required: true,
38281
+ // Conservative by default (invariant #10): brokered egress is confirmed by
38282
+ // default; writes are additionally held for /approvals. A per-seat grant
38283
+ // (script_run_secret_grants) gates availability on top of this — no grant, no call.
38284
+ default_access_policy: "always_ask"
38285
+ },
38269
38286
  {
38270
38287
  id: "ap.invoices.read",
38271
38288
  title: "Read AP invoices",
@@ -39000,8 +39017,29 @@ var agentSetupNextActionSchema = external_exports.enum([
39000
39017
  "sign_manifest",
39001
39018
  "run_dry_run",
39002
39019
  "go_live",
39003
- "complete"
39020
+ "complete",
39021
+ // DER-1628: live-agent remediation actions. A live agent is NOT automatically
39022
+ // "complete" — a missing/never-approved active Charter or an ARCHIVED
39023
+ // configured parent is a real post-go-live defect that must route the operator
39024
+ // to the exact repair instead of falsely reading complete. These only ever
39025
+ // appear for a live/promotable agent (the setup wizard's forward actions above
39026
+ // cover the draft flow), and DER-1652 deep-links each to its repair surface.
39027
+ "fix_charter",
39028
+ "fix_reporting_line"
39004
39029
  ]);
39030
+ var agentSetupBlockerCodeSchema = external_exports.enum([
39031
+ "missing_active_charter",
39032
+ "archived_parent",
39033
+ "missing_parent",
39034
+ "missing_steward",
39035
+ "missing_occupancy",
39036
+ "missing_goal_or_measurable",
39037
+ "skill_dependency_blocked"
39038
+ ]);
39039
+ var agentSetupBlockerSchema = external_exports.object({
39040
+ code: agentSetupBlockerCodeSchema,
39041
+ message: external_exports.string().min(1).max(500)
39042
+ }).strict();
39005
39043
  var agentSetupSkillRecommendationSchema = skillSummarySchema.extend({
39006
39044
  match_score: external_exports.number().int().min(0).max(100),
39007
39045
  recommendation_reason: external_exports.string().min(1).max(240)
@@ -39067,7 +39105,10 @@ var agentSetupStateSchema = external_exports.object({
39067
39105
  // reload. Optional so a pre-DER-842 recorded result still validates.
39068
39106
  transcript: dryRunTranscriptSchema.optional()
39069
39107
  }).strict().nullable(),
39070
- blockers: external_exports.array(external_exports.string()),
39108
+ // DER-1628: typed, stable completeness blockers (was `string[]`). `complete`
39109
+ // is impossible while this array is non-empty — every surface reads the same
39110
+ // canonical result rather than doing its own completeness math.
39111
+ blockers: external_exports.array(agentSetupBlockerSchema),
39071
39112
  next_action: agentSetupNextActionSchema
39072
39113
  }).strict();
39073
39114
  var agentSetupToolUpdateSchema = external_exports.object({
@@ -40819,7 +40860,11 @@ var goalBindMeasurableOutputSchema = external_exports.object({
40819
40860
  computed_status: goalStatusSchema.nullable(),
40820
40861
  // True when a human status pin currently diverges from what the signal computes
40821
40862
  // ("computed says X / you pinned Y").
40822
- pinned_divergence: external_exports.boolean()
40863
+ pinned_divergence: external_exports.boolean(),
40864
+ // DER-1633: false for a fresh binding; true when this exact (goal, Signal) pair was
40865
+ // already bound — the command is an idempotent no-op (no new event, no duplicate
40866
+ // confirmation). Lets a caller distinguish "just bound" from "already bound".
40867
+ already_bound: external_exports.boolean()
40823
40868
  }).strict();
40824
40869
  var goalUnbindMeasurableInputSchema = external_exports.object({
40825
40870
  goal_id: uuidSchema8,
@@ -40846,6 +40891,27 @@ var goalSetAutoStatusOutputSchema = external_exports.object({
40846
40891
  status_source: goalStatusSourceSchema,
40847
40892
  applied_from_signal: external_exports.boolean()
40848
40893
  }).strict();
40894
+ var goalMeasurableBindingSchema = external_exports.object({
40895
+ measurable_id: uuidSchema8,
40896
+ name: external_exports.string(),
40897
+ unit: external_exports.string(),
40898
+ role: external_exports.literal("drives_status"),
40899
+ auto_status_enabled: external_exports.boolean(),
40900
+ // Current signal indicator + the status it would compute from the latest CONFIRMED
40901
+ // reading (null while awaiting a confirmed reading).
40902
+ signal_state: goalSignalStateSchema,
40903
+ computed_status: goalStatusSchema.nullable(),
40904
+ // The latest confirmed reading's value (null while awaiting one) — enough to render
40905
+ // "measured by <Signal>: <value> <unit>" instead of a bare "Not measured".
40906
+ last_reading_value: external_exports.number().nullable()
40907
+ }).strict();
40908
+ var goalListMeasurablesInputSchema = external_exports.object({
40909
+ goal_id: uuidSchema8
40910
+ }).strict();
40911
+ var goalListMeasurablesOutputSchema = external_exports.object({
40912
+ goal_id: uuidSchema8,
40913
+ bindings: external_exports.array(goalMeasurableBindingSchema)
40914
+ }).strict();
40849
40915
  var issueStatusSchema = external_exports.enum(["open", "diagnosing", "resolved", "dropped"]);
40850
40916
  var frictionListInputSchema = external_exports.object({
40851
40917
  status: external_exports.enum(["open", "diagnosing", "resolved", "dropped", "active", "all"]).optional()
@@ -44385,7 +44451,8 @@ var syncBriefExceptionSchema = external_exports.object({
44385
44451
  latest_value: external_exports.number().nullable(),
44386
44452
  target: external_exports.number(),
44387
44453
  unit: external_exports.string(),
44388
- period_start: dateSchema.nullable()
44454
+ period_start: dateSchema.nullable(),
44455
+ freshness: external_exports.enum(["fresh", "due", "stale", "awaiting_first_reading", "not_expected"]).optional()
44389
44456
  }).strict();
44390
44457
  var syncBriefGoalDeltaSchema = external_exports.object({
44391
44458
  goal_id: uuidSchema15,
@@ -44663,10 +44730,20 @@ var statusRecordOutputSchema = external_exports.object({
44663
44730
  event_id: uuidSchema17,
44664
44731
  type: external_exports.literal("status")
44665
44732
  }).strict();
44733
+ var duplicateFrictionCandidateSchema = external_exports.object({
44734
+ issue_id: uuidSchema17,
44735
+ summary: external_exports.string().min(1),
44736
+ // pg_trgm similarity in [0, 1]; higher is more similar.
44737
+ similarity: external_exports.number().min(0).max(1)
44738
+ }).strict();
44666
44739
  var frictionFileIssueOutputSchema = external_exports.object({
44667
44740
  event_id: uuidSchema17,
44668
44741
  issue_id: uuidSchema17,
44669
- type: external_exports.literal("issue")
44742
+ type: external_exports.literal("issue"),
44743
+ // DER-1522: likely-duplicate candidates detected before creation. Recommend,
44744
+ // never block — filing always proceeds; empty when nothing crossed the
44745
+ // conservative threshold (or the actor is not an agent).
44746
+ duplicate_candidates: external_exports.array(duplicateFrictionCandidateSchema).default([])
44670
44747
  }).strict();
44671
44748
  var workLogInputSchema = external_exports.object({
44672
44749
  note: external_exports.string().min(1)
@@ -45759,7 +45836,7 @@ For CLI and MCP setup, read agent-skill-setup-guide before adding or assigning S
45759
45836
  order: 42,
45760
45837
  title: "Design a custom agent",
45761
45838
  summary: "How to build a custom agent from operational questions through the Charter Builder, tools, dry run, and go-live without writing prompts.",
45762
- version: "2026-07-10.1",
45839
+ version: "2026-07-12.1",
45763
45840
  public: true,
45764
45841
  audiences: ["human", "cli", "mcp", "in_app_agent"],
45765
45842
  stages: ["staffing", "charter_design"],
@@ -45824,6 +45901,14 @@ The same path is command-backed:
45824
45901
  7. \`agent.configure_tools\` / \`rost_configure_agent_tools\` records connect/decline decisions and credential-ingress requests (vault refs only).
45825
45902
  8. \`agent.run_dry_run\` / \`rost_run_agent_dry_run\` rehearses the task after the manifest is signed.
45826
45903
 
45904
+ ## Setup completeness and blockers
45905
+
45906
+ \`agent_setup.get\` derives completeness canonically, so every surface \u2014 the web builder, the CLI, and the \`agent.show_markdown\` readout \u2014 reads one result instead of doing its own math. It returns a \`blockers\` array plus a \`next_action\`. Each blocker is a typed \`{ code, message }\`: consumers key off the stable \`code\` (to group blockers or deep-link to the exact repair) and show \`message\` verbatim. A setup is \`complete\` only when \`blockers\` is empty; while any blocker is present, \`next_action\` points at the highest-priority repair rather than \`complete\`.
45907
+
45908
+ The blocker codes are a stable vocabulary \u2014 new reasons get a new code rather than a rename. Emitted today: \`missing_active_charter\`, \`archived_parent\`, \`missing_parent\`, \`missing_steward\`, and \`skill_dependency_blocked\` (\`missing_occupancy\` and \`missing_goal_or_measurable\` are reserved for later checks).
45909
+
45910
+ Completeness is not just a draft gate: a **live** agent is not automatically \`complete\`. If a live seat has no active, approved Charter, its configured parent is archived, or its steward chain no longer resolves to a human, \`agent_setup.get\` surfaces the matching blocker and routes \`next_action\` to the fix \u2014 \`fix_charter\` for \`missing_active_charter\`, \`fix_reporting_line\` for \`archived_parent\`, then \`set_steward\` for \`missing_steward\`, in that priority order. A live agent with no configured parent at all is the legitimate top-level case and stays \`complete\`; only an archived configured parent blocks it.
45911
+
45827
45912
  ## Dry run and go-live
45828
45913
 
45829
45914
  The dry run is a real sandbox rehearsal, not a stamp. It executes a mock-provider run derived from the Charter \u2014 the agent works against sandbox data only and is expected to escalate where the Charter's must-escalate clause requires it. The same rehearsal works on all three lanes: cloud, external MCP, and local Runner. External MCP dry runs require an active seat-scoped MCP token; Runner dry runs require a paired Runner. Missing substrate returns a typed precondition error, not a generic failure. The recorded run keeps the agent's actual lane, so the evidence you review matches the lane you selected. The result is earned: a run that escalates the must-escalate boundary passes; a run that acts on that boundary instead of escalating fails. A failed dry run keeps the draft and shows the reason so you can edit and rerun. The rehearsal returns a transcript \u2014 the steps the agent took and the escalation it raised \u2014 shown step by step in the builder and printed by the CLI, so you can see the governance model working before anything goes live. The transcript is also lane-honest: each granted tool is marked executable, held for the steward, or granted but unimplemented in this lane, with a plain-count verdict such as "2 of 6 granted tools don't execute in the cloud lane yet" \u2014 so a grant that would silently no-op in the cloud runtime is visible before go-live instead of passing green. Runner and MCP-session agents run those tools through their own local skills, so their grants are not flagged as unimplemented. When the dry run passes, a human promotes the agent live. The dry run rehearses the specific model tier you chose, so once it passes the model is locked \u2014 changing the model requires re-running the dry run on the new model before go-live.
@@ -46169,7 +46254,7 @@ External connectors are being rolled out provider by provider, conservatively (r
46169
46254
  order: 48,
46170
46255
  title: "CLI and MCP installation guide",
46171
46256
  summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
46172
- version: "2026-07-11.1",
46257
+ version: "2026-07-12.1",
46173
46258
  public: true,
46174
46259
  audiences: ["human", "cli", "mcp", "in_app_agent"],
46175
46260
  stages: ["company_setup", "staffing"],
@@ -46842,6 +46927,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
46842
46927
  | \`rost_import_rocks_from_a_ninety_rocks_export\` | \`cascade.import\` | Bulk-import Rocks as Cascade cycle goals under a company objective in the active cycle (from a ninety Rocks export). Owners resolve to seats; idempotent re-import skips a cycle goal already imported for the same objective + seat + title. | Tenant | Call with the parsed \`rocks\` array. |
46843
46928
  | \`rost_import_a_ninety_v_to_into_a_compass_draft\` | \`compass.import\` | AI-draft a Compass from a ninety V/TO (Core Values \u2192 principles, 10/3/1-Year \u2192 horizon goals, Rocks \u2192 cycle objectives), landed as a draft a human confirms by supersession \u2014 never an accepted Compass. Idempotent by document content (a re-upload of the same V/TO short-circuits without re-drafting). | Tenant | Call with the extracted V/TO \`text\` (and optional \`source_name\`). |
46844
46929
  | \`rost_list_cascade_goals\` | \`goal.list\` | List Cascade goals, optionally by cycle or seat. | Seat or tenant-admin | Call with \`{}\` or \`{"cycle_id":"<id>"}\`. |
46930
+ | \`rost_list_a_cascade_goals_signals\` | \`goal.list_measurables\` | List the Signals bound to a goal (drives_status) with each one's current indicator and latest confirmed reading. Read-only. | Seat or tenant-admin | Call with \`{"goal_id":"<id>"}\`. |
46845
46931
  | \`rost_create_cascade_goal\` | \`goal.create\` | Create a cycle goal under an objective. | Tenant | Call with cycle, seat, parent, title, definition of done. |
46846
46932
  | \`rost_update_cascade_goal\` | \`goal.update\` | Update a goal's title or definition of done. | Tenant | Call with \`goal_id\` and the changed fields. |
46847
46933
  | \`rost_set_cascade_goal_status\` | \`goal.set_status\` | Set a goal's status (on/off/done). | Seat or tenant-admin | Seats may set only their own goals. |
@@ -50102,6 +50188,7 @@ var COMMAND_MANIFEST = [
50102
50188
  { "id": "goal.drop", "namespace": "goal", "action": "drop", "title": "Drop Cascade goal", "description": "Drop (retire) a goal by setting status to dropped. Dropping retires the commitment, so it is human-gated. The row is retained for audit (never deleted).", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Drop a goal to retire a commitment; the goal is retained for audit and dropping is human-gated." },
50103
50189
  { "id": "goal.list", "namespace": "goal", "action": "list", "title": "List Cascade goals", "description": "List goals in the tenant, optionally filtered by cycle or seat. Seat-scoped callers see only their own seat's goals.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cycle_id", "flag": "cycle-id", "type": "string", "required": false }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "List Cascade goals to find goal ids, parentage, and seat ownership before mutating the tree." },
50104
50190
  { "id": "goal.list_at_risk", "namespace": "goal", "action": "list_at_risk", "title": "List at-risk Cascade goals", "description": "List goals projected to miss their cycle pace (at-risk or projected-miss), with how many days behind pace. Read-only; status-only goals (no progress) are excluded.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List goals projected off pace (at-risk or projected-miss), with how many days behind pace. Read-only; status-only goals are excluded." },
50191
+ { "id": "goal.list_measurables", "namespace": "goal", "action": "list_measurables", "title": "List a Cascade goal's Signals", "description": "List the Signals bound to a Cascade goal (role drives_status), each with its current signal indicator and latest confirmed reading. Read-only.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "List the Signals bound to a goal (role drives_status) with each one's current indicator and latest confirmed reading." },
50105
50192
  { "id": "goal.reparent", "namespace": "goal", "action": "reparent", "title": "Reparent Cascade goal", "description": "Move a goal under a different parent. Reparenting changes accountable structure, so it is human-gated. One-root and no-cycle are enforced server-side.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "parent_goal_id", "flag": "parent-goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Reparent a goal only when it clarifies accountable structure; reparenting changes authority and is human-gated." },
50106
50193
  { "id": "goal.set_auto_status", "namespace": "goal", "action": "set_auto_status", "title": "Toggle Signal-driven auto-status", "description": "Opt a goal's drives_status binding into (or out of) auto-status. Default OFF. Enabling lets confirmed readings drive the goal's status; a human status pin still wins. Human-gated opt-in.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "measurable_id", "flag": "measurable-id", "type": "string", "required": true }, { "name": "enabled", "flag": "enabled", "type": "boolean", "required": true }], "hasComplexInput": false, "help": "Opt a goal's Signal binding into (or out of) auto-status. Default OFF. Enabling lets confirmed readings drive the status; a human status pin still wins." },
50107
50194
  { "id": "goal.set_progress", "namespace": "goal", "action": "set_progress", "title": "Set Cascade goal progress", "description": "Set a goal's quantified progress (0\u2013100). Seat-scoped callers may set progress only for their own goals. An agent's progress is a proposal a human approves before it lands.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "progress_pct", "flag": "progress-pct", "type": "integer", "required": true }], "hasComplexInput": false, "help": "Report a goal's quantified progress (0-100). An agent's progress is a proposal a human approves before the goal moves." },
@@ -54599,6 +54686,80 @@ async function removeWorkspace(ws) {
54599
54686
  await removeWorktree(ws.baseRepo, ws.worktreeDir);
54600
54687
  }
54601
54688
 
54689
+ // src/host-resource.ts
54690
+ import { execFileSync } from "node:child_process";
54691
+ import { readFileSync as readFileSync4 } from "node:fs";
54692
+ import { freemem, loadavg, platform as osPlatform } from "node:os";
54693
+ var MB = 1024 * 1024;
54694
+ function parseLinuxMeminfoSwap(meminfo) {
54695
+ const total = /^SwapTotal:\s+(\d+)\s*kB/m.exec(meminfo);
54696
+ const free = /^SwapFree:\s+(\d+)\s*kB/m.exec(meminfo);
54697
+ if (!total || !free) return null;
54698
+ const totalKb = Number(total[1]);
54699
+ const freeKb = Number(free[1]);
54700
+ if (!Number.isFinite(totalKb) || !Number.isFinite(freeKb)) return null;
54701
+ const usedKb = Math.max(0, totalKb - freeKb);
54702
+ return { swap_used_mb: Math.round(usedKb / 1024), swap_total_mb: Math.round(totalKb / 1024) };
54703
+ }
54704
+ function parseDarwinSwapusage(output) {
54705
+ const total = /total\s*=\s*([\d.]+)\s*([KMGT])/i.exec(output);
54706
+ const used = /used\s*=\s*([\d.]+)\s*([KMGT])/i.exec(output);
54707
+ if (!total || !used) return null;
54708
+ const toMb = (value, unit) => {
54709
+ const n = Number(value);
54710
+ const u = unit.toUpperCase();
54711
+ const mult = u === "G" ? 1024 : u === "T" ? 1024 * 1024 : u === "K" ? 1 / 1024 : 1;
54712
+ return n * mult;
54713
+ };
54714
+ const usedValue = used[1];
54715
+ const usedUnit = used[2];
54716
+ const totalValue = total[1];
54717
+ const totalUnit = total[2];
54718
+ if (usedValue === void 0 || usedUnit === void 0 || totalValue === void 0 || totalUnit === void 0) return null;
54719
+ const usedMb = toMb(usedValue, usedUnit);
54720
+ const totalMb = toMb(totalValue, totalUnit);
54721
+ if (!Number.isFinite(usedMb) || !Number.isFinite(totalMb)) return null;
54722
+ return { swap_used_mb: Math.round(usedMb), swap_total_mb: Math.round(totalMb) };
54723
+ }
54724
+ var defaultDeps = {
54725
+ platform: () => osPlatform(),
54726
+ loadAvg: () => loadavg(),
54727
+ freeMemBytes: () => freemem(),
54728
+ readLinuxMeminfo: () => readFileSync4("/proc/meminfo", "utf8"),
54729
+ readDarwinSwapusage: () => execFileSync("sysctl", ["-n", "vm.swapusage"], { encoding: "utf8", timeout: 2e3 })
54730
+ };
54731
+ function detectHostResource(deps = defaultDeps) {
54732
+ let load_avg_1m = null;
54733
+ try {
54734
+ const l = deps.loadAvg();
54735
+ const first = Array.isArray(l) ? l[0] : void 0;
54736
+ load_avg_1m = typeof first === "number" && Number.isFinite(first) ? first : null;
54737
+ } catch {
54738
+ load_avg_1m = null;
54739
+ }
54740
+ let memory_available_mb = null;
54741
+ try {
54742
+ const bytes = deps.freeMemBytes();
54743
+ memory_available_mb = Number.isFinite(bytes) && bytes >= 0 ? Math.round(bytes / MB) : null;
54744
+ } catch {
54745
+ memory_available_mb = null;
54746
+ }
54747
+ let swap = null;
54748
+ try {
54749
+ const p = deps.platform();
54750
+ if (p === "linux") swap = parseLinuxMeminfoSwap(deps.readLinuxMeminfo());
54751
+ else if (p === "darwin") swap = parseDarwinSwapusage(deps.readDarwinSwapusage());
54752
+ } catch {
54753
+ swap = null;
54754
+ }
54755
+ return {
54756
+ load_avg_1m,
54757
+ memory_available_mb,
54758
+ swap_used_mb: swap?.swap_used_mb ?? null,
54759
+ swap_total_mb: swap?.swap_total_mb ?? null
54760
+ };
54761
+ }
54762
+
54602
54763
  // src/runner-serve.ts
54603
54764
  var execFile5 = promisify5(execFileCallback5);
54604
54765
  var RUNNER_WORK_ORDER_TOOLS = [
@@ -54784,6 +54945,7 @@ function capabilitiesForAnalytics(capabilities) {
54784
54945
  }
54785
54946
  function detectTelemetry(capabilities, env, activeSessions, cliVersion) {
54786
54947
  const usageState = env.RUNNER_MODEL_ACCOUNT_STATE ?? env.ROST_RUNNER_MODEL_ACCOUNT_STATE ?? "unknown";
54948
+ const host = detectHostResource();
54787
54949
  return {
54788
54950
  os: platform(),
54789
54951
  cpu_count: cpus().length,
@@ -54797,7 +54959,11 @@ function detectTelemetry(capabilities, env, activeSessions, cliVersion) {
54797
54959
  usage_limit_observation: {
54798
54960
  state: usageState,
54799
54961
  source: "runner_env_or_unknown"
54800
- }
54962
+ },
54963
+ load_avg_1m: host.load_avg_1m,
54964
+ memory_available_mb: host.memory_available_mb,
54965
+ swap_used_mb: host.swap_used_mb,
54966
+ swap_total_mb: host.swap_total_mb
54801
54967
  };
54802
54968
  }
54803
54969
  function parseServeArgs(args, appUrl2, env, homeDir) {