@isomorph.ai/app-sdk 1.36.2 → 1.37.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.
- package/README.md +3 -2
- package/dist/computer-use.d.ts +13 -0
- package/dist/computer-use.js +14 -3
- package/dist/index.d.ts +8 -1
- package/dist/integration-execute-input-rules.d.ts +12 -0
- package/dist/integration-execute-input-rules.js +6 -0
- package/dist/integration-operations.d.ts +7 -0
- package/dist/integration-operations.js +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -393,7 +393,7 @@ A job's agent can hand one browser task, writes included, to the computer use se
|
|
|
393
393
|
import { createComputerUseTool } from '@isomorph.ai/app-sdk/dist/computer-use.js';
|
|
394
394
|
// Inside a job handler:
|
|
395
395
|
const computerUse = createComputerUseTool({ runKey: ctx.runId ?? `my-job/${ctx.scheduledAt}`, progress: ctx.progress, cancelled: ctx.cancelled });
|
|
396
|
-
// Add { computerUse } to generateText's tools. It returns { status: 'done' | 'failed', summary, finalUrl }.
|
|
396
|
+
// Add { computerUse } to generateText's tools. It returns { status: 'done' | 'failed', summary, finalUrl, downloads }.
|
|
397
397
|
```
|
|
398
398
|
|
|
399
399
|
- The tool calls the task API at `ISOMORPH_COMPUTER_USE_URL` (region `ISOMORPH_COMPUTER_USE_REGION`, default `us-east-1`); Provision sets both when the cell has the API. Each request is signed with SigV4 (`execute-api`) as the runtime's own role: the Lambda environment's credentials, or on a cluster pod its ServiceAccount role through STS `AssumeRoleWithWebIdentity`.
|
|
@@ -409,10 +409,11 @@ Options the app passes, never the model:
|
|
|
409
409
|
- `session`: the name of a runtime secret a sign-in was saved under (`finishSignIn`'s `saveAs`, below). The task starts signed in and can use only that sign-in's websites. When the task is `done` the refreshed session is saved back to the same secret. A missing one fails with `No saved sign-in named <name>.` Run one task per saved sign-in at a time: two tasks would both save back, and some websites sign out the older copy.
|
|
410
410
|
- `secrets`: `{ name: value }`, at most 10, names `^[A-Za-z][A-Za-z0-9_-]{0,63}$`, values up to 4096 bytes. The computer types a value into a password field by its name; the model sees only the names. Never put a password or any other credential in the task text; pass it here and say "sign in with the `password` secret".
|
|
411
411
|
- `allowedHosts`: the websites (1 to 10 lower-case hostnames) a task with `secrets` and no `session` may use. A saved sign-in carries its own.
|
|
412
|
+
- `onDownload({ name, contentType, size, blob })`: called once for each file a `done` task downloaded, one at a time, before the tool returns (at most 10 files, 100 MiB each). Store the `blob` yourself; the CUA keeps the files for a day at most. Without it nothing is fetched. A link that does not answer 200 fails the tool. The model only sees `downloads: [{ name, size }]`.
|
|
412
413
|
|
|
413
414
|
A task with `session` or `secrets` works the page through clicks and typing only. `connectionId` is gone: pass `session`.
|
|
414
415
|
|
|
415
|
-
(1.25.0, 1.36.0; data plane ADR 0078, ADR 0090)
|
|
416
|
+
(1.25.0, 1.36.0, 1.37.0; data plane ADR 0078, ADR 0090, ADR 0091)
|
|
416
417
|
|
|
417
418
|
## Browser sign-in for computer use
|
|
418
419
|
|
package/dist/computer-use.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ export interface ComputerUseFile {
|
|
|
3
3
|
contentType: "application/pdf";
|
|
4
4
|
dataBase64: string;
|
|
5
5
|
}
|
|
6
|
+
export interface ComputerUseDownload {
|
|
7
|
+
name: string;
|
|
8
|
+
contentType: string;
|
|
9
|
+
size: number;
|
|
10
|
+
blob: Blob;
|
|
11
|
+
}
|
|
6
12
|
export interface ComputerUseOptions {
|
|
7
13
|
/** App-authorized PDFs, at most five files and 2 MiB total. Never supplied by the model. */
|
|
8
14
|
files?: readonly ComputerUseFile[];
|
|
@@ -18,6 +24,8 @@ export interface ComputerUseOptions {
|
|
|
18
24
|
* Never put a credential in the task text.
|
|
19
25
|
*/
|
|
20
26
|
secrets?: Readonly<Record<string, string>>;
|
|
27
|
+
/** The app's code gets each file the task downloaded, one at a time, when the task is done. Never seen by the model. */
|
|
28
|
+
onDownload?(download: ComputerUseDownload): Promise<void> | void;
|
|
21
29
|
/** The job's runId, or `<job name>/<scheduledAt>` for a scheduled job: one task record per job run. */
|
|
22
30
|
runKey: string;
|
|
23
31
|
/** The job's progress: called on each new step and at least once a minute, which renews the job's lease. */
|
|
@@ -35,6 +43,11 @@ export interface ComputerUseResult {
|
|
|
35
43
|
summary: string | null;
|
|
36
44
|
/** The page the browser was on when the task ended; a sign-in page there means the saved sign-in has expired. */
|
|
37
45
|
finalUrl: string | null;
|
|
46
|
+
/** The files the task downloaded; their bytes went to onDownload. */
|
|
47
|
+
downloads: {
|
|
48
|
+
name: string;
|
|
49
|
+
size: number;
|
|
50
|
+
}[];
|
|
38
51
|
}
|
|
39
52
|
export declare function createComputerUseTool(options: ComputerUseOptions): ({
|
|
40
53
|
deferLoading?: boolean;
|
package/dist/computer-use.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// agent (CUA) and waits for its result. Calls go to the CUA's task API, signed
|
|
3
3
|
// with SigV4 as the runtime's own role (ADR 0078). A saved sign-in is a runtime
|
|
4
4
|
// secret: its session goes with the task and the refreshed one is saved back
|
|
5
|
-
// to it (ADR 0090).
|
|
5
|
+
// to it (ADR 0090). Files the task downloads go to the app's onDownload, never
|
|
6
|
+
// to the model (ADR 0091).
|
|
6
7
|
import { setTimeout as sleep } from 'node:timers/promises';
|
|
7
8
|
import { jsonSchema, tool } from 'ai';
|
|
8
9
|
import { allowedHostsOf, computerUseApi, refused } from './computer-use-api.js';
|
|
@@ -71,7 +72,7 @@ export function createComputerUseTool(options) {
|
|
|
71
72
|
}
|
|
72
73
|
};
|
|
73
74
|
return tool({
|
|
74
|
-
description: 'Do one task in a web browser, such as filling in and submitting a form on a website. Describe the whole task in plain words, with the website address and any details it needs. Waits until the task ends and returns its status and a summary.',
|
|
75
|
+
description: 'Do one task in a web browser, such as filling in and submitting a form on a website. Describe the whole task in plain words, with the website address and any details it needs. Waits until the task ends and returns its status and a summary. Files the task downloads go to the app; the result lists their names.',
|
|
75
76
|
inputSchema: jsonSchema({ type: 'object', properties: { task: { type: 'string', minLength: 1 } }, required: ['task'], additionalProperties: false }),
|
|
76
77
|
execute: async ({ task }) => {
|
|
77
78
|
await api.post('/tasks', {
|
|
@@ -101,7 +102,17 @@ export function createComputerUseTool(options) {
|
|
|
101
102
|
if (answer.status === 'done' || answer.status === 'failed') {
|
|
102
103
|
if (answer.status === 'done' && session !== undefined && answer.session)
|
|
103
104
|
await runtimeSecrets.put(session, JSON.stringify(answer.session), transport);
|
|
104
|
-
|
|
105
|
+
const downloads = answer.downloads ?? [];
|
|
106
|
+
if (options.onDownload) {
|
|
107
|
+
for (const { name, contentType, size, url } of downloads) {
|
|
108
|
+
await options.progress(99, `Computer use download: ${name}`);
|
|
109
|
+
const response = await (options.fetch ?? fetch)(url);
|
|
110
|
+
if (response.status !== 200)
|
|
111
|
+
throw refused(`the download ${name}`, response.status, undefined);
|
|
112
|
+
await options.onDownload({ name, contentType, size, blob: await response.blob() });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { status: answer.status, summary: answer.summary ?? null, finalUrl: answer.final_url ?? null, downloads: downloads.map(({ name, size }) => ({ name, size })) };
|
|
105
116
|
}
|
|
106
117
|
if (answer.steps > steps || now() - reported >= HEARTBEAT_MS) {
|
|
107
118
|
steps = Math.max(steps, answer.steps);
|
package/dist/index.d.ts
CHANGED
|
@@ -1177,6 +1177,13 @@ export type ZohoBooksRequest = {
|
|
|
1177
1177
|
quantity: string;
|
|
1178
1178
|
}[];
|
|
1179
1179
|
};
|
|
1180
|
+
} | {
|
|
1181
|
+
operation: 'zohobooks.invoice.markSent';
|
|
1182
|
+
resource: 'organization';
|
|
1183
|
+
idempotencyKey: string;
|
|
1184
|
+
input: {
|
|
1185
|
+
documentId: string;
|
|
1186
|
+
};
|
|
1180
1187
|
} | {
|
|
1181
1188
|
operation: 'zohobooks.creditnote.create';
|
|
1182
1189
|
resource: 'organization';
|
|
@@ -1744,7 +1751,7 @@ export type IntegrationResult<R extends IntegrationRequest> = R extends {
|
|
|
1744
1751
|
} : R extends {
|
|
1745
1752
|
operation: 'zohobooks.invoice.pdf';
|
|
1746
1753
|
} ? GmailAttachmentReadResult : R extends {
|
|
1747
|
-
operation: 'zohobooks.bill.create' | 'zohobooks.invoice.create' | 'zohobooks.invoice.reviseDraft' | 'zohobooks.creditnote.create';
|
|
1754
|
+
operation: 'zohobooks.bill.create' | 'zohobooks.invoice.create' | 'zohobooks.invoice.reviseDraft' | 'zohobooks.invoice.markSent' | 'zohobooks.creditnote.create';
|
|
1748
1755
|
} ? {
|
|
1749
1756
|
id: string;
|
|
1750
1757
|
} : R extends ZohoBooksRequest ? {
|
|
@@ -2485,6 +2485,18 @@ export declare const IntegrationExecuteInputRules: {
|
|
|
2485
2485
|
};
|
|
2486
2486
|
};
|
|
2487
2487
|
};
|
|
2488
|
+
readonly "zohobooks.invoice.markSent": {
|
|
2489
|
+
readonly idempotencyKey: true;
|
|
2490
|
+
readonly fields: {
|
|
2491
|
+
readonly documentId: {
|
|
2492
|
+
readonly kind: "string";
|
|
2493
|
+
readonly required: true;
|
|
2494
|
+
readonly minLength: 0;
|
|
2495
|
+
readonly maxLength: 32;
|
|
2496
|
+
readonly pattern: "^[0-9]{1,32}$";
|
|
2497
|
+
};
|
|
2498
|
+
};
|
|
2499
|
+
};
|
|
2488
2500
|
readonly "zohobooks.creditnote.create": {
|
|
2489
2501
|
readonly idempotencyKey: true;
|
|
2490
2502
|
readonly fields: {
|
|
@@ -768,6 +768,12 @@ export const IntegrationExecuteInputRules = {
|
|
|
768
768
|
} },
|
|
769
769
|
},
|
|
770
770
|
},
|
|
771
|
+
"zohobooks.invoice.markSent": {
|
|
772
|
+
idempotencyKey: true,
|
|
773
|
+
fields: {
|
|
774
|
+
documentId: { kind: "string", required: true, minLength: 0, maxLength: 32, pattern: "^[0-9]{1,32}$" },
|
|
775
|
+
},
|
|
776
|
+
},
|
|
771
777
|
"zohobooks.creditnote.create": {
|
|
772
778
|
idempotencyKey: true,
|
|
773
779
|
fields: {
|
|
@@ -644,6 +644,13 @@ export declare const IntegrationOperations: {
|
|
|
644
644
|
readonly declaredMode: false;
|
|
645
645
|
readonly idempotencyKey: true;
|
|
646
646
|
};
|
|
647
|
+
readonly "zohobooks.invoice.markSent": {
|
|
648
|
+
readonly kind: "saas";
|
|
649
|
+
readonly identities: readonly ["user"];
|
|
650
|
+
readonly readOnly: false;
|
|
651
|
+
readonly declaredMode: false;
|
|
652
|
+
readonly idempotencyKey: true;
|
|
653
|
+
};
|
|
647
654
|
readonly "zohobooks.creditnote.create": {
|
|
648
655
|
readonly kind: "saas";
|
|
649
656
|
readonly identities: readonly ["user"];
|
|
@@ -834,6 +834,15 @@ export const IntegrationOperations = {
|
|
|
834
834
|
"declaredMode": false,
|
|
835
835
|
"idempotencyKey": true
|
|
836
836
|
},
|
|
837
|
+
"zohobooks.invoice.markSent": {
|
|
838
|
+
"kind": "saas",
|
|
839
|
+
"identities": [
|
|
840
|
+
"user"
|
|
841
|
+
],
|
|
842
|
+
"readOnly": false,
|
|
843
|
+
"declaredMode": false,
|
|
844
|
+
"idempotencyKey": true
|
|
845
|
+
},
|
|
837
846
|
"zohobooks.creditnote.create": {
|
|
838
847
|
"kind": "saas",
|
|
839
848
|
"identities": [
|