sparkecoder 0.1.60 → 0.1.61

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 (171) hide show
  1. package/dist/agent/index.d.ts +4 -3
  2. package/dist/agent/index.js +588 -176
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +818 -95
  5. package/dist/cli.js.map +1 -1
  6. package/dist/db/index.d.ts +3 -2
  7. package/dist/db/index.js.map +1 -1
  8. package/dist/{index-Csad1Nx4.d.ts → index-DuGtMaAJ.d.ts} +85 -4
  9. package/dist/index.d.ts +6 -5
  10. package/dist/index.js +1202 -665
  11. package/dist/index.js.map +1 -1
  12. package/dist/schema-C7Mm4Ykn.d.ts +1410 -0
  13. package/dist/{search-BETuS1vh.d.ts → search-C_IFImt1.d.ts} +3 -3
  14. package/dist/server/index.js +605 -68
  15. package/dist/server/index.js.map +1 -1
  16. package/dist/tools/index.d.ts +38 -3
  17. package/dist/tools/index.js +230 -2
  18. package/dist/tools/index.js.map +1 -1
  19. package/package.json +5 -3
  20. package/web/.next/BUILD_ID +1 -1
  21. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  22. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  23. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  24. package/web/.next/standalone/web/.next/server/app/(main)/page.js.nft.json +1 -1
  25. package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
  26. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
  27. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  29. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  34. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  36. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  37. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +2 -2
  38. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  39. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  40. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  41. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  43. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  44. package/web/.next/standalone/web/.next/server/app/api/config/route.js.nft.json +1 -1
  45. package/web/.next/standalone/web/.next/server/app/api/health/route.js.nft.json +1 -1
  46. package/web/.next/standalone/web/.next/server/app/docs/installation/page_client-reference-manifest.js +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  48. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +2 -2
  49. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +2 -2
  50. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +2 -2
  52. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +2 -2
  53. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  54. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  55. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/page_client-reference-manifest.js +1 -1
  57. package/web/.next/standalone/web/.next/server/app/docs/skills/page_client-reference-manifest.js +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  59. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +2 -2
  60. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +2 -2
  61. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  62. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +2 -2
  63. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +2 -2
  64. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  65. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs/tools/page_client-reference-manifest.js +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  69. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +2 -2
  70. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +2 -2
  71. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  72. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +2 -2
  73. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +2 -2
  74. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  75. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  76. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  77. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  78. package/web/.next/standalone/web/.next/server/app/docs.rsc +2 -2
  79. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +2 -2
  80. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  81. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +2 -2
  82. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +2 -2
  83. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  84. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  85. package/web/.next/standalone/web/.next/server/app/embed/[id]/page.js.nft.json +1 -1
  86. package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +1 -1
  87. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  88. package/web/.next/standalone/web/.next/server/app/index.rsc +4 -4
  89. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
  90. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
  91. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
  92. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  93. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
  94. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  95. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_19289e11._.js → 2374f_03d22c16._.js} +1 -1
  96. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_b4b86c1f._.js → 2374f_0d0b1fb9._.js} +1 -1
  97. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_4858a1ea._.js → 2374f_3f7d6d28._.js} +1 -1
  98. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_51385fed._.js → 2374f_6166d14d._.js} +1 -1
  99. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_40e35a02._.js → 2374f_67b9525f._.js} +1 -1
  100. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_fb95e3c9._.js → 2374f_6b436efc._.js} +1 -1
  101. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_2f0d9f6f._.js → 2374f_784d851c._.js} +1 -1
  102. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_35475cbe._.js → 2374f_976b2ded._.js} +1 -1
  103. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_7db22cde._.js → 2374f_98eba491._.js} +1 -1
  104. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_90b8e4fb._.js → 2374f_99b7b533._.js} +1 -1
  105. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_4666c827._.js → 2374f_a1a36483._.js} +1 -1
  106. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_076f03ec._.js → 2374f_b98835eb._.js} +1 -1
  107. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_b17fce11._.js → 2374f_e19eaecc._.js} +1 -1
  108. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_d8b9ce38._.js → 2374f_e3aec189._.js} +1 -1
  109. package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__7775f784._.js → [root-of-the-server]__4f176a16._.js} +2 -2
  110. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__d59f831d._.js +15 -0
  111. package/web/.next/standalone/web/.next/server/chunks/ssr/{web_645f4b90._.js → web_693f514e._.js} +2 -2
  112. package/web/.next/standalone/web/.next/server/chunks/ssr/web_a42a2651._.js +7 -0
  113. package/web/.next/standalone/web/.next/server/chunks/ssr/web_dc6ce793._.js +7 -0
  114. package/web/.next/standalone/web/.next/server/chunks/ssr/web_src_components_sessions-sidebar_tsx_92510070._.js +1 -1
  115. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  116. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  117. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  118. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  119. package/web/.next/standalone/web/.next/static/chunks/0358a0e7a40cfb93.css +1 -0
  120. package/web/.next/standalone/web/.next/static/chunks/1ecde4c0d426a635.js +1 -0
  121. package/web/.next/standalone/web/.next/static/chunks/20e0fa99c7a1c1fc.js +13 -0
  122. package/web/.next/standalone/web/.next/static/chunks/36688a049d72e8ab.js +5 -0
  123. package/web/.next/standalone/web/.next/static/chunks/95436454a7559b0d.js +7 -0
  124. package/web/.next/standalone/web/.next/static/chunks/a751ca474cc46212.js +5 -0
  125. package/web/.next/standalone/web/.next/static/static/chunks/0358a0e7a40cfb93.css +1 -0
  126. package/web/.next/standalone/web/.next/static/static/chunks/1ecde4c0d426a635.js +1 -0
  127. package/web/.next/standalone/web/.next/static/static/chunks/20e0fa99c7a1c1fc.js +13 -0
  128. package/web/.next/standalone/web/.next/static/static/chunks/36688a049d72e8ab.js +5 -0
  129. package/web/.next/standalone/web/.next/static/static/chunks/95436454a7559b0d.js +7 -0
  130. package/web/.next/standalone/web/.next/static/static/chunks/a751ca474cc46212.js +5 -0
  131. package/web/.next/standalone/web/src/components/ai-elements/complete-task-tool.tsx +126 -0
  132. package/web/.next/standalone/web/src/components/chat-interface.tsx +68 -3
  133. package/web/.next/standalone/web/src/components/sessions-sidebar.tsx +18 -1
  134. package/web/.next/standalone/web/src/lib/api.ts +12 -0
  135. package/web/.next/static/chunks/0358a0e7a40cfb93.css +1 -0
  136. package/web/.next/static/chunks/1ecde4c0d426a635.js +1 -0
  137. package/web/.next/static/chunks/20e0fa99c7a1c1fc.js +13 -0
  138. package/web/.next/static/chunks/36688a049d72e8ab.js +5 -0
  139. package/web/.next/static/chunks/95436454a7559b0d.js +7 -0
  140. package/web/.next/static/chunks/a751ca474cc46212.js +5 -0
  141. package/dist/schema-NcQknWCg.d.ts +0 -295
  142. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__bd396152._.js +0 -15
  143. package/web/.next/standalone/web/.next/server/chunks/ssr/web_9c9f0e3b._.js +0 -7
  144. package/web/.next/standalone/web/.next/server/chunks/ssr/web_d08270f7._.js +0 -7
  145. package/web/.next/standalone/web/.next/static/chunks/2868b007ce5163fc.css +0 -1
  146. package/web/.next/standalone/web/.next/static/chunks/3f295b6960943c38.js +0 -1
  147. package/web/.next/standalone/web/.next/static/chunks/631b023d37a08635.js +0 -13
  148. package/web/.next/standalone/web/.next/static/chunks/a2b4737b190d1b54.js +0 -5
  149. package/web/.next/standalone/web/.next/static/chunks/e97212fcc8221479.js +0 -5
  150. package/web/.next/standalone/web/.next/static/chunks/f6e47c8a9766ce91.js +0 -7
  151. package/web/.next/standalone/web/.next/static/static/chunks/2868b007ce5163fc.css +0 -1
  152. package/web/.next/standalone/web/.next/static/static/chunks/3f295b6960943c38.js +0 -1
  153. package/web/.next/standalone/web/.next/static/static/chunks/631b023d37a08635.js +0 -13
  154. package/web/.next/standalone/web/.next/static/static/chunks/a2b4737b190d1b54.js +0 -5
  155. package/web/.next/standalone/web/.next/static/static/chunks/e97212fcc8221479.js +0 -5
  156. package/web/.next/standalone/web/.next/static/static/chunks/f6e47c8a9766ce91.js +0 -7
  157. package/web/.next/static/chunks/2868b007ce5163fc.css +0 -1
  158. package/web/.next/static/chunks/3f295b6960943c38.js +0 -1
  159. package/web/.next/static/chunks/631b023d37a08635.js +0 -13
  160. package/web/.next/static/chunks/a2b4737b190d1b54.js +0 -5
  161. package/web/.next/static/chunks/e97212fcc8221479.js +0 -5
  162. package/web/.next/static/chunks/f6e47c8a9766ce91.js +0 -7
  163. /package/web/.next/standalone/web/.next/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_buildManifest.js +0 -0
  164. /package/web/.next/standalone/web/.next/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_clientMiddlewareManifest.json +0 -0
  165. /package/web/.next/standalone/web/.next/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_ssgManifest.js +0 -0
  166. /package/web/.next/standalone/web/.next/static/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_buildManifest.js +0 -0
  167. /package/web/.next/standalone/web/.next/static/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_clientMiddlewareManifest.json +0 -0
  168. /package/web/.next/standalone/web/.next/static/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_ssgManifest.js +0 -0
  169. /package/web/.next/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_buildManifest.js +0 -0
  170. /package/web/.next/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_clientMiddlewareManifest.json +0 -0
  171. /package/web/.next/static/{R5xiWSOp_Nqqe_js-LROo → 8zJH-RqrUQ3scBGbdaCmn}/_ssgManifest.js +0 -0
