@renxqoo/renx-code 0.0.4 → 0.0.6

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 (210) hide show
  1. package/README.md +82 -51
  2. package/bin/renx.cjs +16 -0
  3. package/package.json +2 -45
  4. package/src/agent/runtime/runtime.context-usage.test.ts +4 -5
  5. package/src/agent/runtime/runtime.error-handling.test.ts +4 -5
  6. package/src/agent/runtime/runtime.test.ts +7 -4
  7. package/src/agent/runtime/runtime.ts +3 -9
  8. package/src/agent/runtime/runtime.usage-forwarding.test.ts +4 -5
  9. package/src/agent/runtime/source-modules.test.ts +16 -35
  10. package/src/agent/runtime/source-modules.ts +17 -0
  11. package/vendor/agent-root/src/agent/ENTERPRISE_ACCEPTANCE_CHECKLIST.md +95 -0
  12. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.html +1345 -0
  13. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.md +1353 -0
  14. package/vendor/agent-root/src/agent/ERROR_CONTRACT.md +60 -0
  15. package/vendor/agent-root/src/agent/TEST_COVERAGE_ANALYSIS.md +278 -0
  16. package/vendor/agent-root/src/agent/__test__/error-contract.test.ts +72 -0
  17. package/vendor/agent-root/src/agent/__test__/types.test.ts +137 -0
  18. package/vendor/agent-root/src/agent/agent/__test__/abort-runtime.test.ts +83 -0
  19. package/vendor/agent-root/src/agent/agent/__test__/callback-safety.test.ts +34 -0
  20. package/vendor/agent-root/src/agent/agent/__test__/compaction.test.ts +323 -0
  21. package/vendor/agent-root/src/agent/agent/__test__/concurrency.test.ts +290 -0
  22. package/vendor/agent-root/src/agent/agent/__test__/error-normalizer.test.ts +377 -0
  23. package/vendor/agent-root/src/agent/agent/__test__/error.test.ts +212 -0
  24. package/vendor/agent-root/src/agent/agent/__test__/fault-injection.test.ts +295 -0
  25. package/vendor/agent-root/src/agent/agent/__test__/index.test.ts +3607 -0
  26. package/vendor/agent-root/src/agent/agent/__test__/logger.test.ts +35 -0
  27. package/vendor/agent-root/src/agent/agent/__test__/message-utils.test.ts +517 -0
  28. package/vendor/agent-root/src/agent/agent/__test__/telemetry.test.ts +97 -0
  29. package/vendor/agent-root/src/agent/agent/__test__/timeout-budget.test.ts +479 -0
  30. package/vendor/agent-root/src/agent/agent/__test__/tool-call-merge.test.ts +80 -0
  31. package/vendor/agent-root/src/agent/agent/__test__/tool-execution-ledger.test.ts +76 -0
  32. package/vendor/agent-root/src/agent/agent/__test__/write-buffer.test.ts +173 -0
  33. package/vendor/agent-root/src/agent/agent/__test__/write-file-session.test.ts +109 -0
  34. package/vendor/agent-root/src/agent/agent/abort-runtime.ts +71 -0
  35. package/vendor/agent-root/src/agent/agent/callback-safety.ts +33 -0
  36. package/vendor/agent-root/src/agent/agent/compaction.ts +291 -0
  37. package/vendor/agent-root/src/agent/agent/concurrency.ts +103 -0
  38. package/vendor/agent-root/src/agent/agent/error-normalizer.ts +190 -0
  39. package/vendor/agent-root/src/agent/agent/error.ts +198 -0
  40. package/vendor/agent-root/src/agent/agent/index.ts +1772 -0
  41. package/vendor/agent-root/src/agent/agent/logger.ts +65 -0
  42. package/vendor/agent-root/src/agent/agent/message-utils.ts +101 -0
  43. package/vendor/agent-root/src/agent/agent/stream-events.ts +61 -0
  44. package/vendor/agent-root/src/agent/agent/telemetry.ts +123 -0
  45. package/vendor/agent-root/src/agent/agent/timeout-budget.ts +227 -0
  46. package/vendor/agent-root/src/agent/agent/tool-call-merge.ts +111 -0
  47. package/vendor/agent-root/src/agent/agent/tool-execution-ledger.ts +164 -0
  48. package/vendor/agent-root/src/agent/agent/write-buffer.ts +188 -0
  49. package/vendor/agent-root/src/agent/agent/write-file-session.ts +238 -0
  50. package/vendor/agent-root/src/agent/app/__test__/agent-app-service.test.ts +1053 -0
  51. package/vendor/agent-root/src/agent/app/__test__/minimal-agent-application.test.ts +158 -0
  52. package/vendor/agent-root/src/agent/app/__test__/sqlite-agent-app-store.test.ts +437 -0
  53. package/vendor/agent-root/src/agent/app/agent-app-service.ts +748 -0
  54. package/vendor/agent-root/src/agent/app/contracts.ts +109 -0
  55. package/vendor/agent-root/src/agent/app/index.ts +5 -0
  56. package/vendor/agent-root/src/agent/app/minimal-agent-application.ts +151 -0
  57. package/vendor/agent-root/src/agent/app/ports.ts +72 -0
  58. package/vendor/agent-root/src/agent/app/sqlite-agent-app-store.ts +1182 -0
  59. package/vendor/agent-root/src/agent/app/sqlite-client.ts +177 -0
  60. package/vendor/agent-root/src/agent/docs/cli-app-layer/00-README.md +36 -0
  61. package/vendor/agent-root/src/agent/docs/cli-app-layer/01-scope-and-goals.md +33 -0
  62. package/vendor/agent-root/src/agent/docs/cli-app-layer/02-architecture-overview.md +40 -0
  63. package/vendor/agent-root/src/agent/docs/cli-app-layer/03-domain-model-and-contracts.md +91 -0
  64. package/vendor/agent-root/src/agent/docs/cli-app-layer/04-ports-and-interfaces.md +116 -0
  65. package/vendor/agent-root/src/agent/docs/cli-app-layer/05-run-orchestration-and-state-machine.md +52 -0
  66. package/vendor/agent-root/src/agent/docs/cli-app-layer/06-cli-commands-and-ux.md +53 -0
  67. package/vendor/agent-root/src/agent/docs/cli-app-layer/07-storage-design-local.md +52 -0
  68. package/vendor/agent-root/src/agent/docs/cli-app-layer/08-error-and-observability.md +40 -0
  69. package/vendor/agent-root/src/agent/docs/cli-app-layer/09-security-and-policy-boundary.md +19 -0
  70. package/vendor/agent-root/src/agent/docs/cli-app-layer/10-test-plan-and-acceptance.md +28 -0
  71. package/vendor/agent-root/src/agent/docs/cli-app-layer/11-implementation-phases.md +26 -0
  72. package/vendor/agent-root/src/agent/docs/cli-app-layer/12-open-questions-and-risks.md +30 -0
  73. package/vendor/agent-root/src/agent/docs/cli-app-layer/13-sqlite-schema-fields-and-rationale.md +567 -0
  74. package/vendor/agent-root/src/agent/docs/cli-app-layer/14-project-flow-mermaid.md +583 -0
  75. package/vendor/agent-root/src/agent/docs/cli-app-layer/15-openclaw-style-project-blueprint.md +972 -0
  76. package/vendor/agent-root/src/agent/error-contract.ts +154 -0
  77. package/vendor/agent-root/src/agent/prompts/system.ts +246 -0
  78. package/vendor/agent-root/src/agent/prompts/system1.ts +208 -0
  79. package/vendor/agent-root/src/agent/storage/__test__/file-history-store.test.ts +98 -0
  80. package/vendor/agent-root/src/agent/storage/file-history-store.ts +313 -0
  81. package/vendor/agent-root/src/agent/storage/file-storage-config.ts +94 -0
  82. package/vendor/agent-root/src/agent/storage/file-system.ts +31 -0
  83. package/vendor/agent-root/src/agent/storage/file-write-service.ts +21 -0
  84. package/vendor/agent-root/src/agent/tool/__test__/base-tool.test.ts +413 -0
  85. package/vendor/agent-root/src/agent/tool/__test__/bash-policy.test.ts +356 -0
  86. package/vendor/agent-root/src/agent/tool/__test__/bash.mocked-coverage.test.ts +375 -0
  87. package/vendor/agent-root/src/agent/tool/__test__/bash.test.ts +372 -0
  88. package/vendor/agent-root/src/agent/tool/__test__/error.test.ts +108 -0
  89. package/vendor/agent-root/src/agent/tool/__test__/file-edit-tool.test.ts +258 -0
  90. package/vendor/agent-root/src/agent/tool/__test__/file-history-tools.test.ts +121 -0
  91. package/vendor/agent-root/src/agent/tool/__test__/file-read-tool.test.ts +210 -0
  92. package/vendor/agent-root/src/agent/tool/__test__/glob.test.ts +139 -0
  93. package/vendor/agent-root/src/agent/tool/__test__/grep.mocked-coverage.test.ts +456 -0
  94. package/vendor/agent-root/src/agent/tool/__test__/grep.test.ts +192 -0
  95. package/vendor/agent-root/src/agent/tool/__test__/lsp.test.ts +300 -0
  96. package/vendor/agent-root/src/agent/tool/__test__/outside-workspace-confirmation.test.ts +214 -0
  97. package/vendor/agent-root/src/agent/tool/__test__/path-security.test.ts +336 -0
  98. package/vendor/agent-root/src/agent/tool/__test__/skill-loader.test.ts +494 -0
  99. package/vendor/agent-root/src/agent/tool/__test__/skill-parser.test.ts +543 -0
  100. package/vendor/agent-root/src/agent/tool/__test__/skill-tool.test.ts +172 -0
  101. package/vendor/agent-root/src/agent/tool/__test__/task-concurrency-and-version.test.ts +116 -0
  102. package/vendor/agent-root/src/agent/tool/__test__/task-create-get-list-update.test.ts +267 -0
  103. package/vendor/agent-root/src/agent/tool/__test__/task-create.test.ts +519 -0
  104. package/vendor/agent-root/src/agent/tool/__test__/task-errors.test.ts +225 -0
  105. package/vendor/agent-root/src/agent/tool/__test__/task-output-blocking.test.ts +223 -0
  106. package/vendor/agent-root/src/agent/tool/__test__/task-output.test.ts +184 -0
  107. package/vendor/agent-root/src/agent/tool/__test__/task-parent-abort.test.ts +287 -0
  108. package/vendor/agent-root/src/agent/tool/__test__/task-real-runner-adapter.test.ts +190 -0
  109. package/vendor/agent-root/src/agent/tool/__test__/task-run-lifecycle.test.ts +352 -0
  110. package/vendor/agent-root/src/agent/tool/__test__/task-store-runner-branches.test.ts +395 -0
  111. package/vendor/agent-root/src/agent/tool/__test__/task-store.test.ts +391 -0
  112. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config-integration.test.ts +176 -0
  113. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config.test.ts +68 -0
  114. package/vendor/agent-root/src/agent/tool/__test__/task-tools-core-edges.test.ts +630 -0
  115. package/vendor/agent-root/src/agent/tool/__test__/task-tools-runtime-edges.test.ts +732 -0
  116. package/vendor/agent-root/src/agent/tool/__test__/task-types.test.ts +494 -0
  117. package/vendor/agent-root/src/agent/tool/__test__/task-utils-branches.test.ts +175 -0
  118. package/vendor/agent-root/src/agent/tool/__test__/tool-manager.test.ts +505 -0
  119. package/vendor/agent-root/src/agent/tool/__test__/types.test.ts +55 -0
  120. package/vendor/agent-root/src/agent/tool/__test__/web-fetch.test.ts +244 -0
  121. package/vendor/agent-root/src/agent/tool/__test__/web-search.test.ts +290 -0
  122. package/vendor/agent-root/src/agent/tool/__test__/write-file.test.ts +368 -0
  123. package/vendor/agent-root/src/agent/tool/base-tool.ts +345 -0
  124. package/vendor/agent-root/src/agent/tool/bash-policy.ts +636 -0
  125. package/vendor/agent-root/src/agent/tool/bash.ts +688 -0
  126. package/vendor/agent-root/src/agent/tool/error.ts +131 -0
  127. package/vendor/agent-root/src/agent/tool/file-edit-tool.ts +264 -0
  128. package/vendor/agent-root/src/agent/tool/file-history-list.ts +103 -0
  129. package/vendor/agent-root/src/agent/tool/file-history-restore.ts +149 -0
  130. package/vendor/agent-root/src/agent/tool/file-read-tool.ts +211 -0
  131. package/vendor/agent-root/src/agent/tool/glob.ts +171 -0
  132. package/vendor/agent-root/src/agent/tool/grep.ts +496 -0
  133. package/vendor/agent-root/src/agent/tool/lsp.ts +481 -0
  134. package/vendor/agent-root/src/agent/tool/path-security.ts +117 -0
  135. package/vendor/agent-root/src/agent/tool/search/common.ts +153 -0
  136. package/vendor/agent-root/src/agent/tool/skill/index.ts +13 -0
  137. package/vendor/agent-root/src/agent/tool/skill/loader.ts +229 -0
  138. package/vendor/agent-root/src/agent/tool/skill/parser.ts +124 -0
  139. package/vendor/agent-root/src/agent/tool/skill/types.ts +27 -0
  140. package/vendor/agent-root/src/agent/tool/skill-tool.ts +143 -0
  141. package/vendor/agent-root/src/agent/tool/task-create.ts +186 -0
  142. package/vendor/agent-root/src/agent/tool/task-errors.ts +42 -0
  143. package/vendor/agent-root/src/agent/tool/task-get.ts +116 -0
  144. package/vendor/agent-root/src/agent/tool/task-graph.ts +78 -0
  145. package/vendor/agent-root/src/agent/tool/task-list.ts +141 -0
  146. package/vendor/agent-root/src/agent/tool/task-mock-runner-adapter.ts +232 -0
  147. package/vendor/agent-root/src/agent/tool/task-output.ts +223 -0
  148. package/vendor/agent-root/src/agent/tool/task-parent-abort.ts +115 -0
  149. package/vendor/agent-root/src/agent/tool/task-real-runner-adapter.ts +336 -0
  150. package/vendor/agent-root/src/agent/tool/task-runner-adapter.ts +55 -0
  151. package/vendor/agent-root/src/agent/tool/task-stop.ts +187 -0
  152. package/vendor/agent-root/src/agent/tool/task-store.ts +217 -0
  153. package/vendor/agent-root/src/agent/tool/task-subagent-config.ts +149 -0
  154. package/vendor/agent-root/src/agent/tool/task-types.ts +264 -0
  155. package/vendor/agent-root/src/agent/tool/task-update.ts +315 -0
  156. package/vendor/agent-root/src/agent/tool/task.ts +209 -0
  157. package/vendor/agent-root/src/agent/tool/tool-manager.ts +362 -0
  158. package/vendor/agent-root/src/agent/tool/tool-prompts.ts +242 -0
  159. package/vendor/agent-root/src/agent/tool/types.ts +116 -0
  160. package/vendor/agent-root/src/agent/tool/web-fetch.ts +227 -0
  161. package/vendor/agent-root/src/agent/tool/web-search.ts +208 -0
  162. package/vendor/agent-root/src/agent/tool/write-file.ts +497 -0
  163. package/vendor/agent-root/src/agent/types.ts +232 -0
  164. package/vendor/agent-root/src/agent/utils/__tests__/index.test.ts +18 -0
  165. package/vendor/agent-root/src/agent/utils/__tests__/message-utils.test.ts +610 -0
  166. package/vendor/agent-root/src/agent/utils/__tests__/message.test.ts +223 -0
  167. package/vendor/agent-root/src/agent/utils/__tests__/token.test.ts +42 -0
  168. package/vendor/agent-root/src/agent/utils/index.ts +16 -0
  169. package/vendor/agent-root/src/agent/utils/message.ts +171 -0
  170. package/vendor/agent-root/src/agent/utils/token.ts +28 -0
  171. package/vendor/agent-root/src/config/__tests__/load-config-to-env.test.ts +129 -0
  172. package/vendor/agent-root/src/config/__tests__/loader.test.ts +247 -0
  173. package/vendor/agent-root/src/config/__tests__/runtime.test.ts +88 -0
  174. package/vendor/agent-root/src/config/index.ts +54 -0
  175. package/vendor/agent-root/src/config/loader.ts +431 -0
  176. package/vendor/agent-root/src/config/paths.ts +30 -0
  177. package/vendor/agent-root/src/config/runtime.ts +163 -0
  178. package/vendor/agent-root/src/config/types.ts +70 -0
  179. package/vendor/agent-root/src/logger/index.ts +57 -0
  180. package/vendor/agent-root/src/logger/logger.ts +819 -0
  181. package/vendor/agent-root/src/logger/types.ts +150 -0
  182. package/vendor/agent-root/src/providers/__tests__/errors.test.ts +441 -0
  183. package/vendor/agent-root/src/providers/__tests__/index.test.ts +16 -0
  184. package/vendor/agent-root/src/providers/__tests__/openai-compatible.options.test.ts +318 -0
  185. package/vendor/agent-root/src/providers/__tests__/openai-compatible.test.ts +600 -0
  186. package/vendor/agent-root/src/providers/__tests__/registry.test.ts +449 -0
  187. package/vendor/agent-root/src/providers/__tests__/responses-adapter.test.ts +298 -0
  188. package/vendor/agent-root/src/providers/adapters/__tests__/anthropic.test.ts +354 -0
  189. package/vendor/agent-root/src/providers/adapters/__tests__/kimi.test.ts +58 -0
  190. package/vendor/agent-root/src/providers/adapters/__tests__/standard.test.ts +261 -0
  191. package/vendor/agent-root/src/providers/adapters/anthropic.ts +572 -0
  192. package/vendor/agent-root/src/providers/adapters/base.ts +131 -0
  193. package/vendor/agent-root/src/providers/adapters/kimi.ts +48 -0
  194. package/vendor/agent-root/src/providers/adapters/responses.ts +732 -0
  195. package/vendor/agent-root/src/providers/adapters/standard.ts +120 -0
  196. package/vendor/agent-root/src/providers/http/__tests__/client.timeout.test.ts +313 -0
  197. package/vendor/agent-root/src/providers/http/client.ts +289 -0
  198. package/vendor/agent-root/src/providers/http/stream-parser.ts +109 -0
  199. package/vendor/agent-root/src/providers/index.ts +76 -0
  200. package/vendor/agent-root/src/providers/kimi-headers.ts +177 -0
  201. package/vendor/agent-root/src/providers/openai-compatible.ts +387 -0
  202. package/vendor/agent-root/src/providers/registry/model-config.ts +230 -0
  203. package/vendor/agent-root/src/providers/registry/provider-factory.ts +123 -0
  204. package/vendor/agent-root/src/providers/registry.ts +135 -0
  205. package/vendor/agent-root/src/providers/types/api.ts +284 -0
  206. package/vendor/agent-root/src/providers/types/config.ts +58 -0
  207. package/vendor/agent-root/src/providers/types/errors.ts +323 -0
  208. package/vendor/agent-root/src/providers/types/index.ts +72 -0
  209. package/vendor/agent-root/src/providers/types/provider.ts +45 -0
  210. package/vendor/agent-root/src/providers/types/registry.ts +88 -0
