create-windy 0.3.16 → 0.3.18

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 (65) hide show
  1. package/README.md +14 -36
  2. package/dist/cli.js +1831 -3178
  3. package/package.json +1 -1
  4. package/template/.windy-template.json +2 -2
  5. package/template/AGENTS.md +7 -1
  6. package/template/README.md +8 -11
  7. package/template/apps/agent-server/Dockerfile +2 -1
  8. package/template/apps/agent-server/README.md +13 -5
  9. package/template/apps/agent-server/adk_web_agents/canonical_debug/__init__.py +1 -0
  10. package/template/apps/agent-server/adk_web_agents/canonical_debug/agent.py +125 -0
  11. package/template/apps/agent-server/project/adk-web-debug.json +4 -0
  12. package/template/apps/agent-server/src/southwind_agent_server/adk_debug.py +315 -0
  13. package/template/apps/agent-server/tests/test_adk_web_canonical_debug.py +235 -0
  14. package/template/apps/server/Dockerfile +1 -1
  15. package/template/apps/server/src/agent/run-debug-authorization.ts +27 -0
  16. package/template/apps/server/src/agent/run-facade-adk-debug.test.ts +56 -0
  17. package/template/apps/server/src/agent/run-facade.test-support.ts +235 -0
  18. package/template/apps/server/src/agent/run-facade.test.ts +8 -244
  19. package/template/apps/server/src/agent/run-facade.ts +23 -48
  20. package/template/apps/server/src/agent/run-operation-registry.ts +51 -0
  21. package/template/apps/server/src/agent/runtime-bootstrap.ts +5 -2
  22. package/template/apps/server/src/agent/tool-audit.ts +3 -0
  23. package/template/apps/server/src/agent/tool-registry.test.ts +29 -0
  24. package/template/apps/server/src/application-services.ts +83 -15
  25. package/template/apps/server/src/audit/contracts.ts +8 -0
  26. package/template/apps/server/src/audit/recovery-queue.test.ts +48 -1
  27. package/template/apps/server/src/audit/recovery-queue.ts +73 -4
  28. package/template/apps/server/src/audit/reliable-writer.test.ts +120 -2
  29. package/template/apps/server/src/audit/reliable-writer.ts +98 -34
  30. package/template/apps/server/src/guards.ts +16 -0
  31. package/template/apps/server/src/index.ts +23 -20
  32. package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +0 -1
  33. package/template/apps/server/src/jobs/legacy-adapter.test.ts +6 -0
  34. package/template/apps/server/src/jobs/legacy-service-runtime.ts +18 -0
  35. package/template/apps/server/src/module-host/durable-context-unavailable.test.ts +84 -0
  36. package/template/apps/server/src/module-host/durable-context.test.ts +14 -0
  37. package/template/apps/server/src/module-host/durable-context.ts +17 -15
  38. package/template/apps/server/src/module-host/request-context.test.ts +30 -1
  39. package/template/apps/server/src/module-host/request-context.ts +15 -2
  40. package/template/apps/server/src/module-host/storage-port.ts +1 -1
  41. package/template/apps/server/src/platform-bootstrap.ts +16 -0
  42. package/template/apps/server/src/runtime-adk-debug.test.ts +246 -0
  43. package/template/apps/server/src/runtime-adk-debug.ts +158 -0
  44. package/template/apps/server/src/runtime-request-actor.test.ts +55 -0
  45. package/template/apps/server/src/runtime-request-actor.ts +22 -0
  46. package/template/apps/server/src/runtime.test.ts +3 -0
  47. package/template/apps/server/src/runtime.ts +36 -3
  48. package/template/apps/server/src/scheduler/definitions.test.ts +16 -0
  49. package/template/apps/web/Dockerfile +1 -1
  50. package/template/docker-compose.agent-debug.yml +56 -0
  51. package/template/docker-compose.yml +1 -39
  52. package/template/docs/architecture/ai-runtime.md +14 -5
  53. package/template/docs/architecture/module-manifest-composition.md +14 -0
  54. package/template/docs/development/custom-login-page.md +2 -16
  55. package/template/docs/platform/agent-runtime.md +57 -16
  56. package/template/docs/platform/agent-tool-sandbox.md +4 -3
  57. package/template/docs/platform/audit-reliability.md +33 -5
  58. package/template/docs/platform/platform-authentication.md +9 -1
  59. package/template/package.json +4 -3
  60. package/template/packages/database/drizzle/0043_activate_agent_dependencies.sql +196 -0
  61. package/template/packages/database/drizzle/meta/0043_snapshot.json +8335 -0
  62. package/template/packages/database/drizzle/meta/_journal.json +7 -0
  63. package/template/packages/database/src/schema-notification-delivery.test.ts +15 -6
  64. package/template/packages/database/src/schema-workflow-notification.test.ts +44 -29
  65. package/template/scripts/dev-adk-web.ts +107 -0
@@ -302,6 +302,13 @@
302
302
  "when": 1785151819729,
303
303
  "tag": "0042_puzzling_rumiko_fujikawa",
