nolo-cli 0.1.10 → 0.1.11

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.
Files changed (240) hide show
  1. package/README.md +0 -32
  2. package/agentRuntimeCommands.ts +3 -3
  3. package/commandRegistry.ts +2 -2
  4. package/machineCommands.ts +31 -6
  5. package/package.json +6 -22
  6. package/ai/agent/_executeModel.ts +0 -118
  7. package/ai/agent/agentSlice.ts +0 -525
  8. package/ai/agent/appWorkingMemory.ts +0 -126
  9. package/ai/agent/avatarUtils.ts +0 -24
  10. package/ai/agent/buildEditingContext.ts +0 -373
  11. package/ai/agent/buildSystemPrompt.ts +0 -532
  12. package/ai/agent/cleanAgentMessages.ts +0 -140
  13. package/ai/agent/cliChatClient.ts +0 -119
  14. package/ai/agent/cliExecutor.ts +0 -733
  15. package/ai/agent/cliPrompt.ts +0 -10
  16. package/ai/agent/contextCompiler.ts +0 -107
  17. package/ai/agent/contextLayerContract.ts +0 -44
  18. package/ai/agent/createAgentSchema.ts +0 -234
  19. package/ai/agent/executeToolCall.ts +0 -58
  20. package/ai/agent/fetchAgentContexts.ts +0 -42
  21. package/ai/agent/generatePrompt.ts +0 -3
  22. package/ai/agent/getFullChatContextKeys.ts +0 -168
  23. package/ai/agent/hooks/fetchPublicAgents.ts +0 -133
  24. package/ai/agent/hooks/useAgentConfig.ts +0 -61
  25. package/ai/agent/hooks/useAgentDialog.ts +0 -35
  26. package/ai/agent/hooks/useAgentFormValidation.ts +0 -202
  27. package/ai/agent/hooks/usePublicAgents.ts +0 -473
  28. package/ai/agent/machineRunPermissions.ts +0 -95
  29. package/ai/agent/persistMessageWithFixedId.ts +0 -37
  30. package/ai/agent/planSlice.ts +0 -259
  31. package/ai/agent/referenceUtils.ts +0 -229
  32. package/ai/agent/runAgentBackground.ts +0 -238
  33. package/ai/agent/runAgentClientLoop.ts +0 -138
  34. package/ai/agent/runtimeGuidance.ts +0 -97
  35. package/ai/agent/runtimeServerBase.ts +0 -37
  36. package/ai/agent/server/fetchPublicAgents.ts +0 -128
  37. package/ai/agent/startParallelAgentStreams.ts +0 -424
  38. package/ai/agent/startupProtocol.ts +0 -53
  39. package/ai/agent/streamAgentChatTurn.ts +0 -1278
  40. package/ai/agent/streamAgentChatTurnUtils.ts +0 -738
  41. package/ai/agent/types.ts +0 -71
  42. package/ai/agent/utils/imageOutput.ts +0 -33
  43. package/ai/agent/utils/sortUtils.ts +0 -250
  44. package/ai/agent/web/referencePickerUtils.ts +0 -146
  45. package/ai/ai.locale.ts +0 -1079
  46. package/ai/chat/accumulateToolCallChunks.ts +0 -95
  47. package/ai/chat/fetchUtils.native.ts +0 -276
  48. package/ai/chat/fetchUtils.ts +0 -153
  49. package/ai/chat/parseApiError.ts +0 -64
  50. package/ai/chat/parseMultilineSSE.ts +0 -95
  51. package/ai/chat/sendOpenAICompletionsRequest.native.ts +0 -682
  52. package/ai/chat/sendOpenAICompletionsRequest.ts +0 -703
  53. package/ai/chat/sendOpenAIResponseRequest.ts +0 -491
  54. package/ai/chat/shouldUseServerProxy.ts +0 -18
  55. package/ai/chat/sseClient.native.ts +0 -91
  56. package/ai/chat/sseClient.ts +0 -67
  57. package/ai/chat/streamReader.native.ts +0 -31
  58. package/ai/chat/streamReader.ts +0 -62
  59. package/ai/chat/updateTotalUsage.ts +0 -72
  60. package/ai/context/buildReferenceContext.ts +0 -437
  61. package/ai/context/calculateContextUsage.ts +0 -133
  62. package/ai/context/retention.ts +0 -165
  63. package/ai/context/tokenUtils.ts +0 -78
  64. package/ai/index.ts +0 -1
  65. package/ai/llm/calculateGeminiImageTokens.ts +0 -57
  66. package/ai/llm/deepinfra.ts +0 -28
  67. package/ai/llm/fireworks.ts +0 -50
  68. package/ai/llm/generateRequestBody.ts +0 -165
  69. package/ai/llm/getModelContextWindow.ts +0 -84
  70. package/ai/llm/getNoloKey.ts +0 -31
  71. package/ai/llm/getPricing.ts +0 -199
  72. package/ai/llm/hooks/useModelPricing.ts +0 -75
  73. package/ai/llm/imagePricing.ts +0 -40
  74. package/ai/llm/isResponseAPIModel.ts +0 -13
  75. package/ai/llm/mimo.ts +0 -71
  76. package/ai/llm/mistral.ts +0 -22
  77. package/ai/llm/modelAvatar.ts +0 -427
  78. package/ai/llm/models.ts +0 -45
  79. package/ai/llm/openrouterModels.ts +0 -269
  80. package/ai/llm/providers.ts +0 -306
  81. package/ai/llm/reasoningModels.ts +0 -28
  82. package/ai/llm/types.ts +0 -59
  83. package/ai/llm/usageRequestOptions.ts +0 -59
  84. package/ai/memory/capture.ts +0 -148
  85. package/ai/memory/consolidate.ts +0 -104
  86. package/ai/memory/delete.ts +0 -147
  87. package/ai/memory/overlay.ts +0 -84
  88. package/ai/memory/query.ts +0 -38
  89. package/ai/memory/queryShared.ts +0 -160
  90. package/ai/memory/rank.ts +0 -105
  91. package/ai/memory/recentRelationshipRecap.ts +0 -249
  92. package/ai/memory/remember.ts +0 -167
  93. package/ai/memory/runtime.ts +0 -76
  94. package/ai/memory/store.ts +0 -20
  95. package/ai/memory/storeShared.ts +0 -76
  96. package/ai/memory/types.ts +0 -46
  97. package/ai/memory/understanding.ts +0 -349
  98. package/ai/memory/understandingGreeting.ts +0 -264
  99. package/ai/messages/type.ts +0 -20
  100. package/ai/policy/personalizationDialog.ts +0 -333
  101. package/ai/policy/runtimePolicy.ts +0 -440
  102. package/ai/policy/selfUpdateFields.ts +0 -48
  103. package/ai/policy/types.ts +0 -64
  104. package/ai/skills/referenceRuntime.ts +0 -274
  105. package/ai/skills/skillDiagnostics.ts +0 -251
  106. package/ai/skills/skillDocBuilder.ts +0 -139
  107. package/ai/skills/skillDocProtocol.ts +0 -434
  108. package/ai/skills/skillReferenceSummary.ts +0 -63
  109. package/ai/skills/skillSummaryMarker.ts +0 -26
  110. package/ai/token/calculatePrice.ts +0 -544
  111. package/ai/token/db.ts +0 -98
  112. package/ai/token/externalToolCost.ts +0 -330
  113. package/ai/token/hooks/useRecords.ts +0 -65
  114. package/ai/token/missingUsageEstimate.ts +0 -42
  115. package/ai/token/modelUsageQuery.ts +0 -252
  116. package/ai/token/normalizeUsage.ts +0 -84
  117. package/ai/token/openaiImageGenerationUsage.ts +0 -56
  118. package/ai/token/prepareTokenUsageData.ts +0 -88
  119. package/ai/token/query.ts +0 -88
  120. package/ai/token/queryUserTokens.ts +0 -59
  121. package/ai/token/resolveBillingTarget.ts +0 -52
  122. package/ai/token/saveTokenRecord.ts +0 -53
  123. package/ai/token/serverDialogProjection.ts +0 -78
  124. package/ai/token/serverTokenWriter.ts +0 -143
  125. package/ai/token/stats.ts +0 -21
  126. package/ai/token/tokenThunks.ts +0 -24
  127. package/ai/token/types.ts +0 -93
  128. package/ai/tools/agent/agentTools.ts +0 -176
  129. package/ai/tools/agent/agentUpdateShared.ts +0 -311
  130. package/ai/tools/agent/callAgentTool.ts +0 -139
  131. package/ai/tools/agent/createAgentTool.ts +0 -512
  132. package/ai/tools/agent/createDialogTool.ts +0 -69
  133. package/ai/tools/agent/createSkillAgentTool.ts +0 -62
  134. package/ai/tools/agent/parallelBudget.ts +0 -221
  135. package/ai/tools/agent/presets/appBuilderPreset.ts +0 -145
  136. package/ai/tools/agent/runLlmTool.ts +0 -96
  137. package/ai/tools/agent/runStreamingAgentTool.ts +0 -73
  138. package/ai/tools/agent/skillAgentArgs.ts +0 -106
  139. package/ai/tools/agent/skillAgentPreset.ts +0 -89
  140. package/ai/tools/agent/streamParallelAgentsTool.ts +0 -122
  141. package/ai/tools/agent/updateAgentTool.ts +0 -96
  142. package/ai/tools/agent/updateSelfTool.ts +0 -113
  143. package/ai/tools/amazonProductScraperTool.ts +0 -86
  144. package/ai/tools/apifyActorClient.ts +0 -45
  145. package/ai/tools/appEditGuard.ts +0 -372
  146. package/ai/tools/appReadSnapshot.ts +0 -153
  147. package/ai/tools/appTools.ts +0 -1549
  148. package/ai/tools/applyEditTool.ts +0 -256
  149. package/ai/tools/applyLineEditsTool.ts +0 -312
  150. package/ai/tools/browserTools/click.ts +0 -33
  151. package/ai/tools/browserTools/closeSession.ts +0 -29
  152. package/ai/tools/browserTools/common.ts +0 -27
  153. package/ai/tools/browserTools/openSession.ts +0 -48
  154. package/ai/tools/browserTools/readContent.ts +0 -38
  155. package/ai/tools/browserTools/selectOption.ts +0 -46
  156. package/ai/tools/browserTools/typeText.ts +0 -42
  157. package/ai/tools/category/createCategoryTool.ts +0 -66
  158. package/ai/tools/category/queryContentsByCategoryTool.ts +0 -69
  159. package/ai/tools/category/updateContentCategoryTool.ts +0 -75
  160. package/ai/tools/cfBrowserTools.ts +0 -319
  161. package/ai/tools/cfSpeechToTextTool.ts +0 -49
  162. package/ai/tools/checkEnvTool.ts +0 -65
  163. package/ai/tools/cloudflareCrawlTool.ts +0 -289
  164. package/ai/tools/codeSearchTool.ts +0 -111
  165. package/ai/tools/codeTools.ts +0 -101
  166. package/ai/tools/createDocTool.ts +0 -132
  167. package/ai/tools/createPlanTool.ts +0 -999
  168. package/ai/tools/createSkillDocTool.ts +0 -155
  169. package/ai/tools/createWorkflowTool.ts +0 -154
  170. package/ai/tools/deepseekOcrTool.ts +0 -34
  171. package/ai/tools/delayTool.ts +0 -31
  172. package/ai/tools/deleteSpacesTool.ts +0 -325
  173. package/ai/tools/deleteSpacesToolModel.ts +0 -159
  174. package/ai/tools/devReloadUtils.ts +0 -29
  175. package/ai/tools/dialogMessageSearch.ts +0 -137
  176. package/ai/tools/doctorSkillTool.ts +0 -72
  177. package/ai/tools/ecommerceScraperTool.ts +0 -86
  178. package/ai/tools/emailTools.ts +0 -549
  179. package/ai/tools/evalSkillTool.ts +0 -92
  180. package/ai/tools/exaSearchTool.ts +0 -64
  181. package/ai/tools/execBashTool.ts +0 -379
  182. package/ai/tools/executeSqlTool.ts +0 -192
  183. package/ai/tools/fetchWebpageSupport.ts +0 -309
  184. package/ai/tools/fetchWebpageTool.ts +0 -84
  185. package/ai/tools/geminiImagePreviewTool.ts +0 -361
  186. package/ai/tools/generateDocxTool.ts +0 -215
  187. package/ai/tools/googleSearchScraperTool.ts +0 -106
  188. package/ai/tools/importDataTool.ts +0 -133
  189. package/ai/tools/importSkillTool.ts +0 -162
  190. package/ai/tools/index.ts +0 -1858
  191. package/ai/tools/listFilesTool.ts +0 -82
  192. package/ai/tools/listUserSpacesTool.ts +0 -113
  193. package/ai/tools/modelUsageTools.ts +0 -142
  194. package/ai/tools/olmOcrTool.ts +0 -34
  195. package/ai/tools/openaiImageTool.ts +0 -218
  196. package/ai/tools/paddleOcrTool.ts +0 -34
  197. package/ai/tools/prepareTools.ts +0 -23
  198. package/ai/tools/readDocTool.ts +0 -84
  199. package/ai/tools/readFileTool.ts +0 -211
  200. package/ai/tools/readTool.ts +0 -163
  201. package/ai/tools/readXPostTool.ts +0 -233
  202. package/ai/tools/rememberMemoryTool.ts +0 -84
  203. package/ai/tools/remotionVideoTool.ts +0 -151
  204. package/ai/tools/searchDialogMessagesTool.ts +0 -222
  205. package/ai/tools/searchRepoTool.ts +0 -115
  206. package/ai/tools/searchWorkspaceTool.ts +0 -259
  207. package/ai/tools/skillFollowup.ts +0 -86
  208. package/ai/tools/surfWeatherTool.ts +0 -169
  209. package/ai/tools/table/addTableRowTool.ts +0 -217
  210. package/ai/tools/table/createTableTool.ts +0 -315
  211. package/ai/tools/table/rowTools.ts +0 -366
  212. package/ai/tools/table/schemaTools.ts +0 -244
  213. package/ai/tools/table/shareTableTool.ts +0 -148
  214. package/ai/tools/table/toolShared.ts +0 -129
  215. package/ai/tools/toolApiClient.ts +0 -198
  216. package/ai/tools/toolNameAliases.ts +0 -57
  217. package/ai/tools/toolResultError.ts +0 -42
  218. package/ai/tools/toolRunSlice.ts +0 -303
  219. package/ai/tools/toolSchemaCompatibility.ts +0 -53
  220. package/ai/tools/toolVisibility.ts +0 -4
  221. package/ai/tools/types.ts +0 -20
  222. package/ai/tools/uiAskChoiceTool.ts +0 -104
  223. package/ai/tools/updateContentTitleTool.ts +0 -84
  224. package/ai/tools/updateDocTool.ts +0 -105
  225. package/ai/tools/updateUserPreferenceProfileTool.ts +0 -145
  226. package/ai/tools/whisperTool.ts +0 -77
  227. package/ai/tools/writeFileTool.ts +0 -210
  228. package/ai/tools/youtubeScraperTool.ts +0 -116
  229. package/ai/tools/ziweiChartTool.ts +0 -678
  230. package/ai/types.ts +0 -55
  231. package/ai/workflow/workflowExecutor.ts +0 -323
  232. package/ai/workflow/workflowSlice.ts +0 -73
  233. package/ai/workflow/workflowTypes.ts +0 -106
  234. package/client/compactDialog.ts +0 -222
  235. package/connector-experimental/capabilities.ts +0 -73
  236. package/connector-experimental/codexBinary.ts +0 -41
  237. package/connector-experimental/heartbeatLoop.ts +0 -22
  238. package/connector-experimental/index.ts +0 -5
  239. package/connector-experimental/machineInfo.ts +0 -46
  240. package/connector-experimental/protocol.ts +0 -54
