mandala-computer-mcp 0.1.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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +544 -0
  3. package/dist/api.d.ts +186 -0
  4. package/dist/api.d.ts.map +1 -0
  5. package/dist/api.js +932 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli.d.ts +55 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +292 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/errors.d.ts +560 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +873 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/events.d.ts +406 -0
  16. package/dist/events.d.ts.map +1 -0
  17. package/dist/events.js +1679 -0
  18. package/dist/events.js.map +1 -0
  19. package/dist/format.d.ts +125 -0
  20. package/dist/format.d.ts.map +1 -0
  21. package/dist/format.js +180 -0
  22. package/dist/format.js.map +1 -0
  23. package/dist/http.d.ts +46 -0
  24. package/dist/http.d.ts.map +1 -0
  25. package/dist/http.js +792 -0
  26. package/dist/http.js.map +1 -0
  27. package/dist/index.d.ts +13 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +12 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/paths.d.ts +394 -0
  32. package/dist/paths.d.ts.map +1 -0
  33. package/dist/paths.js +677 -0
  34. package/dist/paths.js.map +1 -0
  35. package/dist/server.d.ts +18 -0
  36. package/dist/server.d.ts.map +1 -0
  37. package/dist/server.js +97 -0
  38. package/dist/server.js.map +1 -0
  39. package/dist/session.d.ts +78 -0
  40. package/dist/session.d.ts.map +1 -0
  41. package/dist/session.js +166 -0
  42. package/dist/session.js.map +1 -0
  43. package/dist/stdio.d.ts +11 -0
  44. package/dist/stdio.d.ts.map +1 -0
  45. package/dist/stdio.js +43 -0
  46. package/dist/stdio.js.map +1 -0
  47. package/dist/tools/agent.d.ts +16 -0
  48. package/dist/tools/agent.d.ts.map +1 -0
  49. package/dist/tools/agent.js +147 -0
  50. package/dist/tools/agent.js.map +1 -0
  51. package/dist/tools/computers.d.ts +3 -0
  52. package/dist/tools/computers.d.ts.map +1 -0
  53. package/dist/tools/computers.js +1037 -0
  54. package/dist/tools/computers.js.map +1 -0
  55. package/dist/tools/events.d.ts +3 -0
  56. package/dist/tools/events.d.ts.map +1 -0
  57. package/dist/tools/events.js +1077 -0
  58. package/dist/tools/events.js.map +1 -0
  59. package/dist/tools/guest.d.ts +3 -0
  60. package/dist/tools/guest.d.ts.map +1 -0
  61. package/dist/tools/guest.js +761 -0
  62. package/dist/tools/guest.js.map +1 -0
  63. package/dist/tools/input.d.ts +3 -0
  64. package/dist/tools/input.d.ts.map +1 -0
  65. package/dist/tools/input.js +240 -0
  66. package/dist/tools/input.js.map +1 -0
  67. package/dist/tools/snapshots.d.ts +3 -0
  68. package/dist/tools/snapshots.d.ts.map +1 -0
  69. package/dist/tools/snapshots.js +333 -0
  70. package/dist/tools/snapshots.js.map +1 -0
  71. package/dist/tools/templates.d.ts +3 -0
  72. package/dist/tools/templates.d.ts.map +1 -0
  73. package/dist/tools/templates.js +492 -0
  74. package/dist/tools/templates.js.map +1 -0
  75. package/dist/tools/types.d.ts +18 -0
  76. package/dist/tools/types.d.ts.map +1 -0
  77. package/dist/tools/types.js +2 -0
  78. package/dist/tools/types.js.map +1 -0
  79. package/dist/tools/webhooks.d.ts +3 -0
  80. package/dist/tools/webhooks.d.ts.map +1 -0
  81. package/dist/tools/webhooks.js +260 -0
  82. package/dist/tools/webhooks.js.map +1 -0
  83. package/package.json +59 -0