304
304
  "breakpoints": true
305
+ },
306
+ {
307
+ "idx": 43,
308
+ "version": "7",
309
+ "when": 1785269877377,
310
+ "tag": "0043_activate_agent_dependencies",
311
+ "breakpoints": true
305
312
  }
306
313
  ]
307
314
  }
@@ -39,16 +39,25 @@ describe("通知策略与投递 schema", () => {
39
39
  ),
40
40
  ).toBe(true);
41
41
 
42
- const migration = await Bun.file(
43
- new URL("../drizzle/0038_uneven_wasp.sql", import.meta.url),
44
- ).text();
42
+ const migration = await migrationHistory(
43
+ "0038_uneven_wasp.sql",
44
+ "0043_activate_agent_dependencies.sql",
45
+ );
45
46
  expect(migration).toContain('CREATE TABLE "notification_preferences"');
46
47
  expect(migration).toContain('CREATE TABLE "notification_delivery_outbox"');
47
- expect(migration).toContain(
48
- 'ALTER TABLE "platform_notifications" ADD COLUMN "scheduled_for"',
49
- );
48
+ expect(migration).toContain('"scheduled_for" timestamp with time zone');
50
49
  expect(migration).toContain(
51
50
  'CREATE INDEX "idx_notification_delivery_claim"',
52
51
  );
53
52
  });
54
53
  });
54
+
55
+ async function migrationHistory(...names: string[]) {
56
+ return (
57
+ await Promise.all(
58
+ names.map((name) =>
59
+ Bun.file(new URL(`../drizzle/${name}`, import.meta.url)).text(),
60
+ ),
61
+ )
62
+ ).join("\n");
63
+ }
@@ -10,6 +10,18 @@ import {
10
10
  } from "./schema/index.js";
11
11
 