@@ -0,0 +1,748 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import type { LLMGenerateOptions, MessageContent, Tool, Usage } from '../../providers';
3
+ import { StatelessAgent } from '../agent';
4
+ import type { AgentLogContext, AgentLogger } from '../agent/logger';
5
+ import type { AgentCallbacks, Message } from '../types';
6
+ import type {
7
+ CliEventEnvelope,
8
+ CompactionDroppedMessageRecord,
9
+ ListRunsOptions,
10
+ ListRunsResult,
11
+ RunRecord,
12
+ RunLogLevel,
13
+ RunLogRecord,
14
+ TerminalReason,
15
+ } from './contracts';
16
+ import type {
17
+ ContextProjectionStorePort,
18
+ EventStorePort,
19
+ ExecutionStorePort,
20
+ MessageProjectionStorePort,
21
+ RunLogStorePort,
22
+ } from './ports';
23
+
24
+ type RunFinishReason = 'stop' | 'max_steps' | 'error';
25
+
26
+ interface ErrorEventPayload {
27
+ errorCode?: string;
28
+ category?: string;
29
+ message?: string;
30
+ code?: string;
31
+ retryable?: boolean;
32
+ httpStatus?: number;
33
+ name?: string;
34
+ }
35
+
36
+ export interface RunForegroundRequest {
37
+ conversationId: string;
38
+ userInput: MessageContent;
39
+ executionId?: string;
40
+ historyMessages?: Message[];
41
+ systemPrompt?: string;
42
+ tools?: Tool[];
43
+ config?: LLMGenerateOptions;
44
+ maxSteps?: number;
45
+ abortSignal?: AbortSignal;
46
+ timeoutBudgetMs?: number;
47
+ llmTimeoutRatio?: number;
48
+ contextLimitTokens?: number;
49
+ modelLabel?: string;
50
+ }
51
+
52
+ export interface RunForegroundUsage {
53
+ sequence: number;
54
+ stepIndex: number;
55
+ messageId: string;
56
+ usage: Usage;
57
+ cumulativeUsage: Usage;
58
+ contextTokens?: number;
59
+ contextLimitTokens?: number;
60
+ contextUsagePercent?: number;
61
+ }
62
+
63
+ export interface RunForegroundCallbacks extends Partial<AgentCallbacks> {
64
+ onToolStream?: (event: CliEventEnvelope) => void | Promise<void>;
65
+ onEvent?: (event: CliEventEnvelope) => void | Promise<void>;
66
+ onUsage?: (usage: RunForegroundUsage) => void | Promise<void>;
67
+ }
68
+
69
+ export interface RunForegroundResult {
70
+ executionId: string;
71
+ conversationId: string;
72
+ messages: Message[];
73
+ events: CliEventEnvelope[];
74
+ finishReason: RunFinishReason;
75
+ steps: number;
76
+ run: RunRecord;
77
+ }
78
+
79
+ export interface AgentAppServiceDeps {
80
+ agent: StatelessAgent;
81
+ executionStore: ExecutionStorePort;
82
+ eventStore: EventStorePort;
83
+ messageStore?: MessageProjectionStorePort;
84
+ runLogStore?: RunLogStorePort;
85
+ }
86
+
87
+ interface RunObservabilityContext {
88
+ executionId: string;
89
+ conversationId: string;
90
+ getStepIndex: () => number;
91
+ enqueue: (task: () => Promise<void>) => void;
92
+ appendEvent: (eventType: CliEventEnvelope['eventType'], data: unknown) => Promise<void>;
93
+ }
94
+
95
+ export class AgentAppService {
96
+ private readonly observabilityScope = new AsyncLocalStorage<RunObservabilityContext>();
97
+
98
+ constructor(private readonly deps: AgentAppServiceDeps) {
99
+ this.deps.agent.attachLogger(this.createScopedLogger());
100
+ }
101
+
102
+ async runForeground(
103
+ request: RunForegroundRequest,
104
+ callbacks?: RunForegroundCallbacks
105
+ ): Promise<RunForegroundResult> {
106
+ const executionId = request.executionId ?? createId('exec_');
107
+ const now = Date.now();
108
+ const baseMessages = request.historyMessages ? [...request.historyMessages] : [];
109
+ const userMessage = createUserMessage(request.userInput);
110
+ const inputMessages = [...baseMessages, userMessage];
111
+ const emittedMessages: Message[] = [];
112
+ const events: CliEventEnvelope[] = [];
113
+ let finishReason: RunFinishReason = 'error';
114
+ let currentStepIndex = 0;
115
+ let steps = 0;
116
+ let terminalEventSeen = false;
117
+ let latestErrorPayload: ErrorEventPayload | undefined;
118
+ let streamFailure: unknown;
119
+ let toolStreamFailure: unknown;
120
+ const cumulativeUsage: Usage = {
121
+ prompt_tokens: 0,
122
+ completion_tokens: 0,
123
+ total_tokens: 0,
124
+ };
125
+ let usageSequence = 0;
126
+ let latestContextUsage:
127
+ | {
128
+ stepIndex: number;
129
+ contextTokens: number;
130
+ contextLimitTokens: number;
131
+ contextUsagePercent: number;
132
+ }
133
+ | undefined;
134
+
135
+ await this.deps.executionStore.create({
136
+ executionId,
137
+ runId: executionId,
138
+ conversationId: request.conversationId,
139
+ status: 'CREATED',
140
+ createdAt: now,
141
+ updatedAt: now,
142
+ stepIndex: 0,
143
+ });
144
+
145
+ const appendAndProject = async (
146
+ eventType: CliEventEnvelope['eventType'],
147
+ data: unknown
148
+ ): Promise<CliEventEnvelope> => {
149
+ const envelope = await this.deps.eventStore.appendAutoSeq({
150
+ executionId,
151
+ conversationId: request.conversationId,
152
+ eventType,
153
+ data,
154
+ createdAt: Date.now(),
155
+ });
156
+ events.push(envelope);
157
+ if (this.deps.messageStore) {
158
+ await this.deps.messageStore.upsertFromEvent(envelope);
159
+ }
160
+ if (eventType === 'tool_stream') {
161
+ await callbacks?.onToolStream?.(envelope);
162
+ }
163
+ await callbacks?.onEvent?.(envelope);
164
+ return envelope;
165
+ };
166
+
167
+ await appendAndProject('user_message', { message: userMessage, stepIndex: 0 });
168
+ await this.deps.executionStore.patch(executionId, {
169
+ status: 'RUNNING',
170
+ startedAt: Date.now(),
171
+ updatedAt: Date.now(),
172
+ });
173
+
174
+ let toolEventQueue: Promise<void> = Promise.resolve();
175
+ let observabilityQueue: Promise<void> = Promise.resolve();
176
+ const toolChunkListener = (payload: unknown): void => {
177
+ toolEventQueue = toolEventQueue
178
+ .then(async () => {
179
+ await appendAndProject('tool_stream', payload);
180
+ })
181
+ .catch((error: unknown) => {
182
+ toolStreamFailure = error;
183
+ });
184
+ };
185
+
186
+ const enqueueObservabilityTask = (task: () => Promise<void>) => {
187
+ observabilityQueue = observabilityQueue.then(task).catch((error: unknown) => {
188
+ if (!streamFailure) {
189
+ streamFailure = error;
190
+ }
191
+ });
192
+ };
193
+
194
+ this.deps.agent.on('tool_chunk', toolChunkListener);
195
+
196
+ const agentCallbacks: AgentCallbacks = {
197
+ onContextUsage: async (contextUsage) => {
198
+ latestContextUsage = {
199
+ stepIndex: contextUsage.stepIndex,
200
+ contextTokens: contextUsage.contextTokens,
201
+ contextLimitTokens: contextUsage.contextLimitTokens,
202
+ contextUsagePercent: contextUsage.contextUsagePercent,
203
+ };
204
+ await callbacks?.onContextUsage?.(contextUsage);
205
+ },
206
+ onMessage: async (message) => {
207
+ // 添加模型信息到消息的 metadata 中
208
+ if (request.modelLabel && message.role === 'assistant') {
209
+ message.metadata = {
210
+ ...message.metadata,
211
+ modelLabel: request.modelLabel,
212
+ };
213
+ }
214
+ emittedMessages.push(message);
215
+ await appendAndProject('assistant_message', {
216
+ message,
217
+ stepIndex: currentStepIndex,
218
+ });
219
+ const usage = readUsage(message.usage);
220
+ if (message.role === 'assistant' && usage) {
221
+ usageSequence += 1;
222
+ cumulativeUsage.prompt_tokens += usage.prompt_tokens;
223
+ cumulativeUsage.completion_tokens += usage.completion_tokens;
224
+ cumulativeUsage.total_tokens += usage.total_tokens;
225
+ const usageStepIndex = latestContextUsage?.stepIndex ?? currentStepIndex;
226
+
227
+ const usagePayload: RunForegroundUsage = {
228
+ sequence: usageSequence,
229
+ stepIndex: usageStepIndex,
230
+ messageId: message.messageId,
231
+ usage,
232
+ cumulativeUsage: { ...cumulativeUsage },
233
+ contextTokens: latestContextUsage?.contextTokens,
234
+ contextLimitTokens: latestContextUsage?.contextLimitTokens,
235
+ contextUsagePercent: latestContextUsage?.contextUsagePercent,
236
+ };
237
+ await callbacks?.onUsage?.(usagePayload);
238
+ }
239
+ await callbacks?.onMessage?.(message);
240
+ },
241
+ onCheckpoint: async (checkpoint) => {
242
+ await callbacks?.onCheckpoint?.(checkpoint);
243
+ },
244
+ onProgress: callbacks?.onProgress,
245
+ onCompaction: callbacks?.onCompaction,
246
+ onMetric: async (metric) => {
247
+ enqueueObservabilityTask(async () => {
248
+ await appendAndProject('metric', metric);
249
+ });
250
+ await callbacks?.onMetric?.(metric);
251
+ },
252
+ onTrace: async (event) => {
253
+ enqueueObservabilityTask(async () => {
254
+ await appendAndProject('trace', event);
255
+ });
256
+ await callbacks?.onTrace?.(event);
257
+ },
258
+ onToolPolicy: callbacks?.onToolPolicy,
259
+ onError: callbacks?.onError,
260
+ };
261
+
262
+ await this.observabilityScope.run(
263
+ {
264
+ executionId,
265
+ conversationId: request.conversationId,
266
+ getStepIndex: () => currentStepIndex,
267
+ enqueue: enqueueObservabilityTask,
268
+ appendEvent: async (eventType, data) => {
269
+ await appendAndProject(eventType, data);
270
+ },
271
+ },
272
+ async () => {
273
+ try {
274
+ for await (const event of this.deps.agent.runStream(
275
+ {
276
+ executionId,
277
+ conversationId: request.conversationId,
278
+ messages: inputMessages,
279
+ systemPrompt: request.systemPrompt,
280
+ tools: request.tools,
281
+ config: request.config,
282
+ maxSteps: request.maxSteps,
283
+ abortSignal: request.abortSignal,
284
+ timeoutBudgetMs: request.timeoutBudgetMs,
285
+ llmTimeoutRatio: request.llmTimeoutRatio,
286
+ contextLimitTokens: request.contextLimitTokens,
287
+ },
288
+ agentCallbacks
289
+ )) {
290
+ const envelope = await appendAndProject(event.type, event.data);
291
+
292
+ if (event.type === 'progress' || event.type === 'checkpoint') {
293
+ const stepIndex = readStepIndex(event.data);
294
+ if (stepIndex > currentStepIndex) {
295
+ currentStepIndex = stepIndex;
296
+ }
297
+ await this.deps.executionStore.patch(executionId, {
298
+ stepIndex: currentStepIndex,
299
+ updatedAt: Date.now(),
300
+ ...(event.type === 'checkpoint' ? { lastCheckpointSeq: envelope.seq } : {}),
301
+ });
302
+ }
303
+
304
+ if (event.type === 'compaction') {
305
+ const contextStore = resolveContextStore(this.deps.messageStore);
306
+ if (contextStore) {
307
+ const compaction = extractCompactionInfo(event.data, currentStepIndex);
308
+ if (compaction.removedMessageIds.length > 0) {
309
+ await contextStore.applyCompaction({
310
+ conversationId: request.conversationId,
311
+ executionId,
312
+ stepIndex: compaction.stepIndex,
313
+ removedMessageIds: compaction.removedMessageIds,
314
+ createdAt: envelope.createdAt,
315
+ });
316
+ }
317
+ }
318
+ }
319
+
320
+ if (event.type === 'done') {
321
+ terminalEventSeen = true;
322
+ const doneData = event.data as {
323
+ finishReason?: 'stop' | 'max_steps';
324
+ steps?: number;
325
+ };
326
+ finishReason = doneData.finishReason ?? 'stop';
327
+ if (typeof doneData.steps === 'number' && doneData.steps > 0) {
328
+ steps = doneData.steps;
329
+ currentStepIndex = Math.max(currentStepIndex, doneData.steps);
330
+ }
331
+ }
332
+
333
+ if (event.type === 'error') {
334
+ terminalEventSeen = true;
335
+ finishReason = 'error';
336
+ latestErrorPayload = extractErrorPayload(event.data);
337
+ }
338
+ }
339
+ } catch (error) {
340
+ streamFailure = error;
341
+ } finally {
342
+ this.deps.agent.off('tool_chunk', toolChunkListener);
343
+ await toolEventQueue;
344
+ await observabilityQueue;
345
+ }
346
+ }
347
+ );
348
+
349
+ if (toolStreamFailure && !streamFailure) {
350
+ streamFailure = toolStreamFailure;
351
+ }
352
+
353
+ if (streamFailure) {
354
+ finishReason = 'error';
355
+ const normalized = normalizeUnknownError(streamFailure);
356
+ if (!terminalEventSeen) {
357
+ await appendAndProject('error', normalized);
358
+ }
359
+ if (!latestErrorPayload) {
360
+ latestErrorPayload = normalized;
361
+ }
362
+ }
363
+
364
+ if (steps === 0) {
365
+ steps = inferSteps(events);
366
+ }
367
+ currentStepIndex = Math.max(currentStepIndex, steps);
368
+
369
+ await this.deps.executionStore.patch(
370
+ executionId,
371
+ buildTerminalPatch(finishReason, {
372
+ stepIndex: currentStepIndex,
373
+ error: latestErrorPayload,
374
+ })
375
+ );
376
+
377
+ const run = await this.deps.executionStore.get(executionId);
378
+ if (!run) {
379
+ throw new Error(`Run not found after completion: ${executionId}`);
380
+ }
381
+
382
+ return {
383
+ executionId,
384
+ conversationId: request.conversationId,
385
+ messages: [...inputMessages, ...emittedMessages],
386
+ events,
387
+ finishReason,
388
+ steps: currentStepIndex,
389
+ run,
390
+ };
391
+ }
392
+
393
+ async getRun(executionId: string): Promise<RunRecord | null> {
394
+ return this.deps.executionStore.get(executionId);
395
+ }
396
+
397
+ async listRuns(conversationId: string, opts?: ListRunsOptions): Promise<ListRunsResult> {
398
+ return this.deps.executionStore.listByConversation(conversationId, opts);
399
+ }
400
+
401
+ async listRunEvents(executionId: string): Promise<CliEventEnvelope[]> {
402
+ return this.deps.eventStore.listByRun(executionId);
403
+ }
404
+
405
+ async listContextMessages(conversationId: string): Promise<Message[]> {
406
+ const contextStore = resolveContextStore(this.deps.messageStore);
407
+ if (contextStore) {
408
+ return contextStore.listContext(conversationId);
409
+ }
410
+ if (this.deps.messageStore) {
411
+ return this.deps.messageStore.list(conversationId);
412
+ }
413
+ return [];
414
+ }
415
+
416
+ async listDroppedMessages(
417
+ executionId: string,
418
+ opts?: { stepIndex?: number; limit?: number }
419
+ ): Promise<CompactionDroppedMessageRecord[]> {
420
+ const contextStore = resolveContextStore(this.deps.messageStore);
421
+ if (!contextStore) {
422
+ return [];
423
+ }
424
+ return contextStore.listDroppedMessages(executionId, opts);
425
+ }
426
+
427
+ async listRunLogs(executionId: string, opts?: { level?: RunLogLevel; limit?: number }) {
428
+ const runLogStore = resolveRunLogStore(this.deps);
429
+ if (!runLogStore) {
430
+ return [];
431
+ }
432
+ return runLogStore.listRunLogs(executionId, opts);
433
+ }
434
+
435
+ private createScopedLogger(): AgentLogger {
436
+ return {
437
+ debug: (message, context, data) => {
438
+ this.enqueueRunLog('debug', message, undefined, context, data);
439
+ },
440
+ info: (message, context, data) => {
441
+ this.enqueueRunLog('info', message, undefined, context, data);
442
+ },
443
+ warn: (message, context, data) => {
444
+ this.enqueueRunLog('warn', message, undefined, context, data);
445
+ },
446
+ error: (message, error, context) => {
447
+ this.enqueueRunLog('error', message, error, context);
448
+ },
449
+ };
450
+ }
451
+
452
+ private enqueueRunLog(
453
+ level: RunLogLevel,
454
+ message: string,
455
+ error?: unknown,
456
+ context?: AgentLogContext,
457
+ data?: unknown
458
+ ): void {
459
+ const scope = this.observabilityScope.getStore();
460
+ const runLogStore = resolveRunLogStore(this.deps);
461
+ if (!scope || !runLogStore) {
462
+ return;
463
+ }
464
+
465
+ const payload = buildRunLogPayload({
466
+ level,
467
+ message,
468
+ error,
469
+ context,
470
+ data,
471
+ executionId: scope.executionId,
472
+ conversationId: scope.conversationId,
473
+ stepIndex: scope.getStepIndex(),
474
+ });
475
+
476
+ scope.enqueue(async () => {
477
+ await runLogStore.appendRunLog(payload);
478
+ await scope.appendEvent('run_log', payload);
479
+ });
480
+ }
481
+ }
482
+
483
+ function buildTerminalPatch(
484
+ finishReason: RunFinishReason,
485
+ context: { stepIndex: number; error?: ErrorEventPayload }
486
+ ): Partial<RunRecord> {
487
+ const now = Date.now();
488
+ const terminalCommon = {
489
+ updatedAt: now,
490
+ completedAt: now,
491
+ stepIndex: context.stepIndex,
492
+ };
493
+
494
+ if (finishReason === 'stop' || finishReason === 'max_steps') {
495
+ return {
496
+ ...terminalCommon,
497
+ status: 'COMPLETED',
498
+ terminalReason: finishReason,
499
+ };
500
+ }
501
+
502
+ const mapped = mapErrorPayloadToTerminal(context.error);
503
+ return {
504
+ ...terminalCommon,
505
+ status: mapped.status,
506
+ terminalReason: mapped.terminalReason,
507
+ errorCode: context.error?.errorCode,
508
+ errorCategory: context.error?.category,
509
+ errorMessage: context.error?.message,
510
+ };
511
+ }
512
+
513
+ function mapErrorPayloadToTerminal(error?: ErrorEventPayload): {
514
+ status: RunRecord['status'];
515
+ terminalReason: TerminalReason;
516
+ } {
517
+ switch (error?.errorCode) {
518
+ case 'AGENT_ABORTED':
519
+ return { status: 'CANCELLED', terminalReason: 'aborted' };
520
+ case 'AGENT_TIMEOUT_BUDGET_EXCEEDED':
521
+ case 'AGENT_UPSTREAM_TIMEOUT':
522
+ return { status: 'FAILED', terminalReason: 'timeout' };
523
+ case 'AGENT_UPSTREAM_RATE_LIMIT':
524
+ return { status: 'FAILED', terminalReason: 'rate_limit' };
525
+ case 'AGENT_MAX_RETRIES_REACHED':
526
+ return { status: 'FAILED', terminalReason: 'max_retries' };
527
+ default:
528
+ return { status: 'FAILED', terminalReason: 'error' };
529
+ }
530
+ }
531
+
532
+ function inferSteps(events: CliEventEnvelope[]): number {
533
+ let maxStep = 0;
534
+ for (const event of events) {
535
+ if (event.eventType !== 'progress' && event.eventType !== 'checkpoint') {
536
+ continue;
537
+ }
538
+ const stepIndex = readStepIndex(event.data);
539
+ if (stepIndex > maxStep) {
540
+ maxStep = stepIndex;
541
+ }
542
+ }
543
+ return maxStep;
544
+ }
545
+
546
+ function readStepIndex(payload: unknown): number {
547
+ if (!isRecord(payload)) {
548
+ return 0;
549
+ }
550
+ const stepIndex = payload.stepIndex;
551
+ return typeof stepIndex === 'number' && Number.isFinite(stepIndex) && stepIndex > 0
552
+ ? stepIndex
553
+ : 0;
554
+ }
555
+
556
+ function extractErrorPayload(payload: unknown): ErrorEventPayload | undefined {
557
+ if (!isRecord(payload)) {
558
+ return undefined;
559
+ }
560
+ return {
561
+ errorCode: readString(payload.errorCode) ?? readString(payload.code),
562
+ code: readString(payload.code),
563
+ category: readString(payload.category),
564
+ message: readString(payload.message),
565
+ retryable: readBoolean(payload.retryable),
566
+ httpStatus: readNumber(payload.httpStatus),
567
+ name: readString(payload.name),
568
+ };
569
+ }
570
+
571
+ function buildRunLogPayload(input: {
572
+ level: RunLogLevel;
573
+ message: string;
574
+ error?: unknown;
575
+ context?: AgentLogContext;
576
+ data?: unknown;
577
+ executionId: string;
578
+ conversationId: string;
579
+ stepIndex: number;
580
+ }): RunLogRecord {
581
+ const errorRecord = toErrorRecord(input.error);
582
+ const code =
583
+ readString(input.context?.errorCode) ??
584
+ readString(errorRecord?.errorCode) ??
585
+ readString(errorRecord?.code);
586
+
587
+ return {
588
+ executionId: input.executionId,
589
+ conversationId: input.conversationId,
590
+ stepIndex: input.stepIndex > 0 ? input.stepIndex : undefined,
591
+ level: input.level,
592
+ code: code ?? undefined,
593
+ source: typeof input.context?.toolName === 'string' ? 'tool' : 'agent',
594
+ message: input.message,
595
+ error: errorRecord ?? undefined,
596
+ context: input.context ? { ...input.context } : undefined,
597
+ data: input.data,
598
+ createdAt: Date.now(),
599
+ };
600
+ }
601
+
602
+ function toErrorRecord(error: unknown): Record<string, unknown> | undefined {
603
+ if (!error) {
604
+ return undefined;
605
+ }
606
+ if (error instanceof Error) {
607
+ const maybeError = error as Error & Record<string, unknown>;
608
+ return {
609
+ name: error.name,
610
+ message: error.message,
611
+ stack: error.stack,
612
+ ...(typeof error.cause !== 'undefined' ? { cause: error.cause } : {}),
613
+ ...(readString(maybeError.errorCode) ? { errorCode: readString(maybeError.errorCode) } : {}),
614
+ ...(readString(maybeError.code) ? { code: readString(maybeError.code) } : {}),
615
+ };
616
+ }
617
+ if (isRecord(error)) {
618
+ return { ...error };
619
+ }
620
+ return { message: String(error) };
621
+ }
622
+
623
+ function resolveRunLogStore(deps: AgentAppServiceDeps): RunLogStorePort | undefined {
624
+ if (deps.runLogStore) {
625
+ return deps.runLogStore;
626
+ }
627
+ if (isRunLogStorePort(deps.executionStore)) {
628
+ return deps.executionStore;
629
+ }
630
+ return undefined;
631
+ }
632
+
633
+ function isRunLogStorePort(value: unknown): value is RunLogStorePort {
634
+ return (
635
+ isRecord(value) &&
636
+ typeof value.appendRunLog === 'function' &&
637
+ typeof value.listRunLogs === 'function'
638
+ );
639
+ }
640
+
641
+ function normalizeUnknownError(error: unknown): ErrorEventPayload {
642
+ if (isRecord(error)) {
643
+ const message = readString(error.message) ?? 'Unknown error';
644
+ return {
645
+ name: readString(error.name) ?? 'Error',
646
+ message,
647
+ errorCode: readString(error.errorCode) ?? readString(error.code) ?? 'UNKNOWN_ERROR',
648
+ code: readString(error.code),
649
+ category: readString(error.category),
650
+ retryable: readBoolean(error.retryable),
651
+ httpStatus: readNumber(error.httpStatus),
652
+ };
653
+ }
654
+ if (error instanceof Error) {
655
+ return {
656
+ name: error.name,
657
+ message: error.message,
658
+ errorCode: 'UNKNOWN_ERROR',
659
+ };
660
+ }
661
+ return {
662
+ name: 'Error',
663
+ message: String(error),
664
+ errorCode: 'UNKNOWN_ERROR',
665
+ };
666
+ }
667
+
668
+ function createUserMessage(content: MessageContent): Message {
669
+ return {
670
+ messageId: createId('msg_usr_'),
671
+ type: 'user',
672
+ role: 'user',
673
+ content,
674
+ timestamp: Date.now(),
675
+ };
676
+ }
677
+
678
+ function createId(prefix: string): string {
679
+ return `${prefix}${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
680
+ }
681
+
682
+ function isRecord(value: unknown): value is Record<string, unknown> {
683
+ return typeof value === 'object' && value !== null;
684
+ }
685
+
686
+ function readString(value: unknown): string | undefined {
687
+ return typeof value === 'string' ? value : undefined;
688
+ }
689
+
690
+ function readNumber(value: unknown): number | undefined {
691
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
692
+ }
693
+
694
+ function readBoolean(value: unknown): boolean | undefined {
695
+ return typeof value === 'boolean' ? value : undefined;
696
+ }
697
+
698
+ function readUsage(value: unknown): Usage | undefined {
699
+ if (!isRecord(value)) {
700
+ return undefined;
701
+ }
702
+ const promptTokens = readNumber(value.prompt_tokens);
703
+ const completionTokens = readNumber(value.completion_tokens);
704
+ const totalTokens = readNumber(value.total_tokens);
705
+ if (promptTokens === undefined || completionTokens === undefined || totalTokens === undefined) {
706
+ return undefined;
707
+ }
708
+ return {
709
+ ...value,
710
+ prompt_tokens: Math.max(0, promptTokens),
711
+ completion_tokens: Math.max(0, completionTokens),
712
+ total_tokens: Math.max(0, totalTokens),
713
+ };
714
+ }
715
+
716
+ function resolveContextStore(
717
+ store?: MessageProjectionStorePort
718
+ ): ContextProjectionStorePort | undefined {
719
+ if (
720
+ store &&
721
+ typeof (store as ContextProjectionStorePort).listContext === 'function' &&
722
+ typeof (store as ContextProjectionStorePort).applyCompaction === 'function' &&
723
+ typeof (store as ContextProjectionStorePort).listDroppedMessages === 'function'
724
+ ) {
725
+ return store as ContextProjectionStorePort;
726
+ }
727
+ return undefined;
728
+ }
729
+
730
+ function extractCompactionInfo(
731
+ payload: unknown,
732
+ fallbackStepIndex: number
733
+ ): { stepIndex: number; removedMessageIds: string[] } {
734
+ if (!isRecord(payload)) {
735
+ return { stepIndex: fallbackStepIndex, removedMessageIds: [] };
736
+ }
737
+ const rawRemoved = payload.removedMessageIds;
738
+ const removedMessageIds = Array.isArray(rawRemoved)
739
+ ? rawRemoved.filter((item): item is string => typeof item === 'string')
740
+ : [];
741
+ const stepIndex = readStepIndex(payload);
742
+ return {
743
+ stepIndex: stepIndex > 0 ? stepIndex : fallbackStepIndex,
744
+ removedMessageIds,
745
+ };
746
+ }
747
+
748
+ export const AGENT_APP_SERVICE_MODULE = 'renx-app-service';