godot-daedalus_backend 1.0.0

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 (67) hide show
  1. package/README.md +101 -0
  2. package/bin/godot-daedalus-backend.js +4 -0
  3. package/bin/godot-daedalus-mcp.js +4 -0
  4. package/bin/godot-daedalus-terminal-mcp.js +4 -0
  5. package/bin/run-tsx-entry.js +26 -0
  6. package/package.json +54 -0
  7. package/scripts/deepseek-tokenizer-server.py +54 -0
  8. package/src/app-paths.ts +36 -0
  9. package/src/main.ts +21 -0
  10. package/src/mcp/content-length-protocol.ts +68 -0
  11. package/src/mcp/custom-mcp-config-store.ts +397 -0
  12. package/src/mcp/godot-diagnostics-bridge.ts +1298 -0
  13. package/src/mcp/godot-editor-bridge.ts +307 -0
  14. package/src/mcp/godot-mcp-server.ts +3484 -0
  15. package/src/mcp/godot-paths.ts +151 -0
  16. package/src/mcp/godot-project-settings.ts +233 -0
  17. package/src/mcp/godot-tool-registration.ts +46 -0
  18. package/src/mcp/mcp-config.ts +48 -0
  19. package/src/mcp/mcp-host.ts +393 -0
  20. package/src/mcp/mcp-session.ts +81 -0
  21. package/src/mcp/terminal-mcp-server.ts +576 -0
  22. package/src/mcp/tscn-tools.ts +302 -0
  23. package/src/mcp/types.ts +12 -0
  24. package/src/ping-client.ts +24 -0
  25. package/src/prompts/registry.ts +97 -0
  26. package/src/prompts/templates/backend-helper.md +25 -0
  27. package/src/prompts/templates/gdscript-reviewer.md +19 -0
  28. package/src/prompts/templates/godot-assistant.md +225 -0
  29. package/src/prompts/templates/scene-architect.md +15 -0
  30. package/src/prompts/templates/session-compressor.md +33 -0
  31. package/src/protocol/schema.ts +486 -0
  32. package/src/protocol/types.ts +77 -0
  33. package/src/providers/deepseek-agent.ts +1014 -0
  34. package/src/providers/deepseek-client.ts +114 -0
  35. package/src/providers/deepseek-dsml-tools.ts +90 -0
  36. package/src/providers/deepseek-loose-tools.ts +450 -0
  37. package/src/providers/provider-config-store.ts +164 -0
  38. package/src/server/client-session.ts +93 -0
  39. package/src/server/request-dispatcher.ts +74 -0
  40. package/src/server/response-helpers.ts +33 -0
  41. package/src/server/send-json.ts +8 -0
  42. package/src/server/websocket-server.ts +3997 -0
  43. package/src/session/session-compressor.ts +68 -0
  44. package/src/session/session-store.ts +669 -0
  45. package/src/skills/registry.ts +180 -0
  46. package/src/skills/templates/backend-helper.md +12 -0
  47. package/src/skills/templates/file-creator.md +14 -0
  48. package/src/skills/templates/gdscript-review.md +12 -0
  49. package/src/skills/templates/godot-project-init.md +29 -0
  50. package/src/skills/templates/scene-builder.md +12 -0
  51. package/src/tokens/deepseek-tokenizer-counter.ts +233 -0
  52. package/src/tokens/model-profiles.ts +38 -0
  53. package/src/tokens/token-counter-factory.ts +52 -0
  54. package/src/tokens/token-counter.ts +22 -0
  55. package/src/tools/approval-gateway.ts +111 -0
  56. package/src/tools/llm-tools.ts +1415 -0
  57. package/src/tools/tool-dispatcher.ts +147 -0
  58. package/src/tools/tool-event-describer.ts +387 -0
  59. package/src/tools/tool-idempotency.ts +373 -0
  60. package/src/tools/tool-policy-table.ts +61 -0
  61. package/src/tools/tool-policy.ts +73 -0
  62. package/src/workflow/llm-planner.ts +407 -0
  63. package/src/workflow/planner.ts +201 -0
  64. package/src/workflow/runner.ts +141 -0
  65. package/src/workflow/types.ts +69 -0
  66. package/src/workspace/registry.ts +104 -0
  67. package/src/workspace/types.ts +7 -0
