@downcity/agent 1.1.6 → 1.1.8
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/bin/agent/AgentContext.d.ts.map +1 -1
- package/bin/agent/AgentContext.js +1 -0
- package/bin/agent/AgentContext.js.map +1 -1
- package/bin/agent/AgentContextTypes.d.ts +5 -1
- package/bin/agent/AgentContextTypes.d.ts.map +1 -1
- package/bin/agent/AgentRuntime.d.ts +6 -1
- package/bin/agent/AgentRuntime.d.ts.map +1 -1
- package/bin/agent/AgentRuntime.js +22 -3
- package/bin/agent/AgentRuntime.js.map +1 -1
- package/bin/agent/AgentRuntimeState.d.ts.map +1 -1
- package/bin/agent/AgentRuntimeState.js +58 -2
- package/bin/agent/AgentRuntimeState.js.map +1 -1
- package/bin/agent/AgentRuntimeTypes.d.ts +5 -1
- package/bin/agent/AgentRuntimeTypes.d.ts.map +1 -1
- package/bin/agent/project/AgentInitializer.d.ts +3 -2
- package/bin/agent/project/AgentInitializer.d.ts.map +1 -1
- package/bin/agent/project/AgentInitializer.js +34 -44
- package/bin/agent/project/AgentInitializer.js.map +1 -1
- package/bin/config/Config.d.ts.map +1 -1
- package/bin/config/Config.js +2 -21
- package/bin/config/Config.js.map +1 -1
- package/bin/config/Paths.d.ts +1 -5
- package/bin/config/Paths.d.ts.map +1 -1
- package/bin/config/Paths.js +2 -8
- package/bin/config/Paths.js.map +1 -1
- package/bin/host/daemon/ProjectSetup.d.ts +2 -1
- package/bin/host/daemon/ProjectSetup.d.ts.map +1 -1
- package/bin/host/daemon/ProjectSetup.js +14 -21
- package/bin/host/daemon/ProjectSetup.js.map +1 -1
- package/bin/host/runtime/AgentHostRuntime.d.ts.map +1 -1
- package/bin/host/runtime/AgentHostRuntime.js +1 -2
- package/bin/host/runtime/AgentHostRuntime.js.map +1 -1
- package/bin/host/runtime/CityPaths.d.ts +0 -3
- package/bin/host/runtime/CityPaths.d.ts.map +1 -1
- package/bin/host/runtime/CityPaths.js +0 -3
- package/bin/host/runtime/CityPaths.js.map +1 -1
- package/bin/host/sdk/Agent.d.ts +4 -0
- package/bin/host/sdk/Agent.d.ts.map +1 -1
- package/bin/host/sdk/Agent.js +71 -2
- package/bin/host/sdk/Agent.js.map +1 -1
- package/bin/host/sdk/AgentSdkTypes.d.ts +9 -0
- package/bin/host/sdk/AgentSdkTypes.d.ts.map +1 -1
- package/bin/host/sdk/SdkSessionSystemComposer.d.ts +11 -2
- package/bin/host/sdk/SdkSessionSystemComposer.d.ts.map +1 -1
- package/bin/host/sdk/SdkSessionSystemComposer.js +19 -2
- package/bin/host/sdk/SdkSessionSystemComposer.js.map +1 -1
- package/bin/host/sdk/Session.d.ts +10 -0
- package/bin/host/sdk/Session.d.ts.map +1 -1
- package/bin/host/sdk/Session.js +8 -0
- package/bin/host/sdk/Session.js.map +1 -1
- package/bin/http/Server.d.ts.map +1 -1
- package/bin/http/Server.js +1 -11
- package/bin/http/Server.js.map +1 -1
- package/bin/http/auth/AuthEnv.d.ts +0 -9
- package/bin/http/auth/AuthEnv.d.ts.map +1 -1
- package/bin/http/auth/AuthEnv.js +0 -9
- package/bin/http/auth/AuthEnv.js.map +1 -1
- package/bin/http/auth/CliAuthStateStore.d.ts +0 -4
- package/bin/http/auth/CliAuthStateStore.d.ts.map +1 -1
- package/bin/http/auth/CliAuthStateStore.js +0 -4
- package/bin/http/auth/CliAuthStateStore.js.map +1 -1
- package/bin/http/control/ModelRoutes.d.ts.map +1 -1
- package/bin/http/control/ModelRoutes.js +3 -8
- package/bin/http/control/ModelRoutes.js.map +1 -1
- package/bin/index.d.ts +2 -6
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +2 -6
- package/bin/index.js.map +1 -1
- package/bin/model/CreateModel.d.ts +2 -2
- package/bin/model/CreateModel.d.ts.map +1 -1
- package/bin/model/CreateModel.js +13 -12
- package/bin/model/CreateModel.js.map +1 -1
- package/bin/plugin/Activation.d.ts +4 -0
- package/bin/plugin/Activation.d.ts.map +1 -1
- package/bin/plugin/Activation.js +2 -2
- package/bin/plugin/Activation.js.map +1 -1
- package/bin/plugin/LocalExecution.d.ts.map +1 -1
- package/bin/plugin/LocalExecution.js +23 -2
- package/bin/plugin/LocalExecution.js.map +1 -1
- package/bin/plugin/PluginRegistry.js +2 -2
- package/bin/plugin/PluginRegistry.js.map +1 -1
- package/bin/plugins/asr/Plugin.d.ts.map +1 -1
- package/bin/plugins/asr/Plugin.js +4 -5
- package/bin/plugins/asr/Plugin.js.map +1 -1
- package/bin/plugins/auth/Plugin.d.ts.map +1 -1
- package/bin/plugins/auth/Plugin.js +1 -0
- package/bin/plugins/auth/Plugin.js.map +1 -1
- package/bin/plugins/auth/runtime/AuthorizationConfig.d.ts +4 -4
- package/bin/plugins/auth/runtime/AuthorizationConfig.d.ts.map +1 -1
- package/bin/plugins/auth/runtime/AuthorizationConfig.js +28 -26
- package/bin/plugins/auth/runtime/AuthorizationConfig.js.map +1 -1
- package/bin/plugins/auth/runtime/AuthorizationPolicy.d.ts +2 -0
- package/bin/plugins/auth/runtime/AuthorizationPolicy.d.ts.map +1 -1
- package/bin/plugins/auth/runtime/AuthorizationPolicy.js +3 -2
- package/bin/plugins/auth/runtime/AuthorizationPolicy.js.map +1 -1
- package/bin/plugins/auth/runtime/AuthorizationStore.d.ts +1 -1
- package/bin/plugins/auth/runtime/AuthorizationStore.d.ts.map +1 -1
- package/bin/plugins/auth/runtime/AuthorizationStore.js +3 -4
- package/bin/plugins/auth/runtime/AuthorizationStore.js.map +1 -1
- package/bin/plugins/skill/Plugin.js +2 -2
- package/bin/plugins/skill/Plugin.js.map +1 -1
- package/bin/plugins/tts/Plugin.d.ts.map +1 -1
- package/bin/plugins/tts/Plugin.js +4 -5
- package/bin/plugins/tts/Plugin.js.map +1 -1
- package/bin/plugins/web/Plugin.d.ts.map +1 -1
- package/bin/plugins/web/Plugin.js +4 -5
- package/bin/plugins/web/Plugin.js.map +1 -1
- package/bin/plugins/workboard/Plugin.js +2 -2
- package/bin/plugins/workboard/Plugin.js.map +1 -1
- package/bin/service/builtins/chat/accounts/ChannelAccountService.d.ts +4 -1
- package/bin/service/builtins/chat/accounts/ChannelAccountService.d.ts.map +1 -1
- package/bin/service/builtins/chat/accounts/ChannelAccountService.js +64 -91
- package/bin/service/builtins/chat/accounts/ChannelAccountService.js.map +1 -1
- package/bin/service/builtins/chat/runtime/ChatChannelActions.d.ts.map +1 -1
- package/bin/service/builtins/chat/runtime/ChatChannelActions.js +11 -18
- package/bin/service/builtins/chat/runtime/ChatChannelActions.js.map +1 -1
- package/bin/service/builtins/chat/runtime/ChatChannelCore.d.ts +1 -1
- package/bin/service/builtins/chat/runtime/ChatChannelCore.d.ts.map +1 -1
- package/bin/service/builtins/chat/runtime/ChatChannelCore.js +9 -17
- package/bin/service/builtins/chat/runtime/ChatChannelCore.js.map +1 -1
- package/bin/service/builtins/memory/Action.d.ts +1 -5
- package/bin/service/builtins/memory/Action.d.ts.map +1 -1
- package/bin/service/builtins/memory/Action.js +4 -42
- package/bin/service/builtins/memory/Action.js.map +1 -1
- package/bin/service/builtins/memory/MemoryService.d.ts.map +1 -1
- package/bin/service/builtins/memory/MemoryService.js +2 -32
- package/bin/service/builtins/memory/MemoryService.js.map +1 -1
- package/bin/service/builtins/memory/runtime/Search.d.ts +7 -3
- package/bin/service/builtins/memory/runtime/Search.d.ts.map +1 -1
- package/bin/service/builtins/memory/runtime/Search.js +220 -16
- package/bin/service/builtins/memory/runtime/Search.js.map +1 -1
- package/bin/service/builtins/memory/runtime/Store.d.ts +9 -50
- package/bin/service/builtins/memory/runtime/Store.d.ts.map +1 -1
- package/bin/service/builtins/memory/runtime/Store.js +10 -130
- package/bin/service/builtins/memory/runtime/Store.js.map +1 -1
- package/bin/service/builtins/memory/runtime/Writer.d.ts.map +1 -1
- package/bin/service/builtins/memory/runtime/Writer.js +1 -2
- package/bin/service/builtins/memory/runtime/Writer.js.map +1 -1
- package/bin/service/builtins/memory/types/Memory.d.ts +3 -57
- package/bin/service/builtins/memory/types/Memory.d.ts.map +1 -1
- package/bin/service/schedule/Store.d.ts +22 -25
- package/bin/service/schedule/Store.d.ts.map +1 -1
- package/bin/service/schedule/Store.js +172 -154
- package/bin/service/schedule/Store.js.map +1 -1
- package/bin/session/composer/system/default/SystemDomain.d.ts.map +1 -1
- package/bin/session/composer/system/default/SystemDomain.js +1 -0
- package/bin/session/composer/system/default/SystemDomain.js.map +1 -1
- package/bin/shared/types/AgentHost.d.ts +120 -4
- package/bin/shared/types/AgentHost.d.ts.map +1 -1
- package/bin/shared/types/Plugin.d.ts +5 -1
- package/bin/shared/types/Plugin.d.ts.map +1 -1
- package/package.json +1 -4
- package/src/agent/AgentContext.ts +1 -0
- package/src/agent/AgentContextTypes.ts +5 -0
- package/src/agent/AgentRuntime.ts +32 -3
- package/src/agent/AgentRuntimeState.ts +66 -2
- package/src/agent/AgentRuntimeTypes.ts +5 -0
- package/src/agent/project/AgentInitializer.ts +40 -42
- package/src/config/Config.ts +2 -17
- package/src/config/Paths.ts +2 -9
- package/src/host/daemon/ProjectSetup.ts +19 -21
- package/src/host/runtime/AgentHostRuntime.ts +0 -2
- package/src/host/runtime/CityPaths.ts +0 -3
- package/src/host/sdk/Agent.ts +67 -2
- package/src/host/sdk/AgentSdkTypes.ts +10 -0
- package/src/host/sdk/SdkSessionSystemComposer.ts +39 -2
- package/src/host/sdk/Session.ts +18 -0
- package/src/http/Server.ts +0 -13
- package/src/http/auth/AuthEnv.ts +0 -9
- package/src/http/auth/CliAuthStateStore.ts +0 -4
- package/src/http/control/ModelRoutes.ts +3 -9
- package/src/index.ts +2 -12
- package/src/model/CreateModel.ts +15 -13
- package/src/plugin/Activation.ts +6 -2
- package/src/plugin/LocalExecution.ts +24 -2
- package/src/plugin/PluginRegistry.ts +2 -2
- package/src/plugins/asr/Plugin.ts +4 -5
- package/src/plugins/auth/Plugin.ts +1 -0
- package/src/plugins/auth/runtime/AuthorizationConfig.ts +47 -37
- package/src/plugins/auth/runtime/AuthorizationPolicy.ts +5 -2
- package/src/plugins/auth/runtime/AuthorizationStore.ts +6 -5
- package/src/plugins/skill/Plugin.ts +2 -2
- package/src/plugins/tts/Plugin.ts +4 -5
- package/src/plugins/web/Plugin.ts +4 -5
- package/src/plugins/workboard/Plugin.ts +2 -2
- package/src/service/builtins/chat/accounts/ChannelAccountService.ts +42 -62
- package/src/service/builtins/chat/runtime/ChatChannelActions.ts +12 -18
- package/src/service/builtins/chat/runtime/ChatChannelCore.ts +9 -14
- package/src/service/builtins/memory/Action.ts +6 -47
- package/src/service/builtins/memory/MemoryService.ts +1 -33
- package/src/service/builtins/memory/runtime/Search.ts +256 -16
- package/src/service/builtins/memory/runtime/Store.ts +13 -185
- package/src/service/builtins/memory/runtime/Writer.ts +1 -2
- package/src/service/builtins/memory/types/Memory.ts +2 -59
- package/src/service/schedule/Store.ts +215 -175
- package/src/session/composer/system/default/SystemDomain.ts +1 -0
- package/src/shared/types/AgentHost.ts +138 -4
- package/src/shared/types/Plugin.ts +5 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/bin/http/auth/AuthMiddleware.d.ts +0 -36
- package/bin/http/auth/AuthMiddleware.d.ts.map +0 -1
- package/bin/http/auth/AuthMiddleware.js +0 -37
- package/bin/http/auth/AuthMiddleware.js.map +0 -1
- package/bin/http/auth/AuthRoutes.d.ts +0 -17
- package/bin/http/auth/AuthRoutes.d.ts.map +0 -1
- package/bin/http/auth/AuthRoutes.js +0 -78
- package/bin/http/auth/AuthRoutes.js.map +0 -1
- package/bin/http/auth/AuthService.d.ts +0 -119
- package/bin/http/auth/AuthService.d.ts.map +0 -1
- package/bin/http/auth/AuthService.js +0 -307
- package/bin/http/auth/AuthService.js.map +0 -1
- package/bin/http/auth/AuthStore.d.ts +0 -165
- package/bin/http/auth/AuthStore.d.ts.map +0 -1
- package/bin/http/auth/AuthStore.js +0 -442
- package/bin/http/auth/AuthStore.js.map +0 -1
- package/bin/http/auth/RoutePolicy.d.ts +0 -30
- package/bin/http/auth/RoutePolicy.d.ts.map +0 -1
- package/bin/http/auth/RoutePolicy.js +0 -229
- package/bin/http/auth/RoutePolicy.js.map +0 -1
- package/bin/plugin/Lifecycle.d.ts +0 -33
- package/bin/plugin/Lifecycle.d.ts.map +0 -1
- package/bin/plugin/Lifecycle.js +0 -102
- package/bin/plugin/Lifecycle.js.map +0 -1
- package/bin/service/builtins/memory/runtime/Indexer.d.ts +0 -71
- package/bin/service/builtins/memory/runtime/Indexer.d.ts.map +0 -1
- package/bin/service/builtins/memory/runtime/Indexer.js +0 -345
- package/bin/service/builtins/memory/runtime/Indexer.js.map +0 -1
- package/bin/service/schedule/Schema.d.ts +0 -171
- package/bin/service/schedule/Schema.d.ts.map +0 -1
- package/bin/service/schedule/Schema.js +0 -26
- package/bin/service/schedule/Schema.js.map +0 -1
- package/bin/shared/utils/store/StoreChannelAccountRepository.d.ts +0 -34
- package/bin/shared/utils/store/StoreChannelAccountRepository.d.ts.map +0 -1
- package/bin/shared/utils/store/StoreChannelAccountRepository.js +0 -198
- package/bin/shared/utils/store/StoreChannelAccountRepository.js.map +0 -1
- package/bin/shared/utils/store/StoreEnvRepository.d.ts +0 -98
- package/bin/shared/utils/store/StoreEnvRepository.d.ts.map +0 -1
- package/bin/shared/utils/store/StoreEnvRepository.js +0 -334
- package/bin/shared/utils/store/StoreEnvRepository.js.map +0 -1
- package/bin/shared/utils/store/StoreModelRepository.d.ts +0 -61
- package/bin/shared/utils/store/StoreModelRepository.d.ts.map +0 -1
- package/bin/shared/utils/store/StoreModelRepository.js +0 -278
- package/bin/shared/utils/store/StoreModelRepository.js.map +0 -1
- package/bin/shared/utils/store/StoreSchema.d.ts +0 -13
- package/bin/shared/utils/store/StoreSchema.d.ts.map +0 -1
- package/bin/shared/utils/store/StoreSchema.js +0 -319
- package/bin/shared/utils/store/StoreSchema.js.map +0 -1
- package/bin/shared/utils/store/StoreSecureSettings.d.ts +0 -33
- package/bin/shared/utils/store/StoreSecureSettings.d.ts.map +0 -1
- package/bin/shared/utils/store/StoreSecureSettings.js +0 -91
- package/bin/shared/utils/store/StoreSecureSettings.js.map +0 -1
- package/bin/shared/utils/store/StoreShared.d.ts +0 -44
- package/bin/shared/utils/store/StoreShared.d.ts.map +0 -1
- package/bin/shared/utils/store/StoreShared.js +0 -40
- package/bin/shared/utils/store/StoreShared.js.map +0 -1
- package/bin/shared/utils/store/crypto.d.ts +0 -24
- package/bin/shared/utils/store/crypto.d.ts.map +0 -1
- package/bin/shared/utils/store/crypto.js +0 -101
- package/bin/shared/utils/store/crypto.js.map +0 -1
- package/bin/shared/utils/store/index.d.ts +0 -230
- package/bin/shared/utils/store/index.d.ts.map +0 -1
- package/bin/shared/utils/store/index.js +0 -360
- package/bin/shared/utils/store/index.js.map +0 -1
- package/bin/shared/utils/store/schema.d.ts +0 -690
- package/bin/shared/utils/store/schema.d.ts.map +0 -1
- package/bin/shared/utils/store/schema.js +0 -81
- package/bin/shared/utils/store/schema.js.map +0 -1
- package/src/http/auth/AuthMiddleware.ts +0 -61
- package/src/http/auth/AuthRoutes.ts +0 -100
- package/src/http/auth/AuthService.ts +0 -367
- package/src/http/auth/AuthStore.ts +0 -572
- package/src/http/auth/RoutePolicy.ts +0 -255
- package/src/plugin/Lifecycle.ts +0 -116
- package/src/service/builtins/memory/runtime/Indexer.ts +0 -466
- package/src/service/schedule/Schema.ts +0 -34
- package/src/shared/utils/store/StoreChannelAccountRepository.ts +0 -269
- package/src/shared/utils/store/StoreEnvRepository.ts +0 -452
- package/src/shared/utils/store/StoreModelRepository.ts +0 -324
- package/src/shared/utils/store/StoreSchema.ts +0 -344
- package/src/shared/utils/store/StoreSecureSettings.ts +0 -126
- package/src/shared/utils/store/StoreShared.ts +0 -67
- package/src/shared/utils/store/crypto.ts +0 -112
- package/src/shared/utils/store/index.ts +0 -497
- package/src/shared/utils/store/schema.ts +0 -103
|
@@ -17,9 +17,9 @@ export type MemorySourceType = "longterm" | "daily" | "working";
|
|
|
17
17
|
* 查询模式。
|
|
18
18
|
*
|
|
19
19
|
* 说明(中文)
|
|
20
|
-
* -
|
|
20
|
+
* - 当前实现直接扫描 Markdown 文件,不再维护额外索引库。
|
|
21
21
|
*/
|
|
22
|
-
export type MemorySearchMode = "
|
|
22
|
+
export type MemorySearchMode = "scan";
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* 单条记忆检索结果。
|
|
@@ -175,38 +175,6 @@ export interface MemoryStoreResponse {
|
|
|
175
175
|
writtenChars: number;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
/**
|
|
179
|
-
* 手动索引请求。
|
|
180
|
-
*/
|
|
181
|
-
export interface MemoryIndexPayload {
|
|
182
|
-
/**
|
|
183
|
-
* 是否强制全量重建。
|
|
184
|
-
*/
|
|
185
|
-
force?: boolean;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* 手动索引响应。
|
|
190
|
-
*/
|
|
191
|
-
export interface MemoryIndexResponse {
|
|
192
|
-
/**
|
|
193
|
-
* 本轮扫描文件总数。
|
|
194
|
-
*/
|
|
195
|
-
totalFiles: number;
|
|
196
|
-
/**
|
|
197
|
-
* 本轮新增/变更并完成重建的文件数。
|
|
198
|
-
*/
|
|
199
|
-
reindexedFiles: number;
|
|
200
|
-
/**
|
|
201
|
-
* 本轮删除的失效文件数。
|
|
202
|
-
*/
|
|
203
|
-
removedFiles: number;
|
|
204
|
-
/**
|
|
205
|
-
* 本轮写入 chunk 总数。
|
|
206
|
-
*/
|
|
207
|
-
totalChunks: number;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
178
|
/**
|
|
211
179
|
* Flush 请求。
|
|
212
180
|
*/
|
|
@@ -273,14 +241,6 @@ export interface MemoryStatusResponse {
|
|
|
273
241
|
* 当前检索模式。
|
|
274
242
|
*/
|
|
275
243
|
mode: MemorySearchMode;
|
|
276
|
-
/**
|
|
277
|
-
* 索引文件路径(相对项目根目录)。
|
|
278
|
-
*/
|
|
279
|
-
dbPath: string;
|
|
280
|
-
/**
|
|
281
|
-
* 当前是否为 dirty 状态。
|
|
282
|
-
*/
|
|
283
|
-
dirty: boolean;
|
|
284
244
|
/**
|
|
285
245
|
* 文件总数。
|
|
286
246
|
*/
|
|
@@ -293,14 +253,6 @@ export interface MemoryStatusResponse {
|
|
|
293
253
|
* 按来源统计。
|
|
294
254
|
*/
|
|
295
255
|
sourceCounts: MemorySourceStat[];
|
|
296
|
-
/**
|
|
297
|
-
* 最近一次同步时间戳(ms)。
|
|
298
|
-
*/
|
|
299
|
-
lastSyncAt?: number;
|
|
300
|
-
/**
|
|
301
|
-
* 最近一次同步错误。
|
|
302
|
-
*/
|
|
303
|
-
lastError?: string;
|
|
304
256
|
}
|
|
305
257
|
|
|
306
258
|
/**
|
|
@@ -319,14 +271,6 @@ export interface MemoryDefaults {
|
|
|
319
271
|
* 注入预算(字符)。
|
|
320
272
|
*/
|
|
321
273
|
maxInjectedChars: number;
|
|
322
|
-
/**
|
|
323
|
-
* 文件变更 debounce 时间(毫秒)。
|
|
324
|
-
*/
|
|
325
|
-
watchDebounceMs: number;
|
|
326
|
-
/**
|
|
327
|
-
* 后台同步周期(分钟)。
|
|
328
|
-
*/
|
|
329
|
-
intervalMinutes: number;
|
|
330
274
|
}
|
|
331
275
|
|
|
332
276
|
/**
|
|
@@ -336,6 +280,5 @@ export type MemoryActionPayload =
|
|
|
336
280
|
| MemorySearchPayload
|
|
337
281
|
| MemoryGetPayload
|
|
338
282
|
| MemoryStorePayload
|
|
339
|
-
| MemoryIndexPayload
|
|
340
283
|
| MemoryFlushPayload
|
|
341
284
|
| Record<string, JsonValue>;
|
|
@@ -2,16 +2,13 @@
|
|
|
2
2
|
* Service Schedule 持久化存储。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
5
|
+
* - 调度任务改为使用项目内 `jsonl` 事件流持久化,不再依赖 SQLite。
|
|
6
|
+
* - 这里采用“全量重放 + 内存归并”的最简实现,保持职责清晰且易于迁移。
|
|
7
|
+
* - 文件只记录状态事件;对外仍暴露稳定的调度任务查询与状态更新接口。
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import fs from "fs-extra";
|
|
10
|
-
import Database from "better-sqlite3";
|
|
11
11
|
import path from "node:path";
|
|
12
|
-
import { and, asc, desc, eq, inArray, lte } from "drizzle-orm";
|
|
13
|
-
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
14
|
-
import { scheduledJobsTable } from "./Schema.js";
|
|
15
12
|
import type {
|
|
16
13
|
CreateScheduledJobInput,
|
|
17
14
|
ScheduledJobRecord,
|
|
@@ -21,80 +18,137 @@ import type { JsonValue } from "@/shared/types/Json.js";
|
|
|
21
18
|
import { generateId } from "@shared/utils/Id.js";
|
|
22
19
|
import { getDowncityScheduleDbPath } from "@/config/Paths.js";
|
|
23
20
|
|
|
24
|
-
type
|
|
21
|
+
type ScheduledJobEvent =
|
|
22
|
+
| {
|
|
23
|
+
/**
|
|
24
|
+
* 事件版本号。
|
|
25
|
+
*/
|
|
26
|
+
v: 1;
|
|
27
|
+
/**
|
|
28
|
+
* 事件类型:创建任务。
|
|
29
|
+
*/
|
|
30
|
+
type: "created";
|
|
31
|
+
/**
|
|
32
|
+
* 调度任务快照。
|
|
33
|
+
*/
|
|
34
|
+
job: ScheduledJobRecord;
|
|
35
|
+
}
|
|
36
|
+
| {
|
|
37
|
+
/**
|
|
38
|
+
* 事件版本号。
|
|
39
|
+
*/
|
|
40
|
+
v: 1;
|
|
41
|
+
/**
|
|
42
|
+
* 事件类型:状态更新。
|
|
43
|
+
*/
|
|
44
|
+
type: "status";
|
|
45
|
+
/**
|
|
46
|
+
* 目标任务 ID。
|
|
47
|
+
*/
|
|
48
|
+
jobId: string;
|
|
49
|
+
/**
|
|
50
|
+
* 新状态。
|
|
51
|
+
*/
|
|
52
|
+
status: ScheduledJobStatus;
|
|
53
|
+
/**
|
|
54
|
+
* 最新更新时间。
|
|
55
|
+
*/
|
|
56
|
+
updatedAt: number;
|
|
57
|
+
/**
|
|
58
|
+
* 可选错误信息。
|
|
59
|
+
*/
|
|
60
|
+
error?: string;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
function readJsonlLines(filePath: string): string[] {
|
|
64
|
+
if (!fs.existsSync(filePath)) return [];
|
|
65
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
66
|
+
return raw
|
|
67
|
+
.split(/\r?\n/)
|
|
68
|
+
.map((line) => line.trim())
|
|
69
|
+
.filter(Boolean);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function normalizeJobRecord(input: ScheduledJobRecord): ScheduledJobRecord {
|
|
73
|
+
return {
|
|
74
|
+
id: String(input.id || "").trim(),
|
|
75
|
+
serviceName: String(input.serviceName || "").trim(),
|
|
76
|
+
actionName: String(input.actionName || "").trim(),
|
|
77
|
+
payload: input.payload ?? null,
|
|
78
|
+
runAtMs: Math.trunc(input.runAtMs),
|
|
79
|
+
status: input.status,
|
|
80
|
+
...(typeof input.error === "string" && input.error ? { error: input.error } : {}),
|
|
81
|
+
createdAt: Math.trunc(input.createdAt),
|
|
82
|
+
updatedAt: Math.trunc(input.updatedAt),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function parseEvent(line: string): ScheduledJobEvent | null {
|
|
87
|
+
try {
|
|
88
|
+
const raw = JSON.parse(line) as Partial<ScheduledJobEvent> | null;
|
|
89
|
+
if (!raw || typeof raw !== "object") return null;
|
|
90
|
+
if (raw.type === "created" && raw.job) {
|
|
91
|
+
return {
|
|
92
|
+
v: 1,
|
|
93
|
+
type: "created",
|
|
94
|
+
job: normalizeJobRecord(raw.job as ScheduledJobRecord),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (
|
|
98
|
+
raw.type === "status" &&
|
|
99
|
+
typeof raw.jobId === "string" &&
|
|
100
|
+
typeof raw.status === "string" &&
|
|
101
|
+
typeof raw.updatedAt === "number"
|
|
102
|
+
) {
|
|
103
|
+
return {
|
|
104
|
+
v: 1,
|
|
105
|
+
type: "status",
|
|
106
|
+
jobId: raw.jobId,
|
|
107
|
+
status: raw.status as ScheduledJobStatus,
|
|
108
|
+
updatedAt: Math.trunc(raw.updatedAt),
|
|
109
|
+
...(typeof raw.error === "string" ? { error: raw.error } : {}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
} catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function compareJobs(a: ScheduledJobRecord, b: ScheduledJobRecord): number {
|
|
119
|
+
if (a.runAtMs !== b.runAtMs) return a.runAtMs - b.runAtMs;
|
|
120
|
+
return b.createdAt - a.createdAt;
|
|
121
|
+
}
|
|
25
122
|
|
|
26
123
|
/**
|
|
27
124
|
* Service Schedule Store。
|
|
28
125
|
*/
|
|
29
126
|
export class ServiceScheduleStore {
|
|
30
|
-
private readonly
|
|
31
|
-
|
|
32
|
-
private readonly db: ReturnType<typeof drizzle>;
|
|
127
|
+
private readonly filePath: string;
|
|
33
128
|
|
|
34
129
|
constructor(projectRoot: string) {
|
|
35
|
-
|
|
36
|
-
fs.ensureDirSync(path.dirname(
|
|
37
|
-
this.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
this.ensureSchema();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* 初始化表结构。
|
|
45
|
-
*/
|
|
46
|
-
private ensureSchema(): void {
|
|
47
|
-
this.sqlite.exec(`
|
|
48
|
-
CREATE TABLE IF NOT EXISTS scheduled_jobs (
|
|
49
|
-
id TEXT PRIMARY KEY NOT NULL,
|
|
50
|
-
service_name TEXT NOT NULL,
|
|
51
|
-
action_name TEXT NOT NULL,
|
|
52
|
-
payload_json TEXT NOT NULL,
|
|
53
|
-
run_at_ms INTEGER NOT NULL,
|
|
54
|
-
status TEXT NOT NULL,
|
|
55
|
-
error TEXT,
|
|
56
|
-
created_at INTEGER NOT NULL,
|
|
57
|
-
updated_at INTEGER NOT NULL
|
|
58
|
-
);
|
|
59
|
-
`);
|
|
60
|
-
this.sqlite.exec(`
|
|
61
|
-
CREATE INDEX IF NOT EXISTS scheduled_jobs_status_run_at_idx
|
|
62
|
-
ON scheduled_jobs(status, run_at_ms);
|
|
63
|
-
`);
|
|
64
|
-
this.sqlite.exec(`
|
|
65
|
-
CREATE INDEX IF NOT EXISTS scheduled_jobs_run_at_idx
|
|
66
|
-
ON scheduled_jobs(run_at_ms);
|
|
67
|
-
`);
|
|
130
|
+
this.filePath = getDowncityScheduleDbPath(projectRoot);
|
|
131
|
+
fs.ensureDirSync(path.dirname(this.filePath));
|
|
132
|
+
if (!fs.existsSync(this.filePath)) {
|
|
133
|
+
fs.writeFileSync(this.filePath, "", "utf-8");
|
|
134
|
+
}
|
|
68
135
|
}
|
|
69
136
|
|
|
70
137
|
/**
|
|
71
|
-
*
|
|
138
|
+
* 关闭存储。
|
|
139
|
+
*
|
|
140
|
+
* 说明(中文)
|
|
141
|
+
* - jsonl 版本无需保持长连接,因此 close 为 no-op。
|
|
72
142
|
*/
|
|
73
|
-
close(): void {
|
|
74
|
-
this.sqlite.close();
|
|
75
|
-
}
|
|
143
|
+
close(): void {}
|
|
76
144
|
|
|
77
145
|
/**
|
|
78
146
|
* 创建调度任务。
|
|
79
147
|
*/
|
|
80
148
|
createJob(input: CreateScheduledJobInput): ScheduledJobRecord {
|
|
81
149
|
const now = Date.now();
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
this.db.insert(scheduledJobsTable).values({
|
|
85
|
-
id,
|
|
86
|
-
serviceName: String(input.serviceName || "").trim(),
|
|
87
|
-
actionName: String(input.actionName || "").trim(),
|
|
88
|
-
payloadJson,
|
|
89
|
-
runAtMs: Math.trunc(input.runAtMs),
|
|
90
|
-
status: "pending",
|
|
91
|
-
error: null,
|
|
92
|
-
createdAt: now,
|
|
93
|
-
updatedAt: now,
|
|
94
|
-
}).run();
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
id,
|
|
150
|
+
const job: ScheduledJobRecord = {
|
|
151
|
+
id: `sched_${generateId()}`,
|
|
98
152
|
serviceName: String(input.serviceName || "").trim(),
|
|
99
153
|
actionName: String(input.actionName || "").trim(),
|
|
100
154
|
payload: input.payload ?? null,
|
|
@@ -103,16 +157,21 @@ export class ServiceScheduleStore {
|
|
|
103
157
|
createdAt: now,
|
|
104
158
|
updatedAt: now,
|
|
105
159
|
};
|
|
160
|
+
this.appendEvent({
|
|
161
|
+
v: 1,
|
|
162
|
+
type: "created",
|
|
163
|
+
job,
|
|
164
|
+
});
|
|
165
|
+
return job;
|
|
106
166
|
}
|
|
107
167
|
|
|
108
168
|
/**
|
|
109
169
|
* 获取单个任务。
|
|
110
170
|
*/
|
|
111
171
|
getJobById(jobId: string): ScheduledJobRecord | null {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return row ? this.toJobRecord(row) : null;
|
|
172
|
+
const key = String(jobId || "").trim();
|
|
173
|
+
if (!key) return null;
|
|
174
|
+
return this.readJobMap().get(key) || null;
|
|
116
175
|
}
|
|
117
176
|
|
|
118
177
|
/**
|
|
@@ -120,19 +179,14 @@ export class ServiceScheduleStore {
|
|
|
120
179
|
*/
|
|
121
180
|
listJobsByStatus(statuses: ScheduledJobStatus[]): ScheduledJobRecord[] {
|
|
122
181
|
if (statuses.length === 0) return [];
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
.
|
|
126
|
-
.
|
|
127
|
-
return rows.map((row) => this.toJobRecord(row));
|
|
182
|
+
const allowed = new Set(statuses);
|
|
183
|
+
return this.readJobs()
|
|
184
|
+
.filter((job) => allowed.has(job.status))
|
|
185
|
+
.sort(compareJobs);
|
|
128
186
|
}
|
|
129
187
|
|
|
130
188
|
/**
|
|
131
189
|
* 列出任务。
|
|
132
|
-
*
|
|
133
|
-
* 说明(中文)
|
|
134
|
-
* - 默认按 `runAtMs` 升序返回,便于排查“接下来会执行什么”。
|
|
135
|
-
* - 可选状态过滤与数量限制,避免一次输出过多记录。
|
|
136
190
|
*/
|
|
137
191
|
listJobs(params?: {
|
|
138
192
|
status?: ScheduledJobStatus;
|
|
@@ -142,75 +196,44 @@ export class ServiceScheduleStore {
|
|
|
142
196
|
typeof params?.limit === "number" && Number.isFinite(params.limit)
|
|
143
197
|
? Math.max(1, Math.trunc(params.limit))
|
|
144
198
|
: 100;
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
? query
|
|
150
|
-
.where(eq(scheduledJobsTable.status, status))
|
|
151
|
-
.orderBy(asc(scheduledJobsTable.runAtMs), desc(scheduledJobsTable.createdAt))
|
|
152
|
-
.limit(limit)
|
|
153
|
-
.all()
|
|
154
|
-
: query
|
|
155
|
-
.orderBy(asc(scheduledJobsTable.runAtMs), desc(scheduledJobsTable.createdAt))
|
|
156
|
-
.limit(limit)
|
|
157
|
-
.all();
|
|
158
|
-
return rows.map((row) => this.toJobRecord(row));
|
|
199
|
+
const jobs = this.readJobs()
|
|
200
|
+
.filter((job) => !params?.status || job.status === params.status)
|
|
201
|
+
.sort(compareJobs);
|
|
202
|
+
return jobs.slice(0, limit);
|
|
159
203
|
}
|
|
160
204
|
|
|
161
205
|
/**
|
|
162
206
|
* 列出已到点且待执行的任务。
|
|
163
207
|
*/
|
|
164
208
|
listDuePendingJobs(nowMs: number): ScheduledJobRecord[] {
|
|
165
|
-
|
|
166
|
-
.
|
|
167
|
-
|
|
168
|
-
eq(scheduledJobsTable.status, "pending"),
|
|
169
|
-
lte(scheduledJobsTable.runAtMs, Math.trunc(nowMs)),
|
|
170
|
-
),
|
|
171
|
-
)
|
|
172
|
-
.orderBy(asc(scheduledJobsTable.runAtMs))
|
|
173
|
-
.all();
|
|
174
|
-
return rows.map((row) => this.toJobRecord(row));
|
|
209
|
+
return this.readJobs()
|
|
210
|
+
.filter((job) => job.status === "pending" && job.runAtMs <= Math.trunc(nowMs))
|
|
211
|
+
.sort(compareJobs);
|
|
175
212
|
}
|
|
176
213
|
|
|
177
214
|
/**
|
|
178
215
|
* 启动恢复时,把历史 `running` 回退到 `pending`。
|
|
179
216
|
*/
|
|
180
217
|
resetRunningJobsToPending(): number {
|
|
218
|
+
const runningJobs = this.readJobs().filter((job) => job.status === "running");
|
|
181
219
|
const now = Date.now();
|
|
182
|
-
const
|
|
183
|
-
.
|
|
220
|
+
for (const job of runningJobs) {
|
|
221
|
+
this.appendEvent({
|
|
222
|
+
v: 1,
|
|
223
|
+
type: "status",
|
|
224
|
+
jobId: job.id,
|
|
184
225
|
status: "pending",
|
|
185
226
|
updatedAt: now,
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
.run();
|
|
190
|
-
return Number(result.changes || 0);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
return runningJobs.length;
|
|
191
230
|
}
|
|
192
231
|
|
|
193
232
|
/**
|
|
194
233
|
* 将任务标记为执行中。
|
|
195
|
-
*
|
|
196
|
-
* 关键点(中文)
|
|
197
|
-
* - 仅允许从 `pending` 进入 `running`,避免重复领取。
|
|
198
234
|
*/
|
|
199
235
|
markJobRunning(jobId: string): boolean {
|
|
200
|
-
|
|
201
|
-
.set({
|
|
202
|
-
status: "running",
|
|
203
|
-
updatedAt: Date.now(),
|
|
204
|
-
error: null,
|
|
205
|
-
})
|
|
206
|
-
.where(
|
|
207
|
-
and(
|
|
208
|
-
eq(scheduledJobsTable.id, String(jobId || "").trim()),
|
|
209
|
-
eq(scheduledJobsTable.status, "pending"),
|
|
210
|
-
),
|
|
211
|
-
)
|
|
212
|
-
.run();
|
|
213
|
-
return Number(result.changes || 0) > 0;
|
|
236
|
+
return this.transitionPendingJob(jobId, "running");
|
|
214
237
|
}
|
|
215
238
|
|
|
216
239
|
/**
|
|
@@ -246,71 +269,88 @@ export class ServiceScheduleStore {
|
|
|
246
269
|
|
|
247
270
|
/**
|
|
248
271
|
* 取消待执行任务。
|
|
249
|
-
*
|
|
250
|
-
* 关键点(中文)
|
|
251
|
-
* - 仅允许取消 `pending`,避免打断已经开始执行的任务。
|
|
252
272
|
*/
|
|
253
273
|
cancelPendingJob(jobId: string): boolean {
|
|
254
|
-
|
|
255
|
-
.set({
|
|
256
|
-
status: "cancelled",
|
|
257
|
-
updatedAt: Date.now(),
|
|
258
|
-
error: null,
|
|
259
|
-
})
|
|
260
|
-
.where(
|
|
261
|
-
and(
|
|
262
|
-
eq(scheduledJobsTable.id, String(jobId || "").trim()),
|
|
263
|
-
eq(scheduledJobsTable.status, "pending"),
|
|
264
|
-
),
|
|
265
|
-
)
|
|
266
|
-
.run();
|
|
267
|
-
return Number(result.changes || 0) > 0;
|
|
274
|
+
return this.transitionPendingJob(jobId, "cancelled");
|
|
268
275
|
}
|
|
269
276
|
|
|
270
277
|
/**
|
|
271
|
-
*
|
|
278
|
+
* 仅读取当前任务快照。
|
|
272
279
|
*/
|
|
273
|
-
private
|
|
274
|
-
|
|
275
|
-
status: Exclude<ScheduledJobStatus, "pending" | "running">;
|
|
276
|
-
error?: string;
|
|
277
|
-
}): boolean {
|
|
278
|
-
const result = this.db.update(scheduledJobsTable)
|
|
279
|
-
.set({
|
|
280
|
-
status: params.status,
|
|
281
|
-
updatedAt: Date.now(),
|
|
282
|
-
error: params.error ? String(params.error) : null,
|
|
283
|
-
})
|
|
284
|
-
.where(eq(scheduledJobsTable.id, String(params.jobId || "").trim()))
|
|
285
|
-
.run();
|
|
286
|
-
return Number(result.changes || 0) > 0;
|
|
280
|
+
private readJobs(): ScheduledJobRecord[] {
|
|
281
|
+
return [...this.readJobMap().values()];
|
|
287
282
|
}
|
|
288
283
|
|
|
289
284
|
/**
|
|
290
|
-
*
|
|
285
|
+
* 重放事件流,构造当前任务快照。
|
|
291
286
|
*/
|
|
292
|
-
private
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
287
|
+
private readJobMap(): Map<string, ScheduledJobRecord> {
|
|
288
|
+
const jobs = new Map<string, ScheduledJobRecord>();
|
|
289
|
+
for (const line of readJsonlLines(this.filePath)) {
|
|
290
|
+
const event = parseEvent(line);
|
|
291
|
+
if (!event) continue;
|
|
292
|
+
if (event.type === "created") {
|
|
293
|
+
jobs.set(event.job.id, normalizeJobRecord(event.job));
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
const current = jobs.get(event.jobId);
|
|
297
|
+
if (!current) continue;
|
|
298
|
+
jobs.set(event.jobId, {
|
|
299
|
+
...current,
|
|
300
|
+
status: event.status,
|
|
301
|
+
updatedAt: event.updatedAt,
|
|
302
|
+
...(event.error ? { error: event.error } : {}),
|
|
303
|
+
...(event.status === "succeeded" || event.status === "cancelled"
|
|
304
|
+
? { error: undefined }
|
|
305
|
+
: {}),
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return jobs;
|
|
304
309
|
}
|
|
305
310
|
|
|
306
311
|
/**
|
|
307
|
-
*
|
|
312
|
+
* 追加单条事件。
|
|
308
313
|
*/
|
|
309
|
-
private
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
+
private appendEvent(event: ScheduledJobEvent): void {
|
|
315
|
+
fs.appendFileSync(this.filePath, `${JSON.stringify(event)}\n`, "utf-8");
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* 执行 pending -> target 的状态迁移。
|
|
320
|
+
*/
|
|
321
|
+
private transitionPendingJob(jobId: string, status: "running" | "cancelled"): boolean {
|
|
322
|
+
const current = this.getJobById(jobId);
|
|
323
|
+
if (!current || current.status !== "pending") {
|
|
324
|
+
return false;
|
|
314
325
|
}
|
|
326
|
+
this.appendEvent({
|
|
327
|
+
v: 1,
|
|
328
|
+
type: "status",
|
|
329
|
+
jobId: current.id,
|
|
330
|
+
status,
|
|
331
|
+
updatedAt: Date.now(),
|
|
332
|
+
});
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 统一写入终态。
|
|
338
|
+
*/
|
|
339
|
+
private updateTerminalStatus(params: {
|
|
340
|
+
jobId: string;
|
|
341
|
+
status: Exclude<ScheduledJobStatus, "pending" | "running">;
|
|
342
|
+
error?: string;
|
|
343
|
+
}): boolean {
|
|
344
|
+
const current = this.getJobById(params.jobId);
|
|
345
|
+
if (!current) return false;
|
|
346
|
+
this.appendEvent({
|
|
347
|
+
v: 1,
|
|
348
|
+
type: "status",
|
|
349
|
+
jobId: current.id,
|
|
350
|
+
status: params.status,
|
|
351
|
+
updatedAt: Date.now(),
|
|
352
|
+
...(params.error ? { error: String(params.error) } : {}),
|
|
353
|
+
});
|
|
354
|
+
return true;
|
|
315
355
|
}
|
|
316
356
|
}
|