@cloudcli-ai/cloudcli 1.35.0 → 1.36.0

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 (126) hide show
  1. package/README.md +12 -7
  2. package/dist/api-docs.html +8 -2
  3. package/dist/assets/{index-CtwxqzGG.js → index-S6cIy7hj.js} +271 -260
  4. package/dist/assets/index-uLUE6Qt1.css +32 -0
  5. package/dist/index.html +12 -4
  6. package/dist-server/server/claude-sdk.js +25 -26
  7. package/dist-server/server/claude-sdk.js.map +1 -1
  8. package/dist-server/server/index.js +0 -13
  9. package/dist-server/server/index.js.map +1 -1
  10. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +70 -1
  11. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
  12. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +52 -11
  13. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
  14. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +138 -1
  15. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
  16. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +5 -0
  17. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -1
  18. package/dist-server/server/modules/providers/services/provider-models.service.js +1 -1
  19. package/dist-server/server/modules/providers/tests/opencode-models.test.js +58 -1
  20. package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -1
  21. package/dist-server/server/modules/websocket/services/websocket-server.service.js +0 -5
  22. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -1
  23. package/dist-server/server/openai-codex.js +9 -8
  24. package/dist-server/server/openai-codex.js.map +1 -1
  25. package/dist-server/server/opencode-cli.js +20 -2
  26. package/dist-server/server/opencode-cli.js.map +1 -1
  27. package/dist-server/server/routes/agent.js +14 -3
  28. package/dist-server/server/routes/agent.js.map +1 -1
  29. package/electron/desktopWindow.js +0 -15
  30. package/electron/launcher/launcher.js +1 -143
  31. package/electron/main.js +1 -117
  32. package/electron/preload.cjs +0 -3
  33. package/package.json +3 -8
  34. package/public/api-docs.html +8 -2
  35. package/scripts/release/prepare-desktop-app.js +0 -6
  36. package/server/claude-sdk.js +32 -26
  37. package/server/index.js +0 -14
  38. package/server/modules/providers/list/claude/claude-models.provider.ts +73 -1
  39. package/server/modules/providers/list/codex/codex-models.provider.ts +59 -11
  40. package/server/modules/providers/list/opencode/opencode-models.provider.ts +180 -1
  41. package/server/modules/providers/services/provider-capabilities.service.ts +7 -0
  42. package/server/modules/providers/services/provider-models.service.ts +1 -1
  43. package/server/modules/providers/tests/opencode-models.test.ts +62 -0
  44. package/server/modules/websocket/services/websocket-server.service.ts +0 -6
  45. package/server/openai-codex.js +9 -7
  46. package/server/opencode-cli.js +21 -2
  47. package/server/routes/agent.js +14 -3
  48. package/server/shared/types.ts +7 -0
  49. package/dist/assets/index-DlvtxFyt.css +0 -32
  50. package/dist-server/server/computer-use-agent.js +0 -242
  51. package/dist-server/server/computer-use-agent.js.map +0 -1
  52. package/dist-server/server/computer-use-mcp.js +0 -519
  53. package/dist-server/server/computer-use-mcp.js.map +0 -1
  54. package/dist-server/server/modules/computer-use/actions/raw-action-dispatcher.js +0 -55
  55. package/dist-server/server/modules/computer-use/actions/raw-action-dispatcher.js.map +0 -1
  56. package/dist-server/server/modules/computer-use/actions/raw-action-types.js +0 -2
  57. package/dist-server/server/modules/computer-use/actions/raw-action-types.js.map +0 -1
  58. package/dist-server/server/modules/computer-use/computer-executor.js +0 -212
  59. package/dist-server/server/modules/computer-use/computer-executor.js.map +0 -1
  60. package/dist-server/server/modules/computer-use/computer-semantics.service.js +0 -422
  61. package/dist-server/server/modules/computer-use/computer-semantics.service.js.map +0 -1
  62. package/dist-server/server/modules/computer-use/computer-use-mcp.routes.js +0 -126
  63. package/dist-server/server/modules/computer-use/computer-use-mcp.routes.js.map +0 -1
  64. package/dist-server/server/modules/computer-use/computer-use.routes.js +0 -196
  65. package/dist-server/server/modules/computer-use/computer-use.routes.js.map +0 -1
  66. package/dist-server/server/modules/computer-use/computer-use.service.js +0 -759
  67. package/dist-server/server/modules/computer-use/computer-use.service.js.map +0 -1
  68. package/dist-server/server/modules/computer-use/desktop-agent-relay.service.js +0 -126
  69. package/dist-server/server/modules/computer-use/desktop-agent-relay.service.js.map +0 -1
  70. package/dist-server/server/modules/computer-use/index.js +0 -3
  71. package/dist-server/server/modules/computer-use/index.js.map +0 -1
  72. package/dist-server/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.js +0 -59
  73. package/dist-server/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.js.map +0 -1
  74. package/dist-server/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.js +0 -5
  75. package/dist-server/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.js.map +0 -1
  76. package/dist-server/server/modules/computer-use/semantics/adapters/semantic-adapter.js +0 -2
  77. package/dist-server/server/modules/computer-use/semantics/adapters/semantic-adapter.js.map +0 -1
  78. package/dist-server/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.js +0 -5
  79. package/dist-server/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.js.map +0 -1
  80. package/dist-server/server/modules/computer-use/semantics/bin/darwin-arm64/CloudCLISemantics +0 -0
  81. package/dist-server/server/modules/computer-use/semantics/bin/darwin-x64/CloudCLISemantics +0 -0
  82. package/dist-server/server/modules/computer-use/semantics/bin/win32-arm64/CloudCLISemantics.exe +0 -0
  83. package/dist-server/server/modules/computer-use/semantics/bin/win32-x64/CloudCLISemantics.exe +0 -0
  84. package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-process.js +0 -106
  85. package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-process.js.map +0 -1
  86. package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.js +0 -78
  87. package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.js.map +0 -1
  88. package/dist-server/server/modules/computer-use/semantics/semantic-session-store.js +0 -68
  89. package/dist-server/server/modules/computer-use/semantics/semantic-session-store.js.map +0 -1
  90. package/dist-server/server/modules/computer-use/semantics/semantic-tool-dispatcher.js +0 -16
  91. package/dist-server/server/modules/computer-use/semantics/semantic-tool-dispatcher.js.map +0 -1
  92. package/dist-server/server/modules/computer-use/semantics/semantic-types.js +0 -2
  93. package/dist-server/server/modules/computer-use/semantics/semantic-types.js.map +0 -1
  94. package/dist-server/server/modules/websocket/services/desktop-agent-websocket.service.js +0 -39
  95. package/dist-server/server/modules/websocket/services/desktop-agent-websocket.service.js.map +0 -1
  96. package/electron/computerAgent.js +0 -290
  97. package/scripts/build-computer-semantics.mjs +0 -133
  98. package/scripts/copy-computer-semantics-bin.mjs +0 -24
  99. package/server/computer-use-agent.ts +0 -279
  100. package/server/computer-use-mcp.ts +0 -574
  101. package/server/modules/computer-use/actions/raw-action-dispatcher.ts +0 -67
  102. package/server/modules/computer-use/actions/raw-action-types.ts +0 -28
  103. package/server/modules/computer-use/computer-executor.ts +0 -242
  104. package/server/modules/computer-use/computer-semantics.service.ts +0 -460
  105. package/server/modules/computer-use/computer-use-mcp.routes.ts +0 -141
  106. package/server/modules/computer-use/computer-use.routes.ts +0 -211
  107. package/server/modules/computer-use/computer-use.service.ts +0 -920
  108. package/server/modules/computer-use/desktop-agent-relay.service.ts +0 -158
  109. package/server/modules/computer-use/index.ts +0 -2
  110. package/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.ts +0 -82
  111. package/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.ts +0 -5
  112. package/server/modules/computer-use/semantics/adapters/semantic-adapter.ts +0 -23
  113. package/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.ts +0 -5
  114. package/server/modules/computer-use/semantics/bin/darwin-arm64/CloudCLISemantics +0 -0
  115. package/server/modules/computer-use/semantics/bin/darwin-x64/CloudCLISemantics +0 -0
  116. package/server/modules/computer-use/semantics/bin/win32-arm64/CloudCLISemantics.exe +0 -0
  117. package/server/modules/computer-use/semantics/bin/win32-x64/CloudCLISemantics.exe +0 -0
  118. package/server/modules/computer-use/semantics/helpers/macos/CloudCLISemantics.swift +0 -467
  119. package/server/modules/computer-use/semantics/helpers/semantic-helper-process.ts +0 -124
  120. package/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.ts +0 -97
  121. package/server/modules/computer-use/semantics/helpers/windows/CloudCLISemantics.csproj +0 -11
  122. package/server/modules/computer-use/semantics/helpers/windows/Program.cs +0 -534
  123. package/server/modules/computer-use/semantics/semantic-session-store.ts +0 -87
  124. package/server/modules/computer-use/semantics/semantic-tool-dispatcher.ts +0 -17
  125. package/server/modules/computer-use/semantics/semantic-types.ts +0 -58
  126. package/server/modules/websocket/services/desktop-agent-websocket.service.ts +0 -51