@@ -8,6 +8,191 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
+ // src/config/types.ts
12
+ import { z } from "zod";
13
+ var ToolApprovalConfigSchema, SkillMetadataSchema, TaskConfigSchema, SessionConfigSchema, VectorGatewayConfigSchema, RemoteServerConfigSchema, SparkcoderConfigSchema;
14
+ var init_types = __esm({
15
+ "src/config/types.ts"() {
16
+ "use strict";
17
+ ToolApprovalConfigSchema = z.object({
18
+ bash: z.boolean().optional().default(true),
19
+ write_file: z.boolean().optional().default(false),
20
+ read_file: z.boolean().optional().default(false),
21
+ load_skill: z.boolean().optional().default(false),
22
+ todo: z.boolean().optional().default(false)
23
+ });
24
+ SkillMetadataSchema = z.object({
25
+ name: z.string(),
26
+ description: z.string(),
27
+ // Whether to always inject this skill into context (vs on-demand loading)
28
+ alwaysApply: z.boolean().optional().default(false),
29
+ // Glob patterns - auto-inject when working with matching files
30
+ globs: z.array(z.string()).optional().default([])
31
+ });
32
+ TaskConfigSchema = z.object({
33
+ enabled: z.boolean(),
34
+ outputSchema: z.record(z.string(), z.unknown()),
35
+ webhookUrl: z.string().url().optional(),
36
+ maxIterations: z.number().optional(),
37
+ status: z.enum(["running", "completed", "failed"]),
38
+ result: z.unknown().optional(),
39
+ error: z.string().optional(),
40
+ iterations: z.number().optional()
41
+ });
42
+ SessionConfigSchema = z.object({
43
+ toolApprovals: z.record(z.string(), z.boolean()).optional(),
44
+ approvalWebhook: z.string().url().optional(),
45
+ skillsDirectory: z.string().optional(),
46
+ maxContextChars: z.number().optional().default(2e5),
47
+ task: TaskConfigSchema.optional()
48
+ });
49
+ VectorGatewayConfigSchema = z.object({
50
+ // Redis cluster nodes URL for Vector Gateway (or use REDIS_CLUSTER_NODES env var)
51
+ redisUrl: z.string().optional(),
52
+ // HTTP URL for database operations (or use VECTOR_HTTP_URL env var)
53
+ httpUrl: z.string().optional(),
54
+ // Embedding model to use (default: text-embedding-3-small)
55
+ embeddingModel: z.string().default("gemini-embedding-001"),
56
+ // Custom namespace override (auto-generated from git remote if not set)
57
+ namespace: z.string().optional(),
58
+ // File patterns to include in indexing
59
+ include: z.array(z.string()).optional().default([
60
+ "**/*.ts",
61
+ "**/*.tsx",
62
+ "**/*.js",
63
+ "**/*.jsx",
64
+ "**/*.py",
65
+ "**/*.go",
66
+ "**/*.rs",
67
+ "**/*.java",
68
+ "**/*.md",
69
+ "**/*.mdx",
70
+ "**/*.txt"
71
+ ]),
72
+ // File patterns to exclude from indexing
73
+ exclude: z.array(z.string()).optional().default([
74
+ "**/node_modules/**",
75
+ "**/dist/**",
76
+ "**/build/**",
77
+ "**/.git/**",
78
+ "**/.next/**",
79
+ "**/*.min.js",
80
+ "**/*.bundle.js",
81
+ "**/pnpm-lock.yaml",
82
+ "**/package-lock.json",
83
+ "**/yarn.lock",
84
+ "**/.test-workspace/**",
85
+ "**/.semantic-test-workspace/**",
86
+ "**/.semantic-integration-test/**"
87
+ ])
88
+ }).optional();
89
+ RemoteServerConfigSchema = z.object({
90
+ // URL of the remote server (e.g., https://agent.sparkecode.com)
91
+ url: z.string().url().optional(),
92
+ // Auth key for the remote server (auto-generated on first use if not set)
93
+ // Can also be set via SPARKECODER_AUTH_KEY env var
94
+ authKey: z.string().optional()
95
+ }).optional();
96
+ SparkcoderConfigSchema = z.object({
97
+ // Default model to use (Vercel AI Gateway format)
98
+ defaultModel: z.string().default("anthropic/claude-opus-4-6"),
99
+ // Working directory for file operations
100
+ workingDirectory: z.string().optional(),
101
+ // Tool approval settings
102
+ toolApprovals: ToolApprovalConfigSchema.optional().default({}),
103
+ // Approval webhook URL (called when approval is needed)
104
+ approvalWebhook: z.string().url().optional(),
105
+ // Skills configuration
106
+ skills: z.object({
107
+ // Directory containing skill files
108
+ directory: z.string().optional().default("./skills"),
109
+ // Additional skill directories to include
110
+ additionalDirectories: z.array(z.string()).optional().default([])
111
+ }).optional().default({}),
112
+ // Context management
113
+ context: z.object({
114
+ // Maximum context size before summarization (in characters)
115
+ maxChars: z.number().optional().default(2e5),
116
+ // Enable automatic summarization
117
+ autoSummarize: z.boolean().optional().default(true),
118
+ // Number of recent messages to keep after summarization
119
+ keepRecentMessages: z.number().optional().default(10)
120
+ }).optional().default({}),
121
+ // Server configuration
122
+ server: z.object({
123
+ port: z.number().default(3141),
124
+ host: z.string().default("127.0.0.1"),
125
+ // Public URL for web UI to connect to API (for Docker/remote access)
126
+ // If not set, defaults to http://{host}:{port}
127
+ publicUrl: z.string().url().optional()
128
+ }).default({ port: 3141, host: "127.0.0.1" }),
129
+ // Database path (used for local SQLite - ignored if remoteServer is configured)
130
+ databasePath: z.string().optional().default("./sparkecoder.db"),
131
+ // Remote server configuration (for centralized storage)
132
+ // If configured, uses remote MongoDB instead of local SQLite
133
+ remoteServer: RemoteServerConfigSchema,
134
+ // Vector Gateway configuration for semantic search
135
+ vectorGateway: VectorGatewayConfigSchema
136
+ });
137
+ }
138
+ });
139
+
140
+ // src/config/index.ts
141
+ import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
142
+ import { resolve, dirname, join } from "path";
143
+ import { homedir, platform } from "os";
144
+ function getAppDataDirectory() {
145
+ const appName = "sparkecoder";
146
+ switch (platform()) {
147
+ case "darwin":
148
+ return join(homedir(), "Library", "Application Support", appName);
149
+ case "win32":
150
+ return join(process.env.APPDATA || join(homedir(), "AppData", "Roaming"), appName);
151
+ default:
152
+ return join(process.env.XDG_DATA_HOME || join(homedir(), ".local", "share"), appName);
153
+ }
154
+ }
155
+ function getConfig() {
156
+ if (!cachedConfig) {
157
+ throw new Error("Config not loaded. Call loadConfig first.");
158
+ }
159
+ return cachedConfig;
160
+ }
161
+ function requiresApproval(toolName, sessionConfig) {
162
+ const config = getConfig();
163
+ if (sessionConfig?.toolApprovals?.["*"] !== void 0) {
164
+ return sessionConfig.toolApprovals["*"];
165
+ }
166
+ if (sessionConfig?.toolApprovals?.[toolName] !== void 0) {
167
+ return sessionConfig.toolApprovals[toolName];
168
+ }
169
+ const globalApprovals = config.toolApprovals;
170
+ if (globalApprovals[toolName] !== void 0) {
171
+ return globalApprovals[toolName];
172
+ }
173
+ if (toolName === "bash") {
174
+ return true;
175
+ }
176
+ return false;
177
+ }
178
+ var cachedConfig, PROVIDER_ENV_MAP, SUPPORTED_PROVIDERS;
179
+ var init_config = __esm({
180
+ "src/config/index.ts"() {
181
+ "use strict";
182
+ init_types();
183
+ init_types();
184
+ cachedConfig = null;
185
+ PROVIDER_ENV_MAP = {
186
+ anthropic: "ANTHROPIC_API_KEY",
187
+ openai: "OPENAI_API_KEY",
188
+ google: "GOOGLE_GENERATIVE_AI_API_KEY",
189
+ xai: "XAI_API_KEY",
190
+ "ai-gateway": "AI_GATEWAY_API_KEY"
191
+ };
192
+ SUPPORTED_PROVIDERS = Object.keys(PROVIDER_ENV_MAP);
193
+ }
194
+ });
195
+
11
196
  // src/db/remote.ts
