pomerado 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/typescript/authoring/core/SKILL.md +12 -0
- package/dist/typescript/authoring/examples/dates-and-dropdowns.js +5 -2
- package/dist/typescript/authoring/examples/dates-and-dropdowns.ts +5 -2
- package/dist/typescript/authoring/examples/dates-and-files.d.ts +4 -4
- package/dist/typescript/authoring/examples/dates-and-files.js +5 -5
- package/dist/typescript/authoring/examples/dates-and-files.ts +5 -5
- package/dist/typescript/authoring/examples/dialog-picker.d.ts +2 -2
- package/dist/typescript/authoring/examples/dialog-picker.js +3 -3
- package/dist/typescript/authoring/examples/dialog-picker.ts +3 -3
- package/dist/typescript/authoring/examples/native-dialog.d.ts +2 -2
- package/dist/typescript/authoring/examples/native-dialog.js +3 -3
- package/dist/typescript/authoring/examples/native-dialog.ts +3 -3
- package/dist/typescript/authoring/examples/navigation.d.ts +4 -4
- package/dist/typescript/authoring/examples/navigation.js +8 -5
- package/dist/typescript/authoring/examples/navigation.ts +8 -5
- package/dist/typescript/authoring/examples/parser.d.ts +2 -2
- package/dist/typescript/authoring/examples/parser.js +1 -1
- package/dist/typescript/authoring/examples/parser.ts +1 -1
- package/dist/typescript/authoring/examples/write-session.d.ts +13 -13
- package/dist/typescript/authoring/examples/write-session.js +9 -9
- package/dist/typescript/authoring/examples/write-session.ts +9 -9
- package/dist/typescript/src/mint/contracts.d.ts +9 -2
- package/dist/typescript/src/mint/contracts.js +8 -0
- package/dist/typescript/src/mint/harness.js +5 -1
- package/dist/typescript/src/mint/publication-block.js +2 -1
- package/dist/typescript/src/mint/registry-feedback.js +4 -0
- package/dist/typescript/src/registry/issues.d.ts +3 -1
- package/dist/typescript/src/registry/site-naming.d.ts +7 -0
- package/dist/typescript/src/registry/site-naming.js +6 -0
- package/package.json +6 -1
|
@@ -140,6 +140,18 @@ request and the flow, never from one caller's account or example.
|
|
|
140
140
|
schema, inside `Schema.optional(...)` for an optional one; a `Schema.Date` keeps it only on
|
|
141
141
|
`Schema.optional(Schema.Date)` or `Schema.propertySignature(Schema.Date)`. Callers see each
|
|
142
142
|
beside its name.
|
|
143
|
+
- Shape inputs and outputs like Pomerado's own API, so every tool reads alike: field names in
|
|
144
|
+
snake_case; dates as `YYYY-MM-DD` and timestamps as ISO 8601 with an offset; money as an
|
|
145
|
+
integer in minor units with an ISO 4217 `currency` beside it, such as `total_minor` 12999 and
|
|
146
|
+
`currency` `"USD"`; enum values in lowercase snake_case (`"premium_economy"`); booleans named
|
|
147
|
+
as statements (`refundable`, not `is_refundable_flag`); lists named in the plural; and the
|
|
148
|
+
unit in the field name or its description (`duration_minutes`). Convert between these and the
|
|
149
|
+
site's own formats in code.
|
|
150
|
+
- Give every input field one `examples` annotation value, which callers, the docs and the Try it
|
|
151
|
+
form use to assemble a sample request: public, generic data such as a well-known airport code
|
|
152
|
+
(`examples: ["SFO"]`), a date a few weeks ahead or a common product category. Never use a value
|
|
153
|
+
from this session: not the caller's input, the owner's answers or anything the site showed
|
|
154
|
+
this account.
|
|
143
155
|
- Descriptions, titles, examples and defaults are published and reviewed for private data,
|
|
144
156
|
and an annotation never declares its contents public. Explain constraints without copying private input
|
|
145
157
|
or unneeded numeric identifiers; for a nonnegative safe integer,
|
|
@@ -20,8 +20,11 @@ const failures = [
|
|
|
20
20
|
export default defineOperation({
|
|
21
21
|
name: "set_departure",
|
|
22
22
|
input: Schema.Struct({
|
|
23
|
-
date: DateOnly.annotations({
|
|
24
|
-
|
|
23
|
+
date: DateOnly.annotations({
|
|
24
|
+
description: "Departure date, YYYY-MM-DD",
|
|
25
|
+
examples: ["2026-11-14"],
|
|
26
|
+
}),
|
|
27
|
+
cabin: Cabin.annotations({ description: "Cabin class to search", examples: ["economy"] }),
|
|
25
28
|
}),
|
|
26
29
|
output: Schema.Struct({
|
|
27
30
|
date: DateOnly.annotations({ description: "Departure date the form now holds, YYYY-MM-DD" }),
|
|
@@ -23,8 +23,11 @@ export default defineOperation(
|
|
|
23
23
|
{
|
|
24
24
|
name: "set_departure",
|
|
25
25
|
input: Schema.Struct({
|
|
26
|
-
date: DateOnly.annotations({
|
|
27
|
-
|
|
26
|
+
date: DateOnly.annotations({
|
|
27
|
+
description: "Departure date, YYYY-MM-DD",
|
|
28
|
+
examples: ["2026-11-14"],
|
|
29
|
+
}),
|
|
30
|
+
cabin: Cabin.annotations({ description: "Cabin class to search", examples: ["economy"] }),
|
|
28
31
|
}),
|
|
29
32
|
output: Schema.Struct({
|
|
30
33
|
date: DateOnly.annotations({ description: "Departure date the form now holds, YYYY-MM-DD" }),
|
|
@@ -9,11 +9,11 @@ export declare const pickTravelDate: import("../../src/runtime/kernel-operation.
|
|
|
9
9
|
}>;
|
|
10
10
|
declare const _default: import("../../src/runtime/kernel-operation.js").KernelOperation<{
|
|
11
11
|
readonly name: string;
|
|
12
|
-
readonly
|
|
13
|
-
readonly
|
|
12
|
+
readonly mime_type: string;
|
|
13
|
+
readonly content_base64: string;
|
|
14
14
|
}, {
|
|
15
|
-
readonly
|
|
16
|
-
readonly
|
|
15
|
+
readonly content_base64: string;
|
|
16
|
+
readonly mime_type: string;
|
|
17
17
|
readonly name: string;
|
|
18
18
|
}, {
|
|
19
19
|
readonly name: string;
|
|
@@ -59,10 +59,10 @@ export default defineOperation({
|
|
|
59
59
|
name: Schema.NonEmptyString.annotations({
|
|
60
60
|
description: "File name for the document, with its extension",
|
|
61
61
|
}),
|
|
62
|
-
|
|
62
|
+
mime_type: Schema.NonEmptyString.annotations({
|
|
63
63
|
description: "The document's media type, such as application/pdf",
|
|
64
64
|
}),
|
|
65
|
-
|
|
65
|
+
content_base64: Schema.String.annotations({ description: "The document's bytes, base64" }),
|
|
66
66
|
}),
|
|
67
67
|
output: Schema.Struct({
|
|
68
68
|
name: Schema.String.annotations({ description: "Name of the file the field now holds" }),
|
|
@@ -79,8 +79,8 @@ export default defineOperation({
|
|
|
79
79
|
await field.setInputFiles(
|
|
80
80
|
{
|
|
81
81
|
name: ${JSON.stringify(input.name)},
|
|
82
|
-
mimeType: ${JSON.stringify(input.
|
|
83
|
-
buffer: Buffer.from(${JSON.stringify(input.
|
|
82
|
+
mimeType: ${JSON.stringify(input.mime_type)},
|
|
83
|
+
buffer: Buffer.from(${JSON.stringify(input.content_base64)}, "base64"),
|
|
84
84
|
},
|
|
85
85
|
{ timeout: 30000 },
|
|
86
86
|
);
|
|
@@ -95,7 +95,7 @@ export default defineOperation({
|
|
|
95
95
|
if ("failure" in result)
|
|
96
96
|
throw new errors.OperationFailure(result.failure, { dispatch: "not_sent" });
|
|
97
97
|
const file = result.files[0];
|
|
98
|
-
const size = Buffer.from(input.
|
|
98
|
+
const size = Buffer.from(input.content_base64, "base64").byteLength;
|
|
99
99
|
// Selection is not proof the site accepted the upload; this reads back only the choice.
|
|
100
100
|
if (result.files.length !== 1 || file?.name !== input.name || file.size !== size)
|
|
101
101
|
throw new errors.OperationFailure("The chosen file did not read back", { dispatch: "sent" });
|
|
@@ -76,10 +76,10 @@ export default defineOperation(
|
|
|
76
76
|
name: Schema.NonEmptyString.annotations({
|
|
77
77
|
description: "File name for the document, with its extension",
|
|
78
78
|
}),
|
|
79
|
-
|
|
79
|
+
mime_type: Schema.NonEmptyString.annotations({
|
|
80
80
|
description: "The document's media type, such as application/pdf",
|
|
81
81
|
}),
|
|
82
|
-
|
|
82
|
+
content_base64: Schema.String.annotations({ description: "The document's bytes, base64" }),
|
|
83
83
|
}),
|
|
84
84
|
output: Schema.Struct({
|
|
85
85
|
name: Schema.String.annotations({ description: "Name of the file the field now holds" }),
|
|
@@ -97,8 +97,8 @@ export default defineOperation(
|
|
|
97
97
|
await field.setInputFiles(
|
|
98
98
|
{
|
|
99
99
|
name: ${JSON.stringify(input.name)},
|
|
100
|
-
mimeType: ${JSON.stringify(input.
|
|
101
|
-
buffer: Buffer.from(${JSON.stringify(input.
|
|
100
|
+
mimeType: ${JSON.stringify(input.mime_type)},
|
|
101
|
+
buffer: Buffer.from(${JSON.stringify(input.content_base64)}, "base64"),
|
|
102
102
|
},
|
|
103
103
|
{ timeout: 30000 },
|
|
104
104
|
);
|
|
@@ -118,7 +118,7 @@ export default defineOperation(
|
|
|
118
118
|
if ("failure" in result)
|
|
119
119
|
throw new errors.OperationFailure(result.failure, { dispatch: "not_sent" });
|
|
120
120
|
const file = result.files[0];
|
|
121
|
-
const size = Buffer.from(input.
|
|
121
|
+
const size = Buffer.from(input.content_base64, "base64").byteLength;
|
|
122
122
|
// Selection is not proof the site accepted the upload; this reads back only the choice.
|
|
123
123
|
if (result.files.length !== 1 || file?.name !== input.name || file.size !== size)
|
|
124
124
|
throw new errors.OperationFailure("The chosen file did not read back", { dispatch: "sent" });
|
|
@@ -5,8 +5,8 @@ declare const _default: import("../../src/runtime/kernel-operation.js").KernelOp
|
|
|
5
5
|
readonly key: string;
|
|
6
6
|
readonly query: string;
|
|
7
7
|
}, {
|
|
8
|
-
readonly
|
|
8
|
+
readonly selected_key: string;
|
|
9
9
|
}, {
|
|
10
|
-
readonly
|
|
10
|
+
readonly selected_key: string;
|
|
11
11
|
}>;
|
|
12
12
|
export default _default;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
import { defineOperation } from "../../src/browser/index.js";
|
|
3
|
-
const Picked = Schema.Union(Schema.Struct({
|
|
3
|
+
const Picked = Schema.Union(Schema.Struct({ selected_key: Schema.NonEmptyString }), Schema.Struct({
|
|
4
4
|
failure: Schema.Literal("query_mismatch", "option_identity_mismatch", "committed_key_mismatch"),
|
|
5
5
|
}));
|
|
6
6
|
// These roles, names and data attributes describe one synthetic site's observed picker.
|
|
@@ -14,7 +14,7 @@ export default defineOperation({
|
|
|
14
14
|
}),
|
|
15
15
|
}),
|
|
16
16
|
output: Schema.Struct({
|
|
17
|
-
|
|
17
|
+
selected_key: Schema.NonEmptyString.annotations({
|
|
18
18
|
description: "Catalog key the page now shows as selected",
|
|
19
19
|
}),
|
|
20
20
|
}),
|
|
@@ -45,7 +45,7 @@ export default defineOperation({
|
|
|
45
45
|
const committed = page.getByRole("textbox", { name: "Selected catalog key", exact: true });
|
|
46
46
|
const until = Date.now() + 30000;
|
|
47
47
|
while (Date.now() < until) {
|
|
48
|
-
if ((await committed.inputValue({ timeout: 1000 })) === key) return {
|
|
48
|
+
if ((await committed.inputValue({ timeout: 1000 })) === key) return { selected_key: key };
|
|
49
49
|
await page.waitForTimeout(100);
|
|
50
50
|
}
|
|
51
51
|
return { failure: "committed_key_mismatch" };
|
|
@@ -2,7 +2,7 @@ import { Schema } from "effect";
|
|
|
2
2
|
import { defineOperation } from "../../src/browser/index.js";
|
|
3
3
|
|
|
4
4
|
const Picked = Schema.Union(
|
|
5
|
-
Schema.Struct({
|
|
5
|
+
Schema.Struct({ selected_key: Schema.NonEmptyString }),
|
|
6
6
|
Schema.Struct({
|
|
7
7
|
failure: Schema.Literal("query_mismatch", "option_identity_mismatch", "committed_key_mismatch"),
|
|
8
8
|
}),
|
|
@@ -20,7 +20,7 @@ export default defineOperation(
|
|
|
20
20
|
}),
|
|
21
21
|
}),
|
|
22
22
|
output: Schema.Struct({
|
|
23
|
-
|
|
23
|
+
selected_key: Schema.NonEmptyString.annotations({
|
|
24
24
|
description: "Catalog key the page now shows as selected",
|
|
25
25
|
}),
|
|
26
26
|
}),
|
|
@@ -52,7 +52,7 @@ export default defineOperation(
|
|
|
52
52
|
const committed = page.getByRole("textbox", { name: "Selected catalog key", exact: true });
|
|
53
53
|
const until = Date.now() + 30000;
|
|
54
54
|
while (Date.now() < until) {
|
|
55
|
-
if ((await committed.inputValue({ timeout: 1000 })) === key) return {
|
|
55
|
+
if ((await committed.inputValue({ timeout: 1000 })) === key) return { selected_key: key };
|
|
56
56
|
await page.waitForTimeout(100);
|
|
57
57
|
}
|
|
58
58
|
return { failure: "committed_key_mismatch" };
|
|
@@ -7,7 +7,7 @@ const InvoiceId = Schema.String.pipe(Schema.pattern(/^[A-Za-z0-9_-]{1,100}$/));
|
|
|
7
7
|
export default defineOperation({
|
|
8
8
|
name: "delete_invoice",
|
|
9
9
|
input: Schema.Struct({
|
|
10
|
-
|
|
10
|
+
invoice_id: InvoiceId.annotations({ description: "ID of the invoice to delete" }),
|
|
11
11
|
}),
|
|
12
12
|
output: Schema.Struct({
|
|
13
13
|
deleted: Schema.Boolean.annotations({
|
|
@@ -18,7 +18,7 @@ export default defineOperation({
|
|
|
18
18
|
const raised = await kernel.browsers.playwright.execute(sessionId, {
|
|
19
19
|
timeout_sec: 30,
|
|
20
20
|
code: `
|
|
21
|
-
const row = page.getByRole("row").filter({ has: page.getByText(${JSON.stringify(input.
|
|
21
|
+
const row = page.getByRole("row").filter({ has: page.getByText(${JSON.stringify(input.invoice_id)}, { exact: true }) });
|
|
22
22
|
if ((await row.count()) !== 1) return { failure: "invoice_missing" };
|
|
23
23
|
const shown = new Promise((resolve) => page.once("dialog", (dialog) => {
|
|
24
24
|
globalThis.dialog = dialog;
|
|
@@ -53,7 +53,7 @@ export default defineOperation({
|
|
|
53
53
|
? `await globalThis.dialog.accept(${JSON.stringify(decision.promptText ?? "")});`
|
|
54
54
|
: "await globalThis.dialog.dismiss();"}
|
|
55
55
|
delete globalThis.dialog;
|
|
56
|
-
const row = page.getByRole("row").filter({ has: page.getByText(${JSON.stringify(input.
|
|
56
|
+
const row = page.getByRole("row").filter({ has: page.getByText(${JSON.stringify(input.invoice_id)}, { exact: true }) });
|
|
57
57
|
// Read the result back: the row is gone only if the site deleted it.
|
|
58
58
|
await row.waitFor({ state: ${JSON.stringify(decision.choice === "accept" ? "detached" : "visible")}, timeout: 10000 });
|
|
59
59
|
return { deleted: (await row.count()) === 0 };
|
|
@@ -10,7 +10,7 @@ export default defineOperation(
|
|
|
10
10
|
{
|
|
11
11
|
name: "delete_invoice",
|
|
12
12
|
input: Schema.Struct({
|
|
13
|
-
|
|
13
|
+
invoice_id: InvoiceId.annotations({ description: "ID of the invoice to delete" }),
|
|
14
14
|
}),
|
|
15
15
|
output: Schema.Struct({
|
|
16
16
|
deleted: Schema.Boolean.annotations({
|
|
@@ -22,7 +22,7 @@ export default defineOperation(
|
|
|
22
22
|
const raised = await kernel.browsers.playwright.execute(sessionId, {
|
|
23
23
|
timeout_sec: 30,
|
|
24
24
|
code: `
|
|
25
|
-
const row = page.getByRole("row").filter({ has: page.getByText(${JSON.stringify(input.
|
|
25
|
+
const row = page.getByRole("row").filter({ has: page.getByText(${JSON.stringify(input.invoice_id)}, { exact: true }) });
|
|
26
26
|
if ((await row.count()) !== 1) return { failure: "invoice_missing" };
|
|
27
27
|
const shown = new Promise((resolve) => page.once("dialog", (dialog) => {
|
|
28
28
|
globalThis.dialog = dialog;
|
|
@@ -64,7 +64,7 @@ export default defineOperation(
|
|
|
64
64
|
: "await globalThis.dialog.dismiss();"
|
|
65
65
|
}
|
|
66
66
|
delete globalThis.dialog;
|
|
67
|
-
const row = page.getByRole("row").filter({ has: page.getByText(${JSON.stringify(input.
|
|
67
|
+
const row = page.getByRole("row").filter({ has: page.getByText(${JSON.stringify(input.invoice_id)}, { exact: true }) });
|
|
68
68
|
// Read the result back: the row is gone only if the site deleted it.
|
|
69
69
|
await row.waitFor({ state: ${JSON.stringify(decision.choice === "accept" ? "detached" : "visible")}, timeout: 10000 });
|
|
70
70
|
return { deleted: (await row.count()) === 0 };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export declare const detailNavigation: import("../../src/runtime/kernel-operation.js").KernelOperation<{
|
|
2
|
-
readonly
|
|
2
|
+
readonly record_id: string;
|
|
3
3
|
}, {
|
|
4
|
-
readonly
|
|
4
|
+
readonly record_id: string;
|
|
5
5
|
}, {
|
|
6
|
-
readonly
|
|
6
|
+
readonly record_id: string;
|
|
7
7
|
readonly title: string;
|
|
8
8
|
}, {
|
|
9
|
-
readonly
|
|
9
|
+
readonly record_id: string;
|
|
10
10
|
readonly title: string;
|
|
11
11
|
}>;
|
|
12
12
|
declare const _default: import("../../src/runtime/kernel-operation.js").KernelOperation<{}, {}, {
|
|
@@ -9,16 +9,19 @@ const Detail = Schema.Union(Schema.Struct({ title: Schema.NonEmptyString }), Sch
|
|
|
9
9
|
export const detailNavigation = defineOperation({
|
|
10
10
|
name: "read_record_detail",
|
|
11
11
|
input: Schema.Struct({
|
|
12
|
-
|
|
12
|
+
record_id: RecordId.annotations({
|
|
13
|
+
description: "ID of the record to read, as in its URL",
|
|
14
|
+
examples: ["record_42"],
|
|
15
|
+
}),
|
|
13
16
|
}),
|
|
14
17
|
output: Schema.Struct({
|
|
15
|
-
|
|
18
|
+
record_id: RecordId.annotations({ description: "ID of the record read" }),
|
|
16
19
|
title: Schema.NonEmptyString.annotations({ description: "The record's title" }),
|
|
17
20
|
}),
|
|
18
21
|
}, async ({ kernel, sessionId, siteOrigin, siteDomain, input, errors }) => {
|
|
19
22
|
if (siteOrigin === undefined)
|
|
20
23
|
throw new errors.OperationFailure("No site origin for a live run", { dispatch: "not_sent" });
|
|
21
|
-
const target = new URL(`/records/${input.
|
|
24
|
+
const target = new URL(`/records/${input.record_id}`, siteOrigin);
|
|
22
25
|
const answer = await kernel.browsers.playwright.execute(sessionId, {
|
|
23
26
|
timeout_sec: 90,
|
|
24
27
|
code: `
|
|
@@ -28,7 +31,7 @@ export const detailNavigation = defineOperation({
|
|
|
28
31
|
const siteDomain = ${JSON.stringify(siteDomain ?? null)};
|
|
29
32
|
const onSite = (url) => siteDomain === null ? url.origin === ${JSON.stringify(siteOrigin)}
|
|
30
33
|
: url.protocol === "https:" && (url.hostname === siteDomain || url.hostname.endsWith("." + siteDomain));
|
|
31
|
-
const recordId = ${JSON.stringify(input.
|
|
34
|
+
const recordId = ${JSON.stringify(input.record_id)};
|
|
32
35
|
const detail = page.getByRole("region", { name: "Record details", exact: true });
|
|
33
36
|
const interstitial = page.getByRole("region", { name: "Continue to record", exact: true });
|
|
34
37
|
const proceed = interstitial.getByRole("button", { name: "Continue", exact: true });
|
|
@@ -81,7 +84,7 @@ export const detailNavigation = defineOperation({
|
|
|
81
84
|
const result = Schema.decodeUnknownSync(Detail)(answer.result);
|
|
82
85
|
if ("failure" in result)
|
|
83
86
|
throw new errors.OperationFailure(result.failure);
|
|
84
|
-
return {
|
|
87
|
+
return { record_id: input.record_id, title: result.title };
|
|
85
88
|
});
|
|
86
89
|
// A bounded first-page read. A fast exploration load does not remove the readiness wait.
|
|
87
90
|
export default defineOperation({
|
|
@@ -20,17 +20,20 @@ export const detailNavigation = defineOperation(
|
|
|
20
20
|
{
|
|
21
21
|
name: "read_record_detail",
|
|
22
22
|
input: Schema.Struct({
|
|
23
|
-
|
|
23
|
+
record_id: RecordId.annotations({
|
|
24
|
+
description: "ID of the record to read, as in its URL",
|
|
25
|
+
examples: ["record_42"],
|
|
26
|
+
}),
|
|
24
27
|
}),
|
|
25
28
|
output: Schema.Struct({
|
|
26
|
-
|
|
29
|
+
record_id: RecordId.annotations({ description: "ID of the record read" }),
|
|
27
30
|
title: Schema.NonEmptyString.annotations({ description: "The record's title" }),
|
|
28
31
|
}),
|
|
29
32
|
},
|
|
30
33
|
async ({ kernel, sessionId, siteOrigin, siteDomain, input, errors }) => {
|
|
31
34
|
if (siteOrigin === undefined)
|
|
32
35
|
throw new errors.OperationFailure("No site origin for a live run", { dispatch: "not_sent" });
|
|
33
|
-
const target = new URL(`/records/${input.
|
|
36
|
+
const target = new URL(`/records/${input.record_id}`, siteOrigin);
|
|
34
37
|
const answer = await kernel.browsers.playwright.execute(sessionId, {
|
|
35
38
|
timeout_sec: 90,
|
|
36
39
|
code: `
|
|
@@ -40,7 +43,7 @@ export const detailNavigation = defineOperation(
|
|
|
40
43
|
const siteDomain = ${JSON.stringify(siteDomain ?? null)};
|
|
41
44
|
const onSite = (url) => siteDomain === null ? url.origin === ${JSON.stringify(siteOrigin)}
|
|
42
45
|
: url.protocol === "https:" && (url.hostname === siteDomain || url.hostname.endsWith("." + siteDomain));
|
|
43
|
-
const recordId = ${JSON.stringify(input.
|
|
46
|
+
const recordId = ${JSON.stringify(input.record_id)};
|
|
44
47
|
const detail = page.getByRole("region", { name: "Record details", exact: true });
|
|
45
48
|
const interstitial = page.getByRole("region", { name: "Continue to record", exact: true });
|
|
46
49
|
const proceed = interstitial.getByRole("button", { name: "Continue", exact: true });
|
|
@@ -92,7 +95,7 @@ export const detailNavigation = defineOperation(
|
|
|
92
95
|
throw new errors.OperationFailure(String(answer.error), { stderr: answer.stderr });
|
|
93
96
|
const result = Schema.decodeUnknownSync(Detail)(answer.result);
|
|
94
97
|
if ("failure" in result) throw new errors.OperationFailure(result.failure);
|
|
95
|
-
return {
|
|
98
|
+
return { record_id: input.record_id, title: result.title };
|
|
96
99
|
},
|
|
97
100
|
);
|
|
98
101
|
|
|
@@ -5,7 +5,7 @@ declare const _default: import("../../src/runtime/kernel-operation.js").KernelOp
|
|
|
5
5
|
}, {
|
|
6
6
|
readonly invoices: readonly {
|
|
7
7
|
readonly id: string;
|
|
8
|
-
readonly
|
|
8
|
+
readonly total_minor: number;
|
|
9
9
|
readonly currency: "USD";
|
|
10
10
|
}[];
|
|
11
11
|
readonly complete: boolean;
|
|
@@ -14,7 +14,7 @@ declare const _default: import("../../src/runtime/kernel-operation.js").KernelOp
|
|
|
14
14
|
readonly invoices: readonly {
|
|
15
15
|
readonly currency: "USD";
|
|
16
16
|
readonly id: string;
|
|
17
|
-
readonly
|
|
17
|
+
readonly total_minor: number;
|
|
18
18
|
}[];
|
|
19
19
|
}>;
|
|
20
20
|
export default _default;
|
|
@@ -2,7 +2,7 @@ import { Schema } from "effect";
|
|
|
2
2
|
import { defineOperation } from "../../src/browser/index.js";
|
|
3
3
|
const Invoice = Schema.Struct({
|
|
4
4
|
id: Schema.NonEmptyString.annotations({ description: "The site's invoice ID" }),
|
|
5
|
-
|
|
5
|
+
total_minor: Schema.Int.annotations({ description: "Invoice total in minor units (cents)" }),
|
|
6
6
|
currency: Schema.Literal("USD").annotations({ description: "Currency of the total" }),
|
|
7
7
|
});
|
|
8
8
|
const Body = Schema.Struct({
|
|
@@ -3,7 +3,7 @@ import { defineOperation } from "../../src/browser/index.js";
|
|
|
3
3
|
|
|
4
4
|
const Invoice = Schema.Struct({
|
|
5
5
|
id: Schema.NonEmptyString.annotations({ description: "The site's invoice ID" }),
|
|
6
|
-
|
|
6
|
+
total_minor: Schema.Int.annotations({ description: "Invoice total in minor units (cents)" }),
|
|
7
7
|
currency: Schema.Literal("USD").annotations({ description: "Currency of the total" }),
|
|
8
8
|
});
|
|
9
9
|
const Body = Schema.Struct({
|
|
@@ -2,48 +2,48 @@ import { Schema } from "effect";
|
|
|
2
2
|
export declare const OrderInput: Schema.Struct<{
|
|
3
3
|
item: Schema.refine<string, typeof Schema.String>;
|
|
4
4
|
quantity: Schema.refine<number, typeof Schema.Int>;
|
|
5
|
-
|
|
5
|
+
gift_wrap: Schema.SchemaClass<boolean, boolean, never>;
|
|
6
6
|
}>;
|
|
7
7
|
/** Act step 1: fills the checkout on the site origin page and stops before the commit. */
|
|
8
8
|
export declare const fillStep: import("../../src/runtime/kernel-operation.js").KernelOperation<{
|
|
9
9
|
readonly item: string;
|
|
10
10
|
readonly quantity: number;
|
|
11
|
-
readonly
|
|
11
|
+
readonly gift_wrap: boolean;
|
|
12
12
|
}, {
|
|
13
|
-
readonly
|
|
13
|
+
readonly gift_wrap: boolean;
|
|
14
14
|
readonly item: string;
|
|
15
15
|
readonly quantity: number;
|
|
16
16
|
}, {
|
|
17
|
-
readonly
|
|
17
|
+
readonly review_shown: boolean;
|
|
18
18
|
}, {
|
|
19
|
-
readonly
|
|
19
|
+
readonly review_shown: boolean;
|
|
20
20
|
}>;
|
|
21
21
|
/** Act step 2: continues on the page step 1 left, commits once and reads the confirmation. */
|
|
22
22
|
export declare const placeStep: import("../../src/runtime/kernel-operation.js").KernelOperation<{
|
|
23
23
|
readonly item: string;
|
|
24
24
|
readonly quantity: number;
|
|
25
|
-
readonly
|
|
25
|
+
readonly gift_wrap: boolean;
|
|
26
26
|
}, {
|
|
27
|
-
readonly
|
|
27
|
+
readonly gift_wrap: boolean;
|
|
28
28
|
readonly item: string;
|
|
29
29
|
readonly quantity: number;
|
|
30
30
|
}, {
|
|
31
|
-
readonly
|
|
31
|
+
readonly order_number: string;
|
|
32
32
|
}, {
|
|
33
|
-
readonly
|
|
33
|
+
readonly order_number: string;
|
|
34
34
|
}>;
|
|
35
35
|
/** The composed script, published without another run: the whole flow from the site origin page. */
|
|
36
36
|
declare const _default: import("../../src/runtime/kernel-operation.js").KernelOperation<{
|
|
37
37
|
readonly item: string;
|
|
38
38
|
readonly quantity: number;
|
|
39
|
-
readonly
|
|
39
|
+
readonly gift_wrap: boolean;
|
|
40
40
|
}, {
|
|
41
|
-
readonly
|
|
41
|
+
readonly gift_wrap: boolean;
|
|
42
42
|
readonly item: string;
|
|
43
43
|
readonly quantity: number;
|
|
44
44
|
}, {
|
|
45
|
-
readonly
|
|
45
|
+
readonly order_number: string;
|
|
46
46
|
}, {
|
|
47
|
-
readonly
|
|
47
|
+
readonly order_number: string;
|
|
48
48
|
}>;
|
|
49
49
|
export default _default;
|
|
@@ -11,15 +11,15 @@ export const OrderInput = Schema.Struct({
|
|
|
11
11
|
quantity: Schema.Int.pipe(Schema.between(1, 99)).annotations({
|
|
12
12
|
description: "How many to order, 1 to 99",
|
|
13
13
|
}),
|
|
14
|
-
|
|
14
|
+
gift_wrap: Schema.Boolean.annotations({ description: "Whether to add gift wrap" }),
|
|
15
15
|
});
|
|
16
16
|
const Placed = Schema.Struct({
|
|
17
|
-
|
|
17
|
+
order_number: Schema.NonEmptyString.annotations({
|
|
18
18
|
description: "Order number from the confirmation",
|
|
19
19
|
}),
|
|
20
20
|
});
|
|
21
|
-
const Filled = Schema.Union(Schema.Struct({
|
|
22
|
-
const Confirmed = Schema.Union(Schema.Struct({
|
|
21
|
+
const Filled = Schema.Union(Schema.Struct({ review_shown: Schema.Literal(true) }), Schema.Struct({ failure: Schema.Literal("checkout_changed") }));
|
|
22
|
+
const Confirmed = Schema.Union(Schema.Struct({ order_number: Schema.NonEmptyString }), Schema.Struct({ failure: Schema.Literal("review_missing", "not_confirmed") }));
|
|
23
23
|
// The act steps and the composed script share these calls, so the published script repeats
|
|
24
24
|
// exactly what the session did.
|
|
25
25
|
/** From the site origin page: open the checkout, fill it from the input and stop at the review step. */
|
|
@@ -36,10 +36,10 @@ const fillCheckout = async ({ kernel, sessionId, siteOrigin, input, errors }) =>
|
|
|
36
36
|
if ((await form.count()) !== 1) return { failure: "checkout_changed" };
|
|
37
37
|
await form.getByLabel("Item", { exact: true }).fill(input.item, { timeout: 5000 });
|
|
38
38
|
await form.getByLabel("Quantity", { exact: true }).fill(String(input.quantity), { timeout: 5000 });
|
|
39
|
-
await form.getByLabel("Gift wrap", { exact: true }).setChecked(input.
|
|
39
|
+
await form.getByLabel("Gift wrap", { exact: true }).setChecked(input.gift_wrap, { timeout: 5000 });
|
|
40
40
|
await form.getByRole("button", { name: "Continue", exact: true }).click({ timeout: 5000 });
|
|
41
41
|
await page.getByRole("button", { name: "Place order", exact: true }).waitFor({ timeout: 10000 });
|
|
42
|
-
return {
|
|
42
|
+
return { review_shown: true };
|
|
43
43
|
`,
|
|
44
44
|
});
|
|
45
45
|
if (!answer.success)
|
|
@@ -63,7 +63,7 @@ const placeAndConfirm = async ({ kernel, sessionId, errors, verified, enteringCo
|
|
|
63
63
|
const confirmation = page.getByRole("status", { name: "Order confirmation", exact: true });
|
|
64
64
|
try { await confirmation.waitFor({ timeout: 15000 }); } catch { return { failure: "not_confirmed" }; }
|
|
65
65
|
const number = /^Order (ORD-[0-9]+)/.exec(await confirmation.innerText())?.[1];
|
|
66
|
-
return number === undefined ? { failure: "not_confirmed" } : {
|
|
66
|
+
return number === undefined ? { failure: "not_confirmed" } : { order_number: number };
|
|
67
67
|
`,
|
|
68
68
|
});
|
|
69
69
|
// A failure after the click leaves the write uncertain. Nothing here resubmits it.
|
|
@@ -83,11 +83,11 @@ export const fillStep = defineOperation({
|
|
|
83
83
|
name: "fill_checkout",
|
|
84
84
|
input: OrderInput,
|
|
85
85
|
output: Schema.Struct({
|
|
86
|
-
|
|
86
|
+
review_shown: Schema.Boolean.annotations({ description: "True once the review step shows" }),
|
|
87
87
|
}),
|
|
88
88
|
}, async (context) => {
|
|
89
89
|
await fillCheckout(context);
|
|
90
|
-
return {
|
|
90
|
+
return { review_shown: true };
|
|
91
91
|
});
|
|
92
92
|
/** Act step 2: continues on the page step 1 left, commits once and reads the confirmation. */
|
|
93
93
|
export const placeStep = defineOperation({ name: "place_order", input: OrderInput, output: Placed }, placeAndConfirm);
|
|
@@ -13,20 +13,20 @@ export const OrderInput = Schema.Struct({
|
|
|
13
13
|
quantity: Schema.Int.pipe(Schema.between(1, 99)).annotations({
|
|
14
14
|
description: "How many to order, 1 to 99",
|
|
15
15
|
}),
|
|
16
|
-
|
|
16
|
+
gift_wrap: Schema.Boolean.annotations({ description: "Whether to add gift wrap" }),
|
|
17
17
|
});
|
|
18
18
|
type OrderInput = typeof OrderInput.Type;
|
|
19
19
|
const Placed = Schema.Struct({
|
|
20
|
-
|
|
20
|
+
order_number: Schema.NonEmptyString.annotations({
|
|
21
21
|
description: "Order number from the confirmation",
|
|
22
22
|
}),
|
|
23
23
|
});
|
|
24
24
|
const Filled = Schema.Union(
|
|
25
|
-
Schema.Struct({
|
|
25
|
+
Schema.Struct({ review_shown: Schema.Literal(true) }),
|
|
26
26
|
Schema.Struct({ failure: Schema.Literal("checkout_changed") }),
|
|
27
27
|
);
|
|
28
28
|
const Confirmed = Schema.Union(
|
|
29
|
-
Schema.Struct({
|
|
29
|
+
Schema.Struct({ order_number: Schema.NonEmptyString }),
|
|
30
30
|
Schema.Struct({ failure: Schema.Literal("review_missing", "not_confirmed") }),
|
|
31
31
|
);
|
|
32
32
|
type Context = KernelOperationContext<OrderInput>;
|
|
@@ -48,10 +48,10 @@ const fillCheckout = async ({ kernel, sessionId, siteOrigin, input, errors }: Co
|
|
|
48
48
|
if ((await form.count()) !== 1) return { failure: "checkout_changed" };
|
|
49
49
|
await form.getByLabel("Item", { exact: true }).fill(input.item, { timeout: 5000 });
|
|
50
50
|
await form.getByLabel("Quantity", { exact: true }).fill(String(input.quantity), { timeout: 5000 });
|
|
51
|
-
await form.getByLabel("Gift wrap", { exact: true }).setChecked(input.
|
|
51
|
+
await form.getByLabel("Gift wrap", { exact: true }).setChecked(input.gift_wrap, { timeout: 5000 });
|
|
52
52
|
await form.getByRole("button", { name: "Continue", exact: true }).click({ timeout: 5000 });
|
|
53
53
|
await page.getByRole("button", { name: "Place order", exact: true }).waitFor({ timeout: 10000 });
|
|
54
|
-
return {
|
|
54
|
+
return { review_shown: true };
|
|
55
55
|
`,
|
|
56
56
|
});
|
|
57
57
|
if (!answer.success)
|
|
@@ -82,7 +82,7 @@ const placeAndConfirm = async ({
|
|
|
82
82
|
const confirmation = page.getByRole("status", { name: "Order confirmation", exact: true });
|
|
83
83
|
try { await confirmation.waitFor({ timeout: 15000 }); } catch { return { failure: "not_confirmed" }; }
|
|
84
84
|
const number = /^Order (ORD-[0-9]+)/.exec(await confirmation.innerText())?.[1];
|
|
85
|
-
return number === undefined ? { failure: "not_confirmed" } : {
|
|
85
|
+
return number === undefined ? { failure: "not_confirmed" } : { order_number: number };
|
|
86
86
|
`,
|
|
87
87
|
});
|
|
88
88
|
// A failure after the click leaves the write uncertain. Nothing here resubmits it.
|
|
@@ -104,12 +104,12 @@ export const fillStep = defineOperation(
|
|
|
104
104
|
name: "fill_checkout",
|
|
105
105
|
input: OrderInput,
|
|
106
106
|
output: Schema.Struct({
|
|
107
|
-
|
|
107
|
+
review_shown: Schema.Boolean.annotations({ description: "True once the review step shows" }),
|
|
108
108
|
}),
|
|
109
109
|
},
|
|
110
110
|
async (context) => {
|
|
111
111
|
await fillCheckout(context);
|
|
112
|
-
return {
|
|
112
|
+
return { review_shown: true };
|
|
113
113
|
},
|
|
114
114
|
);
|
|
115
115
|
|
|
@@ -182,8 +182,12 @@ export declare class MintFailure extends MintFailure_base<{
|
|
|
182
182
|
| "login_url_one_time"
|
|
183
183
|
/** The login URL to publish carries a registered credential; refused every time. */
|
|
184
184
|
| "login_url_contains_credential"
|
|
185
|
-
/** The name or
|
|
185
|
+
/** The name, description, site name or summary to publish carries a registered credential. */
|
|
186
186
|
| "metadata_contains_credential"
|
|
187
|
+
/** The site's integration has no name yet, and the metadata names no `siteName` and `siteSummary`. */
|
|
188
|
+
| "site_metadata_required"
|
|
189
|
+
/** Another enabled tool in the integration this would join has the same tool name. */
|
|
190
|
+
| "tool_name_taken"
|
|
187
191
|
/** The publication gate refused a file Guardian's review reads; `publicationBlock` names it. */
|
|
188
192
|
| "evidence_screening"
|
|
189
193
|
/** A `read_source` of a capture the workspace does not hold: it is not saved yet. */
|
|
@@ -192,7 +196,7 @@ export declare class MintFailure extends MintFailure_base<{
|
|
|
192
196
|
readonly publicationFeedback?: {
|
|
193
197
|
readonly oneTimeParameters?: readonly string[];
|
|
194
198
|
readonly parts?: readonly {
|
|
195
|
-
readonly part: "loginUrl" | "name" | "description";
|
|
199
|
+
readonly part: "loginUrl" | "name" | "description" | "siteName" | "siteSummary";
|
|
196
200
|
readonly credentialKinds: readonly string[];
|
|
197
201
|
}[];
|
|
198
202
|
};
|
|
@@ -440,6 +444,9 @@ export declare const PublicationRequest: Schema.Struct<{
|
|
|
440
444
|
metadata: Schema.Struct<{
|
|
441
445
|
name: typeof Schema.String;
|
|
442
446
|
description: typeof Schema.String;
|
|
447
|
+
/** Required only while the site's integration has no name yet; a later one is ignored. */
|
|
448
|
+
siteName: Schema.optional<Schema.refine<string, Schema.filter<Schema.filter<typeof Schema.String>>>>;
|
|
449
|
+
siteSummary: Schema.optional<Schema.refine<string, Schema.filter<Schema.filter<typeof Schema.String>>>>;
|
|
443
450
|
supportedVariants: Schema.optional<Schema.filter<Schema.filter<Schema.Array$<Schema.Struct<{
|
|
444
451
|
id: Schema.filter<typeof Schema.String>;
|
|
445
452
|
entrypoint: Schema.filter<typeof Schema.String>;
|
|
@@ -2,6 +2,7 @@ import { CredentialRejectedField } from "../runtime/authentication.js";
|
|
|
2
2
|
import { IntakeReasonCode } from "../capabilities/intake-contracts.js";
|
|
3
3
|
import { Context, Data, Schema } from "effect";
|
|
4
4
|
import { AutofillPopup, AutofillApproval, DateOfBirthFormat, IdentifierKinds, maximumStepFields, RejectedMarker, SecretSlots, SignInMethodChoice, } from "../destinations/autofill-contracts.js";
|
|
5
|
+
import { SiteNaming } from "../registry/site-naming.js";
|
|
5
6
|
import { SupportedOperationVariant } from "../registry/operation-variants.js";
|
|
6
7
|
import { ChoiceQuestion, ConfirmQuestion, MultiChoiceQuestion, SecretQuestion, TextQuestion, } from "../runtime/input-request.js";
|
|
7
8
|
import { PublicationFinding, PublicationReason } from "../guardian/review-contracts.js";
|
|
@@ -152,6 +153,13 @@ export const PublicationRequest = Schema.Struct({
|
|
|
152
153
|
metadata: Schema.Struct({
|
|
153
154
|
name: Schema.String,
|
|
154
155
|
description: Schema.String,
|
|
156
|
+
/** Required only while the site's integration has no name yet; a later one is ignored. */
|
|
157
|
+
siteName: Schema.optional(SiteNaming.fields.name.annotations({
|
|
158
|
+
description: "The site's everyday name, as people say it, such as Google Flights",
|
|
159
|
+
})),
|
|
160
|
+
siteSummary: Schema.optional(SiteNaming.fields.summary.annotations({
|
|
161
|
+
description: "One sentence on what the site is, not what this tool does",
|
|
162
|
+
})),
|
|
155
163
|
supportedVariants: Schema.optional(Schema.Array(SupportedOperationVariant).pipe(Schema.minItems(1), Schema.maxItems(32))),
|
|
156
164
|
}),
|
|
157
165
|
coverage: Schema.String,
|
|
@@ -1969,6 +1969,10 @@ export const runMint = (input) => Effect.scoped(Effect.gen(function* () {
|
|
|
1969
1969
|
instruction: "Not published: the source this repair would publish is byte for byte the registered revision's, so there is nothing to publish. A new name or description alone is not a repair. The registered revision stays current and this repair ends here; do not call finish_build again.",
|
|
1970
1970
|
});
|
|
1971
1971
|
}
|
|
1972
|
+
if (error.reason === "tool_name_taken")
|
|
1973
|
+
return notPublished(error.code, error.reason, {}, `Not published and not reviewed: ${registryRefusal("tool_name_taken").instruction}`);
|
|
1974
|
+
if (error.reason === "site_metadata_required")
|
|
1975
|
+
return notPublished(error.code, error.reason, {}, "Not published and not reviewed: this is the first tool of this site's integration, which takes its name from this publication. Add siteName, the site's everyday name as people say it (such as Google Flights, 1 to 60 characters), and siteSummary, one sentence on what the site is, not what this tool does (1 to 160 characters), to finish_build's metadata, and call finish_build again with the same executionId. Both are public: write them from what the site shows anyone, never from this account or session.");
|
|
1972
1976
|
if (error.reason === "variants_unsupported")
|
|
1973
1977
|
return notPublished(error.code, error.reason, {}, "Not published: this Kernel script declares supportedVariants, and only Effect runs dispatch variants, so every call would fail with InvalidOutput. Either remove supportedVariants from the tool's metadata (keep one script that handles the variation itself) and call finish_build again with the same executionId; the recorded example and result stay valid and nothing needs to run again. Or, if variants are essential, make it an offline tool: execute a new example with target pureFiles, then call finish_build with that new executionId. The same executionId is refused again while its receipt is a Kernel script.");
|
|
1974
1978
|
if (error.reason === "http_implementation_untested" ||
|
|
@@ -1981,7 +1985,7 @@ export const runMint = (input) => Effect.scoped(Effect.gen(function* () {
|
|
|
1981
1985
|
return notPublished(error.code, error.reason, { ...error.publicationFeedback }, "Not published yet: the login URL this tool would publish (the loginUrl you passed to authenticate, or the page the browser was on when you passed none) is one authorization request: an identity provider's authorize URL, or a URL carrying one-time authorization values (oneTimeParameters names the authorize path and those values). They are spent once this sign-in ends, so later runs that reopen it would start from stale values. The host changed nothing. Navigate the browser to the site's stable sign-in entry, the page a person would bookmark or the site's own login link before it redirected, run authenticate again with that page's address as loginUrl, then call finish_build again with the same executionId. If no stable entry exists, call finish_build again and the host publishes the URL as it is, flagged. The host asks only once.");
|
|
1982
1986
|
if (error.reason === "login_url_contains_credential" ||
|
|
1983
1987
|
error.reason === "metadata_contains_credential")
|
|
1984
|
-
return notPublished(error.code, error.reason, { ...error.publicationFeedback }, "Not published: each part named in parts holds a registered credential (credentialKinds names the kind, never the value). A published tool never carries one, and the host changes nothing itself. For loginUrl, run authenticate again with a login URL that has no credential in it, the site's plain sign-in page. For name or
|
|
1988
|
+
return notPublished(error.code, error.reason, { ...error.publicationFeedback }, "Not published: each part named in parts holds a registered credential (credentialKinds names the kind, never the value). A published tool never carries one, and the host changes nothing itself. For loginUrl, run authenticate again with a login URL that has no credential in it, the site's plain sign-in page. For name, description, siteName or siteSummary, rewrite the text without it. Then call finish_build again with the same executionId. The host refuses every time until the credential is gone; the build is not over.");
|
|
1985
1989
|
if (error.reason === "secret_handle") {
|
|
1986
1990
|
const path = error.screening?.path ?? "the source";
|
|
1987
1991
|
return notPublished(error.code, error.reason, { path: error.screening?.path }, `Not published: ${path} holds a {{secret.…}} handle. A handle works only in this build's own executions, where the host fills in the caller's answer; published code never holds a handle or a value. Declare the value as a secret question in the operation's questions and read it with ask at run time, as .agents/caller-input/SKILL.md shows, then call finish_build again.`);
|
|
@@ -30,9 +30,10 @@ const matched = (block) => {
|
|
|
30
30
|
*/
|
|
31
31
|
const definitionFeedback = (block) => {
|
|
32
32
|
const file = "publication/definition.json";
|
|
33
|
-
const part = block.section ?? "its name, description, schemas or supported variants";
|
|
33
|
+
const part = block.section ?? "its name, description, site, schemas or supported variants";
|
|
34
34
|
const metadata = block.section === "name" ||
|
|
35
35
|
block.section === "description" ||
|
|
36
|
+
block.section === "site" ||
|
|
36
37
|
block.section === "supportedVariants";
|
|
37
38
|
const fix = metadata
|
|
38
39
|
? "Change it in finish_build's metadata, then call finish_build again with the same executionId."
|
|
@@ -61,6 +61,10 @@ const feedback = {
|
|
|
61
61
|
fixable: true,
|
|
62
62
|
instruction: "The published tool changed while this build ran: another publication advanced it, and the host did not commit this build over it. If this build should still replace that version, call finish_build again with the same executionId; the host reads the current version and reviews the publication afresh. Otherwise end the build.",
|
|
63
63
|
},
|
|
64
|
+
tool_name_taken: {
|
|
65
|
+
fixable: true,
|
|
66
|
+
instruction: 'Another tool on this site already has this name: tool names are unique within a site\'s integration, and callers pick a tool by its name. Give this tool a name that says what it does differently, a 2–5 word verb phrase such as "Search award flights" beside "Search flights", in finish_build\'s metadata, and call finish_build again with the same executionId.',
|
|
67
|
+
},
|
|
64
68
|
revision_exists: {
|
|
65
69
|
fixable: false,
|
|
66
70
|
instruction: "The registry already holds a different revision under this build's revision id.",
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
export type RegistryIssue = "definition_invalid" | "site_origin_invalid" | "destination_evidence_invalid" | "variants_invalid" | "login_url_without_signed_in_browser" | "login_url_unusable" | "target_mismatch" | "write_confirmation_on_read" | "catalog_generation_invalid" | "attempt_stopped" | "catalog_moved" | "variant_removed" | "variant_contract_changed" | "generation_moved" | "revision_exists"
|
|
1
|
+
export type RegistryIssue = "definition_invalid" | "site_origin_invalid" | "destination_evidence_invalid" | "variants_invalid" | "login_url_without_signed_in_browser" | "login_url_unusable" | "target_mismatch" | "write_confirmation_on_read" | "catalog_generation_invalid" | "attempt_stopped" | "catalog_moved" | "variant_removed" | "variant_contract_changed" | "generation_moved" | "revision_exists"
|
|
2
|
+
/** Another enabled tool in the integration has the same tool name. */
|
|
3
|
+
| "tool_name_taken";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** A website integration's site: its everyday name ("Google Flights") and what the site is, never its tools. */
|
|
3
|
+
export declare const SiteNaming: Schema.Struct<{
|
|
4
|
+
name: Schema.filter<Schema.filter<Schema.filter<typeof Schema.String>>>;
|
|
5
|
+
summary: Schema.filter<Schema.filter<Schema.filter<typeof Schema.String>>>;
|
|
6
|
+
}>;
|
|
7
|
+
export type SiteNaming = typeof SiteNaming.Type;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** A website integration's site: its everyday name ("Google Flights") and what the site is, never its tools. */
|
|
3
|
+
export const SiteNaming = Schema.Struct({
|
|
4
|
+
name: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(60), Schema.pattern(/\S/)),
|
|
5
|
+
summary: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(160), Schema.pattern(/\S/)),
|
|
6
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pomerado",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Pomerado's integration minter and Guardian with local compute and native Playwright",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -586,6 +586,11 @@
|
|
|
586
586
|
"types": "./dist/typescript/authoring/examples/write-session.d.ts",
|
|
587
587
|
"import": "./dist/typescript/authoring/examples/write-session.js",
|
|
588
588
|
"default": "./dist/typescript/authoring/examples/write-session.js"
|
|
589
|
+
},
|
|
590
|
+
"./core/registry/site-naming": {
|
|
591
|
+
"types": "./dist/typescript/src/registry/site-naming.d.ts",
|
|
592
|
+
"import": "./dist/typescript/src/registry/site-naming.js",
|
|
593
|
+
"default": "./dist/typescript/src/registry/site-naming.js"
|
|
589
594
|
}
|
|
590
595
|
},
|
|
591
596
|
"files": [
|