@lota-sdk/core 0.4.8 → 0.4.10

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 (272) hide show
  1. package/package.json +11 -12
  2. package/src/ai/embedding-cache.ts +96 -22
  3. package/src/ai-gateway/ai-gateway.ts +766 -223
  4. package/src/config/agent-defaults.ts +189 -75
  5. package/src/config/agent-types.ts +54 -4
  6. package/src/config/background-processing.ts +1 -1
  7. package/src/config/constants.ts +8 -2
  8. package/src/config/index.ts +0 -1
  9. package/src/config/logger.ts +299 -19
  10. package/src/config/thread-defaults.ts +40 -20
  11. package/src/create-runtime.ts +200 -449
  12. package/src/db/base.service.ts +52 -28
  13. package/src/db/cursor-pagination.ts +71 -30
  14. package/src/db/memory-query-builder.ts +2 -1
  15. package/src/db/memory-store.helpers.ts +4 -7
  16. package/src/db/memory-store.ts +868 -601
  17. package/src/db/memory.ts +396 -280
  18. package/src/db/record-id.ts +32 -10
  19. package/src/db/schema-fingerprint.ts +30 -12
  20. package/src/db/service-normalization.ts +288 -0
  21. package/src/db/service.ts +912 -779
  22. package/src/db/startup.ts +153 -68
  23. package/src/db/transaction-conflict.ts +15 -0
  24. package/src/effect/awaitable-effect.ts +96 -0
  25. package/src/effect/errors.ts +121 -0
  26. package/src/effect/helpers.ts +123 -0
  27. package/src/effect/index.ts +24 -0
  28. package/src/effect/layers.ts +238 -0
  29. package/src/effect/runtime-ref.ts +25 -0
  30. package/src/effect/runtime.ts +46 -0
  31. package/src/effect/services.ts +61 -0
  32. package/src/effect/zod.ts +43 -0
  33. package/src/embeddings/provider.ts +128 -83
  34. package/src/index.ts +48 -1
  35. package/src/openrouter/direct-provider.ts +11 -35
  36. package/src/queues/autonomous-job.queue.ts +117 -73
  37. package/src/queues/context-compaction.queue.ts +50 -17
  38. package/src/queues/delayed-node-promotion.queue.ts +46 -17
  39. package/src/queues/document-processor.queue.ts +52 -77
  40. package/src/queues/memory-consolidation.queue.ts +47 -32
  41. package/src/queues/organization-learning.queue.ts +26 -4
  42. package/src/queues/plan-agent-heartbeat.queue.ts +71 -24
  43. package/src/queues/plan-scheduler.queue.ts +97 -33
  44. package/src/queues/post-chat-memory.queue.ts +56 -26
  45. package/src/queues/queue-factory.ts +227 -59
  46. package/src/queues/standalone-worker.ts +39 -0
  47. package/src/queues/title-generation.queue.ts +45 -11
  48. package/src/redis/connection.ts +182 -113
  49. package/src/redis/index.ts +6 -8
  50. package/src/redis/org-memory-lock.ts +60 -27
  51. package/src/redis/redis-lease-lock.ts +200 -121
  52. package/src/redis/runtime-connection.ts +20 -0
  53. package/src/redis/stream-context.ts +92 -46
  54. package/src/runtime/agent-identity-overrides.ts +2 -2
  55. package/src/runtime/agent-runtime-policy.ts +5 -2
  56. package/src/runtime/agent-stream-helpers.ts +24 -9
  57. package/src/runtime/chat-run-orchestration.ts +102 -19
  58. package/src/runtime/chat-run-registry.ts +36 -2
  59. package/src/runtime/context-compaction/context-compaction-runtime.ts +107 -0
  60. package/src/runtime/{context-compaction.ts → context-compaction/context-compaction.ts} +161 -94
  61. package/src/runtime/domain-layer.ts +192 -0
  62. package/src/runtime/execution-plan-visibility.ts +2 -2
  63. package/src/runtime/execution-plan.ts +42 -15
  64. package/src/runtime/graph-designer.ts +16 -4
  65. package/src/runtime/helper-model.ts +139 -48
  66. package/src/runtime/index.ts +7 -8
  67. package/src/runtime/indexed-repositories-policy.ts +3 -3
  68. package/src/runtime/{memory-block.ts → memory/memory-block.ts} +50 -36
  69. package/src/runtime/{memory-digest-policy.ts → memory/memory-digest-policy.ts} +1 -1
  70. package/src/runtime/{memory-pipeline.ts → memory/memory-pipeline.ts} +54 -67
  71. package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
  72. package/src/runtime/memory/memory-scope.ts +53 -0
  73. package/src/runtime/plugin-resolution.ts +124 -25
  74. package/src/runtime/plugin-types.ts +9 -1
  75. package/src/runtime/post-turn-side-effects.ts +177 -130
  76. package/src/runtime/retrieval-adapters.ts +40 -6
  77. package/src/runtime/runtime-accessors.ts +92 -0
  78. package/src/runtime/runtime-config.ts +150 -61
  79. package/src/runtime/runtime-extensions.ts +23 -25
  80. package/src/runtime/runtime-lifecycle.ts +124 -0
  81. package/src/runtime/runtime-services.ts +386 -0
  82. package/src/runtime/runtime-token.ts +47 -0
  83. package/src/runtime/social-chat/social-chat-agent-runner.ts +159 -0
  84. package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +51 -20
  85. package/src/runtime/social-chat/social-chat.ts +630 -0
  86. package/src/runtime/specialist-runner.ts +36 -10
  87. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +433 -0
  88. package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts} +6 -2
  89. package/src/runtime/thread-chat-helpers.ts +2 -2
  90. package/src/runtime/thread-plan-turn.ts +2 -1
  91. package/src/runtime/thread-turn-context.ts +183 -111
  92. package/src/runtime/turn-lifecycle.ts +93 -27
  93. package/src/services/agent-activity.service.ts +287 -203
  94. package/src/services/agent-executor.service.ts +253 -149
  95. package/src/services/artifact.service.ts +231 -149
  96. package/src/services/attachment.service.ts +171 -115
  97. package/src/services/autonomous-job.service.ts +890 -491
  98. package/src/services/background-work.service.ts +54 -0
  99. package/src/services/chat-run-registry.service.ts +13 -1
  100. package/src/services/context-compaction.service.ts +136 -86
  101. package/src/services/document-chunk.service.ts +151 -88
  102. package/src/services/execution-plan/execution-plan-approval.ts +26 -0
  103. package/src/services/execution-plan/execution-plan-context.ts +29 -0
  104. package/src/services/execution-plan/execution-plan-graph.ts +278 -0
  105. package/src/services/execution-plan/execution-plan-schedule.ts +84 -0
  106. package/src/services/execution-plan/execution-plan-spec.ts +75 -0
  107. package/src/services/execution-plan/execution-plan.service.ts +1041 -0
  108. package/src/services/feedback-loop.service.ts +132 -76
  109. package/src/services/global-orchestrator.service.ts +101 -168
  110. package/src/services/graph-full-routing.ts +193 -0
  111. package/src/services/index.ts +19 -21
  112. package/src/services/institutional-memory.service.ts +213 -125
  113. package/src/services/learned-skill.service.ts +368 -260
  114. package/src/services/memory/memory-conversation.ts +95 -0
  115. package/src/services/memory/memory-errors.ts +27 -0
  116. package/src/services/memory/memory-org-memory.ts +50 -0
  117. package/src/services/memory/memory-preseeded.ts +86 -0
  118. package/src/services/memory/memory-rerank.ts +297 -0
  119. package/src/services/{memory-utils.ts → memory/memory-utils.ts} +6 -5
  120. package/src/services/memory/memory.service.ts +674 -0
  121. package/src/services/memory/rerank.service.ts +201 -0
  122. package/src/services/monitoring-window.service.ts +92 -70
  123. package/src/services/mutating-approval.service.ts +62 -53
  124. package/src/services/node-workspace.service.ts +141 -98
  125. package/src/services/notification.service.ts +29 -16
  126. package/src/services/organization-member.service.ts +120 -66
  127. package/src/services/organization.service.ts +153 -77
  128. package/src/services/ownership-dispatcher.service.ts +456 -263
  129. package/src/services/plan/plan-agent-heartbeat.service.ts +234 -0
  130. package/src/services/plan/plan-agent-query.service.ts +322 -0
  131. package/src/services/{plan-approval.service.ts → plan/plan-approval.service.ts} +45 -22
  132. package/src/services/plan/plan-artifact.service.ts +60 -0
  133. package/src/services/plan/plan-builder.service.ts +76 -0
  134. package/src/services/plan/plan-checkpoint.service.ts +103 -0
  135. package/src/services/{plan-compiler.service.ts → plan/plan-compiler.service.ts} +26 -9
  136. package/src/services/plan/plan-completion-side-effects.ts +169 -0
  137. package/src/services/plan/plan-coordination.service.ts +181 -0
  138. package/src/services/plan/plan-cycle.service.ts +405 -0
  139. package/src/services/plan/plan-deadline.service.ts +533 -0
  140. package/src/services/plan/plan-event-delivery.service.ts +266 -0
  141. package/src/services/plan/plan-executor-context.ts +35 -0
  142. package/src/services/plan/plan-executor-graph.ts +522 -0
  143. package/src/services/plan/plan-executor-helpers.ts +307 -0
  144. package/src/services/plan/plan-executor-persistence.ts +209 -0
  145. package/src/services/plan/plan-executor.service.ts +1737 -0
  146. package/src/services/{plan-helpers.ts → plan/plan-helpers.ts} +1 -1
  147. package/src/services/{plan-run-data.ts → plan/plan-run-data.ts} +4 -4
  148. package/src/services/plan/plan-run-serialization.ts +15 -0
  149. package/src/services/plan/plan-run.service.ts +637 -0
  150. package/src/services/plan/plan-scheduler.service.ts +379 -0
  151. package/src/services/plan/plan-template.service.ts +224 -0
  152. package/src/services/plan/plan-transaction-events.ts +36 -0
  153. package/src/services/plan/plan-validator.service.ts +907 -0
  154. package/src/services/plan/plan-workspace.service.ts +131 -0
  155. package/src/services/plugin-executor.service.ts +102 -68
  156. package/src/services/quality-metrics.service.ts +112 -94
  157. package/src/services/queue-job.service.ts +288 -231
  158. package/src/services/recent-activity-title.service.ts +73 -36
  159. package/src/services/recent-activity.service.ts +274 -259
  160. package/src/services/skill-resolver.service.ts +38 -12
  161. package/src/services/social-chat-history.service.ts +190 -122
  162. package/src/services/system-executor.service.ts +96 -61
  163. package/src/services/thread/thread-active-run.ts +203 -0
  164. package/src/services/thread/thread-bootstrap.ts +385 -0
  165. package/src/services/thread/thread-listing.ts +199 -0
  166. package/src/services/thread/thread-memory-block.ts +130 -0
  167. package/src/services/thread/thread-message.service.ts +379 -0
  168. package/src/services/thread/thread-record-store.ts +155 -0
  169. package/src/services/thread/thread-title.service.ts +74 -0
  170. package/src/services/thread/thread-turn-execution.ts +280 -0
  171. package/src/services/thread/thread-turn-message-context.ts +73 -0
  172. package/src/services/thread/thread-turn-preparation.service.ts +1148 -0
  173. package/src/services/thread/thread-turn-streaming.ts +403 -0
  174. package/src/services/thread/thread-turn-tracing.ts +35 -0
  175. package/src/services/thread/thread-turn.ts +376 -0
  176. package/src/services/thread/thread.service.ts +344 -0
  177. package/src/services/user.service.ts +82 -32
  178. package/src/services/write-intent-validator.service.ts +63 -51
  179. package/src/storage/attachment-parser.ts +69 -27
  180. package/src/storage/attachment-storage.service.ts +334 -275
  181. package/src/storage/generated-document-storage.service.ts +66 -34
  182. package/src/system-agents/agent-result.ts +3 -1
  183. package/src/system-agents/context-compaction.agent.ts +3 -3
  184. package/src/system-agents/delegated-agent-factory.ts +159 -90
  185. package/src/system-agents/helper-agent-options.ts +1 -1
  186. package/src/system-agents/memory-reranker.agent.ts +3 -3
  187. package/src/system-agents/memory.agent.ts +3 -3
  188. package/src/system-agents/recent-activity-title-refiner.agent.ts +3 -3
  189. package/src/system-agents/regular-chat-memory-digest.agent.ts +3 -3
  190. package/src/system-agents/skill-extractor.agent.ts +3 -3
  191. package/src/system-agents/skill-manager.agent.ts +3 -3
  192. package/src/system-agents/thread-router.agent.ts +157 -113
  193. package/src/system-agents/title-generator.agent.ts +3 -3
  194. package/src/tools/execution-plan.tool.ts +241 -171
  195. package/src/tools/fetch-webpage.tool.ts +29 -18
  196. package/src/tools/firecrawl-client.ts +26 -6
  197. package/src/tools/index.ts +1 -0
  198. package/src/tools/memory-block.tool.ts +14 -6
  199. package/src/tools/plan-approval.tool.ts +57 -47
  200. package/src/tools/read-file-parts.tool.ts +44 -33
  201. package/src/tools/remember-memory.tool.ts +65 -45
  202. package/src/tools/search-web.tool.ts +33 -22
  203. package/src/tools/search.tool.ts +41 -29
  204. package/src/tools/team-think.tool.ts +125 -84
  205. package/src/tools/user-questions.tool.ts +4 -3
  206. package/src/tools/web-tool-shared.ts +6 -0
  207. package/src/utils/async.ts +25 -22
  208. package/src/utils/crypto.ts +21 -0
  209. package/src/utils/date-time.ts +40 -1
  210. package/src/utils/errors.ts +111 -20
  211. package/src/utils/hono-error-handler.ts +24 -39
  212. package/src/utils/index.ts +2 -1
  213. package/src/utils/null-proto-record.ts +41 -0
  214. package/src/utils/sse-keepalive.ts +124 -21
  215. package/src/workers/bootstrap.ts +164 -52
  216. package/src/workers/memory-consolidation.worker.ts +325 -237
  217. package/src/workers/organization-learning.worker.ts +50 -16
  218. package/src/workers/regular-chat-memory-digest.helpers.ts +28 -27
  219. package/src/workers/regular-chat-memory-digest.runner.ts +185 -114
  220. package/src/workers/skill-extraction.runner.ts +176 -93
  221. package/src/workers/utils/file-section-chunker.ts +8 -10
  222. package/src/workers/utils/repo-structure-extractor.ts +349 -260
  223. package/src/workers/utils/repomix-file-sections.ts +2 -2
  224. package/src/workers/utils/thread-message-query.ts +97 -38
  225. package/src/workers/worker-utils.ts +74 -31
  226. package/src/config/debug-logger.ts +0 -47
  227. package/src/config/search.ts +0 -3
  228. package/src/redis/connection-accessor.ts +0 -26
  229. package/src/runtime/agent-types.ts +0 -1
  230. package/src/runtime/context-compaction-runtime.ts +0 -87
  231. package/src/runtime/memory-scope.ts +0 -43
  232. package/src/runtime/social-chat-agent-runner.ts +0 -118
  233. package/src/runtime/social-chat.ts +0 -516
  234. package/src/runtime/team-consultation-orchestrator.ts +0 -272
  235. package/src/services/adaptive-playbook.service.ts +0 -152
  236. package/src/services/artifact-provenance.service.ts +0 -172
  237. package/src/services/chat-attachments.service.ts +0 -17
  238. package/src/services/context-compaction-runtime.singleton.ts +0 -13
  239. package/src/services/execution-plan.service.ts +0 -1118
  240. package/src/services/memory.service.ts +0 -914
  241. package/src/services/plan-agent-heartbeat.service.ts +0 -136
  242. package/src/services/plan-agent-query.service.ts +0 -267
  243. package/src/services/plan-artifact.service.ts +0 -50
  244. package/src/services/plan-builder.service.ts +0 -67
  245. package/src/services/plan-checkpoint.service.ts +0 -81
  246. package/src/services/plan-completion-side-effects.ts +0 -80
  247. package/src/services/plan-coordination.service.ts +0 -157
  248. package/src/services/plan-cycle.service.ts +0 -284
  249. package/src/services/plan-deadline.service.ts +0 -430
  250. package/src/services/plan-event-delivery.service.ts +0 -166
  251. package/src/services/plan-executor.service.ts +0 -1950
  252. package/src/services/plan-run.service.ts +0 -515
  253. package/src/services/plan-scheduler.service.ts +0 -240
  254. package/src/services/plan-template.service.ts +0 -177
  255. package/src/services/plan-validator.service.ts +0 -818
  256. package/src/services/plan-workspace.service.ts +0 -83
  257. package/src/services/rerank.service.ts +0 -156
  258. package/src/services/thread-message.service.ts +0 -275
  259. package/src/services/thread-plan-registry.service.ts +0 -22
  260. package/src/services/thread-title.service.ts +0 -39
  261. package/src/services/thread-turn-preparation.service.ts +0 -1147
  262. package/src/services/thread-turn.ts +0 -172
  263. package/src/services/thread.service.ts +0 -869
  264. package/src/utils/env.ts +0 -8
  265. /package/src/runtime/{context-compaction-constants.ts → context-compaction/context-compaction-constants.ts} +0 -0
  266. /package/src/runtime/{memory-format.ts → memory/memory-format.ts} +0 -0
  267. /package/src/runtime/{memory-prompts-parse.ts → memory/memory-prompts-parse.ts} +0 -0
  268. /package/src/runtime/{memory-prompts-update.ts → memory/memory-prompts-update.ts} +0 -0
  269. /package/src/runtime/{social-chat-prompts.ts → social-chat/social-chat-prompts.ts} +0 -0
  270. /package/src/services/{plan-node-spec.ts → plan/plan-node-spec.ts} +0 -0
  271. /package/src/services/{thread-constants.ts → thread/thread-constants.ts} +0 -0
  272. /package/src/services/{thread.types.ts → thread/thread.types.ts} +0 -0
