@agimon-ai/po-computer-use 0.0.0-alpha.31 → 0.0.0-alpha.33

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.
@@ -44,6 +44,26 @@ const ComputerStateSchema = typebox.Type.Object({
44
44
  failure: O(Error),
45
45
  artifact: O(Artifact)
46
46
  });
47
+ const Permission = values([
48
+ "accessibility",
49
+ "screen-recording",
50
+ "microphone",
51
+ "automation",
52
+ "full-disk-access"
53
+ ]);
54
+ const PermissionState = values([
55
+ "granted",
56
+ "denied",
57
+ "not-determined",
58
+ "per-app"
59
+ ]);
60
+ const DesktopPermissionStatesSchema = typebox.Type.Object({
61
+ accessibility: PermissionState,
62
+ "screen-recording": PermissionState,
63
+ microphone: PermissionState,
64
+ automation: PermissionState,
65
+ "full-disk-access": PermissionState
66
+ });
47
67
  const Reference = {
48
68
  snapshotId: typebox.Type.String({ minLength: 1 }),
49
69
  elementRef: typebox.Type.String({ minLength: 1 })
@@ -96,6 +116,32 @@ const apiContracts = (0, _agimon_ai_po_core_apiContracts.defineApiContract)({
96
116
  version: 1,
97
117
  dynamic: ["Desktop provider target extensions, observations and operation results are runtime-defined JSON."],
98
118
  http: [
119
+ ...[
120
+ "global",
121
+ "workspace",
122
+ "session"
123
+ ].flatMap((scope) => ["GET", "POST"].map((method) => ({
124
+ id: `computer.permissions.${method === "GET" ? "read" : "request"}`,
125
+ scope,
126
+ basePath: "desktop-permissions",
127
+ path: "/",
128
+ method,
129
+ authentication: "owner",
130
+ description: method === "GET" ? "Read the Mac-owned permission states. Requires an authorized local Desktop caller or trusted remote caller." : "Ask macOS for one named permission. Requires an authorized local Desktop caller or remote passkey step-up.",
131
+ availability: "Requires Po Desktop to be running this server; otherwise returns 404.",
132
+ ...method === "POST" ? { body: {
133
+ required: true,
134
+ contentType: "application/json",
135
+ schema: typebox.Type.Object({ permission: Permission })
136
+ } } : {},
137
+ responses: {
138
+ ...(0, _agimon_ai_po_core_apiContracts.jsonApiResponses)(DesktopPermissionStatesSchema),
139
+ "502": {
140
+ description: "Desktop permission request failed.",
141
+ schema: typebox.Type.Object({ error: S })
142
+ }
143
+ }
144
+ }))),
99
145
  {
100
146
  id: "computer.activation.state",
101
147
  scope: "session",
@@ -1 +1 @@
1
- {"version":3,"file":"apiContracts.cjs","names":["Type","jsonApiResponses","defineApiContract"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses, type PoHttpContract } from '@agimon-ai/po-core/apiContracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst N = Type.Number();\nconst O = Type.Optional;\nconst values = <T extends string>(items: T[]) => Type.Union(items.map((item) => Type.Literal(item)));\nconst Json = Type.Unknown({\n description:\n 'Desktop provider JSON value. Targets, observations and action results are supplied by the admitted Desktop provider.',\n});\nconst Target = Type.Record(S, Json);\nconst Error = Type.Object({ code: S, message: S });\nconst Artifact = Type.Object({\n artifactId: S,\n status: values(['ready', 'failed']),\n sizeBytes: O(N),\n downloadUrl: O(S),\n previewUrl: O(S),\n actionCount: O(N),\n completedAt: O(S),\n failure: O(Error),\n});\nexport const ComputerStateSchema = Type.Object({\n sessionId: S,\n revision: N,\n wake: N,\n phase: values(['inactive', 'awaiting_confirmation', 'activating', 'active', 'stopping', 'failed']),\n requestId: O(S),\n target: O(Target),\n durationMs: O(N),\n expiresAt: O(N),\n failure: O(Error),\n artifact: O(Artifact),\n});\nconst Reference = { snapshotId: Type.String({ minLength: 1 }), elementRef: Type.String({ minLength: 1 }) };\nexport const ComputerActionSchema = Type.Union([\n Type.Object({ kind: values(['press', 'focus']), ...Reference }, { additionalProperties: false }),\n Type.Object({ kind: Type.Literal('set_value'), ...Reference, value: S }, { additionalProperties: false }),\n Type.Object(\n {\n kind: Type.Literal('scroll'),\n ...Reference,\n direction: values(['up', 'down', 'left', 'right']),\n amount: values(['line', 'page']),\n },\n { additionalProperties: false },\n ),\n]);\nconst internal = (\n method: 'GET' | 'POST',\n path: string,\n output: object,\n body?: object,\n status = 200,\n): PoHttpContract => ({\n id: `computer.${path.slice(1).replaceAll('/', '.')}`,\n scope: 'session',\n basePath: 'computer-use',\n path,\n method,\n authentication: 'owner',\n description: `Computer use broker ${path}. Requires the host-issued ${path.startsWith('/agent/') ? 'agent' : 'hub'} bearer token.`,\n availability: 'Internal broker route; ordinary browser credentials are insufficient.',\n parameters: [{ name: 'Authorization', in: 'header', required: true, schema: Type.String({ pattern: '^Bearer .+' }) }],\n ...(body ? { body: { required: true, contentType: 'application/json', schema: body } } : {}),\n responses: jsonApiResponses(output, status),\n});\nexport const apiContracts = defineApiContract({\n version: 1,\n dynamic: ['Desktop provider target extensions, observations and operation results are runtime-defined JSON.'],\n http: [\n {\n id: 'computer.activation.state',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'GET',\n authentication: 'owner',\n description: 'Read state as the matching pending requester or approved recording reader.',\n responses: jsonApiResponses(ComputerStateSchema),\n },\n {\n id: 'computer.activation.cancel',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Cancel only the matching requester pending activation.',\n responses: jsonApiResponses(ComputerStateSchema, 202),\n },\n {\n id: 'computer.activate',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'POST',\n authentication: 'owner',\n description:\n 'Request confirmed Desktop access with admitted caller and remote step-up context. A remote caller may omit target so the local Mac selects the window.',\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({\n target: O(Type.Object({ windowId: S, bundleId: S })),\n durationMs: Type.Integer({ minimum: 1000, maximum: 1800000 }),\n }),\n },\n responses: jsonApiResponses(ComputerStateSchema, 202),\n },\n {\n id: 'computer.artifact',\n scope: 'session',\n basePath: 'computer-use',\n path: '/artifact',\n method: 'GET',\n authentication: 'owner',\n description: 'Read at most 1 MiB of a recording belonging to this session and approved caller.',\n parameters: [\n { name: 'artifactId', in: 'query', required: true, schema: S },\n { name: 'offset', in: 'query', required: true, schema: Type.Integer({ minimum: 0 }) },\n ],\n responses: {\n 206: {\n description: 'Bounded recording bytes.',\n contentType: 'video/mp4',\n schema: Type.String({ format: 'binary' }),\n },\n },\n },\n internal('GET', '/agent/state', ComputerStateSchema),\n internal('GET', '/hub/state', ComputerStateSchema),\n internal('POST', '/agent/observe', Json),\n internal('POST', '/agent/action', Json, ComputerActionSchema),\n internal('POST', '/agent/stop', ComputerStateSchema, undefined, 202),\n internal(\n 'GET',\n '/hub/activation',\n Type.Union([\n Type.Null(),\n Type.Object({\n requestId: S,\n target: Target,\n durationSeconds: N,\n createdAt: N,\n confirmationExpiresAt: N,\n caller: Type.Object({ locality: values(['local', 'remote']), stepUp: S }),\n }),\n ]),\n ),\n internal('GET', '/hub/authorization', Type.Union([Type.Null(), Type.Object({ grantId: S, expiresAt: O(N) })])),\n internal(\n 'GET',\n '/hub/next',\n Type.Union([\n Type.Null(),\n Type.Object({ id: S, operation: values(['observe', 'act']), payload: O(Json), grantId: S, sequence: O(N) }),\n ]),\n ),\n internal('POST', '/hub/complete', ComputerStateSchema, Type.Object({ id: S, error: O(S), result: O(Json) })),\n internal(\n 'POST',\n '/hub/stop',\n ComputerStateSchema,\n Type.Object({ error: O(S), host: O(Type.Object({ grantId: S, expiresAt: N })), artifact: O(Artifact) }),\n ),\n ],\n sockets: (['global', 'workspace'] as const).flatMap((scope) => [\n {\n id: 'computer.state',\n scope,\n service: 'po.hub',\n member: 'computer_use_state',\n kind: 'channel',\n direction: 'server-to-client',\n description: 'Computer use channel payload.',\n input: Type.Object({ state: ComputerStateSchema, targets: Type.Array(Target), busy: O(Type.Literal(true)) }),\n },\n {\n id: 'computer.command',\n scope,\n service: 'po.hub',\n member: 'computer_use_state',\n kind: 'channel',\n direction: 'client-to-server',\n description: 'Computer use browser channel command.',\n input: Type.Object({ action: values(['status', 'targets', 'stop', 'artifacts']) }),\n },\n ]),\n});\nexport default apiContracts;\n"],"mappings":"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"}
1
+ {"version":3,"file":"apiContracts.cjs","names":["Type","jsonApiResponses","defineApiContract"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses, type PoHttpContract } from '@agimon-ai/po-core/apiContracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst N = Type.Number();\nconst O = Type.Optional;\nconst values = <T extends string>(items: T[]) => Type.Union(items.map((item) => Type.Literal(item)));\nconst Json = Type.Unknown({\n description:\n 'Desktop provider JSON value. Targets, observations and action results are supplied by the admitted Desktop provider.',\n});\nconst Target = Type.Record(S, Json);\nconst Error = Type.Object({ code: S, message: S });\nconst Artifact = Type.Object({\n artifactId: S,\n status: values(['ready', 'failed']),\n sizeBytes: O(N),\n downloadUrl: O(S),\n previewUrl: O(S),\n actionCount: O(N),\n completedAt: O(S),\n failure: O(Error),\n});\nexport const ComputerStateSchema = Type.Object({\n sessionId: S,\n revision: N,\n wake: N,\n phase: values(['inactive', 'awaiting_confirmation', 'activating', 'active', 'stopping', 'failed']),\n requestId: O(S),\n target: O(Target),\n durationMs: O(N),\n expiresAt: O(N),\n failure: O(Error),\n artifact: O(Artifact),\n});\nconst Permission = values(['accessibility', 'screen-recording', 'microphone', 'automation', 'full-disk-access']);\nconst PermissionState = values(['granted', 'denied', 'not-determined', 'per-app']);\nexport const DesktopPermissionStatesSchema = Type.Object({\n accessibility: PermissionState,\n 'screen-recording': PermissionState,\n microphone: PermissionState,\n automation: PermissionState,\n 'full-disk-access': PermissionState,\n});\nconst Reference = { snapshotId: Type.String({ minLength: 1 }), elementRef: Type.String({ minLength: 1 }) };\nexport const ComputerActionSchema = Type.Union([\n Type.Object({ kind: values(['press', 'focus']), ...Reference }, { additionalProperties: false }),\n Type.Object({ kind: Type.Literal('set_value'), ...Reference, value: S }, { additionalProperties: false }),\n Type.Object(\n {\n kind: Type.Literal('scroll'),\n ...Reference,\n direction: values(['up', 'down', 'left', 'right']),\n amount: values(['line', 'page']),\n },\n { additionalProperties: false },\n ),\n]);\nconst internal = (\n method: 'GET' | 'POST',\n path: string,\n output: object,\n body?: object,\n status = 200,\n): PoHttpContract => ({\n id: `computer.${path.slice(1).replaceAll('/', '.')}`,\n scope: 'session',\n basePath: 'computer-use',\n path,\n method,\n authentication: 'owner',\n description: `Computer use broker ${path}. Requires the host-issued ${path.startsWith('/agent/') ? 'agent' : 'hub'} bearer token.`,\n availability: 'Internal broker route; ordinary browser credentials are insufficient.',\n parameters: [{ name: 'Authorization', in: 'header', required: true, schema: Type.String({ pattern: '^Bearer .+' }) }],\n ...(body ? { body: { required: true, contentType: 'application/json', schema: body } } : {}),\n responses: jsonApiResponses(output, status),\n});\nexport const apiContracts = defineApiContract({\n version: 1,\n dynamic: ['Desktop provider target extensions, observations and operation results are runtime-defined JSON.'],\n http: [\n ...(['global', 'workspace', 'session'] as const).flatMap((scope) =>\n (['GET', 'POST'] as const).map((method) => ({\n id: `computer.permissions.${method === 'GET' ? 'read' : 'request'}`,\n scope,\n basePath: 'desktop-permissions',\n path: '/',\n method,\n authentication: 'owner' as const,\n description:\n method === 'GET'\n ? 'Read the Mac-owned permission states. Requires an authorized local Desktop caller or trusted remote caller.'\n : 'Ask macOS for one named permission. Requires an authorized local Desktop caller or remote passkey step-up.',\n availability: 'Requires Po Desktop to be running this server; otherwise returns 404.',\n ...(method === 'POST'\n ? {\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({ permission: Permission }),\n },\n }\n : {}),\n responses: {\n ...jsonApiResponses(DesktopPermissionStatesSchema),\n '502': { description: 'Desktop permission request failed.', schema: Type.Object({ error: S }) },\n },\n })),\n ),\n {\n id: 'computer.activation.state',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'GET',\n authentication: 'owner',\n description: 'Read state as the matching pending requester or approved recording reader.',\n responses: jsonApiResponses(ComputerStateSchema),\n },\n {\n id: 'computer.activation.cancel',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Cancel only the matching requester pending activation.',\n responses: jsonApiResponses(ComputerStateSchema, 202),\n },\n {\n id: 'computer.activate',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'POST',\n authentication: 'owner',\n description:\n 'Request confirmed Desktop access with admitted caller and remote step-up context. A remote caller may omit target so the local Mac selects the window.',\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({\n target: O(Type.Object({ windowId: S, bundleId: S })),\n durationMs: Type.Integer({ minimum: 1000, maximum: 1800000 }),\n }),\n },\n responses: jsonApiResponses(ComputerStateSchema, 202),\n },\n {\n id: 'computer.artifact',\n scope: 'session',\n basePath: 'computer-use',\n path: '/artifact',\n method: 'GET',\n authentication: 'owner',\n description: 'Read at most 1 MiB of a recording belonging to this session and approved caller.',\n parameters: [\n { name: 'artifactId', in: 'query', required: true, schema: S },\n { name: 'offset', in: 'query', required: true, schema: Type.Integer({ minimum: 0 }) },\n ],\n responses: {\n 206: {\n description: 'Bounded recording bytes.',\n contentType: 'video/mp4',\n schema: Type.String({ format: 'binary' }),\n },\n },\n },\n internal('GET', '/agent/state', ComputerStateSchema),\n internal('GET', '/hub/state', ComputerStateSchema),\n internal('POST', '/agent/observe', Json),\n internal('POST', '/agent/action', Json, ComputerActionSchema),\n internal('POST', '/agent/stop', ComputerStateSchema, undefined, 202),\n internal(\n 'GET',\n '/hub/activation',\n Type.Union([\n Type.Null(),\n Type.Object({\n requestId: S,\n target: Target,\n durationSeconds: N,\n createdAt: N,\n confirmationExpiresAt: N,\n caller: Type.Object({ locality: values(['local', 'remote']), stepUp: S }),\n }),\n ]),\n ),\n internal('GET', '/hub/authorization', Type.Union([Type.Null(), Type.Object({ grantId: S, expiresAt: O(N) })])),\n internal(\n 'GET',\n '/hub/next',\n Type.Union([\n Type.Null(),\n Type.Object({ id: S, operation: values(['observe', 'act']), payload: O(Json), grantId: S, sequence: O(N) }),\n ]),\n ),\n internal('POST', '/hub/complete', ComputerStateSchema, Type.Object({ id: S, error: O(S), result: O(Json) })),\n internal(\n 'POST',\n '/hub/stop',\n ComputerStateSchema,\n Type.Object({ error: O(S), host: O(Type.Object({ grantId: S, expiresAt: N })), artifact: O(Artifact) }),\n ),\n ],\n sockets: (['global', 'workspace'] as const).flatMap((scope) => [\n {\n id: 'computer.state',\n scope,\n service: 'po.hub',\n member: 'computer_use_state',\n kind: 'channel',\n direction: 'server-to-client',\n description: 'Computer use channel payload.',\n input: Type.Object({ state: ComputerStateSchema, targets: Type.Array(Target), busy: O(Type.Literal(true)) }),\n },\n {\n id: 'computer.command',\n scope,\n service: 'po.hub',\n member: 'computer_use_state',\n kind: 'channel',\n direction: 'client-to-server',\n description: 'Computer use browser channel command.',\n input: Type.Object({ action: values(['status', 'targets', 'stop', 'artifacts']) }),\n },\n ]),\n});\nexport default apiContracts;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../src/schemas/apiContracts.ts"],"mappings":";;qBAoEa"}
1
+ {"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../src/schemas/apiContracts.ts"],"mappings":";;qBA6Ea"}
@@ -40,6 +40,26 @@ const ComputerStateSchema = Type.Object({
40
40
  failure: O(Error),
41
41
  artifact: O(Artifact)
42
42
  });
