@crosshands/cli 0.1.6 → 0.2.1

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 (54) hide show
  1. package/dist/bin.js +3 -3
  2. package/dist/bin.js.map +1 -1
  3. package/dist/broker-host.d.ts +2 -1
  4. package/dist/broker-host.d.ts.map +1 -1
  5. package/dist/broker-host.js +65 -40
  6. package/dist/broker-host.js.map +1 -1
  7. package/dist/broker-result.d.ts +7 -0
  8. package/dist/broker-result.d.ts.map +1 -0
  9. package/dist/broker-result.js +10 -0
  10. package/dist/broker-result.js.map +1 -0
  11. package/dist/index.d.ts +6 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +60 -32
  14. package/dist/index.js.map +1 -1
  15. package/dist/intent/dispatch.d.ts +13 -0
  16. package/dist/intent/dispatch.d.ts.map +1 -0
  17. package/dist/intent/dispatch.js +277 -0
  18. package/dist/intent/dispatch.js.map +1 -0
  19. package/dist/intent/env.d.ts +11 -0
  20. package/dist/intent/env.d.ts.map +1 -0
  21. package/dist/intent/env.js +10 -0
  22. package/dist/intent/env.js.map +1 -0
  23. package/dist/intent/evaluate.d.ts +31 -0
  24. package/dist/intent/evaluate.d.ts.map +1 -0
  25. package/dist/intent/evaluate.js +156 -0
  26. package/dist/intent/evaluate.js.map +1 -0
  27. package/dist/intent/http.d.ts +8 -0
  28. package/dist/intent/http.d.ts.map +1 -0
  29. package/dist/intent/http.js +4 -0
  30. package/dist/intent/http.js.map +1 -0
  31. package/dist/intent/log.d.ts +82 -0
  32. package/dist/intent/log.d.ts.map +1 -0
  33. package/dist/intent/log.js +124 -0
  34. package/dist/intent/log.js.map +1 -0
  35. package/dist/intent/tree.d.ts +13 -0
  36. package/dist/intent/tree.d.ts.map +1 -0
  37. package/dist/intent/tree.js +99 -0
  38. package/dist/intent/tree.js.map +1 -0
  39. package/dist/local-client.d.ts +1 -0
  40. package/dist/local-client.d.ts.map +1 -1
  41. package/dist/local-client.js +23 -15
  42. package/dist/local-client.js.map +1 -1
  43. package/package.json +6 -6
  44. package/src/bin.ts +4 -3
  45. package/src/broker-host.ts +68 -38
  46. package/src/broker-result.ts +14 -0
  47. package/src/index.ts +71 -35
  48. package/src/intent/dispatch.ts +373 -0
  49. package/src/intent/env.ts +13 -0
  50. package/src/intent/evaluate.ts +211 -0
  51. package/src/intent/http.ts +10 -0
  52. package/src/intent/log.ts +219 -0
  53. package/src/intent/tree.ts +108 -0
  54. package/src/local-client.ts +31 -15
