@terreno/blocks 57.10.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/LICENSE +21 -0
- package/README.md +62 -0
- package/biome.jsonc +18 -0
- package/bunfig.toml +6 -0
- package/dist/asks/errors.d.ts +77 -0
- package/dist/asks/errors.js +364 -0
- package/dist/asks/files.d.ts +53 -0
- package/dist/asks/files.js +171 -0
- package/dist/asks/formValues.d.ts +32 -0
- package/dist/asks/formValues.js +229 -0
- package/dist/asks/headless.d.ts +227 -0
- package/dist/asks/headless.js +94 -0
- package/dist/asks/jsonSchema.d.ts +6 -0
- package/dist/asks/jsonSchema.js +62 -0
- package/dist/asks/limits.d.ts +58 -0
- package/dist/asks/limits.js +61 -0
- package/dist/asks/prompt.d.ts +10 -0
- package/dist/asks/prompt.js +144 -0
- package/dist/asks/schema.d.ts +826 -0
- package/dist/asks/schema.js +864 -0
- package/dist/asks/simpleCard.d.ts +85 -0
- package/dist/asks/simpleCard.js +279 -0
- package/dist/asks/validateInput.d.ts +13 -0
- package/dist/asks/validateInput.js +19 -0
- package/dist/asks/validateResponse.d.ts +13 -0
- package/dist/asks/validateResponse.js +278 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +58 -0
- package/dist/errors.d.ts +51 -0
- package/dist/errors.js +106 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +111 -0
- package/dist/jsonSchema.d.ts +5 -0
- package/dist/jsonSchema.js +12 -0
- package/dist/limits.d.ts +27 -0
- package/dist/limits.js +30 -0
- package/dist/lint.d.ts +21 -0
- package/dist/lint.js +388 -0
- package/dist/parse.d.ts +16 -0
- package/dist/parse.js +95 -0
- package/dist/parsePartial.d.ts +12 -0
- package/dist/parsePartial.js +105 -0
- package/dist/prompt.d.ts +9 -0
- package/dist/prompt.js +95 -0
- package/dist/schema.d.ts +199 -0
- package/dist/schema.js +277 -0
- package/dist/validate.d.ts +17 -0
- package/dist/validate.js +331 -0
- package/package.json +60 -0
- package/schemas/pendingAsksResponse.schema.json +195 -0
- package/schemas/simpleCard.schema.json +135 -0
- package/schemas/turnRequest.schema.json +108 -0
- package/schemas/turnResponse.schema.json +204 -0
- package/scripts/writeJsonSchemas.ts +11 -0
- package/src/asks/docParity.test.ts +65 -0
- package/src/asks/errors.test.ts +250 -0
- package/src/asks/errors.ts +449 -0
- package/src/asks/files.test.ts +294 -0
- package/src/asks/files.ts +216 -0
- package/src/asks/fixtures/invalid/choice-blank-text.json +20 -0
- package/src/asks/fixtures/invalid/choice-default-not-in-options.json +13 -0
- package/src/asks/fixtures/invalid/choice-default-selects-two.json +16 -0
- package/src/asks/fixtures/invalid/choice-description-too-long.json +24 -0
- package/src/asks/fixtures/invalid/choice-duplicate-ids.json +17 -0
- package/src/asks/fixtures/invalid/choice-label-too-long.json +23 -0
- package/src/asks/fixtures/invalid/choice-many-bounds-not-whole.json +17 -0
- package/src/asks/fixtures/invalid/choice-many-bounds-out-of-range.json +17 -0
- package/src/asks/fixtures/invalid/choice-many-default-duplicate.json +17 -0
- package/src/asks/fixtures/invalid/choice-many-default-too-many.json +15 -0
- package/src/asks/fixtures/invalid/choice-many-max-above-options.json +14 -0
- package/src/asks/fixtures/invalid/choice-many-min-above-choices.json +13 -0
- package/src/asks/fixtures/invalid/choice-many-min-above-max.json +15 -0
- package/src/asks/fixtures/invalid/choice-missing-required.json +14 -0
- package/src/asks/fixtures/invalid/choice-mixed-errors.json +19 -0
- package/src/asks/fixtures/invalid/choice-not-an-object.json +5 -0
- package/src/asks/fixtures/invalid/choice-one-with-many-fields.json +19 -0
- package/src/asks/fixtures/invalid/choice-option-id-format.json +35 -0
- package/src/asks/fixtures/invalid/choice-options-not-objects.json +12 -0
- package/src/asks/fixtures/invalid/choice-other-label-too-long.json +25 -0
- package/src/asks/fixtures/invalid/choice-other-label-without-allow-other.json +14 -0
- package/src/asks/fixtures/invalid/choice-prompt-empty.json +12 -0
- package/src/asks/fixtures/invalid/choice-prompt-too-long.json +23 -0
- package/src/asks/fixtures/invalid/choice-select-unknown.json +12 -0
- package/src/asks/fixtures/invalid/choice-submit-label-too-long.json +13 -0
- package/src/asks/fixtures/invalid/choice-title-too-long.json +24 -0
- package/src/asks/fixtures/invalid/choice-too-few-options.json +9 -0
- package/src/asks/fixtures/invalid/choice-too-many-options.json +219 -0
- package/src/asks/fixtures/invalid/choice-unknown-key-option.json +15 -0
- package/src/asks/fixtures/invalid/choice-unknown-key-root.json +13 -0
- package/src/asks/fixtures/invalid/choice-wrong-types.json +16 -0
- package/src/asks/fixtures/invalid/confirm-emoji-label-too-long.json +13 -0
- package/src/asks/fixtures/invalid/confirm-label-too-long.json +14 -0
- package/src/asks/fixtures/invalid/confirm-labels-alike-after-trim.json +14 -0
- package/src/asks/fixtures/invalid/confirm-labels-alike.json +13 -0
- package/src/asks/fixtures/invalid/confirm-missing-prompt-blank-label.json +16 -0
- package/src/asks/fixtures/invalid/confirm-unknown-keys.json +23 -0
- package/src/asks/fixtures/invalid/confirm-wrong-types.json +18 -0
- package/src/asks/fixtures/invalid/files-accept-duplicate.json +13 -0
- package/src/asks/fixtures/invalid/files-accept-empty.json +13 -0
- package/src/asks/fixtures/invalid/files-accept-unknown.json +13 -0
- package/src/asks/fixtures/invalid/files-counts-out-of-range.json +19 -0
- package/src/asks/fixtures/invalid/files-min-above-max.json +15 -0
- package/src/asks/fixtures/invalid/files-missing-accept-unknown-key.json +17 -0
- package/src/asks/fixtures/invalid/form-default-bad-format.json +40 -0
- package/src/asks/fixtures/invalid/form-default-invalid-date.json +40 -0
- package/src/asks/fixtures/invalid/form-default-not-in-options.json +58 -0
- package/src/asks/fixtures/invalid/form-default-out-of-range.json +33 -0
- package/src/asks/fixtures/invalid/form-default-text-bounds.json +42 -0
- package/src/asks/fixtures/invalid/form-default-wrong-type.json +30 -0
- package/src/asks/fixtures/invalid/form-duplicate-field-ids.json +24 -0
- package/src/asks/fixtures/invalid/form-field-id-format.json +19 -0
- package/src/asks/fixtures/invalid/form-field-text-limits.json +33 -0
- package/src/asks/fixtures/invalid/form-keys-of-another-type.json +39 -0
- package/src/asks/fixtures/invalid/form-length-above-cap.json +30 -0
- package/src/asks/fixtures/invalid/form-min-above-max.json +32 -0
- package/src/asks/fixtures/invalid/form-no-fields.json +13 -0
- package/src/asks/fixtures/invalid/form-select-options.json +44 -0
- package/src/asks/fixtures/invalid/form-too-many-fields.json +59 -0
- package/src/asks/fixtures/invalid/form-unknown-field-type.json +27 -0
- package/src/asks/fixtures/invalid/markdown-bounds-out-of-range.json +18 -0
- package/src/asks/fixtures/invalid/markdown-initial-above-cap.json +13 -0
- package/src/asks/fixtures/invalid/markdown-max-above-cap.json +13 -0
- package/src/asks/fixtures/invalid/markdown-min-above-cap.json +13 -0
- package/src/asks/fixtures/invalid/markdown-min-above-max.json +14 -0
- package/src/asks/fixtures/invalid/markdown-placeholder-too-long.json +13 -0
- package/src/asks/fixtures/invalid/markdown-wrong-types-unknown-key.json +27 -0
- package/src/asks/fixtures/valid/choice-emoji-label-cut.json +32 -0
- package/src/asks/fixtures/valid/choice-labels-collide-after-cut.json +21 -0
- package/src/asks/fixtures/valid/choice-long-text-cut.json +41 -0
- package/src/asks/fixtures/valid/choice-many-default-below-min.json +24 -0
- package/src/asks/fixtures/valid/choice-many-every-choice-with-other.json +24 -0
- package/src/asks/fixtures/valid/choice-many-no-default.json +21 -0
- package/src/asks/fixtures/valid/choice-many-optional-no-buttons.json +20 -0
- package/src/asks/fixtures/valid/choice-many-options-default-label-collides.json +23 -0
- package/src/asks/fixtures/valid/choice-many-options-no-buttons.json +21 -0
- package/src/asks/fixtures/valid/choice-many-options-no-default.json +22 -0
- package/src/asks/fixtures/valid/choice-many-options-with-default.json +30 -0
- package/src/asks/fixtures/valid/choice-many-required-with-default.json +29 -0
- package/src/asks/fixtures/valid/choice-many-single-pick-or-other.json +29 -0
- package/src/asks/fixtures/valid/choice-many-toppings-with-default.json +36 -0
- package/src/asks/fixtures/valid/choice-max-limits.json +245 -0
- package/src/asks/fixtures/valid/choice-plan-with-default.json +42 -0
- package/src/asks/fixtures/valid/choice-two-options-no-decline.json +32 -0
- package/src/asks/fixtures/valid/choice-two-options.json +32 -0
- package/src/asks/fixtures/valid/confirm-allow-decline.json +40 -0
- package/src/asks/fixtures/valid/confirm-default-labels.json +36 -0
- package/src/asks/fixtures/valid/confirm-destructive-delete.json +41 -0
- package/src/asks/fixtures/valid/confirm-emoji-labels.json +38 -0
- package/src/asks/fixtures/valid/confirm-long-text-cut.json +40 -0
- package/src/asks/fixtures/valid/files-every-type.json +28 -0
- package/src/asks/fixtures/valid/files-one-csv-no-decline.json +16 -0
- package/src/asks/fixtures/valid/files-receipt-photos.json +24 -0
- package/src/asks/fixtures/valid/form-boolean-newsletter.json +30 -0
- package/src/asks/fixtures/valid/form-date-due.json +44 -0
- package/src/asks/fixtures/valid/form-datetime-meeting.json +44 -0
- package/src/asks/fixtures/valid/form-datetime-minutes-offset.json +44 -0
- package/src/asks/fixtures/valid/form-eight-fields.json +71 -0
- package/src/asks/fixtures/valid/form-email-contact.json +44 -0
- package/src/asks/fixtures/valid/form-invoice-details.json +68 -0
- package/src/asks/fixtures/valid/form-multiselect-channels.json +64 -0
- package/src/asks/fixtures/valid/form-number-budget.json +45 -0
- package/src/asks/fixtures/valid/form-phone-callback.json +44 -0
- package/src/asks/fixtures/valid/form-select-shipping.json +58 -0
- package/src/asks/fixtures/valid/form-text-required-default.json +47 -0
- package/src/asks/fixtures/valid/form-textarea-notes.json +23 -0
- package/src/asks/fixtures/valid/form-time-reminder.json +44 -0
- package/src/asks/fixtures/valid/form-url-website.json +30 -0
- package/src/asks/fixtures/valid/markdown-announcement-draft.json +39 -0
- package/src/asks/fixtures/valid/markdown-empty-draft.json +34 -0
- package/src/asks/fixtures/valid/markdown-initial-blank-below-min.json +24 -0
- package/src/asks/fixtures/valid/markdown-initial-over-max.json +24 -0
- package/src/asks/fixtures/valid/markdown-long-text-cut.json +37 -0
- package/src/asks/fixtures/valid/markdown-no-decline.json +28 -0
- package/src/asks/fixtures/valid/markdown-no-initial-with-min.json +25 -0
- package/src/asks/formValues.ts +320 -0
- package/src/asks/headless.test.ts +146 -0
- package/src/asks/headless.ts +130 -0
- package/src/asks/jsonSchema.test.ts +171 -0
- package/src/asks/jsonSchema.ts +89 -0
- package/src/asks/limits.ts +58 -0
- package/src/asks/prompt.test.ts +200 -0
- package/src/asks/prompt.ts +173 -0
- package/src/asks/schema.test.ts +198 -0
- package/src/asks/schema.ts +1203 -0
- package/src/asks/simpleCard.test.ts +998 -0
- package/src/asks/simpleCard.ts +341 -0
- package/src/asks/validateInput.test.ts +875 -0
- package/src/asks/validateInput.ts +24 -0
- package/src/asks/validateResponse.test.ts +740 -0
- package/src/asks/validateResponse.ts +341 -0
- package/src/blocksDocParity.test.ts +21 -0
- package/src/cli.test.ts +134 -0
- package/src/cli.ts +65 -0
- package/src/display.test.ts +68 -0
- package/src/errors.test.ts +29 -0
- package/src/errors.ts +125 -0
- package/src/fixtures/invalid/column-not-found.yaml +14 -0
- package/src/fixtures/invalid/column-type.yaml +14 -0
- package/src/fixtures/invalid/dataset-not-found.yaml +7 -0
- package/src/fixtures/invalid/dataset-too-large.yaml +20 -0
- package/src/fixtures/invalid/depth-exceeded.yaml +10 -0
- package/src/fixtures/invalid/duplicate-id.yaml +6 -0
- package/src/fixtures/invalid/invalid-enum.yaml +5 -0
- package/src/fixtures/invalid/key-order.yaml +4 -0
- package/src/fixtures/invalid/missing-required.yaml +3 -0
- package/src/fixtures/invalid/not-a-document.txt +1 -0
- package/src/fixtures/invalid/row-arity.yaml +11 -0
- package/src/fixtures/invalid/select-target.yaml +12 -0
- package/src/fixtures/invalid/table-too-wide.yaml +9 -0
- package/src/fixtures/invalid/too-many-points.yaml +8 -0
- package/src/fixtures/invalid/unknown-key.yaml +5 -0
- package/src/fixtures/invalid/unsupported-version.yaml +4 -0
- package/src/fixtures/invalid/yaml-anchor.yaml +6 -0
- package/src/fixtures/partial/cut-after-divider.yaml +5 -0
- package/src/fixtures/valid/actions.yaml +32 -0
- package/src/fixtures/valid/chart.yaml +20 -0
- package/src/fixtures/valid/layout.yaml +26 -0
- package/src/fixtures/valid/prose.yaml +4 -0
- package/src/html.test.ts +52 -0
- package/src/index.test.ts +114 -0
- package/src/index.ts +175 -0
- package/src/jsonSchema.test.ts +33 -0
- package/src/jsonSchema.ts +11 -0
- package/src/limits.ts +27 -0
- package/src/lint.test.ts +289 -0
- package/src/lint.ts +484 -0
- package/src/parse.test.ts +281 -0
- package/src/parse.ts +104 -0
- package/src/parsePartial.test.ts +53 -0
- package/src/parsePartial.ts +116 -0
- package/src/prompt.test.ts +24 -0
- package/src/prompt.ts +104 -0
- package/src/schema.ts +509 -0
- package/src/tests/askFixtures.ts +40 -0
- package/src/validate.perf.test.ts +43 -0
- package/src/validate.ts +369 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fileNotOwnedError = exports.checkAskFileBytes = exports.fileTooLargeDraft = exports.sniffFileBytes = exports.base64ByteLength = exports.parseAskDataUrl = exports.isTextFileMimeType = exports.acceptedFileMimeTypes = exports.ASK_FILE_ACCEPT = exports.ASK_FILE_ACCEPT_MIME_TYPES = void 0;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
/** What a `files` ask may accept, and the MIME types each value allows. */
|
|
6
|
+
exports.ASK_FILE_ACCEPT_MIME_TYPES = {
|
|
7
|
+
csv: ["text/csv"],
|
|
8
|
+
image: ["image/jpeg", "image/png", "image/gif", "image/webp"],
|
|
9
|
+
json: ["application/json"],
|
|
10
|
+
pdf: ["application/pdf"],
|
|
11
|
+
text: ["text/plain"],
|
|
12
|
+
};
|
|
13
|
+
/** The values of a `files` ask's `accept` list, in the order the docs and prompt list them. */
|
|
14
|
+
exports.ASK_FILE_ACCEPT = ["image", "pdf", "text", "csv", "json"];
|
|
15
|
+
/** The MIME types an `accept` list allows, each listed once, in `accept` order. */
|
|
16
|
+
const acceptedFileMimeTypes = (accept) => [
|
|
17
|
+
...new Set(accept.flatMap((value) => exports.ASK_FILE_ACCEPT_MIME_TYPES[value])),
|
|
18
|
+
];
|
|
19
|
+
exports.acceptedFileMimeTypes = acceptedFileMimeTypes;
|
|
20
|
+
const TEXT_MIME_TYPES = ["text/plain", "text/csv", "application/json"];
|
|
21
|
+
/** Whether a file of this type reaches the model as text rather than as bytes. */
|
|
22
|
+
const isTextFileMimeType = (mimeType) => TEXT_MIME_TYPES.includes(mimeType);
|
|
23
|
+
exports.isTextFileMimeType = isTextFileMimeType;
|
|
24
|
+
const BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
25
|
+
/**
|
|
26
|
+
* Splits a base64 `data:` URL into its media type (lowercase, without parameters) and payload.
|
|
27
|
+
* Returns undefined for anything else, including URL-encoded data URLs and remote URLs.
|
|
28
|
+
*/
|
|
29
|
+
const parseAskDataUrl = (url) => {
|
|
30
|
+
if (!url.startsWith("data:")) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const comma = url.indexOf(",");
|
|
34
|
+
if (comma === -1) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const params = url.slice("data:".length, comma).split(";");
|
|
38
|
+
if (params.length < 2 || params.at(-1)?.toLowerCase() !== "base64") {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
const mediaType = params[0].trim().toLowerCase();
|
|
42
|
+
const base64 = url.slice(comma + 1);
|
|
43
|
+
if (mediaType === "" || base64.length % 4 !== 0 || !BASE64_PATTERN.test(base64)) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
return { base64, mediaType };
|
|
47
|
+
};
|
|
48
|
+
exports.parseAskDataUrl = parseAskDataUrl;
|
|
49
|
+
/** The number of bytes a base64 payload decodes to. */
|
|
50
|
+
const base64ByteLength = (base64) => {
|
|
51
|
+
const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
|
|
52
|
+
return (base64.length / 4) * 3 - padding;
|
|
53
|
+
};
|
|
54
|
+
exports.base64ByteLength = base64ByteLength;
|
|
55
|
+
const startsWith = (bytes, signature, offset = 0) => bytes.length >= offset + signature.length &&
|
|
56
|
+
signature.every((byte, index) => bytes[offset + index] === byte);
|
|
57
|
+
const ascii = (text) => [...text].map((character) => character.charCodeAt(0));
|
|
58
|
+
const decodeUtf8 = (bytes) => {
|
|
59
|
+
try {
|
|
60
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Reads a file's type from its first bytes. Images and PDFs are matched by their signatures;
|
|
68
|
+
* anything else that is valid UTF-8 with no NUL character is text.
|
|
69
|
+
*/
|
|
70
|
+
const sniffFileBytes = (bytes) => {
|
|
71
|
+
if (startsWith(bytes, [0xff, 0xd8, 0xff])) {
|
|
72
|
+
return "image/jpeg";
|
|
73
|
+
}
|
|
74
|
+
if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) {
|
|
75
|
+
return "image/png";
|
|
76
|
+
}
|
|
77
|
+
if (startsWith(bytes, ascii("GIF87a")) || startsWith(bytes, ascii("GIF89a"))) {
|
|
78
|
+
return "image/gif";
|
|
79
|
+
}
|
|
80
|
+
if (startsWith(bytes, ascii("RIFF")) && startsWith(bytes, ascii("WEBP"), 8)) {
|
|
81
|
+
return "image/webp";
|
|
82
|
+
}
|
|
83
|
+
if (startsWith(bytes, ascii("%PDF-"))) {
|
|
84
|
+
return "application/pdf";
|
|
85
|
+
}
|
|
86
|
+
const text = decodeUtf8(bytes);
|
|
87
|
+
if (text === undefined || text.includes("\u0000")) {
|
|
88
|
+
return "unknown";
|
|
89
|
+
}
|
|
90
|
+
return "text";
|
|
91
|
+
};
|
|
92
|
+
exports.sniffFileBytes = sniffFileBytes;
|
|
93
|
+
const isJson = (bytes) => {
|
|
94
|
+
try {
|
|
95
|
+
JSON.parse(decodeUtf8(bytes) ?? "");
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const bytesMatchType = (bytes, mimeType) => {
|
|
103
|
+
const sniffed = (0, exports.sniffFileBytes)(bytes);
|
|
104
|
+
if (!(0, exports.isTextFileMimeType)(mimeType)) {
|
|
105
|
+
return sniffed === mimeType;
|
|
106
|
+
}
|
|
107
|
+
if (sniffed !== "text") {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return mimeType !== "application/json" || isJson(bytes);
|
|
111
|
+
};
|
|
112
|
+
const describeSniffed = (bytes) => {
|
|
113
|
+
const sniffed = (0, exports.sniffFileBytes)(bytes);
|
|
114
|
+
if (sniffed === "text") {
|
|
115
|
+
return "text";
|
|
116
|
+
}
|
|
117
|
+
if (sniffed === "unknown") {
|
|
118
|
+
return "no accepted type";
|
|
119
|
+
}
|
|
120
|
+
return sniffed;
|
|
121
|
+
};
|
|
122
|
+
const oneDecimal = (value) => Math.round(value * 10) / 10;
|
|
123
|
+
/** "512 bytes", "4.5 KB", or "10 MB". */
|
|
124
|
+
const formatBytes = (bytes) => {
|
|
125
|
+
if (bytes < 1024) {
|
|
126
|
+
return bytes === 1 ? "1 byte" : `${bytes} bytes`;
|
|
127
|
+
}
|
|
128
|
+
if (bytes < 1024 * 1024) {
|
|
129
|
+
return `${oneDecimal(bytes / 1024)} KB`;
|
|
130
|
+
}
|
|
131
|
+
return `${oneDecimal(bytes / 1024 / 1024)} MB`;
|
|
132
|
+
};
|
|
133
|
+
const fileTooLargeDraft = ({ maxFileSizeBytes, segments, size, }) => ({
|
|
134
|
+
code: "FILE_TOO_LARGE",
|
|
135
|
+
fix: `Send a file of ${formatBytes(maxFileSizeBytes)} or less.`,
|
|
136
|
+
message: `The file is ${formatBytes(size)}, but the limit is ${formatBytes(maxFileSizeBytes)}.`,
|
|
137
|
+
segments,
|
|
138
|
+
});
|
|
139
|
+
exports.fileTooLargeDraft = fileTooLargeDraft;
|
|
140
|
+
/**
|
|
141
|
+
* Checks the bytes of the file at `content.files[index]` on the server: they must fit the per-file
|
|
142
|
+
* cap and match the declared MIME type (a JSON file must also parse).
|
|
143
|
+
*/
|
|
144
|
+
const checkAskFileBytes = ({ bytes, index, maxFileSizeBytes, mimeType, }) => {
|
|
145
|
+
const segments = ["content", "files", index];
|
|
146
|
+
if (bytes.length > maxFileSizeBytes) {
|
|
147
|
+
return (0, errors_1.finalizeAskErrors)([
|
|
148
|
+
(0, exports.fileTooLargeDraft)({ maxFileSizeBytes, segments: [...segments, "size"], size: bytes.length }),
|
|
149
|
+
]);
|
|
150
|
+
}
|
|
151
|
+
if (bytesMatchType(bytes, mimeType)) {
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
return (0, errors_1.finalizeAskErrors)([
|
|
155
|
+
{
|
|
156
|
+
code: "MIME_MISMATCH",
|
|
157
|
+
fix: `Send the file with its real type, or a file that is ${mimeType}.`,
|
|
158
|
+
message: `The file is declared as ${mimeType}, but its bytes are ${describeSniffed(bytes)}.`,
|
|
159
|
+
segments: [...segments, "mimeType"],
|
|
160
|
+
},
|
|
161
|
+
]);
|
|
162
|
+
};
|
|
163
|
+
exports.checkAskFileBytes = checkAskFileBytes;
|
|
164
|
+
/** The error for a `fileId` that the caller did not upload, or that the host cannot load. */
|
|
165
|
+
const fileNotOwnedError = ({ index }) => ({
|
|
166
|
+
code: "FILE_NOT_OWNED",
|
|
167
|
+
fix: "Upload the file with POST /files/upload and send the id it returns, or send a data: URL.",
|
|
168
|
+
message: "The file id does not name one of your uploads.",
|
|
169
|
+
path: (0, errors_1.formatAskPath)(["content", "files", index, "fileId"]),
|
|
170
|
+
});
|
|
171
|
+
exports.fileNotOwnedError = fileNotOwnedError;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type AskErrorDraft } from "./errors";
|
|
2
|
+
import type { FormAskInput, FormField } from "./schema";
|
|
3
|
+
/** A value a form answer holds for one field. */
|
|
4
|
+
export type FormValue = boolean | number | string | string[];
|
|
5
|
+
/** The longest value a field accepts, in UTF-16 code units. */
|
|
6
|
+
export declare const formTextMaxLength: (field: FormField) => number;
|
|
7
|
+
/**
|
|
8
|
+
* Whether a value counts as unanswered: a string with no visible characters, or an empty list.
|
|
9
|
+
* `false` and `0` are answers.
|
|
10
|
+
*/
|
|
11
|
+
export declare const isBlankFormValue: (value: unknown) => boolean;
|
|
12
|
+
interface CheckContext {
|
|
13
|
+
field: FormField;
|
|
14
|
+
/** True when the value is the field's `default` in an ask, not a user's answer. */
|
|
15
|
+
isDefault: boolean;
|
|
16
|
+
segments: readonly PropertyKey[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Checks one present value against its field: its JSON type, then the type's own rules (length,
|
|
20
|
+
* format, range, calendar date, offered options). Used for every answer value and every default,
|
|
21
|
+
* so a default is always a value the field accepts. Blank values are the caller's concern, except
|
|
22
|
+
* that a blank default string fails with `TOO_SHORT`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const checkFormValue: ({ field, isDefault, segments, value, }: CheckContext & {
|
|
25
|
+
value: unknown;
|
|
26
|
+
}) => AskErrorDraft[];
|
|
27
|
+
/**
|
|
28
|
+
* The values a form starts with: each field's `default`, keyed by field id. Fields without a
|
|
29
|
+
* default are left out.
|
|
30
|
+
*/
|
|
31
|
+
export declare const formDefaultValues: (input: FormAskInput) => Record<string, FormValue>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formDefaultValues = exports.checkFormValue = exports.isBlankFormValue = exports.formTextMaxLength = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
const limits_1 = require("./limits");
|
|
7
|
+
const emailSchema = zod_1.z.email();
|
|
8
|
+
const urlSchema = zod_1.z.url({ protocol: /^https?$/ });
|
|
9
|
+
const PHONE_CHARACTERS = /^\+?[0-9 ().-]+$/;
|
|
10
|
+
const NON_DIGITS = /\D/g;
|
|
11
|
+
/** The ISO 8601 shape each date field type takes, with an example for fixes. */
|
|
12
|
+
const DATE_FORMATS = {
|
|
13
|
+
date: { example: "2026-10-01", format: "YYYY-MM-DD", schema: zod_1.z.iso.date() },
|
|
14
|
+
datetime: {
|
|
15
|
+
example: "2026-10-01T09:30:00Z",
|
|
16
|
+
format: "an ISO 8601 date and time with Z or an offset such as +02:00 (seconds optional)",
|
|
17
|
+
schema: zod_1.z.union([
|
|
18
|
+
zod_1.z.iso.datetime({ offset: true, precision: -1 }),
|
|
19
|
+
zod_1.z.iso.datetime({ offset: true }),
|
|
20
|
+
]),
|
|
21
|
+
},
|
|
22
|
+
time: { example: "09:30", format: "HH:mm (24-hour)", schema: zod_1.z.iso.time({ precision: -1 }) },
|
|
23
|
+
};
|
|
24
|
+
const TYPE_NAMES = {
|
|
25
|
+
boolean: "true or false",
|
|
26
|
+
date: "a date string",
|
|
27
|
+
datetime: "a datetime string",
|
|
28
|
+
email: "an email address",
|
|
29
|
+
multiselect: "a list of option ids",
|
|
30
|
+
number: "a number",
|
|
31
|
+
phone: "a phone number",
|
|
32
|
+
select: "an option id",
|
|
33
|
+
text: "a string",
|
|
34
|
+
textarea: "a string",
|
|
35
|
+
time: "a time string",
|
|
36
|
+
url: "an http or https URL",
|
|
37
|
+
};
|
|
38
|
+
const characters = (count) => (count === 1 ? "1 character" : `${count} characters`);
|
|
39
|
+
/** The longest value a field accepts, in UTF-16 code units. */
|
|
40
|
+
const formTextMaxLength = (field) => {
|
|
41
|
+
if (field.type === "textarea") {
|
|
42
|
+
return field.maxLength ?? limits_1.ASK_LIMITS.form.textareaMaxLength;
|
|
43
|
+
}
|
|
44
|
+
if (field.type === "text") {
|
|
45
|
+
return field.maxLength ?? limits_1.ASK_LIMITS.form.textMaxLength;
|
|
46
|
+
}
|
|
47
|
+
return limits_1.ASK_LIMITS.form.textMaxLength;
|
|
48
|
+
};
|
|
49
|
+
exports.formTextMaxLength = formTextMaxLength;
|
|
50
|
+
/**
|
|
51
|
+
* Whether a value counts as unanswered: a string with no visible characters, or an empty list.
|
|
52
|
+
* `false` and `0` are answers.
|
|
53
|
+
*/
|
|
54
|
+
const isBlankFormValue = (value) => (typeof value === "string" && value.trim() === "") ||
|
|
55
|
+
(Array.isArray(value) && value.length === 0);
|
|
56
|
+
exports.isBlankFormValue = isBlankFormValue;
|
|
57
|
+
const draft = ({ segments }, code, message, fix) => ({ code, fix, message, segments });
|
|
58
|
+
const mismatch = (context, detail) => {
|
|
59
|
+
const path = (0, errors_1.formatAskPath)(context.segments);
|
|
60
|
+
const expected = TYPE_NAMES[context.field.type];
|
|
61
|
+
return draft(context, "FIELD_TYPE_MISMATCH", detail ??
|
|
62
|
+
`${path} must be ${expected} for the ${context.field.type} field "${context.field.id}".`, `Make ${path} ${expected}.`);
|
|
63
|
+
};
|
|
64
|
+
const checkLength = (context, value) => {
|
|
65
|
+
const path = (0, errors_1.formatAskPath)(context.segments);
|
|
66
|
+
const max = (0, exports.formTextMaxLength)(context.field);
|
|
67
|
+
const drafts = [];
|
|
68
|
+
if (value.length > max) {
|
|
69
|
+
drafts.push(draft(context, "TOO_LONG", `${path} is ${characters(value.length)}, but the field allows at most ${max}.`, `Shorten ${path} to ${characters(max)} or fewer.`));
|
|
70
|
+
}
|
|
71
|
+
const { field } = context;
|
|
72
|
+
const min = field.type === "text" || field.type === "textarea" ? (field.minLength ?? 0) : 0;
|
|
73
|
+
const visibleLength = value.trim().length;
|
|
74
|
+
if (visibleLength === 0 && context.isDefault) {
|
|
75
|
+
drafts.push(draft(context, "TOO_SHORT", `${path} must contain visible text.`, `Write at least one visible character in ${path}, or remove it.`));
|
|
76
|
+
}
|
|
77
|
+
else if (visibleLength < min) {
|
|
78
|
+
drafts.push(draft(context, "TOO_SHORT", `${path} is ${characters(visibleLength)}, but the field needs at least ${min}.`, `Write at least ${characters(min)} in ${path}.`));
|
|
79
|
+
}
|
|
80
|
+
return drafts;
|
|
81
|
+
};
|
|
82
|
+
const checkStringFormat = (context, value) => {
|
|
83
|
+
const path = (0, errors_1.formatAskPath)(context.segments);
|
|
84
|
+
const { type } = context.field;
|
|
85
|
+
if (type === "email" && !emailSchema.safeParse(value).success) {
|
|
86
|
+
return [mismatch(context, `${path} ${(0, errors_1.quoteValue)(value)} is not a valid email address.`)];
|
|
87
|
+
}
|
|
88
|
+
if (type === "url" && !urlSchema.safeParse(value).success) {
|
|
89
|
+
return [mismatch(context, `${path} ${(0, errors_1.quoteValue)(value)} is not an http or https URL.`)];
|
|
90
|
+
}
|
|
91
|
+
if (type === "phone") {
|
|
92
|
+
const digits = value.replace(NON_DIGITS, "").length;
|
|
93
|
+
const { phoneDigitsMax, phoneDigitsMin } = limits_1.ASK_LIMITS.form;
|
|
94
|
+
if (!PHONE_CHARACTERS.test(value) || digits < phoneDigitsMin || digits > phoneDigitsMax) {
|
|
95
|
+
return [
|
|
96
|
+
draft(context, "FIELD_TYPE_MISMATCH", `${path} ${(0, errors_1.quoteValue)(value)} is not a valid phone number.`, `Make ${path} ${phoneDigitsMin}-${phoneDigitsMax} digits, optionally starting with "+", with only spaces, dots, dashes, or parentheses between them.`),
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return [];
|
|
101
|
+
};
|
|
102
|
+
const checkNumber = (context, value) => {
|
|
103
|
+
const { field } = context;
|
|
104
|
+
if (field.type !== "number") {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
108
|
+
return [mismatch(context)];
|
|
109
|
+
}
|
|
110
|
+
const path = (0, errors_1.formatAskPath)(context.segments);
|
|
111
|
+
if (field.integer === true && !Number.isInteger(value)) {
|
|
112
|
+
return [
|
|
113
|
+
draft(context, "FIELD_TYPE_MISMATCH", `${path} is ${value}, but the field takes whole numbers only.`, `Make ${path} a whole number.`),
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
if (field.min !== undefined && value < field.min) {
|
|
117
|
+
return [
|
|
118
|
+
draft(context, "OUT_OF_RANGE", `${path} is ${value}, below the field's min of ${field.min}.`, `Make ${path} at least ${field.min}.`),
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
if (field.max !== undefined && value > field.max) {
|
|
122
|
+
return [
|
|
123
|
+
draft(context, "OUT_OF_RANGE", `${path} is ${value}, above the field's max of ${field.max}.`, `Make ${path} at most ${field.max}.`),
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
return [];
|
|
127
|
+
};
|
|
128
|
+
const notOffered = (context, id, segments) => context.isDefault
|
|
129
|
+
? {
|
|
130
|
+
code: "DEFAULT_NOT_IN_OPTIONS",
|
|
131
|
+
fix: `Use an id from fields[${String(context.segments[1])}].options, or remove it from the default.`,
|
|
132
|
+
message: `Default ${(0, errors_1.quoteValue)(id)} is not the id of any option of the field.`,
|
|
133
|
+
segments,
|
|
134
|
+
}
|
|
135
|
+
: {
|
|
136
|
+
code: "OPTION_NOT_OFFERED",
|
|
137
|
+
fix: `Use the id of one of the options of the field "${context.field.id}".`,
|
|
138
|
+
message: `${(0, errors_1.quoteValue)(id)} is not one of the field's options.`,
|
|
139
|
+
segments,
|
|
140
|
+
};
|
|
141
|
+
const checkOptions = (context, value) => {
|
|
142
|
+
const { field } = context;
|
|
143
|
+
if (field.type !== "select" && field.type !== "multiselect") {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
const offered = new Set(field.options.map((option) => option.id));
|
|
147
|
+
if (field.type === "select") {
|
|
148
|
+
if (typeof value !== "string") {
|
|
149
|
+
return [mismatch(context)];
|
|
150
|
+
}
|
|
151
|
+
return offered.has(value) ? [] : [notOffered(context, value, [...context.segments])];
|
|
152
|
+
}
|
|
153
|
+
if (!Array.isArray(value) || value.some((id) => typeof id !== "string")) {
|
|
154
|
+
return [mismatch(context)];
|
|
155
|
+
}
|
|
156
|
+
const path = (0, errors_1.formatAskPath)(context.segments);
|
|
157
|
+
if (value.length > limits_1.ASK_LIMITS.choice.optionsMax) {
|
|
158
|
+
return [
|
|
159
|
+
draft(context, "TOO_MANY", `${path} has more than ${limits_1.ASK_LIMITS.choice.optionsMax} items.`, `Remove items from ${path} until it has ${limits_1.ASK_LIMITS.choice.optionsMax} or fewer.`),
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
const firstIndexById = new Map();
|
|
163
|
+
return value.flatMap((id, index) => {
|
|
164
|
+
const segments = [...context.segments, index];
|
|
165
|
+
const firstIndex = firstIndexById.get(id);
|
|
166
|
+
if (firstIndex !== undefined) {
|
|
167
|
+
return [
|
|
168
|
+
{
|
|
169
|
+
code: "DUPLICATE_ID",
|
|
170
|
+
fix: `List each option id in ${path} once.`,
|
|
171
|
+
message: `${(0, errors_1.quoteValue)(id)} is already listed at ${(0, errors_1.formatAskPath)([...context.segments, firstIndex])}.`,
|
|
172
|
+
segments,
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
firstIndexById.set(id, index);
|
|
177
|
+
return offered.has(id) ? [] : [notOffered(context, id, segments)];
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Checks one present value against its field: its JSON type, then the type's own rules (length,
|
|
182
|
+
* format, range, calendar date, offered options). Used for every answer value and every default,
|
|
183
|
+
* so a default is always a value the field accepts. Blank values are the caller's concern, except
|
|
184
|
+
* that a blank default string fails with `TOO_SHORT`.
|
|
185
|
+
*/
|
|
186
|
+
const checkFormValue = ({ field, isDefault, segments, value, }) => {
|
|
187
|
+
const context = { field, isDefault, segments };
|
|
188
|
+
switch (field.type) {
|
|
189
|
+
case "boolean":
|
|
190
|
+
return typeof value === "boolean" ? [] : [mismatch(context)];
|
|
191
|
+
case "number":
|
|
192
|
+
return checkNumber(context, value);
|
|
193
|
+
case "select":
|
|
194
|
+
case "multiselect":
|
|
195
|
+
return checkOptions(context, value);
|
|
196
|
+
case "date":
|
|
197
|
+
case "time":
|
|
198
|
+
case "datetime": {
|
|
199
|
+
if (typeof value !== "string") {
|
|
200
|
+
return [mismatch(context)];
|
|
201
|
+
}
|
|
202
|
+
const { example, format, schema } = DATE_FORMATS[field.type];
|
|
203
|
+
if (schema.safeParse(value).success) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
const path = (0, errors_1.formatAskPath)(segments);
|
|
207
|
+
return [
|
|
208
|
+
draft(context, "INVALID_DATE", `${path} ${(0, errors_1.quoteValue)(value)} is not a real ${field.type} in ${format}.`, `Write ${path} as ${format}, such as "${example}".`),
|
|
209
|
+
];
|
|
210
|
+
}
|
|
211
|
+
default: {
|
|
212
|
+
if (typeof value !== "string") {
|
|
213
|
+
return [mismatch(context)];
|
|
214
|
+
}
|
|
215
|
+
const lengthDrafts = checkLength(context, value);
|
|
216
|
+
if (lengthDrafts.length > 0 || value.trim() === "") {
|
|
217
|
+
return lengthDrafts;
|
|
218
|
+
}
|
|
219
|
+
return checkStringFormat(context, value);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
exports.checkFormValue = checkFormValue;
|
|
224
|
+
/**
|
|
225
|
+
* The values a form starts with: each field's `default`, keyed by field id. Fields without a
|
|
226
|
+
* default are left out.
|
|
227
|
+
*/
|
|
228
|
+
const formDefaultValues = (input) => Object.fromEntries(input.fields.flatMap((field) => field.default === undefined ? [] : [[field.id, field.default]]));
|
|
229
|
+
exports.formDefaultValues = formDefaultValues;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const askSurfaceSchema: z.ZodEnum<{
|
|
3
|
+
full: "full";
|
|
4
|
+
compact: "compact";
|
|
5
|
+
}>;
|
|
6
|
+
/** An answer to a pending ask: the answer envelope plus the ask's `toolCallId`. */
|
|
7
|
+
export declare const askResponseWithToolCallIdSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
8
|
+
action: z.ZodLiteral<"accept">;
|
|
9
|
+
content: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
10
|
+
toolCallId: z.ZodString;
|
|
11
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
12
|
+
action: z.ZodLiteral<"decline">;
|
|
13
|
+
toolCallId: z.ZodString;
|
|
14
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
15
|
+
action: z.ZodLiteral<"cancel">;
|
|
16
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
17
|
+
toolCallId: z.ZodString;
|
|
18
|
+
}, z.core.$strict>], "action">;
|
|
19
|
+
export type AskResponseWithToolCallId = z.infer<typeof askResponseWithToolCallIdSchema>;
|
|
20
|
+
/** The body of `POST /gpt/histories/:id/turn`. */
|
|
21
|
+
export declare const turnRequestSchema: z.ZodObject<{
|
|
22
|
+
askResponse: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
23
|
+
action: z.ZodLiteral<"accept">;
|
|
24
|
+
content: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
25
|
+
toolCallId: z.ZodString;
|
|
26
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
27
|
+
action: z.ZodLiteral<"decline">;
|
|
28
|
+
toolCallId: z.ZodString;
|
|
29
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
30
|
+
action: z.ZodLiteral<"cancel">;
|
|
31
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
32
|
+
toolCallId: z.ZodString;
|
|
33
|
+
}, z.core.$strict>], "action">>;
|
|
34
|
+
buttonId: z.ZodOptional<z.ZodString>;
|
|
35
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
36
|
+
surface: z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
full: "full";
|
|
38
|
+
compact: "compact";
|
|
39
|
+
}>>;
|
|
40
|
+
toolCallId: z.ZodOptional<z.ZodString>;
|
|
41
|
+
}, z.core.$strict>;
|
|
42
|
+
export type TurnRequest = z.infer<typeof turnRequestSchema>;
|
|
43
|
+
export declare const pendingAskSummarySchema: z.ZodObject<{
|
|
44
|
+
kind: z.ZodEnum<{
|
|
45
|
+
markdown: "markdown";
|
|
46
|
+
files: "files";
|
|
47
|
+
choice: "choice";
|
|
48
|
+
confirm: "confirm";
|
|
49
|
+
form: "form";
|
|
50
|
+
}>;
|
|
51
|
+
simple: z.ZodObject<{
|
|
52
|
+
buttons: z.ZodArray<z.ZodObject<{
|
|
53
|
+
id: z.ZodString;
|
|
54
|
+
label: z.ZodString;
|
|
55
|
+
response: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
56
|
+
action: z.ZodLiteral<"accept">;
|
|
57
|
+
content: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
58
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
59
|
+
action: z.ZodLiteral<"decline">;
|
|
60
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
61
|
+
action: z.ZodLiteral<"cancel">;
|
|
62
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
63
|
+
}, z.core.$strict>], "action">;
|
|
64
|
+
style: z.ZodEnum<{
|
|
65
|
+
primary: "primary";
|
|
66
|
+
destructive: "destructive";
|
|
67
|
+
default: "default";
|
|
68
|
+
cancel: "cancel";
|
|
69
|
+
}>;
|
|
70
|
+
}, z.core.$strict>>;
|
|
71
|
+
handoff: z.ZodBoolean;
|
|
72
|
+
kind: z.ZodEnum<{
|
|
73
|
+
markdown: "markdown";
|
|
74
|
+
files: "files";
|
|
75
|
+
choice: "choice";
|
|
76
|
+
confirm: "confirm";
|
|
77
|
+
form: "form";
|
|
78
|
+
}>;
|
|
79
|
+
text: z.ZodString;
|
|
80
|
+
title: z.ZodOptional<z.ZodString>;
|
|
81
|
+
toolCallId: z.ZodString;
|
|
82
|
+
}, z.core.$strict>;
|
|
83
|
+
toolCallId: z.ZodString;
|
|
84
|
+
}, z.core.$strict>;
|
|
85
|
+
export type PendingAskSummary = z.infer<typeof pendingAskSummarySchema>;
|
|
86
|
+
/** What `POST /gpt/histories/:id/turn` returns in `data` once the turn finishes. */
|
|
87
|
+
export declare const turnResultSchema: z.ZodObject<{
|
|
88
|
+
error: z.ZodOptional<z.ZodString>;
|
|
89
|
+
historyId: z.ZodString;
|
|
90
|
+
pendingAsk: z.ZodOptional<z.ZodObject<{
|
|
91
|
+
kind: z.ZodEnum<{
|
|
92
|
+
markdown: "markdown";
|
|
93
|
+
files: "files";
|
|
94
|
+
choice: "choice";
|
|
95
|
+
confirm: "confirm";
|
|
96
|
+
form: "form";
|
|
97
|
+
}>;
|
|
98
|
+
simple: z.ZodObject<{
|
|
99
|
+
buttons: z.ZodArray<z.ZodObject<{
|
|
100
|
+
id: z.ZodString;
|
|
101
|
+
label: z.ZodString;
|
|
102
|
+
response: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
103
|
+
action: z.ZodLiteral<"accept">;
|
|
104
|
+
content: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
105
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
106
|
+
action: z.ZodLiteral<"decline">;
|
|
107
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
108
|
+
action: z.ZodLiteral<"cancel">;
|
|
109
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
110
|
+
}, z.core.$strict>], "action">;
|
|
111
|
+
style: z.ZodEnum<{
|
|
112
|
+
primary: "primary";
|
|
113
|
+
destructive: "destructive";
|
|
114
|
+
default: "default";
|
|
115
|
+
cancel: "cancel";
|
|
116
|
+
}>;
|
|
117
|
+
}, z.core.$strict>>;
|
|
118
|
+
handoff: z.ZodBoolean;
|
|
119
|
+
kind: z.ZodEnum<{
|
|
120
|
+
markdown: "markdown";
|
|
121
|
+
files: "files";
|
|
122
|
+
choice: "choice";
|
|
123
|
+
confirm: "confirm";
|
|
124
|
+
form: "form";
|
|
125
|
+
}>;
|
|
126
|
+
text: z.ZodString;
|
|
127
|
+
title: z.ZodOptional<z.ZodString>;
|
|
128
|
+
toolCallId: z.ZodString;
|
|
129
|
+
}, z.core.$strict>;
|
|
130
|
+
toolCallId: z.ZodString;
|
|
131
|
+
}, z.core.$strict>>;
|
|
132
|
+
text: z.ZodString;
|
|
133
|
+
title: z.ZodOptional<z.ZodString>;
|
|
134
|
+
}, z.core.$strict>;
|
|
135
|
+
export type TurnResult = z.infer<typeof turnResultSchema>;
|
|
136
|
+
export declare const pendingAskListItemSchema: z.ZodObject<{
|
|
137
|
+
created: z.ZodISODateTime;
|
|
138
|
+
historyId: z.ZodString;
|
|
139
|
+
kind: z.ZodEnum<{
|
|
140
|
+
markdown: "markdown";
|
|
141
|
+
files: "files";
|
|
142
|
+
choice: "choice";
|
|
143
|
+
confirm: "confirm";
|
|
144
|
+
form: "form";
|
|
145
|
+
}>;
|
|
146
|
+
simple: z.ZodObject<{
|
|
147
|
+
buttons: z.ZodArray<z.ZodObject<{
|
|
148
|
+
id: z.ZodString;
|
|
149
|
+
label: z.ZodString;
|
|
150
|
+
response: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
151
|
+
action: z.ZodLiteral<"accept">;
|
|
152
|
+
content: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
153
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
154
|
+
action: z.ZodLiteral<"decline">;
|
|
155
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
156
|
+
action: z.ZodLiteral<"cancel">;
|
|
157
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
158
|
+
}, z.core.$strict>], "action">;
|
|
159
|
+
style: z.ZodEnum<{
|
|
160
|
+
primary: "primary";
|
|
161
|
+
destructive: "destructive";
|
|
162
|
+
default: "default";
|
|
163
|
+
cancel: "cancel";
|
|
164
|
+
}>;
|
|
165
|
+
}, z.core.$strict>>;
|
|
166
|
+
handoff: z.ZodBoolean;
|
|
167
|
+
kind: z.ZodEnum<{
|
|
168
|
+
markdown: "markdown";
|
|
169
|
+
files: "files";
|
|
170
|
+
choice: "choice";
|
|
171
|
+
confirm: "confirm";
|
|
172
|
+
form: "form";
|
|
173
|
+
}>;
|
|
174
|
+
text: z.ZodString;
|
|
175
|
+
title: z.ZodOptional<z.ZodString>;
|
|
176
|
+
toolCallId: z.ZodString;
|
|
177
|
+
}, z.core.$strict>;
|
|
178
|
+
title: z.ZodOptional<z.ZodString>;
|
|
179
|
+
toolCallId: z.ZodString;
|
|
180
|
+
}, z.core.$strict>;
|
|
181
|
+
export type PendingAskListItem = z.infer<typeof pendingAskListItemSchema>;
|
|
182
|
+
/** What `GET /gpt/histories/pendingAsks` returns in `data`: the caller's pending asks, newest first. */
|
|
183
|
+
export declare const pendingAskListSchema: z.ZodArray<z.ZodObject<{
|
|
184
|
+
created: z.ZodISODateTime;
|
|
185
|
+
historyId: z.ZodString;
|
|
186
|
+
kind: z.ZodEnum<{
|
|
187
|
+
markdown: "markdown";
|
|
188
|
+
files: "files";
|
|
189
|
+
choice: "choice";
|
|
190
|
+
confirm: "confirm";
|
|
191
|
+
form: "form";
|
|
192
|
+
}>;
|
|
193
|
+
simple: z.ZodObject<{
|
|
194
|
+
buttons: z.ZodArray<z.ZodObject<{
|
|
195
|
+
id: z.ZodString;
|
|
196
|
+
label: z.ZodString;
|
|
197
|
+
response: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
198
|
+
action: z.ZodLiteral<"accept">;
|
|
199
|
+
content: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
200
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
201
|
+
action: z.ZodLiteral<"decline">;
|
|
202
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
203
|
+
action: z.ZodLiteral<"cancel">;
|
|
204
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
205
|
+
}, z.core.$strict>], "action">;
|
|
206
|
+
style: z.ZodEnum<{
|
|
207
|
+
primary: "primary";
|
|
208
|
+
destructive: "destructive";
|
|
209
|
+
default: "default";
|
|
210
|
+
cancel: "cancel";
|
|
211
|
+
}>;
|
|
212
|
+
}, z.core.$strict>>;
|
|
213
|
+
handoff: z.ZodBoolean;
|
|
214
|
+
kind: z.ZodEnum<{
|
|
215
|
+
markdown: "markdown";
|
|
216
|
+
files: "files";
|
|
217
|
+
choice: "choice";
|
|
218
|
+
confirm: "confirm";
|
|
219
|
+
form: "form";
|
|
220
|
+
}>;
|
|
221
|
+
text: z.ZodString;
|
|
222
|
+
title: z.ZodOptional<z.ZodString>;
|
|
223
|
+
toolCallId: z.ZodString;
|
|
224
|
+
}, z.core.$strict>;
|
|
225
|
+
title: z.ZodOptional<z.ZodString>;
|
|
226
|
+
toolCallId: z.ZodString;
|
|
227
|
+
}, z.core.$strict>>;
|