@agimon-ai/po-computer-use 0.0.0-alpha.30 → 0.0.0-alpha.32

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.
@@ -1,19 +1,47 @@
1
- import { defineActivityGroup, defineChannelFile, defineNativePlugin, defineSessionStore } from "@agimon-ai/po-core/native";
1
+ import { createApiClient, defineActivityGroup, defineChannelFile, defineFill, defineNativePlugin, defineSessionStore, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
2
+ import { View } from "react-native-unistyles/components/native/View";
3
+ import { Text } from "react-native-unistyles/components/native/Text";
4
+ import { Button, fontOf } from "@agimon-ai/po-native-components";
5
+ import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
6
+ import { StyleSheet } from "react-native-unistyles";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
8
  //#region src/types/computerUseApi.ts
3
9
  const computerUseChannelType = "computer_use_state";
10
+ const COMPUTER_USE_STATUS_KEY = "po-computer-use";
11
+ const COMPUTER_USE_DEFAULT_DURATION_MS = 3e5;
12
+ /**
13
+ * Every path this API answers on, below its mount.
14
+ *
15
+ * The typed route table in `./apiRoutes` is built from this, the dispatcher
16
+ * reads that table, and the hub channel addresses the broker with these same
17
+ * strings, so a route cannot move on one side alone.
18
+ */
19
+ const COMPUTER_USE_ROUTES = {
20
+ activate: "/activate",
21
+ artifact: "/artifact",
22
+ agentState: "/agent/state",
23
+ agentObserve: "/agent/observe",
24
+ agentAction: "/agent/action",
25
+ agentStop: "/agent/stop",
26
+ hubState: "/hub/state",
27
+ hubActivation: "/hub/activation",
28
+ hubAuthorization: "/hub/authorization",
29
+ hubNext: "/hub/next",
30
+ hubComplete: "/hub/complete",
31
+ hubStop: "/hub/stop"
32
+ };
4
33
  //#endregion
5
34
  //#region src/extensions/workspaces/sessions/(frontend)/activity-group/computer-use.native.ts
6
- /** Computer control remains a desktop capability, including when its status is reported to a phone. */
35
+ /** Remote clients request control from the Desktop host through their session Activity. */
7
36
  var computer_use_native_default$1 = defineActivityGroup({
8
37
  name: "computer-use",
9
38
  keys: "c e",
10
39
  order: 70,
11
- statusKey: "po-computer-use",
40
+ statusKey: COMPUTER_USE_STATUS_KEY,
12
41
  hideWhenEmpty: true,
13
- desktopOnly: true,
14
42
  marksBackgroundWork: false
15
43
  });
16
- const computerUse = defineSessionStore({
44
+ const computerUse$1 = defineSessionStore({
17
45
  state: {
18
46
  sessionId: "",
19
47
  revision: 0,
@@ -25,7 +53,7 @@ const computerUse = defineSessionStore({
25
53
  function isRecord(value) {
26
54
  return typeof value === "object" && value !== null && !Array.isArray(value);
27
55
  }
28
- const computerUseChannel = computerUse.channel({
56
+ const computerUseChannel = computerUse$1.channel({
29
57
  channel: computerUseChannelType,
30
58
  parse(input) {
31
59
  if (!isRecord(input) || !isRecord(input.state) || !Array.isArray(input.targets)) return null;
@@ -38,6 +66,309 @@ const computerUseChannel = computerUse.channel({
38
66
  //#region src/extensions/workspaces/sessions/(frontend)/channel/computer-use.native.ts
39
67
  var computer_use_native_default = defineChannelFile(computerUseChannel);
40
68
  //#endregion
69
+ //#region src/types/apiRoutes.ts
70
+ /**
71
+ * This package's routes, as data.
72
+ *
73
+ * No scope and no base path: the build reads both off
74
+ * `src/extensions/workspaces/sessions/(backend)/api/computer-use/`, so the
75
+ * mount is stated once, by the folder that creates it.
76
+ *
77
+ * The paths come from `COMPUTER_USE_ROUTES` rather than being written out
78
+ * again. That table already addressed the broker from the hub channel and from
79
+ * the broker's own dispatcher, and a second copy here is exactly the
80
+ * disagreement this file exists to prevent. The dispatcher now reads this
81
+ * table, so the page, the broker and the hub all resolve one set of strings.
82
+ *
83
+ * Activation, status, cancellation and recording reads are reachable from a browser. The `/agent/` and `/hub/` routes
84
+ * each demand a host-issued bearer token and answer 404 without one; they are
85
+ * declared here because they are this API's surface, not because a page calls
86
+ * them.
87
+ */
88
+ const routes = {
89
+ artifact: {
90
+ method: "GET",
91
+ path: COMPUTER_USE_ROUTES.artifact,
92
+ query: ["artifactId", "offset"],
93
+ raw: true
94
+ },
95
+ activationState: {
96
+ method: "GET",
97
+ path: COMPUTER_USE_ROUTES.activate,
98
+ response: void 0
99
+ },
100
+ cancelActivation: {
101
+ method: "DELETE",
102
+ path: COMPUTER_USE_ROUTES.activate,
103
+ response: void 0
104
+ },
105
+ activate: {
106
+ method: "POST",
107
+ path: COMPUTER_USE_ROUTES.activate,
108
+ response: void 0
109
+ },
110
+ agentState: {
111
+ method: "GET",
112
+ path: COMPUTER_USE_ROUTES.agentState,
113
+ response: void 0
114
+ },
115
+ /** Answers whatever the admitted Desktop provider returned, which is runtime-defined JSON. */
116
+ agentObserve: {
117
+ method: "POST",
118
+ path: COMPUTER_USE_ROUTES.agentObserve,
119
+ response: void 0
120
+ },
121
+ agentAction: {
122
+ method: "POST",
123
+ path: COMPUTER_USE_ROUTES.agentAction,
124
+ response: void 0
125
+ },
126
+ agentStop: {
127
+ method: "POST",
128
+ path: COMPUTER_USE_ROUTES.agentStop,
129
+ response: void 0
130
+ },
131
+ hubState: {
132
+ method: "GET",
133
+ path: COMPUTER_USE_ROUTES.hubState,
134
+ response: void 0
135
+ },
136
+ /** Null until a reader has confirmed one; reading it moves the session to `activating`. */
137
+ hubActivation: {
138
+ method: "GET",
139
+ path: COMPUTER_USE_ROUTES.hubActivation,
140
+ response: void 0
141
+ },
142
+ hubAuthorization: {
143
+ method: "GET",
144
+ path: COMPUTER_USE_ROUTES.hubAuthorization,
145
+ response: void 0
146
+ },
147
+ hubNext: {
148
+ method: "GET",
149
+ path: COMPUTER_USE_ROUTES.hubNext,
150
+ response: void 0
151
+ },
152
+ hubComplete: {
153
+ method: "POST",
154
+ path: COMPUTER_USE_ROUTES.hubComplete,
155
+ response: void 0
156
+ },
157
+ hubStop: {
158
+ method: "POST",
159
+ path: COMPUTER_USE_ROUTES.hubStop,
160
+ response: void 0
161
+ },
162
+ /** Desktop's macOS permission states, served by the hub's `desktop-permissions` mount. */
163
+ desktopPermissions: {
164
+ method: "GET",
165
+ path: "/",
166
+ response: void 0
167
+ },
168
+ /** Asks macOS for the body's permission on the Mac running Desktop; answers the states after. */
169
+ requestDesktopPermission: {
170
+ method: "POST",
171
+ path: "/",
172
+ response: void 0
173
+ }
174
+ };
175
+ const computerUse = createApiClient(routes, {
176
+ scopes: ["session"],
177
+ basePath: "computer-use",
178
+ transport: nativeApiTransport,
179
+ sessionAddress: sessionApiAddress
180
+ });
181
+ createApiClient(routes, {
182
+ scopes: [
183
+ "global",
184
+ "workspace",
185
+ "session"
186
+ ],
187
+ basePath: "desktop-permissions",
188
+ transport: nativeApiTransport,
189
+ sessionAddress: sessionApiAddress
190
+ });
191
+ //#endregion
192
+ //#region src/extensions/workspaces/sessions/(frontend)/fill/_components/ComputerUsePanel.native.tsx
193
+ function ComputerUseView({ state, busy = false, error, submitting = false, onActivate, onCancel, onStop }) {
194
+ const pending = state.phase === "awaiting_confirmation" || state.phase === "activating";
195
+ const active = state.phase === "active" || state.phase === "stopping";
196
+ const failure = error ?? state.failure?.message;
197
+ return /* @__PURE__ */ jsxs(View, {
198
+ style: styles.panel,
199
+ children: [
200
+ /* @__PURE__ */ jsx(Text, {
201
+ style: styles.detail,
202
+ accessibilityLiveRegion: "polite",
203
+ children: state.phase.replaceAll("_", " ")
204
+ }),
205
+ busy ? /* @__PURE__ */ jsx(Text, {
206
+ style: styles.detail,
207
+ children: "Computer use is busy in another session."
208
+ }) : null,
209
+ failure ? /* @__PURE__ */ jsx(Text, {
210
+ style: styles.error,
211
+ accessibilityRole: "alert",
212
+ children: failure
213
+ }) : null,
214
+ pending ? /* @__PURE__ */ jsxs(Fragment, { children: [
215
+ /* @__PURE__ */ jsx(Text, {
216
+ style: styles.text,
217
+ children: "Desktop activation is pending."
218
+ }),
219
+ /* @__PURE__ */ jsx(Text, {
220
+ style: styles.detail,
221
+ children: "Choose and confirm an application window on your Mac."
222
+ }),
223
+ /* @__PURE__ */ jsx(Button, {
224
+ variant: "outline",
225
+ disabled: submitting,
226
+ onPress: onCancel,
227
+ children: "Cancel activation"
228
+ })
229
+ ] }) : active ? /* @__PURE__ */ jsxs(Fragment, { children: [state.target ? /* @__PURE__ */ jsx(Text, {
230
+ style: styles.text,
231
+ children: `${typeof state.target.applicationName === "string" ? state.target.applicationName : "Application"}: ${typeof state.target.windowTitle === "string" ? state.target.windowTitle : "Window"}`
232
+ }) : null, /* @__PURE__ */ jsx(Button, {
233
+ variant: "outline",
234
+ disabled: submitting || state.phase === "stopping",
235
+ onPress: onStop,
236
+ children: "Stop computer use"
237
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text, {
238
+ style: styles.detail,
239
+ children: "Request 5 minutes of control. Your Mac asks you to choose and confirm a window."
240
+ }), /* @__PURE__ */ jsx(Button, {
241
+ variant: "primary",
242
+ disabled: busy || submitting,
243
+ onPress: onActivate,
244
+ children: "Choose window on Mac"
245
+ })] })
246
+ ]
247
+ });
248
+ }
249
+ function SessionPanel({ sessionId, sendSessionFrame }) {
250
+ const subscribe = useCallback((listener) => {
251
+ const subscription = computerUse$1.store.subscribe(listener);
252
+ return () => subscription.unsubscribe();
253
+ }, []);
254
+ const session = useSyncExternalStore(subscribe, () => computerUse$1.select(computerUse$1.store.state, sessionId));
255
+ const [error, setError] = useState();
256
+ const [submitting, setSubmitting] = useState(false);
257
+ const requests = useRef(null);
258
+ const update = (state) => computerUse$1.update(sessionId, (current) => state.revision >= current.state.revision ? {
259
+ ...current,
260
+ state
261
+ } : current);
262
+ useEffect(() => {
263
+ const controller = new AbortController();
264
+ requests.current = controller;
265
+ let timer;
266
+ sendSessionFrame(sessionId, {
267
+ type: computerUseChannelType,
268
+ payload: { action: "status" }
269
+ });
270
+ const poll = async () => {
271
+ try {
272
+ const result = await computerUse.session(sessionId).activationState({ signal: controller.signal });
273
+ if (result.ok && !controller.signal.aborted) computerUse$1.update(sessionId, (current) => result.data.revision >= current.state.revision ? {
274
+ ...current,
275
+ state: result.data
276
+ } : current);
277
+ } catch {
278
+ if (!controller.signal.aborted) setError("The session is unreachable.");
279
+ }
280
+ if (!controller.signal.aborted) timer = setTimeout(() => void poll(), 2e3);
281
+ };
282
+ poll();
283
+ return () => {
284
+ controller.abort();
285
+ clearTimeout(timer);
286
+ };
287
+ }, [sessionId, sendSessionFrame]);
288
+ const submit = async (action) => {
289
+ const signal = requests.current?.signal;
290
+ if (!signal || signal.aborted || submitting) return;
291
+ setError(void 0);
292
+ setSubmitting(true);
293
+ try {
294
+ const client = computerUse.session(sessionId);
295
+ const result = action === "activate" ? await client.activate({
296
+ body: { durationMs: COMPUTER_USE_DEFAULT_DURATION_MS },
297
+ signal
298
+ }) : await client.cancelActivation({ signal });
299
+ if (signal.aborted) return;
300
+ if (result.ok) update(result.data);
301
+ else setError(result.status === 0 ? "The session is unreachable." : result.error || "The activation request failed.");
302
+ } catch {
303
+ if (!signal.aborted) setError("The activation request is unavailable.");
304
+ } finally {
305
+ if (!signal.aborted) setSubmitting(false);
306
+ }
307
+ };
308
+ return /* @__PURE__ */ jsx(ComputerUseView, {
309
+ state: session.state,
310
+ busy: session.busy,
311
+ error,
312
+ submitting,
313
+ onActivate: () => void submit("activate"),
314
+ onCancel: () => void submit("cancel"),
315
+ onStop: () => {
316
+ setError(void 0);
317
+ try {
318
+ sendSessionFrame(sessionId, {
319
+ type: computerUseChannelType,
320
+ payload: { action: "stop" }
321
+ });
322
+ } catch {
323
+ setError("The stop request is unavailable.");
324
+ }
325
+ }
326
+ });
327
+ }
328
+ function ComputerUsePanel(props) {
329
+ return props.sessionId === null ? /* @__PURE__ */ jsx(Text, {
330
+ style: styles.detail,
331
+ children: "Select a session."
332
+ }) : /* @__PURE__ */ jsx(SessionPanel, {
333
+ ...props,
334
+ sessionId: props.sessionId
335
+ }, props.sessionId);
336
+ }
337
+ const styles = StyleSheet.create((theme) => ({
338
+ panel: {
339
+ gap: theme.spacing(3),
340
+ uni__dependencies: [0]
341
+ },
342
+ text: {
343
+ fontFamily: fontOf(theme.fontFamily.sans),
344
+ fontSize: theme.fontSize.base,
345
+ lineHeight: theme.lineHeightRelaxed.base,
346
+ color: theme.colors.text,
347
+ uni__dependencies: [0]
348
+ },
349
+ detail: {
350
+ fontFamily: fontOf(theme.fontFamily.sans),
351
+ fontSize: theme.fontSize.sm,
352
+ lineHeight: theme.lineHeightRelaxed.sm,
353
+ color: theme.colors.dim,
354
+ uni__dependencies: [0]
355
+ },
356
+ error: {
357
+ fontFamily: fontOf(theme.fontFamily.sans),
358
+ fontSize: theme.fontSize.base,
359
+ lineHeight: theme.lineHeightRelaxed.base,
360
+ color: theme.colors.red,
361
+ uni__dependencies: [0]
362
+ }
363
+ }));
364
+ //#endregion
365
+ //#region src/extensions/workspaces/sessions/(frontend)/fill/ComputerUse.activity.computer-use.native.tsx
366
+ var ComputerUse_activity_computer_use_native_default = defineFill({
367
+ id: "computer-use",
368
+ slot: "activity.computer-use",
369
+ component: ComputerUsePanel
370
+ });
371
+ //#endregion
41
372
  //#region generated/native.ts
42
373
  const via = (identity, value) => value === void 0 ? void 0 : {
43
374
  ...identity,
@@ -51,6 +382,12 @@ const nativePlugin = defineNativePlugin({
51
382
  },
52
383
  get channels() {
53
384
  return [via({ channel: "computer_use" }, computer_use_native_default)];
385
+ },
386
+ get fills() {
387
+ return [via({
388
+ slot: "activity.computer-use",
389
+ id: "computer-use"
390
+ }, ComputerUse_activity_computer_use_native_default)];
54
391
  }
55
392
  }
56
393
  });
@@ -1 +1 @@
1
- {"version":3,"file":"native.mjs","names":["activityGroupComputerUse","channelComputerUse"],"sources":["../../src/types/computerUseApi.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/computer-use.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/computerUseStore.native.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/computer-use.native.ts","../../generated/native.ts"],"sourcesContent":["import type { PoApiCaller } from '@agimon-ai/po-core/packageApi';\n\nexport const API_BASE_PATH = 'computer-use';\nexport const computerUseChannelType = 'computer_use_state';\nexport const COMPUTER_USE_MODE_ID = 'computer-use';\nexport const COMPUTER_USE_STATUS_KEY = 'po-computer-use';\nexport const COMPUTER_USE_MODE_STATUS_KEY = 'po-computer-use-mode';\nexport const COMPUTER_USE_MAX_DURATION_MS = 1_800 * 1_000;\nexport const COMPUTER_USE_DEFAULT_DURATION_MS = 300 * 1_000;\nexport const COMPUTER_USE_CONFIRMATION_WINDOW_MS = 2 * 60 * 1_000;\n\n/**\n * Every path this API answers on, below its mount.\n *\n * The typed route table in `./apiRoutes` is built from this, the dispatcher\n * reads that table, and the hub channel addresses the broker with these same\n * strings, so a route cannot move on one side alone.\n */\nexport const COMPUTER_USE_ROUTES = {\n activate: '/activate',\n artifact: '/artifact',\n agentState: '/agent/state',\n agentObserve: '/agent/observe',\n agentAction: '/agent/action',\n agentStop: '/agent/stop',\n hubState: '/hub/state',\n hubActivation: '/hub/activation',\n hubAuthorization: '/hub/authorization',\n hubNext: '/hub/next',\n hubComplete: '/hub/complete',\n hubStop: '/hub/stop',\n} as const;\n\nexport const COMPUTER_USE_WAKE_LIMIT = 1_000_000;\n\nexport interface ComputerUseArtifactView {\n readonly artifactId: string;\n readonly status: 'ready' | 'failed';\n readonly sizeBytes?: number;\n readonly downloadUrl?: string;\n readonly previewUrl?: string;\n readonly actionCount?: number;\n readonly completedAt?: string;\n readonly failure?: { readonly code: string; readonly message: string };\n}\n\nexport interface ComputerUseSessionView {\n readonly sessionId: string;\n readonly revision: number;\n readonly wake: number;\n readonly phase: 'inactive' | 'awaiting_confirmation' | 'activating' | 'active' | 'stopping' | 'failed';\n readonly requestId?: string;\n readonly target?: Record<string, unknown>;\n readonly durationMs?: number;\n readonly expiresAt?: number;\n readonly failure?: { readonly code: string; readonly message: string };\n readonly artifact?: ComputerUseArtifactView;\n}\n\nexport interface ComputerUseActivationRequest {\n readonly requestId: string;\n readonly target?: Record<string, unknown>;\n readonly durationSeconds: number;\n readonly createdAt: number;\n readonly confirmationExpiresAt: number;\n readonly caller: PoApiCaller;\n}\n\nexport interface ComputerUseBrokerRequest {\n readonly id: string;\n readonly operation: 'observe' | 'act';\n readonly payload?: unknown;\n readonly grantId: string;\n readonly sequence?: number;\n}\n\nexport interface ComputerUseChannelPayload {\n readonly state: ComputerUseSessionView;\n readonly targets: readonly Record<string, unknown>[];\n readonly busy?: true;\n}\n\nexport type ComputerUseBrowserCommand = { readonly action: 'status' | 'targets' | 'stop' | 'artifacts' };\n","import { defineActivityGroup } from '@agimon-ai/po-core/native';\n\nimport { COMPUTER_USE_STATUS_KEY } from '../../../../../types/computerUseApi';\n\n/** Computer control remains a desktop capability, including when its status is reported to a phone. */\nexport default defineActivityGroup({\n name: 'computer-use',\n keys: 'c e',\n order: 70,\n statusKey: COMPUTER_USE_STATUS_KEY,\n hideWhenEmpty: true,\n desktopOnly: true,\n marksBackgroundWork: false,\n});\n","import { defineSessionStore } from '@agimon-ai/po-core/native';\n\nimport { computerUseChannelType } from '../../../../../types/computerUseApi';\nimport type { ComputerUseChannelPayload } from '../../../../../types/computerUseApi';\n\nexport interface ComputerUseSession extends ComputerUseChannelPayload {}\n\nconst initialState: ComputerUseSession = {\n state: { sessionId: '', revision: 0, wake: 0, phase: 'inactive' },\n targets: [],\n};\n\nexport const computerUse = defineSessionStore<ComputerUseSession>(initialState);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport const computerUseChannel = computerUse.channel<ComputerUseChannelPayload>({\n channel: computerUseChannelType,\n parse(input) {\n if (!isRecord(input) || !isRecord(input.state) || !Array.isArray(input.targets)) return null;\n if (typeof input.state.phase !== 'string' || typeof input.state.revision !== 'number') return null;\n return input as unknown as ComputerUseChannelPayload;\n },\n reduce: (_current, payload) => payload,\n});\n","import { defineChannelFile } from '@agimon-ai/po-core/native';\n\nimport { computerUseChannel } from '../_lib/computerUseStore.native';\n\nexport default defineChannelFile(computerUseChannel);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineNativePlugin, type WebPluginContributions } from '@agimon-ai/po-core/native';\n\nimport activityGroupComputerUse from '../src/extensions/workspaces/sessions/(frontend)/activity-group/computer-use.native';\nimport channelComputerUse from '../src/extensions/workspaces/sessions/(frontend)/channel/computer-use.native';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const nativePlugin = defineNativePlugin({\n id: 'computer-use',\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'computer-use' }, activityGroupComputerUse)]; },\n get channels(): WebPluginContributions['channels'] { return [via({ channel: 'computer_use' }, channelComputerUse)]; },\n },\n});\n"],"mappings":";;AAGA,MAAa,yBAAyB;;;;ACEtC,IAAA,gCAAe,oBAAoB;CACjC,MAAM;CACN,MAAM;CACN,OAAO;CACP,WAAW;CACX,eAAe;CACf,aAAa;CACb,qBAAqB;AACvB,CAAC;ACDD,MAAa,cAAc,mBAAuC;CAJhE,OAAO;EAAE,WAAW;EAAI,UAAU;EAAG,MAAM;EAAG,OAAO;CAAW;CAChE,SAAS,CAAC;AAGsD,CAAY;AAE9E,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,MAAa,qBAAqB,YAAY,QAAmC;CAC/E,SAAS;CACT,MAAM,OAAO;EACX,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,MAAM,KAAK,KAAK,CAAC,MAAM,QAAQ,MAAM,OAAO,GAAG,OAAO;EACxF,IAAI,OAAO,MAAM,MAAM,UAAU,YAAY,OAAO,MAAM,MAAM,aAAa,UAAU,OAAO;EAC9F,OAAO;CACT;CACA,SAAS,UAAU,YAAY;AACjC,CAAC;;;ACtBD,IAAA,8BAAe,kBAAkB,kBAAkB;;;ACEnD,MAAM,OAAU,UAAmC,UAChD,UAAU,KAAA,IAAY,KAAA,IAAY;CAAE,GAAG;CAAU,GAAI;AAAiB;AAEzE,MAAa,eAAe,mBAAmB;CAC7C,IAAI;CACJ,SAAS;EACP,IAAI,iBAA2D;GAAE,OAAO,CAAC,IAAI,EAAE,MAAM,eAAe,GAAGA,6BAAwB,CAAC;EAAG;EACnI,IAAI,WAA+C;GAAE,OAAO,CAAC,IAAI,EAAE,SAAS,eAAe,GAAGC,2BAAkB,CAAC;EAAG;CACtH;AACF,CAAC"}
1
+ {"version":3,"file":"native.mjs","names":["computerUse","WebPluginSlotProps","Button","fontOf","PoNativeTheme","useCallback","useEffect","useRef","useState","useSyncExternalStore","StyleSheet","computerUse","api","COMPUTER_USE_DEFAULT_DURATION_MS","computerUseChannelType","ComputerUseSessionView","ComputerUseView","state","busy","error","submitting","onActivate","onCancel","onStop","pending","phase","active","failure","message","styles","panel","detail","replaceAll","text","target","applicationName","windowTitle","SessionPanel","sessionId","sendSessionFrame","subscribe","listener","subscription","store","unsubscribe","session","select","setError","setSubmitting","requests","AbortController","update","current","revision","controller","timer","ReturnType","setTimeout","type","payload","action","poll","result","activationState","signal","ok","aborted","data","abort","clearTimeout","submit","undefined","client","activate","body","durationMs","cancelActivation","status","ComputerUsePanel","props","create","theme","gap","spacing","uni__dependencies","fontFamily","sans","fontSize","base","lineHeight","lineHeightRelaxed","color","colors","sm","dim","red","computerUse","api","activityGroupComputerUse","channelComputerUse","fillComputerUse"],"sources":["../../src/types/computerUseApi.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/computer-use.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/computerUseStore.native.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/computer-use.native.ts","../../src/types/apiRoutes.ts","../../generated/client.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/ComputerUsePanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/ComputerUse.activity.computer-use.native.tsx","../../generated/native.ts"],"sourcesContent":["import type { PoApiCaller } from '@agimon-ai/po-core/packageApi';\n\nexport const API_BASE_PATH = 'computer-use';\nexport const computerUseChannelType = 'computer_use_state';\nexport const COMPUTER_USE_MODE_ID = 'computer-use';\nexport const COMPUTER_USE_STATUS_KEY = 'po-computer-use';\nexport const COMPUTER_USE_MODE_STATUS_KEY = 'po-computer-use-mode';\nexport const COMPUTER_USE_MAX_DURATION_MS = 1_800 * 1_000;\nexport const COMPUTER_USE_DEFAULT_DURATION_MS = 300 * 1_000;\nexport const COMPUTER_USE_CONFIRMATION_WINDOW_MS = 2 * 60 * 1_000;\n\n/**\n * Every path this API answers on, below its mount.\n *\n * The typed route table in `./apiRoutes` is built from this, the dispatcher\n * reads that table, and the hub channel addresses the broker with these same\n * strings, so a route cannot move on one side alone.\n */\nexport const COMPUTER_USE_ROUTES = {\n activate: '/activate',\n artifact: '/artifact',\n agentState: '/agent/state',\n agentObserve: '/agent/observe',\n agentAction: '/agent/action',\n agentStop: '/agent/stop',\n hubState: '/hub/state',\n hubActivation: '/hub/activation',\n hubAuthorization: '/hub/authorization',\n hubNext: '/hub/next',\n hubComplete: '/hub/complete',\n hubStop: '/hub/stop',\n} as const;\n\nexport const COMPUTER_USE_WAKE_LIMIT = 1_000_000;\n\nexport interface ComputerUseArtifactView {\n readonly artifactId: string;\n readonly status: 'ready' | 'failed';\n readonly sizeBytes?: number;\n readonly downloadUrl?: string;\n readonly previewUrl?: string;\n readonly actionCount?: number;\n readonly completedAt?: string;\n readonly failure?: { readonly code: string; readonly message: string };\n}\n\nexport interface ComputerUseSessionView {\n readonly sessionId: string;\n readonly revision: number;\n readonly wake: number;\n readonly phase: 'inactive' | 'awaiting_confirmation' | 'activating' | 'active' | 'stopping' | 'failed';\n readonly requestId?: string;\n readonly target?: Record<string, unknown>;\n readonly durationMs?: number;\n readonly expiresAt?: number;\n readonly failure?: { readonly code: string; readonly message: string };\n readonly artifact?: ComputerUseArtifactView;\n}\n\nexport interface ComputerUseActivationRequest {\n readonly requestId: string;\n readonly target?: Record<string, unknown>;\n readonly durationSeconds: number;\n readonly createdAt: number;\n readonly confirmationExpiresAt: number;\n readonly caller: PoApiCaller;\n}\n\nexport interface ComputerUseBrokerRequest {\n readonly id: string;\n readonly operation: 'observe' | 'act';\n readonly payload?: unknown;\n readonly grantId: string;\n readonly sequence?: number;\n}\n\nexport interface ComputerUseChannelPayload {\n readonly state: ComputerUseSessionView;\n readonly targets: readonly Record<string, unknown>[];\n readonly busy?: true;\n}\n\nexport type ComputerUseBrowserCommand = { readonly action: 'status' | 'targets' | 'stop' | 'artifacts' };\n","import { defineActivityGroup } from '@agimon-ai/po-core/native';\n\nimport { COMPUTER_USE_STATUS_KEY } from '../../../../../types/computerUseApi';\n\n/** Remote clients request control from the Desktop host through their session Activity. */\nexport default defineActivityGroup({\n name: 'computer-use',\n keys: 'c e',\n order: 70,\n statusKey: COMPUTER_USE_STATUS_KEY,\n hideWhenEmpty: true,\n marksBackgroundWork: false,\n});\n","import { defineSessionStore } from '@agimon-ai/po-core/native';\n\nimport { computerUseChannelType } from '../../../../../types/computerUseApi';\nimport type { ComputerUseChannelPayload } from '../../../../../types/computerUseApi';\n\nexport interface ComputerUseSession extends ComputerUseChannelPayload {}\n\nconst initialState: ComputerUseSession = {\n state: { sessionId: '', revision: 0, wake: 0, phase: 'inactive' },\n targets: [],\n};\n\nexport const computerUse = defineSessionStore<ComputerUseSession>(initialState);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport const computerUseChannel = computerUse.channel<ComputerUseChannelPayload>({\n channel: computerUseChannelType,\n parse(input) {\n if (!isRecord(input) || !isRecord(input.state) || !Array.isArray(input.targets)) return null;\n if (typeof input.state.phase !== 'string' || typeof input.state.revision !== 'number') return null;\n return input as unknown as ComputerUseChannelPayload;\n },\n reduce: (_current, payload) => payload,\n});\n","import { defineChannelFile } from '@agimon-ai/po-core/native';\n\nimport { computerUseChannel } from '../_lib/computerUseStore.native';\n\nexport default defineChannelFile(computerUseChannel);\n","import type { ApiResponseOf, ApiRoutes } from '@agimon-ai/po-core/web';\n\nimport {\n COMPUTER_USE_ROUTES,\n type ComputerUseActivationRequest,\n type ComputerUseBrokerRequest,\n type ComputerUseSessionView,\n} from './computerUseApi';\nimport { DESKTOP_PERMISSIONS_PATH, type DesktopPermissionStates } from './desktopPermissions';\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path: the build reads both off\n * `src/extensions/workspaces/sessions/(backend)/api/computer-use/`, so the\n * mount is stated once, by the folder that creates it.\n *\n * The paths come from `COMPUTER_USE_ROUTES` rather than being written out\n * again. That table already addressed the broker from the hub channel and from\n * the broker's own dispatcher, and a second copy here is exactly the\n * disagreement this file exists to prevent. The dispatcher now reads this\n * table, so the page, the broker and the hub all resolve one set of strings.\n *\n * Activation, status, cancellation and recording reads are reachable from a browser. The `/agent/` and `/hub/` routes\n * each demand a host-issued bearer token and answer 404 without one; they are\n * declared here because they are this API's surface, not because a page calls\n * them.\n */\nconst routes = {\n artifact: {\n method: 'GET',\n path: COMPUTER_USE_ROUTES.artifact,\n query: ['artifactId', 'offset'],\n raw: true,\n },\n activationState: {\n method: 'GET',\n path: COMPUTER_USE_ROUTES.activate,\n response: undefined as unknown as ApiResponseOf<ComputerUseSessionView>,\n },\n cancelActivation: {\n method: 'DELETE',\n path: COMPUTER_USE_ROUTES.activate,\n response: undefined as unknown as ApiResponseOf<ComputerUseSessionView>,\n },\n activate: {\n method: 'POST',\n path: COMPUTER_USE_ROUTES.activate,\n response: undefined as unknown as ApiResponseOf<ComputerUseSessionView>,\n },\n agentState: {\n method: 'GET',\n path: COMPUTER_USE_ROUTES.agentState,\n response: undefined as unknown as ApiResponseOf<ComputerUseSessionView>,\n },\n /** Answers whatever the admitted Desktop provider returned, which is runtime-defined JSON. */\n agentObserve: {\n method: 'POST',\n path: COMPUTER_USE_ROUTES.agentObserve,\n response: undefined as unknown as ApiResponseOf<unknown>,\n },\n agentAction: {\n method: 'POST',\n path: COMPUTER_USE_ROUTES.agentAction,\n response: undefined as unknown as ApiResponseOf<unknown>,\n },\n agentStop: {\n method: 'POST',\n path: COMPUTER_USE_ROUTES.agentStop,\n response: undefined as unknown as ApiResponseOf<ComputerUseSessionView>,\n },\n hubState: {\n method: 'GET',\n path: COMPUTER_USE_ROUTES.hubState,\n response: undefined as unknown as ApiResponseOf<ComputerUseSessionView>,\n },\n /** Null until a reader has confirmed one; reading it moves the session to `activating`. */\n hubActivation: {\n method: 'GET',\n path: COMPUTER_USE_ROUTES.hubActivation,\n response: undefined as unknown as ApiResponseOf<ComputerUseActivationRequest | null>,\n },\n hubAuthorization: {\n method: 'GET',\n path: COMPUTER_USE_ROUTES.hubAuthorization,\n response: undefined as unknown as ApiResponseOf<{ readonly grantId: string; readonly expiresAt?: number } | null>,\n },\n hubNext: {\n method: 'GET',\n path: COMPUTER_USE_ROUTES.hubNext,\n response: undefined as unknown as ApiResponseOf<ComputerUseBrokerRequest | null>,\n },\n hubComplete: {\n method: 'POST',\n path: COMPUTER_USE_ROUTES.hubComplete,\n response: undefined as unknown as ApiResponseOf<ComputerUseSessionView>,\n },\n hubStop: {\n method: 'POST',\n path: COMPUTER_USE_ROUTES.hubStop,\n response: undefined as unknown as ApiResponseOf<ComputerUseSessionView>,\n },\n /** Desktop's macOS permission states, served by the hub's `desktop-permissions` mount. */\n desktopPermissions: {\n method: 'GET',\n path: DESKTOP_PERMISSIONS_PATH,\n response: undefined as unknown as ApiResponseOf<DesktopPermissionStates>,\n },\n /** Asks macOS for the body's permission on the Mac running Desktop; answers the states after. */\n requestDesktopPermission: {\n method: 'POST',\n path: DESKTOP_PERMISSIONS_PATH,\n response: undefined as unknown as ApiResponseOf<DesktopPermissionStates>,\n },\n} as const satisfies ApiRoutes;\n\nexport default routes;\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { createApiClient, nativeApiTransport, sessionApiAddress } from '@agimon-ai/po-core/native';\n\nimport routes from '../src/types/apiRoutes';\n\n/** Scopes the tree mounts 'computer-use' at for the computer-use mount. */\nexport const computerUseScopes = ['session'] as const;\n\nexport const computerUse = createApiClient(routes, {\n scopes: computerUseScopes,\n basePath: 'computer-use',\n transport: nativeApiTransport,\n sessionAddress: sessionApiAddress,\n});\n\n/** Scopes the tree mounts 'desktop-permissions' at for the desktop-permissions mount. */\nexport const desktopPermissionsScopes = ['global', 'workspace', 'session'] as const;\n\nexport const desktopPermissions = createApiClient(routes, {\n scopes: desktopPermissionsScopes,\n basePath: 'desktop-permissions',\n transport: nativeApiTransport,\n sessionAddress: sessionApiAddress,\n});\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { Button, fontOf } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { computerUse as api } from '../../../../../../../generated/client.native';\nimport { COMPUTER_USE_DEFAULT_DURATION_MS, computerUseChannelType } from '../../../../../../types/computerUseApi';\nimport type { ComputerUseSessionView } from '../../../../../../types/computerUseApi';\nimport { computerUse } from '../../_lib/computerUseStore.native';\n\nexport function ComputerUseView({\n state,\n busy = false,\n error,\n submitting = false,\n onActivate,\n onCancel,\n onStop,\n}: {\n state: ComputerUseSessionView;\n busy?: boolean;\n error?: string;\n submitting?: boolean;\n onActivate: () => void;\n onCancel: () => void;\n onStop: () => void;\n}) {\n const pending = state.phase === 'awaiting_confirmation' || state.phase === 'activating';\n const active = state.phase === 'active' || state.phase === 'stopping';\n const failure = error ?? state.failure?.message;\n return (\n <View style={styles.panel}>\n <Text style={styles.detail} accessibilityLiveRegion=\"polite\">\n {state.phase.replaceAll('_', ' ')}\n </Text>\n {busy ? <Text style={styles.detail}>Computer use is busy in another session.</Text> : null}\n {failure ? (\n <Text style={styles.error} accessibilityRole=\"alert\">\n {failure}\n </Text>\n ) : null}\n {pending ? (\n <>\n <Text style={styles.text}>Desktop activation is pending.</Text>\n <Text style={styles.detail}>Choose and confirm an application window on your Mac.</Text>\n <Button variant=\"outline\" disabled={submitting} onPress={onCancel}>\n Cancel activation\n </Button>\n </>\n ) : active ? (\n <>\n {state.target ? (\n <Text style={styles.text}>\n {`${typeof state.target.applicationName === 'string' ? state.target.applicationName : 'Application'}: ${typeof state.target.windowTitle === 'string' ? state.target.windowTitle : 'Window'}`}\n </Text>\n ) : null}\n <Button variant=\"outline\" disabled={submitting || state.phase === 'stopping'} onPress={onStop}>\n Stop computer use\n </Button>\n </>\n ) : (\n <>\n <Text style={styles.detail}>\n Request 5 minutes of control. Your Mac asks you to choose and confirm a window.\n </Text>\n <Button variant=\"primary\" disabled={busy || submitting} onPress={onActivate}>\n Choose window on Mac\n </Button>\n </>\n )}\n </View>\n );\n}\n\nfunction SessionPanel({ sessionId, sendSessionFrame }: WebPluginSlotProps & { sessionId: string }) {\n const subscribe = useCallback((listener: () => void) => {\n const subscription = computerUse.store.subscribe(listener);\n return () => subscription.unsubscribe();\n }, []);\n // Native plugins may not import @tanstack/react-store; it is not a native host module.\n const session = useSyncExternalStore(subscribe, () => computerUse.select(computerUse.store.state, sessionId));\n const [error, setError] = useState<string>();\n const [submitting, setSubmitting] = useState(false);\n const requests = useRef<AbortController | null>(null);\n const update = (state: ComputerUseSessionView) =>\n computerUse.update(sessionId, (current) =>\n state.revision >= current.state.revision ? { ...current, state } : current,\n );\n\n useEffect(() => {\n const controller = new AbortController();\n requests.current = controller;\n let timer: ReturnType<typeof setTimeout> | undefined;\n sendSessionFrame(sessionId, { type: computerUseChannelType, payload: { action: 'status' } });\n const poll = async () => {\n try {\n const result = await api.session(sessionId).activationState({ signal: controller.signal });\n if (result.ok && !controller.signal.aborted)\n computerUse.update(sessionId, (current) =>\n result.data.revision >= current.state.revision ? { ...current, state: result.data } : current,\n );\n } catch {\n if (!controller.signal.aborted) setError('The session is unreachable.');\n }\n if (!controller.signal.aborted) timer = setTimeout(() => void poll(), 2000);\n };\n void poll();\n return () => {\n controller.abort();\n clearTimeout(timer);\n };\n }, [sessionId, sendSessionFrame]);\n\n const submit = async (action: 'activate' | 'cancel') => {\n const signal = requests.current?.signal;\n if (!signal || signal.aborted || submitting) return;\n setError(undefined);\n setSubmitting(true);\n try {\n const client = api.session(sessionId);\n const result =\n action === 'activate'\n ? await client.activate({ body: { durationMs: COMPUTER_USE_DEFAULT_DURATION_MS }, signal })\n : await client.cancelActivation({ signal });\n if (signal.aborted) return;\n if (result.ok) update(result.data);\n else\n setError(\n result.status === 0 ? 'The session is unreachable.' : result.error || 'The activation request failed.',\n );\n } catch {\n if (!signal.aborted) setError('The activation request is unavailable.');\n } finally {\n if (!signal.aborted) setSubmitting(false);\n }\n };\n\n return (\n <ComputerUseView\n state={session.state}\n busy={session.busy}\n error={error}\n submitting={submitting}\n onActivate={() => void submit('activate')}\n onCancel={() => void submit('cancel')}\n onStop={() => {\n setError(undefined);\n try {\n sendSessionFrame(sessionId, { type: computerUseChannelType, payload: { action: 'stop' } });\n } catch {\n setError('The stop request is unavailable.');\n }\n }}\n />\n );\n}\n\nexport function ComputerUsePanel(props: WebPluginSlotProps) {\n return props.sessionId === null ? (\n <Text style={styles.detail}>Select a session.</Text>\n ) : (\n <SessionPanel key={props.sessionId} {...props} sessionId={props.sessionId} />\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { gap: theme.spacing(3) },\n text: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeightRelaxed.base,\n color: theme.colors.text,\n },\n detail: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeightRelaxed.sm,\n color: theme.colors.dim,\n },\n error: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeightRelaxed.base,\n color: theme.colors.red,\n },\n}));\n","import { defineFill } from '@agimon-ai/po-core/native';\n\nimport { ComputerUsePanel } from './_components/ComputerUsePanel.native';\n\nexport default defineFill({ id: 'computer-use', slot: 'activity.computer-use', component: ComputerUsePanel });\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineNativePlugin, type WebPluginContributions } from '@agimon-ai/po-core/native';\n\nimport activityGroupComputerUse from '../src/extensions/workspaces/sessions/(frontend)/activity-group/computer-use.native';\nimport channelComputerUse from '../src/extensions/workspaces/sessions/(frontend)/channel/computer-use.native';\nimport fillComputerUse from '../src/extensions/workspaces/sessions/(frontend)/fill/ComputerUse.activity.computer-use.native';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const nativePlugin = defineNativePlugin({\n id: 'computer-use',\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'computer-use' }, activityGroupComputerUse)]; },\n get channels(): WebPluginContributions['channels'] { return [via({ channel: 'computer_use' }, channelComputerUse)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.computer-use', id: 'computer-use' }, fillComputerUse)]; },\n },\n});\n"],"mappings":"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"}