@@ -1,62 +0,0 @@
1
- // 文件路径: ai/chat/streamReader.ts
2
- // Web 版流式读取器 - 使用 fetch Response + ReadableStream
3
-
4
- import type { SSEClientOptions } from './sseClient';
5
-
6
- export interface StreamReaderOptions {
7
- response: Response;
8
- signal?: AbortSignal;
9
- onChunk: (chunk: string) => void;
10
- onError: (error: Error) => void;
11
- onComplete: () => void;
12
- }
13
-
14
- /**
15
- * Web 版流式读取器
16
- * 从 fetch Response 的 ReadableStream 读取数据
17
- */
18
- export async function readStream(options: StreamReaderOptions): Promise<void> {
19
- const { response, onChunk, onError, onComplete } = options;
20
-
21
- const reader = response.body?.getReader();
22
- if (!reader) {
23
- onError(new Error('Response body is not readable'));
24
- return;
25
- }
26
-
27
- const decoder = new TextDecoder();
28
-
29
- try {
30
- while (true) {
31
- const { done, value } = await reader.read();
32
-
33
- if (done) {
34
- onComplete();
35
- break;
36
- }
37
-
38
- const chunk = decoder.decode(value, { stream: true });
39
- onChunk(chunk);
40
- }
41
- } catch (error: any) {
42
- if (error?.name === 'AbortError') {
43
- onComplete();
44
- } else {
45
- onError(error instanceof Error ? error : new Error(String(error)));
46
- }
47
- } finally {
48
- try {
49
- await reader.cancel();
50
- } catch (_e) {
51
- // ignore
52
- }
53
- }
54
- }
55
-
56
- /**
57
- * 检查当前环境是否支持 ReadableStream
58
- * Web 环境返回 true,React Native 返回 false
59
- */
60
- export function supportsReadableStream(): boolean {
61
- return true;
62
- }
@@ -1,72 +0,0 @@
1
- // 文件路径: ai/chat/updateTotalUsage.ts
2
-
3
- /**
4
- * ✨ 新增辅助函数 ✨
5
- * 根据新的数据块更新累积的 token 使用量。
6
- * @param currentUsage - 当前的累积 usage 对象,可能为 null。
7
- * @param newUsageChunk - 从流中收到的新 usage 数据块。
8
- * @returns 更新后的 usage 对象。
9
- */
10
- export function updateTotalUsage(currentUsage: any, newUsageChunk: any): any {
11
- if (!newUsageChunk) {
12
- return currentUsage;
13
- }
14
-
15
- // 如果是第一次接收,直接克隆新数据块
16
- if (!currentUsage) {
17
- return { ...newUsageChunk };
18
- }
19
-
20
- // 否则,在现有基础上进行累加或更新
21
- const updatedUsage = { ...currentUsage };
22
-
23
- // === token 相关 ===
24
- updatedUsage.completion_tokens =
25
- newUsageChunk.completion_tokens ?? updatedUsage.completion_tokens;
26
- updatedUsage.prompt_tokens =
27
- newUsageChunk.prompt_tokens ?? updatedUsage.prompt_tokens;
28
- updatedUsage.total_tokens =
29
- newUsageChunk.total_tokens ?? updatedUsage.total_tokens;
30
-
31
- if (newUsageChunk.prompt_tokens_details) {
32
- updatedUsage.prompt_tokens_details = {
33
- ...(updatedUsage.prompt_tokens_details || {}),
34
- ...newUsageChunk.prompt_tokens_details,
35
- };
36
- }
37
- if (newUsageChunk.completion_tokens_details) {
38
- updatedUsage.completion_tokens_details = {
39
- ...(updatedUsage.completion_tokens_details || {}),
40
- ...newUsageChunk.completion_tokens_details,
41
- };
42
- }
43
-
44
- // === OpenRouter usage.cost 相关 ===
45
- if (typeof newUsageChunk.cost === "number") {
46
- // 对于 OpenRouter,通常只有最后一条 chunk 带 cost,这里直接覆盖即可
47
- updatedUsage.cost = newUsageChunk.cost;
48
- }
49
-
50
- if (newUsageChunk.cost_details) {
51
- updatedUsage.cost_details = {
52
- ...(updatedUsage.cost_details || {}),
53
- ...newUsageChunk.cost_details,
54
- };
55
- }
56
-
57
- if (
58
- typeof newUsageChunk.billing_provider === "string" &&
59
- newUsageChunk.billing_provider.trim()
60
- ) {
61
- updatedUsage.billing_provider = newUsageChunk.billing_provider.trim();
62
- }
63
-
64
- if (
65
- typeof newUsageChunk.billing_model === "string" &&
66
- newUsageChunk.billing_model.trim()
67
- ) {
68
- updatedUsage.billing_model = newUsageChunk.billing_model.trim();
69
- }
70
-
71
- return updatedUsage;
72
- }
@@ -1,437 +0,0 @@
1
- // ai/context/fetchReferenceContents.ts
2
-
3
- import { read } from "database/dbSlice";
4
- import { AppDispatch } from "app/store";
5
- import { slateToText } from "create/editor/transforms/slateToText";
6
- import { slateToSimplifiedMarkdown } from "create/editor/transforms/slateToSimplifiedMarkdown";
7
- import { extractCategorizedMentions } from "create/editor/utils/slateUtils";
8
- import { DialogConfig } from "app/types";
9
- import { DataType } from "create/types";
10
- import { extractCustomId } from "core/prefix";
11
- import { getRuntimeServerContext } from "database/runtimeServerContext";
12
- import { fetchAndCacheMessages } from "chat/messages/fetchAndCacheMessages";
13
- import { createSpaceKey } from "create/space/spaceKeys";
14
- import { TableMeta } from "render/table/types";
15
- import { fetchAndSerializeTable } from "render/table/utils/tableSerialization";
16
- import { estimateTokenCount } from "ai/context/tokenUtils";
17
-
18
- interface FetchOptions {
19
- format?: "json" | "text" | "simplified_markdown";
20
- inlineMentionMeta?: boolean;
21
- preloaded?: Map<string, any>;
22
- }
23
-
24
- type MentionMeta = {
25
- displayType?: string;
26
- title?: string;
27
- metaParts: string[] | readonly string[];
28
- };
29
-
30
- const MAX_META_TEXT_LENGTH = 80;
31
- const DIALOG_REFERENCE_MESSAGE_LIMIT = 20;
32
- const DIALOG_REFERENCE_SNIPPET_CHARS = 1200;
33
- const DIALOG_HANDOFF_SNIPPET_CHARS = 360;
34
-
35
- const truncateMetaText = (value: string | undefined, max = MAX_META_TEXT_LENGTH) => {
36
- if (!value) return "";
37
- if (value.length <= max) return value;
38
- return `${value.slice(0, max - 3)}...`;
39
- };
40
-
41
- const readSafe = async (dispatch: AppDispatch, dbKey: string) => {
42
- try {
43
- return await dispatch(read({
44
- dbKey: dbKey
45
- })).unwrap();
46
- } catch {
47
- return null;
48
- }
49
- };
50
-
51
- const buildMentionMetaMap = async (
52
- slateData: any,
53
- dispatch: AppDispatch
54
- ): Promise<Map<string, MentionMeta>> => {
55
- const metaMap = new Map<string, MentionMeta>();
56
- const mentions = extractCategorizedMentions(slateData);
57
-
58
- if (!mentions) return metaMap;
59
-
60
- const pageEntries = await Promise.all(
61
- (mentions.pages || []).map(async (pageId: string) => {
62
- const pageData = await readSafe(dispatch, pageId);
63
- if (!pageData) {
64
- return [`page:${pageId}`, { displayType: "page", metaParts: [] }] as const;
65
- }
66
- if (pageData.type === DataType.DIALOG) {
67
- const cybotCount = Array.isArray(pageData.cybots)
68
- ? pageData.cybots.length
69
- : 0;
70
- return [
71
- `page:${pageId}`,
72
- {
73
- displayType: "dialog",
74
- title: pageData.title,
75
- metaParts: [
76
- `cybots=${cybotCount}`,
77
- `updated=${pageData.updatedAt || pageData.updated_at || pageData.updated || "Unknown"}`,
78
- ],
79
- },
80
- ] as const;
81
- }
82
-
83
- const tags =
84
- pageData.tags && pageData.tags.length > 0
85
- ? pageData.tags.slice(0, 5).join(", ")
86
- : "";
87
- return [
88
- `page:${pageId}`,
89
- {
90
- displayType: "page",
91
- title: pageData.title,
92
- metaParts: [
93
- pageData.spaceId ? `space=${pageData.spaceId}` : "",
94
- tags ? `tags=${tags}` : "",
95
- `updated=${pageData.updatedAt || pageData.updated_at || pageData.updated || "Unknown"}`,
96
- ].filter(Boolean),
97
- },
98
- ] as const;
99
- })
100
- );
101
-
102
- pageEntries.forEach((entry: any) => metaMap.set(entry[0], entry[1]));
103
-
104
- const agentEntries = await Promise.all(
105
- (mentions.agents || []).map(async (agentId: string) => {
106
- const agentData = await readSafe(dispatch, agentId);
107
- if (!agentData) {
108
- return [`agent:${agentId}`, { displayType: "agent", metaParts: [] }] as const;
109
- }
110
- const desc = truncateMetaText(
111
- agentData.description || agentData.introduction || ""
112
- );
113
- return [
114
- `agent:${agentId}`,
115
- {
116
- displayType: "agent",
117
- title: agentData.name,
118
- metaParts: [
119
- `public=${agentData.isPublic ? "yes" : "no"}`,
120
- desc ? `desc=${desc}` : "",
121
- ].filter(Boolean),
122
- },
123
- ] as const;
124
- })
125
- );
126
-
127
- agentEntries.forEach((entry: any) => metaMap.set(entry[0], entry[1]));
128
-
129
- const spaceEntries = await Promise.all(
130
- (mentions.spaces || []).map(async (spaceId: string) => {
131
- const spaceKey = createSpaceKey.space(spaceId);
132
- const spaceData = await readSafe(dispatch, spaceKey);
133
- if (!spaceData) {
134
- return [`space:${spaceId}`, { displayType: "space", metaParts: [] }] as const;
135
- }
136
- const desc = truncateMetaText(spaceData.description || "");
137
- const categoriesCount = Object.keys(spaceData.categories || {}).length;
138
- const contentsCount = Object.keys(spaceData.contents || {}).length;
139
- return [
140
- `space:${spaceId}`,
141
- {
142
- displayType: "space",
143
- title: spaceData.name,
144
- metaParts: [
145
- desc ? `desc=${desc}` : "",
146
- `categories=${categoriesCount}`,
147
- `contents=${contentsCount}`,
148
- ].filter(Boolean),
149
- },
150
- ] as const;
151
- })
152
- );
153
-
154
- spaceEntries.forEach((entry: any) => metaMap.set(entry[0], entry[1]));
155
-
156
- return metaMap;
157
- };
158
-
159
- const buildInlineMention = (
160
- node: any,
161
- metaMap: Map<string, MentionMeta>
162
- ): string => {
163
- const resourceType = node.resourceType || "unknown";
164
- const resourceId = node.resourceId || "unknown";
165
- const key = `${resourceType}:${resourceId}`;
166
- const meta = metaMap.get(key);
167
- const label = meta?.title || node.label || resourceId || "mention";
168
- const displayType = meta?.displayType || resourceType;
169
- const metaParts = (meta?.metaParts as string[]) ?? [];
170
- const idPart =
171
- resourceType === "tool" ? `tool=${resourceId}` : `dbkey=${resourceId}`;
172
- const metaSuffix = metaParts.length ? ` | ${metaParts.join(" | ")}` : "";
173
- return `@${label}(${displayType} | ${idPart}${metaSuffix})`;
174
- };
175
-
176
- const clipReferenceText = (value: unknown, max: number) => {
177
- const raw =
178
- typeof value === "string"
179
- ? value
180
- : value == null
181
- ? ""
182
- : JSON.stringify(value);
183
- const trimmed = raw.trim();
184
- if (trimmed.length <= max) return trimmed;
185
- return `${trimmed.slice(0, max)}\n...[truncated ${trimmed.length - max} chars]`;
186
- };
187
-
188
- // --- Sub-handlers for specific types ---
189
-
190
- const fetchDialogReference = async (
191
- dbKey: string,
192
- refContent: any,
193
- dispatch: AppDispatch
194
- ): Promise<string> => {
195
- const dialogConfig = refContent as DialogConfig;
196
- const dialogTitle = dialogConfig.title || `Untitled Dialog (${dbKey})`;
197
- const dialogId = extractCustomId(dbKey) || dbKey.replace(/^dialog-/, "");
198
- const checkpoint = (dialogConfig as any).runtimeCheckpoint || null;
199
- const summary = typeof (dialogConfig as any).summary === "string"
200
- ? (dialogConfig as any).summary.trim()
201
- : "";
202
- const proactiveSummary = typeof (dialogConfig as any).proactiveSummary === "string"
203
- ? (dialogConfig as any).proactiveSummary.trim()
204
- : "";
205
-
206
- const messages = await dispatch(
207
- async (_dispatch: any, getState: any, { db }: any) => {
208
- const state = getState();
209
- const { currentToken: token, remoteServers } =
210
- getRuntimeServerContext(state);
211
-
212
- return await fetchAndCacheMessages({
213
- db,
214
- dialogId,
215
- limit: DIALOG_REFERENCE_MESSAGE_LIMIT,
216
- token,
217
- remoteServers: remoteServers.length > 0 ? remoteServers : undefined,
218
- });
219
- }
220
- );
221
-
222
- const sortedMessages = [...messages].reverse();
223
- const formatContent = (content: unknown) =>
224
- clipReferenceText(content, DIALOG_REFERENCE_SNIPPET_CHARS);
225
- const transcript = sortedMessages
226
- .map((msg: any, index) => {
227
- const toolLine = msg.toolName ? ` tool=${msg.toolName}` : "";
228
- const agentLine = msg.cybotKey ? ` agent=${msg.cybotKey}` : "";
229
- const createdLine = msg.createdAt ? ` at=${msg.createdAt}` : "";
230
- return [
231
- `### Message ${index + 1}: ${msg.role || "unknown"} id=${msg.id || "unknown"}${toolLine}${agentLine}${createdLine}`,
232
- formatContent(msg.content) || "[empty]",
233
- ].join("\n");
234
- })
235
- .join("\n\n");
236
-
237
- const checkpointLines: string[] = [];
238
- if (checkpoint && typeof checkpoint === "object") {
239
- if (checkpoint.status) checkpointLines.push(`- status: ${checkpoint.status}`);
240
- if (checkpoint.lastUserInput) checkpointLines.push(`- lastUserInput: ${formatContent(checkpoint.lastUserInput)}`);
241
- if (checkpoint.lastAssistantText) checkpointLines.push(`- lastAssistantText: ${formatContent(checkpoint.lastAssistantText)}`);
242
- if (Array.isArray(checkpoint.lastToolNames) && checkpoint.lastToolNames.length) {
243
- checkpointLines.push(`- lastToolNames: ${checkpoint.lastToolNames.join(", ")}`);
244
- }
245
- if (Array.isArray(checkpoint.availableToolNames) && checkpoint.availableToolNames.length) {
246
- checkpointLines.push(`- availableToolNames: ${checkpoint.availableToolNames.join(", ")}`);
247
- }
248
- }
249
-
250
- const recentToolEvidence = sortedMessages
251
- .filter((msg: any) => msg.role === "tool" || msg.toolName)
252
- .slice(-3)
253
- .map((msg: any) => {
254
- const label = msg.toolName ? `${msg.toolName}` : "tool";
255
- return `- ${label} id=${msg.id || "unknown"}: ${clipReferenceText(msg.content, DIALOG_HANDOFF_SNIPPET_CHARS) || "[empty]"}`;
256
- });
257
-
258
- const handoffLines = [
259
- `- Use this when continuing work, transferring to another Agent, comparing with the current task, or preparing a document/plan from the prior discussion.`,
260
- `- Current state source: ${checkpointLines.length ? "Runtime Checkpoint" : "summaries and recent transcript"}.`,
261
- summary ? `- Compressed background: passive summary is available below; treat it as lossy, not original wording.` : "",
262
- proactiveSummary ? `- Recent work: proactive summary is available below; use it for current direction, not exact evidence.` : "",
263
- recentToolEvidence.length
264
- ? `- Recent tool evidence:\n${recentToolEvidence.join("\n")}`
265
- : `- Recent tool evidence: none loaded in the latest ${DIALOG_REFERENCE_MESSAGE_LIMIT} messages.`,
266
- `- For exact claims, old decisions, original wording, files/tools mentioned earlier, or anything not visible in the recent transcript, call searchDialogMessages with DB Key ${dbKey}.`,
267
- ].filter(Boolean);
268
-
269
- const referenceBody = [
270
- `Conversation Reference:`,
271
- `DB Key: ${dbKey}`,
272
- `Title: ${dialogTitle}`,
273
- `Status: ${(dialogConfig as any).status || "unknown"}`,
274
- `Loaded Recent Messages: ${sortedMessages.length}`,
275
- `Conversation Handoff:\n${handoffLines.join("\n")}`,
276
- checkpointLines.length ? `Runtime Checkpoint:\n${checkpointLines.join("\n")}` : "",
277
- summary ? `Passive Summary (compressed history, not original wording):\n${summary}` : "",
278
- proactiveSummary ? `Proactive Summary (recent work summary, not original wording):\n${proactiveSummary}` : "",
279
- `Recent Transcript (original message excerpts, oldest to newest):\n${transcript || "[no recent messages loaded]"}`,
280
- [
281
- `Coverage Note: This reference intentionally loads only the latest ${DIALOG_REFERENCE_MESSAGE_LIMIT} messages plus summaries/checkpoint to control token load.`,
282
- `Original Message Lookup Policy: If the user asks for an exact old message, original wording, who said what, why a decision was made, early-history detail, file/tool evidence, failed attempts, or a comparison with prior work, use searchDialogMessages({ dialogKey: "${dbKey}", query: "..." }) before making a factual claim from this referenced conversation.`,
283
- ].join("\n"),
284
- ].filter(Boolean).join("\n\n");
285
-
286
- const tokenEstimate = estimateTokenCount(referenceBody);
287
-
288
- return (
289
- `${referenceBody}\n\n` +
290
- `Token Load Estimate: ${tokenEstimate} tokens for this conversation reference.\n` +
291
- `---\n\n`
292
- );
293
- };
294
-
295
- const fetchTableReference = async (
296
- dbKey: string,
297
- refContent: any,
298
- dispatch: AppDispatch
299
- ): Promise<string> => {
300
- const tableMeta = refContent as TableMeta;
301
- const title = tableMeta.displayName || tableMeta.description || `Untitled Table (${dbKey})`;
302
-
303
- const { markdown: tableMd } = await dispatch(
304
- async (_dispatch: any, getState: any, { db }: any) => {
305
- const state = getState();
306
- const { currentToken: token, remoteServers } =
307
- getRuntimeServerContext(state);
308
-
309
- return await fetchAndSerializeTable(tableMeta, db, {
310
- token,
311
- remoteServers,
312
- });
313
- }
314
- );
315
-
316
- const tags = tableMeta.tags?.length ? tableMeta.tags.join(", ") : "None";
317
- const description = tableMeta.description || "No description provided.";
318
-
319
- return (
320
- `Reference Item (Table):\n` +
321
- `DB Key: ${dbKey}\n` +
322
- `Title: ${title}\n` +
323
- `Description: ${description}\n` +
324
- `Tags: ${tags}\n` +
325
- `Content (Markdown Table):\n\n${tableMd}\n` +
326
- `---\n\n`
327
- );
328
- };
329
-
330
- const fetchSlateReference = async (
331
- dbKey: string,
332
- refContent: any,
333
- dispatch: AppDispatch,
334
- options: FetchOptions
335
- ): Promise<string | null> => {
336
- if (!refContent?.slateData) return null;
337
-
338
- const title = refContent.title || `Untitled (${dbKey})`;
339
- let contentString: string;
340
- let contentType: string;
341
- const inlineMentionMeta =
342
- options.inlineMentionMeta ?? options.format === "simplified_markdown";
343
-
344
- switch (options.format) {
345
- case "text":
346
- contentType = "Plain Text";
347
- contentString = slateToText(refContent.slateData);
348
- break;
349
- case "simplified_markdown":
350
- contentType = "Simplified Markdown";
351
- if (inlineMentionMeta) {
352
- const metaMap = await buildMentionMetaMap(refContent.slateData, dispatch);
353
- contentString = slateToSimplifiedMarkdown(refContent.slateData, {
354
- mentionResolver: (node) => buildInlineMention(node, metaMap),
355
- });
356
- } else {
357
- contentString = slateToSimplifiedMarkdown(refContent.slateData);
358
- }
359
- break;
360
- case "json":
361
- default:
362
- contentType = "Slate JSON";
363
- contentString = JSON.stringify(refContent.slateData, null, 2);
364
- break;
365
- }
366
-
367
- if (
368
- !contentString ||
369
- (typeof contentString === "string" && !contentString.trim()) ||
370
- contentString === "[]"
371
- ) {
372
- return null;
373
- }
374
-
375
- const tags = (refContent.tags || []).length > 0 ? refContent.tags.join(", ") : "None";
376
- const createdAt = refContent.created || "Unknown Creation Date";
377
- const updatedAt = refContent.updated || "Unknown Update Date";
378
-
379
- return (
380
- `Reference Item:\n` +
381
- `DB Key: ${dbKey}\n` +
382
- `Title: ${title}\n` +
383
- `Content (${contentType}):\n${contentString}\n` +
384
- `Tags: ${tags}\n` +
385
- `Created At: ${createdAt}\n` +
386
- `Updated At: ${updatedAt}\n` +
387
- `---\n\n`
388
- );
389
- };
390
-
391
- /**
392
- * 智能地获取并格式化参考内容。
393
- */
394
- export const fetchReferenceContents = async (
395
- references: string[],
396
- dispatch: AppDispatch,
397
- options: FetchOptions = { format: "simplified_markdown" }
398
- ): Promise<Map<string, string>> => {
399
- const result = new Map<string, string>();
400
- if (!references || references.length === 0) return result;
401
-
402
- const referencePromises = references.map(async (dbKey) => {
403
- try {
404
- const hasPreloaded = options.preloaded?.has(dbKey);
405
- const refContent = hasPreloaded
406
- ? options.preloaded?.get(dbKey)
407
- : await dispatch(read({
408
- dbKey: dbKey
409
- })).unwrap();
410
-
411
- if (!refContent) return null;
412
-
413
- let formatted: string | null = null;
414
-
415
- if (refContent.type === DataType.DIALOG) {
416
- formatted = await fetchDialogReference(dbKey, refContent, dispatch);
417
- } else if (refContent.type === DataType.TABLE) {
418
- formatted = await fetchTableReference(dbKey, refContent, dispatch);
419
- } else {
420
- formatted = await fetchSlateReference(dbKey, refContent, dispatch, options);
421
- }
422
-
423
- if (formatted) return [dbKey, formatted] as [string, string];
424
- return null;
425
- } catch (error: any) {
426
- console.error(`Error fetching reference ${dbKey}:`, error);
427
- return null;
428
- }
429
- });
430
-
431
- const resolved = await Promise.all(referencePromises);
432
- resolved.forEach((item) => {
433
- if (item) result.set(item[0], item[1]);
434
- });
435
-
436
- return result;
437
- };
@@ -1,133 +0,0 @@
1
- // ai/context/calculateContextUsage.ts
2
-
3
- /**
4
- * 计算 Agent 的 Context 使用情况。
5
- *
6
- * 用于:
7
- * 1. Agent 编辑页面的 Token 预算可视化
8
- * 2. 运行时的 Context 监控
9
- * 3. 超标警告
10
- */
11
-
12
- import { estimateTokenCount, CONTEXT_BUDGET, calcTokenUsagePercent } from "./tokenUtils";
13
- import { getModelContextWindow } from "../llm/getModelContextWindow";
14
- import type { ReferenceItem } from "app/types";
15
-
16
- export interface ContextUsageBreakdown {
17
- // 各部分 Token 使用
18
- referencesTokens: number;
19
- spaceContextTokens: number;
20
- systemPromptTokens: number;
21
- historyTokens: number;
22
-
23
- // 总计
24
- totalUsed: number;
25
- modelContextWindow: number;
26
- availableTokens: number;
27
-
28
- // 百分比
29
- usedPercent: number;
30
- referencesPercent: number;
31
-
32
- // 状态
33
- isWarning: boolean;
34
- isCritical: boolean;
35
- warningMessage?: string;
36
- }
37
-
38
- export interface ContextUsageInput {
39
- modelName: string;
40
- references?: ReferenceItem[];
41
- referencesContent?: string; // 如果已经拼接好的内容
42
- spaceContext?: string | null;
43
- systemPrompt?: string;
44
- historyContext?: string | null;
45
- }
46
-
47
- /**
48
- * 计算 Context 使用情况
49
- */
50
- export const calculateContextUsage = (input: ContextUsageInput): ContextUsageBreakdown => {
51
- const {
52
- modelName,
53
- references,
54
- referencesContent,
55
- spaceContext,
56
- systemPrompt,
57
- historyContext,
58
- } = input;
59
-
60
- // 获取模型的 Context Window
61
- const modelContextWindow = getModelContextWindow(modelName);
62
-
63
- // 估算各部分 Token 数
64
- // References: 如果提供了 content 直接用,否则根据数量估算
65
- let referencesTokens = 0;
66
- if (referencesContent) {
67
- referencesTokens = estimateTokenCount(referencesContent);
68
- } else if (references && references.length > 0) {
69
- // 粗略估算:每个 reference 平均 2000 tokens(需要实际获取内容才能精确)
70
- referencesTokens = references.length * 2000;
71
- }
72
-
73
- const spaceContextTokens = estimateTokenCount(spaceContext || "");
74
- const systemPromptTokens = estimateTokenCount(systemPrompt || "");
75
- const historyTokens = estimateTokenCount(historyContext || "");
76
-
77
- // 计算总使用量(References + Space 是预分配的,其他是动态的)
78
- const preAllocatedTokens = referencesTokens + spaceContextTokens;
79
- const totalUsed = preAllocatedTokens + systemPromptTokens + historyTokens;
80
- const availableTokens = modelContextWindow - totalUsed;
81
-
82
- // 计算百分比
83
- const usedPercent = calcTokenUsagePercent(totalUsed, modelContextWindow);
84
- const referencesPercent = calcTokenUsagePercent(preAllocatedTokens, modelContextWindow);
85
-
86
- // 判断状态
87
- const isWarning = referencesPercent > CONTEXT_BUDGET.REFERENCES_MAX_PERCENT;
88
- const isCritical = usedPercent > 80;
89
-
90
- // 生成警告消息
91
- let warningMessage: string | undefined;
92
- if (isCritical) {
93
- warningMessage = `⚠️ 上下文已使用 ${usedPercent}%,可能影响对话质量。建议减少 References 或 Space 内容。`;
94
- } else if (isWarning) {
95
- warningMessage = `⚡ References 和 Space 已占用 ${referencesPercent}% 上下文,建议控制在 ${CONTEXT_BUDGET.REFERENCES_MAX_PERCENT}% 以内。`;
96
- }
97
-
98
- return {
99
- referencesTokens,
100
- spaceContextTokens,
101
- systemPromptTokens,
102
- historyTokens,
103
- totalUsed,
104
- modelContextWindow,
105
- availableTokens,
106
- usedPercent,
107
- referencesPercent,
108
- isWarning,
109
- isCritical,
110
- warningMessage,
111
- };
112
- };
113
-
114
- /**
115
- * 快速检查 References 是否超标
116
- * 用于 Agent 编辑页面的实时反馈
117
- */
118
- export const checkReferencesOverBudget = (
119
- modelName: string,
120
- referencesTokens: number
121
- ): { isOver: boolean; percent: number; message?: string } => {
122
- const modelContextWindow = getModelContextWindow(modelName);
123
- const percent = calcTokenUsagePercent(referencesTokens, modelContextWindow);
124
- const isOver = percent > CONTEXT_BUDGET.REFERENCES_MAX_PERCENT;
125
-
126
- return {
127
- isOver,
128
- percent,
129
- message: isOver
130
- ? `References 占用 ${percent}%,超过建议上限 ${CONTEXT_BUDGET.REFERENCES_MAX_PERCENT}%`
131
- : undefined,
132
- };
133
- };