@@ -0,0 +1,147 @@
1
+ import { z } from 'zod';
2
+ import { MODEL_KEY_HEADER } from '../api.js';
3
+ import { guarded, refused, said } from '../format.js';
4
+ import * as P from '../paths.js';
5
+ /**
6
+ * The platform's own agent loop, as one tool.
7
+ *
8
+ * Registered only when a model key is configured, and that is the point of the
9
+ * conditional: a tool a model can see is a tool it will try, and one that fails
10
+ * on every call with "no model key" costs a turn to discover. Absent is a
11
+ * clearer answer than present-and-broken.
12
+ *
13
+ * Worth having even though the caller is already a model with eyes. The outer
14
+ * agent pays for every screenshot in context; this route runs the pixel-level
15
+ * loop inside the platform on the caller's own Anthropic key and hands back a
16
+ * sentence. Ten clicks stop being ten images.
17
+ */
18
+ export const registerAgent = (server, session) => {
19
+ if (!session.modelKey)
20
+ return;
21
+ server.registerTool('run_agent', {
22
+ title: 'Have the platform drive the computer',
23
+ description: 'Give the computer a task in plain language and let the platform drive it — screenshot, decide, click, type, repeat — until it is done. Runs on the Anthropic key this server was configured with, and bills that key for every step. Use it to delegate a long stretch of pixel work; drive with the individual tools when you want to see each frame yourself. The computer must already be running. A run is MINUTES, not seconds: it reports progress on every step so a client that sends a progressToken and sets resetTimeoutOnProgress can hold the request open, and a client that cannot should lower max_steps rather than watch its own default timeout cancel a run it is already paying for.',
24
+ inputSchema: {
25
+ computer_id: z
26
+ .string()
27
+ .optional()
28
+ .describe('Which computer. Defaults to the one selected with use_computer.'),
29
+ prompt: z.string().describe('The task, in plain language.'),
30
+ system: z.string().optional().describe('Standing instructions carried into the run.'),
31
+ max_steps: z
32
+ .number()
33
+ .int()
34
+ .min(1)
35
+ .max(100)
36
+ .default(20)
37
+ .describe('Each step is a model call plus a screenshot on your key, so this is a spending cap as much as a loop bound.'),
38
+ },
39
+ annotations: { openWorldHint: true },
40
+ }, ({ computer_id, prompt, system, max_steps }, extra) => guarded(async () => {
41
+ const id = session.resolve(computer_id);
42
+ const steps = [];
43
+ let done;
44
+ // The token the CLIENT sends when it wants progress, exactly as
45
+ // watch_build reads it. Without one there is nothing to address a
46
+ // progress notification to, and this falls back to logging alone.
47
+ const progressToken = extra._meta?.progressToken;
48
+ for await (const ev of session.api.sse('POST', P.computerAction(id, 'agent'), {
49
+ body: P.agentBody({ prompt, system, max_steps, stream: true }),
50
+ headers: { [MODEL_KEY_HEADER]: session.modelKey },
51
+ signal: extra.signal,
52
+ })) {
53
+ if (ev.event === 'step') {
54
+ if (!isRecord(ev.data))
55
+ continue;
56
+ const s = ev.data;
57
+ steps.push(`${s.n ?? steps.length + 1}. ${s.detail ?? s.action ?? 'step'}`);
58
+ // A PROGRESS notification, not only a logging one, for the reason
59
+ // watch_build sends one: `_onprogress` in the SDK's
60
+ // shared/protocol.js resets a pending request's timer, and
61
+ // `notifications/message` — what sendLoggingMessage emits — never
62
+ // touches it. This tool had only the logging half, so a run of the
63
+ // default 20 steps, each a model call plus a screenshot, sailed past
64
+ // the client's 60s default and was cancelled while the platform went
65
+ // on driving the desktop on the caller's own Anthropic key.
66
+ //
67
+ // Not sufficient on its own, and the same caveat applies here as
68
+ // there: protocol.js reads `options?.resetTimeoutOnProgress ?? false`,
69
+ // so a client that mints a token and leaves that option alone is
70
+ // still cancelled. What this does is make the keepalive AVAILABLE.
71
+ // The description says so, and max_steps is the lever for a client
72
+ // that cannot opt in.
73
+ if (progressToken !== undefined) {
74
+ await extra
75
+ .sendNotification({
76
+ method: 'notifications/progress',
77
+ params: {
78
+ progressToken,
79
+ // The step COUNT, which the SDK's ProgressSchema asks to
80
+ // increase every time. `max_steps` is a real total here —
81
+ // unlike a build's step count it is known before the first
82
+ // step and cannot change — so the bar means something.
83
+ progress: steps.length,
84
+ total: max_steps,
85
+ message: steps[steps.length - 1],
86
+ },
87
+ })
88
+ .catch(() => { });
89
+ }
90
+ // Told, not just collected. A run is minutes of clicking, and a tool
91
+ // that says nothing until it is over is one nobody watching can tell
92
+ // from a hang.
93
+ await server.server
94
+ .sendLoggingMessage({ level: 'info', data: steps[steps.length - 1] })
95
+ .catch(() => { });
96
+ }
97
+ else if (ev.event === 'done') {
98
+ // Stop at the terminal frame rather than waiting for EOF, as
99
+ // watch_build does. Waiting held a result that was already in hand
100
+ // until the generator ended, so a client that aborted in that window
101
+ // — or a stream the platform left open — turned a finished run into
102
+ // a CancelledError and threw the answer away.
103
+ //
104
+ // Terminal means it SAYS SO, which is watch_build's discipline
105
+ // (OPL-3835) applied to this stream's own vocabulary: `stop` is the
106
+ // field the platform always sends on a result — the AgentResult type
107
+ // in its lib/agent.ts requires it, and every `done` it yields carries
108
+ // one — and it is the field the verdict below reads. A record
109
+ // without it is not a result, so it is kept, in case nothing better
110
+ // arrives, but it does not end the loop and discard the frame that
111
+ // would have been the real one. A `done` that is not a record at all
112
+ // is skipped entirely: the null-done case the regression suite pins.
113
+ if (isRecord(ev.data)) {
114
+ done = ev.data;
115
+ if (typeof ev.data.stop === 'string' && ev.data.stop)
116
+ break;
117
+ }
118
+ }
119
+ else if (ev.event === 'error') {
120
+ // A run that errored is a failure, and has to carry `isError` to
121
+ // say so. Prose alone leaves it indistinguishable at the protocol
122
+ // level from a run that worked — a caller checking whether the step
123
+ // succeeded would read this one as a success that happened to have
124
+ // a discouraging sentence in it.
125
+ return refused(`The run failed after ${steps.length} step(s).`, ev.data);
126
+ }
127
+ }
128
+ if (!done) {
129
+ return refused(`The stream ended without a result after ${steps.length} step(s). What it did:\n${steps.join('\n')}`);
130
+ }
131
+ // `stop` is the field that matters and the one a caller most easily
132
+ // ignores: a run that hit max_steps ended without finishing, and
133
+ // treating every ending as success reports a failure as a result.
134
+ const stop = String(done.stop ?? 'unknown');
135
+ const verdict = stop === 'end_turn'
136
+ ? 'finished'
137
+ : stop === 'max_steps'
138
+ ? `RAN OUT OF STEPS after ${done.steps ?? max_steps} — the task is probably unfinished`
139
+ : stop === 'refusal'
140
+ ? 'the model declined the task'
141
+ : `ended: ${stop}`;
142
+ const result = `${verdict}\n\n${String(done.text ?? '')}\n\nWhat it did:\n${steps.join('\n')}`;
143
+ return stop === 'end_turn' ? said(result, done) : refused(result, done);
144
+ }));
145
+ };
146
+ const isRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
147
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/tools/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Registrar } from './types.js';
2
+ export declare const registerComputers: Registrar;
3
+ //# sourceMappingURL=computers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computers.d.ts","sourceRoot":"","sources":["../../src/tools/computers.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA8P5C,eAAO,MAAM,iBAAiB,EAAE,SA6iC/B,CAAC"}