12
197
  function parseDates(obj) {
13
198
  if (obj === null || obj === void 0) return obj;
@@ -298,177 +483,6 @@ var init_db = __esm({
298
483
  }
299
484
  });
300
485
 
301
- // src/config/types.ts
302
- import { z } from "zod";
303
- var ToolApprovalConfigSchema, SkillMetadataSchema, SessionConfigSchema, VectorGatewayConfigSchema, RemoteServerConfigSchema, SparkcoderConfigSchema;
304
- var init_types = __esm({
305
- "src/config/types.ts"() {
306
- "use strict";
307
- ToolApprovalConfigSchema = z.object({
308
- bash: z.boolean().optional().default(true),
309
- write_file: z.boolean().optional().default(false),
310
- read_file: z.boolean().optional().default(false),
311
- load_skill: z.boolean().optional().default(false),
312
- todo: z.boolean().optional().default(false)
313
- });
314
- SkillMetadataSchema = z.object({
315
- name: z.string(),
316
- description: z.string(),
317
- // Whether to always inject this skill into context (vs on-demand loading)
318
- alwaysApply: z.boolean().optional().default(false),
319
- // Glob patterns - auto-inject when working with matching files
320
- globs: z.array(z.string()).optional().default([])
321
- });
322
- SessionConfigSchema = z.object({
323
- toolApprovals: z.record(z.string(), z.boolean()).optional(),
324
- approvalWebhook: z.string().url().optional(),
325
- skillsDirectory: z.string().optional(),
326
- maxContextChars: z.number().optional().default(2e5)
327
- });
328
- VectorGatewayConfigSchema = z.object({
329
- // Redis cluster nodes URL for Vector Gateway (or use REDIS_CLUSTER_NODES env var)
330
- redisUrl: z.string().optional(),
331
- // HTTP URL for database operations (or use VECTOR_HTTP_URL env var)
332
- httpUrl: z.string().optional(),
333
- // Embedding model to use (default: text-embedding-3-small)
334
- embeddingModel: z.string().default("gemini-embedding-001"),
335
- // Custom namespace override (auto-generated from git remote if not set)
336
- namespace: z.string().optional(),
337
- // File patterns to include in indexing
338
- include: z.array(z.string()).optional().default([
339
- "**/*.ts",
340
- "**/*.tsx",
341
- "**/*.js",
342
- "**/*.jsx",
343
- "**/*.py",
344
- "**/*.go",
345
- "**/*.rs",
346
- "**/*.java",
347
- "**/*.md",
348
- "**/*.mdx",
349
- "**/*.txt"
350
- ]),
351
- // File patterns to exclude from indexing
352
- exclude: z.array(z.string()).optional().default([
353
- "**/node_modules/**",
354
- "**/dist/**",
355
- "**/build/**",
356
- "**/.git/**",
357
- "**/.next/**",
358
- "**/*.min.js",
359
- "**/*.bundle.js",
360
- "**/pnpm-lock.yaml",
361
- "**/package-lock.json",
362
- "**/yarn.lock",
363
- "**/.test-workspace/**",
364
- "**/.semantic-test-workspace/**",
365
- "**/.semantic-integration-test/**"
366
- ])
367
- }).optional();
368
- RemoteServerConfigSchema = z.object({
369
- // URL of the remote server (e.g., https://agent.sparkecode.com)
370
- url: z.string().url().optional(),
371
- // Auth key for the remote server (auto-generated on first use if not set)
372
- // Can also be set via SPARKECODER_AUTH_KEY env var
373
- authKey: z.string().optional()
374
- }).optional();
375
- SparkcoderConfigSchema = z.object({
376
- // Default model to use (Vercel AI Gateway format)
377
- defaultModel: z.string().default("anthropic/claude-opus-4-6"),
378
- // Working directory for file operations
379
- workingDirectory: z.string().optional(),
380
- // Tool approval settings
381
- toolApprovals: ToolApprovalConfigSchema.optional().default({}),
382
- // Approval webhook URL (called when approval is needed)
383
- approvalWebhook: z.string().url().optional(),
384
- // Skills configuration
385
- skills: z.object({
386
- // Directory containing skill files
387
- directory: z.string().optional().default("./skills"),
388
- // Additional skill directories to include
389
- additionalDirectories: z.array(z.string()).optional().default([])
390
- }).optional().default({}),
391
- // Context management
392
- context: z.object({
393
- // Maximum context size before summarization (in characters)
394
- maxChars: z.number().optional().default(2e5),
395
- // Enable automatic summarization
396
- autoSummarize: z.boolean().optional().default(true),
397
- // Number of recent messages to keep after summarization
398
- keepRecentMessages: z.number().optional().default(10)
399
- }).optional().default({}),
400
- // Server configuration
401
- server: z.object({
402
- port: z.number().default(3141),
403
- host: z.string().default("127.0.0.1"),
404
- // Public URL for web UI to connect to API (for Docker/remote access)
405
- // If not set, defaults to http://{host}:{port}
406
- publicUrl: z.string().url().optional()
407
- }).default({ port: 3141, host: "127.0.0.1" }),
408
- // Database path (used for local SQLite - ignored if remoteServer is configured)
409
- databasePath: z.string().optional().default("./sparkecoder.db"),
410
- // Remote server configuration (for centralized storage)
411
- // If configured, uses remote MongoDB instead of local SQLite
412
- remoteServer: RemoteServerConfigSchema,
413
- // Vector Gateway configuration for semantic search
414
- vectorGateway: VectorGatewayConfigSchema
415
- });
416
- }
417
- });
418
-
419
- // src/config/index.ts
420
- import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
421
- import { resolve, dirname, join } from "path";
422
- import { homedir, platform } from "os";
423
- function getAppDataDirectory() {
424
- const appName = "sparkecoder";
425
- switch (platform()) {
426
- case "darwin":
427
- return join(homedir(), "Library", "Application Support", appName);
428
- case "win32":
429
- return join(process.env.APPDATA || join(homedir(), "AppData", "Roaming"), appName);
430
- default:
431
- return join(process.env.XDG_DATA_HOME || join(homedir(), ".local", "share"), appName);
432
- }
433
- }
434
- function getConfig() {
435
- if (!cachedConfig) {
436
- throw new Error("Config not loaded. Call loadConfig first.");
437
- }
438
- return cachedConfig;
439
- }
440
- function requiresApproval(toolName, sessionConfig) {
441
- const config = getConfig();
442
- if (sessionConfig?.toolApprovals?.[toolName] !== void 0) {
443
- return sessionConfig.toolApprovals[toolName];
444
- }
445
- const globalApprovals = config.toolApprovals;
446
- if (globalApprovals[toolName] !== void 0) {
447
- return globalApprovals[toolName];
448
- }
449
- if (toolName === "bash") {
450
- return true;
451
- }
452
- return false;
453
- }
454
- var cachedConfig, PROVIDER_ENV_MAP, SUPPORTED_PROVIDERS;
455
- var init_config = __esm({
456
- "src/config/index.ts"() {
457
- "use strict";
458
- init_types();
459
- init_types();
460
- cachedConfig = null;
461
- PROVIDER_ENV_MAP = {
462
- anthropic: "ANTHROPIC_API_KEY",
463
- openai: "OPENAI_API_KEY",
464
- google: "GOOGLE_GENERATIVE_AI_API_KEY",
465
- xai: "XAI_API_KEY",
466
- "ai-gateway": "AI_GATEWAY_API_KEY"
467
- };
468
- SUPPORTED_PROVIDERS = Object.keys(PROVIDER_ENV_MAP);
469
- }
470
- });
471
-
472
486
  // src/skills/index.ts
