nolo-cli 0.32.0-alpha.4 → 0.33.0-alpha.2
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 +6 -12
- package/{_executeModel-YXHDCXHF.js → _executeModel-RWPVI3YV.js} +76 -67
- package/{action-HI3VRQLP.js → action-SMLG6OTB.js} +17 -15
- package/{addContentAction-NCURJ6PK.js → addContentAction-SFO244QN.js} +14 -13
- package/{addDialogAgentAction-RCY4ECF4.js → addDialogAgentAction-W44ZCEHB.js} +14 -13
- package/{agentDeleteCommand-QWWT4EBM.js → agentDeleteCommand-KU2RXQPP.js} +42 -59
- package/{agentEmailCommands-T2WV6M3L.js → agentEmailCommands-MPCMDENS.js} +89 -80
- package/{agentGrantCommands-E7ZZFRHK.js → agentGrantCommands-2LEZDADN.js} +2 -2
- package/{agentListCommands-SQLSBSZX.js → agentListCommands-EPD4N6FX.js} +73 -78
- package/{agentMachineCommands-O7MZVQEL.js → agentMachineCommands-AF7C3YRT.js} +40 -57
- package/{agentPullCommand-ARSIDNVC.js → agentPullCommand-YH5GEBK4.js} +5 -5
- package/agentRecordCommands-EYE6MZZG.js +112 -0
- package/agentRunCommand-LL22SGTN.js +130 -0
- package/{agentRuntimeLocal-JPSR5BZ5.js → agentRuntimeLocal-JX34G47Z.js} +35 -50
- package/{agentSlice-QYJQOUVC.js → agentSlice-TNMFQQOV.js} +15 -13
- package/{appDeleteCommands-ZQLZ4R54.js → appDeleteCommands-43K5VXQB.js} +38 -55
- package/{appDeployCommands-A5ISQH7L.js → appDeployCommands-FEEJSVDZ.js} +38 -55
- package/{appDeployStatusCommands-PVIPXEJZ.js → appDeployStatusCommands-H76CG45R.js} +38 -55
- package/{appGetCommands-CTMVFLQF.js → appGetCommands-MDZYFTYZ.js} +38 -55
- package/{appListCommands-WXIHMKQQ.js → appListCommands-TUJJXPWG.js} +38 -55
- package/{authCommand-BBDHMSO6.js → authCommand-T7UK4CWS.js} +18 -18
- package/{authCommands-4UDEKRE6.js → authCommands-EAPFGNHN.js} +8 -8
- package/chatQueueReduxAdapter-LVQXC4ZY.js +180 -0
- package/chunk-2H3XIBY4.js +239 -0
- package/{chunk-IRZBFTQA.js → chunk-2IVEXF7P.js} +11 -4
- package/{chunk-WTGCTVJG.js → chunk-2QTEYCR7.js} +3 -6
- package/{chunk-DOISARTV.js → chunk-2UECQ7RE.js} +1 -1
- package/{chunk-SWYMCHM7.js → chunk-37V5LNEQ.js} +69 -1
- package/{chunk-E3APEOIM.js → chunk-3GZXL6FM.js} +4 -19
- package/{chunk-RMOJVZWX.js → chunk-3VAQHAXT.js} +44 -44
- package/{chunk-6VCKAMSL.js → chunk-3WXRAHCG.js} +6 -5
- package/{chunk-LAXMH7JY.js → chunk-57QJXIB6.js} +18 -15
- package/chunk-5CS33IBL.js +301 -0
- package/{chunk-MW4IK7L4.js → chunk-5SBK2MTI.js} +4 -365
- package/chunk-6PO2SYCS.js +1800 -0
- package/{chunk-7WEUX3P3.js → chunk-6SXC35F4.js} +182 -20
- package/{chunk-MXFQHRSS.js → chunk-6XIE5ZGI.js} +1 -1
- package/{chunk-Y7WMYFED.js → chunk-73GINUCW.js} +256 -451
- package/{chunk-VMWR7VNI.js → chunk-7E72JMBB.js} +7 -7
- package/{chunk-7YQOB4DH.js → chunk-AAGCMVFT.js} +106 -124
- package/chunk-ADLYMQB6.js +642 -0
- package/{chunk-ZWJOGMKH.js → chunk-AETZ7AD6.js} +1 -1
- package/{chunk-UDA3ZYLW.js → chunk-AFV4FOT2.js} +70 -24
- package/{chunk-BGTUGS3T.js → chunk-AOXVOC6D.js} +4 -30
- package/{chunk-3GX5X3X3.js → chunk-B2BSG6QQ.js} +12 -11
- package/{chunk-44HACRCK.js → chunk-BANYWEYY.js} +4 -4
- package/{chunk-TOW4E763.js → chunk-BJIRLHJR.js} +2 -0
- package/{chunk-ZJ2WITOO.js → chunk-BQXOGBFN.js} +2 -2
- package/{chunk-G5GVZAXF.js → chunk-CLP2K7U4.js} +15 -19
- package/{chunk-2K4NDPT5.js → chunk-DFUPZE6V.js} +20 -12
- package/{chunk-YHGHADBQ.js → chunk-DPMBNHOJ.js} +4 -4
- package/chunk-EGRJC4ZN.js +91 -0
- package/{chunk-K6QEHQZ3.js → chunk-EKLRRZIN.js} +1 -1
- package/{chunk-XFG3BAKN.js → chunk-FMEVI5TG.js} +65 -0
- package/{chunk-CHHN4XWM.js → chunk-FSSX3XRY.js} +2 -4
- package/{chunk-VP4WJWKW.js → chunk-GM6PU7B6.js} +431 -345
- package/{chunk-6AD7WQOJ.js → chunk-GMXWYXAF.js} +7 -7
- package/{chunk-SFWZUTCI.js → chunk-GTYM4HKV.js} +1 -1
- package/{chunk-NYBNI5MY.js → chunk-HDKRSRYU.js} +1461 -301
- package/chunk-HS7MLR74.js +38 -0
- package/{chunk-3AUWC6EM.js → chunk-HUCT7HID.js} +5 -84
- package/{chunk-PTHDLIRB.js → chunk-I6N2UVVY.js} +1 -1
- package/chunk-IDAU4UFS.js +437 -0
- package/{chunk-OF5JK63U.js → chunk-IHEC7VBF.js} +1 -1
- package/{chunk-NM3AVNMH.js → chunk-IL545V3E.js} +4 -4
- package/{chunk-3LY4F7SV.js → chunk-INZZJSQF.js} +348 -331
- package/{chunk-CF2WZF4N.js → chunk-J6WH4PYZ.js} +0 -8
- package/{chunk-VMRGMPNM.js → chunk-JMPYDFHY.js} +6 -6
- package/{chunk-V54H24CQ.js → chunk-JTSGWTYZ.js} +3 -3
- package/{chunk-ATK5WJOA.js → chunk-JZ5AMMXU.js} +4 -4
- package/chunk-KHCLMKZZ.js +3062 -0
- package/{chunk-WHLVPK32.js → chunk-KMSZPTM6.js} +27 -3
- package/{chunk-L3GCUVOH.js → chunk-KSRFVP36.js} +1 -1
- package/{chunk-33COESA5.js → chunk-LOD75GOS.js} +336 -32
- package/{chunk-C3POSH7K.js → chunk-M2YMQOLC.js} +44 -53
- package/chunk-M3JEW6N6.js +193 -0
- package/{chunk-MQFSFU3Y.js → chunk-M4NC7NF6.js} +95 -95
- package/{chunk-GVNRF276.js → chunk-MPZJVZDC.js} +3735 -1394
- package/{chunk-IXZX5CJK.js → chunk-MQRZ5QUH.js} +1 -1
- package/{chunk-3ASDTTEI.js → chunk-MRWGHF56.js} +2 -0
- package/{chunk-D34RI6NI.js → chunk-NNWHHCVP.js} +75 -1
- package/{chunk-6YABCOFU.js → chunk-NUO3QFWD.js} +1 -1
- package/{chunk-NSXTWXGH.js → chunk-O6GEBMIY.js} +269 -309
- package/{chunk-CAENRKNJ.js → chunk-OR2HNLVO.js} +126 -88
- package/chunk-OW765XBU.js +10 -0
- package/chunk-PREQU5QV.js +231 -0
- package/{chunk-Q3CSL43H.js → chunk-Q5ITEGIN.js} +1 -1
- package/{chunk-7S54ZGF6.js → chunk-RAZOLMJR.js} +256 -12
- package/chunk-RCFIB45Q.js +28 -0
- package/chunk-RY57GLGW.js +188 -0
- package/{chunk-KGEVMUMI.js → chunk-TFPUAELY.js} +11 -11
- package/{chunk-ZJH3LKEW.js → chunk-UK5JGQVU.js} +94 -15
- package/chunk-URMS4XY2.js +10 -0
- package/{chunk-POMSDOTR.js → chunk-VH2F7ZB6.js} +1 -1
- package/chunk-VIDPVFP3.js +20 -0
- package/{chunk-CBVEM475.js → chunk-WHD6BG7M.js} +400 -115
- package/{chunk-5RDLGLAP.js → chunk-WJSW43QZ.js} +4 -7
- package/{chunk-CF7S2RYZ.js → chunk-WLH5BAKX.js} +6 -6
- package/{chunk-2DQTFBJX.js → chunk-X2DAEZ3X.js} +1 -1
- package/{chunk-2IJAKBK2.js → chunk-X664KVEV.js} +426 -246
- package/{chunk-43EPBPZ2.js → chunk-XCCGU6QB.js} +2 -2
- package/chunk-Y5GCAMGP.js +9 -0
- package/{chunk-2VOSL35C.js → chunk-YDTYDA5W.js} +3 -3
- package/chunk-YYLHWIW6.js +48 -0
- package/{chunk-AOS5IN2I.js → chunk-ZHYK3N56.js} +1 -1
- package/{chunk-7MTP4AIU.js → chunk-ZJMME4DS.js} +19 -303
- package/{chunk-PJ2DDQQM.js → chunk-ZURFOV5J.js} +2 -2
- package/chunk-ZZ2MH7LE.js +84 -0
- package/{cliExecutor-BBUVQU4L.js → cliExecutor-DW3PHGEL.js} +2 -2
- package/{clipboardy-BVE3LVEH.js → clipboardy-MMBYVRLF.js} +166 -372
- package/{codingSkills-V35TRR4Y.js → codingSkills-DY5MINPG.js} +5 -4
- package/{createAgentAutomationAction-5I6ZMYIA.js → createAgentAutomationAction-INQT23LX.js} +40 -31
- package/createDialogAction-LDCPDI73.js +60 -0
- package/{createPageAction-M75JWNUP.js → createPageAction-5YXOG2M4.js} +56 -47
- package/{db-6DPSJ6WT.js → db-3H3JECGY.js} +45 -5
- package/{dbSlice-BBL3PEVW.js → dbSlice-3SD5L5H2.js} +13 -12
- package/{deleteFile-RJTEPOT4.js → deleteFile-XQXPBFFB.js} +7 -6
- package/dialogCommands-CHJO47AX.js +81 -0
- package/{dialogSlice-WDIOJW3W.js → dialogSlice-DOWKOILN.js} +36 -29
- package/{docCreateCommands-XU72LHUF.js → docCreateCommands-OVZARUFX.js} +40 -55
- package/{docDeleteCommands-EUN6IJ6O.js → docDeleteCommands-E2XJ62LD.js} +42 -57
- package/{docReadCommands-LKE4DVQI.js → docReadCommands-I7OSREPJ.js} +40 -55
- package/{docStore-BDOACT3C.js → docStore-UAWSKZ2Y.js} +39 -30
- package/{docUpdateCommands-SL6IUM52.js → docUpdateCommands-X4Z26VJM.js} +43 -58
- package/{fetchMessages-VPPQDDZ4.js → fetchMessages-7QRCCRYK.js} +3 -3
- package/{getPricing-QO5TYNCK.js → getPricing-L2ENXWHV.js} +7 -6
- package/{handleSendMessageAction-OUQ5QCMS.js → handleSendMessageAction-C3TSDWKH.js} +38 -31
- package/index.js +67 -67
- package/{lib-FYYBQIXS.js → lib-2ZTNRXR4.js} +432 -183
- package/{localDialogRead-3DBXVYXS.js → localDialogRead-SLMPV5SK.js} +2 -2
- package/{localRuntimeAuthority-NDUA2D7Y.js → localRuntimeAuthority-E3R24J4T.js} +4 -2
- package/{localRuntimeDb-GKYRBWLQ.js → localRuntimeDb-DDZCJFQZ.js} +1 -1
- package/{machineCommands-UUW4ZBMZ.js → machineCommands-BUOIYJAD.js} +93 -84
- package/{machineWsRunDispatch-HGYZ47ND.js → machineWsRunDispatch-7CRWAA6O.js} +83 -74
- package/{models-WDUTTYFS.js → models-OX2S5C6Q.js} +2 -2
- package/{offlineMarxistsAgentCommand-E6LUG63A.js → offlineMarxistsAgentCommand-GEH6SNNA.js} +1 -1
- package/package.json +1 -4
- package/{read-64OQDO3I.js → read-6G73BMEY.js} +8 -7
- package/{readDocTool-MXM3T6PE.js → readDocTool-DK4EI2GA.js} +1 -2
- package/{readlineWorkspace-IHXWZCWS.js → readlineWorkspace-ZDWEASJV.js} +265 -428
- package/{removeDialogAgentAction-NEKVAMSH.js → removeDialogAgentAction-E7H557UO.js} +19 -17
- package/{runAgentClientLoop-TBZZWCN6.js → runAgentClientLoop-U7HYA3O5.js} +72 -64
- package/{runtimeDoctorCommands-WI2YZUSJ.js → runtimeDoctorCommands-KIKM6BIO.js} +5 -5
- package/{setDialogExtraReferencesAction-WTOHQDIV.js → setDialogExtraReferencesAction-RMMGBR5F.js} +15 -14
- package/{setPrimaryDialogAgentAction-LDJOYC4F.js → setPrimaryDialogAgentAction-FWBKKLVA.js} +19 -17
- package/{settingSlice-4M37TN7V.js → settingSlice-73PV4KG4.js} +16 -14
- package/{skillDiscovery-5U6RYAHN.js → skillDiscovery-KLLKXPUO.js} +4 -4
- package/{slateUtils-2M7MUTWX.js → slateUtils-VO2FU36K.js} +1 -1
- package/{spaceCommands-B6SAUSGD.js → spaceCommands-GEWZXGHM.js} +43 -240
- package/{spaceSlice-Q6IMD5NX.js → spaceSlice-B6MOVY4N.js} +38 -61
- package/{streamAgentChatTurn-X4LGYPQX.js → streamAgentChatTurn-T527EQTT.js} +1261 -150
- package/{switchDialogAgentAction-XVWGKR2Z.js → switchDialogAgentAction-US6QNL3N.js} +14 -13
- package/syncMapping-RK2MANUX.js +43 -0
- package/{tableCommands-RJZ3V4TF.js → tableCommands-QE47K72R.js} +8 -7
- package/{toolApiClient-ARGFDJAG.js → toolApiClient-B2MFXMEG.js} +3 -3
- package/tools-XMWCVMPM.js +98 -0
- package/{tuiSummaryLlmCaller-SRZ4QQUP.js → tuiSummaryLlmCaller-NCAJSVSD.js} +24 -21
- package/{updateDialogTitleAction-HOYHEVOU.js → updateDialogTitleAction-XPJZRJEL.js} +48 -38
- package/agentRecordCommands-GFPAXOW5.js +0 -103
- package/agentRunCommand-IXI7BKCG.js +0 -121
- package/chunk-DCDL3GC4.js +0 -171
- package/chunk-F3MP7CP6.js +0 -73
- package/chunk-RPHGRXQM.js +0 -1707
- package/chunk-WI7I7UKC.js +0 -3158
- package/chunk-WZSRQNQG.js +0 -2587
- package/createDialogAction-WXVKBBRV.js +0 -52
- package/dialogCommands-7QDRPPWW.js +0 -95
- package/tools-44PI5ZON.js +0 -90
- package/{chunk-Z5MXSEOJ.js → chunk-RQSOAMPJ.js} +2 -2
- package/{chunk-JDSUTNYY.js → chunk-SAQQLJZ5.js} +3 -3
package/chunk-WI7I7UKC.js
DELETED
|
@@ -1,3158 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
buildDialogSummaryLayer,
|
|
3
|
-
buildLinkedSpacesSection,
|
|
4
|
-
buildSpaceContextLayer
|
|
5
|
-
} from "./chunk-DOISARTV.js";
|
|
6
|
-
import {
|
|
7
|
-
buildCurrentTimeBlock,
|
|
8
|
-
buildIdentityBlock,
|
|
9
|
-
buildRuntimeGuidanceBlocks,
|
|
10
|
-
fetchReferenceContents,
|
|
11
|
-
resolveToolGuidedSections
|
|
12
|
-
} from "./chunk-MW4IK7L4.js";
|
|
13
|
-
import {
|
|
14
|
-
getAllToolRuns,
|
|
15
|
-
resolveAgentRecommendedSkillNames,
|
|
16
|
-
resolveAgentRequiredPackIds
|
|
17
|
-
} from "./chunk-RPHGRXQM.js";
|
|
18
|
-
import {
|
|
19
|
-
getDocState
|
|
20
|
-
} from "./chunk-6AD7WQOJ.js";
|
|
21
|
-
import {
|
|
22
|
-
resolveToolBaseUrl
|
|
23
|
-
} from "./chunk-44HACRCK.js";
|
|
24
|
-
import {
|
|
25
|
-
getFinalPrice,
|
|
26
|
-
getModelPricing,
|
|
27
|
-
getPrices,
|
|
28
|
-
hasExplicitAgentPricing
|
|
29
|
-
} from "./chunk-E3APEOIM.js";
|
|
30
|
-
import {
|
|
31
|
-
selectCurrentTable,
|
|
32
|
-
selectTableRows,
|
|
33
|
-
selectViewMode
|
|
34
|
-
} from "./chunk-GVNRF276.js";
|
|
35
|
-
import {
|
|
36
|
-
PERSONALIZATION_DIALOG_CATEGORY,
|
|
37
|
-
buildPersonalizationDialogPolicyContext,
|
|
38
|
-
extractReferenceKeysFromMessage,
|
|
39
|
-
getModelContextWindow,
|
|
40
|
-
resolveBuiltinPlatformAgentConfig,
|
|
41
|
-
selectAllMsgs
|
|
42
|
-
} from "./chunk-Y7WMYFED.js";
|
|
43
|
-
import {
|
|
44
|
-
COMPACTION_SUMMARY_SYSTEM_PROMPT,
|
|
45
|
-
buildCompactionMetricsFromPlan,
|
|
46
|
-
buildCompactionUserContent,
|
|
47
|
-
clipCompactText,
|
|
48
|
-
estimateTokenCount,
|
|
49
|
-
formatCompactionMetricsLog,
|
|
50
|
-
formatFileOperationsFromMessages,
|
|
51
|
-
formatMessagesForSummaryWithTruncation,
|
|
52
|
-
planCompression,
|
|
53
|
-
planContextUsage
|
|
54
|
-
} from "./chunk-BGTUGS3T.js";
|
|
55
|
-
import {
|
|
56
|
-
toErrorMessage
|
|
57
|
-
} from "./chunk-HNMXYYJR.js";
|
|
58
|
-
import {
|
|
59
|
-
selectPendingFiles
|
|
60
|
-
} from "./chunk-3ASDTTEI.js";
|
|
61
|
-
import {
|
|
62
|
-
findModelConfig,
|
|
63
|
-
getModelConfig,
|
|
64
|
-
getProviderByModelName
|
|
65
|
-
} from "./chunk-2K4NDPT5.js";
|
|
66
|
-
import {
|
|
67
|
-
PLATFORM_HOSTED_QWEN_37_FLASH_MODEL
|
|
68
|
-
} from "./chunk-CAENRKNJ.js";
|
|
69
|
-
import {
|
|
70
|
-
DEFAULT_AGENT_BASE_POLICY,
|
|
71
|
-
DEFAULT_USER_PREFERENCE_PROFILE,
|
|
72
|
-
selectAiRecentContentLimit,
|
|
73
|
-
selectGlobalPrompt,
|
|
74
|
-
selectKnowledgeCaptureLevel,
|
|
75
|
-
selectSpaceContextLevel,
|
|
76
|
-
selectUserTonePreset
|
|
77
|
-
} from "./chunk-G5GVZAXF.js";
|
|
78
|
-
import {
|
|
79
|
-
asRecordOrEmpty
|
|
80
|
-
} from "./chunk-KX6YBIHG.js";
|
|
81
|
-
import {
|
|
82
|
-
read,
|
|
83
|
-
selectById
|
|
84
|
-
} from "./chunk-LAXMH7JY.js";
|
|
85
|
-
import {
|
|
86
|
-
asTrimmedLowercaseString
|
|
87
|
-
} from "./chunk-QSJ3HFEF.js";
|
|
88
|
-
import {
|
|
89
|
-
PUBLIC_QWEN_37_FLASH_AGENT_KEY
|
|
90
|
-
} from "./chunk-ZJH3LKEW.js";
|
|
91
|
-
import {
|
|
92
|
-
extractCustomId
|
|
93
|
-
} from "./chunk-TOW4E763.js";
|
|
94
|
-
import {
|
|
95
|
-
selectIdentityUserBalance,
|
|
96
|
-
selectIdentityUserId
|
|
97
|
-
} from "./chunk-2IJAKBK2.js";
|
|
98
|
-
import {
|
|
99
|
-
isRecord
|
|
100
|
-
} from "./chunk-KUG52IAP.js";
|
|
101
|
-
import {
|
|
102
|
-
canonicalizeToolName,
|
|
103
|
-
canonicalizeToolNames,
|
|
104
|
-
prioritizeToolNames
|
|
105
|
-
} from "./chunk-3AUWC6EM.js";
|
|
106
|
-
import {
|
|
107
|
-
TOOL_PACKS,
|
|
108
|
-
addDefaultSystemCapabilityTools,
|
|
109
|
-
applyDefaultWebToolPacks,
|
|
110
|
-
applyDisabledTools,
|
|
111
|
-
applySystemBuiltinSkillFilter,
|
|
112
|
-
expandEnabledPackPromptPatches,
|
|
113
|
-
expandEnabledPacks,
|
|
114
|
-
resolveEffectiveEnabledPacks
|
|
115
|
-
} from "./chunk-CF7S2RYZ.js";
|
|
116
|
-
import {
|
|
117
|
-
asNonEmptyStringArray
|
|
118
|
-
} from "./chunk-I42VC5KR.js";
|
|
119
|
-
import {
|
|
120
|
-
asOptionalTrimmedString
|
|
121
|
-
} from "./chunk-G3SUCT4W.js";
|
|
122
|
-
|
|
123
|
-
// packages/agent-runtime/actionGate.ts
|
|
124
|
-
function readCommandActionGatePayload(payload) {
|
|
125
|
-
if (!isRecord(payload)) return null;
|
|
126
|
-
if (!Array.isArray(payload.command)) return null;
|
|
127
|
-
const command = payload.command.flatMap((item) => {
|
|
128
|
-
const value = asOptionalTrimmedString(item);
|
|
129
|
-
return value ? [value] : [];
|
|
130
|
-
});
|
|
131
|
-
if (command.length === 0) return null;
|
|
132
|
-
const displayCommand = asOptionalTrimmedString(payload.displayCommand);
|
|
133
|
-
return {
|
|
134
|
-
command,
|
|
135
|
-
...displayCommand ? { displayCommand } : {}
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
function readActionGate(value) {
|
|
139
|
-
if (!isRecord(value)) return null;
|
|
140
|
-
if (typeof value.id !== "string" || !value.id.trim()) return null;
|
|
141
|
-
if (value.kind !== "confirm" && value.kind !== "handoff" && value.kind !== "input") return null;
|
|
142
|
-
if (typeof value.title !== "string" || !value.title.trim()) return null;
|
|
143
|
-
const titleParams = readTitleParams(value.titleParams);
|
|
144
|
-
return {
|
|
145
|
-
id: value.id.trim(),
|
|
146
|
-
kind: value.kind,
|
|
147
|
-
title: value.title.trim(),
|
|
148
|
-
...titleParams ? { titleParams } : {},
|
|
149
|
-
...asOptionalTrimmedString(value.body) ? { body: asOptionalTrimmedString(value.body) } : {},
|
|
150
|
-
...Object.prototype.hasOwnProperty.call(value, "payload") ? { payload: value.payload } : {}
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
function readTitleParams(value) {
|
|
154
|
-
if (!isRecord(value)) return void 0;
|
|
155
|
-
const entries = Object.entries(value).flatMap(([key, raw]) => {
|
|
156
|
-
if (typeof raw === "string" || typeof raw === "number") {
|
|
157
|
-
return [[key, raw]];
|
|
158
|
-
}
|
|
159
|
-
return [];
|
|
160
|
-
});
|
|
161
|
-
if (entries.length === 0) return void 0;
|
|
162
|
-
return Object.fromEntries(entries);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// packages/ai/agent/getFullChatContextKeys.ts
|
|
166
|
-
var difference = (arrA, arrB) => {
|
|
167
|
-
if (!arrA.length) return [];
|
|
168
|
-
if (!arrB.length) return [...arrA];
|
|
169
|
-
const exclude = new Set(arrB);
|
|
170
|
-
return arrA.filter((item) => !exclude.has(item));
|
|
171
|
-
};
|
|
172
|
-
var getFullChatContextKeys = async (state, dispatch, agentConfig, userInput, dialogConfig) => {
|
|
173
|
-
const msgs = selectAllMsgs(
|
|
174
|
-
state,
|
|
175
|
-
dialogConfig?.dbKey ? extractCustomId(dialogConfig.dbKey) : dialogConfig?.id
|
|
176
|
-
);
|
|
177
|
-
const botInstructionKeys = /* @__PURE__ */ new Set();
|
|
178
|
-
const botKnowledgeKeys = /* @__PURE__ */ new Set();
|
|
179
|
-
if (Array.isArray(agentConfig.references)) {
|
|
180
|
-
for (const ref of agentConfig.references) {
|
|
181
|
-
if (!ref?.dbKey) continue;
|
|
182
|
-
if (ref.type === "instruction") {
|
|
183
|
-
botInstructionKeys.add(ref.dbKey);
|
|
184
|
-
} else {
|
|
185
|
-
botKnowledgeKeys.add(ref.dbKey);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
const currentInputKeys = /* @__PURE__ */ new Set();
|
|
190
|
-
if (Array.isArray(userInput)) {
|
|
191
|
-
for (const part of userInput) {
|
|
192
|
-
if (part?.pageKey) currentInputKeys.add(part.pageKey);
|
|
193
|
-
if (part?.dialogKey) currentInputKeys.add(part.dialogKey);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
const historyKeys = /* @__PURE__ */ new Set();
|
|
197
|
-
const savedKeys = dialogConfig?.referenceKeys;
|
|
198
|
-
if (Array.isArray(savedKeys)) {
|
|
199
|
-
savedKeys.forEach((k) => historyKeys.add(k));
|
|
200
|
-
}
|
|
201
|
-
const scanContentParts = (msg) => {
|
|
202
|
-
if (!msg) return;
|
|
203
|
-
for (const key of extractReferenceKeysFromMessage(msg)) {
|
|
204
|
-
historyKeys.add(key);
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
if (msgs && msgs.length > 0) {
|
|
208
|
-
const summarizedBeforeId = dialogConfig?.summarizedBeforeId;
|
|
209
|
-
if (!summarizedBeforeId) {
|
|
210
|
-
for (const msg of msgs) scanContentParts(msg);
|
|
211
|
-
} else {
|
|
212
|
-
let foundMarker = false;
|
|
213
|
-
let startScan = false;
|
|
214
|
-
for (const msg of msgs) {
|
|
215
|
-
if (!startScan) {
|
|
216
|
-
if (msg.id === summarizedBeforeId) {
|
|
217
|
-
foundMarker = true;
|
|
218
|
-
startScan = true;
|
|
219
|
-
}
|
|
220
|
-
continue;
|
|
221
|
-
}
|
|
222
|
-
scanContentParts(msg);
|
|
223
|
-
}
|
|
224
|
-
if (!foundMarker) {
|
|
225
|
-
console.warn(`[getFullChatContextKeys] marker ${summarizedBeforeId} not found, scanning all`);
|
|
226
|
-
for (const msg of msgs) scanContentParts(msg);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return {
|
|
231
|
-
botInstructionKeys,
|
|
232
|
-
currentInputKeys,
|
|
233
|
-
historyKeys,
|
|
234
|
-
botKnowledgeKeys
|
|
235
|
-
};
|
|
236
|
-
};
|
|
237
|
-
var deduplicateContextKeys = (keys) => {
|
|
238
|
-
const {
|
|
239
|
-
botInstructionKeys,
|
|
240
|
-
currentInputKeys,
|
|
241
|
-
historyKeys,
|
|
242
|
-
botKnowledgeKeys
|
|
243
|
-
} = keys;
|
|
244
|
-
const finalBotInstructionKeys = Array.from(botInstructionKeys);
|
|
245
|
-
const finalCurrentInputKeys = difference(
|
|
246
|
-
Array.from(currentInputKeys),
|
|
247
|
-
finalBotInstructionKeys
|
|
248
|
-
);
|
|
249
|
-
const finalHistoryKeys = difference(Array.from(historyKeys), [
|
|
250
|
-
...finalBotInstructionKeys,
|
|
251
|
-
...finalCurrentInputKeys
|
|
252
|
-
]);
|
|
253
|
-
const finalBotKnowledgeKeys = difference(Array.from(botKnowledgeKeys), [
|
|
254
|
-
...finalBotInstructionKeys,
|
|
255
|
-
...finalCurrentInputKeys,
|
|
256
|
-
...finalHistoryKeys
|
|
257
|
-
]);
|
|
258
|
-
return {
|
|
259
|
-
botInstructionsContext: finalBotInstructionKeys,
|
|
260
|
-
currentInputContext: finalCurrentInputKeys,
|
|
261
|
-
historyContext: finalHistoryKeys,
|
|
262
|
-
botKnowledgeContext: finalBotKnowledgeKeys
|
|
263
|
-
};
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
// packages/ai/agent/toolOutputPolicy.ts
|
|
267
|
-
var MAX_HISTORICAL_TOOL_CONTENT_CHARS = 1600;
|
|
268
|
-
var MAX_IN_TURN_TOOL_CONTENT_CHARS = 4e3;
|
|
269
|
-
var FRESH_TOOL_OUTPUT_MAX_CHARS = 32e3;
|
|
270
|
-
var DEFAULT_TOOL_OUTPUT_PROFILE = {
|
|
271
|
-
maxChars: MAX_IN_TURN_TOOL_CONTENT_CHARS,
|
|
272
|
-
headRatio: 0.5
|
|
273
|
-
};
|
|
274
|
-
var TOOL_OUTPUT_PROFILES = {
|
|
275
|
-
readFile: { maxChars: 4800, headRatio: 0.68, historicalMaxChars: 4800 },
|
|
276
|
-
read_file: { maxChars: 4800, headRatio: 0.68, historicalMaxChars: 4800 },
|
|
277
|
-
readWorkspaceFile: { maxChars: 4800, headRatio: 0.68, historicalMaxChars: 4800 },
|
|
278
|
-
searchFiles: { maxChars: 3600, headRatio: 0.78 },
|
|
279
|
-
search_files: { maxChars: 3600, headRatio: 0.78 },
|
|
280
|
-
listFiles: { maxChars: 2800, headRatio: 0.85 },
|
|
281
|
-
globFiles: { maxChars: 2800, headRatio: 0.85 },
|
|
282
|
-
execShell: { maxChars: 4e3, headRatio: 0.35 },
|
|
283
|
-
runCommand: { maxChars: 4e3, headRatio: 0.35 },
|
|
284
|
-
launchProcess: { maxChars: 2800, headRatio: 0.35 },
|
|
285
|
-
editFile: { maxChars: 2800, headRatio: 0.62 },
|
|
286
|
-
writeFile: { maxChars: 2400, headRatio: 0.62 },
|
|
287
|
-
readPastedText: { maxChars: 4800, headRatio: 0.5, historicalMaxChars: 4800 }
|
|
288
|
-
};
|
|
289
|
-
function resolveToolOutputProfile(toolName) {
|
|
290
|
-
return (toolName ? TOOL_OUTPUT_PROFILES[toolName] : void 0) ?? DEFAULT_TOOL_OUTPUT_PROFILE;
|
|
291
|
-
}
|
|
292
|
-
function resolveHistoricalToolContentCap(toolName, historicalMaxChars) {
|
|
293
|
-
const profile = toolName ? TOOL_OUTPUT_PROFILES[toolName] : void 0;
|
|
294
|
-
return profile?.historicalMaxChars !== void 0 ? Math.max(historicalMaxChars, profile.historicalMaxChars) : historicalMaxChars;
|
|
295
|
-
}
|
|
296
|
-
function projectToolMessageContent(input) {
|
|
297
|
-
const { content, isFresh, toolName, historicalMaxChars } = input;
|
|
298
|
-
if (isFresh) {
|
|
299
|
-
if (content.length <= FRESH_TOOL_OUTPUT_MAX_CHARS) return content;
|
|
300
|
-
return clipToolText(
|
|
301
|
-
content,
|
|
302
|
-
FRESH_TOOL_OUTPUT_MAX_CHARS,
|
|
303
|
-
resolveToolOutputProfile(toolName).headRatio,
|
|
304
|
-
`
|
|
305
|
-
\u2026[\u622A\u65AD\uFF0C\u539F\u59CB\u957F\u5EA6 ${content.length} \u5B57\u7B26]`
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
const cap = resolveHistoricalToolContentCap(toolName, historicalMaxChars);
|
|
309
|
-
if (content.length <= cap) return content;
|
|
310
|
-
return content.slice(0, cap) + `
|
|
311
|
-
\u2026[\u622A\u65AD\uFF0C\u539F\u59CB\u957F\u5EA6 ${content.length} \u5B57\u7B26]`;
|
|
312
|
-
}
|
|
313
|
-
function clipToolText(content, maxChars, headRatio, marker = "\n\n[... tool output middle omitted; head/tail preserved ...]\n\n") {
|
|
314
|
-
const normalized = content.replace(/\r\n/g, "\n").trim();
|
|
315
|
-
if (normalized.length <= maxChars) return normalized;
|
|
316
|
-
if (maxChars <= marker.length + 2) return normalized.slice(0, maxChars);
|
|
317
|
-
const available = maxChars - marker.length;
|
|
318
|
-
const headChars = Math.max(1, Math.floor(available * headRatio));
|
|
319
|
-
const tailChars = Math.max(1, available - headChars);
|
|
320
|
-
return `${normalized.slice(0, headChars)}${marker}${normalized.slice(-tailChars)}`;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// packages/ai/policy/runtimePolicy.ts
|
|
324
|
-
var clampLevel = (value, fallback) => {
|
|
325
|
-
const n = Number(value);
|
|
326
|
-
if (n === 1 || n === 2 || n === 3 || n === 4) {
|
|
327
|
-
return n;
|
|
328
|
-
}
|
|
329
|
-
return fallback;
|
|
330
|
-
};
|
|
331
|
-
var normalizeTonePreset = (value, fallback) => {
|
|
332
|
-
switch (value) {
|
|
333
|
-
case "professional":
|
|
334
|
-
case "friendly":
|
|
335
|
-
case "direct":
|
|
336
|
-
case "pragmatic":
|
|
337
|
-
case "default":
|
|
338
|
-
return value;
|
|
339
|
-
default:
|
|
340
|
-
return fallback;
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
var normalizeToneResolutionMode = (value, fallback) => {
|
|
344
|
-
switch (value) {
|
|
345
|
-
case "agent_first":
|
|
346
|
-
case "user_first":
|
|
347
|
-
case "blend":
|
|
348
|
-
return value;
|
|
349
|
-
default:
|
|
350
|
-
return fallback;
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
var normalizeSelfEvolutionMode = (value, fallback) => {
|
|
354
|
-
switch (value) {
|
|
355
|
-
case "none":
|
|
356
|
-
case "knowledge_only":
|
|
357
|
-
case "prompt_and_refs":
|
|
358
|
-
case "full":
|
|
359
|
-
return value;
|
|
360
|
-
default:
|
|
361
|
-
return fallback;
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
var resolveAgentBasePolicy = (agentConfig) => {
|
|
365
|
-
const raw = agentConfig?.basePolicy ?? {};
|
|
366
|
-
return {
|
|
367
|
-
version: 1,
|
|
368
|
-
tone: {
|
|
369
|
-
preset: normalizeTonePreset(
|
|
370
|
-
raw?.tone?.preset,
|
|
371
|
-
DEFAULT_AGENT_BASE_POLICY.tone?.preset ?? "default"
|
|
372
|
-
),
|
|
373
|
-
resolutionMode: normalizeToneResolutionMode(
|
|
374
|
-
raw?.tone?.resolutionMode,
|
|
375
|
-
DEFAULT_AGENT_BASE_POLICY.tone?.resolutionMode ?? "blend"
|
|
376
|
-
)
|
|
377
|
-
},
|
|
378
|
-
knowledgeCaptureMaxLevel: clampLevel(
|
|
379
|
-
raw?.knowledgeCaptureMaxLevel,
|
|
380
|
-
DEFAULT_AGENT_BASE_POLICY.knowledgeCaptureMaxLevel
|
|
381
|
-
),
|
|
382
|
-
spaceContextMaxLevel: clampLevel(
|
|
383
|
-
raw?.spaceContextMaxLevel,
|
|
384
|
-
DEFAULT_AGENT_BASE_POLICY.spaceContextMaxLevel
|
|
385
|
-
),
|
|
386
|
-
selfEvolutionMode: normalizeSelfEvolutionMode(
|
|
387
|
-
raw?.selfEvolutionMode,
|
|
388
|
-
DEFAULT_AGENT_BASE_POLICY.selfEvolutionMode
|
|
389
|
-
)
|
|
390
|
-
};
|
|
391
|
-
};
|
|
392
|
-
var resolveUserPreferenceProfile = (settingsRecord) => {
|
|
393
|
-
const fallbackSpaceLevel = settingsRecord?.enableReadCurrentSpace === false ? 1 : DEFAULT_USER_PREFERENCE_PROFILE.spaceContextLevel;
|
|
394
|
-
return {
|
|
395
|
-
version: 1,
|
|
396
|
-
tone: {
|
|
397
|
-
preset: normalizeTonePreset(
|
|
398
|
-
settingsRecord?.userTonePreset,
|
|
399
|
-
DEFAULT_USER_PREFERENCE_PROFILE.tone?.preset ?? "default"
|
|
400
|
-
)
|
|
401
|
-
},
|
|
402
|
-
knowledgeCaptureLevel: clampLevel(
|
|
403
|
-
settingsRecord?.knowledgeCaptureLevel,
|
|
404
|
-
DEFAULT_USER_PREFERENCE_PROFILE.knowledgeCaptureLevel
|
|
405
|
-
),
|
|
406
|
-
spaceContextLevel: clampLevel(
|
|
407
|
-
settingsRecord?.spaceContextLevel,
|
|
408
|
-
fallbackSpaceLevel
|
|
409
|
-
)
|
|
410
|
-
};
|
|
411
|
-
};
|
|
412
|
-
var containsAny = (text, patterns) => patterns.some((pattern) => text.includes(pattern));
|
|
413
|
-
var inferCaptureIntent = (userInput) => {
|
|
414
|
-
const normalized = userInput.toLowerCase();
|
|
415
|
-
if (containsAny(normalized, [
|
|
416
|
-
"\u4FDD\u5B58",
|
|
417
|
-
"\u5B58\u4E00\u4E0B",
|
|
418
|
-
"\u6C89\u6DC0",
|
|
419
|
-
"\u8BB0\u4F4F",
|
|
420
|
-
"\u5199\u5165\u6587\u6863",
|
|
421
|
-
"\u5EFA\u6587\u6863",
|
|
422
|
-
"\u521B\u5EFA\u6587\u6863",
|
|
423
|
-
"\u5BFC\u5165 skill",
|
|
424
|
-
"\u5BFC\u5165\u8FD9\u4E2A skill",
|
|
425
|
-
"\u786E\u8BA4\u5BFC\u5165",
|
|
426
|
-
"\u786E\u8BA4\u5BFC\u5165\u8FD9\u4E2A skill",
|
|
427
|
-
"\u5BFC\u5165\u8FD9\u4E2A\u6280\u80FD",
|
|
428
|
-
"\u786E\u8BA4\u5BFC\u5165\u8FD9\u4E2A\u6280\u80FD",
|
|
429
|
-
"\u521B\u5EFA skill",
|
|
430
|
-
"\u521B\u5EFA\u8FD9\u4E2A skill",
|
|
431
|
-
"skill \u6587\u6863",
|
|
432
|
-
"\u521B\u5EFA\u8868\u683C",
|
|
433
|
-
"createtable",
|
|
434
|
-
"addtablerow",
|
|
435
|
-
"addtablerows",
|
|
436
|
-
"\u5EFA\u8868",
|
|
437
|
-
"\u5EFA\u4E2A\u8868",
|
|
438
|
-
"\u505A\u4E2A\u8868",
|
|
439
|
-
"\u505A\u4E00\u5F20\u8868",
|
|
440
|
-
"\u5199\u8868",
|
|
441
|
-
"\u5199\u5165\u8868",
|
|
442
|
-
"\u5199\u5165\u4E00\u884C",
|
|
443
|
-
"\u5199\u5165 table",
|
|
444
|
-
"\u653E\u5230 table",
|
|
445
|
-
"\u5B58\u5230 table",
|
|
446
|
-
"\u4FDD\u5B58\u5230 table",
|
|
447
|
-
"\u8BB0\u5F55\u4E0B\u6765",
|
|
448
|
-
"\u91C7\u96C6",
|
|
449
|
-
"\u505A\u6570\u636E\u96C6",
|
|
450
|
-
"\u505A\u6210\u6570\u636E\u96C6",
|
|
451
|
-
"\u6574\u7406\u6210\u6570\u636E\u96C6",
|
|
452
|
-
"\u6574\u7406\u6210\u8868",
|
|
453
|
-
"\u6574\u7406\u6210\u4E00\u5F20\u8868",
|
|
454
|
-
"\u5EFA\u7ACB\u4E00\u4E2A\u8868",
|
|
455
|
-
"\u5EFA\u7ACB\u4E00\u5F20\u8868",
|
|
456
|
-
"\u5EFA\u7ACB\u6210\u8868",
|
|
457
|
-
"\u5EFA\u7ACB\u6210\u4E00\u5F20\u8868",
|
|
458
|
-
"\u521B\u5EFA\u8FD9\u4E2A\u8868\u683C",
|
|
459
|
-
"\u786E\u8BA4\u521B\u5EFA",
|
|
460
|
-
"\u786E\u8BA4\u521B\u5EFA\u8FD9\u5F20\u8868\u683C",
|
|
461
|
-
"create doc",
|
|
462
|
-
"import skill",
|
|
463
|
-
"confirm import",
|
|
464
|
-
"create skill",
|
|
465
|
-
"create table",
|
|
466
|
-
"write table",
|
|
467
|
-
"save to table",
|
|
468
|
-
"dataset",
|
|
469
|
-
"save this",
|
|
470
|
-
"remember this",
|
|
471
|
-
"document this"
|
|
472
|
-
])) {
|
|
473
|
-
return "strong";
|
|
474
|
-
}
|
|
475
|
-
if (containsAny(normalized, [
|
|
476
|
-
"\u603B\u7ED3",
|
|
477
|
-
"\u65B9\u6848",
|
|
478
|
-
"\u8C03\u7814",
|
|
479
|
-
"\u89C4\u8303",
|
|
480
|
-
"\u4F1A\u8BAE\u7EAA\u8981",
|
|
481
|
-
"\u603B\u7ED3\u4E00\u4E0B",
|
|
482
|
-
"research",
|
|
483
|
-
"proposal",
|
|
484
|
-
"spec",
|
|
485
|
-
"summary"
|
|
486
|
-
])) {
|
|
487
|
-
return "possible";
|
|
488
|
-
}
|
|
489
|
-
return "none";
|
|
490
|
-
};
|
|
491
|
-
var resolveTonePreset = (agentTone, userTone, mode) => {
|
|
492
|
-
if (mode === "agent_first") {
|
|
493
|
-
return agentTone === "default" ? userTone : agentTone;
|
|
494
|
-
}
|
|
495
|
-
if (mode === "user_first") {
|
|
496
|
-
return userTone === "default" ? agentTone : userTone;
|
|
497
|
-
}
|
|
498
|
-
if (userTone !== "default") return userTone;
|
|
499
|
-
return agentTone;
|
|
500
|
-
};
|
|
501
|
-
var preloadSummaryCountByLevel = (level) => ({ 1: 0, 2: 0, 3: 8, 4: 16 })[level];
|
|
502
|
-
var preloadBudgetRatioByLevel = (level) => ({ 1: 0, 2: 0.01, 3: 0.04, 4: 0.08 })[level];
|
|
503
|
-
var knowledgeCaptureLevelLabel = (level) => ({
|
|
504
|
-
1: "\u4E0D\u4E3B\u52A8\u521B\u5EFA",
|
|
505
|
-
2: "\u5148\u95EE\u518D\u521B\u5EFA",
|
|
506
|
-
3: "\u56DE\u7B54\u540E\u5EFA\u8BAE\u521B\u5EFA",
|
|
507
|
-
4: "\u9AD8\u4EF7\u503C\u7ED3\u679C\u53EF\u81EA\u52A8\u521B\u5EFA"
|
|
508
|
-
})[level] ?? "\u672A\u77E5\u7EA7\u522B";
|
|
509
|
-
var spaceContextLevelLabel = (level) => ({
|
|
510
|
-
1: "\u4E0D\u81EA\u52A8\u8BFB\u53D6",
|
|
511
|
-
2: "\u53EA\u770B\u7ED3\u6784\u548C\u6807\u9898",
|
|
512
|
-
3: "\u8F7B\u91CF\u8BFB\u53D6",
|
|
513
|
-
4: "\u81EA\u9002\u5E94\u8BFB\u53D6"
|
|
514
|
-
})[level] ?? "\u672A\u77E5\u7EA7\u522B";
|
|
515
|
-
var buildStaticUserPolicyContext = (params) => {
|
|
516
|
-
const agentBasePolicy = resolveAgentBasePolicy(params.agentConfig);
|
|
517
|
-
const userPreferenceProfile = resolveUserPreferenceProfile(params.settingsRecord);
|
|
518
|
-
const tonePreset = resolveTonePreset(
|
|
519
|
-
agentBasePolicy.tone?.preset ?? "default",
|
|
520
|
-
userPreferenceProfile.tone?.preset ?? "default",
|
|
521
|
-
agentBasePolicy.tone?.resolutionMode ?? "blend"
|
|
522
|
-
);
|
|
523
|
-
const knowledgeLevel = Math.min(
|
|
524
|
-
agentBasePolicy.knowledgeCaptureMaxLevel,
|
|
525
|
-
userPreferenceProfile.knowledgeCaptureLevel
|
|
526
|
-
);
|
|
527
|
-
const spaceLevel = Math.min(
|
|
528
|
-
agentBasePolicy.spaceContextMaxLevel,
|
|
529
|
-
userPreferenceProfile.spaceContextLevel
|
|
530
|
-
);
|
|
531
|
-
return [
|
|
532
|
-
`\u7528\u6237\u8BED\u6C14\u504F\u597D\uFF1A${tonePreset}`,
|
|
533
|
-
`\u77E5\u8BC6\u6C89\u6DC0\u7EA7\u522B\uFF1A${knowledgeLevel}\uFF08${knowledgeCaptureLevelLabel(knowledgeLevel)}\uFF09`,
|
|
534
|
-
`\u7A7A\u95F4\u4E0A\u4E0B\u6587\u7EA7\u522B\uFF1A${spaceLevel}\uFF08${spaceContextLevelLabel(spaceLevel)}\uFF09`,
|
|
535
|
-
"\u8BF7\u5C3D\u91CF\u4FDD\u7559 agent \u81EA\u8EAB\u89D2\u8272\u8BBE\u5B9A\uFF0C\u540C\u65F6\u6309\u7528\u6237\u504F\u597D\u8C03\u6574\u8868\u8FBE\u548C\u81EA\u52A8\u5316\u7A0B\u5EA6\u3002"
|
|
536
|
-
].join("\n");
|
|
537
|
-
};
|
|
538
|
-
var resolveSpaceContextPreloadPlan = (level) => ({
|
|
539
|
-
preloadSummaryCount: preloadSummaryCountByLevel(level),
|
|
540
|
-
preloadBudgetRatio: preloadBudgetRatioByLevel(level),
|
|
541
|
-
includeRecentContent: level >= 3
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
// packages/ai/agent/canvasEditingContext.ts
|
|
545
|
-
function buildCanvasNodeEditingContextSummary(runtimeOptions) {
|
|
546
|
-
if (runtimeOptions?.editingTarget?.kind !== "canvas_node") return null;
|
|
547
|
-
const editingTarget = runtimeOptions.editingTarget;
|
|
548
|
-
const metadata = editingTarget.metadata ?? {};
|
|
549
|
-
const selectedNodeId = typeof metadata.selectedNodeId === "string" ? metadata.selectedNodeId : editingTarget.key ?? "(\u672A\u77E5\u8282\u70B9)";
|
|
550
|
-
const part = typeof metadata.part === "string" ? metadata.part : editingTarget.title ?? selectedNodeId;
|
|
551
|
-
const nodeType = typeof metadata.type === "string" ? metadata.type : "(\u672A\u77E5\u7C7B\u578B)";
|
|
552
|
-
const path = Array.isArray(metadata.path) ? metadata.path.filter((item) => typeof item === "string") : [];
|
|
553
|
-
const props = asRecordOrEmpty(metadata.props);
|
|
554
|
-
const style = asRecordOrEmpty(metadata.style);
|
|
555
|
-
return [
|
|
556
|
-
"\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1ACanvas Tree \u4E2D\u7684\u4E00\u4E2A\u9009\u4E2D\u8282\u70B9\u3002",
|
|
557
|
-
`- \u8282\u70B9 ID: ${selectedNodeId}`,
|
|
558
|
-
`- part: ${part}`,
|
|
559
|
-
`- \u8282\u70B9\u7C7B\u578B: ${nodeType}`,
|
|
560
|
-
...path.length ? [`- \u8282\u70B9\u8DEF\u5F84: ${path.join(" > ")}`] : [],
|
|
561
|
-
"",
|
|
562
|
-
"\u5F53\u524D\u8282\u70B9 props:",
|
|
563
|
-
JSON.stringify(props, null, 2),
|
|
564
|
-
"",
|
|
565
|
-
"\u5F53\u524D\u8282\u70B9 style:",
|
|
566
|
-
JSON.stringify(style, null, 2),
|
|
567
|
-
"",
|
|
568
|
-
"\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
|
|
569
|
-
`1. \u5982\u679C\u7528\u6237\u8981\u6C42\u4FEE\u6539\u5F53\u524D\u6A21\u5757\uFF0C\u53EA\u8F93\u51FA updateNode\uFF0C\u76EE\u6807 id \u5FC5\u987B\u662F ${selectedNodeId}\u3002`,
|
|
570
|
-
"2. \u4E0D\u8981\u91CD\u5EFA root/shell\uFF0C\u4E0D\u8981\u91CD\u65B0 append \u5DF2\u5B58\u5728\u7684\u5927\u5757\u5185\u5BB9\u3002",
|
|
571
|
-
"3. \u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u65B0\u589E\u5B50\u6A21\u5757\uFF0C\u5426\u5219\u4E0D\u8981 appendNode\u3002",
|
|
572
|
-
"4. \u56DE\u590D\u4ECD\u5FC5\u987B\u9075\u5B88 Canvas Tree MVP \u534F\u8BAE\uFF1A\u53EA\u8F93\u51FA canvas_snapshot NDJSON\uFF0C\u4E0D\u8981\u8F93\u51FA\u89E3\u91CA\u6216\u6E90\u7801\u3002"
|
|
573
|
-
].join("\n");
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// packages/ai/agent/buildEditingContext.ts
|
|
577
|
-
var buildAppConstraintPacks = (args) => {
|
|
578
|
-
const imports = new Set(args.externalImports);
|
|
579
|
-
const fileSet = new Set(args.fileNames);
|
|
580
|
-
const packs = [
|
|
581
|
-
{
|
|
582
|
-
id: "repair-loop",
|
|
583
|
-
title: "\u9884\u68C0\u4E0E\u5B9A\u70B9\u4FEE\u590D",
|
|
584
|
-
rules: [
|
|
585
|
-
"\u6BCF\u6B21\u6539\u5B8C\u4EE3\u7801\u540E\uFF0C\u5148\u8C03\u7528 appPreflight\uFF0C\u53EA\u6709\u9884\u68C0\u901A\u8FC7\u540E\u518D\u8C03\u7528 appDeploy\u3002",
|
|
586
|
-
"\u5982\u679C preflight / deploy \u5931\u8D25\uFF0C\u4F18\u5148\u6839\u636E\u8FD4\u56DE\u7684 issues \u505A\u5B9A\u70B9\u4FEE\u590D\uFF0C\u7136\u540E\u91CD\u65B0 preflight\uFF1B\u4E0D\u8981\u65E0\u5173\u91CD\u5199\u6574\u9875\u5E94\u7528\u3002",
|
|
587
|
-
"\u5982\u679C\u5DE5\u5177\u7ED3\u679C\u91CC\u5E26\u6709 repairPlan\uFF0C\u9ED8\u8BA4\u7ACB\u5373\u6267\u884C repairPlan \u4E2D\u7684\u5C40\u90E8\u4FEE\u590D\u6B65\u9AA4\uFF0C\u4E0D\u8981\u5148\u505C\u4E0B\u6765\u95EE\u7528\u6237\u3002",
|
|
588
|
-
"\u5982\u679C\u5DE5\u5177\u7ED3\u679C\u660E\u786E\u8BF4\u660E\u662F HTML / \u975E JSON \u54CD\u5E94\u3001transport failure \u6216 retryable=false\uFF0C\u505C\u6B62\u81EA\u52A8 deploy \u91CD\u8BD5\uFF1B\u8FD9\u8BF4\u660E\u5F53\u524D\u662F\u5E73\u53F0\u901A\u9053\u5F02\u5E38\uFF0C\u4E0D\u662F\u4EE3\u7801\u95EE\u9898\u3002"
|
|
589
|
-
]
|
|
590
|
-
},
|
|
591
|
-
{
|
|
592
|
-
id: "design-system",
|
|
593
|
-
title: "\u8BBE\u8BA1\u7CFB\u7EDF\u4E0E\u5C0F\u6539\u52A8\u7EA6\u675F",
|
|
594
|
-
rules: [
|
|
595
|
-
"\u5148\u68C0\u67E5\u5F53\u524D\u5E94\u7528\u662F\u5426\u5DF2\u7ECF\u6709 theme / tokens / designSystem / \u5171\u4EAB\u6837\u5F0F\u5E38\u91CF\uFF1B\u5982\u679C\u5DF2\u6709\uFF0C\u4F18\u5148\u6CBF\u7528\u8FD9\u5957\u8BBE\u8BA1\u7CFB\u7EDF\uFF0C\u4E0D\u8981\u5E73\u884C\u518D\u9020\u4E00\u5957\u3002",
|
|
596
|
-
"\u5982\u679C\u5F53\u524D\u5E94\u7528\u8FD8\u6CA1\u6709\u8BBE\u8BA1\u7CFB\u7EDF\uFF0C\u800C\u7528\u6237\u9700\u6C42\u6D89\u53CA UI / \u6837\u5F0F / \u65B0\u9875\u9762\uFF0C\u4F18\u5148\u8865\u4E00\u5C42\u6700\u5C0F\u5171\u4EAB token\uFF08colors\u3001typography\u3001spacing\u3001radius\u3001shadow\uFF09\uFF0C\u518D\u8BA9\u7EC4\u4EF6\u6D88\u8D39\u8FD9\u4E9B token\u3002",
|
|
597
|
-
"\u5982\u679C\u5F53\u524D\u5E94\u7528\u662F\u65E7\u5199\u6CD5\uFF1A\u89C6\u89C9\u503C\u6563\u843D\u5728\u591A\u4E2A\u7EC4\u4EF6\u7684\u786C\u7F16\u7801 style / \u5E38\u91CF\u91CC\uFF0C\u800C\u672C\u6B21\u9700\u6C42\u53EA\u662F\u8C03\u5B57\u4F53\u3001\u989C\u8272\u3001\u95F4\u8DDD\u3001\u5706\u89D2\u3001\u9634\u5F71\uFF0C\u9ED8\u8BA4\u6267\u884C\u4E00\u6B21\u6700\u5C0F token \u8FC1\u79FB\uFF0C\u518D\u5728 token \u5C42\u5B8C\u6210\u8C03\u6574\uFF1B\u4E0D\u8981\u7EE7\u7EED\u628A\u65B0\u6570\u5B57\u6563\u843D\u5199\u56DE\u591A\u4E2A\u4F4D\u7F6E\u3002",
|
|
598
|
-
"\u5F53\u7528\u6237\u53EA\u662F\u60F3\u8C03\u5B57\u4F53\u5927\u5C0F\u3001\u5B57\u91CD\u3001\u989C\u8272\u3001\u5706\u89D2\u3001\u9634\u5F71\u3001\u95F4\u8DDD\u7B49\u89C6\u89C9\u53C2\u6570\u65F6\uFF0C\u4F18\u5148\u4FEE\u6539 token \u6216\u547D\u4E2D\u7684\u5C40\u90E8\u7EC4\u4EF6\uFF0C\u4E0D\u8981\u987A\u624B\u91CD\u5199\u6574\u4E2A\u9875\u9762\u7ED3\u6784\u3002",
|
|
599
|
-
"\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u6574\u4F53\u6539\u7248\u6216\u91CD\u505A\u98CE\u683C\uFF0C\u5426\u5219\u4E0D\u8981\u8FDE\u5E26\u4FEE\u6539\u5E03\u5C40\u3001\u7EC4\u4EF6\u6811\u3001\u6587\u6848\u3001\u6570\u636E\u6D41\u3001\u8DEF\u7531\u6216\u672A\u547D\u4E2D\u7684\u9875\u9762\u3002",
|
|
600
|
-
"\u5982\u679C\u53EA\u662F\u5C0F\u6539\u4E00\u5904\uFF0C\u5C3D\u91CF\u628A\u53D8\u66F4\u6536\u655B\u5728\u5C11\u6570\u6587\u4EF6\uFF0C\u5E76\u4FDD\u6301\u672A\u547D\u4E2D\u6587\u4EF6\u7684\u7ED3\u6784\u4E0E\u547D\u540D\u7A33\u5B9A\u3002"
|
|
601
|
-
]
|
|
602
|
-
}
|
|
603
|
-
];
|
|
604
|
-
if (args.framework === "react-spa" || fileSet.has("main.tsx") || fileSet.has("App.tsx")) {
|
|
605
|
-
packs.push({
|
|
606
|
-
id: "react-spa-core",
|
|
607
|
-
title: "React SPA \u5F62\u6001\u4FDD\u6301",
|
|
608
|
-
rules: [
|
|
609
|
-
'\u7EE7\u7EED\u6CBF\u7528 framework: "react-spa" + files\uFF0C\u4E0D\u8981\u9000\u56DE\u5355\u6587\u4EF6 Worker\u3002',
|
|
610
|
-
"\u4FDD\u7559\u7A33\u5B9A\u5165\u53E3\u7ED3\u6784\uFF0C\u4F18\u5148\u7EF4\u62A4 main.tsx + App.tsx\uFF0C\u518D\u5C40\u90E8\u4FEE\u6539\u7EC4\u4EF6\u6587\u4EF6\u3002"
|
|
611
|
-
]
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
|
-
if (imports.has("react-icons/lu")) {
|
|
615
|
-
packs.push({
|
|
616
|
-
id: "react-icons-lu",
|
|
617
|
-
title: "Lucide \u56FE\u6807\u5B89\u5168\u89C4\u5219",
|
|
618
|
-
rules: [
|
|
619
|
-
"\u53EA\u80FD\u4F7F\u7528 react-icons/lu \u4E2D\u771F\u5B9E\u5B58\u5728\u7684\u56FE\u6807\u540D\uFF0C\u4E0D\u8981\u731C\u6D4B\u53D8\u4F53\u540D\u3002",
|
|
620
|
-
"\u5982\u679C\u4E0D\u786E\u5B9A\u56FE\u6807\u540D\uFF0C\u4F18\u5148\u4F7F\u7528 LuCircle\u3001LuCheck\u3001LuX\u3001LuInfo\u3001LuArrowRight \u8FD9\u7C7B\u57FA\u7840\u56FE\u6807\u3002"
|
|
621
|
-
]
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
if (imports.has("leaflet") || imports.has("react-leaflet")) {
|
|
625
|
-
packs.push({
|
|
626
|
-
id: "leaflet",
|
|
627
|
-
title: "Leaflet \u5730\u56FE\u7EA6\u675F",
|
|
628
|
-
rules: [
|
|
629
|
-
"\u4E0D\u8981\u624B\u52A8 import leaflet.css\uFF1B\u5E73\u53F0\u4F1A\u81EA\u52A8\u6CE8\u5165 Leaflet \u6837\u5F0F\u3002",
|
|
630
|
-
"\u4FEE\u6539\u5730\u56FE\u65F6\u4F18\u5148\u4FDD\u7559\u73B0\u6709\u5750\u6807\u3001\u7F29\u653E\u548C\u56FE\u5C42\u7ED3\u6784\uFF0C\u53EA\u505A\u5FC5\u8981\u7684\u4EA4\u4E92\u6216\u89C6\u89C9\u8C03\u6574\u3002"
|
|
631
|
-
]
|
|
632
|
-
});
|
|
633
|
-
}
|
|
634
|
-
if (imports.has("@xyflow/react")) {
|
|
635
|
-
packs.push({
|
|
636
|
-
id: "xyflow",
|
|
637
|
-
title: "Flow \u56FE\u7F16\u8F91\u7EA6\u675F",
|
|
638
|
-
rules: [
|
|
639
|
-
"\u4E0D\u8981\u65B0\u589E\u5916\u90E8 CSS import\uFF1B\u9700\u8981\u6837\u5F0F\u65F6\u76F4\u63A5\u8865\u6700\u5C0F\u5FC5\u8981\u5185\u8054\u6837\u5F0F\u6216\u7EC4\u4EF6\u5185 style \u6807\u7B7E\u3002",
|
|
640
|
-
"\u4F18\u5148\u590D\u7528\u73B0\u6709\u8282\u70B9/\u8FB9\u6570\u636E\u7ED3\u6784\uFF0C\u907F\u514D\u91CD\u5199\u6574\u5957 flow \u753B\u5E03\u3002"
|
|
641
|
-
]
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
if (imports.has("echarts") || imports.has("echarts-for-react")) {
|
|
645
|
-
packs.push({
|
|
646
|
-
id: "echarts",
|
|
647
|
-
title: "\u56FE\u8868\u6539\u52A8\u7EA6\u675F",
|
|
648
|
-
rules: [
|
|
649
|
-
"\u4F18\u5148\u5C40\u90E8\u4FEE\u6539 option \u914D\u7F6E\u3001\u6570\u636E\u6620\u5C04\u548C\u7EC4\u4EF6 props\uFF0C\u4E0D\u8981\u91CD\u5199\u6574\u4E2A\u56FE\u8868\u9875\u9762\u3002",
|
|
650
|
-
"\u54CD\u5E94\u5F0F\u5E03\u5C40\u4F18\u5148\u9760\u5BB9\u5668\u5C3A\u5BF8\u548C\u73B0\u6709\u7EC4\u4EF6\u7ED3\u6784\u8C03\u6574\uFF0C\u4E0D\u8981\u989D\u5916\u5F15\u5165 CSS \u6587\u4EF6\u3002"
|
|
651
|
-
]
|
|
652
|
-
});
|
|
653
|
-
}
|
|
654
|
-
if (imports.has("docx") || imports.has("xlsx")) {
|
|
655
|
-
packs.push({
|
|
656
|
-
id: "file-processing",
|
|
657
|
-
title: "\u6587\u6863/\u8868\u683C\u5904\u7406\u7EA6\u675F",
|
|
658
|
-
rules: [
|
|
659
|
-
"\u4E0D\u8981\u628A\u5927\u578B\u6570\u636E\u6216\u6A21\u677F\u5185\u5BB9\u76F4\u63A5\u5185\u5D4C\u8FDB\u4EE3\u7801\u5E38\u91CF\uFF1B\u4F18\u5148\u4FDD\u7559\u8FD0\u884C\u65F6\u52A0\u8F7D\u65B9\u5F0F\u3002",
|
|
660
|
-
"\u4FEE\u6539\u5BFC\u5165\u5BFC\u51FA\u903B\u8F91\u65F6\uFF0C\u4F18\u5148\u6CBF\u7528\u73B0\u6709\u6587\u4EF6\u5904\u7406\u94FE\u8DEF\u548C\u6570\u636E\u7ED3\u6784\u3002"
|
|
661
|
-
]
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
return packs;
|
|
665
|
-
};
|
|
666
|
-
var formatAppConstraintPacks = (packs) => {
|
|
667
|
-
if (packs.length === 0) return [];
|
|
668
|
-
return [
|
|
669
|
-
"",
|
|
670
|
-
"\u5F53\u524D\u6FC0\u6D3B\u7EA6\u675F\u5305\uFF08\u6309\u5F53\u524D\u5E94\u7528\u4F9D\u8D56/\u5F62\u6001\u52A8\u6001\u6CE8\u5165\uFF09\uFF1A",
|
|
671
|
-
...packs.flatMap((pack) => [
|
|
672
|
-
`- ${pack.title}\uFF08${pack.id}\uFF09`,
|
|
673
|
-
...pack.rules.map((rule) => ` - ${rule}`)
|
|
674
|
-
])
|
|
675
|
-
];
|
|
676
|
-
};
|
|
677
|
-
var buildEditingContextSummary = (state, runtimeOptions) => {
|
|
678
|
-
const targetKind = runtimeOptions?.editingTarget?.kind;
|
|
679
|
-
if (targetKind === "table") {
|
|
680
|
-
const table = selectCurrentTable(state);
|
|
681
|
-
const rows = selectTableRows(state);
|
|
682
|
-
const metadata = runtimeOptions?.editingTarget?.metadata;
|
|
683
|
-
const focusContext = metadata && typeof metadata === "object" ? metadata.focusContext : null;
|
|
684
|
-
if (!table) return null;
|
|
685
|
-
const columns = Array.isArray(table.columns) ? table.columns : [];
|
|
686
|
-
const columnSummaries = columns.length ? columns.map((c) => {
|
|
687
|
-
const displayName = c.label || c.name;
|
|
688
|
-
const type = c.type || "text";
|
|
689
|
-
const requiredFlag = c.required ? "\u5FC5\u586B" : "\u53EF\u9009";
|
|
690
|
-
const primaryFlag = c.isPrimary ? "\uFF0C\u4E3B\u5B57\u6BB5" : "";
|
|
691
|
-
const optionsStr = Array.isArray(c.options) && c.options.length ? `\uFF0C\u53EF\u9009\u503C\uFF1A${c.options.join(" | ")}` : "";
|
|
692
|
-
const descStr = c.description ? `\u3002\u8BF4\u660E\uFF1A${c.description}` : "";
|
|
693
|
-
return `- ${c.name}\uFF08\u663E\u793A\u540D\uFF1A${displayName}\uFF0C\u7C7B\u578B\uFF1A${type}\uFF0C${requiredFlag}${primaryFlag}${optionsStr}${descStr}\uFF09`;
|
|
694
|
-
}) : ["- (\u5F53\u524D\u8868\u5C1A\u672A\u5B9A\u4E49\u5B57\u6BB5)"];
|
|
695
|
-
const sampleRows = Array.isArray(rows) ? rows.slice(0, 20) : [];
|
|
696
|
-
const rowsPreview = sampleRows.length ? JSON.stringify(sampleRows, null, 2) : "(\u5F53\u524D\u8868\u6682\u65E0\u884C\u6570\u636E)";
|
|
697
|
-
const tableTitle = table.displayName ?? table.tableId ?? "(\u672A\u547D\u540D\u8868)";
|
|
698
|
-
const tableDesc = table.description ? `\u7528\u9014\u8BF4\u660E\uFF1A${table.description}` : "(\u6682\u65E0\u7528\u9014\u8BF4\u660E)";
|
|
699
|
-
const tableTagsLine = Array.isArray(table.tags) && table.tags.length ? `- \u5173\u952E\u8BCD\u6807\u7B7E: ${table.tags.join(", ")}` : null;
|
|
700
|
-
return [
|
|
701
|
-
"\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u4E00\u5F20\u6570\u636E\u8868\uFF08Editing Table\uFF09\u3002",
|
|
702
|
-
`- \u8868 ID: ${table.tableId}`,
|
|
703
|
-
`- \u663E\u793A\u540D\u79F0: ${tableTitle}`,
|
|
704
|
-
`- ${tableDesc}`,
|
|
705
|
-
...tableTagsLine ? [tableTagsLine] : [],
|
|
706
|
-
...focusContext && typeof focusContext === "object" && "columnName" in focusContext ? [
|
|
707
|
-
"",
|
|
708
|
-
"\u5F53\u524D\u7126\u70B9\uFF08Focus Context\uFF09\uFF1A",
|
|
709
|
-
`- \u5F53\u524D\u5355\u5143\u683C\u5217: ${String(focusContext.columnName ?? "(\u672A\u77E5\u5217)")}`,
|
|
710
|
-
...focusContext.rowTitle ? [`- \u5F53\u524D\u884C\u6807\u9898: ${String(focusContext.rowTitle)}`] : [],
|
|
711
|
-
...focusContext.rowIndex !== null && focusContext.rowIndex !== void 0 ? [`- \u5F53\u524D\u884C\u53F7: ${Number(focusContext.rowIndex) + 1}`] : [],
|
|
712
|
-
...focusContext.cellPreview ? [`- \u5F53\u524D\u5355\u5143\u683C\u5185\u5BB9\u9884\u89C8: ${String(focusContext.cellPreview)}`] : []
|
|
713
|
-
] : [],
|
|
714
|
-
"",
|
|
715
|
-
"\u5B57\u6BB5\u5B9A\u4E49\uFF08Field Schema\uFF09\uFF1A",
|
|
716
|
-
...columnSummaries,
|
|
717
|
-
"",
|
|
718
|
-
"\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
|
|
719
|
-
"\u5F53\u7528\u6237\u5E0C\u671B\u5728\u5F53\u524D\u8868\u4E2D\u201C\u65B0\u589E\u4E00\u884C / \u65B0\u589E\u8BB0\u5F55 / \u63D2\u5165\u4E00\u6761 / \u5E2E\u6211\u8BB0\u4E00\u6761 xxx\u201D\u65F6\uFF1A",
|
|
720
|
-
"1. \u5FC5\u987B\u8C03\u7528\u5DE5\u5177 addTableRow\uFF08\u800C\u4E0D\u662F\u53EA\u5728\u56DE\u7B54\u4E2D\u53E3\u5934\u63CF\u8FF0\u8981\u65B0\u589E\u7684\u6570\u636E\uFF09\u3002",
|
|
721
|
-
"2. \u8C03\u7528 addTableRow \u65F6\uFF1A",
|
|
722
|
-
" - \u4F7F\u7528\u53C2\u6570 values\uFF08\u4E00\u4E2A\u5BF9\u8C61\uFF09\uFF0C\u5176\u4E2D\u6BCF\u4E2A key \u5FC5\u987B\u662F\u4E0A\u9762\u5B57\u6BB5\u540D\u4E4B\u4E00\uFF08name\uFF0C\u800C\u4E0D\u662F label\uFF09\u3002",
|
|
723
|
-
' - \u4F8B\u5982\uFF1A{"values":{"title":"\u4FEE Bug #123","status":"todo","note":"\u9AD8\u4F18\u5148\u7EA7"}}\u3002',
|
|
724
|
-
" - \u5C3D\u91CF\u4ECE\u7528\u6237\u7684\u81EA\u7136\u8BED\u8A00\u4E2D\u63A8\u65AD\u5E76\u586B\u6EE1\u6240\u6709\u76F8\u5173\u5B57\u6BB5\uFF1B\u5BF9\u4E8E\u5FC5\u586B\u5B57\u6BB5\uFF08required=true\uFF09\u5C24\u5176\u8981\u6CE8\u610F\u3002",
|
|
725
|
-
' - \u7528\u6237\u6CA1\u6709\u63D0\u5230\u7684\u5B57\u6BB5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u7A7A\u5B57\u7B26\u4E32 "" \u6216 null \u4F5C\u4E3A\u5360\u4F4D\u3002',
|
|
726
|
-
" - \u7EDD\u4E0D\u8981\u4F20\u5165\u7A7A\u5BF9\u8C61 {} \u4F5C\u4E3A values\u3002",
|
|
727
|
-
"",
|
|
728
|
-
"\u4EE5\u4E0B\u662F\u90E8\u5206\u793A\u4F8B\u884C\uFF08\u6700\u591A 20 \u884C\uFF0C\u7528\u4E8E\u5E2E\u52A9\u4F60\u7406\u89E3\u5217\u542B\u4E49\uFF0C\u8BF7\u907F\u514D\u5728\u56DE\u7B54\u4E2D\u5B8C\u6574\u7C98\u8D34\u6574\u8868\uFF09\uFF1A",
|
|
729
|
-
rowsPreview
|
|
730
|
-
].join("\n");
|
|
731
|
-
}
|
|
732
|
-
if (targetKind === "page" || targetKind === "article") {
|
|
733
|
-
const page = getDocState();
|
|
734
|
-
const metadata = runtimeOptions?.editingTarget?.metadata;
|
|
735
|
-
const focusContext = metadata && typeof metadata === "object" ? metadata.focusContext : null;
|
|
736
|
-
if (!page) return null;
|
|
737
|
-
const title = page.title ?? "(\u672A\u547D\u540D\u9875\u9762)";
|
|
738
|
-
return [
|
|
739
|
-
"\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u4E00\u4E2A\u9875\u9762 / \u6587\u7AE0\uFF08Editing Document\uFF09\u3002",
|
|
740
|
-
`- \u6807\u9898: ${title}`,
|
|
741
|
-
...focusContext && typeof focusContext === "object" && "anchorPath" in focusContext ? [
|
|
742
|
-
"",
|
|
743
|
-
"\u5F53\u524D\u7126\u70B9\uFF08Focus Context\uFF09\uFF1A",
|
|
744
|
-
`- \u5149\u6807\u662F\u5426\u6298\u53E0: ${Boolean(focusContext.isCollapsed) ? "\u662F" : "\u5426"}`,
|
|
745
|
-
...focusContext.blockType ? [`- \u5F53\u524D\u5757\u7C7B\u578B: ${String(focusContext.blockType)}`] : [],
|
|
746
|
-
...focusContext.selectedText ? [`- \u5F53\u524D\u9009\u4E2D\u6587\u672C: ${String(focusContext.selectedText)}`] : [],
|
|
747
|
-
...focusContext.anchorPath?.length ? [`- \u5F53\u524D\u951A\u70B9\u8DEF\u5F84: ${focusContext.anchorPath.join(" > ")}`] : []
|
|
748
|
-
] : [],
|
|
749
|
-
"",
|
|
750
|
-
"\u5982\u679C\u7528\u6237\u8981\u6C42\u4F60\u5BF9\u8FD9\u7BC7\u6587\u7AE0\u8FDB\u884C\u4FEE\u6539\u6216\u4F18\u5316\uFF0C\u8BF7\u5728\u56DE\u7B54\u4E2D\u660E\u786E\u6307\u51FA\u4FEE\u6539\u65B9\u5411\u3002",
|
|
751
|
-
"\u5982\u679C\u5B58\u5728\u5F53\u524D\u9009\u533A\u6216\u5149\u6807\u4E0A\u4E0B\u6587\uFF0C\u4F18\u5148\u56F4\u7ED5\u8BE5\u5C40\u90E8\u4F4D\u7F6E\u505A\u5B9A\u70B9\u6539\u5199\uFF0C\u800C\u4E0D\u662F\u6CDB\u6CDB\u91CD\u5199\u6574\u7BC7\u6587\u6863\u3002"
|
|
752
|
-
].join("\n");
|
|
753
|
-
}
|
|
754
|
-
if (targetKind === "app") {
|
|
755
|
-
const editingTarget = runtimeOptions?.editingTarget;
|
|
756
|
-
const metadata = editingTarget?.metadata;
|
|
757
|
-
const appId = editingTarget?.key ?? "(\u672A\u77E5 appId)";
|
|
758
|
-
const title = editingTarget?.title ?? "(\u672A\u547D\u540D\u5E94\u7528)";
|
|
759
|
-
const framework = typeof metadata?.framework === "string" ? metadata.framework : "worker";
|
|
760
|
-
const appUrl = typeof metadata?.appUrl === "string" ? metadata.appUrl : null;
|
|
761
|
-
const fileNames = Array.isArray(metadata?.fileNames) ? metadata.fileNames.filter((name) => typeof name === "string") : [];
|
|
762
|
-
const externalImports = Array.isArray(metadata?.externalImports) ? metadata.externalImports.filter(
|
|
763
|
-
(name) => typeof name === "string"
|
|
764
|
-
) : [];
|
|
765
|
-
const sourceSummary = asOptionalTrimmedString(editingTarget?.summary) ?? null;
|
|
766
|
-
const selectedNode = metadata && typeof metadata === "object" && metadata.selectedNode && typeof metadata.selectedNode === "object" ? metadata.selectedNode : null;
|
|
767
|
-
const constraintPacks = buildAppConstraintPacks({
|
|
768
|
-
framework,
|
|
769
|
-
fileNames,
|
|
770
|
-
externalImports
|
|
771
|
-
});
|
|
772
|
-
if (selectedNode && typeof selectedNode.cssPath === "string") {
|
|
773
|
-
const tagName = typeof selectedNode.tagName === "string" && selectedNode.tagName ? selectedNode.tagName : "\u5143\u7D20";
|
|
774
|
-
const cssPath = String(selectedNode.cssPath);
|
|
775
|
-
const outerHTMLSnippet = typeof selectedNode.outerHTMLSnippet === "string" ? selectedNode.outerHTMLSnippet : "";
|
|
776
|
-
const textSnippet = typeof selectedNode.textSnippet === "string" ? selectedNode.textSnippet : "";
|
|
777
|
-
const noloLoc = typeof selectedNode.noloLoc === "string" ? selectedNode.noloLoc : "";
|
|
778
|
-
constraintPacks.push({
|
|
779
|
-
id: "selected-node",
|
|
780
|
-
title: "\u7528\u6237\u9009\u4E2D\u8282\u70B9\uFF08\u5B9A\u70B9\u4FEE\u6539\uFF09",
|
|
781
|
-
rules: [
|
|
782
|
-
`\u7528\u6237\u5DF2\u5728\u9884\u89C8\u4E2D\u7CBE\u51C6\u9009\u4E2D\u4E00\u4E2A\u5143\u7D20\uFF1A<${tagName}> \uFF0CCSS \u8DEF\u5F84\uFF1A${cssPath}${noloLoc ? `\uFF0C\u6E90\u7801\u4F4D\u7F6E\uFF1A${noloLoc}` : ""}\u3002\u672C\u8F6E\u4FEE\u6539\u5FC5\u987B\u4EE5\u8FD9\u4E2A\u5143\u7D20\u4E3A\u4E2D\u5FC3\u3002`,
|
|
783
|
-
`\u9009\u4E2D\u5143\u7D20\u7684 HTML \u7247\u6BB5\uFF08\u53EF\u80FD\u622A\u65AD\uFF09\uFF1A${outerHTMLSnippet}${textSnippet ? `\uFF1B\u53EF\u89C1\u6587\u672C\uFF1A${textSnippet}` : ""}\u3002\u5148\u5728\u6E90\u7801\u6587\u4EF6\u4E2D\u5B9A\u4F4D\u5230\u751F\u6210\u8FD9\u6BB5 HTML \u7684\u4EE3\u7801\uFF0C\u518D\u52A8\u624B\u3002`,
|
|
784
|
-
"\u4FEE\u6539\u6536\u655B\u5728\u8BE5\u5143\u7D20\u53CA\u5176\u76F4\u63A5\u6837\u5F0F\u6765\u6E90\uFF08\u547D\u4E2D\u7684\u7EC4\u4EF6/\u7C7B/design token\uFF09\uFF1B\u8C03\u89C6\u89C9\u53C2\u6570\u4F18\u5148\u6539 token \u6216\u5C40\u90E8\u7EC4\u4EF6\u3002",
|
|
785
|
-
"\u7981\u6B62\u91CD\u5199\u672A\u547D\u4E2D\u7684\u9875\u9762\u7ED3\u6784\u3001\u5E03\u5C40\u3001\u6587\u6848\u3001\u6570\u636E\u6D41\u6216\u5176\u4ED6\u7EC4\u4EF6\uFF1B\u4FDD\u6301\u672A\u547D\u4E2D\u6587\u4EF6\u4E0D\u53D8\u3002",
|
|
786
|
-
"\u5982\u679C\u6309 CSS \u8DEF\u5F84\u548C HTML \u7247\u6BB5\u5728\u6E90\u7801\u4E2D\u627E\u4E0D\u5230\u5BF9\u5E94\u4F4D\u7F6E\uFF0C\u5148\u5411\u7528\u6237\u8BF4\u660E\u5E76\u8BF7\u7528\u6237\u91CD\u65B0\u9009\u62E9\uFF0C\u4E0D\u8981\u51ED\u731C\u6D4B\u5927\u8303\u56F4\u6539\u52A8\u3002"
|
|
787
|
-
]
|
|
788
|
-
});
|
|
789
|
-
}
|
|
790
|
-
return [
|
|
791
|
-
"\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u4E00\u4E2A Web \u5E94\u7528\uFF08Editing App\uFF09\u3002",
|
|
792
|
-
`- \u5E94\u7528 ID: ${appId}`,
|
|
793
|
-
`- \u540D\u79F0: ${title}`,
|
|
794
|
-
`- \u6280\u672F\u5F62\u6001: ${framework}`,
|
|
795
|
-
...appUrl ? [`- \u5F53\u524D\u8BBF\u95EE\u5730\u5740: ${appUrl}`] : [],
|
|
796
|
-
...fileNames.length ? [`- \u5F53\u524D\u6E90\u7801\u6587\u4EF6: ${fileNames.join(", ")}`] : ["- \u5F53\u524D\u6E90\u7801\u6587\u4EF6: (\u672A\u63D0\u4F9B\u591A\u6587\u4EF6\u6E05\u5355\uFF1B\u53EF\u80FD\u662F\u5355\u6587\u4EF6\u6E90\u7801\uFF0C\u4E5F\u53EF\u80FD\u53EA\u5269\u90E8\u7F72\u4EA7\u7269)"],
|
|
797
|
-
...externalImports.length ? [`- \u5F53\u524D\u4F9D\u8D56\u767D\u540D\u5355\u547D\u4E2D: ${externalImports.join(", ")}`] : [],
|
|
798
|
-
...sourceSummary ? ["", sourceSummary] : [],
|
|
799
|
-
"",
|
|
800
|
-
"\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
|
|
801
|
-
"1. \u7528\u6237\u8981\u6C42\u4FEE\u6539\u5F53\u524D\u5E94\u7528\u65F6\uFF0C\u5148\u8C03\u7528 appRead \u83B7\u53D6\u5F53\u524D\u4EE3\u7801/\u6587\u4EF6\uFF0C\u518D\u57FA\u4E8E\u73B0\u6709\u5B9E\u73B0\u4FEE\u6539\u3002",
|
|
802
|
-
"1b. \u5982\u679C appFileList / appFileSearch / appFileRead \u8FD4\u56DE 409\uFF08APP_WORKSPACE_MISSING / \u6E90\u7801\u5DE5\u4F5C\u533A\u7F3A\u5931\uFF09\u6216 400\uFF08UNSUPPORTED_APP_FRAMEWORK / \u4E0D\u662F Nolo React SSR\uFF09\uFF0C**\u7ACB\u5373\u505C\u6B62\u4FEE\u6539\uFF0C\u4E0D\u8981\u81EA\u5DF1\u7F16\u5360\u4F4D\u4EE3\u7801\u6216\u964D\u7EA7 framework \u53BB appDeploy**\u3002\u5148\u8C03\u7528 appVersionList(appId) \u67E5\u770B\u5386\u53F2\u7248\u672C\uFF0C\u9009\u4E00\u4E2A\u6700\u8FD1\u7684\u5B8C\u6574\u7248\u672C\u7528 appVersionRestore(appId, versionId) \u6062\u590D\uFF0C\u6062\u590D\u540E\u6E90\u7801\u5DE5\u4F5C\u533A\u4F1A\u91CD\u5EFA\uFF0C\u518D\u7EE7\u7EED\u4FEE\u6539\u3002\u5982\u679C\u6CA1\u6709\u5386\u53F2\u7248\u672C\uFF0C\u518D\u5411\u7528\u6237\u8BF4\u660E\u60C5\u51B5\u3002\u7EDD\u4E0D\u53EF\u4EE5\u7528 `fetch(appUrl)`\u3001\u7A7A\u4EE3\u7801\u3001\u5360\u4F4D\u4EE3\u7801\u53BB appDeploy\u2014\u2014\u90A3\u4F1A\u8986\u76D6\u73B0\u6709\u5E94\u7528\u5BFC\u81F4\u6570\u636E\u4E22\u5931\u3002",
|
|
803
|
-
"2. \u5982\u679C appRead \u8FD4\u56DE workspaceRef/sourceFiles/sourceOmitted\uFF0C\u4E0D\u8981\u6574\u7AD9\u91CD\u5199\uFF1B\u4F7F\u7528 App Builder \u7684\u53D7\u9650 workspace \u6587\u4EF6\u5DE5\u5177\uFF1AappFileList=listFiles\u3001appFileSearch=searchFiles\u3001appFileRead=readFile\u3001appFileReplace=editFile\u3001appFileWrite=writeFile\u3002\u5148\u5B9A\u4F4D\u6587\u4EF6\u4E0E\u547D\u4E2D\u884C\uFF0C\u5927\u6587\u4EF6\u53EA\u8BFB\u53D6\u5FC5\u8981\u884C\u8303\u56F4\uFF1B\u6587\u5B57\u3001\u6837\u5F0F\u3001token\u3001\u5C40\u90E8\u903B\u8F91\u7B49\u5C0F\u6539\u52A8\u5FC5\u987B\u4F18\u5148\u7528 appFileReplace \u7CBE\u786E\u66FF\u6362\u552F\u4E00\u7247\u6BB5\uFF0C\u53EA\u6709\u65B0\u5EFA\u6587\u4EF6\u6216\u786E\u5B9E\u9700\u8981\u6574\u6587\u4EF6\u91CD\u5199\u65F6\u624D\u7528 appFileWrite\u3002",
|
|
804
|
-
"3. \u5148\u8BC6\u522B\u5F53\u524D\u5E94\u7528\u662F\u5426\u5DF2\u6709 theme / tokens / design system\uFF1B\u5DF2\u6709\u5C31\u4F18\u5148\u6539\u8FD9\u5C42\uFF0C\u6CA1\u6709\u518D\u8865\u4E00\u5C42\u6700\u5C0F\u5171\u4EAB token\uFF0C\u518D\u57FA\u4E8E token \u8C03\u6574\u7EC4\u4EF6\u3002",
|
|
805
|
-
"4. \u5982\u679C\u5F53\u524D\u5E94\u7528\u8FD8\u662F\u65E7\u5199\u6CD5\uFF1A\u89C6\u89C9\u503C\u6563\u843D\u5728\u7EC4\u4EF6\u786C\u7F16\u7801 style \u91CC\uFF0C\u800C\u7528\u6237\u53EA\u662F\u505A\u5B57\u4F53/\u989C\u8272/\u95F4\u8DDD\u7B49\u89C6\u89C9\u5FAE\u8C03\uFF0C\u9ED8\u8BA4\u5148\u628A\u547D\u4E2D\u7684\u89C6\u89C9\u503C\u62BD\u5230\u6700\u5C0F token \u5C42\uFF0C\u518D\u5B8C\u6210\u672C\u6B21\u4FEE\u6539\uFF1B\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4E0D\u8981\u91CD\u6784\u3002",
|
|
806
|
-
`5. \u91CD\u65B0\u90E8\u7F72\u5F53\u524D\u5E94\u7528\u65F6\uFF0CappDeploy \u5FC5\u987B\u7EE7\u7EED\u4F20\u540C\u4E00\u4E2A appId\uFF08${appId}\uFF09\uFF0C\u907F\u514D\u521B\u5EFA\u65B0\u5E94\u7528\u3002`,
|
|
807
|
-
framework === "nolo-react" ? "6. \u5F53\u524D\u5E94\u7528\u662F Nolo React SSR\uFF0C\u4FEE\u6539\u65F6\u4F18\u5148\u4F7F\u7528\u53D7\u9650 app workspace \u6587\u4EF6\u5DE5\u5177\u64CD\u4F5C\u6E90\u7801\u5DE5\u4F5C\u533A\uFF0C\u7136\u540E appPreflight/appDeploy\uFF1B\u4E0D\u8981\u9000\u56DE react-spa \u6216\u5355\u6587\u4EF6 Worker\u3002" : framework === "react-spa" ? '6. \u5F53\u524D\u5E94\u7528\u662F React SPA\uFF0C\u4FEE\u6539\u65F6\u7EE7\u7EED\u6CBF\u7528 framework: "react-spa" + files\uFF0C\u4E0D\u8981\u9000\u56DE\u5355\u6587\u4EF6 Worker\u3002' : "6. \u5F53\u524D\u5E94\u7528\u76EE\u524D\u662F Worker \u5F62\u6001\uFF1B\u5982\u679C\u9700\u6C42\u53D8\u6210\u590D\u6742\u4EA4\u4E92\u6216\u56FE\u8868\uFF0C\u53EF\u4EE5\u8BC4\u4F30\u5347\u7EA7\u4E3A React SPA\u3002",
|
|
808
|
-
...fileNames.length ? [] : [
|
|
809
|
-
"7. \u5F53\u524D\u6CA1\u6709\u6E90\u7801\u6587\u4EF6\u6E05\u5355\u65F6\uFF0C\u5FC5\u987B\u5148\u7528 appRead \u5224\u65AD\u8BFB\u5230\u7684\u662F\u53EF\u7EF4\u62A4\u6E90\u7801\u8FD8\u662F\u90E8\u7F72\u4EA7\u7269 / \u6253\u5305 bundle\u3002",
|
|
810
|
-
"8. \u5982\u679C appRead \u8FD4\u56DE\u7684\u662F HTML \u58F3\u3001importmap\u3001\u538B\u7F29 bundle \u6216\u660E\u663E\u4E0D\u662F\u539F\u59CB\u6E90\u7801\u6587\u4EF6\uFF0C\u7981\u6B62\u5728\u672A\u544A\u77E5\u7528\u6237\u98CE\u9669\u7684\u60C5\u51B5\u4E0B\u6574\u7AD9\u91CD\u5199\uFF1B\u5E94\u5148\u8BF4\u660E\u201C\u5F53\u524D\u7F3A\u5C11\u539F\u59CB\u6E90\u7801\u5FEB\u7167\uFF0C\u7EE7\u7EED\u4FEE\u6539\u66F4\u50CF\u6574\u4F53\u91CD\u5EFA\u201D\uFF0C\u7B49\u7528\u6237\u786E\u8BA4\u540E\u518D\u7EE7\u7EED\u3002"
|
|
811
|
-
],
|
|
812
|
-
"9. \u5982\u679C\u7528\u6237\u53EA\u662F\u8981\u8C03\u5B57\u4F53\u5927\u5C0F\u3001\u914D\u8272\u3001\u5706\u89D2\u3001\u9634\u5F71\u3001\u7559\u767D\u7B49\u89C6\u89C9\u7EC6\u8282\uFF0C\u9ED8\u8BA4\u4F18\u5148\u6539\u8BBE\u8BA1 token \u6216\u547D\u4E2D\u7684\u5C40\u90E8\u7EC4\u4EF6\uFF1B\u5BF9\u65E7\u5199\u6CD5\u5E94\u7528\u5219\u4F18\u5148\u505A\u6700\u5C0F token \u8FC1\u79FB\uFF0C\u4E0D\u8981\u53EA\u6539\u6563\u843D\u786C\u7F16\u7801\u3002",
|
|
813
|
-
"10. \u6BCF\u6B21\u4FEE\u6539\u5B8C\u6210\u540E\uFF0C\u5148 appPreflight\uFF0C\u518D appDeploy\uFF1B\u5982\u679C\u5931\u8D25\uFF0C\u6309\u8FD4\u56DE issues \u5B9A\u70B9\u4FEE\u590D\u3002",
|
|
814
|
-
"11. \u56DE\u590D\u7528\u6237\u65F6\u4F18\u5148\u8BF4\u660E\u505A\u4E86\u4EC0\u4E48\u53D8\u5316\u3001\u73B0\u5728\u5E94\u7528\u53EF\u4EE5\u600E\u4E48\u7528\uFF0C\u800C\u4E0D\u662F\u76F4\u63A5\u5806\u4EE3\u7801\u3002",
|
|
815
|
-
...formatAppConstraintPacks(constraintPacks)
|
|
816
|
-
].join("\n");
|
|
817
|
-
}
|
|
818
|
-
if (targetKind === "local_preview") {
|
|
819
|
-
const metadata = runtimeOptions?.editingTarget?.metadata;
|
|
820
|
-
const selectedNode = metadata && typeof metadata === "object" && metadata.selectedNode && typeof metadata.selectedNode === "object" ? metadata.selectedNode : null;
|
|
821
|
-
if (!selectedNode) return null;
|
|
822
|
-
const readString = (key) => typeof selectedNode[key] === "string" ? selectedNode[key] : "";
|
|
823
|
-
const tagName = readString("tagName") || "\u5143\u7D20";
|
|
824
|
-
const cssPath = readString("cssPath");
|
|
825
|
-
const noloLoc = readString("noloLoc");
|
|
826
|
-
const textSnippet = readString("textSnippet");
|
|
827
|
-
const outerHTMLSnippet = readString("outerHTMLSnippet");
|
|
828
|
-
return [
|
|
829
|
-
"\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u672C\u5730\u5DE5\u4F5C\u533A\u91CC\u6B63\u5728\u9884\u89C8\u7684\u7F51\u9875\uFF08Local Preview\uFF09\u3002",
|
|
830
|
-
`\u7528\u6237\u5728\u9884\u89C8\u4E2D\u9009\u4E2D\u4E86\u4E00\u4E2A\u5143\u7D20\uFF1A<${tagName}>\uFF0CCSS \u8DEF\u5F84\uFF1A${cssPath}${noloLoc ? `\uFF0C\u6E90\u7801\u4F4D\u7F6E\uFF1A${noloLoc}` : ""}\u3002`,
|
|
831
|
-
`\u9009\u4E2D\u5143\u7D20\u7684 HTML \u7247\u6BB5\uFF08\u53EF\u80FD\u622A\u65AD\uFF09\uFF1A${outerHTMLSnippet}${textSnippet ? `\uFF1B\u53EF\u89C1\u6587\u672C\uFF1A${textSnippet}` : ""}\u3002`,
|
|
832
|
-
"",
|
|
833
|
-
"\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
|
|
834
|
-
"1. \u672C\u8F6E\u4FEE\u6539\u5FC5\u987B\u4EE5\u8FD9\u4E2A\u5143\u7D20\u4E3A\u4E2D\u5FC3\uFF1B\u5148\u5728\u672C\u5730\u5DE5\u4F5C\u533A\u6E90\u7801\u4E2D\u5B9A\u4F4D\u5230\u751F\u6210\u8FD9\u6BB5 HTML \u7684\u4EE3\u7801\uFF0C\u518D\u52A8\u624B\u3002",
|
|
835
|
-
noloLoc ? "2. \u5DF2\u7ED9\u51FA\u6E90\u7801\u4F4D\u7F6E\uFF0C\u76F4\u63A5\u8BFB\u8BE5\u6587\u4EF6\u7684\u5BF9\u5E94\u884C\u8303\u56F4\u786E\u8BA4\uFF0C\u4E0D\u8981\u5168\u5C40\u641C\u7D22\u3002" : "2. \u6CA1\u6709\u6E90\u7801\u4F4D\u7F6E\u65F6\uFF0C\u7528 CSS \u8DEF\u5F84\u91CC\u7684\u7C7B\u540D\u3001\u53EF\u89C1\u6587\u672C\u6216 HTML \u7247\u6BB5\u641C\u7D22\u5DE5\u4F5C\u533A\u5B9A\u4F4D\uFF0C\u4E0D\u8981\u51ED\u731C\u6D4B\u6539\u52A8\u3002",
|
|
836
|
-
"3. \u4FEE\u6539\u6536\u655B\u5728\u8BE5\u5143\u7D20\u53CA\u5176\u76F4\u63A5\u6837\u5F0F\u6765\u6E90\uFF08\u547D\u4E2D\u7684\u7EC4\u4EF6/\u7C7B/design token\uFF09\uFF1B\u4FDD\u6301\u672A\u547D\u4E2D\u7684\u6587\u4EF6\u4E0D\u53D8\u3002",
|
|
837
|
-
"4. \u5982\u679C\u5B9A\u4F4D\u7ED3\u679C\u843D\u5728 node_modules \u6216\u6765\u81EA\u63A5\u53E3\u6570\u636E\uFF0C\u5148\u544A\u8BC9\u7528\u6237\u5B9E\u9645\u60C5\u51B5\uFF0C\u518D\u63D0\u51FA\u53EF\u884C\u7684\u6539\u6CD5\uFF0C\u4E0D\u8981\u786C\u6539\u3002",
|
|
838
|
-
"5. \u5982\u679C\u6309 CSS \u8DEF\u5F84\u548C HTML \u7247\u6BB5\u627E\u4E0D\u5230\u5BF9\u5E94\u4F4D\u7F6E\uFF0C\u5148\u5411\u7528\u6237\u8BF4\u660E\u5E76\u8BF7\u5176\u91CD\u65B0\u9009\u62E9\u3002"
|
|
839
|
-
].join("\n");
|
|
840
|
-
}
|
|
841
|
-
if (targetKind === "image" || targetKind === "file") {
|
|
842
|
-
const editingTarget = runtimeOptions?.editingTarget;
|
|
843
|
-
const metadata = editingTarget?.metadata;
|
|
844
|
-
const title = editingTarget?.title ?? "(\u672A\u547D\u540D\u5BF9\u8C61)";
|
|
845
|
-
const objectKey = editingTarget?.key ?? "(\u672A\u77E5 key)";
|
|
846
|
-
const fileId = typeof metadata?.fileId === "string" ? metadata.fileId : null;
|
|
847
|
-
const url = typeof metadata?.url === "string" ? metadata.url : null;
|
|
848
|
-
const size = typeof metadata?.size === "number" ? metadata.size : null;
|
|
849
|
-
return [
|
|
850
|
-
`\u5F53\u524D\u7F16\u8F91\u76EE\u6807\uFF1A\u4E00\u4E2A${targetKind === "image" ? "\u56FE\u7247" : "\u6587\u4EF6"}\u5BF9\u8C61\uFF08Editing ${targetKind === "image" ? "Image" : "File"}\uFF09\u3002`,
|
|
851
|
-
`- \u5BF9\u8C61 key: ${objectKey}`,
|
|
852
|
-
`- \u6807\u9898: ${title}`,
|
|
853
|
-
...fileId ? [`- fileId: ${fileId}`] : [],
|
|
854
|
-
...url ? [`- \u8D44\u6E90\u5730\u5740: ${url}`] : [],
|
|
855
|
-
...size !== null ? [`- \u6587\u4EF6\u5927\u5C0F: ${size} bytes`] : [],
|
|
856
|
-
"",
|
|
857
|
-
"\u3010\u7ED9 AI \u7684\u64CD\u4F5C\u6307\u5357 / \u975E\u7528\u6237\u539F\u8BDD\u3011",
|
|
858
|
-
targetKind === "image" ? "\u5F53\u524D\u9636\u6BB5\u4F18\u5148\u5E2E\u52A9\u7528\u6237\u7406\u89E3\u56FE\u7247\u5185\u5BB9\u3001\u63D0\u70BC\u91CD\u70B9\u3001\u547D\u540D\u5F52\u7C7B\u548C\u4E0B\u4E00\u6B65\u5904\u7406\u5EFA\u8BAE\u3002\u4E0D\u8981\u5047\u88C5\u5DF2\u7ECF\u5B8C\u6210\u590D\u6742\u56FE\u7247\u7F16\u8F91\u3002" : "\u5F53\u524D\u9636\u6BB5\u4F18\u5148\u5E2E\u52A9\u7528\u6237\u7406\u89E3\u6587\u4EF6\u7528\u9014\u3001\u63D0\u53D6\u5904\u7406\u601D\u8DEF\u3001\u7ED9\u51FA\u6574\u7406\u5EFA\u8BAE\u548C\u4E0B\u4E00\u6B65\u64CD\u4F5C\u5EFA\u8BAE\u3002\u4E0D\u8981\u5047\u88C5\u5DF2\u7ECF\u5B8C\u6574\u89E3\u6790\u6587\u4EF6\u5185\u5BB9\u3002"
|
|
859
|
-
].join("\n");
|
|
860
|
-
}
|
|
861
|
-
if (targetKind === "canvas_node") {
|
|
862
|
-
return buildCanvasNodeEditingContextSummary(runtimeOptions);
|
|
863
|
-
}
|
|
864
|
-
return null;
|
|
865
|
-
};
|
|
866
|
-
|
|
867
|
-
// packages/ai/llm/agentCapabilities.ts
|
|
868
|
-
var ANTIGRAVITY_EFFORT_SUFFIXES = [
|
|
869
|
-
"-tiered",
|
|
870
|
-
"-extra-low",
|
|
871
|
-
"-low",
|
|
872
|
-
"-medium",
|
|
873
|
-
"-high"
|
|
874
|
-
];
|
|
875
|
-
function stripEffortSuffix(model) {
|
|
876
|
-
for (const suffix of ANTIGRAVITY_EFFORT_SUFFIXES) {
|
|
877
|
-
if (model.endsWith(suffix) && model.length > suffix.length) {
|
|
878
|
-
return model.slice(0, -suffix.length);
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
return model;
|
|
882
|
-
}
|
|
883
|
-
function stripPreviewSuffix(model) {
|
|
884
|
-
const suffix = "-preview";
|
|
885
|
-
if (model.endsWith(suffix) && model.length > suffix.length) {
|
|
886
|
-
return model.slice(0, -suffix.length);
|
|
887
|
-
}
|
|
888
|
-
return model;
|
|
889
|
-
}
|
|
890
|
-
var lookupKnownModelVision = (provider, model) => {
|
|
891
|
-
if (!model) return void 0;
|
|
892
|
-
const candidates = [model];
|
|
893
|
-
const strippedEffort = stripEffortSuffix(model);
|
|
894
|
-
if (strippedEffort !== model) candidates.push(strippedEffort);
|
|
895
|
-
const strippedPreview = stripPreviewSuffix(model);
|
|
896
|
-
if (strippedPreview !== model) candidates.push(strippedPreview);
|
|
897
|
-
for (const candidate of candidates) {
|
|
898
|
-
if (provider && provider !== "custom") {
|
|
899
|
-
const direct = findModelConfig(provider, candidate);
|
|
900
|
-
if (direct && typeof direct.hasVision === "boolean") return direct.hasVision;
|
|
901
|
-
}
|
|
902
|
-
const detected = getProviderByModelName(candidate);
|
|
903
|
-
if (detected) {
|
|
904
|
-
const found = findModelConfig(detected, candidate)?.hasVision;
|
|
905
|
-
if (found !== void 0) return found;
|
|
906
|
-
}
|
|
907
|
-
if (candidate.includes("/")) {
|
|
908
|
-
const slash = candidate.indexOf("/");
|
|
909
|
-
const modelProvider = candidate.slice(0, slash).toLowerCase();
|
|
910
|
-
const modelName = candidate.slice(slash + 1);
|
|
911
|
-
const nested = findModelConfig(modelProvider, modelName);
|
|
912
|
-
if (nested && typeof nested.hasVision === "boolean") return nested.hasVision;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
return void 0;
|
|
916
|
-
};
|
|
917
|
-
var resolveAgentImageInputSupport = (agent) => {
|
|
918
|
-
if (!agent) return true;
|
|
919
|
-
const provider = asTrimmedLowercaseString(agent.provider) || null;
|
|
920
|
-
const model = asOptionalTrimmedString(agent.model) ?? "";
|
|
921
|
-
const catalogHasVision = lookupKnownModelVision(
|
|
922
|
-
provider,
|
|
923
|
-
model
|
|
924
|
-
);
|
|
925
|
-
if (catalogHasVision !== void 0) {
|
|
926
|
-
return catalogHasVision;
|
|
927
|
-
}
|
|
928
|
-
if (typeof agent.hasVision === "boolean") {
|
|
929
|
-
return agent.hasVision;
|
|
930
|
-
}
|
|
931
|
-
return true;
|
|
932
|
-
};
|
|
933
|
-
|
|
934
|
-
// packages/ai/agent/appWorkingMemory.ts
|
|
935
|
-
var APP_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
936
|
-
"appList",
|
|
937
|
-
"appRead",
|
|
938
|
-
"appDeploy",
|
|
939
|
-
"appPreflight",
|
|
940
|
-
"appDelete"
|
|
941
|
-
]);
|
|
942
|
-
var contentToText = (content) => {
|
|
943
|
-
if (!content) return "";
|
|
944
|
-
if (typeof content === "string") return content;
|
|
945
|
-
if (Array.isArray(content)) {
|
|
946
|
-
return content.map((part) => "text" in part ? part.text ?? "" : "").join("\n");
|
|
947
|
-
}
|
|
948
|
-
return "";
|
|
949
|
-
};
|
|
950
|
-
var parseAppListEntries = (text) => text.split("\n").map((line) => line.trim()).filter((line) => line.startsWith("- **") && line.includes("(appId:"));
|
|
951
|
-
var buildRecentAppToolMemory = (messages, toolRuns) => {
|
|
952
|
-
const messageById = new Map(messages.map((msg) => [msg.id, msg]));
|
|
953
|
-
const recentRuns = [...toolRuns].filter((run) => APP_TOOL_NAMES.has(run.toolName)).sort((a, b) => (b.startedAt ?? 0) - (a.startedAt ?? 0)).slice(0, 8);
|
|
954
|
-
if (recentRuns.length === 0) return null;
|
|
955
|
-
const lines = [
|
|
956
|
-
"\u8FD9\u4E9B\u4FE1\u606F\u6765\u81EA\u5F53\u524D\u5BF9\u8BDD\u91CC\u6700\u8FD1\u7684 app \u5DE5\u5177\u8C03\u7528\uFF0C\u4E0D\u4F9D\u8D56\u53F3\u4FA7\u7F16\u8F91\u6001\u3002"
|
|
957
|
-
];
|
|
958
|
-
const latestDeployLike = recentRuns.find(
|
|
959
|
-
(run) => ["appDeploy", "appRead", "appPreflight"].includes(run.toolName)
|
|
960
|
-
);
|
|
961
|
-
if (latestDeployLike) {
|
|
962
|
-
const input = latestDeployLike.input ?? {};
|
|
963
|
-
const parts = [
|
|
964
|
-
`- \u6700\u8FD1\u4E00\u6B21\u5173\u952E app \u64CD\u4F5C: ${latestDeployLike.toolName}`,
|
|
965
|
-
typeof input.appId === "string" ? `appId=${input.appId}` : null,
|
|
966
|
-
typeof input.name === "string" ? `name=${input.name}` : null,
|
|
967
|
-
typeof input.framework === "string" ? `framework=${input.framework}` : null
|
|
968
|
-
].filter(Boolean);
|
|
969
|
-
lines.push(parts.join("\uFF0C"));
|
|
970
|
-
}
|
|
971
|
-
const relatedMessages = recentRuns.map((run) => messageById.get(run.messageId)).filter((msg) => !!msg);
|
|
972
|
-
const appListMessage = relatedMessages.find((msg) => msg.toolName === "appList");
|
|
973
|
-
if (appListMessage) {
|
|
974
|
-
const entries = parseAppListEntries(contentToText(appListMessage.content)).slice(0, 5);
|
|
975
|
-
if (entries.length > 0) {
|
|
976
|
-
lines.push("- \u6700\u8FD1\u4E00\u6B21 appList \u7ED3\u679C\uFF1A");
|
|
977
|
-
lines.push(...entries.map((entry) => ` ${entry}`));
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
const latestReadMessage = relatedMessages.find((msg) => msg.toolName === "appRead");
|
|
981
|
-
if (latestReadMessage) {
|
|
982
|
-
const text = contentToText(latestReadMessage.content);
|
|
983
|
-
const appId = text.match(/- appId:\s*(.+)/)?.[1]?.trim();
|
|
984
|
-
const url = text.match(/- 访问地址:\s*(.+)/)?.[1]?.trim();
|
|
985
|
-
if (appId || url) {
|
|
986
|
-
lines.push(
|
|
987
|
-
[
|
|
988
|
-
"- \u6700\u8FD1\u4E00\u6B21 appRead \u771F\u503C:",
|
|
989
|
-
appId ? `appId=${appId}` : null,
|
|
990
|
-
url ? `url=${url}` : null
|
|
991
|
-
].filter(Boolean).join("\uFF0C")
|
|
992
|
-
);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
const latestPreflightRun = recentRuns.find((run) => run.toolName === "appPreflight");
|
|
996
|
-
if (latestPreflightRun) {
|
|
997
|
-
lines.push(
|
|
998
|
-
[
|
|
999
|
-
"- \u6700\u8FD1\u4E00\u6B21 appPreflight:",
|
|
1000
|
-
latestPreflightRun.status === "failed" ? "\u5931\u8D25" : "\u5DF2\u6267\u884C",
|
|
1001
|
-
latestPreflightRun.outputSummary ? `\u6458\u8981=${latestPreflightRun.outputSummary}` : null
|
|
1002
|
-
].filter(Boolean).join("\uFF0C")
|
|
1003
|
-
);
|
|
1004
|
-
}
|
|
1005
|
-
const latestDeployMessage = relatedMessages.find((msg) => msg.toolName === "appDeploy");
|
|
1006
|
-
if (latestDeployMessage) {
|
|
1007
|
-
const text = contentToText(latestDeployMessage.content);
|
|
1008
|
-
const appId = text.match(/- appId:\s*(.+)/)?.[1]?.trim();
|
|
1009
|
-
const url = text.match(/- 访问地址:\s*(.+)/)?.[1]?.trim();
|
|
1010
|
-
if (appId || url) {
|
|
1011
|
-
lines.push(
|
|
1012
|
-
[
|
|
1013
|
-
"- \u6700\u8FD1\u4E00\u6B21 appDeploy \u7ED3\u679C:",
|
|
1014
|
-
appId ? `appId=${appId}` : null,
|
|
1015
|
-
url ? `url=${url}` : null
|
|
1016
|
-
].filter(Boolean).join("\uFF0C")
|
|
1017
|
-
);
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
lines.push(
|
|
1021
|
-
"- \u5982\u679C\u7528\u6237\u8BF4\u201C\u521A\u624D\u90A3\u4E2A app / \u90A3\u4E2A\u7F51\u7AD9\u201D\uFF0C\u4F18\u5148\u628A\u5B83\u7406\u89E3\u4E3A\u4E0A\u9762\u6700\u8FD1\u4E00\u6B21\u88AB\u8BFB\u53D6\u3001\u9884\u68C0\u6216\u90E8\u7F72\u7684\u5E94\u7528\uFF1B\u82E5\u4ECD\u6709\u6B67\u4E49\uFF0C\u518D\u7528 appList \u6216 appRead \u786E\u8BA4\u3002"
|
|
1022
|
-
);
|
|
1023
|
-
return lines.join("\n");
|
|
1024
|
-
};
|
|
1025
|
-
|
|
1026
|
-
// packages/ai/agent/streamAgentChatTurnUtils.ts
|
|
1027
|
-
var BROWSER_UNAVAILABLE_CORE_TOOLS = {
|
|
1028
|
-
queryModelUsage: true,
|
|
1029
|
-
createAgentAutomation: true,
|
|
1030
|
-
notifyUser: true
|
|
1031
|
-
};
|
|
1032
|
-
var getRuntimeCoreTools = () => {
|
|
1033
|
-
if (typeof window === "undefined") {
|
|
1034
|
-
return [...TOOL_PACKS.CORE];
|
|
1035
|
-
}
|
|
1036
|
-
return TOOL_PACKS.CORE.filter(
|
|
1037
|
-
(toolName) => !BROWSER_UNAVAILABLE_CORE_TOOLS[toolName]
|
|
1038
|
-
);
|
|
1039
|
-
};
|
|
1040
|
-
var isInlineVisualArtifactAgent = (agentConfig) => {
|
|
1041
|
-
const tags = Array.isArray(agentConfig.tags) ? agentConfig.tags : [];
|
|
1042
|
-
return tags.some(
|
|
1043
|
-
(tag) => typeof tag === "string" && ["inline-artifact", "streaming-ui"].includes(tag)
|
|
1044
|
-
);
|
|
1045
|
-
};
|
|
1046
|
-
var estimateTokensOfMessage = (msg) => {
|
|
1047
|
-
let content = "";
|
|
1048
|
-
if (typeof msg.content === "string") {
|
|
1049
|
-
content = msg.content;
|
|
1050
|
-
} else if (Array.isArray(msg.content)) {
|
|
1051
|
-
content = msg.content.map((p) => {
|
|
1052
|
-
if (p.type === "text") return p.text || "";
|
|
1053
|
-
if (p.type === "image_url") return "[image]";
|
|
1054
|
-
return "[non-text]";
|
|
1055
|
-
}).join("");
|
|
1056
|
-
} else if (msg.content && typeof msg.content === "object") {
|
|
1057
|
-
content = JSON.stringify(msg.content);
|
|
1058
|
-
}
|
|
1059
|
-
let extraTokens = 0;
|
|
1060
|
-
if (Array.isArray(msg.tool_calls)) {
|
|
1061
|
-
const toolsStr = JSON.stringify(msg.tool_calls);
|
|
1062
|
-
extraTokens = estimateTokenCount(toolsStr);
|
|
1063
|
-
}
|
|
1064
|
-
return estimateTokenCount(content) + extraTokens;
|
|
1065
|
-
};
|
|
1066
|
-
var classifyConversationLoad = (messages) => {
|
|
1067
|
-
const N = 20;
|
|
1068
|
-
if (!Array.isArray(messages) || messages.length === 0) return "light";
|
|
1069
|
-
const tail = messages.slice(-N);
|
|
1070
|
-
const tokenSamples = tail.map(estimateTokensOfMessage);
|
|
1071
|
-
if (tokenSamples.length === 0) return "light";
|
|
1072
|
-
const sum = tokenSamples.reduce((acc, v) => acc + v, 0);
|
|
1073
|
-
const avg = sum / tokenSamples.length;
|
|
1074
|
-
const sorted = [...tokenSamples].sort((a, b) => a - b);
|
|
1075
|
-
const p95 = sorted[Math.floor((sorted.length - 1) * 0.95)];
|
|
1076
|
-
if (p95 < 200 && avg < 120) {
|
|
1077
|
-
return "light";
|
|
1078
|
-
}
|
|
1079
|
-
if (p95 > 2e3 || avg > 1200) {
|
|
1080
|
-
return "heavy";
|
|
1081
|
-
}
|
|
1082
|
-
return "medium";
|
|
1083
|
-
};
|
|
1084
|
-
var compressOldToolResults = (messages, maxChars = 800) => {
|
|
1085
|
-
let lastToolCallAssistantIdx = -1;
|
|
1086
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1087
|
-
if (messages[i].role === "assistant" && Array.isArray(messages[i].tool_calls) && messages[i].tool_calls.length > 0) {
|
|
1088
|
-
lastToolCallAssistantIdx = i;
|
|
1089
|
-
break;
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
return messages.map((msg, idx) => {
|
|
1093
|
-
if (msg.role !== "tool") return msg;
|
|
1094
|
-
const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
1095
|
-
const projected = projectToolMessageContent({
|
|
1096
|
-
content,
|
|
1097
|
-
isFresh: idx > lastToolCallAssistantIdx,
|
|
1098
|
-
toolName: msg.name,
|
|
1099
|
-
historicalMaxChars: maxChars
|
|
1100
|
-
});
|
|
1101
|
-
if (projected === content) return msg;
|
|
1102
|
-
return { ...msg, content: projected };
|
|
1103
|
-
});
|
|
1104
|
-
};
|
|
1105
|
-
var trimMessagesWithSummary = (messages, contextWindow, summaryTokenCount) => {
|
|
1106
|
-
const recentLoad = classifyConversationLoad(messages);
|
|
1107
|
-
const { rawMessageBudget, minTailTokens } = planContextUsage({
|
|
1108
|
-
contextWindow,
|
|
1109
|
-
summaryTokens: summaryTokenCount,
|
|
1110
|
-
recentLoad
|
|
1111
|
-
});
|
|
1112
|
-
if (!Array.isArray(messages) || messages.length === 0) return messages;
|
|
1113
|
-
let totalTokens = 0;
|
|
1114
|
-
let keepCount = 0;
|
|
1115
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1116
|
-
const t = estimateTokensOfMessage(messages[i]);
|
|
1117
|
-
if (totalTokens + t > rawMessageBudget) break;
|
|
1118
|
-
totalTokens += t;
|
|
1119
|
-
keepCount++;
|
|
1120
|
-
}
|
|
1121
|
-
if (keepCount >= messages.length) {
|
|
1122
|
-
return messages;
|
|
1123
|
-
}
|
|
1124
|
-
if (totalTokens < minTailTokens) {
|
|
1125
|
-
const maxBudgetWithSlack = rawMessageBudget * 1.2;
|
|
1126
|
-
for (let i = messages.length - 1 - keepCount; i >= 0; i--) {
|
|
1127
|
-
const t = estimateTokensOfMessage(messages[i]);
|
|
1128
|
-
if (totalTokens + t > maxBudgetWithSlack) break;
|
|
1129
|
-
totalTokens += t;
|
|
1130
|
-
keepCount++;
|
|
1131
|
-
if (totalTokens >= minTailTokens) break;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
if (keepCount === 0 && messages.length > 0) {
|
|
1135
|
-
keepCount = Math.min(2, messages.length);
|
|
1136
|
-
}
|
|
1137
|
-
let cutIndex = messages.length - keepCount;
|
|
1138
|
-
if (cutIndex < 0) cutIndex = 0;
|
|
1139
|
-
while (cutIndex > 0 && messages[cutIndex]?.role === "tool") {
|
|
1140
|
-
cutIndex--;
|
|
1141
|
-
}
|
|
1142
|
-
return messages.slice(cutIndex);
|
|
1143
|
-
};
|
|
1144
|
-
var createDbSliceTurnContextSource = (dispatch) => ({
|
|
1145
|
-
readRecord: async (dbKey) => {
|
|
1146
|
-
const result = await dispatch(read({ dbKey })).unwrap();
|
|
1147
|
-
return result ?? null;
|
|
1148
|
-
}
|
|
1149
|
-
});
|
|
1150
|
-
var joinMapValues = (map) => Array.from(map.values()).join("");
|
|
1151
|
-
var hasImageInMessages = (messages) => {
|
|
1152
|
-
if (!Array.isArray(messages)) return false;
|
|
1153
|
-
return messages.some((msg) => {
|
|
1154
|
-
const content = msg.content;
|
|
1155
|
-
if (!Array.isArray(content)) return false;
|
|
1156
|
-
return content.some(
|
|
1157
|
-
(part) => part && typeof part === "object" && part.type === "image_url" && part.image_url && typeof part.image_url.url === "string" && part.image_url.url.trim() !== ""
|
|
1158
|
-
);
|
|
1159
|
-
});
|
|
1160
|
-
};
|
|
1161
|
-
var REJECT_NO_VISION_MESSAGE = "\u5F53\u524D Agent \u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF0C\u8BF7\u6539\u7528\u6587\u672C\u6216\u6587\u6863\u3002";
|
|
1162
|
-
function shouldRejectImageInputForAgent(agentConfig, messages) {
|
|
1163
|
-
const agentHasVision = resolveAgentImageInputSupport(agentConfig);
|
|
1164
|
-
if (!agentHasVision && hasImageInMessages(messages)) {
|
|
1165
|
-
return REJECT_NO_VISION_MESSAGE;
|
|
1166
|
-
}
|
|
1167
|
-
return null;
|
|
1168
|
-
}
|
|
1169
|
-
var formatCurrentInputContext = (pendingFiles, currentInputMap) => {
|
|
1170
|
-
if (pendingFiles.length === 0 || currentInputMap.size === 0) {
|
|
1171
|
-
return joinMapValues(currentInputMap);
|
|
1172
|
-
}
|
|
1173
|
-
const relevantPendingFiles = pendingFiles.filter((file) => {
|
|
1174
|
-
const key = file.sourceDialogKey || file.dialogKey || file.pageKey;
|
|
1175
|
-
return key && currentInputMap.has(key);
|
|
1176
|
-
});
|
|
1177
|
-
if (relevantPendingFiles.length === 0) {
|
|
1178
|
-
return joinMapValues(currentInputMap);
|
|
1179
|
-
}
|
|
1180
|
-
const filesByGroup = /* @__PURE__ */ new Map();
|
|
1181
|
-
for (const file of relevantPendingFiles) {
|
|
1182
|
-
const groupKey = file.groupId || file.id;
|
|
1183
|
-
const group = filesByGroup.get(groupKey);
|
|
1184
|
-
if (group) {
|
|
1185
|
-
group.push(file);
|
|
1186
|
-
} else {
|
|
1187
|
-
filesByGroup.set(groupKey, [file]);
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
let sourceCounter = 1;
|
|
1191
|
-
let output = "";
|
|
1192
|
-
filesByGroup.forEach((filesInGroup) => {
|
|
1193
|
-
const isGroup = filesInGroup.length > 1;
|
|
1194
|
-
const sourceName = isGroup ? filesInGroup[0].name.split(" (")[0] : filesInGroup[0].name;
|
|
1195
|
-
output += `--- Source ${sourceCounter}: "${sourceName}" ---
|
|
1196
|
-
`;
|
|
1197
|
-
filesInGroup.forEach((file) => {
|
|
1198
|
-
const key = file.sourceDialogKey || file.dialogKey || file.pageKey;
|
|
1199
|
-
if (!key) return;
|
|
1200
|
-
const content = currentInputMap.get(key);
|
|
1201
|
-
if (!content) return;
|
|
1202
|
-
if (isGroup) {
|
|
1203
|
-
output += `### Document: "${file.name}"
|
|
1204
|
-
${content}
|
|
1205
|
-
`;
|
|
1206
|
-
} else {
|
|
1207
|
-
output += `${content}
|
|
1208
|
-
`;
|
|
1209
|
-
}
|
|
1210
|
-
});
|
|
1211
|
-
output += `--- End of Source ${sourceCounter} ---
|
|
1212
|
-
|
|
1213
|
-
`;
|
|
1214
|
-
sourceCounter++;
|
|
1215
|
-
});
|
|
1216
|
-
return output;
|
|
1217
|
-
};
|
|
1218
|
-
var validateAccessAndBalance = (agentConfig, state) => {
|
|
1219
|
-
const userBalance = selectIdentityUserBalance(state);
|
|
1220
|
-
const currentUserId = selectIdentityUserId(state);
|
|
1221
|
-
const isCustomApi = agentConfig.apiSource === "custom";
|
|
1222
|
-
const isCliApi = agentConfig.apiSource === "cli";
|
|
1223
|
-
const isDeviceLocalOwner = agentConfig.userId === "local" && !currentUserId;
|
|
1224
|
-
const isOwner = isDeviceLocalOwner || Boolean(currentUserId) && agentConfig.userId === currentUserId;
|
|
1225
|
-
if (!isOwner) {
|
|
1226
|
-
const hasWhitelist = Array.isArray(agentConfig.whitelist) && agentConfig.whitelist.length > 0;
|
|
1227
|
-
if (hasWhitelist) {
|
|
1228
|
-
const isUserInWhitelist = !!currentUserId && agentConfig.whitelist?.includes(currentUserId);
|
|
1229
|
-
if (!isUserInWhitelist) {
|
|
1230
|
-
return "\u60A8\u4E0D\u5728\u8BE5\u5E94\u7528\u7684\u767D\u540D\u5355\u4E2D\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002";
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
if (isCustomApi || isCliApi) {
|
|
1235
|
-
return null;
|
|
1236
|
-
}
|
|
1237
|
-
const SUBSCRIPTION_OAUTH_REFS = /* @__PURE__ */ new Set([
|
|
1238
|
-
"cursor",
|
|
1239
|
-
"chatgpt",
|
|
1240
|
-
"xai",
|
|
1241
|
-
"antigravity",
|
|
1242
|
-
"claude"
|
|
1243
|
-
]);
|
|
1244
|
-
if (SUBSCRIPTION_OAUTH_REFS.has((agentConfig.apiKeyRef ?? "").trim().toLowerCase())) {
|
|
1245
|
-
return null;
|
|
1246
|
-
}
|
|
1247
|
-
const isPlatformApi = agentConfig.apiSource === "platform" || agentConfig.useServerProxy === true;
|
|
1248
|
-
if (isDeviceLocalOwner && !isPlatformApi) {
|
|
1249
|
-
return null;
|
|
1250
|
-
}
|
|
1251
|
-
if (typeof userBalance !== "number") {
|
|
1252
|
-
const hasSessionUser = Boolean(
|
|
1253
|
-
state?.auth?.currentUser?.userId
|
|
1254
|
-
);
|
|
1255
|
-
if (!currentUserId || !hasSessionUser) {
|
|
1256
|
-
return "\u8BF7\u767B\u5F55\u540E\u4F7F\u7528\u5E73\u53F0\u6A21\u578B\uFF0C\u6216\u6539\u7528\u672C\u5730\u81EA\u5B9A\u4E49/API/CLI Agent\u3002";
|
|
1257
|
-
}
|
|
1258
|
-
return "\u6B63\u5728\u83B7\u53D6\u7528\u6237\u4F59\u989D\uFF0C\u8BF7\u7A0D\u5019...";
|
|
1259
|
-
}
|
|
1260
|
-
const serverPrices = getModelPricing(agentConfig.provider || "", agentConfig.model);
|
|
1261
|
-
if (!serverPrices && !hasExplicitAgentPricing(agentConfig)) {
|
|
1262
|
-
return "\u65E0\u6CD5\u83B7\u53D6\u6A21\u578B\u5B9A\u4EF7\u4FE1\u606F\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
|
|
1263
|
-
}
|
|
1264
|
-
const prices = getPrices(agentConfig, serverPrices ?? null);
|
|
1265
|
-
const maxPrice = getFinalPrice(prices);
|
|
1266
|
-
if (userBalance < maxPrice) {
|
|
1267
|
-
return "\u4F59\u989D\u4E0D\u8DB3\uFF0C\u8BF7\u5145\u503C\u540E\u518D\u8BD5\u3002";
|
|
1268
|
-
}
|
|
1269
|
-
return null;
|
|
1270
|
-
};
|
|
1271
|
-
var fetchMemoryOverlayContext = async (state, agentConfig, userInput, dialogConfig) => {
|
|
1272
|
-
const token = typeof state?.auth?.currentToken === "string" ? state.auth.currentToken : null;
|
|
1273
|
-
const currentServer = typeof state?.settings?.currentServer === "string" ? state.settings.currentServer : null;
|
|
1274
|
-
const agentKey = asOptionalTrimmedString(agentConfig.dbKey) ?? "";
|
|
1275
|
-
if (!token || !currentServer || !agentKey) return null;
|
|
1276
|
-
const baseUrl = resolveToolBaseUrl(currentServer);
|
|
1277
|
-
if (!baseUrl) return null;
|
|
1278
|
-
const inputText = typeof userInput === "string" ? userInput : JSON.stringify(userInput ?? "");
|
|
1279
|
-
const spaceId = asOptionalTrimmedString(dialogConfig?.spaceId) ?? (state?.space?.viewMode === "all" ? void 0 : asOptionalTrimmedString(state?.space?.currentSpaceId));
|
|
1280
|
-
try {
|
|
1281
|
-
const response = await fetch(`${baseUrl}/api/memory/query`, {
|
|
1282
|
-
method: "POST",
|
|
1283
|
-
headers: {
|
|
1284
|
-
"Content-Type": "application/json",
|
|
1285
|
-
Authorization: `Bearer ${token}`
|
|
1286
|
-
},
|
|
1287
|
-
body: JSON.stringify({
|
|
1288
|
-
agentKey,
|
|
1289
|
-
userInput: inputText,
|
|
1290
|
-
...spaceId ? { spaceId } : {}
|
|
1291
|
-
})
|
|
1292
|
-
});
|
|
1293
|
-
if (!response.ok) return null;
|
|
1294
|
-
const payload = await response.json().catch(() => null);
|
|
1295
|
-
return asOptionalTrimmedString(payload?.promptBlock) ?? null;
|
|
1296
|
-
} catch {
|
|
1297
|
-
return null;
|
|
1298
|
-
}
|
|
1299
|
-
};
|
|
1300
|
-
var buildStaticContexts = async (state, dispatch, agentConfig, dialogConfig, referenceContentCache) => {
|
|
1301
|
-
const keySets = await getFullChatContextKeys(
|
|
1302
|
-
state,
|
|
1303
|
-
dispatch,
|
|
1304
|
-
agentConfig,
|
|
1305
|
-
"",
|
|
1306
|
-
// 静态上下文不需要 userInput
|
|
1307
|
-
void 0
|
|
1308
|
-
// 静态上下文不需要 dialogConfig
|
|
1309
|
-
);
|
|
1310
|
-
const finalKeys = deduplicateContextKeys(keySets);
|
|
1311
|
-
const fetchReferences = (keys) => fetchReferenceContents(keys, dispatch, {
|
|
1312
|
-
format: "simplified_markdown",
|
|
1313
|
-
inlineMentionMeta: true,
|
|
1314
|
-
preloaded: referenceContentCache
|
|
1315
|
-
});
|
|
1316
|
-
const [botInstructionsMap, botKnowledgeMap] = await Promise.all([
|
|
1317
|
-
fetchReferences(finalKeys.botInstructionsContext),
|
|
1318
|
-
fetchReferences(finalKeys.botKnowledgeContext)
|
|
1319
|
-
]);
|
|
1320
|
-
const globalPrompt = selectGlobalPrompt(state);
|
|
1321
|
-
const userTonePreset = selectUserTonePreset(state);
|
|
1322
|
-
const knowledgeCaptureLevel = selectKnowledgeCaptureLevel(state);
|
|
1323
|
-
const spaceContextLevel = selectSpaceContextLevel(state);
|
|
1324
|
-
const userRecentLimit = selectAiRecentContentLimit(state);
|
|
1325
|
-
const contextWindow = getModelContextWindow(agentConfig.model) || 128e3;
|
|
1326
|
-
const preloadPlan = resolveSpaceContextPreloadPlan(spaceContextLevel);
|
|
1327
|
-
const dynamicLimit = Math.floor(contextWindow * preloadPlan.preloadBudgetRatio / 150);
|
|
1328
|
-
const recentLimit = preloadPlan.includeRecentContent ? Math.max(3, Math.min(userRecentLimit, Math.max(3, dynamicLimit))) : 0;
|
|
1329
|
-
const turnContextSource = createDbSliceTurnContextSource(dispatch);
|
|
1330
|
-
let spaceContext = null;
|
|
1331
|
-
if (spaceContextLevel > 1) {
|
|
1332
|
-
const spaceLayer = await buildSpaceContextLayer({
|
|
1333
|
-
source: turnContextSource,
|
|
1334
|
-
spaceId: dialogConfig?.spaceId,
|
|
1335
|
-
recentContentLimit: recentLimit
|
|
1336
|
-
});
|
|
1337
|
-
spaceContext = spaceLayer ? spaceLayer.content.trim() : null;
|
|
1338
|
-
}
|
|
1339
|
-
const linkedSpaceIds = agentConfig.linkedSpaces || [];
|
|
1340
|
-
if (linkedSpaceIds.length > 0 && spaceContextLevel > 1) {
|
|
1341
|
-
const linkedSection = await buildLinkedSpacesSection({
|
|
1342
|
-
source: turnContextSource,
|
|
1343
|
-
linkedSpaceIds
|
|
1344
|
-
});
|
|
1345
|
-
if (linkedSection) {
|
|
1346
|
-
spaceContext = (spaceContext ?? "") + `
|
|
1347
|
-
|
|
1348
|
-
${linkedSection}`;
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
const dialogPolicyContext = dialogConfig?.category === PERSONALIZATION_DIALOG_CATEGORY ? buildPersonalizationDialogPolicyContext() : null;
|
|
1352
|
-
return {
|
|
1353
|
-
botInstructionsContext: joinMapValues(botInstructionsMap),
|
|
1354
|
-
botKnowledgeContext: joinMapValues(botKnowledgeMap),
|
|
1355
|
-
spaceContext,
|
|
1356
|
-
userGlobalPrompt: globalPrompt,
|
|
1357
|
-
userPolicyContext: [
|
|
1358
|
-
buildStaticUserPolicyContext({
|
|
1359
|
-
agentConfig,
|
|
1360
|
-
settingsRecord: {
|
|
1361
|
-
userTonePreset,
|
|
1362
|
-
knowledgeCaptureLevel,
|
|
1363
|
-
spaceContextLevel,
|
|
1364
|
-
enableReadCurrentSpace: spaceContextLevel > 1
|
|
1365
|
-
}
|
|
1366
|
-
}),
|
|
1367
|
-
dialogPolicyContext
|
|
1368
|
-
].filter(Boolean).join("\n")
|
|
1369
|
-
};
|
|
1370
|
-
};
|
|
1371
|
-
var buildDynamicContexts = async (state, dispatch, agentConfig, userInput, runtimeOptions, referenceContentCache, dialogKey) => {
|
|
1372
|
-
let dialogSummary = null;
|
|
1373
|
-
let dialogConfig;
|
|
1374
|
-
if (dialogKey) {
|
|
1375
|
-
dialogConfig = selectById(state, dialogKey);
|
|
1376
|
-
if (dialogConfig?.summary) {
|
|
1377
|
-
dialogSummary = dialogConfig.summary;
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
const keySets = await getFullChatContextKeys(
|
|
1381
|
-
state,
|
|
1382
|
-
dispatch,
|
|
1383
|
-
agentConfig,
|
|
1384
|
-
userInput,
|
|
1385
|
-
dialogConfig
|
|
1386
|
-
);
|
|
1387
|
-
const finalKeys = deduplicateContextKeys(keySets);
|
|
1388
|
-
const fetchReferences = (keys) => fetchReferenceContents(keys, dispatch, {
|
|
1389
|
-
format: "simplified_markdown",
|
|
1390
|
-
inlineMentionMeta: true,
|
|
1391
|
-
preloaded: referenceContentCache
|
|
1392
|
-
});
|
|
1393
|
-
const [currentInputMap, historyMap] = await Promise.all([
|
|
1394
|
-
fetchReferences(finalKeys.currentInputContext),
|
|
1395
|
-
fetchReferences(finalKeys.historyContext)
|
|
1396
|
-
]);
|
|
1397
|
-
const pendingFiles = selectPendingFiles(state);
|
|
1398
|
-
const formattedCurrentInputContext = formatCurrentInputContext(
|
|
1399
|
-
pendingFiles,
|
|
1400
|
-
currentInputMap
|
|
1401
|
-
);
|
|
1402
|
-
const dialogId = dialogConfig?.id ?? null;
|
|
1403
|
-
const currentDialogMessages = selectAllMsgs(state, dialogId);
|
|
1404
|
-
const currentDialogMessageIds = new Set(currentDialogMessages.map((msg) => msg.id));
|
|
1405
|
-
const currentDialogToolRuns = getAllToolRuns().filter(
|
|
1406
|
-
(run) => currentDialogMessageIds.has(run.messageId)
|
|
1407
|
-
);
|
|
1408
|
-
const editingContext = buildEditingContextSummary(state, runtimeOptions);
|
|
1409
|
-
const appWorkingMemory = buildRecentAppToolMemory(
|
|
1410
|
-
currentDialogMessages,
|
|
1411
|
-
currentDialogToolRuns
|
|
1412
|
-
);
|
|
1413
|
-
const memoryOverlay = await fetchMemoryOverlayContext(
|
|
1414
|
-
state,
|
|
1415
|
-
agentConfig,
|
|
1416
|
-
userInput,
|
|
1417
|
-
dialogConfig
|
|
1418
|
-
);
|
|
1419
|
-
return {
|
|
1420
|
-
currentInputContext: formattedCurrentInputContext.trim() || null,
|
|
1421
|
-
historyContext: joinMapValues(historyMap),
|
|
1422
|
-
editingContext,
|
|
1423
|
-
appWorkingMemory,
|
|
1424
|
-
memoryOverlay,
|
|
1425
|
-
dialogSummary,
|
|
1426
|
-
referenceKeys: dialogConfig?.referenceKeys || []
|
|
1427
|
-
};
|
|
1428
|
-
};
|
|
1429
|
-
var mergeContexts = (staticCtx, dynamicCtx) => ({
|
|
1430
|
-
botInstructionsContext: staticCtx.botInstructionsContext || void 0,
|
|
1431
|
-
botKnowledgeContext: staticCtx.botKnowledgeContext || void 0,
|
|
1432
|
-
spaceContext: staticCtx.spaceContext || void 0,
|
|
1433
|
-
userGlobalPrompt: staticCtx.userGlobalPrompt || void 0,
|
|
1434
|
-
userPolicyContext: staticCtx.userPolicyContext || void 0,
|
|
1435
|
-
currentInputContext: dynamicCtx.currentInputContext,
|
|
1436
|
-
historyContext: dynamicCtx.historyContext || void 0,
|
|
1437
|
-
editingContext: dynamicCtx.editingContext,
|
|
1438
|
-
appWorkingMemory: dynamicCtx.appWorkingMemory,
|
|
1439
|
-
memoryOverlay: dynamicCtx.memoryOverlay,
|
|
1440
|
-
dialogSummary: dynamicCtx.dialogSummary,
|
|
1441
|
-
referenceKeys: dynamicCtx.referenceKeys
|
|
1442
|
-
});
|
|
1443
|
-
var mergeAgentToolsWithRuntime = (agentConfig, referencedTools, mentionedTools, runtimeOptions, state) => {
|
|
1444
|
-
const rawBaseTools = Array.isArray(agentConfig.tools) ? agentConfig.tools : [];
|
|
1445
|
-
const agentEnabledPacks = resolveAgentRequiredPackIds(agentConfig);
|
|
1446
|
-
const isInlineArtifact = isInlineVisualArtifactAgent(agentConfig);
|
|
1447
|
-
const effectiveEnabledPacks = resolveEffectiveEnabledPacks({
|
|
1448
|
-
enabledPacks: agentEnabledPacks,
|
|
1449
|
-
declaredOnly: isInlineArtifact
|
|
1450
|
-
});
|
|
1451
|
-
const expandedPackTools = expandEnabledPacks(
|
|
1452
|
-
effectiveEnabledPacks,
|
|
1453
|
-
rawBaseTools
|
|
1454
|
-
);
|
|
1455
|
-
const baseTools = canonicalizeToolNames(expandedPackTools);
|
|
1456
|
-
const requiredSkillTools = canonicalizeToolNames(
|
|
1457
|
-
agentConfig.referencedTools ?? []
|
|
1458
|
-
);
|
|
1459
|
-
const recommendedSkillTools = canonicalizeToolNames(
|
|
1460
|
-
agentConfig.recommendedSkillTools ?? []
|
|
1461
|
-
);
|
|
1462
|
-
const recommendedSkillHints = [
|
|
1463
|
-
.../* @__PURE__ */ new Set([
|
|
1464
|
-
...asNonEmptyStringArray(agentConfig.recommendedSkillHints),
|
|
1465
|
-
...resolveAgentRecommendedSkillNames(agentConfig)
|
|
1466
|
-
])
|
|
1467
|
-
];
|
|
1468
|
-
const skillPromptPatches = [
|
|
1469
|
-
.../* @__PURE__ */ new Set([
|
|
1470
|
-
...asNonEmptyStringArray(agentConfig.skillPromptPatches),
|
|
1471
|
-
// 能力包的 promptPatch(方法论文档)与 skill reference 的 patch 走同一条
|
|
1472
|
-
// 注入链(buildSkillGuidanceBlock → buildSkillGuidancePromptBlock),
|
|
1473
|
-
// 让「工具 + 配套纪律」作为一个能力包整体注入 system prompt。
|
|
1474
|
-
...expandEnabledPackPromptPatches(effectiveEnabledPacks)
|
|
1475
|
-
])
|
|
1476
|
-
];
|
|
1477
|
-
const webPadded = applyDefaultWebToolPacks({
|
|
1478
|
-
toolNames: baseTools,
|
|
1479
|
-
skipWeb: isInlineVisualArtifactAgent(agentConfig)
|
|
1480
|
-
});
|
|
1481
|
-
const enhancedTools = /* @__PURE__ */ new Set([
|
|
1482
|
-
...webPadded,
|
|
1483
|
-
...isInlineVisualArtifactAgent(agentConfig) ? [] : getRuntimeCoreTools(),
|
|
1484
|
-
...isInlineVisualArtifactAgent(agentConfig) ? [] : requiredSkillTools,
|
|
1485
|
-
...isInlineVisualArtifactAgent(agentConfig) ? [] : canonicalizeToolNames(referencedTools),
|
|
1486
|
-
...isInlineVisualArtifactAgent(agentConfig) ? [] : canonicalizeToolNames(mentionedTools)
|
|
1487
|
-
]);
|
|
1488
|
-
const extraTools = isInlineVisualArtifactAgent(agentConfig) ? [] : canonicalizeToolNames(runtimeOptions?.extraTools ?? []);
|
|
1489
|
-
for (const t of extraTools) {
|
|
1490
|
-
enhancedTools.add(t);
|
|
1491
|
-
}
|
|
1492
|
-
if (!isInlineVisualArtifactAgent(agentConfig)) {
|
|
1493
|
-
const viewMode = state ? selectViewMode(state) : "categories";
|
|
1494
|
-
if (viewMode === "all") {
|
|
1495
|
-
enhancedTools.delete("search_workspace");
|
|
1496
|
-
if (!recommendedSkillHints.includes("search-all-spaces")) {
|
|
1497
|
-
recommendedSkillHints.push("search-all-spaces");
|
|
1498
|
-
}
|
|
1499
|
-
} else {
|
|
1500
|
-
enhancedTools.add("search_workspace");
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
const systemBuiltinSkills = state?.settings?.systemBuiltinSkills;
|
|
1504
|
-
const mountedTools = isInlineVisualArtifactAgent(agentConfig) ? Array.from(enhancedTools) : addDefaultSystemCapabilityTools(Array.from(enhancedTools));
|
|
1505
|
-
const filteredTools = applySystemBuiltinSkillFilter(
|
|
1506
|
-
mountedTools,
|
|
1507
|
-
systemBuiltinSkills
|
|
1508
|
-
);
|
|
1509
|
-
return {
|
|
1510
|
-
...agentConfig,
|
|
1511
|
-
tools: applyDisabledTools(
|
|
1512
|
-
prioritizeToolNames(
|
|
1513
|
-
filteredTools,
|
|
1514
|
-
recommendedSkillTools
|
|
1515
|
-
),
|
|
1516
|
-
agentConfig?.disabledTools
|
|
1517
|
-
),
|
|
1518
|
-
recommendedSkillTools,
|
|
1519
|
-
recommendedSkillHints,
|
|
1520
|
-
skillPromptPatches
|
|
1521
|
-
};
|
|
1522
|
-
};
|
|
1523
|
-
var applyImageConfigRuntimeOverride = (agentConfig, runtimeOptions) => {
|
|
1524
|
-
const override = runtimeOptions?.imageConfigOverride;
|
|
1525
|
-
if (!override) {
|
|
1526
|
-
return agentConfig;
|
|
1527
|
-
}
|
|
1528
|
-
const baseImageConfig = agentConfig.imageConfig ?? {};
|
|
1529
|
-
return {
|
|
1530
|
-
...agentConfig,
|
|
1531
|
-
...override.imageModelOverride ? { model: override.imageModelOverride } : {},
|
|
1532
|
-
imageConfig: {
|
|
1533
|
-
...baseImageConfig,
|
|
1534
|
-
...override
|
|
1535
|
-
}
|
|
1536
|
-
};
|
|
1537
|
-
};
|
|
1538
|
-
var formatImageWaitHint = (range) => {
|
|
1539
|
-
if (!range || typeof range.min !== "number" || typeof range.max !== "number") {
|
|
1540
|
-
return void 0;
|
|
1541
|
-
}
|
|
1542
|
-
return `\u901A\u5E38\u9700\u8981 ${range.min}-${range.max} \u79D2`;
|
|
1543
|
-
};
|
|
1544
|
-
var resolveAgentImageModelIdentity = (agentConfig) => {
|
|
1545
|
-
let providerKey = (agentConfig.provider || "").toLowerCase();
|
|
1546
|
-
let modelName = agentConfig.model ?? "";
|
|
1547
|
-
if (modelName.includes("/")) {
|
|
1548
|
-
const slash = modelName.indexOf("/");
|
|
1549
|
-
if (!providerKey) providerKey = modelName.slice(0, slash);
|
|
1550
|
-
modelName = modelName.slice(slash + 1);
|
|
1551
|
-
}
|
|
1552
|
-
try {
|
|
1553
|
-
return {
|
|
1554
|
-
providerKey,
|
|
1555
|
-
modelConfig: getModelConfig(providerKey, modelName)
|
|
1556
|
-
};
|
|
1557
|
-
} catch {
|
|
1558
|
-
try {
|
|
1559
|
-
const detected = getProviderByModelName(modelName);
|
|
1560
|
-
if (!detected) {
|
|
1561
|
-
return { providerKey, modelConfig: null };
|
|
1562
|
-
}
|
|
1563
|
-
return {
|
|
1564
|
-
providerKey: detected,
|
|
1565
|
-
modelConfig: getModelConfig(detected, modelName)
|
|
1566
|
-
};
|
|
1567
|
-
} catch {
|
|
1568
|
-
return { providerKey, modelConfig: null };
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
};
|
|
1572
|
-
var EXPLICIT_IMAGE_GENERATION_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1573
|
-
"openAIGptImage",
|
|
1574
|
-
"openAIGptImageGenerate",
|
|
1575
|
-
"openAIGptImageEdit",
|
|
1576
|
-
"chatgptWebImageGenerate",
|
|
1577
|
-
"geminiFlashImage",
|
|
1578
|
-
"geminiProImagePreview"
|
|
1579
|
-
]);
|
|
1580
|
-
var agentUsesExplicitImageGenerationTool = (agentConfig) => {
|
|
1581
|
-
const toolNames = Array.isArray(agentConfig.tools) ? agentConfig.tools : Array.isArray(agentConfig.toolNames) ? agentConfig.toolNames : [];
|
|
1582
|
-
return toolNames.some(
|
|
1583
|
-
(name) => typeof name === "string" && EXPLICIT_IMAGE_GENERATION_TOOL_NAMES.has(name.trim())
|
|
1584
|
-
);
|
|
1585
|
-
};
|
|
1586
|
-
var resolveImageGenerationStreamingState = (agentConfig, args) => {
|
|
1587
|
-
const { modelConfig } = resolveAgentImageModelIdentity(agentConfig);
|
|
1588
|
-
const hasImageOutput = !!(modelConfig?.hasImageOutput ?? modelConfig?.supportsImageOutput) || agentConfig.imageConfig?.enabled === true || agentUsesExplicitImageGenerationTool(agentConfig);
|
|
1589
|
-
if (!hasImageOutput) {
|
|
1590
|
-
return void 0;
|
|
1591
|
-
}
|
|
1592
|
-
const currentProfile = modelConfig?.imageGenerationProfiles?.find(
|
|
1593
|
-
(profile) => profile.imageModel === modelConfig.name
|
|
1594
|
-
);
|
|
1595
|
-
const usesWebImageTool = agentUsesExplicitImageGenerationTool(agentConfig) && (Array.isArray(agentConfig.tools) ? agentConfig.tools : []).includes("chatgptWebImageGenerate");
|
|
1596
|
-
return {
|
|
1597
|
-
kind: "image_generation",
|
|
1598
|
-
stage: args?.stage ?? args?.previous?.stage ?? "submitted",
|
|
1599
|
-
startedAt: args?.previous?.startedAt ?? Date.now(),
|
|
1600
|
-
waitHint: formatImageWaitHint(modelConfig?.imageGenerationWaitTimeSeconds) ?? (usesWebImageTool ? "\u7F51\u9875\u751F\u56FE\u901A\u5E38\u9700\u8981 30 \u79D2\u5230\u51E0\u5206\u949F\uFF0C\u5207\u6362\u5BF9\u8BDD\u4E0D\u4F1A\u4E2D\u65AD" : "\u901A\u5E38\u9700\u8981\u51E0\u5341\u79D2"),
|
|
1601
|
-
profileLabel: currentProfile?.label
|
|
1602
|
-
};
|
|
1603
|
-
};
|
|
1604
|
-
|
|
1605
|
-
// packages/ai/agent/imagePreprocessing.ts
|
|
1606
|
-
var DEFAULT_IMAGE_PREPROCESSOR_AGENT_KEY = PUBLIC_QWEN_37_FLASH_AGENT_KEY;
|
|
1607
|
-
var DESCRIBE_IMAGE_PROMPT = `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u56FE\u7247\u63CF\u8FF0\u52A9\u624B\u3002\u8BF7\u6781\u5176\u8BE6\u7EC6\u5730\u63CF\u8FF0\u8FD9\u5F20\u56FE\u7247\uFF0C\u76EE\u6807\u662F\u8BA9\u4E00\u4E2A\u770B\u4E0D\u5230\u56FE\u7247\u7684 AI \u52A9\u624B\u80FD\u5B8C\u5168\u7406\u89E3\u56FE\u7247\u5185\u5BB9\u3002
|
|
1608
|
-
|
|
1609
|
-
\u8BF7\u6309\u4EE5\u4E0B\u7ED3\u6784\u63CF\u8FF0\uFF1A
|
|
1610
|
-
|
|
1611
|
-
1. **\u56FE\u7247\u7C7B\u578B**\uFF1A\u8FD9\u662F\u754C\u9762\u622A\u56FE\u3001\u7167\u7247\u3001\u56FE\u8868\u3001\u6587\u6863\u3001\u8FD8\u662F\u5176\u4ED6\u7C7B\u578B\uFF1F
|
|
1612
|
-
|
|
1613
|
-
2. **\u5982\u679C\u662F\u754C\u9762\u622A\u56FE**\uFF1A
|
|
1614
|
-
- \u5217\u51FA\u6240\u6709\u53EF\u89C1\u7684 UI \u5143\u7D20\uFF1A\u6807\u9898\u680F\u3001\u5BFC\u822A\u83DC\u5355\u3001\u6309\u94AE\u3001\u8F93\u5165\u6846\u3001\u5217\u8868\u9879\u7B49
|
|
1615
|
-
- \u9010\u4E2A\u63CF\u8FF0\u6BCF\u4E2A\u5143\u7D20\u7684\u6587\u5B57\u5185\u5BB9\u548C\u4F4D\u7F6E\uFF08\u5982"\u5DE6\u4E0A\u89D2"\u3001"\u53F3\u4FA7\u680F"\uFF09
|
|
1616
|
-
- \u63CF\u8FF0\u989C\u8272\u4E3B\u9898\u3001\u5E03\u5C40\u7ED3\u6784\u3001\u5F53\u524D\u72B6\u6001\uFF08\u5982\u9009\u4E2D\u3001hover\u3001loading\uFF09
|
|
1617
|
-
- \u5982\u679C\u6709\u5F39\u7A97/\u5BF9\u8BDD\u6846/\u901A\u77E5\uFF0C\u5B8C\u6574\u8BB0\u5F55\u5176\u6587\u5B57\u5185\u5BB9
|
|
1618
|
-
|
|
1619
|
-
3. **\u5982\u679C\u662F\u751F\u6D3B\u7167\u7247**\uFF1A
|
|
1620
|
-
- \u573A\u666F/\u73AF\u5883\uFF1A\u5BA4\u5185/\u5BA4\u5916\u3001\u5730\u70B9\u7C7B\u578B\u3001\u65F6\u95F4\u611F\uFF08\u767D\u5929/\u591C\u665A\uFF09
|
|
1621
|
-
- \u4EBA\u7269\uFF1A\u4EBA\u6570\u3001\u59FF\u52BF\u3001\u8868\u60C5\u3001\u7A7F\u7740\u3001\u52A8\u4F5C
|
|
1622
|
-
- \u7269\u4F53\uFF1A\u524D\u666F/\u80CC\u666F\u4E2D\u7684\u6240\u6709\u663E\u8457\u7269\u4F53
|
|
1623
|
-
- \u5149\u7EBF\u3001\u5929\u6C14\u3001\u6C1B\u56F4
|
|
1624
|
-
|
|
1625
|
-
4. **\u5982\u679C\u662F\u56FE\u8868/\u6570\u636E\u56FE**\uFF1A
|
|
1626
|
-
- \u56FE\u8868\u7C7B\u578B\uFF08\u67F1\u72B6\u56FE/\u6298\u7EBF\u56FE/\u997C\u56FE\u7B49\uFF09
|
|
1627
|
-
- \u5750\u6807\u8F74\u6807\u7B7E\u3001\u6570\u503C\u8303\u56F4\u3001\u5355\u4F4D
|
|
1628
|
-
- \u5173\u952E\u6570\u636E\u70B9\u548C\u8D8B\u52BF
|
|
1629
|
-
- \u56FE\u4F8B\u3001\u6807\u9898
|
|
1630
|
-
|
|
1631
|
-
5. **\u6240\u6709\u53EF\u89C1\u6587\u5B57**\uFF1A\u9010\u5B57\u8BB0\u5F55\u56FE\u7247\u4E2D\u51FA\u73B0\u7684\u6240\u6709\u6587\u5B57\uFF08UI \u6587\u5B57\u3001\u8DEF\u724C\u3001\u6807\u7B7E\u3001\u6C34\u5370\u7B49\uFF09\uFF0C\u4FDD\u7559\u539F\u6587\u3002
|
|
1632
|
-
|
|
1633
|
-
6. **\u989C\u8272\u548C\u5E03\u5C40**\uFF1A\u4E3B\u8272\u8C03\u3001\u5E03\u5C40\u7ED3\u6784\u3001\u7A7A\u95F4\u5173\u7CFB\u3002
|
|
1634
|
-
|
|
1635
|
-
\u8BF7\u5C3D\u53EF\u80FD\u8BE6\u7EC6\uFF0C\u4E0D\u8981\u9057\u6F0F\u4EFB\u4F55\u53EF\u89C1\u4FE1\u606F\u3002`;
|
|
1636
|
-
function extractImageUrlsFromMessages(messages) {
|
|
1637
|
-
const urls = [];
|
|
1638
|
-
for (const msg of messages) {
|
|
1639
|
-
if (!Array.isArray(msg.content)) continue;
|
|
1640
|
-
for (const part of msg.content) {
|
|
1641
|
-
if (part && typeof part === "object" && part.type === "image_url" && part.image_url && typeof part.image_url.url === "string" && part.image_url.url.trim()) {
|
|
1642
|
-
urls.push(part.image_url.url);
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
return urls;
|
|
1647
|
-
}
|
|
1648
|
-
function hasImageInRuntimeMessages(messages) {
|
|
1649
|
-
return extractImageUrlsFromMessages(messages).length > 0;
|
|
1650
|
-
}
|
|
1651
|
-
async function preprocessImagesForTextOnlyAgent(messages, describeImage) {
|
|
1652
|
-
const imageUrls = extractImageUrlsFromMessages(messages);
|
|
1653
|
-
if (imageUrls.length === 0) return messages;
|
|
1654
|
-
const description = await describeImage(imageUrls);
|
|
1655
|
-
if (description === null || !description.trim()) return messages;
|
|
1656
|
-
const descriptionText = `[\u56FE\u7247\u63CF\u8FF0] ${description.trim()}`;
|
|
1657
|
-
return messages.map((msg) => {
|
|
1658
|
-
if (!Array.isArray(msg.content)) return msg;
|
|
1659
|
-
const hasImage = msg.content.some((p) => p?.type === "image_url");
|
|
1660
|
-
if (!hasImage) return msg;
|
|
1661
|
-
const newContent = msg.content.map((part) => {
|
|
1662
|
-
if (part && typeof part === "object" && part.type === "image_url") {
|
|
1663
|
-
return { type: "text", text: descriptionText };
|
|
1664
|
-
}
|
|
1665
|
-
return part;
|
|
1666
|
-
}).filter((p) => p !== null && p !== void 0);
|
|
1667
|
-
return { ...msg, content: newContent };
|
|
1668
|
-
});
|
|
1669
|
-
}
|
|
1670
|
-
async function describeImageWithLocalProvider(adapter, imageUrls, visionAgentConfig) {
|
|
1671
|
-
if (imageUrls.length === 0) return null;
|
|
1672
|
-
try {
|
|
1673
|
-
const config = visionAgentConfig ?? resolveBuiltinPlatformAgentConfig(DEFAULT_IMAGE_PREPROCESSOR_AGENT_KEY);
|
|
1674
|
-
if (!config) {
|
|
1675
|
-
console.warn("[imagePreprocessing] vision agent config not found, skipping");
|
|
1676
|
-
return null;
|
|
1677
|
-
}
|
|
1678
|
-
const visionProvider = await adapter.resolveProvider(config);
|
|
1679
|
-
const result = await visionProvider.complete(
|
|
1680
|
-
[{ role: "user", content: buildDescribeContentParts(imageUrls) }],
|
|
1681
|
-
{ timeoutMs: 3e4 }
|
|
1682
|
-
);
|
|
1683
|
-
const text = result.content?.trim();
|
|
1684
|
-
if (!text) return null;
|
|
1685
|
-
return text;
|
|
1686
|
-
} catch (error) {
|
|
1687
|
-
console.warn("[imagePreprocessing] vision describe failed, will fallback:", error);
|
|
1688
|
-
return null;
|
|
1689
|
-
}
|
|
1690
|
-
}
|
|
1691
|
-
async function describeImageViaServerProxy(serverUrl, authToken, imageUrls, visionAgentKey) {
|
|
1692
|
-
if (imageUrls.length === 0) return null;
|
|
1693
|
-
const agentKey = visionAgentKey ?? DEFAULT_IMAGE_PREPROCESSOR_AGENT_KEY;
|
|
1694
|
-
const { model: visionModel, provider: visionProvider } = resolveDefaultVisionModelConfig(agentKey);
|
|
1695
|
-
try {
|
|
1696
|
-
const payload = {
|
|
1697
|
-
model: visionModel,
|
|
1698
|
-
messages: [{ role: "user", content: buildDescribeContentParts(imageUrls) }],
|
|
1699
|
-
stream: false,
|
|
1700
|
-
provider: visionProvider,
|
|
1701
|
-
agentKey,
|
|
1702
|
-
// server proxy 需要 url 字段,但 nolo 平台 agent 的上游由 server 端路由,
|
|
1703
|
-
// 这里放一个占位 url,server 端会根据 provider/model 覆盖。
|
|
1704
|
-
url: "https://api.ollama.com/v1/chat/completions"
|
|
1705
|
-
};
|
|
1706
|
-
const response = await fetch(`${serverUrl}/api/chat`, {
|
|
1707
|
-
method: "POST",
|
|
1708
|
-
headers: {
|
|
1709
|
-
"Content-Type": "application/json",
|
|
1710
|
-
Authorization: `Bearer ${authToken}`
|
|
1711
|
-
},
|
|
1712
|
-
body: JSON.stringify(payload),
|
|
1713
|
-
signal: AbortSignal.timeout(3e4)
|
|
1714
|
-
});
|
|
1715
|
-
if (!response.ok) {
|
|
1716
|
-
console.warn(`[imagePreprocessing] server proxy vision call failed: ${response.status}`);
|
|
1717
|
-
return null;
|
|
1718
|
-
}
|
|
1719
|
-
const data = await response.json();
|
|
1720
|
-
const text = data?.choices?.[0]?.message?.content;
|
|
1721
|
-
if (typeof text === "string" && text.trim()) {
|
|
1722
|
-
return text.trim();
|
|
1723
|
-
}
|
|
1724
|
-
return null;
|
|
1725
|
-
} catch (error) {
|
|
1726
|
-
console.warn("[imagePreprocessing] server proxy vision describe failed:", error);
|
|
1727
|
-
return null;
|
|
1728
|
-
}
|
|
1729
|
-
}
|
|
1730
|
-
function buildDescribeContentParts(imageUrls) {
|
|
1731
|
-
const parts = [{ type: "text", text: DESCRIBE_IMAGE_PROMPT }];
|
|
1732
|
-
for (const url of imageUrls) {
|
|
1733
|
-
parts.push({ type: "image_url", image_url: { url } });
|
|
1734
|
-
}
|
|
1735
|
-
return parts;
|
|
1736
|
-
}
|
|
1737
|
-
function resolveDefaultVisionModelConfig(agentKey) {
|
|
1738
|
-
const key = agentKey ?? DEFAULT_IMAGE_PREPROCESSOR_AGENT_KEY;
|
|
1739
|
-
const config = resolveBuiltinPlatformAgentConfig(key);
|
|
1740
|
-
return {
|
|
1741
|
-
model: config?.model ?? PLATFORM_HOSTED_QWEN_37_FLASH_MODEL,
|
|
1742
|
-
provider: config?.provider ?? "nolo",
|
|
1743
|
-
config
|
|
1744
|
-
};
|
|
1745
|
-
}
|
|
1746
|
-
async function tryPreprocessWebImageOrReject(messages, agentConfig, initialHistoryIds, serverUrl, authToken) {
|
|
1747
|
-
const rejectReason = shouldRejectImageInputForAgent(
|
|
1748
|
-
agentConfig,
|
|
1749
|
-
messages
|
|
1750
|
-
);
|
|
1751
|
-
if (!rejectReason) {
|
|
1752
|
-
const firstDynamicIdx = messages.findIndex((m) => m.id && !initialHistoryIds.has(m.id));
|
|
1753
|
-
const splitIdx2 = firstDynamicIdx === -1 ? messages.length : firstDynamicIdx;
|
|
1754
|
-
return {
|
|
1755
|
-
kind: "ok",
|
|
1756
|
-
messages,
|
|
1757
|
-
stableMessages: messages.slice(0, splitIdx2),
|
|
1758
|
-
dynamicMessages: messages.slice(splitIdx2)
|
|
1759
|
-
};
|
|
1760
|
-
}
|
|
1761
|
-
if (!serverUrl || !authToken) {
|
|
1762
|
-
return { kind: "reject", reason: rejectReason };
|
|
1763
|
-
}
|
|
1764
|
-
const preprocessed = await preprocessImagesForTextOnlyAgent(
|
|
1765
|
-
messages,
|
|
1766
|
-
(urls) => describeImageViaServerProxy(serverUrl, authToken, urls)
|
|
1767
|
-
);
|
|
1768
|
-
if (preprocessed === messages) {
|
|
1769
|
-
return { kind: "reject", reason: rejectReason };
|
|
1770
|
-
}
|
|
1771
|
-
const newMessages = preprocessed;
|
|
1772
|
-
const newFirstDynamicIdx = newMessages.findIndex((m) => m.id && !initialHistoryIds.has(m.id));
|
|
1773
|
-
const splitIdx = newFirstDynamicIdx === -1 ? newMessages.length : newFirstDynamicIdx;
|
|
1774
|
-
return {
|
|
1775
|
-
kind: "ok",
|
|
1776
|
-
messages: newMessages,
|
|
1777
|
-
stableMessages: newMessages.slice(0, splitIdx),
|
|
1778
|
-
dynamicMessages: newMessages.slice(splitIdx)
|
|
1779
|
-
};
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
// packages/agent-runtime/toolCallPairing.ts
|
|
1783
|
-
function readToolCallId(message) {
|
|
1784
|
-
if (typeof message.tool_call_id === "string" && message.tool_call_id) {
|
|
1785
|
-
return message.tool_call_id;
|
|
1786
|
-
}
|
|
1787
|
-
if (typeof message.toolCallId === "string" && message.toolCallId) {
|
|
1788
|
-
return message.toolCallId;
|
|
1789
|
-
}
|
|
1790
|
-
return void 0;
|
|
1791
|
-
}
|
|
1792
|
-
function isContentBlank(content) {
|
|
1793
|
-
if (content == null) return true;
|
|
1794
|
-
if (typeof content === "string") return content.trim().length === 0;
|
|
1795
|
-
if (Array.isArray(content)) {
|
|
1796
|
-
if (content.length === 0) return true;
|
|
1797
|
-
return !content.some((part) => {
|
|
1798
|
-
if (part == null || typeof part !== "object") return false;
|
|
1799
|
-
const p = part;
|
|
1800
|
-
if (p.type === "text") return typeof p.text === "string" && p.text.trim().length > 0;
|
|
1801
|
-
if (p.type === "image_url") {
|
|
1802
|
-
const url = p.image_url?.url;
|
|
1803
|
-
return typeof url === "string" && url.trim().length > 0;
|
|
1804
|
-
}
|
|
1805
|
-
return true;
|
|
1806
|
-
});
|
|
1807
|
-
}
|
|
1808
|
-
return false;
|
|
1809
|
-
}
|
|
1810
|
-
function sanitizeToolCallPairing(messages) {
|
|
1811
|
-
const assistantIndexByCallId = /* @__PURE__ */ new Map();
|
|
1812
|
-
for (let i = 0; i < messages.length; i += 1) {
|
|
1813
|
-
const m = messages[i];
|
|
1814
|
-
if (m == null) continue;
|
|
1815
|
-
if (m.role !== "assistant") continue;
|
|
1816
|
-
const toolCalls = m.tool_calls;
|
|
1817
|
-
if (!Array.isArray(toolCalls)) continue;
|
|
1818
|
-
for (const call of toolCalls) {
|
|
1819
|
-
const id = call?.id;
|
|
1820
|
-
if (typeof id !== "string" || !id) continue;
|
|
1821
|
-
if (!assistantIndexByCallId.has(id)) {
|
|
1822
|
-
assistantIndexByCallId.set(id, i);
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
const toolByCallId = /* @__PURE__ */ new Map();
|
|
1827
|
-
for (let i = 0; i < messages.length; i += 1) {
|
|
1828
|
-
const m = messages[i];
|
|
1829
|
-
if (m == null) continue;
|
|
1830
|
-
if (m.role !== "tool") continue;
|
|
1831
|
-
const id = readToolCallId(m);
|
|
1832
|
-
if (typeof id !== "string" || !id) continue;
|
|
1833
|
-
if (!toolByCallId.has(id)) {
|
|
1834
|
-
toolByCallId.set(id, m);
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
const output = [];
|
|
1838
|
-
const consumedToolCallIds = /* @__PURE__ */ new Set();
|
|
1839
|
-
for (let i = 0; i < messages.length; i += 1) {
|
|
1840
|
-
const m = messages[i];
|
|
1841
|
-
if (m == null) continue;
|
|
1842
|
-
if (m.role === "tool") continue;
|
|
1843
|
-
if (m.role !== "assistant") {
|
|
1844
|
-
output.push(m);
|
|
1845
|
-
continue;
|
|
1846
|
-
}
|
|
1847
|
-
const toolCalls = m.tool_calls;
|
|
1848
|
-
if (!Array.isArray(toolCalls) || toolCalls.length === 0) {
|
|
1849
|
-
output.push(m);
|
|
1850
|
-
continue;
|
|
1851
|
-
}
|
|
1852
|
-
const matchedToolCalls = [];
|
|
1853
|
-
const matchedToolMessages = [];
|
|
1854
|
-
for (const call of toolCalls) {
|
|
1855
|
-
const id = call?.id;
|
|
1856
|
-
if (typeof id !== "string" || !id) continue;
|
|
1857
|
-
const toolMessage = toolByCallId.get(id);
|
|
1858
|
-
if (!toolMessage) continue;
|
|
1859
|
-
if (assistantIndexByCallId.get(id) !== i) continue;
|
|
1860
|
-
if (consumedToolCallIds.has(id)) continue;
|
|
1861
|
-
matchedToolCalls.push(call);
|
|
1862
|
-
matchedToolMessages.push(toolMessage);
|
|
1863
|
-
consumedToolCallIds.add(id);
|
|
1864
|
-
}
|
|
1865
|
-
if (matchedToolCalls.length === 0) {
|
|
1866
|
-
const { tool_calls: _drop, ...rest } = m;
|
|
1867
|
-
const stripped = rest;
|
|
1868
|
-
if (isContentBlank(stripped.content)) {
|
|
1869
|
-
continue;
|
|
1870
|
-
}
|
|
1871
|
-
output.push(stripped);
|
|
1872
|
-
continue;
|
|
1873
|
-
}
|
|
1874
|
-
const normalizedAssistant = { ...m, tool_calls: matchedToolCalls };
|
|
1875
|
-
output.push(normalizedAssistant);
|
|
1876
|
-
for (const toolMessage of matchedToolMessages) {
|
|
1877
|
-
output.push(toolMessage);
|
|
1878
|
-
}
|
|
1879
|
-
}
|
|
1880
|
-
return output;
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1883
|
-
// packages/agent-runtime/parseToolArguments.ts
|
|
1884
|
-
function parseToolArgumentsJson(raw) {
|
|
1885
|
-
if (!raw?.trim()) return {};
|
|
1886
|
-
try {
|
|
1887
|
-
return asRecordOrEmpty(JSON.parse(raw));
|
|
1888
|
-
} catch {
|
|
1889
|
-
return {};
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
|
|
1893
|
-
// packages/agent-runtime/summarizeToolArguments.ts
|
|
1894
|
-
function clip(value, max = 240) {
|
|
1895
|
-
return clipCompactText(value, max);
|
|
1896
|
-
}
|
|
1897
|
-
function summarizeToolArguments(toolName, rawArgs) {
|
|
1898
|
-
const args = parseToolArgumentsJson(rawArgs);
|
|
1899
|
-
const pick = (...keys2) => {
|
|
1900
|
-
for (const key of keys2) {
|
|
1901
|
-
const value = asOptionalTrimmedString(args[key]);
|
|
1902
|
-
if (value) return value;
|
|
1903
|
-
}
|
|
1904
|
-
return "";
|
|
1905
|
-
};
|
|
1906
|
-
const command = pick("command", "cmd", "runCommand", "executeCommand", "bash");
|
|
1907
|
-
if (command) return clip(command);
|
|
1908
|
-
const query = pick("query", "pattern", "search", "q");
|
|
1909
|
-
if (query) return clip(query);
|
|
1910
|
-
const filePath = pick("filePath", "file_path", "path", "filename", "file");
|
|
1911
|
-
if (filePath) return clip(filePath);
|
|
1912
|
-
const keys = Object.keys(args);
|
|
1913
|
-
if (keys.length === 0) return "";
|
|
1914
|
-
return clip(
|
|
1915
|
-
keys.slice(0, 6).map((key) => {
|
|
1916
|
-
const value = args[key];
|
|
1917
|
-
if (typeof value === "string") return `${key}=${clip(value, 80)}`;
|
|
1918
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
1919
|
-
return `${key}=${String(value)}`;
|
|
1920
|
-
}
|
|
1921
|
-
if (Array.isArray(value)) return `${key}[${value.length}]`;
|
|
1922
|
-
return `${key}=${value === null ? "null" : typeof value}`;
|
|
1923
|
-
}).join(" ")
|
|
1924
|
-
);
|
|
1925
|
-
}
|
|
1926
|
-
|
|
1927
|
-
// packages/agent-runtime/contextBlockScope.ts
|
|
1928
|
-
var isContextBlockScope = (value) => {
|
|
1929
|
-
if (typeof value !== "object" || value === null) return false;
|
|
1930
|
-
const candidate = value;
|
|
1931
|
-
return typeof candidate.content === "string" && (candidate.cacheScope === "session" || candidate.cacheScope === "turn");
|
|
1932
|
-
};
|
|
1933
|
-
var normalizeContextBlockScopes = (legacyBlocks = void 0, scopes = void 0) => {
|
|
1934
|
-
const trimmedScopes = (Array.isArray(scopes) ? scopes : []).filter(isContextBlockScope).map((scope) => ({ content: scope.content.trim(), cacheScope: scope.cacheScope })).filter((scope) => scope.content.length > 0);
|
|
1935
|
-
if (trimmedScopes.length > 0) {
|
|
1936
|
-
return trimmedScopes;
|
|
1937
|
-
}
|
|
1938
|
-
return (Array.isArray(legacyBlocks) ? legacyBlocks : []).filter((block) => typeof block === "string").map((block) => block.trim()).filter((block) => block.length > 0).map((block) => ({ content: block, cacheScope: "turn" }));
|
|
1939
|
-
};
|
|
1940
|
-
|
|
1941
|
-
// packages/agent-runtime/localAutoCompaction.ts
|
|
1942
|
-
function toPlanCompressionMessages(history) {
|
|
1943
|
-
return history.map((message, index) => ({
|
|
1944
|
-
id: `local-${index}`,
|
|
1945
|
-
role: message.role,
|
|
1946
|
-
content: message.content,
|
|
1947
|
-
...Array.isArray(message.tool_calls) ? { tool_calls: message.tool_calls } : {}
|
|
1948
|
-
}));
|
|
1949
|
-
}
|
|
1950
|
-
function buildLocalSummaryHistoryMessage(summary) {
|
|
1951
|
-
const layer = buildDialogSummaryLayer({ summary });
|
|
1952
|
-
return {
|
|
1953
|
-
role: "user",
|
|
1954
|
-
content: layer?.content ?? `--- \u5386\u53F2\u5BF9\u8BDD\u6458\u8981 ---
|
|
1955
|
-
${summary.trim()}`
|
|
1956
|
-
};
|
|
1957
|
-
}
|
|
1958
|
-
function projectHistoryWithSummary(args) {
|
|
1959
|
-
const bridged = toPlanCompressionMessages(args.history);
|
|
1960
|
-
let startIndex = 0;
|
|
1961
|
-
if (args.summarizedBeforeId) {
|
|
1962
|
-
const found = bridged.findIndex((m) => m.id === args.summarizedBeforeId);
|
|
1963
|
-
if (found !== -1) startIndex = found + 1;
|
|
1964
|
-
}
|
|
1965
|
-
return [
|
|
1966
|
-
buildLocalSummaryHistoryMessage(args.summary),
|
|
1967
|
-
...args.history.slice(startIndex)
|
|
1968
|
-
];
|
|
1969
|
-
}
|
|
1970
|
-
var COLD_RESUME_IDLE_MS = 60 * 60 * 1e3;
|
|
1971
|
-
function isColdResume(history, nowMs) {
|
|
1972
|
-
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
1973
|
-
const at = history[i]?.createdAt;
|
|
1974
|
-
if (typeof at === "number" && Number.isFinite(at)) {
|
|
1975
|
-
return nowMs - at > COLD_RESUME_IDLE_MS;
|
|
1976
|
-
}
|
|
1977
|
-
}
|
|
1978
|
-
return false;
|
|
1979
|
-
}
|
|
1980
|
-
async function maybeAutoCompactLocalHistory(args) {
|
|
1981
|
-
const { adapter, dialogId, history } = args;
|
|
1982
|
-
const unchanged = () => ({
|
|
1983
|
-
history,
|
|
1984
|
-
compressed: false,
|
|
1985
|
-
summaryGenerated: false
|
|
1986
|
-
});
|
|
1987
|
-
if (!dialogId || history.length === 0 || typeof adapter.loadDialogSummary !== "function" || typeof adapter.saveDialogSummary !== "function") {
|
|
1988
|
-
return unchanged();
|
|
1989
|
-
}
|
|
1990
|
-
let stored = null;
|
|
1991
|
-
try {
|
|
1992
|
-
stored = await adapter.loadDialogSummary(dialogId);
|
|
1993
|
-
} catch (error) {
|
|
1994
|
-
console.warn("[localLoop] loadDialogSummary failed:", error);
|
|
1995
|
-
return unchanged();
|
|
1996
|
-
}
|
|
1997
|
-
const existingSummary = typeof stored?.summary === "string" ? stored.summary : "";
|
|
1998
|
-
const summarizedBeforeId = typeof stored?.summarizedBeforeId === "string" ? stored.summarizedBeforeId : void 0;
|
|
1999
|
-
const contextWindow = typeof args.contextWindow === "number" && Number.isFinite(args.contextWindow) && args.contextWindow > 0 ? args.contextWindow : getModelContextWindow(args.model ?? "");
|
|
2000
|
-
const allMsgs = toPlanCompressionMessages(history);
|
|
2001
|
-
const coldResume = isColdResume(history, args.now?.() ?? Date.now());
|
|
2002
|
-
const plan = planCompression({
|
|
2003
|
-
allMsgs,
|
|
2004
|
-
summarizedBeforeId,
|
|
2005
|
-
summary: existingSummary,
|
|
2006
|
-
contextWindow,
|
|
2007
|
-
// 防死亡螺旋:用 summary 长度作为上次压缩后的基线。如果新内容没让
|
|
2008
|
-
// totalUsed 比 summary 本身增长超过 minNewTokens,不重复触发。
|
|
2009
|
-
lastCompactedTokenCount: existingSummary ? estimateTokenCount(existingSummary) : void 0,
|
|
2010
|
-
...coldResume ? { force: true, reason: "context_budget" } : {}
|
|
2011
|
-
});
|
|
2012
|
-
const projectExisting = () => {
|
|
2013
|
-
if (!existingSummary.trim()) return unchanged();
|
|
2014
|
-
return {
|
|
2015
|
-
history: projectHistoryWithSummary({
|
|
2016
|
-
history,
|
|
2017
|
-
summary: existingSummary,
|
|
2018
|
-
summarizedBeforeId
|
|
2019
|
-
}),
|
|
2020
|
-
compressed: true,
|
|
2021
|
-
summaryGenerated: false
|
|
2022
|
-
};
|
|
2023
|
-
};
|
|
2024
|
-
if (!plan.shouldCompress) {
|
|
2025
|
-
return projectExisting();
|
|
2026
|
-
}
|
|
2027
|
-
try {
|
|
2028
|
-
const provider = await args.resolveProvider();
|
|
2029
|
-
const msgsToCompress = plan.msgsToCompress;
|
|
2030
|
-
const messagesText = formatMessagesForSummaryWithTruncation(msgsToCompress);
|
|
2031
|
-
const fileOpsText = formatFileOperationsFromMessages(
|
|
2032
|
-
msgsToCompress,
|
|
2033
|
-
canonicalizeToolName
|
|
2034
|
-
);
|
|
2035
|
-
const promptContent = buildCompactionUserContent({
|
|
2036
|
-
previousSummary: existingSummary,
|
|
2037
|
-
messagesText,
|
|
2038
|
-
fileOpsText
|
|
2039
|
-
});
|
|
2040
|
-
const result = await provider.complete([
|
|
2041
|
-
{ role: "system", content: COMPACTION_SUMMARY_SYSTEM_PROMPT },
|
|
2042
|
-
{ role: "user", content: promptContent }
|
|
2043
|
-
]);
|
|
2044
|
-
const newSummary = typeof result.content === "string" ? result.content.trim() : "";
|
|
2045
|
-
if (!newSummary) {
|
|
2046
|
-
console.warn(
|
|
2047
|
-
"[localLoop] auto-compaction produced empty summary; keeping prior projection"
|
|
2048
|
-
);
|
|
2049
|
-
return projectExisting();
|
|
2050
|
-
}
|
|
2051
|
-
await adapter.saveDialogSummary({
|
|
2052
|
-
dialogId,
|
|
2053
|
-
summary: newSummary,
|
|
2054
|
-
summarizedBeforeId: plan.newSummarizedBeforeId
|
|
2055
|
-
});
|
|
2056
|
-
const metrics = buildCompactionMetricsFromPlan({
|
|
2057
|
-
reason: coldResume ? "cold_resume" : "context_budget",
|
|
2058
|
-
previousSummary: existingSummary,
|
|
2059
|
-
plan,
|
|
2060
|
-
newSummary,
|
|
2061
|
-
summaryUsage: result.usage
|
|
2062
|
-
});
|
|
2063
|
-
console.log(formatCompactionMetricsLog(metrics));
|
|
2064
|
-
return {
|
|
2065
|
-
history: projectHistoryWithSummary({
|
|
2066
|
-
history,
|
|
2067
|
-
summary: newSummary,
|
|
2068
|
-
summarizedBeforeId: plan.newSummarizedBeforeId
|
|
2069
|
-
}),
|
|
2070
|
-
compressed: true,
|
|
2071
|
-
summaryGenerated: true,
|
|
2072
|
-
...result.usage ? { usage: result.usage } : {},
|
|
2073
|
-
metrics
|
|
2074
|
-
};
|
|
2075
|
-
} catch (error) {
|
|
2076
|
-
console.warn("[localLoop] auto-compaction failed:", error);
|
|
2077
|
-
return projectExisting();
|
|
2078
|
-
}
|
|
2079
|
-
}
|
|
2080
|
-
|
|
2081
|
-
// packages/agent-runtime/localLoop.ts
|
|
2082
|
-
var LOCAL_AGENT_CONFIG_MISSING_CODE = "LOCAL_AGENT_CONFIG_MISSING";
|
|
2083
|
-
var EMPTY_ASSISTANT_REPAIR_PROMPT = "\u8BF7\u7ED9\u51FA\u660E\u786E\u7684\u6587\u5B57\u56DE\u7B54\u6216\u6267\u884C\u4E0B\u4E00\u6B65\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u8BF7\u76F4\u63A5\u603B\u7ED3\u7ED3\u679C\uFF1B\u5982\u679C\u9700\u8981\u8C03\u7528\u5DE5\u5177\uFF0C\u8BF7\u76F4\u63A5\u8F93\u51FA tool_calls\u3002\u8BF7\u5207\u52FF\u8FD4\u56DE\u7A7A\u5185\u5BB9\u3002";
|
|
2084
|
-
var EMPTY_ASSISTANT_FALLBACK_MESSAGE = "\u6A21\u578B\u8FDE\u7EED\u8FD4\u56DE\u7A7A\u6D88\u606F\uFF0C\u5F53\u524D\u4EFB\u52A1\u672A\u5B8C\u6210\u3002\u8BF7\u91CD\u8BD5\u5F53\u524D\u6B65\u9AA4\uFF0C\u6216\u7ED9\u51FA\u66F4\u5177\u4F53\u7684\u4FEE\u6539\u8303\u56F4\u3002";
|
|
2085
|
-
var LENGTH_TRUNCATED_FALLBACK_MESSAGE = "\u8F93\u51FA\u8FBE\u5230\u957F\u5EA6\u4E0A\u9650\u88AB\u622A\u65AD\uFF0C\u5EFA\u8BAE\u7F29\u77ED\u4EFB\u52A1\u6216\u63D0\u9AD8\u8F93\u51FA\u4E0A\u9650\u3002";
|
|
2086
|
-
var STREAM_TRUNCATED_FALLBACK_MESSAGE = "\u4E0A\u6E38\u54CD\u5E94\u6D41\u5728\u6536\u5C3E\u524D\u88AB\u4E2D\u65AD\uFF08\u672A\u6536\u5230\u7ED3\u675F\u6807\u8BB0\uFF09\uFF0C\u672C\u8F6E\u8F93\u51FA\u4E0D\u5B8C\u6574\u3002\u8BF7\u91CD\u8BD5\u5F53\u524D\u6B65\u9AA4\u3002";
|
|
2087
|
-
function resolveEmptyAssistantOutcome(args) {
|
|
2088
|
-
if (args.hasToolCalls || args.hasVisibleOutput) return { kind: "ok" };
|
|
2089
|
-
if (args.finishReason === "length") return { kind: "fallback", reason: "length_truncated" };
|
|
2090
|
-
if (!args.repairUsed) return { kind: "repair" };
|
|
2091
|
-
if (!args.finishReason && !args.streamComplete) {
|
|
2092
|
-
return { kind: "fallback", reason: "stream_truncated" };
|
|
2093
|
-
}
|
|
2094
|
-
return { kind: "fallback", reason: "empty_completion" };
|
|
2095
|
-
}
|
|
2096
|
-
function resolveEmptyAssistantFallbackMessage(reason) {
|
|
2097
|
-
if (reason === "length_truncated") return LENGTH_TRUNCATED_FALLBACK_MESSAGE;
|
|
2098
|
-
if (reason === "stream_truncated") return STREAM_TRUNCATED_FALLBACK_MESSAGE;
|
|
2099
|
-
return EMPTY_ASSISTANT_FALLBACK_MESSAGE;
|
|
2100
|
-
}
|
|
2101
|
-
function hasAssistantVisibleOutput(content) {
|
|
2102
|
-
if (typeof content === "string") return content.trim().length > 0;
|
|
2103
|
-
if (!Array.isArray(content)) return false;
|
|
2104
|
-
return content.some((part) => {
|
|
2105
|
-
if (part?.type === "text" && String(part.text ?? "").trim()) return true;
|
|
2106
|
-
if (part?.type === "image_url") {
|
|
2107
|
-
const url = part?.image_url?.url;
|
|
2108
|
-
return typeof url === "string" && url.trim().length > 0;
|
|
2109
|
-
}
|
|
2110
|
-
return false;
|
|
2111
|
-
});
|
|
2112
|
-
}
|
|
2113
|
-
function formatToolExecutionError(args) {
|
|
2114
|
-
const message = toErrorMessage(args.error);
|
|
2115
|
-
return `${args.toolName} failed: ${message}`;
|
|
2116
|
-
}
|
|
2117
|
-
function formatStructuredToolExecutionError(args) {
|
|
2118
|
-
if (!args.error || typeof args.error !== "object") return null;
|
|
2119
|
-
const error = args.error;
|
|
2120
|
-
if (typeof error.code !== "string") return null;
|
|
2121
|
-
return JSON.stringify({
|
|
2122
|
-
error: error.code,
|
|
2123
|
-
message: typeof error.message === "string" ? error.message : formatToolExecutionError(args),
|
|
2124
|
-
...error.policy && typeof error.policy === "object" ? { policy: error.policy } : {},
|
|
2125
|
-
...error.permissionRequest && typeof error.permissionRequest === "object" ? { permissionRequest: error.permissionRequest } : {}
|
|
2126
|
-
});
|
|
2127
|
-
}
|
|
2128
|
-
function shouldReturnToolExecutionErrors(adapter) {
|
|
2129
|
-
return adapter.capabilities.includes("local-tools");
|
|
2130
|
-
}
|
|
2131
|
-
function emitToolEvent(input, event) {
|
|
2132
|
-
input.onToolEvent?.(event);
|
|
2133
|
-
}
|
|
2134
|
-
function emitLoopEvent(input, event) {
|
|
2135
|
-
if (!input.onLoopEvent) return;
|
|
2136
|
-
try {
|
|
2137
|
-
input.onLoopEvent(event);
|
|
2138
|
-
} catch {
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
var LLM_REQUEST_TIMEOUT = "LLM_REQUEST_TIMEOUT";
|
|
2142
|
-
var LOCAL_TURN_ABORTED_CODE = "LOCAL_TURN_ABORTED";
|
|
2143
|
-
function buildAbortedError() {
|
|
2144
|
-
const error = new Error("local agent turn aborted by user");
|
|
2145
|
-
error.code = LOCAL_TURN_ABORTED_CODE;
|
|
2146
|
-
return error;
|
|
2147
|
-
}
|
|
2148
|
-
function throwIfAborted(input) {
|
|
2149
|
-
if (input.abortSignal?.aborted) throw buildAbortedError();
|
|
2150
|
-
}
|
|
2151
|
-
async function raceWithAbort(input, promise, pendingToolName) {
|
|
2152
|
-
const signal = input.abortSignal;
|
|
2153
|
-
if (!signal) return promise;
|
|
2154
|
-
let abortListener;
|
|
2155
|
-
const abortPromise = new Promise((_resolve, reject) => {
|
|
2156
|
-
abortListener = () => {
|
|
2157
|
-
const error = buildAbortedError();
|
|
2158
|
-
if (pendingToolName) error.pendingToolName = pendingToolName;
|
|
2159
|
-
promise.catch(() => {
|
|
2160
|
-
});
|
|
2161
|
-
reject(error);
|
|
2162
|
-
};
|
|
2163
|
-
if (signal.aborted) {
|
|
2164
|
-
abortListener();
|
|
2165
|
-
return;
|
|
2166
|
-
}
|
|
2167
|
-
signal.addEventListener("abort", abortListener, { once: true });
|
|
2168
|
-
});
|
|
2169
|
-
try {
|
|
2170
|
-
return await Promise.race([promise, abortPromise]);
|
|
2171
|
-
} finally {
|
|
2172
|
-
if (signal && abortListener) signal.removeEventListener("abort", abortListener);
|
|
2173
|
-
}
|
|
2174
|
-
}
|
|
2175
|
-
function resolveLlmRequestTimeoutMs(input) {
|
|
2176
|
-
const raw = input.llmRequestTimeoutMs ?? input.timeoutMs;
|
|
2177
|
-
if (typeof raw !== "number" || !Number.isFinite(raw) || raw <= 0) return void 0;
|
|
2178
|
-
return raw;
|
|
2179
|
-
}
|
|
2180
|
-
async function runCompleteWithTimeout(args) {
|
|
2181
|
-
const { provider, messages, options, timeoutMs, round, input, context } = args;
|
|
2182
|
-
emitLoopEvent(input, {
|
|
2183
|
-
kind: "llm-start",
|
|
2184
|
-
round,
|
|
2185
|
-
atMs: Date.now(),
|
|
2186
|
-
...context ? { context } : {}
|
|
2187
|
-
});
|
|
2188
|
-
const complete = provider.complete(messages, options);
|
|
2189
|
-
let ok = false;
|
|
2190
|
-
const signal = input.abortSignal;
|
|
2191
|
-
let abortListener;
|
|
2192
|
-
const racers = [];
|
|
2193
|
-
if (signal) {
|
|
2194
|
-
racers.push(
|
|
2195
|
-
new Promise((_resolve, reject) => {
|
|
2196
|
-
abortListener = () => reject(buildAbortedError());
|
|
2197
|
-
if (signal.aborted) {
|
|
2198
|
-
abortListener();
|
|
2199
|
-
return;
|
|
2200
|
-
}
|
|
2201
|
-
signal.addEventListener("abort", abortListener, { once: true });
|
|
2202
|
-
})
|
|
2203
|
-
);
|
|
2204
|
-
}
|
|
2205
|
-
let timer;
|
|
2206
|
-
if (typeof timeoutMs === "number") {
|
|
2207
|
-
racers.push(
|
|
2208
|
-
new Promise((_resolve, reject) => {
|
|
2209
|
-
timer = setTimeout(() => {
|
|
2210
|
-
reject(new Error(`__llm_timeout__:${timeoutMs}`));
|
|
2211
|
-
}, timeoutMs);
|
|
2212
|
-
})
|
|
2213
|
-
);
|
|
2214
|
-
}
|
|
2215
|
-
let result;
|
|
2216
|
-
try {
|
|
2217
|
-
result = racers.length === 0 ? await complete : await Promise.race([complete, ...racers]);
|
|
2218
|
-
ok = true;
|
|
2219
|
-
return result;
|
|
2220
|
-
} catch (error) {
|
|
2221
|
-
const isTimeout = error instanceof Error && error.message.startsWith("__llm_timeout__:");
|
|
2222
|
-
if (!isTimeout) throw error;
|
|
2223
|
-
const timeoutError = new Error(
|
|
2224
|
-
`LLM request timed out after ${timeoutMs}ms (round ${round})`
|
|
2225
|
-
);
|
|
2226
|
-
timeoutError.code = LLM_REQUEST_TIMEOUT;
|
|
2227
|
-
throw timeoutError;
|
|
2228
|
-
} finally {
|
|
2229
|
-
if (timer) clearTimeout(timer);
|
|
2230
|
-
if (signal && abortListener) signal.removeEventListener("abort", abortListener);
|
|
2231
|
-
const usage = result?.usage;
|
|
2232
|
-
const cacheHit = Number(usage?.cache_read_input_tokens ?? usage?.prompt_cache_hit_tokens ?? 0);
|
|
2233
|
-
const cacheMiss = Number(usage?.cache_creation_input_tokens ?? usage?.prompt_cache_miss_tokens ?? 0);
|
|
2234
|
-
const inputTokens = Number(usage?.input_tokens ?? usage?.prompt_tokens ?? 0);
|
|
2235
|
-
const outputTokens = Number(usage?.output_tokens ?? usage?.completion_tokens ?? 0);
|
|
2236
|
-
emitLoopEvent(input, {
|
|
2237
|
-
kind: "llm-end",
|
|
2238
|
-
round,
|
|
2239
|
-
atMs: Date.now(),
|
|
2240
|
-
ok,
|
|
2241
|
-
...inputTokens > 0 || cacheHit > 0 || cacheMiss > 0 ? {
|
|
2242
|
-
cache: {
|
|
2243
|
-
inputTokens,
|
|
2244
|
-
outputTokens,
|
|
2245
|
-
cacheHitTokens: cacheHit,
|
|
2246
|
-
cacheMissTokens: cacheMiss,
|
|
2247
|
-
hitRatio: inputTokens > 0 ? Math.round(cacheHit / inputTokens * 1e4) / 1e4 : 0
|
|
2248
|
-
}
|
|
2249
|
-
} : {}
|
|
2250
|
-
});
|
|
2251
|
-
}
|
|
2252
|
-
}
|
|
2253
|
-
function clip2(value, max = 240) {
|
|
2254
|
-
return clipCompactText(value, max);
|
|
2255
|
-
}
|
|
2256
|
-
function summarizeToolResult(content, metadata) {
|
|
2257
|
-
const parts = [];
|
|
2258
|
-
const exitCode = metadata?.exitCode;
|
|
2259
|
-
if (typeof exitCode === "number") parts.push(`exit=${exitCode}`);
|
|
2260
|
-
if (typeof content === "string") {
|
|
2261
|
-
const trimmed = content.trim();
|
|
2262
|
-
if (trimmed) {
|
|
2263
|
-
const lines = trimmed.split(/\r?\n/).length;
|
|
2264
|
-
parts.push(`${lines} line${lines === 1 ? "" : "s"}`);
|
|
2265
|
-
parts.push(`${trimmed.length} chars`);
|
|
2266
|
-
const tail = clip2(trimmed.slice(-160), 160);
|
|
2267
|
-
if (tail) parts.push(`tail="${tail}"`);
|
|
2268
|
-
} else {
|
|
2269
|
-
parts.push("empty");
|
|
2270
|
-
}
|
|
2271
|
-
}
|
|
2272
|
-
return parts.join(" ");
|
|
2273
|
-
}
|
|
2274
|
-
function formatToolMessageContent(args) {
|
|
2275
|
-
if (args.toolName !== "listFiles" && args.toolName !== "globFiles" && args.toolName !== "searchFiles" && args.toolName !== "readFile" || !args.metadata || Object.keys(args.metadata).length === 0) {
|
|
2276
|
-
return args.content;
|
|
2277
|
-
}
|
|
2278
|
-
return `${args.content}
|
|
2279
|
-
|
|
2280
|
-
[tool metadata]
|
|
2281
|
-
${JSON.stringify(args.metadata)}`;
|
|
2282
|
-
}
|
|
2283
|
-
function blocksToOpenAiMessages(blocks) {
|
|
2284
|
-
const out = [];
|
|
2285
|
-
let text = "";
|
|
2286
|
-
let reasoning = "";
|
|
2287
|
-
let pendingToolCalls = [];
|
|
2288
|
-
let pendingToolResults = [];
|
|
2289
|
-
const flushSegment = () => {
|
|
2290
|
-
if (text === "" && pendingToolCalls.length === 0 && reasoning === "") return;
|
|
2291
|
-
out.push({
|
|
2292
|
-
role: "assistant",
|
|
2293
|
-
content: text || null,
|
|
2294
|
-
...reasoning ? { reasoning_content: reasoning } : {},
|
|
2295
|
-
...pendingToolCalls.length > 0 ? { tool_calls: pendingToolCalls } : {}
|
|
2296
|
-
});
|
|
2297
|
-
for (let i = 0; i < pendingToolCalls.length; i += 1) {
|
|
2298
|
-
const tc = pendingToolCalls[i];
|
|
2299
|
-
const res = pendingToolResults[i];
|
|
2300
|
-
out.push({
|
|
2301
|
-
role: "tool",
|
|
2302
|
-
content: formatToolMessageContent({
|
|
2303
|
-
toolName: tc.function.name,
|
|
2304
|
-
content: res?.content ?? "",
|
|
2305
|
-
...res?.metadata ? { metadata: res.metadata } : {}
|
|
2306
|
-
}),
|
|
2307
|
-
tool_call_id: tc.id,
|
|
2308
|
-
toolName: tc.function.name,
|
|
2309
|
-
...res?.metadata ? { tool_result_metadata: res.metadata } : {}
|
|
2310
|
-
});
|
|
2311
|
-
}
|
|
2312
|
-
text = "";
|
|
2313
|
-
reasoning = "";
|
|
2314
|
-
pendingToolCalls = [];
|
|
2315
|
-
pendingToolResults = [];
|
|
2316
|
-
};
|
|
2317
|
-
for (const block of blocks) {
|
|
2318
|
-
if (block.type === "text") {
|
|
2319
|
-
if (pendingToolCalls.length > 0) {
|
|
2320
|
-
flushSegment();
|
|
2321
|
-
}
|
|
2322
|
-
text += block.text;
|
|
2323
|
-
continue;
|
|
2324
|
-
}
|
|
2325
|
-
if (block.type === "thinking") {
|
|
2326
|
-
reasoning += block.thinking;
|
|
2327
|
-
continue;
|
|
2328
|
-
}
|
|
2329
|
-
if (block.type === "toolCall") {
|
|
2330
|
-
pendingToolCalls.push(block.toolCall);
|
|
2331
|
-
pendingToolResults.push({
|
|
2332
|
-
content: block.result?.content ?? "",
|
|
2333
|
-
...block.result?.metadata ? { metadata: block.result.metadata } : {}
|
|
2334
|
-
});
|
|
2335
|
-
}
|
|
2336
|
-
}
|
|
2337
|
-
flushSegment();
|
|
2338
|
-
return out;
|
|
2339
|
-
}
|
|
2340
|
-
function buildActionGate(args) {
|
|
2341
|
-
const gate = readActionGate(args.metadata?.actionGate);
|
|
2342
|
-
if (!gate) return null;
|
|
2343
|
-
if (gate.kind === "handoff" && !readCommandActionGatePayload(gate.payload)) return null;
|
|
2344
|
-
return {
|
|
2345
|
-
...gate,
|
|
2346
|
-
toolName: args.toolName,
|
|
2347
|
-
toolCallId: args.toolCallId
|
|
2348
|
-
};
|
|
2349
|
-
}
|
|
2350
|
-
var TOOL_METADATA_KEYS = [
|
|
2351
|
-
"path",
|
|
2352
|
-
"query",
|
|
2353
|
-
"effectivePattern",
|
|
2354
|
-
"startLine",
|
|
2355
|
-
"endLine",
|
|
2356
|
-
"totalLines",
|
|
2357
|
-
"totalBytes",
|
|
2358
|
-
"bytes",
|
|
2359
|
-
"totalChars",
|
|
2360
|
-
"count",
|
|
2361
|
-
"matchCount",
|
|
2362
|
-
"matchedFiles",
|
|
2363
|
-
"truncated",
|
|
2364
|
-
"limitedByMaxResults",
|
|
2365
|
-
"limitedByMaxDepth",
|
|
2366
|
-
"visitedEntries",
|
|
2367
|
-
"maxResults",
|
|
2368
|
-
"exitCode",
|
|
2369
|
-
"status",
|
|
2370
|
-
"timedOut",
|
|
2371
|
-
"aborted",
|
|
2372
|
-
"replacements",
|
|
2373
|
-
"code",
|
|
2374
|
-
"error",
|
|
2375
|
-
"message",
|
|
2376
|
-
"warnings",
|
|
2377
|
-
"pasteId",
|
|
2378
|
-
"source"
|
|
2379
|
-
];
|
|
2380
|
-
function trimHistoryToContextBudget(history, model) {
|
|
2381
|
-
if (history.length === 0) return { history, droppedCount: 0 };
|
|
2382
|
-
const { rawMessageBudget } = planContextUsage({
|
|
2383
|
-
contextWindow: getModelContextWindow(model ?? ""),
|
|
2384
|
-
summaryTokens: 0,
|
|
2385
|
-
// localLoop 没有 web 端的负载分档器;medium 是中性默认值,
|
|
2386
|
-
// 不为了省几个 token 在这里复制一份分类逻辑。
|
|
2387
|
-
recentLoad: "medium"
|
|
2388
|
-
});
|
|
2389
|
-
const messageTokens = (message) => {
|
|
2390
|
-
const toolCalls = message.tool_calls;
|
|
2391
|
-
return estimateTokenCount(contentAsText(message.content)) + (Array.isArray(toolCalls) ? estimateTokenCount(JSON.stringify(toolCalls)) : 0);
|
|
2392
|
-
};
|
|
2393
|
-
let used = 0;
|
|
2394
|
-
let start = history.length;
|
|
2395
|
-
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
2396
|
-
const cost = messageTokens(history[i]);
|
|
2397
|
-
if (used + cost > rawMessageBudget && start < history.length) break;
|
|
2398
|
-
used += cost;
|
|
2399
|
-
start = i;
|
|
2400
|
-
}
|
|
2401
|
-
if (start === 0) return { history, droppedCount: 0 };
|
|
2402
|
-
return {
|
|
2403
|
-
history: sanitizeToolCallPairing(history.slice(start)),
|
|
2404
|
-
droppedCount: start
|
|
2405
|
-
};
|
|
2406
|
-
}
|
|
2407
|
-
function contentAsText(content) {
|
|
2408
|
-
if (typeof content === "string") return content;
|
|
2409
|
-
if (!Array.isArray(content)) return "";
|
|
2410
|
-
return content.map((part) => {
|
|
2411
|
-
if (part?.type === "text") return part.text;
|
|
2412
|
-
if (part?.type === "image_url") return part.image_url.url;
|
|
2413
|
-
return "";
|
|
2414
|
-
}).join("\n");
|
|
2415
|
-
}
|
|
2416
|
-
function contentCharCount(content) {
|
|
2417
|
-
if (typeof content === "string") return content.length;
|
|
2418
|
-
if (!Array.isArray(content)) return 0;
|
|
2419
|
-
return content.reduce((total, part) => {
|
|
2420
|
-
if (part?.type === "text") return total + part.text.length;
|
|
2421
|
-
if (part?.type === "image_url") return total + part.image_url.url.length;
|
|
2422
|
-
return total;
|
|
2423
|
-
}, 0);
|
|
2424
|
-
}
|
|
2425
|
-
function compactToolMetadata(metadata) {
|
|
2426
|
-
if (!metadata) return "";
|
|
2427
|
-
const selected = {};
|
|
2428
|
-
for (const key of TOOL_METADATA_KEYS) {
|
|
2429
|
-
const value = metadata[key];
|
|
2430
|
-
if (value === void 0) continue;
|
|
2431
|
-
if (typeof value === "string") {
|
|
2432
|
-
selected[key] = clipCompactText(value, 240);
|
|
2433
|
-
continue;
|
|
2434
|
-
}
|
|
2435
|
-
if (Array.isArray(value)) {
|
|
2436
|
-
selected[key] = value.slice(0, 20).map(
|
|
2437
|
-
(item) => typeof item === "string" ? clipCompactText(item, 180) : clipCompactText(JSON.stringify(item), 180)
|
|
2438
|
-
);
|
|
2439
|
-
continue;
|
|
2440
|
-
}
|
|
2441
|
-
selected[key] = value;
|
|
2442
|
-
}
|
|
2443
|
-
return Object.keys(selected).length > 0 ? clipCompactText(JSON.stringify(selected), 1200) : "";
|
|
2444
|
-
}
|
|
2445
|
-
function projectToolContentForProvider(args) {
|
|
2446
|
-
const content = args.content;
|
|
2447
|
-
if (typeof content !== "string") return content;
|
|
2448
|
-
const metadataText = compactToolMetadata(args.metadata);
|
|
2449
|
-
const embeddedMetadataIndex = metadataText ? content.indexOf("\n\n[tool metadata]\n") : -1;
|
|
2450
|
-
const contentForProjection = embeddedMetadataIndex >= 0 ? content.slice(0, embeddedMetadataIndex) : content;
|
|
2451
|
-
const metadataSuffix = metadataText ? `
|
|
2452
|
-
|
|
2453
|
-
[tool metadata]
|
|
2454
|
-
${metadataText}` : "";
|
|
2455
|
-
if (embeddedMetadataIndex >= 0 && content.length <= args.maxChars) {
|
|
2456
|
-
return content;
|
|
2457
|
-
}
|
|
2458
|
-
const headRatio = resolveToolOutputProfile(args.toolName).headRatio;
|
|
2459
|
-
const diagnostic = (clippedLength) => `[${args.label}; originalChars=${content.length}; omittedChars=${Math.max(
|
|
2460
|
-
0,
|
|
2461
|
-
content.length - clippedLength
|
|
2462
|
-
)}]`;
|
|
2463
|
-
const suffix = (clippedLength) => [diagnostic(clippedLength), metadataSuffix.trimStart()].filter(Boolean).join("\n\n");
|
|
2464
|
-
const initialBudget = Math.max(
|
|
2465
|
-
1,
|
|
2466
|
-
args.maxChars - suffix(contentForProjection.length).length - 2
|
|
2467
|
-
);
|
|
2468
|
-
let clipped = clipToolText(contentForProjection, initialBudget, headRatio);
|
|
2469
|
-
const wasClipped = clipped.length < contentForProjection.trim().length;
|
|
2470
|
-
const needsProjection = wasClipped || Boolean(metadataSuffix) || embeddedMetadataIndex >= 0;
|
|
2471
|
-
if (!needsProjection) return args.content;
|
|
2472
|
-
let projected = wasClipped || metadataSuffix ? `${clipped}
|
|
2473
|
-
|
|
2474
|
-
${suffix(clipped.length)}` : clipped;
|
|
2475
|
-
if (projected.length > args.maxChars) {
|
|
2476
|
-
const boundedBudget = Math.max(
|
|
2477
|
-
1,
|
|
2478
|
-
args.maxChars - suffix(clipped.length).length - 2
|
|
2479
|
-
);
|
|
2480
|
-
clipped = clipToolText(contentForProjection, boundedBudget, headRatio);
|
|
2481
|
-
projected = `${clipped}
|
|
2482
|
-
|
|
2483
|
-
${suffix(clipped.length)}`;
|
|
2484
|
-
}
|
|
2485
|
-
return projected.length <= args.maxChars ? projected : projected.slice(0, args.maxChars);
|
|
2486
|
-
}
|
|
2487
|
-
function summarizeHistoricalToolContent(content, toolName, metadata) {
|
|
2488
|
-
return projectToolContentForProvider({
|
|
2489
|
-
content,
|
|
2490
|
-
toolName,
|
|
2491
|
-
metadata,
|
|
2492
|
-
// Same single source of truth as the server path and the read ledgers:
|
|
2493
|
-
// read-family tools keep their profile historical cap (4800) cross-turn,
|
|
2494
|
-
// unprofiled tools fall back to the flat historical budget.
|
|
2495
|
-
maxChars: resolveHistoricalToolContentCap(toolName, MAX_HISTORICAL_TOOL_CONTENT_CHARS),
|
|
2496
|
-
label: "historical tool result truncated for the next turn"
|
|
2497
|
-
});
|
|
2498
|
-
}
|
|
2499
|
-
function prepareMessagesForProviderCall(messages) {
|
|
2500
|
-
const paired = sanitizeToolCallPairing(messages);
|
|
2501
|
-
let freshRunStart = paired.length;
|
|
2502
|
-
while (freshRunStart > 0 && paired[freshRunStart - 1].role === "tool") {
|
|
2503
|
-
freshRunStart -= 1;
|
|
2504
|
-
}
|
|
2505
|
-
let toolMessageCount = 0;
|
|
2506
|
-
let rawToolContentChars = 0;
|
|
2507
|
-
let projectedToolContentChars = 0;
|
|
2508
|
-
let truncatedToolResults = 0;
|
|
2509
|
-
const projected = paired.map((message, index) => {
|
|
2510
|
-
const { context_reference: _contextReference, ...providerMessage } = message;
|
|
2511
|
-
const sanitizedContent = providerMessage.content == null ? "" : typeof providerMessage.content === "string" ? providerMessage.content : providerMessage.content;
|
|
2512
|
-
if (providerMessage.role !== "tool") {
|
|
2513
|
-
return {
|
|
2514
|
-
...providerMessage,
|
|
2515
|
-
content: sanitizedContent
|
|
2516
|
-
};
|
|
2517
|
-
}
|
|
2518
|
-
toolMessageCount += 1;
|
|
2519
|
-
rawToolContentChars += contentCharCount(sanitizedContent);
|
|
2520
|
-
const isFresh = index >= freshRunStart;
|
|
2521
|
-
const maxChars = isFresh ? FRESH_TOOL_OUTPUT_MAX_CHARS : resolveToolOutputProfile(providerMessage.toolName).maxChars;
|
|
2522
|
-
const projectedContent = projectToolContentForProvider({
|
|
2523
|
-
content: sanitizedContent,
|
|
2524
|
-
toolName: providerMessage.toolName,
|
|
2525
|
-
metadata: providerMessage.tool_result_metadata,
|
|
2526
|
-
maxChars,
|
|
2527
|
-
label: "in-turn tool result truncated/projected before next provider call"
|
|
2528
|
-
});
|
|
2529
|
-
projectedToolContentChars += contentCharCount(projectedContent);
|
|
2530
|
-
if (contentCharCount(projectedContent) < contentCharCount(sanitizedContent)) {
|
|
2531
|
-
truncatedToolResults += 1;
|
|
2532
|
-
}
|
|
2533
|
-
return {
|
|
2534
|
-
...providerMessage,
|
|
2535
|
-
content: projectedContent
|
|
2536
|
-
};
|
|
2537
|
-
});
|
|
2538
|
-
return {
|
|
2539
|
-
messages: projected,
|
|
2540
|
-
metrics: {
|
|
2541
|
-
messageCount: projected.length,
|
|
2542
|
-
contentChars: projected.reduce((total, message) => total + contentCharCount(message.content), 0),
|
|
2543
|
-
toolMessageCount,
|
|
2544
|
-
rawToolContentChars,
|
|
2545
|
-
projectedToolContentChars,
|
|
2546
|
-
truncatedToolResults,
|
|
2547
|
-
stableContextChars: 0,
|
|
2548
|
-
dynamicContextChars: 0
|
|
2549
|
-
}
|
|
2550
|
-
};
|
|
2551
|
-
}
|
|
2552
|
-
function prepareHistoryForNextTurn(history, contextReferenceResolver) {
|
|
2553
|
-
return history.map((message) => {
|
|
2554
|
-
if (message.role === "user" && message.context_reference !== void 0 && contextReferenceResolver?.(message.context_reference)) {
|
|
2555
|
-
return { ...message, content: message.context_reference };
|
|
2556
|
-
}
|
|
2557
|
-
if (message.role !== "tool") return message;
|
|
2558
|
-
return {
|
|
2559
|
-
...message,
|
|
2560
|
-
content: summarizeHistoricalToolContent(
|
|
2561
|
-
message.content,
|
|
2562
|
-
message.toolName,
|
|
2563
|
-
message.tool_result_metadata
|
|
2564
|
-
)
|
|
2565
|
-
};
|
|
2566
|
-
});
|
|
2567
|
-
}
|
|
2568
|
-
var IMAGE_OMITTED_PLACEHOLDER = "[Image content omitted: model does not support image input]";
|
|
2569
|
-
function stripImagePartsFromContent(content) {
|
|
2570
|
-
if (!Array.isArray(content)) return content;
|
|
2571
|
-
const filtered = content.filter((part) => part?.type !== "image_url");
|
|
2572
|
-
if (filtered.length === 0) return IMAGE_OMITTED_PLACEHOLDER;
|
|
2573
|
-
return filtered;
|
|
2574
|
-
}
|
|
2575
|
-
function filterImagePartsFromMessages(messages, supportsImages) {
|
|
2576
|
-
if (supportsImages) return messages;
|
|
2577
|
-
return messages.map((msg) => ({
|
|
2578
|
-
...msg,
|
|
2579
|
-
content: stripImagePartsFromContent(msg.content)
|
|
2580
|
-
}));
|
|
2581
|
-
}
|
|
2582
|
-
function buildMessages(args) {
|
|
2583
|
-
if (args.contextBlockScopes?.length) {
|
|
2584
|
-
const blocks2 = args.contextBlockScopes.filter((b) => b.content.trim());
|
|
2585
|
-
const stableParts = [args.prompt?.trim(), ...blocks2.filter((b) => b.cacheScope === "session").map((b) => b.content)].filter(Boolean);
|
|
2586
|
-
const dynamicParts = blocks2.filter((b) => b.cacheScope === "turn").map((b) => b.content).map((block) => block.trim()).filter(Boolean);
|
|
2587
|
-
const stableContent = stableParts.join("\n\n");
|
|
2588
|
-
const dynamicContent = dynamicParts.join("\n\n");
|
|
2589
|
-
const systemContent2 = dynamicContent ? `${stableContent}
|
|
2590
|
-
|
|
2591
|
-
${dynamicContent}` : stableContent;
|
|
2592
|
-
return {
|
|
2593
|
-
messages: [
|
|
2594
|
-
...systemContent2 ? [{
|
|
2595
|
-
role: "system",
|
|
2596
|
-
content: systemContent2,
|
|
2597
|
-
...stableContent ? { stable_prefix_chars: stableContent.length } : {}
|
|
2598
|
-
}] : [],
|
|
2599
|
-
...prepareHistoryForNextTurn(args.history, args.contextReferenceResolver),
|
|
2600
|
-
{ role: "user", content: args.input }
|
|
2601
|
-
],
|
|
2602
|
-
stableContextChars: stableContent.length,
|
|
2603
|
-
dynamicContextChars: dynamicContent.length
|
|
2604
|
-
};
|
|
2605
|
-
}
|
|
2606
|
-
const blocks = (args.contextBlocks ?? []).map((block) => block.trim()).filter(Boolean);
|
|
2607
|
-
const systemContent = [args.prompt?.trim(), ...blocks].filter(Boolean).join("\n\n");
|
|
2608
|
-
return {
|
|
2609
|
-
messages: [
|
|
2610
|
-
...systemContent ? [{ role: "system", content: systemContent }] : [],
|
|
2611
|
-
...prepareHistoryForNextTurn(args.history, args.contextReferenceResolver),
|
|
2612
|
-
{ role: "user", content: args.input }
|
|
2613
|
-
],
|
|
2614
|
-
stableContextChars: (args.prompt?.trim() ?? "").length,
|
|
2615
|
-
dynamicContextChars: blocks.join("\n\n").length
|
|
2616
|
-
};
|
|
2617
|
-
}
|
|
2618
|
-
function mergeTurnUsage(current, next) {
|
|
2619
|
-
if (!next) return current;
|
|
2620
|
-
const read2 = (usage) => ({
|
|
2621
|
-
input: Number(usage.input_tokens ?? usage.prompt_tokens ?? 0),
|
|
2622
|
-
output: Number(usage.output_tokens ?? usage.completion_tokens ?? 0),
|
|
2623
|
-
cacheHit: Number(
|
|
2624
|
-
usage.cache_read_input_tokens ?? usage.prompt_cache_hit_tokens ?? 0
|
|
2625
|
-
),
|
|
2626
|
-
cacheMiss: Number(
|
|
2627
|
-
usage.cache_creation_input_tokens ?? usage.prompt_cache_miss_tokens ?? 0
|
|
2628
|
-
)
|
|
2629
|
-
});
|
|
2630
|
-
const right = read2(next);
|
|
2631
|
-
const left = current ? read2(current) : { input: 0, output: 0, cacheHit: 0, cacheMiss: 0 };
|
|
2632
|
-
return {
|
|
2633
|
-
input_tokens: left.input + right.input,
|
|
2634
|
-
output_tokens: left.output + right.output,
|
|
2635
|
-
cache_read_input_tokens: left.cacheHit + right.cacheHit,
|
|
2636
|
-
cache_creation_input_tokens: left.cacheMiss + right.cacheMiss
|
|
2637
|
-
};
|
|
2638
|
-
}
|
|
2639
|
-
function addOutOfBandUsage(turn, extra) {
|
|
2640
|
-
if (!extra) return turn;
|
|
2641
|
-
const num = (u, ...keys) => {
|
|
2642
|
-
if (!u) return 0;
|
|
2643
|
-
for (const k of keys) {
|
|
2644
|
-
const v = Number(u[k]);
|
|
2645
|
-
if (Number.isFinite(v) && v !== 0) return v;
|
|
2646
|
-
}
|
|
2647
|
-
return 0;
|
|
2648
|
-
};
|
|
2649
|
-
return {
|
|
2650
|
-
...turn ?? {},
|
|
2651
|
-
input_tokens: num(turn, "input_tokens", "prompt_tokens") + num(extra, "input_tokens", "prompt_tokens"),
|
|
2652
|
-
output_tokens: num(turn, "output_tokens", "completion_tokens") + num(extra, "output_tokens", "completion_tokens"),
|
|
2653
|
-
cache_read_input_tokens: num(turn, "cache_read_input_tokens", "prompt_cache_hit_tokens") + num(extra, "cache_read_input_tokens", "prompt_cache_hit_tokens"),
|
|
2654
|
-
cache_creation_input_tokens: num(turn, "cache_creation_input_tokens", "prompt_cache_miss_tokens") + num(extra, "cache_creation_input_tokens", "prompt_cache_miss_tokens")
|
|
2655
|
-
};
|
|
2656
|
-
}
|
|
2657
|
-
function extractUserInputText(content) {
|
|
2658
|
-
if (typeof content === "string") return content;
|
|
2659
|
-
if (!Array.isArray(content)) return "";
|
|
2660
|
-
return content.flatMap((part) => part?.type === "text" && part.text ? [part.text] : []).join("\n").trim();
|
|
2661
|
-
}
|
|
2662
|
-
function attachDialogIdToError(error, dialogId) {
|
|
2663
|
-
if (!dialogId) return;
|
|
2664
|
-
if (typeof error === "object" && error !== null) {
|
|
2665
|
-
error.dialogId = dialogId;
|
|
2666
|
-
}
|
|
2667
|
-
}
|
|
2668
|
-
async function persistFailedLocalTurn(args) {
|
|
2669
|
-
const errorMessage = toErrorMessage(args.error);
|
|
2670
|
-
try {
|
|
2671
|
-
const saved = await args.adapter.saveTurn({
|
|
2672
|
-
agentKey: args.agentKey,
|
|
2673
|
-
messages: args.messages,
|
|
2674
|
-
result: {
|
|
2675
|
-
content: args.partialContent || `[nolo] Agent run failed: ${errorMessage}`,
|
|
2676
|
-
model: args.model ?? "unknown",
|
|
2677
|
-
toolCallCount: args.toolCallCount ?? 0,
|
|
2678
|
-
error: true,
|
|
2679
|
-
errorMessage,
|
|
2680
|
-
...args.usage ? { usage: args.usage } : {}
|
|
2681
|
-
},
|
|
2682
|
-
...args.accountingUsage ? { accountingUsage: args.accountingUsage } : {},
|
|
2683
|
-
...args.usageRecords?.length ? { usageRecords: args.usageRecords } : {},
|
|
2684
|
-
...args.billingConfig ? { billingConfig: args.billingConfig } : {},
|
|
2685
|
-
...args.input.runtimeContext ? { runtimeContext: args.input.runtimeContext } : {},
|
|
2686
|
-
...args.input.continueDialogId ? { continueDialogId: args.input.continueDialogId } : {},
|
|
2687
|
-
...args.input.spaceId ? { spaceId: args.input.spaceId } : {},
|
|
2688
|
-
...args.input.category ? { category: args.input.category } : {},
|
|
2689
|
-
...args.input.inheritedFromDialogKey ? { inheritedFromDialogKey: args.input.inheritedFromDialogKey } : {},
|
|
2690
|
-
...args.input.parentDialogId ? { parentDialogId: args.input.parentDialogId } : {}
|
|
2691
|
-
});
|
|
2692
|
-
return saved?.dialogId;
|
|
2693
|
-
} catch {
|
|
2694
|
-
return args.input.continueDialogId;
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
function applyPersistedTurnInput(messages, persistedInput, persistedInputReference) {
|
|
2698
|
-
if (persistedInput === void 0 && persistedInputReference === void 0) {
|
|
2699
|
-
return messages;
|
|
2700
|
-
}
|
|
2701
|
-
let replaced = false;
|
|
2702
|
-
return messages.map((message) => {
|
|
2703
|
-
if (replaced || message.role !== "user") return message;
|
|
2704
|
-
replaced = true;
|
|
2705
|
-
return {
|
|
2706
|
-
...message,
|
|
2707
|
-
...persistedInput !== void 0 ? { content: persistedInput } : {},
|
|
2708
|
-
...persistedInputReference !== void 0 ? { context_reference: persistedInputReference } : {}
|
|
2709
|
-
};
|
|
2710
|
-
});
|
|
2711
|
-
}
|
|
2712
|
-
async function runLocalAgentTurn(input) {
|
|
2713
|
-
const agentConfig = await input.adapter.loadAgentConfig(input.agentRef);
|
|
2714
|
-
if (!agentConfig) {
|
|
2715
|
-
const error = new Error(
|
|
2716
|
-
`agentRef "${input.agentRef}" \u672A\u5339\u914D\u5230\u672C\u5730 agent\u3002\u8FD9\u4E0D\u662F\u914D\u7F6E\u7F3A\u5931\uFF0C\u8BF7\u7528 listAgents \u67E5\u770B\u53EF\u7528 agent\uFF0C\u518D\u7528 readAgent \u89E3\u6790 agentKey\uFF0C\u52FF\u624B\u5DE5\u62FC key\u3002`
|
|
2717
|
-
);
|
|
2718
|
-
error.code = LOCAL_AGENT_CONFIG_MISSING_CODE;
|
|
2719
|
-
error.agentRef = input.agentRef;
|
|
2720
|
-
throw error;
|
|
2721
|
-
}
|
|
2722
|
-
const rawBillingConfig = agentConfig.rawRecord ?? {};
|
|
2723
|
-
const billingConfig = {
|
|
2724
|
-
model: agentConfig.model || "unknown",
|
|
2725
|
-
...agentConfig.provider ? { provider: agentConfig.provider } : {},
|
|
2726
|
-
...agentConfig.apiSource ? { apiSource: agentConfig.apiSource } : {},
|
|
2727
|
-
...agentConfig.apiKeyRef !== void 0 ? { apiKeyRef: agentConfig.apiKeyRef } : {},
|
|
2728
|
-
...typeof rawBillingConfig.inputPrice === "number" ? { inputPrice: rawBillingConfig.inputPrice } : {},
|
|
2729
|
-
...typeof rawBillingConfig.outputPrice === "number" ? { outputPrice: rawBillingConfig.outputPrice } : {},
|
|
2730
|
-
...rawBillingConfig.sharingLevel ? { sharingLevel: rawBillingConfig.sharingLevel } : {},
|
|
2731
|
-
id: agentConfig.key,
|
|
2732
|
-
...typeof rawBillingConfig.userId === "string" ? { userId: rawBillingConfig.userId } : {}
|
|
2733
|
-
};
|
|
2734
|
-
let history = [];
|
|
2735
|
-
try {
|
|
2736
|
-
history = input.continueDialogId ? await input.adapter.loadDialogHistory(input.continueDialogId) : [];
|
|
2737
|
-
} catch (error) {
|
|
2738
|
-
const dialogId = await persistFailedLocalTurn({
|
|
2739
|
-
adapter: input.adapter,
|
|
2740
|
-
agentKey: agentConfig.key,
|
|
2741
|
-
messages: [{ role: "user", content: input.input }],
|
|
2742
|
-
error,
|
|
2743
|
-
model: agentConfig.model,
|
|
2744
|
-
input
|
|
2745
|
-
});
|
|
2746
|
-
attachDialogIdToError(error, dialogId);
|
|
2747
|
-
throw error;
|
|
2748
|
-
}
|
|
2749
|
-
const identityBlock = buildIdentityBlock({
|
|
2750
|
-
agentName: agentConfig.name,
|
|
2751
|
-
agentId: agentConfig.key,
|
|
2752
|
-
model: agentConfig.model
|
|
2753
|
-
});
|
|
2754
|
-
const agentTools = canonicalizeToolNames(
|
|
2755
|
-
agentConfig.exposedToolNames ?? agentConfig.toolNames ?? []
|
|
2756
|
-
);
|
|
2757
|
-
const guidanceBlocks = buildRuntimeGuidanceBlocks(agentTools);
|
|
2758
|
-
const toolGuidedSections = resolveToolGuidedSections(agentTools);
|
|
2759
|
-
const guidanceScopes = [
|
|
2760
|
-
guidanceBlocks.startupProtocol,
|
|
2761
|
-
guidanceBlocks.contextLayerContract,
|
|
2762
|
-
guidanceBlocks.emailRegistrationWorkflow,
|
|
2763
|
-
guidanceBlocks.webResearchToolPolicy,
|
|
2764
|
-
...Object.values(toolGuidedSections)
|
|
2765
|
-
].map((content) => content.trim()).filter((content) => content.length > 0).map((content) => ({ content, cacheScope: "session" }));
|
|
2766
|
-
const currentTimeScope = [
|
|
2767
|
-
{ content: buildCurrentTimeBlock(/* @__PURE__ */ new Date(), void 0), cacheScope: "turn" }
|
|
2768
|
-
];
|
|
2769
|
-
const callerScopes = normalizeContextBlockScopes(
|
|
2770
|
-
input.contextBlocks,
|
|
2771
|
-
input.contextBlockScopes
|
|
2772
|
-
);
|
|
2773
|
-
const mergedContextBlockScopes = [
|
|
2774
|
-
{ content: identityBlock, cacheScope: "session" },
|
|
2775
|
-
...guidanceScopes,
|
|
2776
|
-
...currentTimeScope,
|
|
2777
|
-
...callerScopes
|
|
2778
|
-
];
|
|
2779
|
-
let resolvedProvider;
|
|
2780
|
-
const resolveProviderOnce = async () => {
|
|
2781
|
-
if (!resolvedProvider) {
|
|
2782
|
-
resolvedProvider = await input.adapter.resolveProvider(agentConfig);
|
|
2783
|
-
}
|
|
2784
|
-
return resolvedProvider;
|
|
2785
|
-
};
|
|
2786
|
-
let compactionUsage;
|
|
2787
|
-
try {
|
|
2788
|
-
const compacted = await maybeAutoCompactLocalHistory({
|
|
2789
|
-
adapter: input.adapter,
|
|
2790
|
-
dialogId: input.continueDialogId,
|
|
2791
|
-
history,
|
|
2792
|
-
model: agentConfig.model,
|
|
2793
|
-
resolveProvider: resolveProviderOnce
|
|
2794
|
-
});
|
|
2795
|
-
history = compacted.history;
|
|
2796
|
-
compactionUsage = compacted.usage;
|
|
2797
|
-
} catch (error) {
|
|
2798
|
-
console.warn("[localLoop] auto-compaction unexpected error:", error);
|
|
2799
|
-
}
|
|
2800
|
-
const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model);
|
|
2801
|
-
if (trimmedHistory.droppedCount > 0) {
|
|
2802
|
-
history = trimmedHistory.history;
|
|
2803
|
-
}
|
|
2804
|
-
const hasContextBlocks = callerScopes.some((block) => block.content.trim()) || mergedContextBlockScopes.some((block) => block.content.trim());
|
|
2805
|
-
const promptMessageCount = agentConfig.prompt?.trim() || hasContextBlocks ? 1 : 0;
|
|
2806
|
-
const turnStartIndex = promptMessageCount + history.length;
|
|
2807
|
-
const builtMessages = buildMessages({
|
|
2808
|
-
prompt: agentConfig.prompt,
|
|
2809
|
-
contextBlockScopes: mergedContextBlockScopes,
|
|
2810
|
-
history,
|
|
2811
|
-
input: input.input,
|
|
2812
|
-
contextReferenceResolver: input.adapter.host === "cli" ? input.contextReferenceResolver : void 0
|
|
2813
|
-
});
|
|
2814
|
-
let messages = builtMessages.messages;
|
|
2815
|
-
const supportsImages = resolveAgentImageInputSupport({
|
|
2816
|
-
apiSource: agentConfig.apiSource,
|
|
2817
|
-
provider: agentConfig.provider,
|
|
2818
|
-
model: agentConfig.model,
|
|
2819
|
-
hasVision: agentConfig.hasVision
|
|
2820
|
-
});
|
|
2821
|
-
if (!supportsImages && hasImageInRuntimeMessages(messages)) {
|
|
2822
|
-
const imageUrls = extractImageUrlsFromMessages(messages);
|
|
2823
|
-
const preprocessed = await preprocessImagesForTextOnlyAgent(
|
|
2824
|
-
messages,
|
|
2825
|
-
(urls) => describeImageWithLocalProvider(input.adapter, urls)
|
|
2826
|
-
);
|
|
2827
|
-
if (preprocessed !== messages) {
|
|
2828
|
-
messages = preprocessed;
|
|
2829
|
-
emitLoopEvent(input, {
|
|
2830
|
-
kind: "image-preprocessed",
|
|
2831
|
-
atMs: Date.now(),
|
|
2832
|
-
imageCount: imageUrls.length
|
|
2833
|
-
});
|
|
2834
|
-
} else {
|
|
2835
|
-
messages = filterImagePartsFromMessages(messages, false);
|
|
2836
|
-
emitLoopEvent(input, {
|
|
2837
|
-
kind: "image-downgraded",
|
|
2838
|
-
reason: "no-vision",
|
|
2839
|
-
atMs: Date.now()
|
|
2840
|
-
});
|
|
2841
|
-
}
|
|
2842
|
-
}
|
|
2843
|
-
const userInputText = extractUserInputText(input.input);
|
|
2844
|
-
let toolCallCount = 0;
|
|
2845
|
-
let result;
|
|
2846
|
-
let turnUsage;
|
|
2847
|
-
let contextUsage;
|
|
2848
|
-
const usageRecords = [];
|
|
2849
|
-
let loopError;
|
|
2850
|
-
let round = 0;
|
|
2851
|
-
let emptyAssistantRepairPending = false;
|
|
2852
|
-
let emptyAssistantRepairUsed = false;
|
|
2853
|
-
let skipFinalAppend = false;
|
|
2854
|
-
let partialContent = "";
|
|
2855
|
-
try {
|
|
2856
|
-
const provider = await resolveProviderOnce();
|
|
2857
|
-
while (true) {
|
|
2858
|
-
partialContent = "";
|
|
2859
|
-
throwIfAborted(input);
|
|
2860
|
-
const preparedMessages = prepareMessagesForProviderCall(messages);
|
|
2861
|
-
const baseRequestMessages = filterImagePartsFromMessages(
|
|
2862
|
-
preparedMessages.messages,
|
|
2863
|
-
supportsImages
|
|
2864
|
-
);
|
|
2865
|
-
const requestMessages = emptyAssistantRepairPending ? [...baseRequestMessages, { role: "user", content: EMPTY_ASSISTANT_REPAIR_PROMPT }] : baseRequestMessages;
|
|
2866
|
-
const contextMetrics = {
|
|
2867
|
-
...preparedMessages.metrics,
|
|
2868
|
-
messageCount: requestMessages.length,
|
|
2869
|
-
contentChars: requestMessages.reduce(
|
|
2870
|
-
(total, message) => total + contentCharCount(message.content),
|
|
2871
|
-
0
|
|
2872
|
-
),
|
|
2873
|
-
stableContextChars: builtMessages.stableContextChars,
|
|
2874
|
-
dynamicContextChars: builtMessages.dynamicContextChars
|
|
2875
|
-
};
|
|
2876
|
-
emptyAssistantRepairPending = false;
|
|
2877
|
-
result = await runCompleteWithTimeout({
|
|
2878
|
-
provider,
|
|
2879
|
-
messages: requestMessages,
|
|
2880
|
-
options: {
|
|
2881
|
-
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
2882
|
-
...input.onTextDelta ? { onTextDelta: (chunk) => {
|
|
2883
|
-
partialContent += chunk;
|
|
2884
|
-
input.onTextDelta(chunk);
|
|
2885
|
-
} } : {},
|
|
2886
|
-
...input.onReasoningDelta ? { onReasoningDelta: input.onReasoningDelta } : {},
|
|
2887
|
-
...input.onToolEvent ? { onToolEvent: input.onToolEvent } : {},
|
|
2888
|
-
...input.onToolEvent ? { toolEventRound: round } : {}
|
|
2889
|
-
},
|
|
2890
|
-
timeoutMs: resolveLlmRequestTimeoutMs(input),
|
|
2891
|
-
round,
|
|
2892
|
-
input,
|
|
2893
|
-
context: contextMetrics
|
|
2894
|
-
});
|
|
2895
|
-
turnUsage = mergeTurnUsage(turnUsage, result.usage);
|
|
2896
|
-
contextUsage = result.usage;
|
|
2897
|
-
if (result.usage && Object.keys(result.usage).length > 0) {
|
|
2898
|
-
usageRecords.push({
|
|
2899
|
-
callId: typeof result.usage.provider_call_id === "string" && result.usage.provider_call_id.trim() ? result.usage.provider_call_id.trim() : crypto.randomUUID(),
|
|
2900
|
-
usage: result.usage,
|
|
2901
|
-
model: result.model || agentConfig.model || "unknown",
|
|
2902
|
-
...result.provider || agentConfig.provider ? { provider: result.provider || agentConfig.provider } : {}
|
|
2903
|
-
});
|
|
2904
|
-
}
|
|
2905
|
-
const toolCalls = result.tool_calls ?? [];
|
|
2906
|
-
const rawToolCallsCount = (result.tool_calls?.length ?? 0) || (Array.isArray(result.raw_tool_calls) ? result.raw_tool_calls.length : 0);
|
|
2907
|
-
if (toolCalls.length === 0 && rawToolCallsCount === 0) {
|
|
2908
|
-
const outcome = resolveEmptyAssistantOutcome({
|
|
2909
|
-
hasToolCalls: rawToolCallsCount > 0,
|
|
2910
|
-
hasVisibleOutput: hasAssistantVisibleOutput(result.content),
|
|
2911
|
-
repairUsed: emptyAssistantRepairUsed,
|
|
2912
|
-
finishReason: result.finish_reason,
|
|
2913
|
-
streamComplete: result.stream_complete
|
|
2914
|
-
});
|
|
2915
|
-
if (outcome.kind === "repair") {
|
|
2916
|
-
emptyAssistantRepairPending = true;
|
|
2917
|
-
emptyAssistantRepairUsed = true;
|
|
2918
|
-
continue;
|
|
2919
|
-
}
|
|
2920
|
-
if (outcome.kind === "fallback") {
|
|
2921
|
-
result = {
|
|
2922
|
-
...result,
|
|
2923
|
-
content: resolveEmptyAssistantFallbackMessage(outcome.reason)
|
|
2924
|
-
};
|
|
2925
|
-
break;
|
|
2926
|
-
}
|
|
2927
|
-
break;
|
|
2928
|
-
}
|
|
2929
|
-
const outputBlocks = result.output ?? [];
|
|
2930
|
-
if (outputBlocks.length > 0) {
|
|
2931
|
-
let hasInlineExecutedTools = false;
|
|
2932
|
-
for (const block of outputBlocks) {
|
|
2933
|
-
if (block.type !== "toolCall") continue;
|
|
2934
|
-
toolCallCount += 1;
|
|
2935
|
-
const toolName = block.toolCall.function.name;
|
|
2936
|
-
if (block.result) {
|
|
2937
|
-
hasInlineExecutedTools = true;
|
|
2938
|
-
} else {
|
|
2939
|
-
throw new Error(
|
|
2940
|
-
`provider returned output block with unexecuted toolCall "${toolName}" (id=${block.toolCall.id}); no provider currently emits this shape. Either the provider must fill block.result (like Cursor's exec channel) or it must not set result.output at all.`
|
|
2941
|
-
);
|
|
2942
|
-
}
|
|
2943
|
-
}
|
|
2944
|
-
if (hasInlineExecutedTools) {
|
|
2945
|
-
messages.push(...blocksToOpenAiMessages(outputBlocks));
|
|
2946
|
-
skipFinalAppend = true;
|
|
2947
|
-
break;
|
|
2948
|
-
}
|
|
2949
|
-
round += 1;
|
|
2950
|
-
continue;
|
|
2951
|
-
}
|
|
2952
|
-
toolCallCount += toolCalls.length;
|
|
2953
|
-
messages.push({
|
|
2954
|
-
role: "assistant",
|
|
2955
|
-
content: result.content || null,
|
|
2956
|
-
...result.reasoning_content ? { reasoning_content: result.reasoning_content } : {},
|
|
2957
|
-
tool_calls: toolCalls
|
|
2958
|
-
});
|
|
2959
|
-
for (const toolCall of toolCalls) {
|
|
2960
|
-
throwIfAborted(input);
|
|
2961
|
-
const toolName = toolCall.function.name;
|
|
2962
|
-
let toolResult;
|
|
2963
|
-
const startedAt = Date.now();
|
|
2964
|
-
emitLoopEvent(input, { kind: "tool-start", name: toolName, atMs: Date.now() });
|
|
2965
|
-
emitToolEvent(input, {
|
|
2966
|
-
type: "tool-call",
|
|
2967
|
-
round,
|
|
2968
|
-
toolCallId: toolCall.id,
|
|
2969
|
-
toolName,
|
|
2970
|
-
argumentsPreview: summarizeToolArguments(toolName, toolCall.function.arguments)
|
|
2971
|
-
});
|
|
2972
|
-
try {
|
|
2973
|
-
const executePromise = input.adapter.executeTool({
|
|
2974
|
-
id: toolCall.id,
|
|
2975
|
-
name: toolName,
|
|
2976
|
-
arguments: toolCall.function.arguments,
|
|
2977
|
-
...userInputText ? { userInput: userInputText } : {},
|
|
2978
|
-
...input.runtimeContext ? { runtimeContext: input.runtimeContext } : {},
|
|
2979
|
-
...input.abortSignal ? { abortSignal: input.abortSignal } : {}
|
|
2980
|
-
}, {
|
|
2981
|
-
...input.abortSignal ? { abortSignal: input.abortSignal } : {},
|
|
2982
|
-
...input.runtimeContext ? { runtimeContext: input.runtimeContext } : {}
|
|
2983
|
-
});
|
|
2984
|
-
toolResult = await raceWithAbort(input, executePromise, toolName);
|
|
2985
|
-
const actionGate = buildActionGate({
|
|
2986
|
-
toolName,
|
|
2987
|
-
toolCallId: toolCall.id,
|
|
2988
|
-
metadata: toolResult.metadata
|
|
2989
|
-
});
|
|
2990
|
-
if (actionGate && input.onActionGate) {
|
|
2991
|
-
const replacement = await input.onActionGate(actionGate);
|
|
2992
|
-
if (replacement) {
|
|
2993
|
-
toolResult = replacement;
|
|
2994
|
-
}
|
|
2995
|
-
}
|
|
2996
|
-
emitLoopEvent(input, { kind: "tool-end", name: toolName, atMs: Date.now(), ok: true });
|
|
2997
|
-
emitToolEvent(input, {
|
|
2998
|
-
type: "tool-result",
|
|
2999
|
-
round,
|
|
3000
|
-
toolCallId: toolCall.id,
|
|
3001
|
-
toolName,
|
|
3002
|
-
elapsedMs: Math.max(0, Date.now() - startedAt),
|
|
3003
|
-
summary: summarizeToolResult(toolResult.content, toolResult.metadata),
|
|
3004
|
-
...typeof toolResult.content === "string" ? { content: toolResult.content } : {},
|
|
3005
|
-
metadata: toolResult.metadata
|
|
3006
|
-
});
|
|
3007
|
-
} catch (error) {
|
|
3008
|
-
emitLoopEvent(input, { kind: "tool-end", name: toolName, atMs: Date.now(), ok: false });
|
|
3009
|
-
if (error && typeof error === "object" && error.code === LOCAL_TURN_ABORTED_CODE) {
|
|
3010
|
-
throw error;
|
|
3011
|
-
}
|
|
3012
|
-
if (!shouldReturnToolExecutionErrors(input.adapter)) throw error;
|
|
3013
|
-
emitToolEvent(input, {
|
|
3014
|
-
type: "tool-error",
|
|
3015
|
-
round,
|
|
3016
|
-
toolCallId: toolCall.id,
|
|
3017
|
-
toolName,
|
|
3018
|
-
elapsedMs: Math.max(0, Date.now() - startedAt),
|
|
3019
|
-
message: toErrorMessage(error)
|
|
3020
|
-
});
|
|
3021
|
-
toolResult = {
|
|
3022
|
-
content: formatStructuredToolExecutionError({ toolName, error }) ?? formatToolExecutionError({ toolName, error }),
|
|
3023
|
-
metadata: {
|
|
3024
|
-
error: true,
|
|
3025
|
-
toolName,
|
|
3026
|
-
message: toErrorMessage(error),
|
|
3027
|
-
...error && typeof error === "object" && typeof error.code === "string" ? { code: error.code } : {}
|
|
3028
|
-
}
|
|
3029
|
-
};
|
|
3030
|
-
}
|
|
3031
|
-
messages.push({
|
|
3032
|
-
role: "tool",
|
|
3033
|
-
content: formatToolMessageContent({
|
|
3034
|
-
toolName,
|
|
3035
|
-
content: toolResult.content,
|
|
3036
|
-
metadata: toolResult.metadata
|
|
3037
|
-
}),
|
|
3038
|
-
tool_call_id: toolCall.id,
|
|
3039
|
-
toolName,
|
|
3040
|
-
...toolResult.metadata ? { tool_result_metadata: toolResult.metadata } : {}
|
|
3041
|
-
});
|
|
3042
|
-
}
|
|
3043
|
-
round += 1;
|
|
3044
|
-
}
|
|
3045
|
-
} catch (error) {
|
|
3046
|
-
loopError = error;
|
|
3047
|
-
}
|
|
3048
|
-
if (loopError) {
|
|
3049
|
-
const turnMessages2 = applyPersistedTurnInput(
|
|
3050
|
-
messages.slice(turnStartIndex),
|
|
3051
|
-
input.persistedInput,
|
|
3052
|
-
input.persistedInputReference
|
|
3053
|
-
);
|
|
3054
|
-
const dialogId = await persistFailedLocalTurn({
|
|
3055
|
-
adapter: input.adapter,
|
|
3056
|
-
agentKey: agentConfig.key,
|
|
3057
|
-
messages: turnMessages2,
|
|
3058
|
-
error: loopError,
|
|
3059
|
-
model: agentConfig.model,
|
|
3060
|
-
toolCallCount,
|
|
3061
|
-
partialContent,
|
|
3062
|
-
usage: contextUsage,
|
|
3063
|
-
accountingUsage: addOutOfBandUsage(turnUsage, compactionUsage),
|
|
3064
|
-
usageRecords: [
|
|
3065
|
-
...compactionUsage ? [{
|
|
3066
|
-
callId: typeof compactionUsage.provider_call_id === "string" && compactionUsage.provider_call_id.trim() ? compactionUsage.provider_call_id.trim() : crypto.randomUUID(),
|
|
3067
|
-
usage: compactionUsage,
|
|
3068
|
-
model: agentConfig.model || "unknown",
|
|
3069
|
-
...agentConfig.provider ? { provider: agentConfig.provider } : {}
|
|
3070
|
-
}] : [],
|
|
3071
|
-
...usageRecords
|
|
3072
|
-
],
|
|
3073
|
-
billingConfig,
|
|
3074
|
-
input
|
|
3075
|
-
});
|
|
3076
|
-
attachDialogIdToError(loopError, dialogId);
|
|
3077
|
-
throw loopError;
|
|
3078
|
-
}
|
|
3079
|
-
result = result;
|
|
3080
|
-
if (!skipFinalAppend) {
|
|
3081
|
-
messages.push({
|
|
3082
|
-
role: "assistant",
|
|
3083
|
-
content: result.content,
|
|
3084
|
-
// 与中间轮(:561)一致带上 reasoning_content,让 saveTurn 持久化思维链,
|
|
3085
|
-
// 空轮/异常排查时能回看模型实际想了什么。
|
|
3086
|
-
...result.reasoning_content ? { reasoning_content: result.reasoning_content } : {}
|
|
3087
|
-
});
|
|
3088
|
-
}
|
|
3089
|
-
const turnMessages = applyPersistedTurnInput(
|
|
3090
|
-
messages.slice(turnStartIndex),
|
|
3091
|
-
input.persistedInput,
|
|
3092
|
-
input.persistedInputReference
|
|
3093
|
-
);
|
|
3094
|
-
if (compactionUsage && Object.keys(compactionUsage).length > 0) {
|
|
3095
|
-
usageRecords.unshift({
|
|
3096
|
-
callId: typeof compactionUsage.provider_call_id === "string" && compactionUsage.provider_call_id.trim() ? compactionUsage.provider_call_id.trim() : crypto.randomUUID(),
|
|
3097
|
-
usage: compactionUsage,
|
|
3098
|
-
model: agentConfig.model || result.model || "unknown",
|
|
3099
|
-
...agentConfig.provider ? { provider: agentConfig.provider } : {}
|
|
3100
|
-
});
|
|
3101
|
-
}
|
|
3102
|
-
const accountingUsage = addOutOfBandUsage(turnUsage, compactionUsage);
|
|
3103
|
-
const saved = await input.adapter.saveTurn({
|
|
3104
|
-
agentKey: agentConfig.key,
|
|
3105
|
-
messages: turnMessages,
|
|
3106
|
-
result: {
|
|
3107
|
-
...result,
|
|
3108
|
-
...toolCallCount > 0 ? { toolCallCount } : {},
|
|
3109
|
-
...agentConfig.toolSurface ? { runtimeToolSurface: agentConfig.toolSurface } : {}
|
|
3110
|
-
},
|
|
3111
|
-
...usageRecords.length > 0 ? { usageRecords } : {},
|
|
3112
|
-
...accountingUsage ? { accountingUsage } : {},
|
|
3113
|
-
billingConfig,
|
|
3114
|
-
...input.runtimeContext ? { runtimeContext: input.runtimeContext } : {},
|
|
3115
|
-
...input.continueDialogId ? { continueDialogId: input.continueDialogId } : {},
|
|
3116
|
-
...input.spaceId ? { spaceId: input.spaceId } : {},
|
|
3117
|
-
...input.category ? { category: input.category } : {},
|
|
3118
|
-
...input.inheritedFromDialogKey ? { inheritedFromDialogKey: input.inheritedFromDialogKey } : {},
|
|
3119
|
-
...input.parentDialogId ? { parentDialogId: input.parentDialogId } : {}
|
|
3120
|
-
});
|
|
3121
|
-
return {
|
|
3122
|
-
...result,
|
|
3123
|
-
...usageRecords.length > 0 ? { usageRecords } : {},
|
|
3124
|
-
...accountingUsage ? { accountingUsage } : {},
|
|
3125
|
-
...toolCallCount > 0 ? { toolCallCount } : {},
|
|
3126
|
-
...agentConfig.toolSurface ? { runtimeToolSurface: agentConfig.toolSurface } : {},
|
|
3127
|
-
// 透出最后一轮 provider 调用的 finish_reason;多轮工具循环里只有最后一轮收尾状态有意义。
|
|
3128
|
-
...result.finish_reason ? { finish_reason: result.finish_reason } : {},
|
|
3129
|
-
dialogId: saved.dialogId,
|
|
3130
|
-
title: saved.title,
|
|
3131
|
-
turnMessages
|
|
3132
|
-
};
|
|
3133
|
-
}
|
|
3134
|
-
|
|
3135
|
-
export {
|
|
3136
|
-
readCommandActionGatePayload,
|
|
3137
|
-
readActionGate,
|
|
3138
|
-
parseToolArgumentsJson,
|
|
3139
|
-
summarizeToolArguments,
|
|
3140
|
-
getFullChatContextKeys,
|
|
3141
|
-
deduplicateContextKeys,
|
|
3142
|
-
resolveHistoricalToolContentCap,
|
|
3143
|
-
inferCaptureIntent,
|
|
3144
|
-
compressOldToolResults,
|
|
3145
|
-
trimMessagesWithSummary,
|
|
3146
|
-
validateAccessAndBalance,
|
|
3147
|
-
buildStaticContexts,
|
|
3148
|
-
buildDynamicContexts,
|
|
3149
|
-
mergeContexts,
|
|
3150
|
-
mergeAgentToolsWithRuntime,
|
|
3151
|
-
applyImageConfigRuntimeOverride,
|
|
3152
|
-
resolveImageGenerationStreamingState,
|
|
3153
|
-
tryPreprocessWebImageOrReject,
|
|
3154
|
-
LOCAL_AGENT_CONFIG_MISSING_CODE,
|
|
3155
|
-
EMPTY_ASSISTANT_REPAIR_PROMPT,
|
|
3156
|
-
LOCAL_TURN_ABORTED_CODE,
|
|
3157
|
-
runLocalAgentTurn
|
|
3158
|
-
};
|