43
+ const Permission = values([
44
+ "accessibility",
45
+ "screen-recording",
46
+ "microphone",
47
+ "automation",
48
+ "full-disk-access"
49
+ ]);
50
+ const PermissionState = values([
51
+ "granted",
52
+ "denied",
53
+ "not-determined",
54
+ "per-app"
55
+ ]);
56
+ const DesktopPermissionStatesSchema = Type.Object({
57
+ accessibility: PermissionState,
58
+ "screen-recording": PermissionState,
59
+ microphone: PermissionState,
60
+ automation: PermissionState,
61
+ "full-disk-access": PermissionState
62
+ });
43
63
  const Reference = {
44
64
  snapshotId: Type.String({ minLength: 1 }),
45
65
  elementRef: Type.String({ minLength: 1 })
@@ -92,6 +112,32 @@ const apiContracts = defineApiContract({
92
112
  version: 1,
93
113
  dynamic: ["Desktop provider target extensions, observations and operation results are runtime-defined JSON."],
94
114
  http: [
115
+ ...[
116
+ "global",
117
+ "workspace",
118
+ "session"
119
+ ].flatMap((scope) => ["GET", "POST"].map((method) => ({
120
+ id: `computer.permissions.${method === "GET" ? "read" : "request"}`,
121
+ scope,
122
+ basePath: "desktop-permissions",
123
+ path: "/",
124
+ method,
125
+ authentication: "owner",
126
+ description: method === "GET" ? "Read the Mac-owned permission states. Requires an authorized local Desktop caller or trusted remote caller." : "Ask macOS for one named permission. Requires an authorized local Desktop caller or remote passkey step-up.",
127
+ availability: "Requires Po Desktop to be running this server; otherwise returns 404.",
128
+ ...method === "POST" ? { body: {
129
+ required: true,
130
+ contentType: "application/json",
131
+ schema: Type.Object({ permission: Permission })
132
+ } } : {},
133
+ responses: {
134
+ ...jsonApiResponses(DesktopPermissionStatesSchema),
135
+ "502": {
136
+ description: "Desktop permission request failed.",
137
+ schema: Type.Object({ error: S })
138
+ }
139
+ }
140
+ }))),
95
141
  {
96
142
  id: "computer.activation.state",
97
143
  scope: "session",
@@ -1 +1 @@
1
- {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses, type PoHttpContract } from '@agimon-ai/po-core/apiContracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst N = Type.Number();\nconst O = Type.Optional;\nconst values = <T extends string>(items: T[]) => Type.Union(items.map((item) => Type.Literal(item)));\nconst Json = Type.Unknown({\n description:\n 'Desktop provider JSON value. Targets, observations and action results are supplied by the admitted Desktop provider.',\n});\nconst Target = Type.Record(S, Json);\nconst Error = Type.Object({ code: S, message: S });\nconst Artifact = Type.Object({\n artifactId: S,\n status: values(['ready', 'failed']),\n sizeBytes: O(N),\n downloadUrl: O(S),\n previewUrl: O(S),\n actionCount: O(N),\n completedAt: O(S),\n failure: O(Error),\n});\nexport const ComputerStateSchema = Type.Object({\n sessionId: S,\n revision: N,\n wake: N,\n phase: values(['inactive', 'awaiting_confirmation', 'activating', 'active', 'stopping', 'failed']),\n requestId: O(S),\n target: O(Target),\n durationMs: O(N),\n expiresAt: O(N),\n failure: O(Error),\n artifact: O(Artifact),\n});\nconst Reference = { snapshotId: Type.String({ minLength: 1 }), elementRef: Type.String({ minLength: 1 }) };\nexport const ComputerActionSchema = Type.Union([\n Type.Object({ kind: values(['press', 'focus']), ...Reference }, { additionalProperties: false }),\n Type.Object({ kind: Type.Literal('set_value'), ...Reference, value: S }, { additionalProperties: false }),\n Type.Object(\n {\n kind: Type.Literal('scroll'),\n ...Reference,\n direction: values(['up', 'down', 'left', 'right']),\n amount: values(['line', 'page']),\n },\n { additionalProperties: false },\n ),\n]);\nconst internal = (\n method: 'GET' | 'POST',\n path: string,\n output: object,\n body?: object,\n status = 200,\n): PoHttpContract => ({\n id: `computer.${path.slice(1).replaceAll('/', '.')}`,\n scope: 'session',\n basePath: 'computer-use',\n path,\n method,\n authentication: 'owner',\n description: `Computer use broker ${path}. Requires the host-issued ${path.startsWith('/agent/') ? 'agent' : 'hub'} bearer token.`,\n availability: 'Internal broker route; ordinary browser credentials are insufficient.',\n parameters: [{ name: 'Authorization', in: 'header', required: true, schema: Type.String({ pattern: '^Bearer .+' }) }],\n ...(body ? { body: { required: true, contentType: 'application/json', schema: body } } : {}),\n responses: jsonApiResponses(output, status),\n});\nexport const apiContracts = defineApiContract({\n version: 1,\n dynamic: ['Desktop provider target extensions, observations and operation results are runtime-defined JSON.'],\n http: [\n {\n id: 'computer.activation.state',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'GET',\n authentication: 'owner',\n description: 'Read state as the matching pending requester or approved recording reader.',\n responses: jsonApiResponses(ComputerStateSchema),\n },\n {\n id: 'computer.activation.cancel',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Cancel only the matching requester pending activation.',\n responses: jsonApiResponses(ComputerStateSchema, 202),\n },\n {\n id: 'computer.activate',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'POST',\n authentication: 'owner',\n description:\n 'Request confirmed Desktop access with admitted caller and remote step-up context. A remote caller may omit target so the local Mac selects the window.',\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({\n target: O(Type.Object({ windowId: S, bundleId: S })),\n durationMs: Type.Integer({ minimum: 1000, maximum: 1800000 }),\n }),\n },\n responses: jsonApiResponses(ComputerStateSchema, 202),\n },\n {\n id: 'computer.artifact',\n scope: 'session',\n basePath: 'computer-use',\n path: '/artifact',\n method: 'GET',\n authentication: 'owner',\n description: 'Read at most 1 MiB of a recording belonging to this session and approved caller.',\n parameters: [\n { name: 'artifactId', in: 'query', required: true, schema: S },\n { name: 'offset', in: 'query', required: true, schema: Type.Integer({ minimum: 0 }) },\n ],\n responses: {\n 206: {\n description: 'Bounded recording bytes.',\n contentType: 'video/mp4',\n schema: Type.String({ format: 'binary' }),\n },\n },\n },\n internal('GET', '/agent/state', ComputerStateSchema),\n internal('GET', '/hub/state', ComputerStateSchema),\n internal('POST', '/agent/observe', Json),\n internal('POST', '/agent/action', Json, ComputerActionSchema),\n internal('POST', '/agent/stop', ComputerStateSchema, undefined, 202),\n internal(\n 'GET',\n '/hub/activation',\n Type.Union([\n Type.Null(),\n Type.Object({\n requestId: S,\n target: Target,\n durationSeconds: N,\n createdAt: N,\n confirmationExpiresAt: N,\n caller: Type.Object({ locality: values(['local', 'remote']), stepUp: S }),\n }),\n ]),\n ),\n internal('GET', '/hub/authorization', Type.Union([Type.Null(), Type.Object({ grantId: S, expiresAt: O(N) })])),\n internal(\n 'GET',\n '/hub/next',\n Type.Union([\n Type.Null(),\n Type.Object({ id: S, operation: values(['observe', 'act']), payload: O(Json), grantId: S, sequence: O(N) }),\n ]),\n ),\n internal('POST', '/hub/complete', ComputerStateSchema, Type.Object({ id: S, error: O(S), result: O(Json) })),\n internal(\n 'POST',\n '/hub/stop',\n ComputerStateSchema,\n Type.Object({ error: O(S), host: O(Type.Object({ grantId: S, expiresAt: N })), artifact: O(Artifact) }),\n ),\n ],\n sockets: (['global', 'workspace'] as const).flatMap((scope) => [\n {\n id: 'computer.state',\n scope,\n service: 'po.hub',\n member: 'computer_use_state',\n kind: 'channel',\n direction: 'server-to-client',\n description: 'Computer use channel payload.',\n input: Type.Object({ state: ComputerStateSchema, targets: Type.Array(Target), busy: O(Type.Literal(true)) }),\n },\n {\n id: 'computer.command',\n scope,\n service: 'po.hub',\n member: 'computer_use_state',\n kind: 'channel',\n direction: 'client-to-server',\n description: 'Computer use browser channel command.',\n input: Type.Object({ action: values(['status', 'targets', 'stop', 'artifacts']) }),\n },\n ]),\n});\nexport default apiContracts;\n"],"mappings":"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"}
1
+ {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses, type PoHttpContract } from '@agimon-ai/po-core/apiContracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst N = Type.Number();\nconst O = Type.Optional;\nconst values = <T extends string>(items: T[]) => Type.Union(items.map((item) => Type.Literal(item)));\nconst Json = Type.Unknown({\n description:\n 'Desktop provider JSON value. Targets, observations and action results are supplied by the admitted Desktop provider.',\n});\nconst Target = Type.Record(S, Json);\nconst Error = Type.Object({ code: S, message: S });\nconst Artifact = Type.Object({\n artifactId: S,\n status: values(['ready', 'failed']),\n sizeBytes: O(N),\n downloadUrl: O(S),\n previewUrl: O(S),\n actionCount: O(N),\n completedAt: O(S),\n failure: O(Error),\n});\nexport const ComputerStateSchema = Type.Object({\n sessionId: S,\n revision: N,\n wake: N,\n phase: values(['inactive', 'awaiting_confirmation', 'activating', 'active', 'stopping', 'failed']),\n requestId: O(S),\n target: O(Target),\n durationMs: O(N),\n expiresAt: O(N),\n failure: O(Error),\n artifact: O(Artifact),\n});\nconst Permission = values(['accessibility', 'screen-recording', 'microphone', 'automation', 'full-disk-access']);\nconst PermissionState = values(['granted', 'denied', 'not-determined', 'per-app']);\nexport const DesktopPermissionStatesSchema = Type.Object({\n accessibility: PermissionState,\n 'screen-recording': PermissionState,\n microphone: PermissionState,\n automation: PermissionState,\n 'full-disk-access': PermissionState,\n});\nconst Reference = { snapshotId: Type.String({ minLength: 1 }), elementRef: Type.String({ minLength: 1 }) };\nexport const ComputerActionSchema = Type.Union([\n Type.Object({ kind: values(['press', 'focus']), ...Reference }, { additionalProperties: false }),\n Type.Object({ kind: Type.Literal('set_value'), ...Reference, value: S }, { additionalProperties: false }),\n Type.Object(\n {\n kind: Type.Literal('scroll'),\n ...Reference,\n direction: values(['up', 'down', 'left', 'right']),\n amount: values(['line', 'page']),\n },\n { additionalProperties: false },\n ),\n]);\nconst internal = (\n method: 'GET' | 'POST',\n path: string,\n output: object,\n body?: object,\n status = 200,\n): PoHttpContract => ({\n id: `computer.${path.slice(1).replaceAll('/', '.')}`,\n scope: 'session',\n basePath: 'computer-use',\n path,\n method,\n authentication: 'owner',\n description: `Computer use broker ${path}. Requires the host-issued ${path.startsWith('/agent/') ? 'agent' : 'hub'} bearer token.`,\n availability: 'Internal broker route; ordinary browser credentials are insufficient.',\n parameters: [{ name: 'Authorization', in: 'header', required: true, schema: Type.String({ pattern: '^Bearer .+' }) }],\n ...(body ? { body: { required: true, contentType: 'application/json', schema: body } } : {}),\n responses: jsonApiResponses(output, status),\n});\nexport const apiContracts = defineApiContract({\n version: 1,\n dynamic: ['Desktop provider target extensions, observations and operation results are runtime-defined JSON.'],\n http: [\n ...(['global', 'workspace', 'session'] as const).flatMap((scope) =>\n (['GET', 'POST'] as const).map((method) => ({\n id: `computer.permissions.${method === 'GET' ? 'read' : 'request'}`,\n scope,\n basePath: 'desktop-permissions',\n path: '/',\n method,\n authentication: 'owner' as const,\n description:\n method === 'GET'\n ? 'Read the Mac-owned permission states. Requires an authorized local Desktop caller or trusted remote caller.'\n : 'Ask macOS for one named permission. Requires an authorized local Desktop caller or remote passkey step-up.',\n availability: 'Requires Po Desktop to be running this server; otherwise returns 404.',\n ...(method === 'POST'\n ? {\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({ permission: Permission }),\n },\n }\n : {}),\n responses: {\n ...jsonApiResponses(DesktopPermissionStatesSchema),\n '502': { description: 'Desktop permission request failed.', schema: Type.Object({ error: S }) },\n },\n })),\n ),\n {\n id: 'computer.activation.state',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'GET',\n authentication: 'owner',\n description: 'Read state as the matching pending requester or approved recording reader.',\n responses: jsonApiResponses(ComputerStateSchema),\n },\n {\n id: 'computer.activation.cancel',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Cancel only the matching requester pending activation.',\n responses: jsonApiResponses(ComputerStateSchema, 202),\n },\n {\n id: 'computer.activate',\n scope: 'session',\n basePath: 'computer-use',\n path: '/activate',\n method: 'POST',\n authentication: 'owner',\n description:\n 'Request confirmed Desktop access with admitted caller and remote step-up context. A remote caller may omit target so the local Mac selects the window.',\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({\n target: O(Type.Object({ windowId: S, bundleId: S })),\n durationMs: Type.Integer({ minimum: 1000, maximum: 1800000 }),\n }),\n },\n responses: jsonApiResponses(ComputerStateSchema, 202),\n },\n {\n id: 'computer.artifact',\n scope: 'session',\n basePath: 'computer-use',\n path: '/artifact',\n method: 'GET',\n authentication: 'owner',\n description: 'Read at most 1 MiB of a recording belonging to this session and approved caller.',\n parameters: [\n { name: 'artifactId', in: 'query', required: true, schema: S },\n { name: 'offset', in: 'query', required: true, schema: Type.Integer({ minimum: 0 }) },\n ],\n responses: {\n 206: {\n description: 'Bounded recording bytes.',\n contentType: 'video/mp4',\n schema: Type.String({ format: 'binary' }),\n },\n },\n },\n internal('GET', '/agent/state', ComputerStateSchema),\n internal('GET', '/hub/state', ComputerStateSchema),\n internal('POST', '/agent/observe', Json),\n internal('POST', '/agent/action', Json, ComputerActionSchema),\n internal('POST', '/agent/stop', ComputerStateSchema, undefined, 202),\n internal(\n 'GET',\n '/hub/activation',\n Type.Union([\n Type.Null(),\n Type.Object({\n requestId: S,\n target: Target,\n durationSeconds: N,\n createdAt: N,\n confirmationExpiresAt: N,\n caller: Type.Object({ locality: values(['local', 'remote']), stepUp: S }),\n }),\n ]),\n ),\n internal('GET', '/hub/authorization', Type.Union([Type.Null(), Type.Object({ grantId: S, expiresAt: O(N) })])),\n internal(\n 'GET',\n '/hub/next',\n Type.Union([\n Type.Null(),\n Type.Object({ id: S, operation: values(['observe', 'act']), payload: O(Json), grantId: S, sequence: O(N) }),\n ]),\n ),\n internal('POST', '/hub/complete', ComputerStateSchema, Type.Object({ id: S, error: O(S), result: O(Json) })),\n internal(\n 'POST',\n '/hub/stop',\n ComputerStateSchema,\n Type.Object({ error: O(S), host: O(Type.Object({ grantId: S, expiresAt: N })), artifact: O(Artifact) }),\n ),\n ],\n sockets: (['global', 'workspace'] as const).flatMap((scope) => [\n {\n id: 'computer.state',\n scope,\n service: 'po.hub',\n member: 'computer_use_state',\n kind: 'channel',\n direction: 'server-to-client',\n description: 'Computer use channel payload.',\n input: Type.Object({ state: ComputerStateSchema, targets: Type.Array(Target), busy: O(Type.Literal(true)) }),\n },\n {\n id: 'computer.command',\n scope,\n service: 'po.hub',\n member: 'computer_use_state',\n kind: 'channel',\n direction: 'client-to-server',\n description: 'Computer use browser channel command.',\n input: Type.Object({ action: values(['status', 'targets', 'stop', 'artifacts']) }),\n },\n ]),\n});\nexport default apiContracts;\n"],"mappings":"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"}
@@ -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
  });