12
12
  describe("审批与通知 schema", () => {
13
+ test("依赖激活 migration 只推进 snapshot lineage", async () => {
14
+ const previous = await snapshot("0042_snapshot.json");
15
+ const activation = await snapshot("0043_snapshot.json");
16
+
17
+ expect(activation.prevId).toBe(previous.id);
18
+ delete previous.id;
19
+ delete previous.prevId;
20
+ delete activation.id;
21
+ delete activation.prevId;
22
+ expect(activation).toEqual(previous);
23
+ });
24
+
13
25
  test("审批任务状态与不可变决定事实分表持久化", async () => {
14
26
  expect(getTableConfig(workflowWorkItems).name).toBe("workflow_work_items");
15
27
  expect(workflowWorkItems.version.notNull).toBe(true);
@@ -23,9 +35,10 @@ describe("审批与通知 schema", () => {
23
35
  (foreignKey) => foreignKey.onDelete === "restrict",
24
36
  ),
25
37
  ).toBe(true);
26
- const migration = await Bun.file(
27
- new URL("../drizzle/0026_aberrant_doctor_octopus.sql", import.meta.url),
28
- ).text();
38
+ const migration = await migrationHistory(
39
+ "0026_aberrant_doctor_octopus.sql",
40
+ "0043_activate_agent_dependencies.sql",
41
+ );
29
42
  expect(migration).toContain('CREATE TABLE "workflow_work_items"');
30
43
  expect(migration).toContain(
31
44
  'CREATE UNIQUE INDEX "uk_workflow_transitions_request"',
@@ -69,34 +82,36 @@ describe("审批与通知 schema", () => {
69
82
  );
70
83
  expect(getTableConfig(notificationRevisions).primaryKeys).toHaveLength(1);
71
84
  expect(platformNotifications.revision.notNull).toBe(true);
72
- const migration = await Bun.file(
73
- new URL("../drizzle/0027_tiny_diamondback.sql", import.meta.url),
74
- ).text();
75
- expect(migration).toContain('ADD COLUMN "target" jsonb');
85
+ const migration = await migrationHistory(
86
+ "0027_tiny_diamondback.sql",
87
+ "0035_material_nightshade.sql",
88
+ "0036_hesitant_speed.sql",
89
+ "0043_activate_agent_dependencies.sql",
90
+ );
91
+ expect(migration).toContain('"target" jsonb');
76
92
  expect(migration).toContain(
77
93
  'CREATE UNIQUE INDEX "uk_platform_notifications_source_key"',
78
94
  );
79
- const favoritesMigration = await Bun.file(
80
- new URL("../drizzle/0035_material_nightshade.sql", import.meta.url),
81
- ).text();
82
- expect(favoritesMigration).toContain(
83
- 'CREATE TABLE "notification_favorites"',
84
- );
85
- expect(favoritesMigration).toContain(
86
- 'PRIMARY KEY("notification_id","user_id")',
87
- );
88
- expect(favoritesMigration).toContain("ON DELETE restrict");
89
- const revisionsMigration = await Bun.file(
90
- new URL("../drizzle/0036_hesitant_speed.sql", import.meta.url),
91
- ).text();
92
- expect(revisionsMigration).toContain(
93
- 'CREATE TABLE "notification_revisions"',
94
- );
95
- expect(revisionsMigration).toContain(
96
- 'ALTER TABLE "platform_notifications" ADD COLUMN "revision"',
97
- );
98
- expect(revisionsMigration).toContain(
99
- 'INSERT INTO "notification_revisions"',
100
- );
95
+ expect(migration).toContain('CREATE TABLE "notification_favorites"');
96
+ expect(migration).toContain('PRIMARY KEY ("notification_id", "user_id")');
97
+ expect(migration).toContain("ON DELETE restrict");
98
+ expect(migration).toContain('CREATE TABLE "notification_revisions"');
99
+ expect(migration).toContain('"revision" integer');
101
100
  });
102
101
  });
102
+
103
+ async function migrationHistory(...names: string[]) {
104
+ return (
105
+ await Promise.all(
106
+ names.map((name) =>
107
+ Bun.file(new URL(`../drizzle/${name}`, import.meta.url)).text(),
108
+ ),
109
+ )
110
+ ).join("\n");
111
+ }
112
+
113
+ async function snapshot(name: string) {
114
+ return (await Bun.file(
115
+ new URL(`../drizzle/meta/${name}`, import.meta.url),
116
+ ).json()) as { id?: string; prevId?: string; [key: string]: unknown };
117
+ }
@@ -0,0 +1,107 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { resolve } from "node:path";
3
+
4
+ interface DebugProjectConfig {
5
+ schemaVersion: 1;
6
+ textOperation: { key: string; dataActorId: string } | null;
7
+ }
8
+
9
+ export async function readDebugOperationConfig(
10
+ path = resolve("apps/agent-server/project/adk-web-debug.json"),
11
+ ): Promise<{ operationKey: string; dataActorId: string }> {
12
+ let value: unknown;
13
+ try {
14
+ value = JSON.parse(await readFile(path, "utf8"));
15
+ } catch (error) {
16
+ throw new Error(`ADK Web 项目调试配置不可读:${path}`, {
17
+ cause: error,
18
+ });
19
+ }
20
+ if (!isDebugProjectConfig(value)) {
21
+ throw new Error("ADK Web 项目调试配置格式无效");
22
+ }
23
+ const key = value.textOperation?.key.trim();
24
+ const dataActorId = value.textOperation?.dataActorId.trim();
25
+ if (!key || !dataActorId) {
26
+ throw new Error(
27
+ "请先在 apps/agent-server/project/adk-web-debug.json 选择文本 Operation 与真实开发数据用户",
28
+ );
29
+ }
30
+ return { operationKey: key, dataActorId };
31
+ }
32
+
33
+ export async function runAdkWeb(): Promise<number> {
34
+ const { operationKey, dataActorId } = await readDebugOperationConfig();
35
+ const child = Bun.spawn(
36
+ [
37
+ "docker",
38
+ "compose",
39
+ "-f",
40
+ "docker-compose.yml",
41
+ "-f",
42
+ "docker-compose.agent-debug.yml",
43
+ "--profile",
44
+ "agent",
45
+ "--profile",
46
+ "agent-debug",
47
+ "up",
48
+ "--build",
49
+ "adk-web-debug",
50
+ ],
51
+ {
52
+ cwd: process.cwd(),
53
+ env: {
54
+ ...process.env,
55
+ WINDY_ADK_DEBUG_OPERATION_KEY: operationKey,
56
+ WINDY_ADK_DEBUG_DATA_ACTOR_ID: dataActorId,
57
+ },
58
+ stdin: "inherit",
59
+ stdout: "inherit",
60
+ stderr: "inherit",
61
+ },
62
+ );
63
+ return child.exited;
64
+ }
65
+
66
+ function isDebugProjectConfig(value: unknown): value is DebugProjectConfig {
67
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
68
+ const record = value as Record<string, unknown>;
69
+ if (
70
+ Object.keys(record).sort().join(",") !== "schemaVersion,textOperation" ||
71
+ record.schemaVersion !== 1
72
+ ) {
73
+ return false;
74
+ }
75
+ if (record.textOperation === null) return true;
76
+ if (
77
+ !record.textOperation ||
78
+ typeof record.textOperation !== "object" ||
79
+ Array.isArray(record.textOperation)
80
+ ) {
81
+ return false;
82
+ }
83
+ const operation = record.textOperation as Record<string, unknown>;
84
+ return (
85
+ Object.keys(operation).sort().join(",") === "dataActorId,key" &&
86
+ isIdentifier(operation.key) &&
87
+ isIdentifier(operation.dataActorId)
88
+ );
89
+ }
90
+
91
+ function isIdentifier(value: unknown): value is string {
92
+ return (
93
+ typeof value === "string" &&
94
+ Boolean(value.trim()) &&
95
+ value.length <= 200 &&
96
+ !/\s/.test(value)
97
+ );
98
+ }
99
+
100
+ if (import.meta.main) {
101
+ try {
102
+ process.exitCode = await runAdkWeb();
103
+ } catch (error) {
104
+ console.error(error instanceof Error ? error.message : String(error));
105
+ process.exitCode = 1;
106
+ }
107
+ }