chainlesschain 0.166.69 → 0.166.71
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 +42 -5
- package/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-FhevRfL6.js → AIOps-6n6RPfD2.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-rOeOykx5.js → ActionButton-BRlz1g77.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BK_wYlfz.js → Analytics-BFx6_nNR.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-_2cCtZKV.js → AppLayout-CcbKe_m4.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-D5MSvVzk.js → Artifacts-DlBMxBaf.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-yd-Ah-A3.js → Audit-aqQRi1IW.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-yCaw_Gu_.js → BackgroundAgents-tzAQeiAS.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-G3ADD4N-.js → Backup-C3sLPZvj.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-ByDhkLbF.js → BaseInput-BdqG7xax.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BMrc7qjz.js → Chat-DXjdkR-r.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-B-3SVP-4.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-BHYgyZWA.js → Checkbox-CACOSDhS.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DJfcy0jC.js → Codegen-ZY0zbHvS.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C27zROxc.js → Col-C511kzpa.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CuS5tq_1.js → Community-CIM5EtmR.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BrYJNe7Q.js → Compact-DpTxu8E7.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-8hfahYHT.js → Compliance-Cu42ksf-.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DdE0n2lp.js → Cowork-BqUbCW9U.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-CUq3aSiX.js → Cron-OXYE4gRs.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BM4XSPWG.js → Crosschain-DPqmhSi6.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CdaBY57N.js → DID-CPp_yj85.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Cwtd52So.js → Dashboard-pki3T5PE.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BvlObh6U.js → Dropdown-IyL1RsjP.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-e3fLhjnX.js → EmailListRenderer-6Kbwb4Ux.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-CTtk1Zo8.js → EvolutionSettings-DGBMs24I.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BpPJUnCU.js → FamilyGuardDashboard-CLz3KJvw.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-vzjZ6_nQ.js → Federation-gMDCbNjS.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DEDNLhkE.js → FormItemContext-bSzQnHE6.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DEl2Te5f.js → GenericCardRenderer-DCyBnm6B.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BzsYQnCq.js → Git-BKqZtZMD.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-zxJs6Y8s.js → Governance-nZDU4Gz2.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-5JUsrmF1.js → Inference-VodzHgdz.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Br8b5Htz.js → KnowledgeGraph-DHjlnyh4.js} +1 -1
- package/src/assets/web-panel/assets/Logs-CPsAssGM.js +2 -0
- package/src/assets/web-panel/assets/{MarkdownRenderer-In4itZX2.js → MarkdownRenderer-ChogLgLv.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-s8MmWkS9.js → Marketplace-Df7Cr8cW.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Wu-WRg4M.js → McpTools-Dy_V6M2q.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-B_i-eX9w.js → Memory-DjYWvH5O.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Ca64kjVx.js → MobileBridge-qYw4QwQh.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-DDA7pzJd.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-DKvGmG3y.js → Mtc-BQ2fg2aQ.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-BVvWx8pF.js → MtcAudit-CaBVA8Cu.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-wqeJ2O9x.js → Multisig-DsTt5nuM.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DX87ysYu.js → NLProgramming-CqpsGgiz.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-ChenGdu0.js → Notes-DpRTGRs9.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BZRa68-x.js → NotificationSettings-CmHeyjUS.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DZ6xG1M6.js → OrderTableRenderer-D-JBdzGf.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BWJp4VPX.js → Organization-QL01Gu7d.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BoM4bYt5.js → Overflow-DjUeTZ69.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Cvi8YV09.js → P2P-DuM6UaEh.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CNVC1NIj.js → PdhVaultBrowser-BsL5CbMs.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DNd1MRjW.js → Permissions-Cfu4vMf9.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DGSBYZ5-.js → PersonalDataHub-HvEGAMl5.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-DkcoGMBo.js → Pipeline-_CZIYXJs.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DltwvMAW.js → Privacy-C6bTNjwi.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-ChYbpHg8.js → ProjectInit-D64UJRfZ.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B8FWiHTJ.js → ProjectSettings-CSTAzKVe.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DuyhtSm4.js → Projects-BudNMgcm.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-Bo18Tx_6.js → Providers-C7ddN75H.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-6W85KlsG.js → QrScannerModal-CtsMC0eH.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DznRUedP.js → QuickAsk-iE7xKI4P.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CQDN3_p-.js → Recommend-5FCqoy3g.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-CiJgokEj.js → RemoteSession-DtX0VARB.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-DexzGH7E.js → Reputation-Hd4dH5ci.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BgZOIvSi.js → Row-CnLRjeGC.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BWIZJ_Jr.js → RssFeed-Ds43ubF9.js} +3 -3
- package/src/assets/web-panel/assets/{Search-B376EwWJ.js → Search-BmXOdvpt.js} +1 -1
- package/src/assets/web-panel/assets/{Security-92mUR5OD.js → Security--yQqv9yt.js} +4 -4
- package/src/assets/web-panel/assets/{Services-ClSEAOHk.js → Services-CNNPxlyA.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DVhLbv99.js → Skeleton-DPmZAdDN.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-JTcXs_xI.js → Skills-Va_WxW7s.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DnKY9zy9.js → Sla-BZoRsy3v.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-GO1JefAH.js → SpeechSettings-XgRV95VE.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-jX5tB2St.js → SyncSettings-Dr7NXCEw.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BxRBzhUc.js → Tasks-j-xRo5_-.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CAVkbTG1.js → Templates-BJSqGQuB.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-5Y7sHBkz.js → Tenant-zuVl_JY7.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CbbLShYb.js → Terminal-B-xNbgfG.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-2HptWihL.js → TimelineRenderer-BtZQpa0b.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-B-jGxzHl.js → Tokens-CXGqGXWd.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-9DGa90DT.js → Trigger-CtDmejyH.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BSJEkEOO.js → Trust-BfDvBu2B.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C807So5R.js → UkeySign-CgHq72xW.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-ByiieAv-.js → VideoEditing-pRBMqiGT.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BixbIOUv.js → Wallet-DHhZSHFo.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-z7akhor4.js → WebAuthn-C-PDGO1-.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-KvijuUuR.js → WorkflowEditor-Dqrh4ooE.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BYKoh0YG.js → chat-Du4rhkgo.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CLT8IYBt.js → colors-CVVon0Yw.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DlBIyYHF.js → compact-item-zcQv_R_9.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-5XmAnNLr.js → createContext-UfW2PpZM.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CoA1apwL.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-rPdRhm7K.js → hasIn-Dko6kq4D.js} +1 -1
- package/src/assets/web-panel/assets/{index-ChlzaTV3.js → index-0d3V2fKV.js} +1 -1
- package/src/assets/web-panel/assets/{index-8un-eUDI.js → index-4YoVVwaY.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZiSMYoD.js → index-5UfwyzQV.js} +3 -3
- package/src/assets/web-panel/assets/{index-Bve7Wsgf.js → index-7aNfa1q3.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1VfBUPB.js → index-B8nu6_LV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DI_tYFBe.js → index-BEOOJevs.js} +1 -1
- package/src/assets/web-panel/assets/{index-kx6zDWew.js → index-BHq5RTAk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIVrVGvf.js → index-BPE8w-x1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DW8vozBS.js → index-BPTQ-SUp.js} +1 -1
- package/src/assets/web-panel/assets/{index-DPS4mWnI.js → index-BR5eNU_w.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZjGcIGU.js → index-BXqsNksk.js} +1 -1
- package/src/assets/web-panel/assets/{index-b-rQCMkx.js → index-BoQJIWkq.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3-NL-x-.js → index-BolCTH1Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-akwXS-FF.js → index-BwcE8uKT.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIRl2Ii5.js → index-CJ72HeXg.js} +1 -1
- package/src/assets/web-panel/assets/{index-Djd7uqwM.js → index-CPqtDZE1.js} +1 -1
- package/src/assets/web-panel/assets/{index-C2sFDVb_.js → index-CV8kORgq.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bzd0sFkp.js → index-CoXowCMA.js} +1 -1
- package/src/assets/web-panel/assets/{index-rRuCGdKW.js → index-CrURt95p.js} +1 -1
- package/src/assets/web-panel/assets/{index-CY6TMc2m.js → index-CrbxgYRx.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuvweiCz.js → index-Cs4qAz6z.js} +1 -1
- package/src/assets/web-panel/assets/index-CsR4S29Z.js +1 -0
- package/src/assets/web-panel/assets/{index-eHbr3f5I.js → index-D4-E1s34.js} +1 -1
- package/src/assets/web-panel/assets/{index-LKT-Ol0A.js → index-DIFh_pNy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BgevTkUv.js → index-DKAB6MRs.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDtlwjSr.js → index-DMdBtncl.js} +1 -1
- package/src/assets/web-panel/assets/{index-DzExCCLS.js → index-DMxhURG4.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3f9Jzx2.js → index-Dgu3vko5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBt2CSAx.js → index-Dh1USRx7.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqZU4_7J.js → index-DhYE_jVw.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dea32nOK.js → index-Dkc1L9vQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsnbOKdI.js → index-DqQhty7h.js} +1 -1
- package/src/assets/web-panel/assets/index-DvcAyRFh.js +1 -0
- package/src/assets/web-panel/assets/{index-DTslLzPJ.js → index-Dviw8PsD.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dntid6oj.js → index-DwXm_6Df.js} +1 -1
- package/src/assets/web-panel/assets/{index-CM_a9spK.js → index-UzXoeYbz.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-0nAxf5.js → index-ija7mc1b.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCDSycWo.js → index-jjgfplWj.js} +1 -1
- package/src/assets/web-panel/assets/{index-CErvHCDe.js → index-ubMuGX5r.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-a8411LiK.js → initDefaultProps-DvSMOW2m.js} +1 -1
- package/src/assets/web-panel/assets/{motion-oVcQdpCm.js → motion-C7PjuFda.js} +1 -1
- package/src/assets/web-panel/assets/{move-B-eyzzzL.js → move-qsgDmMqu.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BCYIxuG7.js → mtc-parser-D7qHulCC.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DuFtWiYh.js → omit-g_tGmcIM.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CVAoJhGu.js → pickAttrs-DGs-br4p.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Y2iub2bO.js → placementArrow-A1KZT5yH.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BHenWIVD.js → responsiveObserve-B98U6Yi5.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CKrMaL29.js → slide-Y5Q6ixV9.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-w8eb_1da.js → statusUtils-CVC7D579.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CCVi_Ww3.js → styleChecker-CDWAgZKa.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BsmR_q0r.js → useFlexGapSupport-C0UFofSm.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-a8GMBjnc.js → useFs-BHEf6SSo.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BMUYSPn-.js → usePersonalDataHub-Bb2M_BPj.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DL2pI31V.js → vnode-DENyLaXR.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Cbi8fISi.js → zoom-BUOUP8-I.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/agent.js +97 -0
- package/src/data/changelog.json +26 -0
- package/src/lib/decision-layer/benchmark.js +164 -0
- package/src/lib/decision-layer/contracts.js +377 -0
- package/src/lib/decision-layer/provider-authority.js +44 -0
- package/src/lib/decision-layer/providers.js +150 -0
- package/src/lib/decision-layer/runtime.js +238 -0
- package/src/lib/decision-layer/typesafe-provider.js +16 -0
- package/src/runtime/agent-core.js +49 -0
- package/src/runtime/headless-runner.js +88 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-nA7n0I6S.js +0 -1
- package/src/assets/web-panel/assets/Logs-D-tubDMJ.js +0 -2
- package/src/assets/web-panel/assets/MobileProjects-Cq9AFiO4.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BmcCIHwY.js +0 -1
- package/src/assets/web-panel/assets/index-DY8rmd6x.js +0 -1
- package/src/assets/web-panel/assets/index-sbwcUeRS.js +0 -1
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { types as utilTypes } from "node:util";
|
|
3
|
+
|
|
4
|
+
export const SKILL_DECISION_REQUEST_SCHEMA =
|
|
5
|
+
"chainlesschain.skill-decision-request/v1";
|
|
6
|
+
export const SKILL_DECISION_RESULT_SCHEMA =
|
|
7
|
+
"chainlesschain.skill-decision-result/v1";
|
|
8
|
+
export const SKILL_DECISION_OBSERVATION_SCHEMA =
|
|
9
|
+
"chainlesschain.skill-decision-observation/v1";
|
|
10
|
+
|
|
11
|
+
export const DECISION_MODES = Object.freeze(["off", "shadow", "suggest"]);
|
|
12
|
+
export const MAX_DECISION_CANDIDATES = 8;
|
|
13
|
+
|
|
14
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
15
|
+
const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,255}$/u;
|
|
16
|
+
|
|
17
|
+
function canonical(value) {
|
|
18
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
19
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
20
|
+
return `{${Object.keys(value)
|
|
21
|
+
.sort()
|
|
22
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
23
|
+
.join(",")}}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function decisionDigest(domain, value) {
|
|
27
|
+
return `sha256:${createHash("sha256")
|
|
28
|
+
.update(domain)
|
|
29
|
+
.update("\0")
|
|
30
|
+
.update(canonical(value))
|
|
31
|
+
.digest("hex")}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function plainObject(value, label) {
|
|
35
|
+
if (
|
|
36
|
+
!value ||
|
|
37
|
+
typeof value !== "object" ||
|
|
38
|
+
Array.isArray(value) ||
|
|
39
|
+
utilTypes.isProxy(value) ||
|
|
40
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(value))
|
|
41
|
+
) {
|
|
42
|
+
throw new TypeError(`${label} must be a plain object`);
|
|
43
|
+
}
|
|
44
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
45
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
46
|
+
if (
|
|
47
|
+
typeof key !== "string" ||
|
|
48
|
+
!descriptor?.enumerable ||
|
|
49
|
+
!("value" in descriptor)
|
|
50
|
+
) {
|
|
51
|
+
throw new TypeError(`${label} contains unsupported properties`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function boundedText(value, label, maximum) {
|
|
58
|
+
if (
|
|
59
|
+
typeof value !== "string" ||
|
|
60
|
+
value.trim() === "" ||
|
|
61
|
+
value.length > maximum ||
|
|
62
|
+
/\p{Cc}/u.test(value)
|
|
63
|
+
) {
|
|
64
|
+
throw new TypeError(`${label} is invalid or unbounded`);
|
|
65
|
+
}
|
|
66
|
+
return value.trim();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function identifier(value, label) {
|
|
70
|
+
const normalized = boundedText(value, label, 256);
|
|
71
|
+
if (!SAFE_ID.test(normalized)) throw new TypeError(`${label} is invalid`);
|
|
72
|
+
return normalized;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function probability(value, label) {
|
|
76
|
+
if (
|
|
77
|
+
typeof value !== "number" ||
|
|
78
|
+
!Number.isFinite(value) ||
|
|
79
|
+
value < 0 ||
|
|
80
|
+
value > 1
|
|
81
|
+
) {
|
|
82
|
+
throw new TypeError(`${label} must be a finite probability`);
|
|
83
|
+
}
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function normalizeCandidate(candidate, index) {
|
|
88
|
+
plainObject(candidate, `candidates[${index}]`);
|
|
89
|
+
const digest = candidate.digest;
|
|
90
|
+
if (!DIGEST.test(digest ?? "")) {
|
|
91
|
+
throw new TypeError(`candidates[${index}].digest is invalid`);
|
|
92
|
+
}
|
|
93
|
+
const tags = Array.isArray(candidate.tags)
|
|
94
|
+
? candidate.tags.map((tag, tagIndex) =>
|
|
95
|
+
boundedText(tag, `candidates[${index}].tags[${tagIndex}]`, 128),
|
|
96
|
+
)
|
|
97
|
+
: [];
|
|
98
|
+
if (tags.length > 32 || new Set(tags).size !== tags.length) {
|
|
99
|
+
throw new TypeError(`candidates[${index}].tags are invalid or unbounded`);
|
|
100
|
+
}
|
|
101
|
+
return Object.freeze({
|
|
102
|
+
candidateId: `c${index + 1}`,
|
|
103
|
+
id: identifier(candidate.id, `candidates[${index}].id`),
|
|
104
|
+
displayName: boundedText(
|
|
105
|
+
candidate.displayName || candidate.id,
|
|
106
|
+
`candidates[${index}].displayName`,
|
|
107
|
+
512,
|
|
108
|
+
),
|
|
109
|
+
description: boundedText(
|
|
110
|
+
candidate.description || "(no description)",
|
|
111
|
+
`candidates[${index}].description`,
|
|
112
|
+
16_384,
|
|
113
|
+
),
|
|
114
|
+
category: boundedText(
|
|
115
|
+
candidate.category || "uncategorized",
|
|
116
|
+
`candidates[${index}].category`,
|
|
117
|
+
128,
|
|
118
|
+
),
|
|
119
|
+
digest,
|
|
120
|
+
tags: Object.freeze(tags),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function normalizeDecisionMode(value = "off") {
|
|
125
|
+
if (!DECISION_MODES.includes(value)) {
|
|
126
|
+
throw new TypeError("decision mode must be off, shadow, or suggest");
|
|
127
|
+
}
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function createSkillDecisionRequest({
|
|
132
|
+
decisionId,
|
|
133
|
+
tenantId,
|
|
134
|
+
sessionId,
|
|
135
|
+
turnId,
|
|
136
|
+
query,
|
|
137
|
+
candidates,
|
|
138
|
+
policyDigest,
|
|
139
|
+
contextRevision,
|
|
140
|
+
} = {}) {
|
|
141
|
+
const normalizedCandidates = Array.isArray(candidates)
|
|
142
|
+
? candidates.map(normalizeCandidate)
|
|
143
|
+
: null;
|
|
144
|
+
if (
|
|
145
|
+
!normalizedCandidates ||
|
|
146
|
+
normalizedCandidates.length < 1 ||
|
|
147
|
+
normalizedCandidates.length > MAX_DECISION_CANDIDATES
|
|
148
|
+
) {
|
|
149
|
+
throw new TypeError("decision candidates are invalid or unbounded");
|
|
150
|
+
}
|
|
151
|
+
if (
|
|
152
|
+
new Set(normalizedCandidates.map(({ digest }) => digest)).size !==
|
|
153
|
+
normalizedCandidates.length
|
|
154
|
+
) {
|
|
155
|
+
throw new TypeError("decision candidates require unique content digests");
|
|
156
|
+
}
|
|
157
|
+
const binding = Object.freeze({
|
|
158
|
+
tenantId: identifier(tenantId, "tenantId"),
|
|
159
|
+
sessionId: identifier(sessionId, "sessionId"),
|
|
160
|
+
turnId: identifier(turnId, "turnId"),
|
|
161
|
+
policyDigest: DIGEST.test(policyDigest ?? "")
|
|
162
|
+
? policyDigest
|
|
163
|
+
: decisionDigest("chainlesschain.skill-decision-policy/v1", {
|
|
164
|
+
version: 1,
|
|
165
|
+
}),
|
|
166
|
+
contextRevision: identifier(
|
|
167
|
+
contextRevision || "current",
|
|
168
|
+
"contextRevision",
|
|
169
|
+
),
|
|
170
|
+
});
|
|
171
|
+
const candidateSetDigest = decisionDigest(
|
|
172
|
+
"chainlesschain.skill-decision-candidates/v1",
|
|
173
|
+
normalizedCandidates,
|
|
174
|
+
);
|
|
175
|
+
const state = Object.freeze({
|
|
176
|
+
task: boundedText(query, "query", 4096),
|
|
177
|
+
candidates: Object.freeze(
|
|
178
|
+
normalizedCandidates.map((candidate) =>
|
|
179
|
+
Object.freeze({
|
|
180
|
+
candidateId: candidate.candidateId,
|
|
181
|
+
name: candidate.displayName,
|
|
182
|
+
description: candidate.description,
|
|
183
|
+
category: candidate.category,
|
|
184
|
+
tags: candidate.tags,
|
|
185
|
+
}),
|
|
186
|
+
),
|
|
187
|
+
),
|
|
188
|
+
});
|
|
189
|
+
if (Buffer.byteLength(canonical(state), "utf8") > 96 * 1024) {
|
|
190
|
+
throw new TypeError("decision state is too large");
|
|
191
|
+
}
|
|
192
|
+
const criteria = Object.fromEntries(
|
|
193
|
+
normalizedCandidates.map((candidate) => [
|
|
194
|
+
candidate.candidateId,
|
|
195
|
+
`Use ${candidate.displayName}: ${candidate.description}`,
|
|
196
|
+
]),
|
|
197
|
+
);
|
|
198
|
+
criteria.none = "None of the listed skills is suitable for this task";
|
|
199
|
+
const questions = {
|
|
200
|
+
needs_skill: {
|
|
201
|
+
type: "noul",
|
|
202
|
+
instructions:
|
|
203
|
+
"Does this task need one of the listed skills to be handled well?",
|
|
204
|
+
},
|
|
205
|
+
best_skill: {
|
|
206
|
+
type: "choice",
|
|
207
|
+
instructions:
|
|
208
|
+
"Which listed skill is the best fit for the task? Choose none when every listed skill is unsuitable.",
|
|
209
|
+
criteria,
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
for (const candidate of normalizedCandidates) {
|
|
213
|
+
questions[`fits_${candidate.candidateId}`] = {
|
|
214
|
+
type: "noul",
|
|
215
|
+
instructions: `Is ${candidate.candidateId} suitable for the task and its stated boundaries?`,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const core = {
|
|
219
|
+
schema: SKILL_DECISION_REQUEST_SCHEMA,
|
|
220
|
+
decisionId: identifier(decisionId, "decisionId"),
|
|
221
|
+
purpose: "skill-routing",
|
|
222
|
+
binding,
|
|
223
|
+
candidateSetDigest,
|
|
224
|
+
candidates: Object.freeze(normalizedCandidates),
|
|
225
|
+
payload: Object.freeze({ state, questions: Object.freeze(questions) }),
|
|
226
|
+
};
|
|
227
|
+
return Object.freeze({
|
|
228
|
+
...core,
|
|
229
|
+
requestDigest: decisionDigest(SKILL_DECISION_REQUEST_SCHEMA, core),
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function normalizeNoul(answer, label) {
|
|
234
|
+
plainObject(answer, label);
|
|
235
|
+
if (answer.type !== undefined && answer.type !== "noul") {
|
|
236
|
+
throw new TypeError(`${label} has the wrong answer type`);
|
|
237
|
+
}
|
|
238
|
+
return Object.freeze({
|
|
239
|
+
type: "noul",
|
|
240
|
+
noul: probability(answer.noul, `${label}.noul`),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function normalizeChoice(answer, allowed, label) {
|
|
245
|
+
plainObject(answer, label);
|
|
246
|
+
if (answer.type !== undefined && answer.type !== "choice") {
|
|
247
|
+
throw new TypeError(`${label} has the wrong answer type`);
|
|
248
|
+
}
|
|
249
|
+
if (!allowed.has(answer.choice)) {
|
|
250
|
+
throw new TypeError(`${label}.choice is outside the candidate set`);
|
|
251
|
+
}
|
|
252
|
+
plainObject(answer.probabilities, `${label}.probabilities`);
|
|
253
|
+
if (
|
|
254
|
+
Object.keys(answer.probabilities).length !== allowed.size ||
|
|
255
|
+
Object.keys(answer.probabilities).some((key) => !allowed.has(key))
|
|
256
|
+
) {
|
|
257
|
+
throw new TypeError(`${label}.probabilities are incomplete`);
|
|
258
|
+
}
|
|
259
|
+
const probabilities = Object.fromEntries(
|
|
260
|
+
[...allowed].map((key) => [
|
|
261
|
+
key,
|
|
262
|
+
probability(answer.probabilities[key], `${label}.probabilities.${key}`),
|
|
263
|
+
]),
|
|
264
|
+
);
|
|
265
|
+
const sum = Object.values(probabilities).reduce(
|
|
266
|
+
(total, value) => total + value,
|
|
267
|
+
0,
|
|
268
|
+
);
|
|
269
|
+
if (Math.abs(sum - 1) > 0.02) {
|
|
270
|
+
throw new TypeError(`${label}.probabilities do not sum to one`);
|
|
271
|
+
}
|
|
272
|
+
return Object.freeze({
|
|
273
|
+
type: "choice",
|
|
274
|
+
choice: answer.choice,
|
|
275
|
+
confidence: probability(answer.confidence, `${label}.confidence`),
|
|
276
|
+
probabilities: Object.freeze(probabilities),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function normalizeSkillDecisionProviderResult(request, value) {
|
|
281
|
+
plainObject(value, "decision provider result");
|
|
282
|
+
plainObject(value.answers, "decision provider result.answers");
|
|
283
|
+
const expectedKeys = [
|
|
284
|
+
"needs_skill",
|
|
285
|
+
"best_skill",
|
|
286
|
+
...request.candidates.map(({ candidateId }) => `fits_${candidateId}`),
|
|
287
|
+
];
|
|
288
|
+
if (
|
|
289
|
+
Object.keys(value.answers).length !== expectedKeys.length ||
|
|
290
|
+
expectedKeys.some((key) => !Object.hasOwn(value.answers, key))
|
|
291
|
+
) {
|
|
292
|
+
throw new TypeError("decision provider answers are incomplete");
|
|
293
|
+
}
|
|
294
|
+
const allowed = new Set([
|
|
295
|
+
...request.candidates.map(({ candidateId }) => candidateId),
|
|
296
|
+
"none",
|
|
297
|
+
]);
|
|
298
|
+
const answers = {
|
|
299
|
+
needs_skill: normalizeNoul(
|
|
300
|
+
value.answers.needs_skill,
|
|
301
|
+
"answers.needs_skill",
|
|
302
|
+
),
|
|
303
|
+
best_skill: normalizeChoice(
|
|
304
|
+
value.answers.best_skill,
|
|
305
|
+
allowed,
|
|
306
|
+
"answers.best_skill",
|
|
307
|
+
),
|
|
308
|
+
};
|
|
309
|
+
for (const candidate of request.candidates) {
|
|
310
|
+
const key = `fits_${candidate.candidateId}`;
|
|
311
|
+
answers[key] = normalizeNoul(value.answers[key], `answers.${key}`);
|
|
312
|
+
}
|
|
313
|
+
const core = {
|
|
314
|
+
schema: SKILL_DECISION_RESULT_SCHEMA,
|
|
315
|
+
decisionId: request.decisionId,
|
|
316
|
+
requestDigest: request.requestDigest,
|
|
317
|
+
candidateSetDigest: request.candidateSetDigest,
|
|
318
|
+
provider: boundedText(value.provider, "provider", 160),
|
|
319
|
+
model: boundedText(value.model, "model", 160),
|
|
320
|
+
answers: Object.freeze(answers),
|
|
321
|
+
};
|
|
322
|
+
return Object.freeze({
|
|
323
|
+
...core,
|
|
324
|
+
usage:
|
|
325
|
+
value.usage && typeof value.usage === "object"
|
|
326
|
+
? Object.freeze({ ...value.usage })
|
|
327
|
+
: null,
|
|
328
|
+
resultDigest: decisionDigest(SKILL_DECISION_RESULT_SCHEMA, core),
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function resolveSkillDecision(request, result, thresholds = {}) {
|
|
333
|
+
const needsSkill = thresholds.needsSkill ?? 0.5;
|
|
334
|
+
const candidateFit = thresholds.candidateFit ?? 0.5;
|
|
335
|
+
const choiceConfidence = thresholds.choiceConfidence ?? 0.5;
|
|
336
|
+
for (const [name, value] of Object.entries({
|
|
337
|
+
needsSkill,
|
|
338
|
+
candidateFit,
|
|
339
|
+
choiceConfidence,
|
|
340
|
+
})) {
|
|
341
|
+
probability(value, `thresholds.${name}`);
|
|
342
|
+
}
|
|
343
|
+
const choice = result.answers.best_skill;
|
|
344
|
+
let status = "suggestion";
|
|
345
|
+
let reasonCode = "accepted";
|
|
346
|
+
let selected = null;
|
|
347
|
+
if (result.answers.needs_skill.noul < needsSkill) {
|
|
348
|
+
status = "no-match";
|
|
349
|
+
reasonCode = "needs-skill-below-threshold";
|
|
350
|
+
} else if (choice.choice === "none") {
|
|
351
|
+
status = "no-match";
|
|
352
|
+
reasonCode = "choice-none";
|
|
353
|
+
} else if (choice.confidence < choiceConfidence) {
|
|
354
|
+
status = "abstain";
|
|
355
|
+
reasonCode = "choice-confidence-below-threshold";
|
|
356
|
+
} else {
|
|
357
|
+
selected = request.candidates.find(
|
|
358
|
+
({ candidateId }) => candidateId === choice.choice,
|
|
359
|
+
);
|
|
360
|
+
const fit = result.answers[`fits_${choice.choice}`].noul;
|
|
361
|
+
if (fit < candidateFit) {
|
|
362
|
+
status = "abstain";
|
|
363
|
+
reasonCode = "candidate-fit-below-threshold";
|
|
364
|
+
selected = null;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return Object.freeze({
|
|
368
|
+
status,
|
|
369
|
+
reasonCode,
|
|
370
|
+
selectedCandidateId: selected?.candidateId ?? null,
|
|
371
|
+
selectedDigest: selected?.digest ?? null,
|
|
372
|
+
selectedSkillId: selected?.id ?? null,
|
|
373
|
+
needsSkillProbability: result.answers.needs_skill.noul,
|
|
374
|
+
choiceConfidence: choice.confidence,
|
|
375
|
+
resultDigest: result.resultDigest,
|
|
376
|
+
});
|
|
377
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { types as utilTypes } from "node:util";
|
|
2
|
+
|
|
3
|
+
export const DECISION_PROVIDER_AUTHORITY_SCHEMA =
|
|
4
|
+
"chainlesschain.decision-provider-authority/v1";
|
|
5
|
+
|
|
6
|
+
const AUTHORITIES = new WeakSet();
|
|
7
|
+
|
|
8
|
+
function boundedText(value, label) {
|
|
9
|
+
if (
|
|
10
|
+
typeof value !== "string" ||
|
|
11
|
+
value.trim() === "" ||
|
|
12
|
+
value.length > 160 ||
|
|
13
|
+
/\p{Cc}/u.test(value)
|
|
14
|
+
) {
|
|
15
|
+
throw new TypeError(`${label} is invalid or unbounded`);
|
|
16
|
+
}
|
|
17
|
+
return value.trim();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function openDecisionProviderAuthority({
|
|
21
|
+
provider,
|
|
22
|
+
model,
|
|
23
|
+
decide,
|
|
24
|
+
} = {}) {
|
|
25
|
+
if (typeof decide !== "function" || utilTypes.isProxy(decide)) {
|
|
26
|
+
throw new TypeError("decision provider decide() is required");
|
|
27
|
+
}
|
|
28
|
+
const operation = (...args) => Reflect.apply(decide, undefined, args);
|
|
29
|
+
const authority = Object.freeze({
|
|
30
|
+
schema: DECISION_PROVIDER_AUTHORITY_SCHEMA,
|
|
31
|
+
provider: boundedText(provider, "provider"),
|
|
32
|
+
model: boundedText(model, "model"),
|
|
33
|
+
decide: operation,
|
|
34
|
+
});
|
|
35
|
+
AUTHORITIES.add(authority);
|
|
36
|
+
return authority;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function captureDecisionProviderAuthority(value) {
|
|
40
|
+
if (!AUTHORITIES.has(value)) {
|
|
41
|
+
throw new TypeError("a branded decision provider authority is required");
|
|
42
|
+
}
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { openDecisionProviderAuthority } from "./provider-authority.js";
|
|
2
|
+
|
|
3
|
+
const PROVIDERS = Object.freeze({
|
|
4
|
+
typesafe: {
|
|
5
|
+
model: "jev-latest",
|
|
6
|
+
baseUrl: "https://api.typesafe.ai",
|
|
7
|
+
label: "TypeSafe",
|
|
8
|
+
},
|
|
9
|
+
laya: {
|
|
10
|
+
model: "laya",
|
|
11
|
+
baseUrl: "http://127.0.0.1:8000",
|
|
12
|
+
label: "Laya",
|
|
13
|
+
},
|
|
14
|
+
"system-one": { label: "System One" },
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function boundedText(value, label, limit = 160) {
|
|
18
|
+
if (
|
|
19
|
+
typeof value !== "string" ||
|
|
20
|
+
value.trim() === "" ||
|
|
21
|
+
value.length > limit ||
|
|
22
|
+
/\p{Cc}/u.test(value)
|
|
23
|
+
) {
|
|
24
|
+
throw new TypeError(`${label} is required and must be bounded text`);
|
|
25
|
+
}
|
|
26
|
+
return value.trim();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function endpointFor(baseUrl, provider) {
|
|
30
|
+
const parsed = new URL(baseUrl);
|
|
31
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
32
|
+
throw new TypeError("decision provider URL must use HTTP or HTTPS");
|
|
33
|
+
}
|
|
34
|
+
if (parsed.username || parsed.password || /[?#]/u.test(baseUrl)) {
|
|
35
|
+
throw new TypeError(
|
|
36
|
+
"decision provider URL must not contain credentials, a query, or a fragment",
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const loopback = ["127.0.0.1", "localhost", "[::1]"].includes(
|
|
40
|
+
parsed.hostname,
|
|
41
|
+
);
|
|
42
|
+
if (provider === "laya" && !loopback) {
|
|
43
|
+
throw new TypeError("Laya decision provider URL must use loopback");
|
|
44
|
+
}
|
|
45
|
+
if (parsed.protocol !== "https:" && !loopback) {
|
|
46
|
+
throw new TypeError("decision provider URL must use HTTPS or loopback");
|
|
47
|
+
}
|
|
48
|
+
const path = parsed.pathname.replace(/\/+$/u, "");
|
|
49
|
+
parsed.pathname = path.endsWith("/v1/systemone")
|
|
50
|
+
? path
|
|
51
|
+
: path.endsWith("/v1")
|
|
52
|
+
? `${path}/systemone`
|
|
53
|
+
: `${path}/v1/systemone`;
|
|
54
|
+
return parsed.toString();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function resolveDecisionProviderOptions({
|
|
58
|
+
decisionProvider = "typesafe",
|
|
59
|
+
decisionModel,
|
|
60
|
+
decisionBaseUrl,
|
|
61
|
+
} = {}) {
|
|
62
|
+
const provider = boundedText(decisionProvider, "decision provider");
|
|
63
|
+
if (!Object.hasOwn(PROVIDERS, provider)) {
|
|
64
|
+
throw new TypeError(`unknown decision provider: ${provider}`);
|
|
65
|
+
}
|
|
66
|
+
const defaults = PROVIDERS[provider];
|
|
67
|
+
const model = boundedText(decisionModel ?? defaults.model, "decision model");
|
|
68
|
+
const baseUrl = boundedText(
|
|
69
|
+
decisionBaseUrl ?? defaults.baseUrl,
|
|
70
|
+
"decision base URL",
|
|
71
|
+
4096,
|
|
72
|
+
);
|
|
73
|
+
endpointFor(baseUrl, provider);
|
|
74
|
+
return { provider, model, baseUrl };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function boundedSecret(value, provider) {
|
|
78
|
+
if (value === undefined && provider !== "typesafe") return undefined;
|
|
79
|
+
if (
|
|
80
|
+
typeof value !== "string" ||
|
|
81
|
+
value.trim() === "" ||
|
|
82
|
+
value.length > 8192 ||
|
|
83
|
+
/\p{Cc}/u.test(value)
|
|
84
|
+
) {
|
|
85
|
+
throw new TypeError(
|
|
86
|
+
`${PROVIDERS[provider].label} API key is required or invalid`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function providerError(status, provider) {
|
|
93
|
+
const error = new Error(
|
|
94
|
+
`${PROVIDERS[provider].label} decision request failed with status ${status}`,
|
|
95
|
+
);
|
|
96
|
+
error.code = "CC_DECISION_PROVIDER_HTTP_ERROR";
|
|
97
|
+
error.status = status;
|
|
98
|
+
return error;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function createDecisionProvider({
|
|
102
|
+
provider,
|
|
103
|
+
model,
|
|
104
|
+
baseUrl,
|
|
105
|
+
apiKey,
|
|
106
|
+
fetchImpl = globalThis.fetch,
|
|
107
|
+
} = {}) {
|
|
108
|
+
const options = resolveDecisionProviderOptions({
|
|
109
|
+
decisionProvider: provider,
|
|
110
|
+
decisionModel: model,
|
|
111
|
+
decisionBaseUrl: baseUrl,
|
|
112
|
+
});
|
|
113
|
+
const secret = boundedSecret(apiKey, options.provider);
|
|
114
|
+
if (typeof fetchImpl !== "function") {
|
|
115
|
+
throw new TypeError("decision provider fetch implementation is required");
|
|
116
|
+
}
|
|
117
|
+
const endpoint = endpointFor(options.baseUrl, options.provider);
|
|
118
|
+
return openDecisionProviderAuthority({
|
|
119
|
+
provider: options.provider,
|
|
120
|
+
model: options.model,
|
|
121
|
+
decide: async (request, { signal } = {}) => {
|
|
122
|
+
const response = await fetchImpl(endpoint, {
|
|
123
|
+
method: "POST",
|
|
124
|
+
headers: {
|
|
125
|
+
...(secret === undefined
|
|
126
|
+
? {}
|
|
127
|
+
: { authorization: `Bearer ${secret}` }),
|
|
128
|
+
"content-type": "application/json",
|
|
129
|
+
},
|
|
130
|
+
body: JSON.stringify({
|
|
131
|
+
model: options.model,
|
|
132
|
+
state: request.payload.state,
|
|
133
|
+
questions: request.payload.questions,
|
|
134
|
+
}),
|
|
135
|
+
signal,
|
|
136
|
+
redirect: "error",
|
|
137
|
+
});
|
|
138
|
+
if (!response?.ok) {
|
|
139
|
+
throw providerError(response?.status ?? 0, options.provider);
|
|
140
|
+
}
|
|
141
|
+
const body = await response.json();
|
|
142
|
+
return {
|
|
143
|
+
provider: options.provider,
|
|
144
|
+
model: typeof body?.model === "string" ? body.model : options.model,
|
|
145
|
+
answers: body?.answers,
|
|
146
|
+
usage: body?.usage,
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
}
|