473
487
  var skills_exports = {};
474
488
  __export(skills_exports, {
@@ -1210,18 +1224,176 @@ var init_semantic_search = __esm({
1210
1224
  import {
1211
1225
  streamText as streamText2,
1212
1226
  generateText as generateText3,
1213
- tool as tool11,
1227
+ tool as tool12,
1214
1228
  stepCountIs as stepCountIs2
1215
1229
  } from "ai";
1216
1230
 
1217
1231
  // src/agent/model.ts
1218
1232
  import { gateway } from "@ai-sdk/gateway";
1233
+
1234
+ // src/agent/remote-model.ts
1235
+ function serializePrompt(prompt) {
1236
+ return prompt.map((msg) => {
1237
+ if (!Array.isArray(msg.content)) return msg;
1238
+ return {
1239
+ ...msg,
1240
+ content: msg.content.map((part) => {
1241
+ if (part.type === "file" && part.data instanceof Uint8Array) {
1242
+ return {
1243
+ ...part,
1244
+ data: Buffer.from(part.data).toString("base64"),
1245
+ _base64: true
1246
+ };
1247
+ }
1248
+ return part;
1249
+ })
1250
+ };
1251
+ });
1252
+ }
1253
+ function deserializeValue(value) {
1254
+ if (value && typeof value === "object") {
1255
+ if (value.__uint8array && typeof value.data === "string") {
1256
+ return Buffer.from(value.data, "base64");
1257
+ }
1258
+ if (Array.isArray(value)) {
1259
+ return value.map(deserializeValue);
1260
+ }
1261
+ const result = {};
1262
+ for (const [k, v] of Object.entries(value)) {
1263
+ result[k] = deserializeValue(v);
1264
+ }
1265
+ return result;
1266
+ }
1267
+ return value;
1268
+ }
1269
+ function prepareOptions(options) {
1270
+ const { abortSignal, ...rest } = options;
1271
+ return {
1272
+ ...rest,
1273
+ prompt: serializePrompt(options.prompt)
1274
+ };
1275
+ }
1276
+ function createRemoteModel(modelId, config) {
1277
+ const baseUrl = config.url.replace(/\/$/, "");
1278
+ const headers = {
1279
+ "Content-Type": "application/json",
1280
+ "Authorization": `Bearer ${config.authKey}`
1281
+ };
1282
+ return {
1283
+ specificationVersion: "v3",
1284
+ provider: "remote-proxy",
1285
+ modelId,
1286
+ supportedUrls: {},
1287
+ async doGenerate(options) {
1288
+ const res = await fetch(`${baseUrl}/inference/generate`, {
1289
+ method: "POST",
1290
+ headers,
1291
+ body: JSON.stringify({
1292
+ modelId,
1293
+ options: prepareOptions(options)
1294
+ }),
1295
+ signal: options.abortSignal
1296
+ });
1297
+ if (!res.ok) {
1298
+ const err = await res.json().catch(() => ({}));
1299
+ throw new Error(
1300
+ `Remote inference failed (${res.status}): ${err.error || res.statusText}`
1301
+ );
1302
+ }
1303
+ const result = await res.json();
1304
+ return deserializeValue(result);
1305
+ },
1306
+ async doStream(options) {
1307
+ const res = await fetch(`${baseUrl}/inference/stream`, {
1308
+ method: "POST",
1309
+ headers,
1310
+ body: JSON.stringify({
1311
+ modelId,
1312
+ options: prepareOptions(options)
1313
+ }),
1314
+ signal: options.abortSignal
1315
+ });
1316
+ if (!res.ok) {
1317
+ const err = await res.json().catch(() => ({}));
1318
+ throw new Error(
1319
+ `Remote inference failed (${res.status}): ${err.error || res.statusText}`
1320
+ );
1321
+ }
1322
+ const reader = res.body.getReader();
1323
+ const decoder = new TextDecoder();
1324
+ let buffer = "";
1325
+ const stream = new ReadableStream({
1326
+ async pull(controller) {
1327
+ while (true) {
1328
+ const { done, value } = await reader.read();
1329
+ if (done) {
1330
+ if (buffer.trim()) {
1331
+ try {
1332
+ const parsed = deserializeValue(JSON.parse(buffer.trim()));
1333
+ if (parsed.type === "error") {
1334
+ controller.error(new Error(parsed.error));
1335
+ } else {
1336
+ controller.enqueue(parsed);
1337
+ }
1338
+ } catch {
1339
+ }
1340
+ }
1341
+ controller.close();
1342
+ return;
1343
+ }
1344
+ buffer += decoder.decode(value, { stream: true });
1345
+ const lines = buffer.split("\n");
1346
+ buffer = lines.pop() || "";
1347
+ for (const line of lines) {
1348
+ if (!line.trim()) continue;
1349
+ try {
1350
+ const parsed = deserializeValue(JSON.parse(line));
1351
+ if (parsed.type === "error") {
1352
+ controller.error(new Error(parsed.error));
1353
+ return;
1354
+ }
1355
+ controller.enqueue(parsed);
1356
+ } catch {
1357
+ }
1358
+ }
1359
+ }
1360
+ },
1361
+ cancel() {
1362
+ reader.cancel();
1363
+ }
1364
+ });
1365
+ const responseHeaders = {};
1366
+ res.headers.forEach((v, k) => {
1367
+ if (k.startsWith("x-upstream-")) {
1368
+ responseHeaders[k.replace("x-upstream-", "")] = v;
1369
+ }
1370
+ });
1371
+ return {
1372
+ stream,
1373
+ response: Object.keys(responseHeaders).length > 0 ? { headers: responseHeaders } : void 0
1374
+ };
1375
+ }
1376
+ };
1377
+ }
1378
+
1379
+ // src/agent/model.ts
1380
+ init_config();
1219
1381
  var ANTHROPIC_PREFIX = "anthropic/";
1220
1382
  function isAnthropicModel(modelId) {
1221
1383
  const normalized = modelId.trim().toLowerCase();
1222
1384
  return normalized.startsWith(ANTHROPIC_PREFIX) || normalized.startsWith("claude-");
1223
1385
  }
1224
1386
  function resolveModel(modelId) {
1387
+ try {
1388
+ const config = getConfig();
1389
+ if (config.resolvedRemoteServer.isConfigured) {
1390
+ return createRemoteModel(modelId.trim(), {
1391
+ url: config.resolvedRemoteServer.url,
1392
+ authKey: config.resolvedRemoteServer.authKey
1393
+ });
1394
+ }
1395
+ } catch {
1396
+ }
1225
1397
  return gateway(modelId.trim());
1226
1398
  }
1227
1399
  var SUBAGENT_MODELS = {
@@ -1233,7 +1405,7 @@ var SUBAGENT_MODELS = {
1233
1405
  // src/agent/index.ts
1234
1406
  init_db();
1235
1407
  init_config();
1236
- import { z as z12 } from "zod";
1408
+ import { z as z13 } from "zod";
1237
1409
  import { nanoid as nanoid3 } from "nanoid";
1238
1410
 
1239
1411
  // src/tools/bash.ts
@@ -4359,6 +4531,59 @@ Context: ${context}` : query;
4359
4531
 
4360
4532
  // src/tools/index.ts
4361
4533
  init_semantic_search();
4534
+
4535
+ // src/tools/task.ts
4536
+ import { tool as tool11 } from "ai";
4537
+ import { z as z12 } from "zod";
4538
+ import Ajv from "ajv";
4539
+ var ajv = new Ajv({ allErrors: true });
4540
+ function createCompleteTaskTool(options) {
4541
+ const validate = ajv.compile(options.outputSchema);
4542
+ return tool11({
4543
+ description: "Call this tool when you have completed the task. Pass the result as a JSON object matching the required output schema. If the result does not match the schema, you will receive validation errors and should fix and retry.",
4544
+ inputSchema: z12.object({
4545
+ result: z12.record(z12.string(), z12.unknown()).describe("The task result as a JSON object matching the output schema")
4546
+ }),
4547
+ execute: async (input) => {
4548
+ const valid = validate(input.result);
4549
+ if (!valid) {
4550
+ const errors = validate.errors?.map((e) => ({
4551
+ path: e.instancePath || "/",
4552
+ message: e.message,
4553
+ params: e.params
4554
+ }));
4555
+ return {
4556
+ status: "validation_error",
4557
+ message: "The result does not match the required output schema. Fix the errors and call complete_task again.",
4558
+ errors,
4559
+ expectedSchema: options.outputSchema
4560
+ };
4561
+ }
4562
+ options.onComplete({ status: "completed", result: input.result });
4563
+ return {
4564
+ status: "completed",
4565
+ message: "Task completed successfully."
4566
+ };
4567
+ }
4568
+ });
4569
+ }
4570
+ function createTaskFailedTool(options) {
4571
+ return tool11({
4572
+ description: "Call this tool if you are unable to complete the task. Provide a clear reason explaining why the task cannot be completed.",
4573
+ inputSchema: z12.object({
4574
+ reason: z12.string().describe("Explanation of why the task cannot be completed")
4575
+ }),
4576
+ execute: async (input) => {
4577
+ options.onComplete({ status: "failed", error: input.reason });
4578
+ return {
4579
+ status: "failed",
4580
+ message: `Task marked as failed: ${input.reason}`
4581
+ };
4582
+ }
4583
+ });
4584
+ }
4585
+
4586
+ // src/tools/index.ts
4362
4587
  init_semantic();
4363
4588
  init_semantic_search();
4364
4589
  async function createTools(options) {
@@ -4410,6 +4635,10 @@ async function createTools(options) {
4410
4635
  } catch {
4411
4636
  }
4412
4637
  }
4638
+ if (options.taskTools) {
4639
+ tools.complete_task = createCompleteTaskTool(options.taskTools);
4640
+ tools.task_failed = createTaskFailedTool(options.taskTools);
4641
+ }
4413
4642
  return tools;
4414
4643
  }
4415
4644
 
@@ -4727,6 +4956,30 @@ function formatTodosForContext(todos) {
4727
4956
  }
4728
4957
  return lines.join("\n");
4729
4958
  }
4959
+ function buildTaskPromptAddendum(outputSchema) {
4960
+ return `
4961
+ ## Task Mode
4962
+
4963
+ You are running in **task mode**. You have been given a specific task to complete autonomously.
4964
+
4965
+ ### Rules
4966
+ 1. Work independently \u2014 no human will approve tool calls. All tools run without approval.
4967
+ 2. Keep working until the task is fully complete.
4968
+ 3. When done, call the \`complete_task\` tool with a JSON result matching the output schema below.
4969
+ 4. If you determine the task is impossible or encounter an unrecoverable error, call the \`task_failed\` tool with a clear reason.
4970
+ 5. Do NOT stop without calling one of these two tools.
4971
+
4972
+ ### Output Schema
4973
+ The \`complete_task\` tool expects a \`result\` object matching this JSON Schema:
4974
+ \`\`\`json
4975
+ ${JSON.stringify(outputSchema, null, 2)}
4976
+ \`\`\`
4977
+
4978
+ ### Completion Tools
4979
+ - **\`complete_task({ result: ... })\`** \u2014 Call when the task is done. The result is validated against the schema above. If validation fails you will get errors back \u2014 fix and retry.
4980
+ - **\`task_failed({ reason: "..." })\`** \u2014 Call only if the task truly cannot be completed.
4981
+ `;
4982
+ }
4730
4983
  function createSummaryPrompt(conversationHistory) {
4731
4984
  return `Please provide a concise summary of the following conversation history. Focus on:
4732
4985
  1. The main task or goal being worked on
@@ -4988,6 +5241,25 @@ ${this.summary}`
4988
5241
  }
4989
5242
  };
4990
5243
 
5244
+ // src/utils/webhook.ts
5245
+ async function sendWebhook(url, event) {
5246
+ try {
5247
+ const controller = new AbortController();
5248
+ const timeout = setTimeout(() => controller.abort(), 5e3);
5249
+ await fetch(url, {
5250
+ method: "POST",
5251
+ headers: {
5252
+ "Content-Type": "application/json",
5253
+ "X-SparkECoder-Event": event.type
5254
+ },
5255
+ body: JSON.stringify(event),
5256
+ signal: controller.signal
5257
+ });
5258
+ clearTimeout(timeout);
5259
+ } catch {
5260
+ }
5261
+ }
5262
+
4991
5263
  // src/agent/index.ts
4992
5264
  var approvalResolvers = /* @__PURE__ */ new Map();
4993
5265
  var Agent = class _Agent {
@@ -5207,6 +5479,145 @@ ${prompt}` });
5207
5479
  steps: result.steps
5208
5480
  };
5209
5481
  }
5482
+ /**
5483
+ * Run the agent in task mode — loops autonomously until the agent calls
5484
+ * complete_task or task_failed (or hits maxIterations).
5485
+ * All tools run without approval. Webhook events are fired throughout.
5486
+ */
5487
+ async runTask(options) {
5488
+ const config = getConfig();
5489
+ const maxIterations = options.taskConfig.maxIterations ?? 50;
5490
+ const webhookUrl = options.taskConfig.webhookUrl;
5491
+ const fireWebhook = (type, data) => {
5492
+ if (!webhookUrl) return;
5493
+ sendWebhook(webhookUrl, {
5494
+ type,
5495
+ taskId: this.session.id,
5496
+ sessionId: this.session.id,
5497
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5498
+ data
5499
+ });
5500
+ };
5501
+ const completion = { signal: null };
5502
+ const onComplete = (signal) => {
5503
+ completion.signal = signal;
5504
+ };
5505
+ const taskTools = await createTools({
5506
+ sessionId: this.session.id,
5507
+ workingDirectory: this.session.workingDirectory,
5508
+ skillsDirectories: config.resolvedSkillsDirectories,
5509
+ onBashProgress: options.onToolProgress ? (progress) => options.onToolProgress({ toolName: "bash", data: progress }) : void 0,
5510
+ onWriteFileProgress: options.onToolProgress ? (progress) => options.onToolProgress({ toolName: "write_file", data: progress }) : void 0,
5511
+ onSearchProgress: options.onToolProgress ? (progress) => options.onToolProgress({ toolName: "explore_agent", data: progress }) : void 0,
5512
+ taskTools: {
5513
+ outputSchema: options.taskConfig.outputSchema,
5514
+ onComplete
5515
+ }
5516
+ });
5517
+ const baseSystemPrompt = await buildSystemPrompt({
5518
+ workingDirectory: this.session.workingDirectory,
5519
+ skillsDirectories: config.resolvedSkillsDirectories,
5520
+ sessionId: this.session.id,
5521
+ discoveredSkills: config.discoveredSkills,
5522
+ activeFiles: []
5523
+ });
5524
+ const taskAddendum = buildTaskPromptAddendum(options.taskConfig.outputSchema);
5525
+ const systemPrompt = `${baseSystemPrompt}
5526
+
5527
+ ${taskAddendum}`;
5528
+ fireWebhook("task.started", { prompt: options.prompt });
5529
+ this.context.addUserMessage(options.prompt);
5530
+ let iteration = 0;
5531
+ while (iteration < maxIterations) {
5532
+ iteration++;
5533
+ if (options.abortSignal?.aborted) {
5534
+ const cancelError = "Task was cancelled";
5535
+ fireWebhook("task.failed", { status: "failed", error: cancelError, iterations: iteration });
5536
+ return { status: "failed", error: cancelError, iterations: iteration };
5537
+ }
5538
+ const messages = await this.context.getMessages();
5539
+ const useAnthropic = isAnthropicModel(this.session.model);
5540
+ const result = await generateText3({
5541
+ model: resolveModel(this.session.model),
5542
+ system: systemPrompt,
5543
+ messages,
5544
+ tools: taskTools,
5545
+ stopWhen: stepCountIs2(500),
5546
+ abortSignal: options.abortSignal,
5547
+ providerOptions: useAnthropic ? {
5548
+ anthropic: {
5549
+ thinking: { type: "enabled", budgetTokens: 1e4 }
5550
+ }
5551
+ } : void 0,
5552
+ onStepFinish: (step) => {
5553
+ options.onStepFinish?.(step);
5554
+ fireWebhook("task.step_finished", { iteration, text: step.text });
5555
+ }
5556
+ });
5557
+ const responseMessages = result.response.messages;
5558
+ this.context.addResponseMessages(responseMessages);
5559
+ if (result.text) {
5560
+ options.onText?.(result.text);
5561
+ fireWebhook("task.message", { iteration, text: result.text });
5562
+ }
5563
+ for (const step of result.steps) {
5564
+ if (step.toolCalls) {
5565
+ for (const tc of step.toolCalls) {
5566
+ options.onToolCall?.({ toolCallId: tc.toolCallId, toolName: tc.toolName, input: tc.args });
5567
+ fireWebhook("task.tool_call", { iteration, toolName: tc.toolName, toolCallId: tc.toolCallId, input: tc.args });
5568
+ }
5569
+ }
5570
+ if (step.toolResults) {
5571
+ for (const tr of step.toolResults) {
5572
+ options.onToolResult?.({ toolCallId: tr.toolCallId, toolName: tr.toolName, output: tr.result });
5573
+ fireWebhook("task.tool_result", { iteration, toolName: tr.toolName, toolCallId: tr.toolCallId, output: tr.result });
5574
+ }
5575
+ }
5576
+ }
5577
+ if (completion.signal) {
5578
+ const sig = completion.signal;
5579
+ const finalStatus = sig.status;
5580
+ const eventType = finalStatus === "completed" ? "task.completed" : "task.failed";
5581
+ fireWebhook(eventType, {
5582
+ status: finalStatus,
5583
+ result: sig.result,
5584
+ error: sig.error,
5585
+ iterations: iteration
5586
+ });
5587
+ const updatedTask2 = {
5588
+ ...options.taskConfig,
5589
+ status: finalStatus,
5590
+ result: sig.result,
5591
+ error: sig.error,
5592
+ iterations: iteration
5593
+ };
5594
+ await sessionQueries.update(this.session.id, {
5595
+ config: { ...this.session.config, task: updatedTask2 }
5596
+ });
5597
+ return {
5598
+ status: finalStatus,
5599
+ result: sig.result,
5600
+ error: sig.error,
5601
+ iterations: iteration
5602
+ };
5603
+ }
5604
+ this.context.addUserMessage(
5605
+ "Continue working on the task. When done, call `complete_task` with the result. If you cannot complete it, call `task_failed` with a reason."
5606
+ );
5607
+ }
5608
+ const timeoutError = `Task did not complete within ${maxIterations} iterations`;
5609
+ fireWebhook("task.failed", { status: "failed", error: timeoutError, iterations: iteration });
5610
+ const updatedTask = {
5611
+ ...options.taskConfig,
5612
+ status: "failed",
5613
+ error: timeoutError,
5614
+ iterations: iteration
5615
+ };
5616
+ await sessionQueries.update(this.session.id, {
5617
+ config: { ...this.session.config, task: updatedTask }
5618
+ });
5619
+ return { status: "failed", error: timeoutError, iterations: iteration };
5620
+ }
5210
5621
  /**
5211
5622
  * Wrap tools to add approval checking
5212
5623
  */
@@ -5220,9 +5631,9 @@ ${prompt}` });
5220
5631
  wrappedTools[name] = originalTool;
5221
5632
  continue;
5222
5633
  }
5223
- wrappedTools[name] = tool11({
5634
+ wrappedTools[name] = tool12({
5224
5635
  description: originalTool.description || "",
5225
- inputSchema: originalTool.inputSchema || z12.object({}),
5636
+ inputSchema: originalTool.inputSchema || z13.object({}),
5226
5637
  execute: async (input, toolOptions) => {
5227
5638
  const toolCallId = toolOptions.toolCallId || nanoid3();
5228
5639
  const execution = toolExecutionQueries.create({
@@ -5333,6 +5744,7 @@ ${prompt}` });
5333
5744
  export {
5334
5745
  Agent,
5335
5746
  ContextManager,
5336
- buildSystemPrompt
5747
+ buildSystemPrompt,
5748
+ buildTaskPromptAddendum
5337
5749
  };
5338
5750
  //# sourceMappingURL=index.js.map