@@ -1,37 +1,58 @@
1
1
  import type { ChatMessage } from '@lota-sdk/shared'
2
2
  import { stepCountIs } from 'ai'
3
3
  import type { ToolSet } from 'ai'
4
+ import { Schema, Effect } from 'effect'
4
5
 
5
- import { createAgent, getAgentRuntimeConfig } from '../config/agent-defaults'
6
+ import { getAgentRuntimeConfig, getResolvedAgentFactoryConfig } from '../config/agent-defaults'
6
7
  import { aiLogger } from '../config/logger'
7
8
  import type { RecordIdRef } from '../db/record-id'
8
9
  import { recordIdToString } from '../db/record-id'
9
10
  import { TABLES } from '../db/tables'
11
+ import { effectTryMaybeAsync as effectTryMaybeAsyncShared } from '../effect/helpers'
10
12
  import { readRuntimeAgentIdentityOverrides } from '../runtime/agent-identity-overrides'
11
13
  import { mergeInstructionSections } from '../runtime/instruction-sections'
12
14
  import { getRuntimeAdapters, getTurnHooks } from '../runtime/runtime-extensions'
13
15
  import type { LotaRuntimeTeamThinkToolsParams } from '../runtime/runtime-extensions'
14
- import { createConsultTeamTool as createConsultTeamToolSdk } from '../runtime/team-consultation-orchestrator'
15
- import type { DefaultRepoSections, TeamConsultationParticipantRunner } from '../runtime/team-consultation-orchestrator'
16
- import { buildTeamConsultationResponseGuard } from '../runtime/team-consultation-prompts'
16
+ import { createConsultTeamTool as createConsultTeamToolSdk } from '../runtime/team-consultation/team-consultation-orchestrator'
17
+ import type {
18
+ DefaultRepoSections,
19
+ TeamConsultationParticipantRunner,
20
+ } from '../runtime/team-consultation/team-consultation-orchestrator'
21
+ import { buildTeamConsultationResponseGuard } from '../runtime/team-consultation/team-consultation-prompts'
17
22
  import { asRecord, readInstructionSections, readOptionalString } from '../runtime/thread-chat-helpers'
