@optimuslabs/runtime 0.3.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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +198 -0
  3. package/dist/capture-prompt.d.ts +14 -0
  4. package/dist/capture-prompt.d.ts.map +1 -0
  5. package/dist/capture-prompt.js +173 -0
  6. package/dist/capture-prompt.js.map +1 -0
  7. package/dist/index.d.ts +9 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +203 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/client-event.d.ts +12 -0
  12. package/dist/lib/client-event.d.ts.map +1 -0
  13. package/dist/lib/client-event.js +140 -0
  14. package/dist/lib/client-event.js.map +1 -0
  15. package/dist/lib/endpoint-config.d.ts +2 -0
  16. package/dist/lib/endpoint-config.d.ts.map +1 -0
  17. package/dist/lib/endpoint-config.js +2 -0
  18. package/dist/lib/endpoint-config.js.map +1 -0
  19. package/dist/lib/hardware-uuid.d.ts +7 -0
  20. package/dist/lib/hardware-uuid.d.ts.map +1 -0
  21. package/dist/lib/hardware-uuid.js +52 -0
  22. package/dist/lib/hardware-uuid.js.map +1 -0
  23. package/dist/lib/machine-auth.d.ts +11 -0
  24. package/dist/lib/machine-auth.d.ts.map +1 -0
  25. package/dist/lib/machine-auth.js +46 -0
  26. package/dist/lib/machine-auth.js.map +1 -0
  27. package/dist/lib/pending-events.d.ts +49 -0
  28. package/dist/lib/pending-events.d.ts.map +1 -0
  29. package/dist/lib/pending-events.js +135 -0
  30. package/dist/lib/pending-events.js.map +1 -0
  31. package/dist/lib/startup-sync.d.ts +13 -0
  32. package/dist/lib/startup-sync.d.ts.map +1 -0
  33. package/dist/lib/startup-sync.js +164 -0
  34. package/dist/lib/startup-sync.js.map +1 -0
  35. package/dist/lib/streaming.d.ts +35 -0
  36. package/dist/lib/streaming.d.ts.map +1 -0
  37. package/dist/lib/streaming.js +326 -0
  38. package/dist/lib/streaming.js.map +1 -0
  39. package/dist/lib/telemetry/build-event.d.ts +10 -0
  40. package/dist/lib/telemetry/build-event.d.ts.map +1 -0
  41. package/dist/lib/telemetry/build-event.js +34 -0
  42. package/dist/lib/telemetry/build-event.js.map +1 -0
  43. package/dist/lib/telemetry/canonical.d.ts +26 -0
  44. package/dist/lib/telemetry/canonical.d.ts.map +1 -0
  45. package/dist/lib/telemetry/canonical.js +153 -0
  46. package/dist/lib/telemetry/canonical.js.map +1 -0
  47. package/dist/lib/telemetry/index.d.ts +9 -0
  48. package/dist/lib/telemetry/index.d.ts.map +1 -0
  49. package/dist/lib/telemetry/index.js +9 -0
  50. package/dist/lib/telemetry/index.js.map +1 -0
  51. package/dist/lib/telemetry/serialize.d.ts +3 -0
  52. package/dist/lib/telemetry/serialize.d.ts.map +1 -0
  53. package/dist/lib/telemetry/serialize.js +15 -0
  54. package/dist/lib/telemetry/serialize.js.map +1 -0
  55. package/dist/lib/telemetry/types.d.ts +35 -0
  56. package/dist/lib/telemetry/types.d.ts.map +1 -0
  57. package/dist/lib/telemetry/types.js +14 -0
  58. package/dist/lib/telemetry/types.js.map +1 -0
  59. package/dist/lib/telemetry/wire-metadata.d.ts +10 -0
  60. package/dist/lib/telemetry/wire-metadata.d.ts.map +1 -0
  61. package/dist/lib/telemetry/wire-metadata.js +28 -0
  62. package/dist/lib/telemetry/wire-metadata.js.map +1 -0
  63. package/dist/lib/telemetry.d.ts +2 -0
  64. package/dist/lib/telemetry.d.ts.map +1 -0
  65. package/dist/lib/telemetry.js +2 -0
  66. package/dist/lib/telemetry.js.map +1 -0
  67. package/dist/lib/tofu.d.ts +16 -0
  68. package/dist/lib/tofu.d.ts.map +1 -0
  69. package/dist/lib/tofu.js +44 -0
  70. package/dist/lib/tofu.js.map +1 -0
  71. package/dist/lib/user-profile.d.ts +17 -0
  72. package/dist/lib/user-profile.d.ts.map +1 -0
  73. package/dist/lib/user-profile.js +187 -0
  74. package/dist/lib/user-profile.js.map +1 -0
  75. package/dist/test/canonical.test.d.ts +2 -0
  76. package/dist/test/canonical.test.d.ts.map +1 -0
  77. package/dist/test/canonical.test.js +138 -0
  78. package/dist/test/canonical.test.js.map +1 -0
  79. package/dist/test/endpoint-config.test.d.ts +2 -0
  80. package/dist/test/endpoint-config.test.d.ts.map +1 -0
  81. package/dist/test/endpoint-config.test.js +73 -0
  82. package/dist/test/endpoint-config.test.js.map +1 -0
  83. package/dist/test/index.test.d.ts +2 -0
  84. package/dist/test/index.test.d.ts.map +1 -0
  85. package/dist/test/index.test.js +376 -0
  86. package/dist/test/index.test.js.map +1 -0
  87. package/dist/test/integration-canonical.test.d.ts +2 -0
  88. package/dist/test/integration-canonical.test.d.ts.map +1 -0
  89. package/dist/test/integration-canonical.test.js +176 -0
  90. package/dist/test/integration-canonical.test.js.map +1 -0
  91. package/dist/test/pending-events.test.d.ts +13 -0
  92. package/dist/test/pending-events.test.d.ts.map +1 -0
  93. package/dist/test/pending-events.test.js +265 -0
  94. package/dist/test/pending-events.test.js.map +1 -0
  95. package/dist/test/startup-sync.test.d.ts +2 -0
  96. package/dist/test/startup-sync.test.d.ts.map +1 -0
  97. package/dist/test/startup-sync.test.js +57 -0
  98. package/dist/test/startup-sync.test.js.map +1 -0
  99. package/dist/test/streaming-http.test.d.ts +11 -0
  100. package/dist/test/streaming-http.test.d.ts.map +1 -0
  101. package/dist/test/streaming-http.test.js +181 -0
  102. package/dist/test/streaming-http.test.js.map +1 -0
  103. package/dist/test/streaming.test.d.ts +2 -0
  104. package/dist/test/streaming.test.d.ts.map +1 -0
  105. package/dist/test/streaming.test.js +223 -0
  106. package/dist/test/streaming.test.js.map +1 -0
  107. package/dist/test/telemetry.test.d.ts +2 -0
  108. package/dist/test/telemetry.test.d.ts.map +1 -0
  109. package/dist/test/telemetry.test.js +201 -0
  110. package/dist/test/telemetry.test.js.map +1 -0
  111. package/package.json +54 -0
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Tool-call client-event reporter → POST /endpoint_security/api/client-event/.
3
+ *
4
+ * Emits a FunctionalRun(unit=tool_call) as a substep of the tool-call HookRun. story_id and
5
+ * story_id: env, else ~/.optimuslabs/management/telemetry/current_story.id (written by start-every-prompt).
6
+ * hook_run_id: env, else deterministic `${story_id}::tool_call`.
7
+ * Best-effort, short timeout, never throws — the tool-call hook must never block on telemetry.
8
+ */
9
+ import os from "os";
10
+ import path from "path";
11
+ import fs from "fs";
12
+ import { fileURLToPath } from "url";
13
+ import { loadEndpointBase, createSignature, readStoredAuthKey } from "./tofu.js";
14
+ import { resolveHardwareUuid } from "./hardware-uuid.js";
15
+ import { OPTIMUS_AUTH_KEY_RELATIVE_PATH } from "./machine-auth.js";
16
+ const SEND_TIMEOUT_MS = 4000;
17
+ /** This package's name + version as "<name>: <version>", read from its own package.json. */
18
+ function readPackageVersion() {
19
+ try {
20
+ const pkgPath = fileURLToPath(new URL("../../package.json", import.meta.url));
21
+ const parsed = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
22
+ const name = typeof parsed?.name === "string" ? parsed.name : "";
23
+ const version = typeof parsed?.version === "string" ? parsed.version : "";
24
+ if (name && version)
25
+ return `${name}: ${version}`;
26
+ return version || name || "unknown";
27
+ }
28
+ catch {
29
+ return "unknown";
30
+ }
31
+ }
32
+ const STORY_FILE_MAX_AGE_MS = 180000;
33
+ function resolveStoryId() {
34
+ const fromEnv = (process.env.OPTIMUS_STORY_ID || "").trim();
35
+ if (fromEnv)
36
+ return fromEnv;
37
+ const home = process.env.HOME || process.env.USERPROFILE;
38
+ if (home) {
39
+ try {
40
+ const p = path.join(home, ".optimuslabs", "management", "telemetry", "current_story.id");
41
+ const st = fs.statSync(p);
42
+ if (Date.now() - st.mtimeMs <= STORY_FILE_MAX_AGE_MS) {
43
+ const fromFile = fs.readFileSync(p, "utf8").trim();
44
+ if (fromFile)
45
+ return fromFile;
46
+ }
47
+ }
48
+ catch {
49
+ // missing/unreadable/stale — mint
50
+ }
51
+ }
52
+ return `toolcall-${Date.now()}-${process.pid}`;
53
+ }
54
+ const KNOWN_AGENTS = new Set(["cursor", "claude", "copilot", "opencode", "codex"]);
55
+ /** Shell env (hook wrapper) wins; payload detection when env is missing (Unknown fix). */
56
+ function resolveReportingAgent(detected) {
57
+ const fromEnv = (process.env.OPTIMUS_HOOK_TYPE || process.env.OPTIMUS_AGENT || "").trim().toLowerCase();
58
+ if (KNOWN_AGENTS.has(fromEnv))
59
+ return fromEnv;
60
+ const fromDetected = (detected || "").trim().toLowerCase();
61
+ if (KNOWN_AGENTS.has(fromDetected))
62
+ return fromDetected;
63
+ return null;
64
+ }
65
+ function metadata(agent) {
66
+ const out = {
67
+ host: os.hostname(),
68
+ platform: `${process.platform}/${process.arch}`,
69
+ node: process.version,
70
+ pid: String(process.pid),
71
+ reporter_version: readPackageVersion(),
72
+ source: "tool_call",
73
+ };
74
+ if (process.env.OPTIMUS_HOOK_SCRIPT_VERSION)
75
+ out.hook_script_version = process.env.OPTIMUS_HOOK_SCRIPT_VERSION;
76
+ if (agent)
77
+ out.hook_type = agent;
78
+ if (process.env.OPTIMUS_ENDPOINT)
79
+ out.endpoint = process.env.OPTIMUS_ENDPOINT;
80
+ return out;
81
+ }
82
+ function resolveHookRunId(storyId) {
83
+ const fromEnv = (process.env.OPTIMUS_HOOK_RUN_ID || "").trim();
84
+ if (fromEnv)
85
+ return fromEnv;
86
+ return `${storyId}::tool_call`;
87
+ }
88
+ export async function reportToolCallRun(fields) {
89
+ try {
90
+ const hardwareUuid = resolveHardwareUuid();
91
+ const storyId = resolveStoryId();
92
+ const agent = resolveReportingAgent(fields.agent);
93
+ const events = [
94
+ {
95
+ kind: "functional_run",
96
+ unit: "tool_call",
97
+ command: fields.command ?? "optimus-tool-call",
98
+ hook_name: "tool_call",
99
+ story_id: storyId,
100
+ hook_run_id: resolveHookRunId(storyId),
101
+ outcome: fields.outcome,
102
+ exit_code: fields.exit_code ?? null,
103
+ message: fields.message ?? "",
104
+ detail: fields.detail ?? "",
105
+ ...(agent ? { agent } : {}),
106
+ metadata: metadata(agent),
107
+ },
108
+ ];
109
+ const signingPayload = { hardware_uuid: hardwareUuid, events };
110
+ let signature = "";
111
+ try {
112
+ const authKey = readStoredAuthKey({ authRelativePath: OPTIMUS_AUTH_KEY_RELATIVE_PATH });
113
+ if (authKey?.key)
114
+ signature = createSignature(signingPayload, authKey.key);
115
+ }
116
+ catch {
117
+ // unsigned is accepted by the backend (signature_valid=false)
118
+ }
119
+ const endpoint = `${loadEndpointBase().replace(/\/+$/, "")}/endpoint_security/api/client-event/`;
120
+ if (typeof fetch === "undefined")
121
+ return;
122
+ const controller = new AbortController();
123
+ const timer = setTimeout(() => controller.abort(), SEND_TIMEOUT_MS);
124
+ try {
125
+ await fetch(endpoint, {
126
+ method: "POST",
127
+ headers: { "Content-Type": "application/json" },
128
+ body: JSON.stringify({ ...signingPayload, signature }),
129
+ signal: controller.signal,
130
+ });
131
+ }
132
+ finally {
133
+ clearTimeout(timer);
134
+ }
135
+ }
136
+ catch {
137
+ // never throw — telemetry must not break the tool-call hook
138
+ }
139
+ }
140
+ //# sourceMappingURL=client-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-event.js","sourceRoot":"","sources":["../../src/lib/client-event.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { loadEndpointBase } from "./tofu.js";
2
+ //# sourceMappingURL=endpoint-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint-config.d.ts","sourceRoot":"","sources":["../../src/lib/endpoint-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { loadEndpointBase } from "./tofu.js";
2
+ //# sourceMappingURL=endpoint-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint-config.js","sourceRoot":"","sources":["../../src/lib/endpoint-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,7 @@
1
+ /** Run a static shell command and return trimmed stdout (same pattern as log-llm-config). */
2
+ export declare function readCommandOutput(command: string): string;
3
+ /** Resolve hardware UUID from environment or macOS system commands (same strategy as log-llm-config). */
4
+ declare function resolveHardwareUuid(): string;
5
+ export declare function tryResolveHardwareUuid(): string | null;
6
+ export { resolveHardwareUuid };
7
+ //# sourceMappingURL=hardware-uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hardware-uuid.d.ts","sourceRoot":"","sources":["../../src/lib/hardware-uuid.ts"],"names":[],"mappings":"AAEA,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASzD;AAED,yGAAyG;AACzG,iBAAS,mBAAmB,IAAI,MAAM,CAyBrC;AAED,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,IAAI,CAMtD;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { execSync } from "node:child_process";
2
+ /** Run a static shell command and return trimmed stdout (same pattern as log-llm-config). */
3
+ export function readCommandOutput(command) {
4
+ try {
5
+ return execSync(command, {
6
+ encoding: "utf8",
7
+ stdio: ["ignore", "pipe", "ignore"],
8
+ }).trim();
9
+ }
10
+ catch {
11
+ return "";
12
+ }
13
+ }
14
+ /** Resolve hardware UUID from environment or macOS system commands (same strategy as log-llm-config). */
15
+ function resolveHardwareUuid() {
16
+ const envUuid = process.env.OPTIMUS_HARDWARE_UUID?.trim();
17
+ if (envUuid)
18
+ return envUuid;
19
+ try {
20
+ const ioregOutput = execSync("ioreg -rd1 -c IOPlatformExpertDevice", {
21
+ encoding: "utf8",
22
+ }).trim();
23
+ const ioregMatch = ioregOutput.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/i);
24
+ if (ioregMatch?.[1])
25
+ return ioregMatch[1];
26
+ }
27
+ catch {
28
+ // try next method
29
+ }
30
+ try {
31
+ const profilerOutput = execSync("system_profiler SPHardwareDataType", {
32
+ encoding: "utf8",
33
+ }).trim();
34
+ const profilerMatch = profilerOutput.match(/Hardware UUID:\s*([A-F0-9-]+)/i);
35
+ if (profilerMatch?.[1])
36
+ return profilerMatch[1];
37
+ }
38
+ catch {
39
+ // both methods failed
40
+ }
41
+ throw new Error("Unable to determine hardware UUID via ioreg or system_profiler.");
42
+ }
43
+ export function tryResolveHardwareUuid() {
44
+ try {
45
+ return resolveHardwareUuid();
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ }
51
+ export { resolveHardwareUuid };
52
+ //# sourceMappingURL=hardware-uuid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hardware-uuid.js","sourceRoot":"","sources":["../../src/lib/hardware-uuid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,6FAA6F;AAC7F,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,EAAE;YACvB,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,yGAAyG;AACzG,SAAS,mBAAmB;IAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE,CAAC;IAC1D,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,QAAQ,CAAC,sCAAsC,EAAE;YACnE,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAC1E,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,QAAQ,CAAC,oCAAoC,EAAE;YACpE,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,aAAa,GAAG,cAAc,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAC7E,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC;QACH,OAAO,mBAAmB,EAAE,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type StoredAuthKey } from "./tofu.js";
2
+ /** Same path as log-llm-config: `~/.optimuslabs/management/auth/auth_key.txt` under `$HOME`. */
3
+ export declare const OPTIMUS_AUTH_KEY_RELATIVE_PATH: string;
4
+ /**
5
+ * Same TOFU + machine key flow as log-llm-config: verify stored key against
6
+ * `/endpoint_security/auth/` or request a new key and persist under HOME.
7
+ */
8
+ export declare function ensureToolCallAuth(hardwareUuid: string): Promise<StoredAuthKey>;
9
+ /** For tests: clear cached auth so HOME / env changes take effect. */
10
+ export declare function resetToolCallAuthCache(): void;
11
+ //# sourceMappingURL=machine-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-auth.d.ts","sourceRoot":"","sources":["../../src/lib/machine-auth.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAEnB,gGAAgG;AAChG,eAAO,MAAM,8BAA8B,QAK1C,CAAC;AAuBF;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,CAgBxB;AAED,sEAAsE;AACtE,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -0,0 +1,46 @@
1
+ import path from "node:path";
2
+ import { ensureAuthentication, loadEndpointBase, readStoredAuthKey, } from "./tofu.js";
3
+ /** Same path as log-llm-config: `~/.optimuslabs/management/auth/auth_key.txt` under `$HOME`. */
4
+ export const OPTIMUS_AUTH_KEY_RELATIVE_PATH = path.join(".optimuslabs", "management", "auth", "auth_key.txt");
5
+ let cached = null;
6
+ async function postJsonForAuth(endpointUrl, body) {
7
+ const res = await fetch(endpointUrl, {
8
+ method: "POST",
9
+ headers: { "Content-Type": "application/json" },
10
+ body: JSON.stringify(body),
11
+ });
12
+ const text = await res.text();
13
+ if (!res.ok) {
14
+ throw new Error(`HTTP ${res.status}: ${text ? text.slice(0, 200) : res.statusText}`);
15
+ }
16
+ if (!text)
17
+ return { status: "error", error: "empty_response" };
18
+ return JSON.parse(text);
19
+ }
20
+ /**
21
+ * Same TOFU + machine key flow as log-llm-config: verify stored key against
22
+ * `/endpoint_security/auth/` or request a new key and persist under HOME.
23
+ */
24
+ export async function ensureToolCallAuth(hardwareUuid) {
25
+ const fromDisk = readStoredAuthKey({
26
+ authRelativePath: OPTIMUS_AUTH_KEY_RELATIVE_PATH,
27
+ });
28
+ if (!fromDisk?.key && cached?.hardwareUuid === hardwareUuid) {
29
+ cached = null;
30
+ }
31
+ if (cached?.hardwareUuid === hardwareUuid)
32
+ return cached.key;
33
+ const key = await ensureAuthentication({
34
+ hardwareUuid,
35
+ endpointBase: loadEndpointBase(),
36
+ authRelativePath: OPTIMUS_AUTH_KEY_RELATIVE_PATH,
37
+ postJson: postJsonForAuth,
38
+ });
39
+ cached = { hardwareUuid, key };
40
+ return key;
41
+ }
42
+ /** For tests: clear cached auth so HOME / env changes take effect. */
43
+ export function resetToolCallAuthCache() {
44
+ cached = null;
45
+ }
46
+ //# sourceMappingURL=machine-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-auth.js","sourceRoot":"","sources":["../../src/lib/machine-auth.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,GAGlB,MAAM,WAAW,CAAC;AAEnB,gGAAgG;AAChG,MAAM,CAAC,MAAM,8BAA8B,GAAG,IAAI,CAAC,IAAI,CACrD,cAAc,EACd,YAAY,EACZ,MAAM,EACN,cAAc,CACf,CAAC;AAEF,IAAI,MAAM,GAAwD,IAAI,CAAC;AAEvE,KAAK,UAAU,eAAe,CAC5B,WAAmB,EACnB,IAA6B;IAE7B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,WAAW,EAAE;QACnC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,QAAQ,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,CACpE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC/D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAqB,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,YAAoB;IAEpB,MAAM,QAAQ,GAAG,iBAAiB,CAAC;QACjC,gBAAgB,EAAE,8BAA8B;KACjD,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,MAAM,EAAE,YAAY,KAAK,YAAY,EAAE,CAAC;QAC5D,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,MAAM,EAAE,YAAY,KAAK,YAAY;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC;IAC7D,MAAM,GAAG,GAAG,MAAM,oBAAoB,CAAC;QACrC,YAAY;QACZ,YAAY,EAAE,gBAAgB,EAAE;QAChC,gBAAgB,EAAE,8BAA8B;QAChD,QAAQ,EAAE,eAAe;KAC1B,CAAC,CAAC;IACH,MAAM,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;IAC/B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,sBAAsB;IACpC,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Durable pending-event buffer for telemetry that failed to send.
3
+ *
4
+ * Note on scope: this buffer handles Optimus backend unavailability, not
5
+ * general internet connectivity loss. If the developer is fully offline,
6
+ * the AI agent itself cannot reach its API, so no tool calls are generated
7
+ * and hooks never fire — there is nothing to buffer. The realistic failure
8
+ * modes this covers are: Optimus backend deploying or restarting mid-session,
9
+ * transient 5xx errors, and network path issues specific to app.optimuslabs.io
10
+ * while the AI API endpoint remains reachable.
11
+ *
12
+ * On network failure or 5xx, events are appended as JSONL to
13
+ * ~/.optimuslabs/management/telemetry/pending_events.jsonl.
14
+ * On the next hook invocation, drainPendingEvents() atomically claims that
15
+ * file (via rename) so a concurrent hook process won't double-send the same
16
+ * batch.
17
+ */
18
+ import type { TelemetryEvent } from "./telemetry.js";
19
+ /**
20
+ * Resolve the telemetry directory at call time so that tests can override it
21
+ * by setting OPTIMUS_TELEMETRY_DIR before calling any function.
22
+ */
23
+ export declare function getPendingDir(): string;
24
+ export declare function getPendingFile(): string;
25
+ export declare function getClientErrorsFile(): string;
26
+ /**
27
+ * Append events to the pending file for retry on the next hook invocation.
28
+ * Used for network failures and transient server errors (5xx).
29
+ */
30
+ export declare function appendPendingEvents(events: TelemetryEvent[]): void;
31
+ /**
32
+ * Log events that failed with a 4xx HTTP error.
33
+ * These are not retried — the request was malformed or rejected by the server.
34
+ * Each line is a JSON object with the HTTP status, timestamp, and original event.
35
+ */
36
+ export declare function appendClientErrors(events: TelemetryEvent[], httpStatus: number): void;
37
+ /**
38
+ * Atomically claim and parse the pending file.
39
+ * Uses rename so two concurrent hook processes never read the same batch.
40
+ * Returns [] if the file does not exist or cannot be read.
41
+ *
42
+ * Crash safety: if `pending_events.jsonl` is missing but `pending_events.jsonl.draining`
43
+ * exists (process died after rename, before successful read), the draining file is moved
44
+ * back to the pending path and processed normally. If read/unlink fails after claim, the
45
+ * batch is renamed back to `pending_events.jsonl` so it can be retried instead of being
46
+ * stranded under `.draining`.
47
+ */
48
+ export declare function drainPendingEvents(): TelemetryEvent[];
49
+ //# sourceMappingURL=pending-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-events.d.ts","sourceRoot":"","sources":["../../src/lib/pending-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAOD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAWlE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAgBrF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,IAAI,cAAc,EAAE,CAoDrD"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Durable pending-event buffer for telemetry that failed to send.
3
+ *
4
+ * Note on scope: this buffer handles Optimus backend unavailability, not
5
+ * general internet connectivity loss. If the developer is fully offline,
6
+ * the AI agent itself cannot reach its API, so no tool calls are generated
7
+ * and hooks never fire — there is nothing to buffer. The realistic failure
8
+ * modes this covers are: Optimus backend deploying or restarting mid-session,
9
+ * transient 5xx errors, and network path issues specific to app.optimuslabs.io
10
+ * while the AI API endpoint remains reachable.
11
+ *
12
+ * On network failure or 5xx, events are appended as JSONL to
13
+ * ~/.optimuslabs/management/telemetry/pending_events.jsonl.
14
+ * On the next hook invocation, drainPendingEvents() atomically claims that
15
+ * file (via rename) so a concurrent hook process won't double-send the same
16
+ * batch.
17
+ */
18
+ import { homedir } from "os";
19
+ import path from "path";
20
+ import fs from "fs";
21
+ /**
22
+ * Resolve the telemetry directory at call time so that tests can override it
23
+ * by setting OPTIMUS_TELEMETRY_DIR before calling any function.
24
+ */
25
+ export function getPendingDir() {
26
+ return process.env.OPTIMUS_TELEMETRY_DIR
27
+ ? path.resolve(process.env.OPTIMUS_TELEMETRY_DIR)
28
+ : path.join(homedir(), ".optimuslabs", "management", "telemetry");
29
+ }
30
+ export function getPendingFile() {
31
+ return path.join(getPendingDir(), "pending_events.jsonl");
32
+ }
33
+ export function getClientErrorsFile() {
34
+ return path.join(getPendingDir(), "client_errors.jsonl");
35
+ }
36
+ function writeLines(dir, file, lines) {
37
+ fs.mkdirSync(dir, { recursive: true });
38
+ fs.appendFileSync(file, lines.join("\n") + "\n", "utf8");
39
+ }
40
+ /**
41
+ * Append events to the pending file for retry on the next hook invocation.
42
+ * Used for network failures and transient server errors (5xx).
43
+ */
44
+ export function appendPendingEvents(events) {
45
+ if (events.length === 0)
46
+ return;
47
+ const dir = getPendingDir();
48
+ try {
49
+ writeLines(dir, getPendingFile(), events.map((e) => JSON.stringify(e)));
50
+ }
51
+ catch (err) {
52
+ console.error("[optimus-tool-call] Failed to write pending events to disk:", err instanceof Error ? err.message : String(err));
53
+ }
54
+ }
55
+ /**
56
+ * Log events that failed with a 4xx HTTP error.
57
+ * These are not retried — the request was malformed or rejected by the server.
58
+ * Each line is a JSON object with the HTTP status, timestamp, and original event.
59
+ */
60
+ export function appendClientErrors(events, httpStatus) {
61
+ if (events.length === 0)
62
+ return;
63
+ const dir = getPendingDir();
64
+ const failedAt = new Date().toISOString();
65
+ try {
66
+ writeLines(dir, getClientErrorsFile(), events.map((e) => JSON.stringify({ http_status: httpStatus, failed_at: failedAt, event: e })));
67
+ }
68
+ catch (err) {
69
+ console.error("[optimus-tool-call] Failed to log client errors to disk:", err instanceof Error ? err.message : String(err));
70
+ }
71
+ }
72
+ /**
73
+ * Atomically claim and parse the pending file.
74
+ * Uses rename so two concurrent hook processes never read the same batch.
75
+ * Returns [] if the file does not exist or cannot be read.
76
+ *
77
+ * Crash safety: if `pending_events.jsonl` is missing but `pending_events.jsonl.draining`
78
+ * exists (process died after rename, before successful read), the draining file is moved
79
+ * back to the pending path and processed normally. If read/unlink fails after claim, the
80
+ * batch is renamed back to `pending_events.jsonl` so it can be retried instead of being
81
+ * stranded under `.draining`.
82
+ */
83
+ export function drainPendingEvents() {
84
+ const pendingFile = getPendingFile();
85
+ const tmpFile = pendingFile + ".draining";
86
+ // Recover a leftover claim file from a crash between rename and successful read/unlink.
87
+ if (!fs.existsSync(pendingFile) && fs.existsSync(tmpFile)) {
88
+ try {
89
+ fs.renameSync(tmpFile, pendingFile);
90
+ }
91
+ catch {
92
+ return [];
93
+ }
94
+ }
95
+ try {
96
+ fs.renameSync(pendingFile, tmpFile);
97
+ }
98
+ catch {
99
+ return [];
100
+ }
101
+ try {
102
+ const content = fs.readFileSync(tmpFile, "utf8");
103
+ const events = [];
104
+ for (const line of content.split("\n")) {
105
+ const trimmed = line.trim();
106
+ if (!trimmed)
107
+ continue;
108
+ try {
109
+ events.push(JSON.parse(trimmed));
110
+ }
111
+ catch {
112
+ // skip malformed lines
113
+ }
114
+ }
115
+ try {
116
+ fs.unlinkSync(tmpFile);
117
+ }
118
+ catch {
119
+ // best-effort cleanup; events are still returned
120
+ }
121
+ return events;
122
+ }
123
+ catch (err) {
124
+ try {
125
+ if (fs.existsSync(tmpFile)) {
126
+ fs.renameSync(tmpFile, pendingFile);
127
+ }
128
+ }
129
+ catch (restoreErr) {
130
+ console.error("[optimus-tool-call] Failed to restore pending_events after drain error:", restoreErr instanceof Error ? restoreErr.message : String(restoreErr), "| original:", err instanceof Error ? err.message : String(err));
131
+ }
132
+ return [];
133
+ }
134
+ }
135
+ //# sourceMappingURL=pending-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-events.js","sourceRoot":"","sources":["../../src/lib/pending-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * POST `/endpoint_security/startup/` with `metadata.user_profile` so `EndpointMachine.user_profile`
3
+ * stays fresh even when `log_uuid` is throttled (e.g. customer hooks with existing auth_key.txt).
4
+ * Signs `payload` with the stored machine key when present (same as `log-llm-config` startup_sender)
5
+ * so the backend does not revoke keys on every unsigned sync.
6
+ *
7
+ * Throttled (default 30 min) on success to avoid an extra HTTP round-trip on every tool call.
8
+ * After failures (network, non-2xx, etc.), exponential backoff caps repeated work so hooks are
9
+ * not blocked on every batch. Override interval with `OPTIMUS_STARTUP_SYNC_INTERVAL_MS` (set to
10
+ * `0` to sync on every batch when healthy). Skip entirely with `OPTIMUS_SKIP_STARTUP_SYNC=1`.
11
+ */
12
+ export declare function ensureStartupMetadataSynced(hardwareUuid: string): Promise<void>;
13
+ //# sourceMappingURL=startup-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup-sync.d.ts","sourceRoot":"","sources":["../../src/lib/startup-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAsEH,wBAAsB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6GrF"}