@addai/node 0.30.13 → 0.30.15

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 (143) hide show
  1. package/dist/auto-update.d.ts +3 -0
  2. package/dist/auto-update.js +15 -0
  3. package/dist/capabilities.d.ts +17 -3
  4. package/dist/capabilities.js +18 -8
  5. package/dist/claude-models.d.ts +4 -12
  6. package/dist/claude-models.js +12 -88
  7. package/dist/claude-print.d.ts +15 -0
  8. package/dist/claude-print.js +16 -0
  9. package/dist/codex-models.d.ts +81 -0
  10. package/dist/codex-models.js +385 -0
  11. package/dist/codex-spawn.d.ts +19 -8
  12. package/dist/codex-spawn.js +68 -16
  13. package/dist/command-runner.js +31 -9
  14. package/dist/desktop/docker.js +2 -0
  15. package/dist/desktop/manager.d.ts +2 -1
  16. package/dist/desktop/manager.js +51 -1
  17. package/dist/desktop/provider.d.ts +1 -1
  18. package/dist/desktop/provider.js +2 -0
  19. package/dist/desktop/relay-client.js +7 -0
  20. package/dist/desktop/spec.d.ts +2 -0
  21. package/dist/direct/aios-bridge.d.ts +13 -0
  22. package/dist/direct/aios-bridge.js +177 -0
  23. package/dist/direct/aios-mcp.d.ts +2 -0
  24. package/dist/direct/aios-mcp.js +132 -0
  25. package/dist/direct/aios-tools.d.ts +351 -0
  26. package/dist/direct/aios-tools.js +120 -0
  27. package/dist/direct/board-chat-provider.d.ts +64 -0
  28. package/dist/direct/board-chat-provider.js +154 -0
  29. package/dist/direct/board-chat.d.ts +40 -0
  30. package/dist/direct/board-chat.js +414 -0
  31. package/dist/direct/config.d.ts +2 -0
  32. package/dist/direct/config.js +60 -0
  33. package/dist/direct/launch.d.ts +14 -0
  34. package/dist/direct/launch.js +121 -0
  35. package/dist/direct/protocol.d.ts +46 -0
  36. package/dist/direct/protocol.js +84 -0
  37. package/dist/direct/relay-main.d.ts +1 -0
  38. package/dist/direct/relay-main.js +21 -0
  39. package/dist/direct/relay.d.ts +26 -0
  40. package/dist/direct/relay.js +334 -0
  41. package/dist/direct/sessions.d.ts +61 -0
  42. package/dist/direct/sessions.js +368 -0
  43. package/dist/direct/supervisor.d.ts +9 -0
  44. package/dist/direct/supervisor.js +137 -0
  45. package/dist/direct/terminal.d.ts +1 -0
  46. package/dist/direct/terminal.js +106 -0
  47. package/dist/direct/worker.d.ts +1 -0
  48. package/dist/direct/worker.js +278 -0
  49. package/dist/entitybox/container-action.cjs +85 -0
  50. package/dist/entitybox/container-watchdog.cjs +70 -0
  51. package/dist/entitybox/model-entry.d.ts +3 -0
  52. package/dist/entitybox/model-entry.js +233 -0
  53. package/dist/entitybox/model-mcp-proxy.d.ts +3 -0
  54. package/dist/entitybox/model-mcp-proxy.js +85 -0
  55. package/dist/entitybox-application-boundary.d.ts +59 -0
  56. package/dist/entitybox-application-boundary.js +161 -0
  57. package/dist/entitybox-application-guard-core.d.ts +44 -0
  58. package/dist/entitybox-application-guard-core.js +164 -0
  59. package/dist/entitybox-application-guard-process.d.ts +1 -0
  60. package/dist/entitybox-application-guard-process.js +83 -0
  61. package/dist/entitybox-application-guard.d.ts +46 -0
  62. package/dist/entitybox-application-guard.js +239 -0
  63. package/dist/entitybox-capacity-health-host.d.ts +12 -0
  64. package/dist/entitybox-capacity-health-host.js +80 -0
  65. package/dist/entitybox-capacity-health-worker.d.ts +22 -0
  66. package/dist/entitybox-capacity-health-worker.js +168 -0
  67. package/dist/entitybox-capacity-host.d.ts +17 -0
  68. package/dist/entitybox-capacity-host.js +155 -0
  69. package/dist/entitybox-capacity-owner-process.d.ts +1 -0
  70. package/dist/entitybox-capacity-owner-process.js +32 -0
  71. package/dist/entitybox-capacity-owner.d.ts +16 -0
  72. package/dist/entitybox-capacity-owner.js +90 -0
  73. package/dist/entitybox-capacity-programs.d.ts +7 -0
  74. package/dist/entitybox-capacity-programs.js +49 -0
  75. package/dist/entitybox-capacity-provisioner.d.ts +82 -0
  76. package/dist/entitybox-capacity-provisioner.js +404 -0
  77. package/dist/entitybox-capacity-publication.d.ts +29 -0
  78. package/dist/entitybox-capacity-publication.js +199 -0
  79. package/dist/entitybox-capacity-registration.d.ts +36 -0
  80. package/dist/entitybox-capacity-registration.js +75 -0
  81. package/dist/entitybox-capacity-worker.d.ts +29 -0
  82. package/dist/entitybox-capacity-worker.js +113 -0
  83. package/dist/entitybox-computer-task.d.ts +69 -0
  84. package/dist/entitybox-computer-task.js +176 -0
  85. package/dist/entitybox-controller-recovery.d.ts +40 -0
  86. package/dist/entitybox-controller-recovery.js +156 -0
  87. package/dist/entitybox-desktop-action-server.d.ts +34 -0
  88. package/dist/entitybox-desktop-action-server.js +176 -0
  89. package/dist/entitybox-desktop-admission.d.ts +32 -0
  90. package/dist/entitybox-desktop-admission.js +79 -0
  91. package/dist/entitybox-display-binding.d.ts +13 -0
  92. package/dist/entitybox-display-binding.js +31 -0
  93. package/dist/entitybox-execution-container.d.ts +82 -0
  94. package/dist/entitybox-execution-container.js +450 -0
  95. package/dist/entitybox-execution-host.d.ts +40 -0
  96. package/dist/entitybox-execution-host.js +168 -0
  97. package/dist/entitybox-execution-lease.d.ts +81 -0
  98. package/dist/entitybox-execution-lease.js +332 -0
  99. package/dist/entitybox-file-inputs.d.ts +51 -0
  100. package/dist/entitybox-file-inputs.js +182 -0
  101. package/dist/entitybox-file-session.d.ts +38 -0
  102. package/dist/entitybox-file-session.js +82 -0
  103. package/dist/entitybox-host-process.d.ts +12 -0
  104. package/dist/entitybox-host-process.js +120 -0
  105. package/dist/entitybox-install.d.ts +10 -0
  106. package/dist/entitybox-install.js +40 -0
  107. package/dist/entitybox-mcp-broker.d.ts +77 -0
  108. package/dist/entitybox-mcp-broker.js +420 -0
  109. package/dist/entitybox-mcp-contract.d.ts +10 -0
  110. package/dist/entitybox-mcp-contract.js +24 -0
  111. package/dist/entitybox-mcp-guard.d.ts +3 -0
  112. package/dist/entitybox-mcp-guard.js +167 -0
  113. package/dist/entitybox-model-artifact.d.ts +9 -0
  114. package/dist/entitybox-model-artifact.js +83 -0
  115. package/dist/entitybox-native-services.d.ts +33 -0
  116. package/dist/entitybox-native-services.js +172 -0
  117. package/dist/entitybox-operation.d.ts +4 -0
  118. package/dist/entitybox-operation.js +34 -0
  119. package/dist/entitybox-provider-broker.d.ts +41 -0
  120. package/dist/entitybox-provider-broker.js +149 -0
  121. package/dist/entitybox-queue-request.d.ts +32 -0
  122. package/dist/entitybox-queue-request.js +141 -0
  123. package/dist/entitybox-recovery-host.d.ts +12 -0
  124. package/dist/entitybox-recovery-host.js +80 -0
  125. package/dist/entitybox-recovery-store.d.ts +33 -0
  126. package/dist/entitybox-recovery-store.js +150 -0
  127. package/dist/entitybox-recovery-worker.d.ts +30 -0
  128. package/dist/entitybox-recovery-worker.js +134 -0
  129. package/dist/entitybox-vault-provider.d.ts +27 -0
  130. package/dist/entitybox-vault-provider.js +127 -0
  131. package/dist/harness-registry.js +3 -1
  132. package/dist/index.js +72 -38
  133. package/dist/install.d.ts +14 -2
  134. package/dist/install.js +115 -10
  135. package/dist/model-cache.d.ts +38 -0
  136. package/dist/model-cache.js +137 -0
  137. package/dist/request-pump.d.ts +3 -0
  138. package/dist/request-pump.js +21 -7
  139. package/dist/session-runner.d.ts +8 -1
  140. package/dist/session-runner.js +56 -3
  141. package/dist/supabase-client.js +4 -1
  142. package/package.json +5 -1
  143. package/scripts/copy-assets.js +4 -2
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.entityboxCapacityEnvironment = entityboxCapacityEnvironment;
37
+ exports.startEntityboxCapacityHost = startEntityboxCapacityHost;
38
+ const path = __importStar(require("path"));
39
+ const child_process_1 = require("child_process");
40
+ const util_1 = require("util");
41
+ const paths_1 = require("./paths");
42
+ const store_1 = require("./store");
43
+ const supabase_client_1 = require("./supabase-client");
44
+ const docker_1 = require("./desktop/docker");
45
+ const manager_1 = require("./desktop/manager");
46
+ const entitybox_capacity_worker_1 = require("./entitybox-capacity-worker");
47
+ const entitybox_desktop_admission_1 = require("./entitybox-desktop-admission");
48
+ const exec = (0, util_1.promisify)(child_process_1.execFile);
49
+ function entityboxCapacityEnvironment(env = process.env) {
50
+ if (env.AINODE_ENTITYBOX_CAPACITY_ENABLED !== '1')
51
+ return undefined;
52
+ const budget = { cpus: Number(env.AINODE_ENTITYBOX_DESKTOP_CPUS), memoryMb: Number(env.AINODE_ENTITYBOX_DESKTOP_MEMORY_MB), diskGb: Number(env.AINODE_ENTITYBOX_DESKTOP_DISK_GB) };
53
+ const imageId = env.AINODE_ENTITYBOX_CAPACITY_IMAGE ?? '', dockerContext = env.AINODE_ENTITYBOX_DOCKER_CONTEXT ?? '', directory = env.AINODE_ENTITYBOX_CAPACITY_DIRECTORY ?? path.join(paths_1.RUNTIME_HOME, 'entitybox', 'capacities');
54
+ if (env.DOCKER_HOST || !/^sha256:[a-f0-9]{64}$/.test(imageId) || !/^[-a-zA-Z0-9_.]{1,80}$/.test(dockerContext) || !path.isAbsolute(directory) || directory.startsWith('\\\\') || !(0, entitybox_desktop_admission_1.validateEntityboxDesktopBudget)(budget))
55
+ throw new Error('Invalid EntityBox computer setup configuration');
56
+ return { enabled: true, recoverPublication: env.AINODE_ENTITYBOX_CAPACITY_RECOVERY_ENABLED === '1', imageId, dockerContext, directory, budget };
57
+ }
58
+ /** Startup integration only. Default-off; no new native queue or host execution
59
+ * route. Budget numbers are explicit operator reservations for AddAI desktops,
60
+ * not claims about other applications or Docker/OS storage quotas. */
61
+ function startEntityboxCapacityHost(env = process.env) {
62
+ const idle = { stop() { }, async drain(_timeout) { return true; } };
63
+ let configuration;
64
+ try {
65
+ configuration = entityboxCapacityEnvironment(env);
66
+ }
67
+ catch {
68
+ console.warn('[entitybox] Computer setup worker is disabled: invalid host configuration.');
69
+ return idle;
70
+ }
71
+ if (!configuration)
72
+ return idle;
73
+ const config = configuration;
74
+ const pairing = (0, store_1.readPairing)();
75
+ if (!pairing) {
76
+ console.warn('[entitybox] Computer setup worker requires a paired runtime.');
77
+ return idle;
78
+ }
79
+ let stopping = false;
80
+ async function policy(rows, id) {
81
+ const current = (0, store_1.readPairing)();
82
+ if (stopping || !current || current.runtimeId !== pairing.runtimeId || (0, supabase_client_1.rpcShouldSkip)() || !(0, manager_1.entityboxDesktopLimitKnown)())
83
+ throw Error('Unavailable');
84
+ if (!Array.isArray(rows) || !rows.length || rows.length > 1000 || rows.some(r => r.runtime_id !== current.runtimeId))
85
+ throw Error('Unavailable');
86
+ // Ordinary native Docker operations use the active context. Never budget a
87
+ // different engine from the one on which those operations will take place.
88
+ const context = (await exec('docker', ['context', 'show'], { windowsHide: true, timeout: 5000, maxBuffer: 4096 })).stdout.trim();
89
+ if (context !== config.dockerContext)
90
+ throw Error('Unavailable');
91
+ const provider = await (0, docker_1.getProvider)();
92
+ if (!provider || provider.id !== 'docker')
93
+ throw Error('Unavailable');
94
+ const observations = [];
95
+ for (const row of rows) {
96
+ if (row.entitybox_managed) {
97
+ observations.push({ row, exists: row.status !== 'pending', running: row.status !== 'pending' });
98
+ continue;
99
+ }
100
+ const actual = await provider.inspect(row);
101
+ observations.push({ row, exists: !!actual, running: actual?.running ?? false });
102
+ }
103
+ return (0, entitybox_desktop_admission_1.entityboxDesktopBudget)(observations, id, (0, manager_1.maxConcurrentDesktops)(), config.budget);
104
+ }
105
+ const gate = (0, entitybox_desktop_admission_1.installEntityboxDesktopAdmission)(policy);
106
+ const reported = new Map();
107
+ const worker = (0, entitybox_capacity_worker_1.createEntityboxCapacityWorker)({ ...config, runtimeId: pairing.runtimeId }, { rpc: supabase_client_1.rpc, pairing: store_1.readPairing,
108
+ admit: (id, createdAt, action, publicationOnly = false) => (0, entitybox_desktop_admission_1.entityboxWithDesktopStart)(async () => {
109
+ if (stopping || (0, supabase_client_1.rpcShouldSkip)())
110
+ return false;
111
+ const rows = await (0, manager_1.listDesktops)(), row = rows.find(r => r.id === id);
112
+ if (!row?.entitybox_managed)
113
+ return false;
114
+ if (publicationOnly) {
115
+ // Recovery only reads the already-reserved physical receipt and publishes
116
+ // it. It must not deadlock behind an ordinary start waiting for that slot.
117
+ // The worker never routes a provisioner through this branch.
118
+ const current = (0, store_1.readPairing)();
119
+ if (!config.recoverPublication || row.status !== 'creating' || row.runtime_id !== pairing.runtimeId || !current || current.runtimeId !== pairing.runtimeId || stopping)
120
+ return false;
121
+ await action();
122
+ return true;
123
+ }
124
+ // The ordinary reconciler owns older start requests. Pending dedicated
125
+ // rows consume no slot, so yielding cannot deadlock the ordinary queue.
126
+ if (rows.some(r => !r.entitybox_managed && r.status === 'queued' && (!r.queued_at || !Number.isFinite(Date.parse(r.queued_at)) || Date.parse(r.queued_at) <= Date.parse(createdAt))))
127
+ return false;
128
+ const room = await policy(rows, id);
129
+ if (!room.allowed)
130
+ return false;
131
+ if (stopping)
132
+ return false;
133
+ await action();
134
+ return true;
135
+ }),
136
+ report: (state, id) => { const key = id ?? 'worker', last = reported.get(key), at = Date.now(); if (last?.state === state && at - last.at < 60000)
137
+ return; if (reported.size > 1000)
138
+ reported.clear(); reported.set(key, { state, at }); console.log('[entitybox] Computer setup ' + state + (id ? ' (' + id + ')' : '')); }, });
139
+ if (!worker) {
140
+ void gate.close();
141
+ return idle;
142
+ }
143
+ worker.start();
144
+ let closing;
145
+ return { stop() { if (stopping)
146
+ return; stopping = true; worker.stop(); closing = gate.close(); }, async drain(timeout = 15000) {
147
+ let deadline;
148
+ try {
149
+ return await Promise.race([Promise.all([worker.drain(timeout), closing]).then(([complete]) => complete), new Promise(resolve => { deadline = setTimeout(() => resolve(false), Math.max(0, timeout)); })]);
150
+ }
151
+ finally {
152
+ clearTimeout(deadline);
153
+ }
154
+ } };
155
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const entitybox_capacity_provisioner_1 = require("./entitybox-capacity-provisioner");
4
+ /** Fixed hidden helper. No real pairing, provider, environment-file or native
5
+ * request-pump imports. Configuration arrives once over private parent IPC.
6
+ * After setup starts, parent disconnect deliberately does not cancel it. */
7
+ if (require.main === module) {
8
+ let configured = false;
9
+ const deadline = setTimeout(() => process.exit(70), 10000);
10
+ process.once('disconnect', () => { if (!configured)
11
+ process.exit(70); });
12
+ process.once('message', async (raw) => {
13
+ configured = true;
14
+ clearTimeout(deadline);
15
+ try {
16
+ const packet = raw;
17
+ if (!packet || Object.keys(packet).sort().join(',') !== 'config,plan,type' || packet.type !== 'provision' || packet.config?.enabled !== true)
18
+ throw Error();
19
+ const owner = entitybox_capacity_provisioner_1.EntityboxCapacityProvisioner.createReserved(packet.config, packet.plan);
20
+ if (!owner)
21
+ throw Error();
22
+ await owner.provision();
23
+ }
24
+ catch {
25
+ process.exitCode = 70;
26
+ }
27
+ finally {
28
+ if (process.connected)
29
+ process.disconnect();
30
+ }
31
+ });
32
+ }
@@ -0,0 +1,16 @@
1
+ import { type ChildProcess, type SpawnOptions } from 'child_process';
2
+ import { readEntityboxCapacity, type EntityboxCapacityConfiguration, type EntityboxCapacityReceipt } from './entitybox-capacity-provisioner';
3
+ interface OwnerIO {
4
+ /** Trusted fixture seams only. No task/model/renderer configuration. */
5
+ launch?: (file: string, args: string[], options: SpawnOptions) => ChildProcess;
6
+ read?: typeof readEntityboxCapacity;
7
+ }
8
+ /** One physical setup process, independent of the runtime controller. The
9
+ * caller must claim the plan before calling provision(). A parent crash does
10
+ * not terminate this process or transfer its immutable desktop reservation.
11
+ * The helper never publishes SQL; recovery verifies its completed receipt. */
12
+ export declare function createEntityboxCapacityOwner(config: EntityboxCapacityConfiguration, io?: OwnerIO): {
13
+ plan: Readonly<import("./entitybox-capacity-provisioner").EntityboxCapacityPlan>;
14
+ provision(): Promise<Readonly<EntityboxCapacityReceipt>>;
15
+ } | undefined;
16
+ export {};
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createEntityboxCapacityOwner = createEntityboxCapacityOwner;
37
+ const child_process_1 = require("child_process");
38
+ const path = __importStar(require("path"));
39
+ const crypto_1 = require("crypto");
40
+ const entitybox_capacity_provisioner_1 = require("./entitybox-capacity-provisioner");
41
+ const entitybox_recovery_store_1 = require("./entitybox-recovery-store");
42
+ const entitybox_execution_lease_1 = require("./entitybox-execution-lease");
43
+ const fail = () => new entitybox_execution_lease_1.EntityboxExecutionError('Independent computer setup could not be verified');
44
+ /** One physical setup process, independent of the runtime controller. The
45
+ * caller must claim the plan before calling provision(). A parent crash does
46
+ * not terminate this process or transfer its immutable desktop reservation.
47
+ * The helper never publishes SQL; recovery verifies its completed receipt. */
48
+ function createEntityboxCapacityOwner(config, io = {}) {
49
+ if (config.enabled !== true)
50
+ return undefined;
51
+ const candidate = entitybox_capacity_provisioner_1.EntityboxCapacityProvisioner.create(config);
52
+ if (!candidate)
53
+ throw fail();
54
+ const plan = candidate.plan;
55
+ const settings = { enabled: true, runtimeId: plan.runtimeId, desktopId: plan.desktopId, imageId: plan.imageId, dockerContext: plan.dockerContext, directory: candidate.directory };
56
+ let password = config.vncPassword, flight;
57
+ const planSha256 = (0, crypto_1.createHash)('sha256').update((0, entitybox_recovery_store_1.entityboxCanonical)(plan)).digest('hex');
58
+ async function run() {
59
+ const env = {};
60
+ for (const key of ['PATH', 'Path', 'SystemRoot', 'WINDIR', 'ComSpec', 'USERPROFILE', 'APPDATA', 'LOCALAPPDATA', 'TEMP', 'TMP', 'HOME', 'DOCKER_CONFIG'])
61
+ if (process.env[key] !== undefined)
62
+ env[key] = process.env[key];
63
+ await new Promise((resolve, reject) => {
64
+ let child;
65
+ try {
66
+ child = (io.launch ?? child_process_1.spawn)(process.execPath, [path.join(__dirname, 'entitybox-capacity-owner-process.js')], { env, detached: true, windowsHide: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc'] });
67
+ }
68
+ catch {
69
+ reject(fail());
70
+ return;
71
+ }
72
+ // Join the process even after an IPC/launch error. Neither a lost response
73
+ // nor a deadline permits another helper or a competing Docker operation.
74
+ child.on('error', () => { });
75
+ child.once('close', () => resolve());
76
+ try {
77
+ child.send({ type: 'provision', config: { ...settings, vncPassword: password }, plan }, () => { });
78
+ }
79
+ catch { /* Completion is determined after process exit. */ }
80
+ password = '';
81
+ });
82
+ // IPC acknowledgement/exit code is not physical proof. The durable original
83
+ // receipt permits recovery even when the final reply was lost.
84
+ const receipt = await (io.read ?? entitybox_capacity_provisioner_1.readEntityboxCapacity)(settings.directory, plan.desktopId, plan.runtimeId);
85
+ if (receipt.planSha256 !== planSha256 || receipt.dockerContext !== plan.dockerContext)
86
+ throw fail();
87
+ return receipt;
88
+ }
89
+ return { plan, provision() { flight ??= run().catch(() => { throw fail(); }).finally(() => { password = ''; }); return flight; } };
90
+ }
@@ -0,0 +1,7 @@
1
+ /** Fixed offline bootstrap programs. No request, prompt, URL or shell input is
2
+ * interpolated into them. They run in newly created dedicated containers. */
3
+ export declare const entityboxCapacityInit: string;
4
+ export declare const entityboxCapacityDisplay: string;
5
+ export declare const entityboxCapacityPassword: string;
6
+ export declare const entityboxCapacityApplication: string;
7
+ export declare const entityboxCapacityReady: string;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.entityboxCapacityReady = exports.entityboxCapacityApplication = exports.entityboxCapacityPassword = exports.entityboxCapacityDisplay = exports.entityboxCapacityInit = void 0;
4
+ /** Fixed offline bootstrap programs. No request, prompt, URL or shell input is
5
+ * interpolated into them. They run in newly created dedicated containers. */
6
+ exports.entityboxCapacityInit = String.raw `
7
+ const fs=require('node:fs');
8
+ for(const p of ['/socket','/profile','/work']) {
9
+ if(fs.readdirSync(p).length)throw Error('Expected empty dedicated volume');
10
+ fs.chownSync(p,10001,10001);fs.chmodSync(p,p==='/socket'?0o1777:0o700);
11
+ }
12
+ `;
13
+ exports.entityboxCapacityDisplay = String.raw `
14
+ const fs=require('node:fs'),{spawn}=require('node:child_process');
15
+ const options={env:{PATH:'/usr/local/bin:/usr/bin:/bin',HOME:'/tmp',DISPLAY:':1',LANG:'C.UTF-8'},stdio:'ignore'};
16
+ const launch=(command,args)=>{const p=spawn(command,args,options);p.once('error',()=>process.exit(70));p.once('exit',()=>process.exit(71));return p;};
17
+ launch('Xvfb',[':1','-screen','0','1280x800x24','-nolisten','tcp','-ac','-extension','MIT-SHM']);
18
+ const deadline=setTimeout(()=>process.exit(72),45000);
19
+ const poll=setInterval(()=>{
20
+ if(!fs.existsSync('/tmp/.X11-unix/X1')||!fs.existsSync('/run/entitybox-vnc-password'))return;
21
+ clearInterval(poll);clearTimeout(deadline);
22
+ launch('x11vnc',['-display',':1','-rfbport','5900','-listen','0.0.0.0','-passwdfile','rm:/run/entitybox-vnc-password','-forever','-shared','-noshm','-nolookup','-noipv6']);
23
+ },100);
24
+ `;
25
+ // A secret goes through stdin to tmpfs. It is absent from argv, Docker config,
26
+ // persistent volumes, public receipts and logs. x11vnc removes it after reading.
27
+ exports.entityboxCapacityPassword = String.raw `
28
+ const fs=require('node:fs');let value='';
29
+ process.stdin.setEncoding('utf8');process.stdin.on('data',chunk=>{value+=chunk;if(value.length>8)process.exit(70)});
30
+ process.stdin.on('end',()=>{if(!/^[A-Za-z0-9_-]{8}$/.test(value))process.exit(71);fs.writeFileSync('/run/entitybox-vnc-password',value+'\n',{flag:'wx',mode:0o600})});
31
+ `;
32
+ exports.entityboxCapacityApplication = String.raw `
33
+ const fs=require('node:fs'),{spawn}=require('node:child_process');
34
+ const html='<!doctype html><html><meta charset="utf-8"><title>EntityBox computer</title><style>body{margin:0;background:#101115;color:#f4f4f7;font:17px system-ui;display:grid;place-items:center;height:100vh}main{max-width:540px;padding:40px}span{color:#a99cff;font-size:15px}h1{font-size:36px;letter-spacing:-1px}p{color:#a9abb7;line-height:1.7}</style><main><span>ENTITYBOX</span><h1>Your computer is ready.</h1><p>This dedicated browser keeps its state between tasks. Its applications stay paused until a task takes ownership.</p></main></html>';
35
+ fs.writeFileSync('/tmp/entitybox-welcome.html',html);
36
+ const browser=spawn('browser',['--no-sandbox','--disable-dev-shm-usage','--disable-gpu','--disable-background-networking','--disable-component-update','--disable-default-apps','--disable-sync','--metrics-recording-only','--no-first-run','--no-default-browser-check','--user-data-dir=/home/entitybox/browser-profile','--window-size=1280,800','--window-position=0,0','file:///tmp/entitybox-welcome.html'],{env:{PATH:'/usr/local/bin:/usr/bin:/bin',HOME:'/home/entitybox',DISPLAY:':1',LANG:'C.UTF-8'},stdio:'ignore'});
37
+ browser.once('error',()=>process.exit(70));browser.once('exit',()=>process.exit(71));
38
+ `;
39
+ exports.entityboxCapacityReady = String.raw `
40
+ const net=require('node:net'),{spawnSync}=require('node:child_process');
41
+ const x=spawnSync('xdotool',['search','--onlyvisible','--name','EntityBox computer'],{env:{PATH:'/usr/local/bin:/usr/bin:/bin',DISPLAY:':1'},timeout:2000});
42
+ if(x.status!==0)process.exit(70);
43
+ const socket=net.connect(5900,'127.0.0.1');let data=Buffer.alloc(0),phase=0;
44
+ socket.setTimeout(2000,()=>process.exit(71));socket.on('error',()=>process.exit(72));
45
+ socket.on('data',chunk=>{data=Buffer.concat([data,chunk]);
46
+ if(phase===0&&data.length>=12){if(!/^RFB 003\./.test(data.subarray(0,12).toString()))process.exit(73);data=data.subarray(12);phase=1;socket.write('RFB 003.008\n');}
47
+ if(phase===1&&data.length&&data.length>=data[0]+1){const types=[...data.subarray(1,1+data[0])];if(types.length!==1||types[0]!==2)process.exit(74);socket.destroy();console.log('ready');}
48
+ });
49
+ `;
@@ -0,0 +1,82 @@
1
+ import type { EntityboxDedicatedCapacity } from './entitybox-native-services';
2
+ export interface EntityboxCapacityConfiguration {
3
+ enabled?: boolean;
4
+ runtimeId: string;
5
+ desktopId: string;
6
+ imageId: string;
7
+ directory: string;
8
+ dockerContext?: string;
9
+ /** Issued and retained by the trusted native desktop allocator. Never a
10
+ * renderer/task input, and never written to this module's public journal. */
11
+ vncPassword: string;
12
+ }
13
+ export interface EntityboxCapacityReceipt extends EntityboxDedicatedCapacity {
14
+ version: 1;
15
+ dockerContext: string;
16
+ planSha256: string;
17
+ vncPort: number;
18
+ channels: readonly ['screen'];
19
+ applicationNetwork: 'none';
20
+ }
21
+ export type EntityboxCapacityDocker = (args: string[], stdin?: string) => Promise<string>;
22
+ export interface EntityboxCapacityPlan {
23
+ version: 1;
24
+ capacityId: string;
25
+ runtimeId: string;
26
+ desktopId: string;
27
+ imageId: string;
28
+ dockerContext: string;
29
+ programsSha256: string;
30
+ }
31
+ export declare const entityboxCapacityLabels: (plan: EntityboxCapacityPlan, role: string) => {
32
+ 'ai.add.entitybox.provision.version': string;
33
+ 'ai.add.entitybox.provision.capacity': string;
34
+ 'ai.add.entitybox.provision.desktop': string;
35
+ 'ai.add.entitybox.provision.runtime': string;
36
+ 'ai.add.entitybox.provision.plan': string;
37
+ 'ai.add.entitybox.provision.role': string;
38
+ };
39
+ /** NEW offline dedicated capacity only. This is deliberately unregistered in
40
+ * the shared desktop command runner/reconciler. The server must reserve a new
41
+ * native desktop identity before invoking it, then publish the verified VNC
42
+ * descriptor through its existing authorization path. */
43
+ export declare class EntityboxCapacityProvisioner {
44
+ private readonly docker;
45
+ readonly plan: Readonly<EntityboxCapacityPlan>;
46
+ readonly directory: string;
47
+ private result?;
48
+ private constructor();
49
+ private password;
50
+ static create(config: EntityboxCapacityConfiguration, docker?: EntityboxCapacityDocker): EntityboxCapacityProvisioner | undefined;
51
+ /** Continue a server-claimed plan in its one physical helper. This is not
52
+ * resumption: run() still atomically reserves the desktop before ANY Docker
53
+ * operation and rejects an existing reservation, even for the same plan. */
54
+ static createReserved(config: EntityboxCapacityConfiguration, plan: EntityboxCapacityPlan, docker?: EntityboxCapacityDocker): EntityboxCapacityProvisioner | undefined;
55
+ /** Calls on this one owner join. A new object/process cannot repeat the
56
+ * operation: the desktop reservation remains, even after an ambiguous error. */
57
+ provision(): Promise<Readonly<EntityboxCapacityReceipt>>;
58
+ private inspect;
59
+ private until;
60
+ private run;
61
+ }
62
+ /** Read-only reopening after a clean setup; never resumes, creates, repairs or
63
+ * deletes anything. Missing/ambiguous setup remains reserved for explicit
64
+ * recovery. A restarted container or changed published port is not adopted. */
65
+ export declare function readEntityboxCapacity(directory: string, desktopId: string, runtimeId: string, docker?: EntityboxCapacityDocker): Promise<Readonly<EntityboxCapacityReceipt>>;
66
+ export interface EntityboxCapacityObservationConfiguration {
67
+ enabled?: boolean;
68
+ directory: string;
69
+ desktopId: string;
70
+ runtimeId: string;
71
+ dockerContext: string;
72
+ /** Exact published native registry receipt, never a renderer-selected binding. */
73
+ receipt: Readonly<EntityboxCapacityReceipt>;
74
+ }
75
+ export type EntityboxCapacityObservation = Readonly<{
76
+ state: 'paused' | 'running' | 'unavailable';
77
+ }>;
78
+ /** A health observation is never execution, ownership, stop proof or permission
79
+ * to replace a computer. Every physical read is limited to this published
80
+ * receipt; unavailable includes missing evidence and inconclusive inspection.
81
+ * The existing task reader continues to require a paused application. */
82
+ export declare function observeEntityboxCapacity(config: EntityboxCapacityObservationConfiguration, docker?: EntityboxCapacityDocker): Promise<EntityboxCapacityObservation | undefined>;