18
23
  import type { ReadableUploadMetadata } from '../services/attachment.service'
19
24
 
20
- async function buildTeamThinkAgentTools(
25
+ function buildTeamThinkAgentToolsEffect(
21
26
  params: LotaRuntimeTeamThinkToolsParams,
22
- ): Promise<{ tools: Record<string, unknown> }> {
27
+ ): Effect.Effect<{ tools: ToolSet }, TeamThinkRuntimeError> {
23
28
  const builder = getRuntimeAdapters().buildTeamThinkAgentTools
24
29
  if (!builder) {
25
- return { tools: {} }
30
+ return Effect.succeed({ tools: {} })
26
31
  }
27
32
 
28
- const result = await builder(params)
29
- return { tools: result.tools as Record<string, unknown> }
33
+ return effectTryMaybeAsync(() => builder(params), 'Failed to build team-think agent tools.')
30
34
  }
31
35
 
32
36
  const TEAM_THINK_AGENT_MAX_RETRIES = 1
33
37
  const TEAM_THINK_AGENT_MAX_STEPS = 3
34
38
 
39
+ class TeamThinkAgentFactoryNotConfiguredError extends Schema.TaggedErrorClass<TeamThinkAgentFactoryNotConfiguredError>()(
40
+ 'TeamThinkAgentFactoryNotConfiguredError',
41
+ { agentId: Schema.String },
42
+ ) {}
43
+
44
+ class TeamThinkRuntimeError extends Schema.TaggedErrorClass<TeamThinkRuntimeError>()('TeamThinkRuntimeError', {
45
+ message: Schema.String,
46
+ cause: Schema.optional(Schema.Defect),
47
+ }) {}
48
+
49
+ function effectTryMaybeAsync<A>(
50
+ evaluate: () => A | PromiseLike<A>,
51
+ message: string,
52
+ ): Effect.Effect<A, TeamThinkRuntimeError> {
53
+ return effectTryMaybeAsyncShared(evaluate, (error) => new TeamThinkRuntimeError({ message, cause: error }))
54
+ }
55
+
35
56
  export function createTeamThinkTool(params: {
36
57
  historyMessages: ChatMessage[]
37
58
  latestUserMessageId: string
@@ -55,82 +76,102 @@ export function createTeamThinkTool(params: {
55
76
  (params.context as Record<string, unknown> | null | undefined) ?? null,
56
77
  )
57
78
  const participantRunner: TeamConsultationParticipantRunner = {
58
- async buildParticipantAgent(agentId, runParams) {
59
- const dynamicInstructionSections = await params.getAdditionalInstructionSections?.()
60
- const agentResolution = asRecord(
61
- await getTurnHooks().resolveAgent?.({
62
- agentId,
63
- mode: 'fixedThreadMode',
64
- thread: null,
65
- threadRef: params.threadId,
66
- orgRef: params.orgId,
67
- userRef: params.userId,
68
- onboardingActive: false,
69
- linearInstalled: false,
70
- githubInstalled: params.githubInstalled,
71
- additionalInstructionSections: mergeInstructionSections(
72
- dynamicInstructionSections,
73
- params.additionalInstructionSections,
74
- ),
75
- context: (params.context as Record<string, unknown> | null | undefined) ?? null,
76
- }),
79
+ buildParticipantAgent(agentId, runParams) {
80
+ return Effect.runPromise(
81
+ Effect.gen(function* () {
82
+ const currentContext = yield* Effect.context()
83
+ const runPromiseWithCurrentContext = Effect.runPromiseWith(currentContext)
84
+ const dynamicInstructionSections = yield* effectTryMaybeAsync(
85
+ () => params.getAdditionalInstructionSections?.(),
86
+ 'Failed to load dynamic team-think instruction sections.',
87
+ )
88
+ const agentResolution = asRecord(
89
+ yield* effectTryMaybeAsync(
90
+ () =>
91
+ getTurnHooks().resolveAgent?.({
92
+ agentId,
93
+ mode: 'fixedThreadMode',
94
+ thread: null,
95
+ threadRef: params.threadId,
96
+ orgRef: params.orgId,
97
+ userRef: params.userId,
98
+ onboardingActive: false,
99
+ linearInstalled: false,
100
+ githubInstalled: params.githubInstalled,
101
+ additionalInstructionSections: mergeInstructionSections(
102
+ dynamicInstructionSections,
103
+ params.additionalInstructionSections,
104
+ ),
105
+ context: (params.context as Record<string, unknown> | null | undefined) ?? null,
106
+ }),
107
+ 'Failed to resolve team-think participant agent.',
108
+ ),
109
+ )
110
+ const resolvedAgentId = readOptionalString(agentResolution?.agentId) ?? agentId
111
+ const config = getAgentRuntimeConfig({
112
+ agentId: resolvedAgentId,
113
+ threadType: 'group' as const,
114
+ mode: 'fixedThreadMode',
115
+ onboardingActive: false,
116
+ linearInstalled: false,
117
+ systemWorkspaceDetails: runParams.systemWorkspaceDetails,
118
+ preSeededMemoriesSection: runParams.preSeededMemoriesSection,
119
+ retrievedKnowledgeSection: runParams.retrievedKnowledgeSection,
120
+ additionalInstructionSections: mergeInstructionSections(
121
+ dynamicInstructionSections,
122
+ params.additionalInstructionSections,
123
+ readInstructionSections(agentResolution?.additionalInstructionSections),
124
+ ),
125
+ responseGuardSection: buildTeamConsultationResponseGuard({
126
+ agentId: resolvedAgentId,
127
+ task: runParams.task,
128
+ }),
129
+ })
130
+ const { tools } = yield* buildTeamThinkAgentToolsEffect({
131
+ agentId: resolvedAgentId,
132
+ workspaceId: params.orgId,
133
+ userId: params.userId,
134
+ workspaceIdString: recordIdToString(params.orgId, TABLES.ORGANIZATION),
135
+ threadId: params.threadId,
136
+ githubInstalled: params.githubInstalled,
137
+ provideRepoTool: resolvedAgentId !== 'mentor' && params.provideRepoTool,
138
+ availableUploads: params.availableUploads,
139
+ defaultRepoSections: params.defaultRepoSectionsByAgent[resolvedAgentId],
140
+ context: params.context,
141
+ toolProviders: params.toolProviders,
142
+ })
143
+ const agentId_ = config.id || resolvedAgentId
144
+ const configuredMaxSteps = config.maxSteps
145
+ const maxSteps = Math.min(configuredMaxSteps, TEAM_THINK_AGENT_MAX_STEPS)
146
+ const agentFactory = getResolvedAgentFactoryConfig().createAgent[agentId_]
147
+ if (!agentFactory) {
148
+ return yield* new TeamThinkAgentFactoryNotConfiguredError({ agentId: agentId_ })
149
+ }
150
+ const agent = agentFactory({
151
+ mode: 'fixedThreadMode',
152
+ tools,
153
+ extraInstructions: config.extraInstructions,
154
+ maxRetries: TEAM_THINK_AGENT_MAX_RETRIES,
155
+ stopWhen: [stepCountIs(maxSteps)],
156
+ })
157
+ const observer = {
158
+ run: <T>(fn: () => T | Promise<T>): Promise<T> =>
159
+ runPromiseWithCurrentContext(effectTryMaybeAsync(fn, `Team-think participant run failed (${agentId}).`)),
160
+ recordError: (error: unknown) => {
161
+ aiLogger.error`Team-think participant failed (${agentId}): ${error}`
162
+ },
163
+ recordAbort: (error: unknown) => {
164
+ aiLogger.debug`Team-think participant aborted (${agentId}): ${
165
+ error instanceof Error ? error.message : String(error)
166
+ }`
167
+ },
168
+ }
169
+ return {
170
+ agent: agent as Awaited<ReturnType<TeamConsultationParticipantRunner['buildParticipantAgent']>>['agent'],
171
+ observer,
172
+ }
173
+ }).pipe(Effect.withSpan('tool.teamThink.buildParticipantAgent')),
77
174
  )
78
- const resolvedAgentId = readOptionalString(agentResolution?.agentId) ?? agentId
79
- const config = getAgentRuntimeConfig({
80
- agentId: resolvedAgentId,
81
- threadType: 'group' as const,
82
- mode: 'fixedThreadMode',
83
- onboardingActive: false,
84
- linearInstalled: false,
85
- systemWorkspaceDetails: runParams.systemWorkspaceDetails,
86
- preSeededMemoriesSection: runParams.preSeededMemoriesSection,
87
- retrievedKnowledgeSection: runParams.retrievedKnowledgeSection,
88
- additionalInstructionSections: mergeInstructionSections(
89
- dynamicInstructionSections,
90
- params.additionalInstructionSections,
91
- readInstructionSections(agentResolution?.additionalInstructionSections),
92
- ),
93
- responseGuardSection: buildTeamConsultationResponseGuard({ agentId: resolvedAgentId, task: runParams.task }),
94
- })
95
- const { tools } = await buildTeamThinkAgentTools({
96
- agentId: resolvedAgentId,
97
- workspaceId: params.orgId,
98
- userId: params.userId,
99
- workspaceIdString: recordIdToString(params.orgId, TABLES.ORGANIZATION),
100
- threadId: params.threadId,
101
- githubInstalled: params.githubInstalled,
102
- provideRepoTool: resolvedAgentId !== 'mentor' && params.provideRepoTool,
103
- availableUploads: params.availableUploads,
104
- defaultRepoSections: params.defaultRepoSectionsByAgent[resolvedAgentId],
105
- context: params.context,
106
- toolProviders: params.toolProviders,
107
- })
108
- const agentConfig = config as Record<string, unknown>
109
- const agentId_ = typeof agentConfig.id === 'string' ? agentConfig.id : resolvedAgentId
110
- const configuredMaxSteps = typeof agentConfig.maxSteps === 'number' ? agentConfig.maxSteps : 10
111
- const maxSteps = Math.min(configuredMaxSteps, TEAM_THINK_AGENT_MAX_STEPS)
112
- const agent = createAgent[agentId_]({
113
- mode: 'fixedThreadMode',
114
- tools,
115
- extraInstructions: agentConfig.extraInstructions,
116
- maxRetries: TEAM_THINK_AGENT_MAX_RETRIES,
117
- stopWhen: [stepCountIs(maxSteps)],
118
- })
119
- const observer = {
120
- run: async <T>(fn: () => T | Promise<T>): Promise<T> => fn(),
121
- recordError: (error: unknown) => {
122
- aiLogger.error`Team-think participant failed (${agentId}): ${error}`
123
- },
124
- recordAbort: (error: unknown) => {
125
- aiLogger.info`Team-think participant aborted (${agentId}): ${
126
- error instanceof Error ? error.message : String(error)
127
- }`
128
- },
129
- }
130
- return {
131
- agent: agent as Awaited<ReturnType<TeamConsultationParticipantRunner['buildParticipantAgent']>>['agent'],
132
- observer,
133
- }
134
175
  },
135
176
  }
136
177
 
@@ -11,8 +11,9 @@ export const userQuestionsTool = {
11
11
  description:
12
12
  'Ask the user structured questions. UI renders them; do not repeat them in text. Turn ends after this call.',
13
13
  inputSchema: UserQuestionsArgsSchema,
14
- execute: async (_args: UserQuestionsArgs) => {
15
- return 'Questions have been presented to the user in the chat UI. Do NOT restate them in text, and do NOT generate further text or tool calls. Your turn is complete.'
16
- },
14
+ execute: (_args: UserQuestionsArgs) =>
15
+ Promise.resolve(
16
+ 'Questions have been presented to the user in the chat UI. Do NOT restate them in text, and do NOT generate further text or tool calls. Your turn is complete.',
17
+ ),
17
18
  }),
18
19
  } as const satisfies ToolDefinition<void>
@@ -0,0 +1,6 @@
1
+ export const WEB_TOOL_TIMEOUT_MS = 30_000
2
+
3
+ export function toRecord(value: unknown): Record<string, unknown> | null {
4
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null
5
+ return value as Record<string, unknown>
6
+ }
@@ -1,30 +1,33 @@
1
+ import { Cause, Duration, Effect, Exit, Schema } from 'effect'
2
+
1
3
  import { serverLogger } from '../config/logger'
2
- import { getErrorMessage } from './errors'
4
+ import { TimeoutError } from '../effect/errors'
5
+ import { getErrorMessage, toError } from './errors'
3
6
 
4
- class TimeoutError extends Error {
5
- constructor(operation: string, ms: number) {
6
- super(`${operation} timed out after ${ms}ms`)
7
- this.name = 'TimeoutError'
8
- }
7
+ class TimedOperationError extends Schema.TaggedErrorClass<TimedOperationError>()('TimedOperationError', {
8
+ operation: Schema.String,
9
+ cause: Schema.Defect,
10
+ }) {}
11
+
12
+ function isTimedOperationError(error: unknown): error is TimedOperationError {
13
+ return typeof error === 'object' && error !== null && '_tag' in error && error._tag === 'TimedOperationError'
9
14
  }
10
15
 
11
- export async function withTimeout<T>(promise: Promise<T>, ms: number, operation: string): Promise<T> {
12
- let timeoutId: ReturnType<typeof setTimeout> | undefined
13
-
14
- try {
15
- return await Promise.race([
16
- promise,
17
- new Promise<never>((_, reject) => {
18
- timeoutId = setTimeout(() => {
19
- reject(new TimeoutError(operation, ms))
20
- }, ms)
21
- }),
22
- ])
23
- } finally {
24
- if (timeoutId) {
25
- clearTimeout(timeoutId)
16
+ export function withTimeout<T>(promise: Promise<T>, ms: number, operation: string): Promise<T> {
17
+ return Effect.runPromise(
18
+ Effect.tryPromise({ try: () => promise, catch: (cause) => new TimedOperationError({ operation, cause }) }).pipe(
19
+ Effect.timeout(Duration.millis(ms)),
20
+ Effect.catchTag('TimeoutError', () => Effect.fail(new TimeoutError({ operation, ms }))),
21
+ Effect.exit,
22
+ ),
23
+ ).then((exit) => {
24
+ if (Exit.isSuccess(exit)) {
25
+ return exit.value
26
26
  }
27
- }
27
+
28
+ const error = Cause.squash(exit.cause)
29
+ throw isTimedOperationError(error) ? toError(error.cause) : error
30
+ })
28
31
  }
29
32
 
30
33
  export function createSafeEnqueue(logger: { warn: (message: string) => void }) {
@@ -0,0 +1,21 @@
1
+ import { RecordId } from 'surrealdb'
2
+
3
+ export function createSha256Hasher(): Bun.CryptoHasher {
4
+ return new Bun.CryptoHasher('sha256')
5
+ }
6
+
7
+ export function sha256Hex(value: string): string {
8
+ return createSha256Hasher().update(value).digest('hex')
9
+ }
10
+
11
+ export function sha256HexFromParts(parts: Iterable<string>): string {
12
+ const hasher = createSha256Hasher()
13
+ for (const part of parts) {
14
+ hasher.update(part)
15
+ }
16
+ return hasher.digest('hex')
17
+ }
18
+
19
+ export function createDeterministicRecordId(table: string, key: string): RecordId {
20
+ return new RecordId(table, sha256Hex(key))
21
+ }
@@ -1,3 +1,5 @@
1
+ import { DateTime } from 'effect'
2
+
1
3
  export { toIsoDateTimeString, toOptionalIsoDateTimeString } from '@lota-sdk/shared'
2
4
 
3
5
  const PROMPT_DATE_FORMATTER = new Intl.DateTimeFormat('en-US', {
@@ -9,9 +11,46 @@ const PROMPT_DATE_FORMATTER = new Intl.DateTimeFormat('en-US', {
9
11
 
10
12
  export function toDatabaseDateTime(value: string | Date | null | undefined): Date | undefined {
11
13
  if (value === null || value === undefined) return undefined
12
- return value instanceof Date ? value : new Date(value)
14
+ return value instanceof Date ? value : DateTime.toDateUtc(DateTime.makeUnsafe(value))
13
15
  }
14
16
 
15
17
  export function formatUtcPromptDate(value: Date): string {
16
18
  return PROMPT_DATE_FORMATTER.format(value)
17
19
  }
20
+
21
+ export function nowDateTime(): DateTime.Utc {
22
+ return DateTime.nowUnsafe()
23
+ }
24
+
25
+ export function nowEpochMillis(): number {
26
+ return nowDateTime().epochMilliseconds
27
+ }
28
+
29
+ export function nowDate(): Date {
30
+ return DateTime.toDateUtc(nowDateTime())
31
+ }
32
+
33
+ export function nowIsoDateTimeString(): string {
34
+ return DateTime.formatIso(nowDateTime())
35
+ }
36
+
37
+ export function unsafeDateFrom(value: string | number | Date): Date {
38
+ if (value instanceof Date) {
39
+ return value
40
+ }
41
+
42
+ const normalized = typeof value === 'number' && value < 1_000_000_000_000 ? value * 1000 : value
43
+ return DateTime.toDateUtc(DateTime.makeUnsafe(normalized))
44
+ }
45
+
46
+ export function unsafeDateFromUnknown(value: unknown): Date {
47
+ if (value instanceof Date) {
48
+ return value
49
+ }
50
+
51
+ if (typeof value === 'number') {
52
+ return unsafeDateFrom(value)
53
+ }
54
+
55
+ return DateTime.toDateUtc(DateTime.makeUnsafe(String(value)))
56
+ }
@@ -1,35 +1,50 @@
1
1
  export { getErrorMessage } from '@lota-sdk/shared'
2
+ import { Data, Match } from 'effect'
3
+
4
+ import type { EffectError, ValidationIssue } from '../effect/errors'
5
+ import { BaseServicePersistenceError, isEffectError } from '../effect/errors'
2
6
 
3
7
  export function toError(value: unknown): Error {
4
8
  return value instanceof Error ? value : new Error(String(value))
5
9
  }
6
10
 
7
- export class AppError extends Error {
8
- public readonly code: string
9
- public readonly statusCode: number
11
+ export interface HttpError {
12
+ statusCode: number
13
+ code: string
14
+ message: string
15
+ }
16
+
17
+ export interface AppErrorResponse {
18
+ status: number
19
+ body: { error: { code: string; message: string } }
20
+ }
21
+
22
+ export type AppErrorLike = Error & { code: string; statusCode: number; toResponse?: () => unknown }
10
23
 
24
+ export class AppError extends Data.Error<{
25
+ readonly message: string
26
+ readonly code: string
27
+ readonly statusCode: number
28
+ }> {
11
29
  constructor(message: string, code: string, statusCode: number) {
12
- super(message)
13
- this.name = this.constructor.name
14
- this.code = code
15
- this.statusCode = statusCode
16
- Error.captureStackTrace(this, this.constructor)
30
+ super({ message, code, statusCode })
31
+ this.name = new.target.name
17
32
  }
18
33
 
19
- public toResponse() {
34
+ toResponse(): AppErrorResponse {
20
35
  return { status: this.statusCode, body: { error: { code: this.code, message: this.message } } }
21
36
  }
22
37
  }
23
38
 
24
- export class NotFoundError extends AppError {
25
- constructor(message = 'Resource not found') {
26
- super(message, 'NOT_FOUND', 404)
39
+ export class BadRequestError extends AppError {
40
+ constructor(message: string) {
41
+ super(message, 'BAD_REQUEST', 400)
27
42
  }
28
43
  }
29
44
 
30
- export class BadRequestError extends AppError {
31
- constructor(message = 'Bad request') {
32
- super(message, 'BAD_REQUEST', 400)
45
+ export class NotFoundError extends AppError {
46
+ constructor(message: string) {
47
+ super(message, 'NOT_FOUND', 404)
33
48
  }
34
49
  }
35
50
 
@@ -44,11 +59,6 @@ type ErrorCode =
44
59
  | 'HTTP_ERROR'
45
60
  | 'TOO_MANY_REQUESTS'
46
61
 
47
- interface ValidationIssue {
48
- path: string
49
- message: string
50
- }
51
-
52
62
  export interface ErrorBody {
53
63
  error: { code: ErrorCode; message: string; issues?: ValidationIssue[] }
54
64
  }
@@ -73,3 +83,84 @@ export const errorResponses = {
73
83
  createValidationErrorResponse(message, issues),
74
84
  httpError: (message: string) => createErrorResponse('HTTP_ERROR', message),
75
85
  } as const
86
+
87
+ function httpError(message: string, code: string, statusCode: number): HttpError {
88
+ return { message, code, statusCode }
89
+ }
90
+
91
+ export function isAppErrorLike(error: unknown): error is AppErrorLike {
92
+ if (!(error instanceof Error)) {
93
+ return false
94
+ }
95
+
96
+ const candidate = error as Partial<AppErrorLike>
97
+ return typeof candidate.code === 'string' && typeof candidate.statusCode === 'number'
98
+ }
99
+
100
+ function isAppErrorResponse(value: unknown): value is AppErrorResponse {
101
+ if (typeof value !== 'object' || value === null) {
102
+ return false
103
+ }
104
+
105
+ const candidate = value as {
106
+ status?: unknown
107
+ body?: { error?: { code?: unknown; message?: unknown } | null } | null
108
+ }
109
+ return (
110
+ typeof candidate.status === 'number' &&
111
+ typeof candidate.body === 'object' &&
112
+ candidate.body !== null &&
113
+ typeof candidate.body.error === 'object' &&
114
+ candidate.body.error !== null &&
115
+ typeof candidate.body.error.code === 'string' &&
116
+ typeof candidate.body.error.message === 'string'
117
+ )
118
+ }
119
+
120
+ export function toAppErrorResponse(error: AppErrorLike): AppErrorResponse {
121
+ if (typeof error.toResponse === 'function') {
122
+ const response = error.toResponse()
123
+ if (isAppErrorResponse(response)) {
124
+ return response
125
+ }
126
+ }
127
+
128
+ return { status: error.statusCode, body: { error: { code: error.code, message: error.message } } }
129
+ }
130
+
131
+ function isBaseServicePersistenceError(error: EffectError): error is BaseServicePersistenceError {
132
+ return error._tag === BaseServicePersistenceError.name
133
+ }
134
+
135
+ const toHttpErrorMatch = Match.type<Exclude<EffectError, BaseServicePersistenceError>>().pipe(
136
+ Match.tag('NotFoundError', (e) => httpError(e.message, 'NOT_FOUND', 404)),
137
+ Match.tag('BadRequestError', (e) => httpError(e.message, 'BAD_REQUEST', 400)),
138
+ Match.tag('ValidationError', (e) => httpError(e.message, 'VALIDATION_ERROR', 400)),
139
+ Match.tag('ConflictError', (e) => httpError(e.message, 'CONFLICT', 409)),
140
+ Match.tag('ForbiddenError', (e) => httpError(e.message, 'FORBIDDEN', 403)),
141
+ Match.tag('ThreadTurnError', (e) =>
142
+ httpError(e.message, e.reason === 'conflict' ? 'CONFLICT' : 'BAD_REQUEST', e.reason === 'conflict' ? 409 : 400),
143
+ ),
144
+ Match.tag('ActiveThreadRunConflictError', (e) => httpError(e.message, 'CONFLICT', 409)),
145
+ Match.tag('ConfigurationError', (e) => httpError(e.message, 'INTERNAL_SERVER_ERROR', 500)),
146
+ Match.tag('DatabaseError', () => httpError('Internal server error', 'INTERNAL_SERVER_ERROR', 500)),
147
+ Match.tag('RedisError', () => httpError('Internal server error', 'INTERNAL_SERVER_ERROR', 500)),
148
+ Match.tag('TimeoutError', (e) =>
149
+ httpError(`Operation "${e.operation}" timed out after ${e.ms}ms`, 'INTERNAL_SERVER_ERROR', 500),
150
+ ),
151
+ Match.tag('LockAcquisitionError', () => httpError('Internal server error', 'INTERNAL_SERVER_ERROR', 500)),
152
+ Match.tag('LockLostError', () => httpError('Internal server error', 'INTERNAL_SERVER_ERROR', 500)),
153
+ Match.tag('AiGenerationError', (e) => httpError(e.message, 'INTERNAL_SERVER_ERROR', 500)),
154
+ Match.tag('ServiceError', () => httpError('Internal server error', 'INTERNAL_SERVER_ERROR', 500)),
155
+ Match.exhaustive,
156
+ )
157
+
158
+ export function toHttpError(error: EffectError): HttpError {
159
+ if (isBaseServicePersistenceError(error)) {
160
+ return httpError('Internal server error', 'INTERNAL_SERVER_ERROR', 500)
161
+ }
162
+
163
+ return toHttpErrorMatch(error)
164
+ }
165
+
166
+ export { isEffectError }
@@ -2,69 +2,54 @@ import type { ErrorHandler } from 'hono'
2
2
  import { HTTPException } from 'hono/http-exception'
3
3
  import { ZodError } from 'zod'
4
4
 
5
- import { AppError, getErrorMessage } from './errors'
6
-
7
- type AppErrorLike = Pick<AppError, 'code' | 'message' | 'statusCode' | 'toResponse'> & { name?: string }
5
+ import { toValidationIssues } from '../effect/zod'
6
+ import { getErrorMessage, isAppErrorLike, isEffectError, toAppErrorResponse, toHttpError } from './errors'
8
7
 
9
8
  type HonoErrorLogger = Pick<Console, 'warn' | 'error'>
10
9
 
11
- function isAppErrorLike(error: unknown): error is AppErrorLike {
12
- if (!error || typeof error !== 'object') {
13
- return false
14
- }
15
-
16
- const candidate = error as Partial<AppErrorLike>
17
- return (
18
- typeof candidate.code === 'string' &&
19
- typeof candidate.message === 'string' &&
20
- typeof candidate.statusCode === 'number' &&
21
- typeof candidate.toResponse === 'function'
22
- )
10
+ function createErrorResponse(code: string, message: string) {
11
+ return { error: { code, message } }
23
12
  }
24
13
 
25
14
  function createValidationErrorResponse(issues: Array<{ path: string; message: string }>) {
26
15
  return { error: { code: 'VALIDATION_ERROR', message: 'Validation failed', issues } }
27
16
  }
28
17
 
29
- function createHttpErrorResponse(message: string) {
30
- return { error: { code: 'HTTP_ERROR', message } }
31
- }
32
-
33
- function createServerErrorResponse(message: string) {
34
- return { error: { code: 'INTERNAL_SERVER_ERROR', message } }
35
- }
36
-
37
18
  export function createHonoErrorHandler(logger: HonoErrorLogger): ErrorHandler {
38
19
  return (error, c) => {
39
- const appError = error instanceof AppError || isAppErrorLike(error) ? error : null
40
-
41
- if (appError) {
42
- const log = appError.statusCode >= 500 ? logger.error : logger.warn
43
- const errorName = typeof appError.name === 'string' && appError.name.length > 0 ? appError.name : 'AppError'
44
- log(`Request failed: ${errorName} (${appError.code}) ${appError.message}`)
45
- const { status, body } = appError.toResponse()
46
- const typedStatus = status as Parameters<typeof c.json>[1]
47
- return c.json(body, typedStatus)
48
- }
49
-
50
20
  if (error instanceof HTTPException) {
51
21
  const log = error.status >= 500 ? logger.error : logger.warn
52
22
  log(`Request failed: HTTPException ${error.status} ${error.message}`)
53
- return error.res ?? c.json(createHttpErrorResponse(error.message), error.status)
23
+ return error.res ?? c.json(createErrorResponse('HTTP_ERROR', error.message), error.status)
54
24
  }
55
25
 
56
26
  if (error instanceof ZodError) {
57
27
  logger.warn(`Request failed: ZodError ${error.message}`)
58
- const issues = error.issues.map((issue) => ({ path: issue.path.join('.'), message: issue.message }))
59
- return c.json(createValidationErrorResponse(issues), 400)
28
+ return c.json(createValidationErrorResponse([...toValidationIssues(error)]), 400)
29
+ }
30
+
31
+ if (isAppErrorLike(error)) {
32
+ const response = toAppErrorResponse(error)
33
+ const log = response.status >= 500 ? logger.error : logger.warn
34
+ log(`Request failed: ${error.name} ${error.message}`)
35
+ const typedStatus = response.status as Parameters<typeof c.json>[1]
36
+ return c.json(response.body, typedStatus)
37
+ }
38
+
39
+ if (isEffectError(error)) {
40
+ const httpError = toHttpError(error)
41
+ const log = httpError.statusCode >= 500 ? logger.error : logger.warn
42
+ log(`Request failed: ${error._tag} ${error.message}`)
43
+ const typedStatus = httpError.statusCode as Parameters<typeof c.json>[1]
44
+ return c.json(createErrorResponse(httpError.code, httpError.message), typedStatus)
60
45
  }
61
46
 
62
47
  if (error instanceof Error) {
63
48
  logger.error(`Server error: ${error.name} ${error.message}\n${error.stack ?? ''}`)
64
- return c.json(createServerErrorResponse('Internal Server Error'), 500)
49
+ return c.json(createErrorResponse('INTERNAL_SERVER_ERROR', 'Internal Server Error'), 500)
65
50
  }
66
51
 
67
52
  logger.error(`Server error: ${getErrorMessage(error)}`)
68
- return c.json(createServerErrorResponse('Internal Server Error'), 500)
53
+ return c.json(createErrorResponse('INTERNAL_SERVER_ERROR', 'Internal Server Error'), 500)
69
54
  }
70
55
  }
@@ -1,8 +1,9 @@
1
1
  export * from './async'
2
+ export * from './crypto'
2
3
  export * from './date-time'
3
- export * from './env'
4
4
  export * from './errors'
5
5
  export * from './hono-error-handler'
6
+ export * from './null-proto-record'
6
7
  export * from './sse-keepalive'
7
8
  export {
8
9
  CHARS_PER_TOKEN_ESTIMATE,