@@ -1,39 +0,0 @@
1
- import { desktopAgentRelay } from '../../../modules/computer-use/index.js';
2
- import { parseIncomingJsonObject } from '../../../shared/utils.js';
3
- /**
4
- * Handles the `/desktop-agent` websocket — the inbound side of the cloud
5
- * Computer Use relay. A linked CloudCLI desktop app connects here and registers
6
- * itself as the executor for this hosted environment. The server then forwards
7
- * `computer_*` actions via `desktopAgentRelay`, and the agent returns results as
8
- * `computer_relay_result` frames correlated by `id`.
9
- */
10
- export function handleDesktopAgentConnection(ws, request) {
11
- let registered = false;
12
- ws.on('message', (rawMessage) => {
13
- const data = parseIncomingJsonObject(rawMessage);
14
- if (!data) {
15
- return;
16
- }
17
- const kind = typeof data.kind === 'string' ? data.kind : typeof data.type === 'string' ? data.type : '';
18
- if (kind === 'register' && !registered) {
19
- const label = typeof data.label === 'string' && data.label.trim()
20
- ? data.label.trim()
21
- : request.user?.username
22
- ? `desktop:${request.user.username}`
23
- : 'desktop-agent';
24
- registered = true;
25
- console.log('[INFO] Desktop agent websocket registered:', label);
26
- desktopAgentRelay.register(ws, label);
27
- return;
28
- }
29
- if (kind === 'computer_relay_result' && typeof data.id === 'string') {
30
- desktopAgentRelay.handleResult(data.id, data.result, typeof data.error === 'string'
31
- ? data.error
32
- : undefined);
33
- }
34
- });
35
- ws.on('close', () => {
36
- console.log('[INFO] Desktop agent websocket disconnected');
37
- });
38
- }
39
- //# sourceMappingURL=desktop-agent-websocket.service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"desktop-agent-websocket.service.js","sourceRoot":"","sources":["../../../../../server/modules/websocket/services/desktop-agent-websocket.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B,CAC1C,EAAa,EACb,OAAsC;IAEtC,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,EAAE;QAC9B,MAAM,IAAI,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACxG,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC,UAAU,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;gBAC/D,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;gBACnB,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ;oBACtB,CAAC,CAAC,WAAW,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE;oBACpC,CAAC,CAAC,eAAe,CAAC;YACtB,UAAU,GAAG,IAAI,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAC;YACjE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QACD,IAAI,IAAI,KAAK,uBAAuB,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YACpE,iBAAiB,CAAC,YAAY,CAC5B,IAAI,CAAC,EAAE,EACN,IAAgC,CAAC,MAAM,EACxC,OAAQ,IAAgC,CAAC,KAAK,KAAK,QAAQ;gBACzD,CAAC,CAAG,IAAgC,CAAC,KAAgB;gBACrD,CAAC,CAAC,SAAS,CACd,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAClB,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,290 +0,0 @@
1
- import { spawn } from 'node:child_process';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
-
5
- const IPC_PREFIX = '@@CUAGENT@@';
6
- const TARGET_STATUS_TIMEOUT_MS = 5000;
7
-
8
- function getDesktopPath() {
9
- const currentPath = process.env.PATH || '';
10
- const commonPaths = process.platform === 'win32'
11
- ? []
12
- : ['/opt/homebrew/bin', '/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin'];
13
- return [...commonPaths, currentPath].filter(Boolean).join(path.delimiter);
14
- }
15
-
16
- function getNodeRuntime(isPackaged) {
17
- if (isPackaged && process.versions.electron) {
18
- return { command: process.execPath, env: { ELECTRON_RUN_AS_NODE: '1' } };
19
- }
20
- if (process.env.npm_node_execpath) {
21
- return { command: process.env.npm_node_execpath, env: {} };
22
- }
23
- return { command: 'node', env: {} };
24
- }
25
-
26
- function toAgentWsUrl(httpUrl) {
27
- try {
28
- const parsed = new URL(httpUrl);
29
- parsed.protocol = parsed.protocol === 'http:' ? 'ws:' : 'wss:';
30
- parsed.pathname = '/desktop-agent';
31
- parsed.search = '';
32
- parsed.hash = '';
33
- return parsed.toString();
34
- } catch {
35
- return null;
36
- }
37
- }
38
-
39
- async function isComputerUseEnabledTarget(httpUrl, apiKey) {
40
- let statusUrl;
41
- try {
42
- statusUrl = new URL('/api/computer-use/status', httpUrl).toString();
43
- } catch {
44
- return false;
45
- }
46
-
47
- const controller = new AbortController();
48
- const timeout = setTimeout(() => controller.abort(), TARGET_STATUS_TIMEOUT_MS);
49
- try {
50
- const response = await fetch(statusUrl, {
51
- signal: controller.signal,
52
- headers: apiKey ? { 'X-API-Key': apiKey } : undefined,
53
- });
54
- const body = await response.json().catch(() => null);
55
- return response.ok && body?.success !== false && body?.data?.enabled === true;
56
- } catch {
57
- return false;
58
- } finally {
59
- clearTimeout(timeout);
60
- }
61
- }
62
-
63
- async function filterEnabledComputerUseTargets(targets, apiKey) {
64
- const checks = await Promise.all(targets.map(async (target) => ({
65
- target,
66
- enabled: await isComputerUseEnabledTarget(target, apiKey),
67
- })));
68
- return checks.filter((item) => item.enabled).map((item) => item.target);
69
- }
70
-
71
- /**
72
- * Keeps a Computer Use desktop agent connected to running cloud environments
73
- * while desktop access is enabled.
74
- */
75
- export class ComputerAgentController {
76
- constructor({ appRoot, settingsPath, isPackaged = false, getRunningEnvironmentUrls, getApiKey, promptConsent, onChange }) {
77
- this.appRoot = appRoot;
78
- this.settingsPath = settingsPath;
79
- this.isPackaged = isPackaged;
80
- this.getRunningEnvironmentUrls = getRunningEnvironmentUrls;
81
- this.getApiKey = getApiKey;
82
- this.promptConsent = promptConsent;
83
- this.onChange = onChange;
84
- this.settings = { enabled: false, consentMode: 'ask' };
85
- this.child = null;
86
- this.connectedUrls = new Set();
87
- this.currentTargets = [];
88
- this.stdoutBuffer = '';
89
- this.lastEvent = null;
90
- this.lastError = null;
91
- }
92
-
93
- getSettings() {
94
- return { ...this.settings };
95
- }
96
-
97
- getState() {
98
- return {
99
- enabled: this.settings.enabled,
100
- consentMode: this.settings.consentMode,
101
- running: Boolean(this.child),
102
- connectedCount: this.connectedUrls.size,
103
- targetCount: this.currentTargets.length,
104
- targetUrls: [...this.currentTargets],
105
- lastEvent: this.lastEvent,
106
- lastError: this.lastError,
107
- };
108
- }
109
-
110
- async loadSettings() {
111
- try {
112
- const raw = await fs.readFile(this.settingsPath, 'utf8');
113
- const stored = JSON.parse(raw);
114
- this.settings = {
115
- enabled: Boolean(stored.enabled),
116
- consentMode: stored.consentMode === 'auto' ? 'auto' : 'ask',
117
- };
118
- } catch {
119
- this.settings = { enabled: false, consentMode: 'ask' };
120
- }
121
- return this.settings;
122
- }
123
-
124
- async saveSettings(next) {
125
- this.settings = {
126
- enabled: Boolean(next.enabled),
127
- consentMode: next.consentMode === 'auto' ? 'auto' : 'ask',
128
- };
129
- await fs.mkdir(path.dirname(this.settingsPath), { recursive: true });
130
- await fs.writeFile(this.settingsPath, JSON.stringify(this.settings, null, 2), 'utf8');
131
- await this.sync();
132
- this.onChange?.();
133
- return this.settings;
134
- }
135
-
136
- async sync() {
137
- const targets = this.settings.enabled ? (this.getRunningEnvironmentUrls?.() || []) : [];
138
- const enabledTargets = this.settings.enabled ? await filterEnabledComputerUseTargets(targets, this.getApiKey?.() || '') : [];
139
- const wsTargets = enabledTargets.map(toAgentWsUrl).filter(Boolean);
140
-
141
- const sameTargets =
142
- wsTargets.length === this.currentTargets.length &&
143
- wsTargets.every((url) => this.currentTargets.includes(url));
144
-
145
- if (!this.settings.enabled || wsTargets.length === 0) {
146
- this.stop();
147
- this.currentTargets = [];
148
- this.lastEvent = this.settings.enabled ? 'no-targets' : 'disabled';
149
- return;
150
- }
151
-
152
- if (this.child && sameTargets) {
153
- return;
154
- }
155
-
156
- this.currentTargets = wsTargets;
157
- this.lastEvent = 'restarting';
158
- this.lastError = null;
159
- this.restart(wsTargets);
160
- }
161
-
162
- restart(wsTargets) {
163
- this.stop();
164
-
165
- const agentEntry = process.env.CLOUDCLI_COMPUTER_AGENT_ENTRY
166
- || path.join(this.appRoot, 'dist-server', 'server', 'computer-use-agent.js');
167
- const runtime = getNodeRuntime(this.isPackaged);
168
-
169
- this.child = spawn(runtime.command, [agentEntry], {
170
- cwd: this.appRoot,
171
- env: {
172
- ...process.env,
173
- ...runtime.env,
174
- PATH: getDesktopPath(),
175
- CLOUDCLI_DESKTOP_AGENT_URLS: wsTargets.join(','),
176
- CLOUDCLI_DESKTOP_AGENT_API_KEY: this.getApiKey?.() || '',
177
- CLOUDCLI_COMPUTER_USE_CONSENT_MODE: this.settings.consentMode,
178
- },
179
- stdio: ['pipe', 'pipe', 'pipe'],
180
- windowsHide: true,
181
- });
182
-
183
- this.connectedUrls = new Set();
184
-
185
- this.child.once('error', (error) => {
186
- console.error('[ComputerAgent] failed to start:', error.message);
187
- this.lastEvent = 'start-error';
188
- this.lastError = error.message;
189
- this.child = null;
190
- this.onChange?.();
191
- });
192
-
193
- this.child.stdout?.on('data', (chunk) => this.handleStdout(String(chunk)));
194
- this.child.stderr?.on('data', (chunk) => {
195
- for (const line of String(chunk).split(/\r?\n/)) {
196
- if (line.trim()) {
197
- this.lastError = line.trim();
198
- console.error('[ComputerAgent]', line);
199
- }
200
- }
201
- });
202
-
203
- this.child.once('exit', (code) => {
204
- console.log(`[ComputerAgent] exited (code ${code ?? 'null'})`);
205
- this.lastEvent = `exit:${code ?? 'null'}`;
206
- this.child = null;
207
- this.connectedUrls = new Set();
208
- this.onChange?.();
209
- });
210
-
211
- this.onChange?.();
212
- }
213
-
214
- handleStdout(chunk) {
215
- this.stdoutBuffer += chunk;
216
- const lines = this.stdoutBuffer.split('\n');
217
- this.stdoutBuffer = lines.pop() || '';
218
- for (const line of lines) {
219
- const trimmed = line.trim();
220
- if (!trimmed.startsWith(IPC_PREFIX)) {
221
- if (trimmed) console.log('[ComputerAgent]', trimmed);
222
- continue;
223
- }
224
- let payload;
225
- try {
226
- payload = JSON.parse(trimmed.slice(IPC_PREFIX.length).trim());
227
- } catch {
228
- continue;
229
- }
230
- void this.handleAgentEvent(payload);
231
- }
232
- }
233
-
234
- async handleAgentEvent(payload) {
235
- switch (payload.type) {
236
- case 'connected':
237
- this.connectedUrls.add(payload.url);
238
- this.lastEvent = 'connected';
239
- this.lastError = null;
240
- this.onChange?.();
241
- break;
242
- case 'disconnected':
243
- this.connectedUrls.delete(payload.url);
244
- this.lastEvent = 'disconnected';
245
- this.onChange?.();
246
- if (payload.reason && /computer use.*disabled/i.test(payload.reason)) {
247
- void this.sync().catch((error) => {
248
- this.lastError = error instanceof Error ? error.message : 'Failed to sync Computer Use targets.';
249
- this.onChange?.();
250
- });
251
- }
252
- break;
253
- case 'starting':
254
- this.lastEvent = 'starting';
255
- this.lastError = null;
256
- this.onChange?.();
257
- break;
258
- case 'error':
259
- this.lastEvent = 'error';
260
- this.lastError = payload.message || 'Computer agent error.';
261
- this.onChange?.();
262
- break;
263
- case 'consent-request': {
264
- const allow = await this.promptConsent?.(payload.sessionId);
265
- this.sendToChild({ type: 'consent-response', sessionId: payload.sessionId, allow: Boolean(allow) });
266
- break;
267
- }
268
- default:
269
- break;
270
- }
271
- }
272
-
273
- sendToChild(message) {
274
- if (this.child?.stdin?.writable) {
275
- this.child.stdin.write(`${IPC_PREFIX} ${JSON.stringify(message)}\n`);
276
- }
277
- }
278
-
279
- revokeSession(sessionId) {
280
- this.sendToChild({ type: 'revoke-session', sessionId });
281
- }
282
-
283
- stop() {
284
- if (!this.child) return;
285
- const child = this.child;
286
- this.child = null;
287
- this.connectedUrls = new Set();
288
- try { child.kill('SIGTERM'); } catch { /* noop */ }
289
- }
290
- }
@@ -1,133 +0,0 @@
1
- #!/usr/bin/env node
2
- import { spawn } from 'node:child_process';
3
- import fs from 'node:fs/promises';
4
- import path from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
-
7
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
- const rootDir = path.resolve(__dirname, '..');
9
- const platform = process.env.CLOUDCLI_SEMANTICS_PLATFORM || process.platform;
10
- const arch = process.env.CLOUDCLI_SEMANTICS_ARCH || process.arch;
11
- const platformArch = `${platform}-${arch}`;
12
- const semanticsRoot = path.join(rootDir, 'server', 'modules', 'computer-use', 'semantics');
13
- const outDir = path.join(semanticsRoot, 'bin', platformArch);
14
- const requireBuild = process.env.CLOUDCLI_SEMANTICS_BUILD_REQUIRED === '1';
15
-
16
- function run(command, args, options = {}) {
17
- return new Promise((resolve, reject) => {
18
- const child = spawn(command, args, {
19
- stdio: 'inherit',
20
- shell: process.platform === 'win32',
21
- ...options,
22
- });
23
- child.once('error', reject);
24
- child.once('exit', (code) => {
25
- if (code === 0) resolve();
26
- else reject(new Error(`${command} ${args.join(' ')} exited with code ${code}`));
27
- });
28
- });
29
- }
30
-
31
- function commandExists(command) {
32
- return new Promise((resolve) => {
33
- const child = spawn(command, ['--version'], {
34
- stdio: 'ignore',
35
- shell: process.platform === 'win32',
36
- });
37
- child.once('error', () => resolve(false));
38
- child.once('exit', (code) => resolve(code === 0));
39
- });
40
- }
41
-
42
- async function pathExists(filePath) {
43
- try {
44
- await fs.access(filePath);
45
- return true;
46
- } catch {
47
- return false;
48
- }
49
- }
50
-
51
- async function isUpToDate(output, inputs) {
52
- if (!(await pathExists(output))) {
53
- return false;
54
- }
55
-
56
- const outputStat = await fs.stat(output);
57
- for (const input of inputs) {
58
- const inputStat = await fs.stat(input);
59
- if (inputStat.mtimeMs > outputStat.mtimeMs) {
60
- return false;
61
- }
62
- }
63
- return true;
64
- }
65
-
66
- async function ensureCommand(command, helpText) {
67
- if (await commandExists(command)) {
68
- return true;
69
- }
70
-
71
- const message = `${command} was not found. ${helpText}`;
72
- if (requireBuild) {
73
- throw new Error(message);
74
- }
75
- console.log(`Skipping semantic helper build: ${message}`);
76
- return false;
77
- }
78
-
79
- if (platform === 'darwin') {
80
- const source = path.join(semanticsRoot, 'helpers', 'macos', 'CloudCLISemantics.swift');
81
- const output = path.join(outDir, 'CloudCLISemantics');
82
-
83
- if (!(await ensureCommand('swiftc', 'Install Xcode Command Line Tools to compile the macOS helper.'))) {
84
- process.exit(0);
85
- }
86
- if (await isUpToDate(output, [source])) {
87
- console.log(`Semantic helper is up to date: ${path.relative(rootDir, output)}`);
88
- process.exit(0);
89
- }
90
-
91
- await fs.mkdir(outDir, { recursive: true });
92
- await run('swiftc', [
93
- source,
94
- '-o',
95
- output,
96
- '-framework',
97
- 'AppKit',
98
- '-framework',
99
- 'ApplicationServices',
100
- ]);
101
- await fs.chmod(output, 0o755);
102
- console.log(`Built ${path.relative(rootDir, output)}`);
103
- } else if (platform === 'win32') {
104
- const project = path.join(semanticsRoot, 'helpers', 'windows', 'CloudCLISemantics.csproj');
105
- const source = path.join(semanticsRoot, 'helpers', 'windows', 'Program.cs');
106
- const output = path.join(outDir, 'CloudCLISemantics.exe');
107
-
108
- if (!(await ensureCommand('dotnet', '.NET SDK is required to compile the Windows helper.'))) {
109
- process.exit(0);
110
- }
111
- if (await isUpToDate(output, [project, source])) {
112
- console.log(`Semantic helper is up to date: ${path.relative(rootDir, output)}`);
113
- process.exit(0);
114
- }
115
-
116
- await fs.mkdir(outDir, { recursive: true });
117
- await run('dotnet', [
118
- 'publish',
119
- project,
120
- '-c',
121
- 'Release',
122
- '-r',
123
- arch === 'arm64' ? 'win-arm64' : 'win-x64',
124
- '--self-contained',
125
- 'false',
126
- '-p:PublishSingleFile=true',
127
- '-o',
128
- outDir,
129
- ]);
130
- console.log(`Built ${path.relative(rootDir, output)}`);
131
- } else {
132
- console.log(`Semantic helper build is not supported for ${platform}-${arch}.`);
133
- }
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
-
6
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
- const rootDir = path.resolve(__dirname, '..');
8
- const sourceDir = path.join(rootDir, 'server', 'modules', 'computer-use', 'semantics', 'bin');
9
- const targetDir = path.join(rootDir, 'dist-server', 'server', 'modules', 'computer-use', 'semantics', 'bin');
10
-
11
- async function pathExists(filePath) {
12
- try {
13
- await fs.access(filePath);
14
- return true;
15
- } catch {
16
- return false;
17
- }
18
- }
19
-
20
- if (await pathExists(sourceDir)) {
21
- await fs.mkdir(path.dirname(targetDir), { recursive: true });
22
- await fs.cp(sourceDir, targetDir, { recursive: true });
23
- console.log(`Copied Computer Use semantic helpers to ${path.relative(rootDir, targetDir)}`);
24
- }