@dudousxd/nestjs-agent-core 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/guardrails/index.d.cts +1 -1
- package/dist/guardrails/index.d.ts +1 -1
- package/dist/index.cjs +339 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +332 -13
- package/dist/index.js.map +1 -1
- package/dist/{tool-B2Dq9ZwF.d.cts → tool-CwXibnce.d.cts} +83 -2
- package/dist/{tool-B2Dq9ZwF.d.ts → tool-CwXibnce.d.ts} +83 -2
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as ModelMessage, a as ToolDefinition, b as ToolCallRequest, c as MessageUsage, d as AgentUiComponent, A as Actor, e as ThreadSummary, f as ThreadDetail, S as StoredMessage, g as ToolResult, h as MessageAttachment, i as ToolCallStatus, U as UsagePurpose, j as ToolSpec, Q as QuotaState, k as AgentRunInput, H as HumanReply, l as ToolKind, m as ToolCallApproval, T as ToolHandler, n as HistoryPolicy, O as OutputProcessor, P as ProcessorContext, I as InputProcessor, o as ProcessedPrompt, p as ModelAnswer, q as PageContext, r as AgentDefinition, s as AgentDelegation, D as DetachedDelivery, t as AiToolCtx, u as PromptBuilder, v as PromptContributor, w as ToolTransientRetrySetting, x as AgentIntake, y as Decision, E as ElicitationRequest, L as LlmStepEnvelope, z as ToolStepEnvelope } from './tool-
|
|
2
|
-
export { B as ASK_TOOL_DESCRIPTION, C as ASK_TOOL_NAME, F as AgentApprovalRequest, G as AgentApprovalSettlement, J as AgentCatalogEntry, K as AgentHistoryWindow, N as AgentStreamEvent, R as AskToolInput, V as DEFAULT_INCREMENTAL_LOOKBACK_CHARS, W as DEFAULT_INTAKE_PREAMBLE, X as DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS, Y as DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS, Z as
|
|
1
|
+
import { M as ModelMessage, a as ToolDefinition, b as ToolCallRequest, c as MessageUsage, d as AgentUiComponent, A as Actor, e as ThreadSummary, f as ThreadDetail, S as StoredMessage, g as ToolResult, h as MessageAttachment, i as ToolCallStatus, U as UsagePurpose, j as ToolSpec, Q as QuotaState, k as AgentRunInput, H as HumanReply, l as ToolKind, m as ToolCallApproval, T as ToolHandler, n as HistoryPolicy, O as OutputProcessor, P as ProcessorContext, I as InputProcessor, o as ProcessedPrompt, p as ModelAnswer, q as PageContext, r as AgentDefinition, s as AgentDelegation, D as DetachedDelivery, t as AiToolCtx, u as PromptBuilder, v as PromptContributor, w as ToolTransientRetrySetting, x as AgentIntake, y as Decision, E as ElicitationRequest, L as LlmStepEnvelope, z as ToolStepEnvelope } from './tool-CwXibnce.cjs';
|
|
2
|
+
export { B as ASK_TOOL_DESCRIPTION, C as ASK_TOOL_NAME, F as AgentApprovalRequest, G as AgentApprovalSettlement, J as AgentCatalogEntry, K as AgentHistoryWindow, N as AgentStreamEvent, R as AskToolInput, V as DEFAULT_INCREMENTAL_LOOKBACK_CHARS, W as DEFAULT_INTAKE_PREAMBLE, X as DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS, Y as DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS, Z as ELICITATION_INPUT_TYPES, _ as ElicitationInput, $ as ElicitationInputType, a0 as ElicitationOption, a1 as ElicitationOutcome, a2 as ElicitationQuestion, a3 as ElicitationReply, a4 as ElicitationResult, a5 as HistoryPolicyContext, a6 as HistorySelection, a7 as HistorySummary, a8 as IncrementalGating, a9 as InvokeWithTransientRetryOptions, aa as MAX_ASK_QUESTIONS, ab as MessageRole, ac as OutputRejectedError, ad as OutputVerdict, ae as ProcessorFailedError, af as PromptContext, ag as QuotaView, ah as ToolCallApprovalStatus, ai as ToolCatalogEntry, aj as ToolConfirmation, ak as ToolPresentation, al as ToolPresentationTone, am as ToolResultField, an as ToolResultView, ao as ToolStepCtx, ap as ToolTransientRetryNumbers, aq as ToolTransientRetryOptions, ar as askInputSchema, as as askToolDefinition, at as decodeStreamEvent, au as encodeStreamEvent, av as invokeWithTransientRetry, aw as isTransientToolError, ax as isTypedQuestion, ay as normalizeElicitationReply, az as questionOptions, aA as readElicitationInput, aB as readElicitationQuestions, aC as renderElicitationAnswers, aD as resolveElicitation, aE as resolveToolTransientRetryNumbers, aF as settleElicitation, aG as validateElicitationAnswer, aH as validateElicitationValue } from './tool-CwXibnce.cjs';
|
|
3
3
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
4
4
|
import { ChannelRegistry } from '@dudousxd/nestjs-diagnostics';
|
|
5
5
|
|
|
@@ -489,6 +489,13 @@ interface AgentStore {
|
|
|
489
489
|
* expired. Absent → every call is treated as the requester's, with no expiry (the old behaviour).
|
|
490
490
|
*/
|
|
491
491
|
toolCallApproval?(toolCallId: string): Promise<ToolCallApprovalState | null>;
|
|
492
|
+
/**
|
|
493
|
+
* OPTIONAL: the input a call was recorded with, or `null` when the call is unknown. Read by the
|
|
494
|
+
* answer route to check a reply against the questions it answers (a typed question's rules, a
|
|
495
|
+
* `required` one left empty) before it is signalled. Absent → answers are checked for shape only,
|
|
496
|
+
* and the loop drops what it cannot settle.
|
|
497
|
+
*/
|
|
498
|
+
toolCallInput?(toolCallId: string): Promise<unknown>;
|
|
492
499
|
/**
|
|
493
500
|
* OPTIONAL: of `mediaIds`, the ones a message that still exists — in a thread owned by
|
|
494
501
|
* `actorRef` — still carries as an attachment. The inverse of
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as ModelMessage, a as ToolDefinition, b as ToolCallRequest, c as MessageUsage, d as AgentUiComponent, A as Actor, e as ThreadSummary, f as ThreadDetail, S as StoredMessage, g as ToolResult, h as MessageAttachment, i as ToolCallStatus, U as UsagePurpose, j as ToolSpec, Q as QuotaState, k as AgentRunInput, H as HumanReply, l as ToolKind, m as ToolCallApproval, T as ToolHandler, n as HistoryPolicy, O as OutputProcessor, P as ProcessorContext, I as InputProcessor, o as ProcessedPrompt, p as ModelAnswer, q as PageContext, r as AgentDefinition, s as AgentDelegation, D as DetachedDelivery, t as AiToolCtx, u as PromptBuilder, v as PromptContributor, w as ToolTransientRetrySetting, x as AgentIntake, y as Decision, E as ElicitationRequest, L as LlmStepEnvelope, z as ToolStepEnvelope } from './tool-
|
|
2
|
-
export { B as ASK_TOOL_DESCRIPTION, C as ASK_TOOL_NAME, F as AgentApprovalRequest, G as AgentApprovalSettlement, J as AgentCatalogEntry, K as AgentHistoryWindow, N as AgentStreamEvent, R as AskToolInput, V as DEFAULT_INCREMENTAL_LOOKBACK_CHARS, W as DEFAULT_INTAKE_PREAMBLE, X as DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS, Y as DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS, Z as
|
|
1
|
+
import { M as ModelMessage, a as ToolDefinition, b as ToolCallRequest, c as MessageUsage, d as AgentUiComponent, A as Actor, e as ThreadSummary, f as ThreadDetail, S as StoredMessage, g as ToolResult, h as MessageAttachment, i as ToolCallStatus, U as UsagePurpose, j as ToolSpec, Q as QuotaState, k as AgentRunInput, H as HumanReply, l as ToolKind, m as ToolCallApproval, T as ToolHandler, n as HistoryPolicy, O as OutputProcessor, P as ProcessorContext, I as InputProcessor, o as ProcessedPrompt, p as ModelAnswer, q as PageContext, r as AgentDefinition, s as AgentDelegation, D as DetachedDelivery, t as AiToolCtx, u as PromptBuilder, v as PromptContributor, w as ToolTransientRetrySetting, x as AgentIntake, y as Decision, E as ElicitationRequest, L as LlmStepEnvelope, z as ToolStepEnvelope } from './tool-CwXibnce.js';
|
|
2
|
+
export { B as ASK_TOOL_DESCRIPTION, C as ASK_TOOL_NAME, F as AgentApprovalRequest, G as AgentApprovalSettlement, J as AgentCatalogEntry, K as AgentHistoryWindow, N as AgentStreamEvent, R as AskToolInput, V as DEFAULT_INCREMENTAL_LOOKBACK_CHARS, W as DEFAULT_INTAKE_PREAMBLE, X as DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS, Y as DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS, Z as ELICITATION_INPUT_TYPES, _ as ElicitationInput, $ as ElicitationInputType, a0 as ElicitationOption, a1 as ElicitationOutcome, a2 as ElicitationQuestion, a3 as ElicitationReply, a4 as ElicitationResult, a5 as HistoryPolicyContext, a6 as HistorySelection, a7 as HistorySummary, a8 as IncrementalGating, a9 as InvokeWithTransientRetryOptions, aa as MAX_ASK_QUESTIONS, ab as MessageRole, ac as OutputRejectedError, ad as OutputVerdict, ae as ProcessorFailedError, af as PromptContext, ag as QuotaView, ah as ToolCallApprovalStatus, ai as ToolCatalogEntry, aj as ToolConfirmation, ak as ToolPresentation, al as ToolPresentationTone, am as ToolResultField, an as ToolResultView, ao as ToolStepCtx, ap as ToolTransientRetryNumbers, aq as ToolTransientRetryOptions, ar as askInputSchema, as as askToolDefinition, at as decodeStreamEvent, au as encodeStreamEvent, av as invokeWithTransientRetry, aw as isTransientToolError, ax as isTypedQuestion, ay as normalizeElicitationReply, az as questionOptions, aA as readElicitationInput, aB as readElicitationQuestions, aC as renderElicitationAnswers, aD as resolveElicitation, aE as resolveToolTransientRetryNumbers, aF as settleElicitation, aG as validateElicitationAnswer, aH as validateElicitationValue } from './tool-CwXibnce.js';
|
|
3
3
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
4
4
|
import { ChannelRegistry } from '@dudousxd/nestjs-diagnostics';
|
|
5
5
|
|
|
@@ -489,6 +489,13 @@ interface AgentStore {
|
|
|
489
489
|
* expired. Absent → every call is treated as the requester's, with no expiry (the old behaviour).
|
|
490
490
|
*/
|
|
491
491
|
toolCallApproval?(toolCallId: string): Promise<ToolCallApprovalState | null>;
|
|
492
|
+
/**
|
|
493
|
+
* OPTIONAL: the input a call was recorded with, or `null` when the call is unknown. Read by the
|
|
494
|
+
* answer route to check a reply against the questions it answers (a typed question's rules, a
|
|
495
|
+
* `required` one left empty) before it is signalled. Absent → answers are checked for shape only,
|
|
496
|
+
* and the loop drops what it cannot settle.
|
|
497
|
+
*/
|
|
498
|
+
toolCallInput?(toolCallId: string): Promise<unknown>;
|
|
492
499
|
/**
|
|
493
500
|
* OPTIONAL: of `mediaIds`, the ones a message that still exists — in a thread owned by
|
|
494
501
|
* `actorRef` — still carries as an attachment. The inverse of
|
package/dist/index.js
CHANGED
|
@@ -831,11 +831,235 @@ ${detail}`;
|
|
|
831
831
|
}
|
|
832
832
|
__name(repairInstruction, "repairInstruction");
|
|
833
833
|
|
|
834
|
-
// src/elicitation.ts
|
|
835
|
-
|
|
836
|
-
|
|
834
|
+
// src/elicitation-input.ts
|
|
835
|
+
var ELICITATION_INPUT_TYPES = [
|
|
836
|
+
"text",
|
|
837
|
+
"textarea",
|
|
838
|
+
"number",
|
|
839
|
+
"boolean",
|
|
840
|
+
"date",
|
|
841
|
+
"email",
|
|
842
|
+
"url",
|
|
843
|
+
"select"
|
|
844
|
+
];
|
|
845
|
+
function questionOptions(question) {
|
|
846
|
+
return question.options ?? [];
|
|
847
|
+
}
|
|
848
|
+
__name(questionOptions, "questionOptions");
|
|
849
|
+
function isTypedQuestion(question) {
|
|
850
|
+
return question.input !== void 0 && question.input.type !== "select";
|
|
851
|
+
}
|
|
852
|
+
__name(isTypedQuestion, "isTypedQuestion");
|
|
853
|
+
var DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
854
|
+
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
855
|
+
var NUMBER_PATTERN = /^-?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i;
|
|
856
|
+
function isDate(value) {
|
|
857
|
+
const match = DATE_PATTERN.exec(value);
|
|
858
|
+
if (match === null) {
|
|
859
|
+
return false;
|
|
860
|
+
}
|
|
861
|
+
const [, year, month, day] = match;
|
|
862
|
+
const date = new Date(Date.UTC(Number(year), Number(month) - 1, Number(day)));
|
|
863
|
+
return date.getUTCFullYear() === Number(year) && date.getUTCMonth() === Number(month) - 1 && date.getUTCDate() === Number(day);
|
|
864
|
+
}
|
|
865
|
+
__name(isDate, "isDate");
|
|
866
|
+
function isHttpUrl(value) {
|
|
867
|
+
try {
|
|
868
|
+
const url = new URL(value);
|
|
869
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
870
|
+
} catch {
|
|
871
|
+
return false;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
__name(isHttpUrl, "isHttpUrl");
|
|
875
|
+
function fullMatch(pattern, value) {
|
|
876
|
+
try {
|
|
877
|
+
return new RegExp(`^(?:${pattern})$`, "u").test(value);
|
|
878
|
+
} catch {
|
|
879
|
+
return void 0;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
__name(fullMatch, "fullMatch");
|
|
883
|
+
function asNumber(bound) {
|
|
884
|
+
if (typeof bound === "number" && Number.isFinite(bound)) {
|
|
885
|
+
return bound;
|
|
886
|
+
}
|
|
887
|
+
if (typeof bound === "string" && NUMBER_PATTERN.test(bound.trim())) {
|
|
888
|
+
return Number(bound);
|
|
889
|
+
}
|
|
890
|
+
return void 0;
|
|
891
|
+
}
|
|
892
|
+
__name(asNumber, "asNumber");
|
|
893
|
+
function validateElicitationValue(question, value) {
|
|
894
|
+
const input = question.input;
|
|
895
|
+
if (input === void 0 || input.type === "select") {
|
|
896
|
+
if (question.allowFreeText === true) {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
return questionOptions(question).some((option) => option.value === value) ? null : "must be one of the offered options";
|
|
900
|
+
}
|
|
901
|
+
switch (input.type) {
|
|
902
|
+
case "number": {
|
|
903
|
+
if (!NUMBER_PATTERN.test(value.trim()) || !Number.isFinite(Number(value))) {
|
|
904
|
+
return "must be a number";
|
|
905
|
+
}
|
|
906
|
+
const number = Number(value);
|
|
907
|
+
const min = asNumber(input.min);
|
|
908
|
+
const max = asNumber(input.max);
|
|
909
|
+
if (min !== void 0 && number < min) {
|
|
910
|
+
return `must be at least ${min}`;
|
|
911
|
+
}
|
|
912
|
+
if (max !== void 0 && number > max) {
|
|
913
|
+
return `must be at most ${max}`;
|
|
914
|
+
}
|
|
915
|
+
return null;
|
|
916
|
+
}
|
|
917
|
+
case "boolean":
|
|
918
|
+
return value === "true" || value === "false" ? null : 'must be "true" or "false"';
|
|
919
|
+
case "date": {
|
|
920
|
+
if (!isDate(value)) {
|
|
921
|
+
return "must be a date as YYYY-MM-DD";
|
|
922
|
+
}
|
|
923
|
+
if (typeof input.min === "string" && isDate(input.min) && value < input.min) {
|
|
924
|
+
return `must be on or after ${input.min}`;
|
|
925
|
+
}
|
|
926
|
+
if (typeof input.max === "string" && isDate(input.max) && value > input.max) {
|
|
927
|
+
return `must be on or before ${input.max}`;
|
|
928
|
+
}
|
|
929
|
+
return null;
|
|
930
|
+
}
|
|
931
|
+
case "email":
|
|
932
|
+
if (!EMAIL_PATTERN.test(value)) {
|
|
933
|
+
return "must be an email address";
|
|
934
|
+
}
|
|
935
|
+
break;
|
|
936
|
+
case "url":
|
|
937
|
+
if (!isHttpUrl(value)) {
|
|
938
|
+
return "must be an http(s) URL";
|
|
939
|
+
}
|
|
940
|
+
break;
|
|
941
|
+
case "text":
|
|
942
|
+
case "textarea": {
|
|
943
|
+
const min = asNumber(input.min);
|
|
944
|
+
const max = asNumber(input.max);
|
|
945
|
+
if (min !== void 0 && value.length < min) {
|
|
946
|
+
return `must be at least ${min} characters`;
|
|
947
|
+
}
|
|
948
|
+
if (max !== void 0 && value.length > max) {
|
|
949
|
+
return `must be at most ${max} characters`;
|
|
950
|
+
}
|
|
951
|
+
break;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
if (input.pattern !== void 0 && fullMatch(input.pattern, value) === false) {
|
|
955
|
+
return "does not match the expected format";
|
|
956
|
+
}
|
|
957
|
+
return null;
|
|
958
|
+
}
|
|
959
|
+
__name(validateElicitationValue, "validateElicitationValue");
|
|
960
|
+
function validateElicitationAnswer(question, values) {
|
|
961
|
+
const present = values.filter((value) => value !== "");
|
|
962
|
+
if (present.length === 0) {
|
|
963
|
+
return question.input?.required === true ? "requires an answer" : null;
|
|
964
|
+
}
|
|
965
|
+
if (question.multiple !== true && present.length > 1) {
|
|
966
|
+
return "takes a single value";
|
|
967
|
+
}
|
|
968
|
+
for (const value of present) {
|
|
969
|
+
const problem = validateElicitationValue(question, value);
|
|
970
|
+
if (problem !== null) {
|
|
971
|
+
return problem;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return null;
|
|
837
975
|
}
|
|
838
|
-
__name(
|
|
976
|
+
__name(validateElicitationAnswer, "validateElicitationAnswer");
|
|
977
|
+
function readElicitationInput(raw) {
|
|
978
|
+
if (typeof raw !== "object" || raw === null) {
|
|
979
|
+
return void 0;
|
|
980
|
+
}
|
|
981
|
+
const candidate = raw;
|
|
982
|
+
const type = candidate.type;
|
|
983
|
+
if (typeof type !== "string" || !ELICITATION_INPUT_TYPES.includes(type)) {
|
|
984
|
+
return void 0;
|
|
985
|
+
}
|
|
986
|
+
const bound = /* @__PURE__ */ __name((value) => typeof value === "number" && Number.isFinite(value) || typeof value === "string" ? value : void 0, "bound");
|
|
987
|
+
const min = bound(candidate.min);
|
|
988
|
+
const max = bound(candidate.max);
|
|
989
|
+
return {
|
|
990
|
+
type,
|
|
991
|
+
...typeof candidate.placeholder === "string" ? {
|
|
992
|
+
placeholder: candidate.placeholder
|
|
993
|
+
} : {},
|
|
994
|
+
...candidate.required === true ? {
|
|
995
|
+
required: true
|
|
996
|
+
} : {},
|
|
997
|
+
...min !== void 0 ? {
|
|
998
|
+
min
|
|
999
|
+
} : {},
|
|
1000
|
+
...max !== void 0 ? {
|
|
1001
|
+
max
|
|
1002
|
+
} : {},
|
|
1003
|
+
...typeof candidate.pattern === "string" ? {
|
|
1004
|
+
pattern: candidate.pattern
|
|
1005
|
+
} : {}
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
__name(readElicitationInput, "readElicitationInput");
|
|
1009
|
+
function readElicitationQuestions(input) {
|
|
1010
|
+
if (typeof input !== "object" || input === null) {
|
|
1011
|
+
return [];
|
|
1012
|
+
}
|
|
1013
|
+
const raw = input.questions;
|
|
1014
|
+
if (!Array.isArray(raw)) {
|
|
1015
|
+
return [];
|
|
1016
|
+
}
|
|
1017
|
+
const questions = [];
|
|
1018
|
+
for (const item of raw) {
|
|
1019
|
+
if (typeof item !== "object" || item === null) {
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
const candidate = item;
|
|
1023
|
+
if (typeof candidate.id !== "string" || typeof candidate.prompt !== "string") {
|
|
1024
|
+
continue;
|
|
1025
|
+
}
|
|
1026
|
+
const options = Array.isArray(candidate.options) ? candidate.options.flatMap((option) => {
|
|
1027
|
+
if (typeof option !== "object" || option === null) {
|
|
1028
|
+
return [];
|
|
1029
|
+
}
|
|
1030
|
+
const { value, label } = option;
|
|
1031
|
+
return typeof value === "string" && typeof label === "string" ? [
|
|
1032
|
+
{
|
|
1033
|
+
value,
|
|
1034
|
+
label
|
|
1035
|
+
}
|
|
1036
|
+
] : [];
|
|
1037
|
+
}) : [];
|
|
1038
|
+
const typed = readElicitationInput(candidate.input);
|
|
1039
|
+
const defaults = Array.isArray(candidate.defaults) ? candidate.defaults.filter((value) => typeof value === "string") : [];
|
|
1040
|
+
questions.push({
|
|
1041
|
+
id: candidate.id,
|
|
1042
|
+
prompt: candidate.prompt,
|
|
1043
|
+
options,
|
|
1044
|
+
...typed !== void 0 ? {
|
|
1045
|
+
input: typed
|
|
1046
|
+
} : {},
|
|
1047
|
+
...defaults.length > 0 ? {
|
|
1048
|
+
defaults
|
|
1049
|
+
} : {},
|
|
1050
|
+
...candidate.multiple === true ? {
|
|
1051
|
+
multiple: true
|
|
1052
|
+
} : {},
|
|
1053
|
+
...candidate.allowFreeText === true ? {
|
|
1054
|
+
allowFreeText: true
|
|
1055
|
+
} : {}
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
return questions;
|
|
1059
|
+
}
|
|
1060
|
+
__name(readElicitationQuestions, "readElicitationQuestions");
|
|
1061
|
+
|
|
1062
|
+
// src/elicitation.ts
|
|
839
1063
|
function normalizeElicitationReply(reply) {
|
|
840
1064
|
if (typeof reply !== "object" || reply === null) {
|
|
841
1065
|
return {
|
|
@@ -871,8 +1095,7 @@ function resolveElicitation(request, raw) {
|
|
|
871
1095
|
defaulted.push(question.id);
|
|
872
1096
|
continue;
|
|
873
1097
|
}
|
|
874
|
-
const
|
|
875
|
-
const valid = question.allowFreeText === true ? submitted : submitted.filter((value) => allowed.has(value));
|
|
1098
|
+
const valid = submitted.filter((value) => value !== "" && validateElicitationValue(question, value) === null);
|
|
876
1099
|
answers[question.id] = question.multiple === true ? valid : valid.slice(0, 1);
|
|
877
1100
|
}
|
|
878
1101
|
return {
|
|
@@ -893,7 +1116,7 @@ __name(settleElicitation, "settleElicitation");
|
|
|
893
1116
|
function renderElicitationAnswers(request, outcome) {
|
|
894
1117
|
const lines = request.questions.map((question) => {
|
|
895
1118
|
const chosen = outcome.answers[question.id] ?? [];
|
|
896
|
-
const labels = chosen.map((value) => question.
|
|
1119
|
+
const labels = chosen.map((value) => questionOptions(question).find((option) => option.value === value)?.label ?? value);
|
|
897
1120
|
return `${question.prompt} \u2192 ${labels.length > 0 ? labels.join(", ") : "(no answer)"}`;
|
|
898
1121
|
});
|
|
899
1122
|
const preface = outcome.skipped ? "The user declined to answer and asked you to proceed on these assumptions:" : "The user answered:";
|
|
@@ -959,7 +1182,23 @@ function parseQuestion(raw, path, issues) {
|
|
|
959
1182
|
], "must be a non-empty string"));
|
|
960
1183
|
return void 0;
|
|
961
1184
|
}
|
|
962
|
-
|
|
1185
|
+
let input;
|
|
1186
|
+
if (candidate.input !== void 0) {
|
|
1187
|
+
input = readElicitationInput(candidate.input);
|
|
1188
|
+
if (input === void 0) {
|
|
1189
|
+
issues.push(issue([
|
|
1190
|
+
...path,
|
|
1191
|
+
"input",
|
|
1192
|
+
"type"
|
|
1193
|
+
], `must be one of ${ELICITATION_INPUT_TYPES.join(", ")}`));
|
|
1194
|
+
return void 0;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
const described = typeof candidate.description === "string" && candidate.description.length > 0 ? {
|
|
1198
|
+
description: candidate.description
|
|
1199
|
+
} : {};
|
|
1200
|
+
const typed = input !== void 0 && input.type !== "select";
|
|
1201
|
+
if (!typed && (!Array.isArray(candidate.options) || candidate.options.length === 0)) {
|
|
963
1202
|
issues.push(issue([
|
|
964
1203
|
...path,
|
|
965
1204
|
"options"
|
|
@@ -967,7 +1206,7 @@ function parseQuestion(raw, path, issues) {
|
|
|
967
1206
|
return void 0;
|
|
968
1207
|
}
|
|
969
1208
|
const options = [];
|
|
970
|
-
for (const [index, rawOption] of candidate.options.entries()) {
|
|
1209
|
+
for (const [index, rawOption] of (Array.isArray(candidate.options) ? candidate.options : []).entries()) {
|
|
971
1210
|
const option = parseOption(rawOption, [
|
|
972
1211
|
...path,
|
|
973
1212
|
"options",
|
|
@@ -977,6 +1216,33 @@ function parseQuestion(raw, path, issues) {
|
|
|
977
1216
|
options.push(option);
|
|
978
1217
|
}
|
|
979
1218
|
}
|
|
1219
|
+
if (typed) {
|
|
1220
|
+
const question = {
|
|
1221
|
+
id: candidate.id,
|
|
1222
|
+
prompt: candidate.prompt,
|
|
1223
|
+
...described,
|
|
1224
|
+
...options.length > 0 ? {
|
|
1225
|
+
options
|
|
1226
|
+
} : {},
|
|
1227
|
+
input,
|
|
1228
|
+
...candidate.multiple === true ? {
|
|
1229
|
+
multiple: true
|
|
1230
|
+
} : {}
|
|
1231
|
+
};
|
|
1232
|
+
const offered2 = Array.isArray(candidate.defaults) ? candidate.defaults.filter((value) => typeof value === "string") : [];
|
|
1233
|
+
const defaults2 = offered2.filter((value) => validateElicitationValue(question, value) === null);
|
|
1234
|
+
if (offered2.length > 0 && defaults2.length === 0) {
|
|
1235
|
+
issues.push(issue([
|
|
1236
|
+
...path,
|
|
1237
|
+
"defaults"
|
|
1238
|
+
], `must be valid ${input.type} values`));
|
|
1239
|
+
return void 0;
|
|
1240
|
+
}
|
|
1241
|
+
return defaults2.length > 0 ? {
|
|
1242
|
+
...question,
|
|
1243
|
+
defaults: defaults2
|
|
1244
|
+
} : question;
|
|
1245
|
+
}
|
|
980
1246
|
if (!Array.isArray(candidate.defaults) || candidate.defaults.length === 0) {
|
|
981
1247
|
issues.push(issue([
|
|
982
1248
|
...path,
|
|
@@ -996,7 +1262,11 @@ function parseQuestion(raw, path, issues) {
|
|
|
996
1262
|
return {
|
|
997
1263
|
id: candidate.id,
|
|
998
1264
|
prompt: candidate.prompt,
|
|
1265
|
+
...described,
|
|
999
1266
|
options,
|
|
1267
|
+
...input !== void 0 ? {
|
|
1268
|
+
input
|
|
1269
|
+
} : {},
|
|
1000
1270
|
defaults,
|
|
1001
1271
|
...candidate.multiple === true ? {
|
|
1002
1272
|
multiple: true
|
|
@@ -1024,9 +1294,7 @@ var ASK_JSON_SCHEMA = {
|
|
|
1024
1294
|
additionalProperties: false,
|
|
1025
1295
|
required: [
|
|
1026
1296
|
"id",
|
|
1027
|
-
"prompt"
|
|
1028
|
-
"options",
|
|
1029
|
-
"defaults"
|
|
1297
|
+
"prompt"
|
|
1030
1298
|
],
|
|
1031
1299
|
properties: {
|
|
1032
1300
|
id: {
|
|
@@ -1036,6 +1304,50 @@ var ASK_JSON_SCHEMA = {
|
|
|
1036
1304
|
prompt: {
|
|
1037
1305
|
type: "string"
|
|
1038
1306
|
},
|
|
1307
|
+
description: {
|
|
1308
|
+
type: "string",
|
|
1309
|
+
description: "A line of help under the prompt."
|
|
1310
|
+
},
|
|
1311
|
+
input: {
|
|
1312
|
+
type: "object",
|
|
1313
|
+
additionalProperties: false,
|
|
1314
|
+
required: [
|
|
1315
|
+
"type"
|
|
1316
|
+
],
|
|
1317
|
+
description: 'Ask for a typed value instead of offering options. Omit for a pick from options. Answers come back as strings: numbers as decimals, booleans as "true"/"false", dates as YYYY-MM-DD.',
|
|
1318
|
+
properties: {
|
|
1319
|
+
type: {
|
|
1320
|
+
type: "string",
|
|
1321
|
+
enum: [
|
|
1322
|
+
...ELICITATION_INPUT_TYPES
|
|
1323
|
+
]
|
|
1324
|
+
},
|
|
1325
|
+
placeholder: {
|
|
1326
|
+
type: "string"
|
|
1327
|
+
},
|
|
1328
|
+
required: {
|
|
1329
|
+
type: "boolean"
|
|
1330
|
+
},
|
|
1331
|
+
min: {
|
|
1332
|
+
type: [
|
|
1333
|
+
"number",
|
|
1334
|
+
"string"
|
|
1335
|
+
],
|
|
1336
|
+
description: "number: minimum; text: minimum length; date: earliest YYYY-MM-DD."
|
|
1337
|
+
},
|
|
1338
|
+
max: {
|
|
1339
|
+
type: [
|
|
1340
|
+
"number",
|
|
1341
|
+
"string"
|
|
1342
|
+
],
|
|
1343
|
+
description: "number: maximum; text: maximum length; date: latest YYYY-MM-DD."
|
|
1344
|
+
},
|
|
1345
|
+
pattern: {
|
|
1346
|
+
type: "string",
|
|
1347
|
+
description: "A regex the whole value must match."
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1039
1351
|
multiple: {
|
|
1040
1352
|
type: "boolean",
|
|
1041
1353
|
description: "Allow more than one option to be chosen."
|
|
@@ -1050,7 +1362,7 @@ var ASK_JSON_SCHEMA = {
|
|
|
1050
1362
|
items: {
|
|
1051
1363
|
type: "string"
|
|
1052
1364
|
},
|
|
1053
|
-
description: "REQUIRED
|
|
1365
|
+
description: "REQUIRED for a pick from options: the option values you would pick yourself, so the user can confirm rather than decide. For a typed input, the value you would enter, when there is a sensible one."
|
|
1054
1366
|
},
|
|
1055
1367
|
options: {
|
|
1056
1368
|
type: "array",
|
|
@@ -4129,6 +4441,7 @@ export {
|
|
|
4129
4441
|
DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS,
|
|
4130
4442
|
DefaultApprovalPolicy,
|
|
4131
4443
|
DefaultRolesPolicy,
|
|
4444
|
+
ELICITATION_INPUT_TYPES,
|
|
4132
4445
|
GLOBAL_SCOPE,
|
|
4133
4446
|
MAX_ASK_QUESTIONS,
|
|
4134
4447
|
OutputRejectedError,
|
|
@@ -4184,6 +4497,7 @@ export {
|
|
|
4184
4497
|
isReplayIntegrityError,
|
|
4185
4498
|
isToolEnabled,
|
|
4186
4499
|
isTransientToolError,
|
|
4500
|
+
isTypedQuestion,
|
|
4187
4501
|
loadSkill,
|
|
4188
4502
|
mayDecideApproval,
|
|
4189
4503
|
memoryForgetVerdict,
|
|
@@ -4205,6 +4519,9 @@ export {
|
|
|
4205
4519
|
publishAgentSkillsResolved,
|
|
4206
4520
|
publishAgentToolCall,
|
|
4207
4521
|
publishAgentToolRetry,
|
|
4522
|
+
questionOptions,
|
|
4523
|
+
readElicitationInput,
|
|
4524
|
+
readElicitationQuestions,
|
|
4208
4525
|
releaseGatedFrames,
|
|
4209
4526
|
rememberInputSchema,
|
|
4210
4527
|
rememberToolDefinition,
|
|
@@ -4235,6 +4552,8 @@ export {
|
|
|
4235
4552
|
traceLlmTurn,
|
|
4236
4553
|
traceToolExecution,
|
|
4237
4554
|
truncateDetailContent,
|
|
4555
|
+
validateElicitationAnswer,
|
|
4556
|
+
validateElicitationValue,
|
|
4238
4557
|
validateStructured,
|
|
4239
4558
|
windowHistory,
|
|
4240
4559
|
withAskTool,
|