@absolutejs/ai 0.6.0 → 0.6.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/CHANGELOG.md +6 -0
- package/README.md +15 -0
- package/changelog.json +19 -0
- package/dist/ai/index.js +75 -1
- package/dist/ai/index.js.map +6 -4
- package/dist/ai/ui/index.js +75 -1
- package/dist/ai/ui/index.js.map +7 -5
- package/dist/angular/ai/index.js +9 -7
- package/dist/angular/ai/index.js.map +2 -2
- package/dist/src/ai/ui/backgroundWork.d.ts +28 -0
- package/dist/src/ai/ui/catalog.d.ts +2 -0
- package/dist/src/ai/ui/formSubmission.d.ts +11 -0
- package/dist/src/ai/ui/index.d.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,12 @@ This file is generated by `absolute-changelog` from the entries in
|
|
|
6
6
|
`changelog/`. Edit an entry, not this file — and add new ones under
|
|
7
7
|
`changelog/unreleased/`.
|
|
8
8
|
|
|
9
|
+
## 0.6.1 — 2026-10-20
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Add typed forms and shared task next actions for top-up continuation** (`FormField`, `formCard`, `parseFormSpec`, `prepareFormSubmission`, `FormSubmission`, `BackgroundWorkCard`, `backgroundWorkNextAction`)
|
|
14
|
+
|
|
9
15
|
## 0.6.0 — 2026-10-20
|
|
10
16
|
|
|
11
17
|
### Added
|
package/README.md
CHANGED
|
@@ -575,3 +575,18 @@ can prevent `done`, and no adapter can reconstruct usage the provider never sent
|
|
|
575
575
|
`onUsage` still reports only complete usage, once per instrumented stream. Keep
|
|
576
576
|
credit reservations separate from charges and reconcile unknown outcomes in the
|
|
577
577
|
host application. The package does not invent token counts or decide billing policy.
|
|
578
|
+
|
|
579
|
+
### Typed forms and background work
|
|
580
|
+
|
|
581
|
+
Form fields support `valueType` (`string`, `number`, `integer`, `boolean`). For a
|
|
582
|
+
numeric dropdown use `type: "select", options: ["3", "10"], valueType: "integer"`.
|
|
583
|
+
All hosts should call `prepareFormSubmission(form, values)` before invoking the
|
|
584
|
+
bound tool: it returns typed input or field errors without discarding answers.
|
|
585
|
+
The host must still validate the complete tool schema and apply authorization.
|
|
586
|
+
Legacy dropdowns retain string values; migrate numeric fields explicitly.
|
|
587
|
+
|
|
588
|
+
`BackgroundWorkCard` and `backgroundWorkNextAction` provide framework-neutral
|
|
589
|
+
progress/CTA semantics. A funding pause offers Add credits; only confirmed
|
|
590
|
+
funding changes it to Continue research. Completed work offers View results;
|
|
591
|
+
uncertain work offers Check status, never replay. The host persists the work ID,
|
|
592
|
+
polls or subscribes to actual progress, and binds actions to authenticated routes.
|
package/changelog.json
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
"contract": 1,
|
|
3
3
|
"name": "@absolutejs/ai",
|
|
4
4
|
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"changes": [
|
|
7
|
+
{
|
|
8
|
+
"kind": "added",
|
|
9
|
+
"summary": "Add typed forms and shared task next actions for top-up continuation",
|
|
10
|
+
"symbols": [
|
|
11
|
+
"FormField",
|
|
12
|
+
"formCard",
|
|
13
|
+
"parseFormSpec",
|
|
14
|
+
"prepareFormSubmission",
|
|
15
|
+
"FormSubmission",
|
|
16
|
+
"BackgroundWorkCard",
|
|
17
|
+
"backgroundWorkNextAction"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"date": "2026-10-20",
|
|
22
|
+
"version": "0.6.1"
|
|
23
|
+
},
|
|
5
24
|
{
|
|
6
25
|
"changes": [
|
|
7
26
|
{
|
package/dist/ai/index.js
CHANGED
|
@@ -2751,6 +2751,11 @@ var parseFormField = (raw) => {
|
|
|
2751
2751
|
if (!name || !label || !type)
|
|
2752
2752
|
return null;
|
|
2753
2753
|
const field = { label, name, type };
|
|
2754
|
+
if (raw.valueType !== undefined) {
|
|
2755
|
+
if (!["string", "number", "integer", "boolean"].includes(String(raw.valueType)))
|
|
2756
|
+
return null;
|
|
2757
|
+
field.valueType = raw.valueType;
|
|
2758
|
+
}
|
|
2754
2759
|
const placeholder = cleanString(raw.placeholder, LABEL_MAX_CHARS);
|
|
2755
2760
|
if (placeholder)
|
|
2756
2761
|
field.placeholder = placeholder;
|
|
@@ -3122,6 +3127,11 @@ var formCard = {
|
|
|
3122
3127
|
items: { type: "string" },
|
|
3123
3128
|
type: "array"
|
|
3124
3129
|
},
|
|
3130
|
+
valueType: {
|
|
3131
|
+
enum: ["string", "number", "integer", "boolean"],
|
|
3132
|
+
type: "string",
|
|
3133
|
+
description: "Submitted scalar type, especially integer for numeric select options"
|
|
3134
|
+
},
|
|
3125
3135
|
placeholder: { type: "string" },
|
|
3126
3136
|
required: { type: "boolean" },
|
|
3127
3137
|
type: { enum: [...FORM_FIELD_TYPES], type: "string" },
|
|
@@ -3628,6 +3638,68 @@ var renderChartSvg = (spec, options = {}) => {
|
|
|
3628
3638
|
const body = spec.type === "donut" ? donutSvg(spec, frame) : cartesianSvg(spec, frame);
|
|
3629
3639
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" role="img" aria-label="${escapeXml(spec.title)}" font-family="${FONT}"><rect width="${width}" height="${height}" fill="${theme.surface}" rx="12"/>${spec.type === "donut" ? headerSvg({ ...spec, series: [] }, frame) : headerSvg(spec, frame)}${body}</svg>`;
|
|
3630
3640
|
};
|
|
3641
|
+
// src/ai/ui/formSubmission.ts
|
|
3642
|
+
var prepareFormSubmission = (form, values) => {
|
|
3643
|
+
const input = { ...form.submit.input };
|
|
3644
|
+
const errors = {};
|
|
3645
|
+
for (const field of form.fields) {
|
|
3646
|
+
if (["__proto__", "constructor", "prototype"].includes(field.name)) {
|
|
3647
|
+
errors.form = "Invalid field name";
|
|
3648
|
+
continue;
|
|
3649
|
+
}
|
|
3650
|
+
const raw = values[field.name];
|
|
3651
|
+
if (raw === undefined || raw === null || typeof raw === "string" && !raw.trim()) {
|
|
3652
|
+
if (field.required)
|
|
3653
|
+
errors[field.name] = "This field is required";
|
|
3654
|
+
continue;
|
|
3655
|
+
}
|
|
3656
|
+
if (field.type === "select" && !field.options?.includes(String(raw))) {
|
|
3657
|
+
errors[field.name] = "Choose one of the available options";
|
|
3658
|
+
continue;
|
|
3659
|
+
}
|
|
3660
|
+
const type = field.valueType ?? (field.type === "number" ? "number" : field.type === "checkbox" ? "boolean" : "string");
|
|
3661
|
+
let value = raw;
|
|
3662
|
+
if (type === "number" || type === "integer") {
|
|
3663
|
+
value = typeof raw === "number" ? raw : typeof raw === "string" && /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/iu.test(raw.trim()) ? Number(raw) : NaN;
|
|
3664
|
+
if (typeof value !== "number" || !Number.isFinite(value) || type === "integer" && !Number.isSafeInteger(value)) {
|
|
3665
|
+
errors[field.name] = type === "integer" ? "Enter a whole number" : "Enter a number";
|
|
3666
|
+
continue;
|
|
3667
|
+
}
|
|
3668
|
+
} else if (type === "boolean") {
|
|
3669
|
+
if (![true, false, "true", "false"].includes(raw)) {
|
|
3670
|
+
errors[field.name] = "Choose yes or no";
|
|
3671
|
+
continue;
|
|
3672
|
+
}
|
|
3673
|
+
value = raw === true || raw === "true";
|
|
3674
|
+
if (field.type === "checkbox" && field.required && !value) {
|
|
3675
|
+
errors[field.name] = "This field is required";
|
|
3676
|
+
continue;
|
|
3677
|
+
}
|
|
3678
|
+
} else {
|
|
3679
|
+
if (typeof raw !== "string") {
|
|
3680
|
+
errors[field.name] = "Enter text";
|
|
3681
|
+
continue;
|
|
3682
|
+
}
|
|
3683
|
+
value = field.type === "password" ? raw : raw.trim();
|
|
3684
|
+
}
|
|
3685
|
+
input[field.name] = value;
|
|
3686
|
+
}
|
|
3687
|
+
return Object.keys(errors).length ? { ok: false, errors } : { ok: true, input };
|
|
3688
|
+
};
|
|
3689
|
+
// src/ai/ui/backgroundWork.ts
|
|
3690
|
+
var backgroundWorkNextAction = (work) => {
|
|
3691
|
+
if (!work.workId || !Number.isSafeInteger(work.totalSteps) || work.totalSteps < 1 || !Number.isSafeInteger(work.completedSteps) || work.completedSteps < 0 || work.completedSteps > work.totalSteps)
|
|
3692
|
+
throw new Error("Invalid background work progress");
|
|
3693
|
+
if (work.status === "completed")
|
|
3694
|
+
return { kind: "view_results", label: "View results" };
|
|
3695
|
+
if (work.status === "paused" && work.pauseReason === "funding")
|
|
3696
|
+
return work.fundingConfirmed ? { kind: "continue", label: "Continue research" } : { kind: "top_up", label: "Add credits" };
|
|
3697
|
+
if (work.status === "unknown")
|
|
3698
|
+
return { kind: "check_status", label: "Check status" };
|
|
3699
|
+
if (work.hasResults)
|
|
3700
|
+
return { kind: "view_results", label: "View saved results" };
|
|
3701
|
+
return { kind: "check_status", label: "Check status" };
|
|
3702
|
+
};
|
|
3631
3703
|
// src/ai/conversationManager.ts
|
|
3632
3704
|
var NOT_FOUND2 = -1;
|
|
3633
3705
|
var TITLE_MAX_LENGTH2 = 80;
|
|
@@ -9160,6 +9232,7 @@ export {
|
|
|
9160
9232
|
aiChat,
|
|
9161
9233
|
alibaba,
|
|
9162
9234
|
anthropic,
|
|
9235
|
+
backgroundWorkNextAction,
|
|
9163
9236
|
chartCard,
|
|
9164
9237
|
choiceCard,
|
|
9165
9238
|
configureProviderResilience,
|
|
@@ -9223,6 +9296,7 @@ export {
|
|
|
9223
9296
|
planCard,
|
|
9224
9297
|
prepareAITextInput,
|
|
9225
9298
|
prepareAITextInputStep,
|
|
9299
|
+
prepareFormSubmission,
|
|
9226
9300
|
providerStatusPage,
|
|
9227
9301
|
remoteProvider,
|
|
9228
9302
|
renderChartSvg,
|
|
@@ -9243,5 +9317,5 @@ export {
|
|
|
9243
9317
|
xai
|
|
9244
9318
|
};
|
|
9245
9319
|
|
|
9246
|
-
//# debugId=
|
|
9320
|
+
//# debugId=75EDBEC482A1645464756E2164756E21
|
|
9247
9321
|
//# sourceMappingURL=index.js.map
|