@@ -0,0 +1,124 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { JsonlFileWriter, diagnosticsDirectory } from '@crosshands/runtime';
3
+ import { localClientPaths } from '../local-client.js';
4
+ import { parseJevEnv } from './env.js';
5
+ import { elapsedMs } from './http.js';
6
+ export function hashGoal(goal) {
7
+ return createHash('sha256').update(goal).digest('hex');
8
+ }
9
+ const OMIT = new Set(['goal', 'apiKey', 'treeText', 'text', 'value', 'TYPESAFE_API_KEY']);
10
+ export function createJevCall(operation, goal) {
11
+ return {
12
+ callId: randomUUID(),
13
+ operation,
14
+ ...(goal === undefined ? {} : { goal }),
15
+ ranks: 0,
16
+ httpMs: 0,
17
+ brokerCalls: 0
18
+ };
19
+ }
20
+ export function recordRank(log, call, phase, stats, suggestion) {
21
+ if (call !== undefined) {
22
+ call.phase = phase;
23
+ call.ranks += 1;
24
+ if (stats.http !== undefined)
25
+ call.httpMs += stats.http.durationMs;
26
+ }
27
+ if (log === undefined || call === undefined)
28
+ return;
29
+ const shared = {
30
+ callId: call.callId,
31
+ operation: call.operation,
32
+ snapshotId: stats.snapshotId,
33
+ phase,
34
+ ...(call.goal === undefined ? {} : { goal: call.goal })
35
+ };
36
+ if (stats.http !== undefined) {
37
+ log.emit({
38
+ kind: 'jev.http',
39
+ ...shared,
40
+ status: stats.http.status,
41
+ durationMs: stats.http.durationMs,
42
+ requestBytes: stats.http.requestBytes,
43
+ responseBytes: stats.http.responseBytes,
44
+ candidateCount: stats.candidateCount
45
+ });
46
+ }
47
+ if (suggestion === undefined)
48
+ return;
49
+ const move = suggestion.move;
50
+ log.emit({
51
+ kind: 'jev.decision',
52
+ ...shared,
53
+ ...(stats.app === undefined ? {} : { app: stats.app }),
54
+ move: move.kind,
55
+ ...(move.kind === 'click' ||
56
+ move.kind === 'setValue' ||
57
+ move.kind === 'secondary' ||
58
+ move.kind === 'scroll'
59
+ ? { elementIndex: move.elementIndex }
60
+ : {}),
61
+ ...(move.kind === 'blocked' ? { reason: move.reason } : {}),
62
+ ...(suggestion.confidence === undefined ? {} : { confidence: suggestion.confidence }),
63
+ goalChars: stats.goalChars,
64
+ treeChars: stats.treeChars,
65
+ elementCount: stats.elementCount,
66
+ candidateCount: stats.candidateCount,
67
+ parseMs: stats.parseMs,
68
+ ...(stats.evaluateMs === undefined ? {} : { evaluateMs: stats.evaluateMs })
69
+ });
70
+ }
71
+ export function emitCall(log, call, started, extra = {}) {
72
+ if (log === undefined || call === undefined)
73
+ return;
74
+ log.emit({
75
+ kind: 'jev.call',
76
+ callId: call.callId,
77
+ operation: call.operation,
78
+ durationMs: elapsedMs(started),
79
+ httpMs: call.httpMs,
80
+ brokerCalls: call.brokerCalls,
81
+ ranks: call.ranks,
82
+ ...(call.phase === undefined ? {} : { phase: call.phase }),
83
+ ...(extra.bound === undefined ? {} : { bound: extra.bound }),
84
+ ...(extra.error === undefined ? {} : { error: extra.error }),
85
+ ...(call.goal === undefined ? {} : { goal: call.goal })
86
+ });
87
+ }
88
+ export function createJevLogger(graphicalSessionId, env = process.env) {
89
+ const writer = new JsonlFileWriter({
90
+ directory: diagnosticsDirectory(graphicalSessionId, { env }),
91
+ generation: `jev-${randomUUID()}`
92
+ });
93
+ writer.start();
94
+ return {
95
+ emit(record) {
96
+ try {
97
+ const raw = record;
98
+ const goal = raw.goal;
99
+ const rest = {
100
+ ...raw,
101
+ kind: record.kind,
102
+ v: 1,
103
+ ts: new Date().toISOString()
104
+ };
105
+ for (const key of OMIT)
106
+ delete rest[key];
107
+ writer.emit({
108
+ ...rest,
109
+ ...(typeof goal === 'string' ? { goalSha256: hashGoal(goal) } : {})
110
+ });
111
+ }
112
+ catch {
113
+ // Jev logs must not fail computer-use.
114
+ }
115
+ },
116
+ close: () => writer.close()
117
+ };
118
+ }
119
+ export function createCliJevLogger(env = process.env) {
120
+ if (parseJevEnv(env).kind === 'off')
121
+ return undefined;
122
+ return createJevLogger(localClientPaths().identity.graphicalSessionId, env);
123
+ }
124
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/intent/log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export type TreeMove = {
2
+ elementIndex: number;
3
+ role: string;
4
+ label: string;
5
+ line: string;
6
+ disabled: boolean;
7
+ clickable: boolean;
8
+ settable: boolean;
9
+ };
10
+ export declare function parseTreeMoves(treeText: string): TreeMove[];
11
+ export declare const JEV_CHOICE_CAP = 255;
12
+ export declare function clickableMoves(moves: readonly TreeMove[]): TreeMove[];
13
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/intent/tree.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAgED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE,CA2B3D;AAED,eAAO,MAAM,cAAc,MAAM,CAAA;AAEjC,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAIrE"}
@@ -0,0 +1,99 @@
1
+ const ROW_START = /^(\t*)(\d+) (.+)$/;
2
+ const MULTI_WORD_ROLES = [
3
+ 'search text field',
4
+ 'text field',
5
+ 'text area',
6
+ 'menu button',
7
+ 'pop up button',
8
+ 'popup button',
9
+ 'radio button',
10
+ 'check box',
11
+ 'combo box',
12
+ 'disclosure triangle',
13
+ 'standard window',
14
+ 'scroll area',
15
+ 'split group',
16
+ 'outline row',
17
+ 'table row'
18
+ ];
19
+ const CLICKABLE_ROLE = new Set([
20
+ 'button',
21
+ 'link',
22
+ 'checkbox',
23
+ 'check box',
24
+ 'radio button',
25
+ 'radio',
26
+ 'tab',
27
+ 'menu button',
28
+ 'pop up button',
29
+ 'popup button',
30
+ 'combo box',
31
+ 'disclosure triangle'
32
+ ]);
33
+ const SETTABLE_ROLE = new Set(['text field', 'search text field', 'text area', 'combo box']);
34
+ function isHeaderOrFooter(line) {
35
+ if (line.length === 0)
36
+ return true;
37
+ if (line.startsWith('App='))
38
+ return true;
39
+ if (line.startsWith('Window:'))
40
+ return true;
41
+ if (line.startsWith('The focused UI element'))
42
+ return true;
43
+ if (line.startsWith('No UI element'))
44
+ return true;
45
+ return false;
46
+ }
47
+ function roleAndLabel(body) {
48
+ const lower = body.toLowerCase();
49
+ const multi = MULTI_WORD_ROLES.find((role) => lower.startsWith(role) && (body.length === role.length || /[\s,(]/.test(body[role.length])));
50
+ if (multi !== undefined) {
51
+ return {
52
+ role: body.slice(0, multi.length),
53
+ label: body.slice(multi.length).replace(/^[\s,]+/, '')
54
+ };
55
+ }
56
+ const comma = body.indexOf(',');
57
+ const head = (comma === -1 ? body : body.slice(0, comma)).trim();
58
+ const space = head.indexOf(' ');
59
+ if (space === -1)
60
+ return { role: head, label: '' };
61
+ return { role: head.slice(0, space), label: head.slice(space + 1).trim() };
62
+ }
63
+ export function parseTreeMoves(treeText) {
64
+ const rows = [];
65
+ for (const line of treeText.split('\n')) {
66
+ const match = ROW_START.exec(line);
67
+ if (match !== null && match[2] !== undefined && match[3] !== undefined) {
68
+ rows.push({ elementIndex: Number(match[2]), body: match[3] });
69
+ continue;
70
+ }
71
+ const previous = rows[rows.length - 1];
72
+ if (previous !== undefined && !isHeaderOrFooter(line))
73
+ previous.body += `\n${line}`;
74
+ }
75
+ return rows.map((row) => {
76
+ const { role, label } = roleAndLabel(row.body);
77
+ const disabled = /\(disabled\)/.test(row.body);
78
+ const roleKey = role.toLowerCase();
79
+ const settable = /\(settable\)/.test(row.body) || SETTABLE_ROLE.has(roleKey);
80
+ const clickable = !disabled && (CLICKABLE_ROLE.has(roleKey) || settable);
81
+ return {
82
+ elementIndex: row.elementIndex,
83
+ role,
84
+ label,
85
+ line: `${row.elementIndex} ${row.body}`,
86
+ disabled,
87
+ clickable,
88
+ settable
89
+ };
90
+ });
91
+ }
92
+ export const JEV_CHOICE_CAP = 255;
93
+ export function clickableMoves(moves) {
94
+ const selected = moves.filter((move) => move.clickable);
95
+ if (selected.length <= JEV_CHOICE_CAP)
96
+ return selected;
97
+ return selected.slice(0, JEV_CHOICE_CAP);
98
+ }
99
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/intent/tree.ts"],"names":[],"mappings":"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"}
@@ -13,5 +13,6 @@ export type ProductionClientOptions = {
13
13
  spawnBroker?: (entrypoint: string) => void | Promise<void>;
14
14
  paths?: LocalClientPaths;
15
15
  };
16
+ export declare function brokerSpawnEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
16
17
  export declare function createProductionBrokerClient(options?: ProductionClientOptions): Promise<CliBrokerClient>;
17
18
  //# sourceMappingURL=local-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-client.d.ts","sourceRoot":"","sources":["../src/local-client.ts"],"names":[],"mappings":"AAOA,OAAO,EAAsB,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAEnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;CAC5C,CAAA;AAED,wBAAgB,gBAAgB,IAAI,gBAAgB,CA2BnD;AAuDD,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1D,KAAK,CAAC,EAAE,gBAAgB,CAAA;CACzB,CAAA;AAkBD,wBAAsB,4BAA4B,CAChD,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,eAAe,CAAC,CAqC1B"}
1
+ {"version":3,"file":"local-client.d.ts","sourceRoot":"","sources":["../src/local-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,cAAc,EAGd,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAG5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;CAC5C,CAAA;AAED,wBAAgB,gBAAgB,IAAI,gBAAgB,CA2BnD;AAwDD,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1D,KAAK,CAAC,EAAE,gBAAgB,CAAA;CACzB,CAAA;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAOxE;AAkBD,wBAAsB,4BAA4B,CAChD,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,eAAe,CAAC,CAqC1B"}
@@ -1,10 +1,10 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { createHash } from 'node:crypto';
3
- import { chmod, lstat, mkdir, readFile } from 'node:fs/promises';
2
+ import { lstat, readFile } from 'node:fs/promises';
4
3
  import { homedir } from 'node:os';
5
4
  import { isAbsolute, join, resolve } from 'node:path';
6
5
  import { CONTRACT_VERSIONS, createComputerError } from '@crosshands/contract';
7
- import { LocalControlClient, brokerEndpoint } from '@crosshands/runtime';
6
+ import { LocalControlClient, brokerEndpoint, ensurePrivateDirectory, graphicalSessionKey } from '@crosshands/runtime';
7
+ import { unwrapBrokerResult } from './broker-result.js';
8
8
  export function localClientPaths() {
9
9
  const uid = process.getuid?.();
10
10
  const osIdentity = process.env.CROSSHANDS_OS_IDENTITY ??
@@ -16,7 +16,7 @@ export function localClientPaths() {
16
16
  process.env.SECURITYSESSIONID ??
17
17
  process.env.SESSIONNAME ??
18
18
  `interactive:${osIdentity}`;
19
- const sessionKey = createHash('sha256').update(graphicalSessionId).digest('hex').slice(0, 12);
19
+ const sessionKey = graphicalSessionKey(graphicalSessionId);
20
20
  const runtimeDirectory = process.env.CROSSHANDS_RUNTIME_DIR ?? defaultRuntimeDirectory(sessionKey);
21
21
  const identity = { osIdentity, graphicalSessionId };
22
22
  return {
@@ -48,14 +48,13 @@ function defaultRuntimeDirectory(sessionKey) {
48
48
  }
49
49
  return join(localAppData, 'CrossHands', 'runtime', sessionKey);
50
50
  }
51
- async function prepareRuntimeDirectory(path) {
52
- await mkdir(path, { recursive: true, mode: 0o700 });
53
- const info = await lstat(path);
54
- if (!info.isDirectory() || info.isSymbolicLink())
55
- throw createComputerError('provider_unavailable', 'CrossHands runtime path is unsafe');
56
- if (process.getuid !== undefined && info.uid !== process.getuid())
57
- throw createComputerError('provider_unavailable', 'CrossHands runtime path has another owner');
58
- await chmod(path, 0o700);
51
+ function prepareRuntimeDirectory(path) {
52
+ try {
53
+ ensurePrivateDirectory(path);
54
+ }
55
+ catch (cause) {
56
+ throw createComputerError('provider_unavailable', cause instanceof Error ? cause.message : 'CrossHands directory is unsafe');
57
+ }
59
58
  }
60
59
  async function readSecureToken(path) {
61
60
  const info = await lstat(path);
@@ -74,12 +73,21 @@ async function connect(paths) {
74
73
  identity: paths.identity
75
74
  });
76
75
  }
76
+ export function brokerSpawnEnv(env) {
77
+ const next = { ...env };
78
+ delete next.CROSSHANDS_JEV;
79
+ for (const key of Object.keys(next)) {
80
+ if (key === 'TYPESAFE_API_KEY' || key.startsWith('TYPESAFE_'))
81
+ delete next[key];
82
+ }
83
+ return next;
84
+ }
77
85
  function defaultSpawnBroker(entrypoint) {
78
86
  const child = spawn(process.execPath, [entrypoint, 'broker'], {
79
87
  detached: true,
80
88
  stdio: 'ignore',
81
89
  windowsHide: true,
82
- env: process.env
90
+ env: brokerSpawnEnv(process.env)
83
91
  });
84
92
  child.unref();
85
93
  }
@@ -91,7 +99,7 @@ function brokerIsAbsent(cause) {
91
99
  }
92
100
  export async function createProductionBrokerClient(options = {}) {
93
101
  const paths = options.paths ?? localClientPaths();
94
- await prepareRuntimeDirectory(paths.runtimeDirectory);
102
+ prepareRuntimeDirectory(paths.runtimeDirectory);
95
103
  try {
96
104
  const control = await connect(paths);
97
105
  return controlAdapter(control);
@@ -124,7 +132,7 @@ export async function createProductionBrokerClient(options = {}) {
124
132
  }
125
133
  function controlAdapter(control) {
126
134
  return {
127
- request: async (operation, input) => control.request({ operation, input }, { deadlineMs: 30_000 }),
135
+ request: async (operation, input) => unwrapBrokerResult(await control.request({ operation, input }, { deadlineMs: 30_000 })),
128
136
  close: () => control.close()
129
137
  };
130
138
  }
@@ -1 +1 @@
1
- {"version":3,"file":"local-client.js","sourceRoot":"","sources":["../src/local-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local-client.js","sourceRoot":"","sources":["../src/local-client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crosshands/cli",
3
- "version": "0.1.6",
3
+ "version": "0.2.1",
4
4
  "description": "Agent-agnostic local computer-use CLI",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -23,8 +23,8 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@crosshands/contract": "0.1.6",
27
- "@crosshands/runtime": "0.1.6"
26
+ "@crosshands/runtime": "0.2.1",
27
+ "@crosshands/contract": "0.2.1"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "24.10.1",
@@ -32,9 +32,9 @@
32
32
  "vitest": "4.1.5"
33
33
  },
34
34
  "optionalDependencies": {
35
- "@crosshands/platform-darwin": "0.1.6",
36
- "@crosshands/platform-windows": "0.1.6",
37
- "@crosshands/platform-linux": "0.1.6"
35
+ "@crosshands/platform-darwin": "0.2.1",
36
+ "@crosshands/platform-windows": "0.2.1",
37
+ "@crosshands/platform-linux": "0.2.1"
38
38
  },
39
39
  "engines": {
40
40
  "node": ">=22"
package/src/bin.ts CHANGED
@@ -3,9 +3,7 @@
3
3
  import { stdin, stderr, stdout } from 'node:process'
4
4
  import { StringDecoder } from 'node:string_decoder'
5
5
 
6
- import { runBrokerHost } from './broker-host.js'
7
- import { runCli, type CliIo } from './index.js'
8
- import { createProductionBrokerClient } from './local-client.js'
6
+ import type { CliIo } from './index.js'
9
7
 
10
8
  async function readStdin(): Promise<string> {
11
9
  const decoder = new StringDecoder('utf8')
@@ -25,9 +23,12 @@ async function readStdin(): Promise<string> {
25
23
  async function main(): Promise<number> {
26
24
  const argv = process.argv.slice(2)
27
25
  if (argv[0] === 'broker') {
26
+ const { runBrokerHost } = await import('./broker-host.js')
28
27
  await runBrokerHost()
29
28
  return 0
30
29
  }
30
+ const { runCli } = await import('./index.js')
31
+ const { createProductionBrokerClient } = await import('./local-client.js')
31
32
  const io: CliIo = {
32
33
  stdin: readStdin,
33
34
  stdout: (value) => stdout.write(value),
@@ -1,3 +1,5 @@
1
+ import { randomUUID } from 'node:crypto'
2
+
1
3
  import {
2
4
  CONTRACT_VERSIONS,
3
5
  createComputerError,
@@ -7,9 +9,13 @@ import {
7
9
  type ReferenceBindings
8
10
  } from '@crosshands/contract'
9
11
  import {
12
+ JsonlDiagnosticsWriter,
10
13
  LocalBroker,
11
14
  LocalControlServer,
15
+ diagnosticsDirectory,
16
+ emitDiagnostic,
12
17
  type BrokerEndpoint,
18
+ type ControlHandshakeEvent,
13
19
  type LocalControlIdentity,
14
20
  type LocalControlRequest,
15
21
  type StableAppIdentity,
@@ -25,6 +31,7 @@ type ProviderModule = {
25
31
  endpoint: BrokerEndpoint
26
32
  identity: LocalControlIdentity
27
33
  handler: (request: LocalControlRequest) => Promise<unknown>
34
+ onHandshake?: (event: ControlHandshakeEvent) => void
28
35
  }) => Promise<{ start(): Promise<void>; close(): Promise<void> }>
29
36
  inspectTarget?: (
30
37
  operation: ComputerOperationName,
@@ -76,9 +83,16 @@ export async function runBrokerHost(): Promise<void> {
76
83
  const providerModule = await loadProviderModule()
77
84
  const paths = localClientPaths()
78
85
  const peer = { ...paths.identity, verified: true, local: true }
86
+ const generation = `broker-${randomUUID()}`
87
+ const diagnostics = new JsonlDiagnosticsWriter({
88
+ directory: diagnosticsDirectory(paths.identity.graphicalSessionId),
89
+ generation
90
+ })
79
91
  const broker = new LocalBroker({
80
92
  identity: peer,
93
+ generation,
81
94
  providerFactory: () => providerModule.createProvider(),
95
+ diagnostics,
82
96
  ...(providerModule.inspectTarget === undefined
83
97
  ? {}
84
98
  : {
@@ -88,45 +102,61 @@ export async function runBrokerHost(): Promise<void> {
88
102
  ): Promise<TargetInspection | null> => providerModule.inspectTarget!(operation, input)
89
103
  })
90
104
  })
91
- await broker.connect({ peer, versions: CONTRACT_VERSIONS })
92
- const handler = async ({ payload, deadlineAt }: LocalControlRequest): Promise<unknown> => {
93
- if (payload === null || typeof payload !== 'object') throw new Error('Invalid broker request')
94
- const record = payload as Record<string, unknown>
95
- if (typeof record.operation !== 'string') throw new Error('Missing operation')
96
- const operation = record.operation as ComputerOperationName
97
- let input: unknown
98
- try {
99
- input = parseOperationInput(operation, record.input)
100
- } catch (cause) {
101
- if (cause instanceof Error && cause.name === 'ZodError') {
102
- throw createComputerError('invalid_argument', 'Invalid input for the selected operation')
105
+ try {
106
+ await broker.connect({ peer, versions: CONTRACT_VERSIONS })
107
+ const handler = async ({ payload, deadlineAt }: LocalControlRequest): Promise<unknown> => {
108
+ if (payload === null || typeof payload !== 'object') throw new Error('Invalid broker request')
109
+ const record = payload as Record<string, unknown>
110
+ if (typeof record.operation !== 'string') throw new Error('Missing operation')
111
+ const operation = record.operation as ComputerOperationName
112
+ let input: unknown
113
+ try {
114
+ input = parseOperationInput(operation, record.input)
115
+ } catch (cause) {
116
+ if (cause instanceof Error && cause.name === 'ZodError') {
117
+ throw createComputerError('invalid_argument', 'Invalid input for the selected operation')
118
+ }
119
+ throw cause
103
120
  }
104
- throw cause
121
+ return broker.request({ operation, input, deadlineMs: Math.max(1, deadlineAt - Date.now()) })
105
122
  }
106
- return broker.request({ operation, input, deadlineMs: Math.max(1, deadlineAt - Date.now()) })
123
+ const onHandshake = (event: ControlHandshakeEvent): void => {
124
+ emitDiagnostic(diagnostics, {
125
+ kind: 'client.handshake',
126
+ ...broker.diagnosticEnvelope(),
127
+ accepted: event.accepted,
128
+ requestId: event.requestId,
129
+ ...(event.code === undefined ? {} : { code: event.code })
130
+ })
131
+ }
132
+ const server =
133
+ paths.endpoint.transport === 'named-pipe'
134
+ ? await (providerModule.createControlServer?.({
135
+ endpoint: paths.endpoint,
136
+ identity: paths.identity,
137
+ handler,
138
+ onHandshake
139
+ }) ??
140
+ Promise.reject(
141
+ new Error('The Windows payload has no native DACL and peer-token control relay')
142
+ ))
143
+ : new LocalControlServer({
144
+ endpoint: paths.endpoint,
145
+ runtimeDirectory: paths.runtimeDirectory,
146
+ tokenFile: paths.tokenFile,
147
+ identity: paths.identity,
148
+ handler,
149
+ onHandshake
150
+ })
151
+ await server.start()
152
+ emitDiagnostic(diagnostics, { kind: 'broker.start', ...broker.diagnosticEnvelope() })
153
+ await new Promise<void>((resolve) => {
154
+ const stop = (): void => resolve()
155
+ process.once('SIGINT', stop)
156
+ process.once('SIGTERM', stop)
157
+ })
158
+ await server.close()
159
+ } finally {
160
+ await broker.close('signal')
107
161
  }
108
- const server =
109
- paths.endpoint.transport === 'named-pipe'
110
- ? await (providerModule.createControlServer?.({
111
- endpoint: paths.endpoint,
112
- identity: paths.identity,
113
- handler
114
- }) ??
115
- Promise.reject(
116
- new Error('The Windows payload has no native DACL and peer-token control relay')
117
- ))
118
- : new LocalControlServer({
119
- endpoint: paths.endpoint,
120
- runtimeDirectory: paths.runtimeDirectory,
121
- tokenFile: paths.tokenFile,
122
- identity: paths.identity,
123
- handler
124
- })
125
- await server.start()
126
- await new Promise<void>((resolve) => {
127
- const stop = (): void => resolve()
128
- process.once('SIGINT', stop)
129
- process.once('SIGTERM', stop)
130
- })
131
- await server.close()
132
162
  }
@@ -0,0 +1,14 @@
1
+ export type BrokerResultEnvelope = {
2
+ requestId: string
3
+ result: unknown
4
+ }
5
+
6
+ export function isBrokerResultEnvelope(value: unknown): value is BrokerResultEnvelope {
7
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) return false
8
+ const record = value as Record<string, unknown>
9
+ return typeof record.requestId === 'string' && 'result' in record
10
+ }
11
+
12
+ export function unwrapBrokerResult(value: unknown): unknown {
13
+ return isBrokerResultEnvelope(value) ? value.result : value
14
+ }