@@ -0,0 +1,486 @@
1
+ import { z } from "zod";
2
+
3
+ export const promptIdSchema = z.enum([
4
+ "godot.assistant",
5
+ "gdscript.reviewer",
6
+ "scene.architect",
7
+ "backend.helper"
8
+ ]);
9
+
10
+ export const skillIdSchema = z.enum([
11
+ "godot.project_init",
12
+ "gdscript.review",
13
+ "scene.builder",
14
+ "file.creator",
15
+ "backend.helper"
16
+ ]);
17
+
18
+ export const additionalContextItemSchema = z.object({
19
+ id: z.string().min(1).max(160),
20
+ kind: z.enum(["editor_selection", "scene", "node", "file", "folder", "script", "script_selection", "filesystem_selection"]),
21
+ title: z.string().min(1).max(200),
22
+ subtitle: z.string().max(400).optional(),
23
+ pinned: z.boolean().optional(),
24
+ source: z.enum(["editor", "manual"]),
25
+ resourcePath: z.string().max(500).optional(),
26
+ nodePath: z.string().max(500).optional(),
27
+ nodeType: z.string().max(160).optional(),
28
+ scriptPath: z.string().max(500).optional(),
29
+ summary: z.string().max(1200).optional(),
30
+ data: z.unknown().optional()
31
+ });
32
+
33
+ export const aiChatParamsSchema = z.object({
34
+ message: z.string(),
35
+ promptId: promptIdSchema.optional(),
36
+ skillId: skillIdSchema.optional(),
37
+ systemPrompt: z.string().optional(),
38
+ retryFromRequestId: z.string().min(1).optional(),
39
+ additionalContext: z.array(additionalContextItemSchema).max(32).optional(),
40
+ options: z.object({
41
+ temperature: z.number().min(0).max(2).optional(),
42
+ topP: z.number().min(0).max(1).optional(),
43
+ maxTokens: z.number().int().positive().optional(),
44
+ stop: z.union([z.string(), z.array(z.string())]).optional(),
45
+ responseFormat: z.union([z.literal("text"), z.literal("json")]).optional(),
46
+ stream: z.boolean().optional(),
47
+ toolBudget: z.enum(["simple", "normal", "codegen", "project_edit"]).optional(),
48
+ workflow: z.enum(["auto", "single", "multi_phase", "llm_planned"]).optional(),
49
+ }).optional()
50
+ });
51
+
52
+ const guideTextSchema = z.string().min(1).max(4000);
53
+ const customMcpSecretRecordSchema = z.record(z.string().min(1).max(160), z.string().max(20000))
54
+ .refine((value: Record<string, string>): boolean => Object.keys(value).length <= 64, "Too many secret entries");
55
+ const customMcpServerInputSchema = z.discriminatedUnion("transport", [
56
+ z.object({
57
+ name: z.string().min(1).max(80),
58
+ description: z.string().max(300).optional(),
59
+ transport: z.literal("stdio"),
60
+ enabled: z.boolean().optional(),
61
+ command: z.string().min(1).max(300),
62
+ args: z.array(z.string().max(1000)).max(64).optional(),
63
+ env: customMcpSecretRecordSchema.optional(),
64
+ }),
65
+ z.object({
66
+ name: z.string().min(1).max(80),
67
+ description: z.string().max(300).optional(),
68
+ transport: z.literal("http"),
69
+ enabled: z.boolean().optional(),
70
+ url: z.string().url().max(1000),
71
+ headers: customMcpSecretRecordSchema.optional(),
72
+ })
73
+ ]);
74
+
75
+ export const clientRequestSchema = z.discriminatedUnion("method", [
76
+ z.object({
77
+ type: z.literal("request"),
78
+ id: z.string(),
79
+ method: z.literal("ping"),
80
+ params: z.object({}).optional(),
81
+ }),
82
+ z.object({
83
+ type: z.literal("request"),
84
+ id: z.string(),
85
+ method: z.literal("provider.configure"),
86
+ params: z.object({
87
+ provider: z.literal("deepseek"),
88
+ apiKey: z.string().min(1),
89
+ model: z.string().min(1).optional(),
90
+ baseUrl: z.string().min(1).optional(),
91
+ }),
92
+ }),
93
+ z.object({
94
+ type: z.literal("request"),
95
+ id: z.string(),
96
+ method: z.literal("provider.config.get"),
97
+ params: z.object({}).optional(),
98
+ }),
99
+ z.object({
100
+ type: z.literal("request"),
101
+ id: z.string(),
102
+ method: z.literal("provider.config.set"),
103
+ params: z.object({
104
+ provider: z.literal("deepseek"),
105
+ apiKey: z.string().optional(),
106
+ model: z.string().min(1).optional(),
107
+ baseUrl: z.string().min(1).optional(),
108
+ }),
109
+ }),
110
+ z.object({
111
+ type: z.literal("request"),
112
+ id: z.string(),
113
+ method: z.literal("provider.config.clear"),
114
+ params: z.object({}).optional(),
115
+ }),
116
+ z.object({
117
+ type: z.literal("request"),
118
+ id: z.string(),
119
+ method: z.literal("ai.chat"),
120
+ params: aiChatParamsSchema,
121
+ }),
122
+ z.object({
123
+ type: z.literal("request"),
124
+ id: z.string(),
125
+ method: z.literal("ai.next_step_hints"),
126
+ params: z.object({
127
+ sessionId: z.string().min(1).optional(),
128
+ anchorRequestId: z.string().min(1).optional(),
129
+ trigger: z.enum(["done", "paused"]).optional(),
130
+ maxHints: z.number().int().min(1).max(5).optional(),
131
+ }).optional(),
132
+ }),
133
+ z.object({
134
+ type: z.literal("request"),
135
+ id: z.string(),
136
+ method: z.literal("ai.cancel"),
137
+ params: z.object({
138
+ requestId: z.string().min(1),
139
+ }),
140
+ }),
141
+ z.object({
142
+ type: z.literal("request"),
143
+ id: z.string(),
144
+ method: z.literal("prompt.list"),
145
+ params: z.object({}).optional(),
146
+ }),
147
+ z.object({
148
+ type: z.literal("request"),
149
+ id: z.string(),
150
+ method: z.literal("skill.list"),
151
+ params: z.object({}).optional(),
152
+ }),
153
+ z.object({
154
+ type: z.literal("request"),
155
+ id: z.string(),
156
+ method: z.literal("skill.activate"),
157
+ params: z.object({
158
+ skillId: skillIdSchema.nullable(),
159
+ }),
160
+ }),
161
+ z.object({
162
+ type: z.literal("request"),
163
+ id: z.string(),
164
+ method: z.literal("session.reset"),
165
+ params: z.object({}).optional(),
166
+ }),
167
+ z.object({
168
+ type: z.literal("request"),
169
+ id: z.string(),
170
+ method: z.literal("session.info"),
171
+ params: z.object({}).optional(),
172
+ }),
173
+ z.object({
174
+ type: z.literal("request"),
175
+ id: z.string(),
176
+ method: z.literal("session.create"),
177
+ params: z.object({
178
+ title: z.string().min(1),
179
+ workspaceId: z.string().optional(),
180
+ skillId: skillIdSchema.optional(),
181
+ }),
182
+ }),
183
+ z.object({
184
+ type: z.literal("request"),
185
+ id: z.string(),
186
+ method: z.literal("session.open"),
187
+ params: z.object({
188
+ sessionId: z.string().min(1),
189
+ limit: z.number().int().positive().max(500).optional(),
190
+ }),
191
+ }),
192
+ z.object({
193
+ type: z.literal("request"),
194
+ id: z.string(),
195
+ method: z.literal("session.timeline"),
196
+ params: z.object({
197
+ sessionId: z.string().min(1).optional(),
198
+ beforeOffset: z.number().int().min(0),
199
+ limit: z.number().int().positive().max(500).optional(),
200
+ }),
201
+ }),
202
+ z.object({
203
+ type: z.literal("request"),
204
+ id: z.string(),
205
+ method: z.literal("session.list"),
206
+ params: z.object({}).optional(),
207
+ }),
208
+ z.object({
209
+ type: z.literal("request"),
210
+ id: z.string(),
211
+ method: z.literal("session.archive"),
212
+ params: z.object({
213
+ sessionId: z.string().min(1),
214
+ }),
215
+ }),
216
+ z.object({
217
+ type: z.literal("request"),
218
+ id: z.string(),
219
+ method: z.literal("session.archived.list"),
220
+ params: z.object({}).optional(),
221
+ }),
222
+ z.object({
223
+ type: z.literal("request"),
224
+ id: z.string(),
225
+ method: z.literal("session.archived.restore"),
226
+ params: z.object({
227
+ sessionId: z.string().min(1),
228
+ }),
229
+ }),
230
+ z.object({
231
+ type: z.literal("request"),
232
+ id: z.string(),
233
+ method: z.literal("session.archived.delete"),
234
+ params: z.object({
235
+ sessionId: z.string().min(1),
236
+ }),
237
+ }),
238
+ z.object({
239
+ type: z.literal("request"),
240
+ id: z.string(),
241
+ method: z.literal("session.save"),
242
+ params: z.object({}).optional(),
243
+ }),
244
+ z.object({
245
+ type: z.literal("request"),
246
+ id: z.string(),
247
+ method: z.literal("session.delete"),
248
+ params: z.object({
249
+ sessionId: z.string().min(1),
250
+ }),
251
+ }),
252
+ z.object({
253
+ type: z.literal("request"),
254
+ id: z.string(),
255
+ method: z.literal("session.rename"),
256
+ params: z.object({
257
+ sessionId: z.string().min(1),
258
+ title: z.string().min(1),
259
+ }),
260
+ }),
261
+ z.object({
262
+ type: z.literal("request"),
263
+ id: z.string(),
264
+ method: z.literal("session.compress"),
265
+ params: z.object({
266
+ keepRecent: z.number().int().min(2).max(50).optional(),
267
+ }).optional(),
268
+ }),
269
+ z.object({
270
+ type: z.literal("request"),
271
+ id: z.string(),
272
+ method: z.literal("session.summary"),
273
+ params: z.object({}).optional(),
274
+ }),
275
+ z.object({
276
+ type: z.literal("request"),
277
+ id: z.string(),
278
+ method: z.literal("session.guide.add"),
279
+ params: z.object({
280
+ clientGuideId: z.string().min(1).max(128),
281
+ text: guideTextSchema,
282
+ anchorRequestId: z.string().min(1).optional(),
283
+ }),
284
+ }),
285
+ z.object({
286
+ type: z.literal("request"),
287
+ id: z.string(),
288
+ method: z.literal("session.guide.update"),
289
+ params: z.object({
290
+ guideId: z.string().min(1),
291
+ text: guideTextSchema,
292
+ }),
293
+ }),
294
+ z.object({
295
+ type: z.literal("request"),
296
+ id: z.string(),
297
+ method: z.literal("session.guide.delete"),
298
+ params: z.object({
299
+ guideId: z.string().min(1),
300
+ }),
301
+ }),
302
+ z.object({
303
+ type: z.literal("request"),
304
+ id: z.string(),
305
+ method: z.literal("mcp.listTools"),
306
+ params: z.object({
307
+ serverId: z.string().optional(),
308
+ }).optional(),
309
+ }),
310
+ z.object({
311
+ type: z.literal("request"),
312
+ id: z.string(),
313
+ method: z.literal("mcp.callTool"),
314
+ params: z.object({
315
+ serverId: z.string().optional(),
316
+ name: z.string(),
317
+ args: z.record(z.string(), z.unknown()).optional(),
318
+ }),
319
+ }),
320
+ z.object({
321
+ type: z.literal("request"),
322
+ id: z.string(),
323
+ method: z.literal("mcp.listResources"),
324
+ params: z.object({
325
+ serverId: z.string().optional(),
326
+ }).optional(),
327
+ }),
328
+ z.object({
329
+ type: z.literal("request"),
330
+ id: z.string(),
331
+ method: z.literal("mcp.readResource"),
332
+ params: z.object({
333
+ serverId: z.string().optional(),
334
+ uri: z.string(),
335
+ }),
336
+ }),
337
+ z.object({
338
+ type: z.literal("request"),
339
+ id: z.string(),
340
+ method: z.literal("mcp.config.list"),
341
+ params: z.object({}).optional(),
342
+ }),
343
+ z.object({
344
+ type: z.literal("request"),
345
+ id: z.string(),
346
+ method: z.literal("mcp.config.add"),
347
+ params: customMcpServerInputSchema,
348
+ }),
349
+ z.object({
350
+ type: z.literal("request"),
351
+ id: z.string(),
352
+ method: z.literal("mcp.config.remove"),
353
+ params: z.object({
354
+ serverId: z.string().min(1),
355
+ }),
356
+ }),
357
+ z.object({
358
+ type: z.literal("request"),
359
+ id: z.string(),
360
+ method: z.literal("mcp.config.setEnabled"),
361
+ params: z.object({
362
+ serverId: z.string().min(1),
363
+ enabled: z.boolean(),
364
+ }),
365
+ }),
366
+ z.object({
367
+ type: z.literal("request"),
368
+ id: z.string(),
369
+ method: z.literal("fileChange.create"),
370
+ params: z.object({
371
+ relativePath: z.string().min(1),
372
+ content: z.string(),
373
+ }),
374
+ }),
375
+ z.object({
376
+ type: z.literal("request"),
377
+ id: z.string(),
378
+ method: z.literal("fileChange.overwrite"),
379
+ params: z.object({
380
+ relativePath: z.string().min(1),
381
+ content: z.string(),
382
+ }),
383
+ }),
384
+ z.object({
385
+ type: z.literal("request"),
386
+ id: z.string(),
387
+ method: z.literal("fileChange.delete"),
388
+ params: z.object({
389
+ relativePath: z.string().min(1),
390
+ }),
391
+ }),
392
+ z.object({
393
+ type: z.literal("request"),
394
+ id: z.string(),
395
+ method: z.literal("approval.list"),
396
+ params: z.object({}).optional(),
397
+ }),
398
+ z.object({
399
+ type: z.literal("request"),
400
+ id: z.string(),
401
+ method: z.literal("approval.mode.set"),
402
+ params: z.object({
403
+ mode: z.enum(["manual", "auto-safe", "read-only"]),
404
+ }),
405
+ }),
406
+ z.object({
407
+ type: z.literal("request"),
408
+ id: z.string(),
409
+ method: z.literal("approval.approve"),
410
+ params: z.object({
411
+ approvalId: z.string().min(1),
412
+ }),
413
+ }),
414
+ z.object({
415
+ type: z.literal("request"),
416
+ id: z.string(),
417
+ method: z.literal("approval.reject"),
418
+ params: z.object({
419
+ approvalId: z.string().min(1),
420
+ }),
421
+ }),
422
+ z.object({
423
+ type: z.literal("request"),
424
+ id: z.string(),
425
+ method: z.literal("environment.configure"),
426
+ params: z.object({
427
+ godotExecutablePath: z.string().min(1).optional(),
428
+ godotProjectPath: z.string().min(1).optional(),
429
+ }),
430
+ }),
431
+ z.object({
432
+ type: z.literal("request"),
433
+ id: z.string(),
434
+ method: z.literal("editor.context.update"),
435
+ params: z.record(z.string(), z.unknown()),
436
+ }),
437
+ z.object({
438
+ type: z.literal("request"),
439
+ id: z.string(),
440
+ method: z.literal("editor.tool.result"),
441
+ params: z.object({
442
+ callId: z.string().min(1),
443
+ ok: z.boolean(),
444
+ result: z.unknown().optional(),
445
+ error: z.string().optional(),
446
+ }),
447
+ }),
448
+ z.object({
449
+ type: z.literal("request"),
450
+ id: z.string(),
451
+ method: z.literal("workspace.list"),
452
+ params: z.object({}).optional(),
453
+ }),
454
+ z.object({
455
+ type: z.literal("request"),
456
+ id: z.string(),
457
+ method: z.literal("workspace.select"),
458
+ params: z.object({
459
+ workspaceId: z.string().min(1),
460
+ }),
461
+ }),
462
+ z.object({
463
+ type: z.literal("request"),
464
+ id: z.string(),
465
+ method: z.literal("workspace.info"),
466
+ params: z.object({}).optional(),
467
+ })
468
+ ]);
469
+
470
+ export const serverResponseSchema = z.discriminatedUnion("ok", [
471
+ z.object({
472
+ type: z.literal("response"),
473
+ id: z.string(),
474
+ ok: z.literal(true),
475
+ result: z.unknown(),
476
+ }),
477
+ z.object({
478
+ type: z.literal("response"),
479
+ id: z.string(),
480
+ ok: z.literal(false),
481
+ error: z.object({
482
+ code: z.string(),
483
+ message: z.string(),
484
+ }),
485
+ }),
486
+ ]);
@@ -0,0 +1,77 @@
1
+ import type { z } from "zod";
2
+ import type { additionalContextItemSchema, aiChatParamsSchema, clientRequestSchema, promptIdSchema, skillIdSchema } from "./schema.js";
3
+
4
+ export type AiChatParams = z.infer<typeof aiChatParamsSchema>;
5
+
6
+ export type AdditionalContextItem = z.infer<typeof additionalContextItemSchema>;
7
+
8
+ export type ClientRequest = z.infer<typeof clientRequestSchema>;
9
+
10
+ export type PromptId = z.infer<typeof promptIdSchema>;
11
+
12
+ export type SkillId = z.infer<typeof skillIdSchema>;
13
+
14
+ export type ChatMessage = {
15
+ role: "system" | "user" | "assistant";
16
+ content: string;
17
+ requestId?: string | undefined;
18
+ createdAt?: string | undefined;
19
+ additionalContext?: AdditionalContextItem[] | undefined;
20
+ };
21
+
22
+ export type ServerResponse =
23
+ | {
24
+ type: "response";
25
+ id: string;
26
+ ok: true;
27
+ result: unknown;
28
+ }
29
+ | {
30
+ type: "response";
31
+ id: string;
32
+ ok: false;
33
+ error: {
34
+ code: string;
35
+ message: string;
36
+ };
37
+ };
38
+
39
+ export type ServerEvent = {
40
+ type: "event";
41
+ id: string;
42
+ event:
43
+ | "ai.delta"
44
+ | "ai.done"
45
+ | "ai.paused"
46
+ | "ai.cancelled"
47
+ | "ai.thinking.delta"
48
+ | "ai.thinking.done"
49
+ | "tool.call"
50
+ | "tool.result"
51
+ | "tool.error"
52
+ | "tool.approval_required"
53
+ | "tool.approved"
54
+ | "tool.rejected"
55
+ | "guide.added"
56
+ | "guide.updated"
57
+ | "guide.deleted"
58
+ | "guide.applied"
59
+ | "editor.tool.requested"
60
+ | "mcp.config.updated"
61
+ | "workflow.started"
62
+ | "workflow.phase.started"
63
+ | "workflow.todo.updated"
64
+ | "workflow.phase.done"
65
+ | "workflow.done"
66
+ | "workflow.error";
67
+ data?: unknown;
68
+ };
69
+
70
+ export type ModelProfile = {
71
+ provider: "deepseek";
72
+ model: string;
73
+ contextWindowTokens: number;
74
+ maxOutputTokens: number;
75
+ defaultOutputReserveTokens: number;
76
+ safetyMarginTokens: number;
77
+ };