create-windy 0.4.0 → 0.5.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 (194) hide show
  1. package/dist/cli.js +263 -121
  2. package/package.json +1 -1
  3. package/template/.windy-template.json +2 -2
  4. package/template/apps/agent-server/adk_web_agents/canonical_debug/agent.py +29 -9
  5. package/template/apps/agent-server/adk_web_agents/services.py +25 -0
  6. package/template/apps/agent-server/src/southwind_agent_server/adk_adapter.py +40 -11
  7. package/template/apps/agent-server/src/southwind_agent_server/adk_debug_sessions.py +325 -0
  8. package/template/apps/agent-server/src/southwind_agent_server/adk_model.py +70 -6
  9. package/template/apps/agent-server/src/southwind_agent_server/adk_tools.py +1 -1
  10. package/template/apps/agent-server/src/southwind_agent_server/app.py +16 -4
  11. package/template/apps/agent-server/src/southwind_agent_server/approval_resolution.py +30 -0
  12. package/template/apps/agent-server/src/southwind_agent_server/contracts.py +9 -0
  13. package/template/apps/agent-server/src/southwind_agent_server/deterministic.py +2 -1
  14. package/template/apps/agent-server/src/southwind_agent_server/engine.py +3 -1
  15. package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +95 -130
  16. package/template/apps/agent-server/src/southwind_agent_server/openai_engine_validation.py +133 -0
  17. package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +89 -20
  18. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_insert.py +34 -0
  19. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_queries.py +234 -0
  20. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_replay.py +44 -0
  21. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_status.py +83 -0
  22. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_store.py +331 -0
  23. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_summary.py +304 -0
  24. package/template/apps/agent-server/src/southwind_agent_server/report_lifecycle.py +217 -0
  25. package/template/apps/agent-server/src/southwind_agent_server/report_metrics.py +149 -0
  26. package/template/apps/agent-server/src/southwind_agent_server/report_presenter.py +280 -0
  27. package/template/apps/agent-server/src/southwind_agent_server/report_routes.py +126 -0
  28. package/template/apps/agent-server/src/southwind_agent_server/report_store.py +344 -0
  29. package/template/apps/agent-server/src/southwind_agent_server/report_types.py +111 -0
  30. package/template/apps/agent-server/src/southwind_agent_server/runtime_factory.py +31 -2
  31. package/template/apps/agent-server/src/southwind_agent_server/service.py +56 -51
  32. package/template/apps/agent-server/src/southwind_agent_server/signal_events.py +18 -1
  33. package/template/apps/agent-server/tests/test_adk_adapter.py +7 -9
  34. package/template/apps/agent-server/tests/test_adk_debug_sessions.py +215 -0
  35. package/template/apps/agent-server/tests/test_adk_web_canonical_debug.py +48 -1
  36. package/template/apps/agent-server/tests/test_openai_provider.py +58 -6
  37. package/template/apps/agent-server/tests/test_postgres_report_status.py +59 -0
  38. package/template/apps/agent-server/tests/test_postgres_report_summary.py +298 -0
  39. package/template/apps/agent-server/tests/test_provider_attempt_reporting.py +152 -0
  40. package/template/apps/agent-server/tests/test_report_attempt_lifecycle.py +126 -0
  41. package/template/apps/agent-server/tests/test_report_resilience.py +181 -0
  42. package/template/apps/agent-server/tests/test_report_store.py +286 -0
  43. package/template/apps/agent-server/tests/test_report_summary_parity.py +115 -0
  44. package/template/apps/agent-server/tests/test_report_terminal_sync.py +177 -0
  45. package/template/apps/server/src/agent/debug-session-facade-provider-failure.test.ts +269 -0
  46. package/template/apps/server/src/agent/debug-session-facade.test.ts +335 -0
  47. package/template/apps/server/src/agent/debug-session-facade.ts +302 -0
  48. package/template/apps/server/src/agent/debug-session-id.test.ts +37 -0
  49. package/template/apps/server/src/agent/debug-session-id.ts +37 -0
  50. package/template/apps/server/src/agent/debug-session-provider-reader.ts +54 -0
  51. package/template/apps/server/src/agent/debug-session-routes.test.ts +64 -0
  52. package/template/apps/server/src/agent/debug-session-routes.ts +73 -0
  53. package/template/apps/server/src/agent/debug-session-validation.ts +106 -0
  54. package/template/apps/server/src/agent/drizzle-run-binding-repository.ts +2 -0
  55. package/template/apps/server/src/agent/provider-input-governance.test.ts +18 -0
  56. package/template/apps/server/src/agent/provider-input-governance.ts +37 -1
  57. package/template/apps/server/src/agent/remote-runtime.test.ts +7 -0
  58. package/template/apps/server/src/agent/remote-runtime.ts +1 -0
  59. package/template/apps/server/src/agent/run-authorization.test.ts +98 -0
  60. package/template/apps/server/src/agent/run-authorization.ts +32 -1
  61. package/template/apps/server/src/agent/run-binding-repository.ts +1 -0
  62. package/template/apps/server/src/agent/run-contracts.ts +5 -0
  63. package/template/apps/server/src/agent/run-facade-adk-debug.test.ts +39 -0
  64. package/template/apps/server/src/agent/run-facade.test.ts +78 -0
  65. package/template/apps/server/src/agent/run-facade.ts +33 -3
  66. package/template/apps/server/src/agent/run-input-commitment.ts +50 -0
  67. package/template/apps/server/src/agent/run-input-verification.ts +41 -0
  68. package/template/apps/server/src/agent/runtime-bootstrap-report.test.ts +136 -0
  69. package/template/apps/server/src/agent/runtime-bootstrap.ts +66 -1
  70. package/template/apps/server/src/agent/tool-host.test.ts +1 -0
  71. package/template/apps/server/src/agent/unavailable-routes.ts +4 -0
  72. package/template/apps/server/src/ai-runtime-report/actor-directory.ts +94 -0
  73. package/template/apps/server/src/ai-runtime-report/actor-handle.test.ts +27 -0
  74. package/template/apps/server/src/ai-runtime-report/actor-handle.ts +81 -0
  75. package/template/apps/server/src/ai-runtime-report/contracts.ts +91 -0
  76. package/template/apps/server/src/ai-runtime-report/remote-parser.ts +212 -0
  77. package/template/apps/server/src/ai-runtime-report/remote-port.ts +138 -0
  78. package/template/apps/server/src/ai-runtime-report/routes.ts +172 -0
  79. package/template/apps/server/src/ai-runtime-report/scope.ts +63 -0
  80. package/template/apps/server/src/ai-runtime-report/service.test.ts +271 -0
  81. package/template/apps/server/src/ai-runtime-report/service.ts +206 -0
  82. package/template/apps/server/src/license/runtime-audit-reliability.test.ts +2 -0
  83. package/template/apps/server/src/license/runtime-service.test.ts +6 -0
  84. package/template/apps/server/src/module-host/ai-operation-port.test.ts +63 -0
  85. package/template/apps/server/src/module-host/ai-operation-port.ts +30 -5
  86. package/template/apps/server/src/module-host/debug-session-provider-registration.test.ts +162 -0
  87. package/template/apps/server/src/module-host/debug-session-provider-registration.ts +84 -0
  88. package/template/apps/server/src/module-host/initialize-contracts.ts +7 -0
  89. package/template/apps/server/src/module-host/initialize.ts +6 -197
  90. package/template/apps/server/src/module-host/request-context.ts +1 -0
  91. package/template/apps/server/src/module-host/scoped-host.ts +214 -0
  92. package/template/apps/server/src/module-host.ts +1 -0
  93. package/template/apps/server/src/runtime-adk-debug.test.ts +25 -1
  94. package/template/apps/server/src/runtime-adk-debug.ts +8 -2
  95. package/template/apps/server/src/settings/drizzle-watermark-repository.integration.test.ts +4 -0
  96. package/template/apps/server/src/settings/drizzle-watermark-repository.ts +11 -3
  97. package/template/apps/server/src/settings/watermark-routes.test.ts +54 -1
  98. package/template/apps/server/src/settings/watermark-routes.ts +29 -1
  99. package/template/apps/server/src/system/operations.test.ts +54 -0
  100. package/template/apps/server/src/system/operations.ts +23 -1
  101. package/template/apps/server/src/system/seed.test.ts +4 -0
  102. package/template/apps/server/src/system/system-resource-monitoring.test.ts +82 -0
  103. package/template/apps/server/src/system/system-resource-monitoring.ts +300 -0
  104. package/template/apps/web/src/composables/useWatermarkSettings.webtest.ts +14 -0
  105. package/template/apps/web/src/composables/watermark-settings.ts +40 -11
  106. package/template/apps/web/src/composables/watermark-settings.webtest.ts +19 -6
  107. package/template/apps/web/src/layout/AppSidebar.vue +6 -1
  108. package/template/apps/web/src/layout/AppSidebar.webtest.ts +2 -0
  109. package/template/apps/web/src/layout/GlobalWatermark.layering.webtest.ts +2 -0
  110. package/template/apps/web/src/layout/GlobalWatermark.vue +4 -8
  111. package/template/apps/web/src/layout/GlobalWatermark.webtest.ts +12 -5
  112. package/template/apps/web/src/pages/auth/LoginPage.vue +6 -1
  113. package/template/apps/web/src/pages/settings/BrandingSettingsSection.vue +20 -3
  114. package/template/apps/web/src/pages/settings/BrandingSettingsSection.webtest.ts +80 -0
  115. package/template/apps/web/src/pages/settings/WatermarkPreview.vue +72 -0
  116. package/template/apps/web/src/pages/settings/WatermarkPreview.webtest.ts +55 -0
  117. package/template/apps/web/src/pages/settings/WatermarkSettingsSection.vue +80 -24
  118. package/template/apps/web/src/pages/settings/WatermarkSettingsSection.webtest.ts +115 -0
  119. package/template/apps/web/src/pages/system/AiRuntimePage.vue +129 -0
  120. package/template/apps/web/src/pages/system/SystemOperationsPage.vue +2 -1
  121. package/template/apps/web/src/pages/system/ai-runtime-presenter.ts +60 -0
  122. package/template/apps/web/src/pages/system/ai-runtime-presenter.webtest.ts +48 -0
  123. package/template/apps/web/src/pages/system/audit-time-range.ts +34 -2
  124. package/template/apps/web/src/pages/system/components/AuditLogFilters.vue +4 -3
  125. package/template/apps/web/src/pages/system/components/AuditLogFilters.webtest.ts +26 -1
  126. package/template/apps/web/src/pages/system/components/OperationGpuMonitor.vue +98 -0
  127. package/template/apps/web/src/pages/system/components/OperationGpuMonitor.webtest.ts +61 -0
  128. package/template/apps/web/src/pages/system/components/OperationServiceMonitor.vue +53 -0
  129. package/template/apps/web/src/pages/system/components/OperationServiceMonitor.webtest.ts +20 -1
  130. package/template/apps/web/src/pages/system/components/SystemResourcePage.webtest.ts +14 -1
  131. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeActivityChart.vue +85 -0
  132. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeCharts.webtest.ts +82 -0
  133. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeFilters.vue +98 -0
  134. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeFilters.webtest.ts +27 -0
  135. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.vue +168 -0
  136. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunTable.vue +130 -0
  137. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeSummaryCards.vue +82 -0
  138. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeSummaryCards.webtest.ts +102 -0
  139. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeTokenByModelChart.vue +101 -0
  140. package/template/apps/web/src/pages/system/composables/useAiRuntimeReport.ts +185 -0
  141. package/template/apps/web/src/pages/system/composables/useAiRuntimeReport.webtest.ts +158 -0
  142. package/template/apps/web/src/pages/system/composables/useSystemResource.ts +21 -7
  143. package/template/apps/web/src/router/error-navigation.ts +22 -0
  144. package/template/apps/web/src/router/index.ts +12 -23
  145. package/template/apps/web/src/router/platform-admin-route-bindings.ts +4 -0
  146. package/template/apps/web/src/services/ai-runtime-api.ts +164 -0
  147. package/template/apps/web/src/services/ai-runtime-api.webtest.ts +111 -0
  148. package/template/apps/web/src/services/operations-api.ts +28 -0
  149. package/template/docker-compose.agent-debug.yml +1 -1
  150. package/template/docs/architecture/ai-runtime.md +2 -1
  151. package/template/docs/architecture/module-host.md +3 -0
  152. package/template/docs/platform/agent-run-attestation.md +65 -0
  153. package/template/docs/platform/agent-runtime-observability.md +135 -0
  154. package/template/docs/platform/agent-runtime.md +47 -3
  155. package/template/docs/platform/operations-overview.md +13 -0
  156. package/template/docs/platform/platform-authentication.md +4 -3
  157. package/template/docs/platform/platform-shell-settings.md +15 -10
  158. package/template/docs/platform/web-system-crud.md +1 -1
  159. package/template/packages/config/package.json +1 -1
  160. package/template/packages/database/drizzle/0044_sweet_tarantula.sql +6 -0
  161. package/template/packages/database/drizzle/0045_tiny_cassandra_nova.sql +65 -0
  162. package/template/packages/database/drizzle/0046_tranquil_living_mummy.sql +6 -0
  163. package/template/packages/database/drizzle/0047_oval_luke_cage.sql +18 -0
  164. package/template/packages/database/drizzle/meta/0044_snapshot.json +8349 -0
  165. package/template/packages/database/drizzle/meta/0045_snapshot.json +8814 -0
  166. package/template/packages/database/drizzle/meta/0046_snapshot.json +8820 -0
  167. package/template/packages/database/drizzle/meta/0047_snapshot.json +8835 -0
  168. package/template/packages/database/drizzle/meta/_journal.json +28 -0
  169. package/template/packages/database/package.json +1 -1
  170. package/template/packages/database/src/agent-runtime-schema.test.ts +54 -0
  171. package/template/packages/database/src/schema/agent-runtime.ts +114 -0
  172. package/template/packages/database/src/schema/platform-settings.ts +3 -0
  173. package/template/packages/jobs/package.json +1 -1
  174. package/template/packages/modules/package.json +1 -1
  175. package/template/packages/modules/src/system-admin-routes.ts +10 -0
  176. package/template/packages/modules/src/system-admin-ui-catalog.ts +1 -1
  177. package/template/packages/modules/src/system-api-control-plane.ts +17 -1
  178. package/template/packages/modules/src/system-audit-actions.ts +10 -0
  179. package/template/packages/modules/src/system-features.ts +8 -0
  180. package/template/packages/modules/src/system-module-catalog.test.ts +35 -0
  181. package/template/packages/modules/src/system-module-catalog.ts +15 -4
  182. package/template/packages/modules/src/system-modules-access.test.ts +69 -0
  183. package/template/packages/modules/src/system-modules.ts +13 -0
  184. package/template/packages/modules/src/system-permissions.ts +2 -0
  185. package/template/packages/server-sdk/index.ts +11 -0
  186. package/template/packages/server-sdk/package.json +2 -1
  187. package/template/packages/server-sdk/src/ai-operation-port.ts +5 -0
  188. package/template/packages/server-sdk/src/debug-session-provider.ts +63 -0
  189. package/template/packages/server-sdk/src/module-host.ts +5 -0
  190. package/template/packages/shared/index.ts +3 -0
  191. package/template/packages/shared/package.json +1 -1
  192. package/template/packages/shared/src/ai-runtime-report.ts +134 -0
  193. package/template/packages/shared/src/platform-settings.ts +17 -0
  194. package/template/scripts/lib/postgres-regression.ts +201 -0
@@ -0,0 +1,63 @@
1
+ import type { ModuleActor } from "./actor.js";
2
+
3
+ export const MODULE_DEBUG_SESSION_SCHEMA_VERSION = 1 as const;
4
+
5
+ export interface ModuleDebugSessionContextV1 {
6
+ readonly actor: ModuleActor;
7
+ readonly operationKey: string;
8
+ readonly signal: AbortSignal;
9
+ }
10
+
11
+ export interface ModuleDebugSessionListInputV1 extends ModuleDebugSessionContextV1 {
12
+ readonly limit: number;
13
+ /** Provider 私有的不透明 keyset cursor;Host 只原样回传给同一 Provider。 */
14
+ readonly cursor?: string;
15
+ }
16
+
17
+ export interface ModuleDebugSessionGetInputV1 extends ModuleDebugSessionContextV1 {
18
+ readonly sourceId: string;
19
+ }
20
+
21
+ export interface ModuleDebugSessionSummaryV1 {
22
+ /** 仅在 Provider 与 Host 之间使用,不会返回给 ADK Web。 */
23
+ readonly sourceId: string;
24
+ readonly title: string;
25
+ readonly scopeLabel?: string;
26
+ readonly updatedAt: string;
27
+ readonly revision: string;
28
+ }
29
+
30
+ export interface ModuleDebugSessionPageV1 {
31
+ readonly sessions: readonly ModuleDebugSessionSummaryV1[];
32
+ readonly truncated: boolean;
33
+ /** truncated=true 时必须提供,用于 Host 继续读取直到完整。 */
34
+ readonly next?: string;
35
+ }
36
+
37
+ export interface ModuleDebugSessionMessageV1 {
38
+ readonly sequence: number;
39
+ readonly role: "user" | "assistant";
40
+ readonly content: string;
41
+ readonly createdAt: string;
42
+ }
43
+
44
+ export interface ModuleDebugSessionV1 extends ModuleDebugSessionSummaryV1 {
45
+ readonly messages: readonly ModuleDebugSessionMessageV1[];
46
+ }
47
+
48
+ /**
49
+ * 开发期 ADK Web 会话投影。Provider 只读业务事实,Host 负责重新授权、审计、
50
+ * 有界校验与不透明 ID;V1 不支持业务会话的追加、重命名或删除。
51
+ */
52
+ export interface ModuleDebugSessionProviderV1 {
53
+ readonly schemaVersion: typeof MODULE_DEBUG_SESSION_SCHEMA_VERSION;
54
+ readonly key: string;
55
+ readonly operationKeys: readonly string[];
56
+ readonly featureKey: string;
57
+ readonly permissionKey: string;
58
+ readonly auditAction: string;
59
+ list(input: ModuleDebugSessionListInputV1): Promise<ModuleDebugSessionPageV1>;
60
+ get(
61
+ input: ModuleDebugSessionGetInputV1,
62
+ ): Promise<ModuleDebugSessionV1 | undefined>;
63
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ModuleAiOperationHandlerRegistration } from "./ai-operation-registration.js";
2
+ import type { ModuleDebugSessionProviderV1 } from "./debug-session-provider.js";
2
3
  import type { ModuleDurableHandlerDefinition } from "./durable-handler.js";
3
4
  import type { ModuleGovernedResourceRegistration } from "./data-governance-registration.js";
4
5
  import type { ModuleRolePreset } from "./role-preset.js";
@@ -60,6 +61,10 @@ export interface ModuleHost {
60
61
  registerRolePresets(presets: readonly ModuleRolePreset[]): void;
61
62
  /** 注册 Manifest `providers` 已声明的搜索 Provider。 */
62
63
  registerSearchProviders(providers: readonly ModuleSearchProvider[]): void;
64
+ /** 注册开发期 ADK Web 使用的只读业务会话投影。 */
65
+ registerDebugSessionProviders(
66
+ providers: readonly ModuleDebugSessionProviderV1[],
67
+ ): void;
63
68
  }
64
69
 
65
70
  /**
@@ -1,4 +1,7 @@
1
1
  export * from "./src/audit.js";
2
+ // @windy-module system.agent begin
3
+ export * from "./src/ai-runtime-report.js";
4
+ // @windy-module system.agent end
2
5
  export * from "./src/database.js";
3
6
  export * from "./src/data-governance.js";
4
7
  export * from "./src/feature.js";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@southwind-ai/shared",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "engines": {
@@ -0,0 +1,134 @@
1
+ import type { ISODateTime, PageResult } from "./primitives.js";
2
+
3
+ export type AiRuntimeReportRange = "day" | "month" | "retained";
4
+ export type AiRuntimeRunStatus =
5
+ | "accepted"
6
+ | "running"
7
+ | "awaiting-approval"
8
+ | "completed"
9
+ | "failed"
10
+ | "cancelled";
11
+ export type AiRuntimeAttemptOutcome =
12
+ | "running"
13
+ | "completed"
14
+ | "failed"
15
+ | "cancelled"
16
+ | "blocked"
17
+ | "abandoned";
18
+ export type AiRuntimeCacheStatus = "hit" | "miss" | "unknown";
19
+ export type AiRuntimeUsageSource =
20
+ | "provider-reported"
21
+ | "estimated"
22
+ | "unknown";
23
+
24
+ export interface AiRuntimeRunCounts {
25
+ total: number;
26
+ completed: number;
27
+ failed: number;
28
+ cancelled: number;
29
+ inProgress: number;
30
+ successRate: number | null;
31
+ }
32
+
33
+ export interface AiRuntimeCacheSummary {
34
+ hit: number;
35
+ miss: number;
36
+ unknown: number;
37
+ hitRate: number | null;
38
+ tokenRate: number | null;
39
+ coverageRate: number;
40
+ }
41
+
42
+ export interface AiRuntimeTokenSummary {
43
+ input: number | null;
44
+ output: number | null;
45
+ cachedInput: number | null;
46
+ reasoning: number | null;
47
+ total: number | null;
48
+ coverageRate: number;
49
+ }
50
+
51
+ export interface AiRuntimeModelUsageSummary {
52
+ deploymentKey: string;
53
+ model: string;
54
+ attempts: number;
55
+ inputTokens: number | null;
56
+ outputTokens: number | null;
57
+ cachedInputTokens: number | null;
58
+ reasoningTokens: number | null;
59
+ totalTokens: number | null;
60
+ unknownUsageCount: number;
61
+ }
62
+
63
+ export interface AiRuntimeActivityPoint {
64
+ date: string;
65
+ runs: number;
66
+ completed: number;
67
+ failed: number;
68
+ totalTokens: number | null;
69
+ }
70
+
71
+ export interface AiRuntimeReportSummary {
72
+ generatedAt: ISODateTime;
73
+ reportingAvailableFrom: ISODateTime | null;
74
+ retentionDays: number;
75
+ runs: AiRuntimeRunCounts;
76
+ cache: AiRuntimeCacheSummary;
77
+ tokens: AiRuntimeTokenSummary;
78
+ byModel: AiRuntimeModelUsageSummary[];
79
+ activity: AiRuntimeActivityPoint[];
80
+ }
81
+
82
+ export interface AiRuntimeActorSummary {
83
+ handle: string;
84
+ displayName: string;
85
+ username?: string;
86
+ }
87
+
88
+ export interface AiRuntimeRunUsage {
89
+ inputTokens: number | null;
90
+ outputTokens: number | null;
91
+ cachedInputTokens: number | null;
92
+ reasoningTokens: number | null;
93
+ totalTokens: number | null;
94
+ }
95
+
96
+ export interface AiRuntimeRunListItem {
97
+ runId: string;
98
+ operationKey: string;
99
+ actor: AiRuntimeActorSummary | null;
100
+ status: AiRuntimeRunStatus;
101
+ startedAt: ISODateTime | null;
102
+ finishedAt: ISODateTime | null;
103
+ durationMs: number | null;
104
+ attemptCount: number;
105
+ models: string[];
106
+ cacheStatus: AiRuntimeCacheStatus;
107
+ usage: AiRuntimeRunUsage;
108
+ }
109
+
110
+ export interface AiRuntimeAttemptDetail extends AiRuntimeRunUsage {
111
+ attemptId: string;
112
+ sequence: number;
113
+ toolRound: number;
114
+ deploymentKey: string;
115
+ model: string;
116
+ outcome: AiRuntimeAttemptOutcome;
117
+ cacheStatus: AiRuntimeCacheStatus;
118
+ usageSource: AiRuntimeUsageSource;
119
+ firstTokenLatencyMs: number | null;
120
+ durationMs: number | null;
121
+ safeErrorCode: string | null;
122
+ startedAt: ISODateTime;
123
+ finishedAt: ISODateTime | null;
124
+ }
125
+
126
+ export interface AiRuntimeRunDetail extends AiRuntimeRunListItem {
127
+ releaseId: string;
128
+ traceId: string;
129
+ safeErrorCode: string | null;
130
+ attempts: AiRuntimeAttemptDetail[];
131
+ }
132
+
133
+ export type AiRuntimeRunPage = PageResult<AiRuntimeRunListItem>;
134
+ export type AiRuntimeActorPage = PageResult<AiRuntimeActorSummary>;
@@ -18,12 +18,27 @@ export const WATERMARK_CONTENT_FIELDS = [
18
18
  ] as const;
19
19
  export type WatermarkContentField = (typeof WATERMARK_CONTENT_FIELDS)[number];
20
20
 
21
+ export const WATERMARK_OPACITY_RANGE = {
22
+ min: 3,
23
+ max: 30,
24
+ step: 1,
25
+ } as const;
26
+
27
+ export const WATERMARK_FONT_SIZE_RANGE = {
28
+ min: 12,
29
+ max: 32,
30
+ step: 1,
31
+ } as const;
32
+
21
33
  export interface PlatformWatermarkPolicy {
22
34
  enabled: boolean;
35
+ /** @deprecated 升级兼容字段,始终与 enabled 保持一致。 */
23
36
  businessPagesEnabled: boolean;
24
37
  density: WatermarkDensity;
25
38
  contentFields: WatermarkContentField[];
26
39
  customContent: string;
40
+ opacityPercent: number;
41
+ fontSize: number;
27
42
  }
28
43
 
29
44
  export const DEFAULT_PLATFORM_WATERMARK_POLICY: Readonly<PlatformWatermarkPolicy> =
@@ -33,4 +48,6 @@ export const DEFAULT_PLATFORM_WATERMARK_POLICY: Readonly<PlatformWatermarkPolicy
33
48
  density: "medium",
34
49
  contentFields: ["username", "displayName"],
35
50
  customContent: "",
51
+ opacityPercent: 8,
52
+ fontSize: 14,
36
53
  };
@@ -0,0 +1,201 @@
1
+ import { resolve } from "node:path";
2
+
3
+ export interface CommandOptions {
4
+ allowFailure?: boolean;
5
+ cwd?: string;
6
+ env?: Record<string, string | undefined>;
7
+ stdin?: string;
8
+ stdout?: "inherit" | "pipe";
9
+ stderr?: "inherit" | "pipe";
10
+ }
11
+
12
+ export interface CommandResult {
13
+ exitCode: number;
14
+ stdout: string;
15
+ stderr: string;
16
+ }
17
+
18
+ export const repositoryRoot = resolve(import.meta.dir, "../..");
19
+
20
+ export async function runCommand(
21
+ command: string[],
22
+ options: CommandOptions = {},
23
+ ): Promise<CommandResult> {
24
+ const child = Bun.spawn(command, {
25
+ cwd: options.cwd || repositoryRoot,
26
+ env: options.env ?? process.env,
27
+ stdin: options.stdin === undefined ? undefined : "pipe",
28
+ stdout: options.stdout || "pipe",
29
+ stderr: options.stderr || "pipe",
30
+ });
31
+ if (options.stdin !== undefined) {
32
+ child.stdin.write(options.stdin);
33
+ child.stdin.end();
34
+ }
35
+ const [stdout, stderr, exitCode] = await Promise.all([
36
+ child.stdout ? new Response(child.stdout).text() : "",
37
+ child.stderr ? new Response(child.stderr).text() : "",
38
+ child.exited,
39
+ ]);
40
+ if (exitCode !== 0 && !options.allowFailure) {
41
+ throw new Error(
42
+ `${command.join(" ")} failed (${exitCode})\n${stdout}${stderr}`,
43
+ );
44
+ }
45
+ return { exitCode, stdout: stdout.trim(), stderr: stderr.trim() };
46
+ }
47
+
48
+ export class PostgresRegressionHarness {
49
+ readonly container: string;
50
+ private port?: string;
51
+
52
+ constructor(prefix: string) {
53
+ this.container = `${prefix}-${crypto.randomUUID().slice(0, 8)}`;
54
+ }
55
+
56
+ async start(): Promise<void> {
57
+ await runCommand([
58
+ "docker",
59
+ "run",
60
+ "--rm",
61
+ "--detach",
62
+ "--name",
63
+ this.container,
64
+ "--env",
65
+ "POSTGRES_DB=windy",
66
+ "--env",
67
+ "POSTGRES_USER=windy",
68
+ "--env",
69
+ "POSTGRES_PASSWORD=windy",
70
+ "--publish",
71
+ "127.0.0.1::5432",
72
+ "postgres:17-alpine",
73
+ ]);
74
+ await this.waitUntilReady();
75
+ const portResult = await runCommand([
76
+ "docker",
77
+ "port",
78
+ this.container,
79
+ "5432/tcp",
80
+ ]);
81
+ this.port = portResult.stdout.match(/:(\d+)$/)?.[1];
82
+ if (!this.port) {
83
+ throw new Error(`无法解析 PostgreSQL 端口:${portResult.stdout}`);
84
+ }
85
+ }
86
+
87
+ databaseUrl(database = "windy"): string {
88
+ if (!this.port) throw new Error("PostgreSQL 容器尚未启动");
89
+ const url = new URL(`postgresql://127.0.0.1:${this.port}/${database}`);
90
+ url.username = "windy";
91
+ url.password = "windy";
92
+ return url.toString();
93
+ }
94
+
95
+ async createDatabase(database: string): Promise<void> {
96
+ await this.execute(`CREATE DATABASE ${quoteIdentifier(database)}`, "windy");
97
+ }
98
+
99
+ async execute(sql: string, database = "windy"): Promise<void> {
100
+ await this.psql(sql, database);
101
+ }
102
+
103
+ async query(sql: string, database = "windy"): Promise<string> {
104
+ return (await this.psql(sql, database)).stdout;
105
+ }
106
+
107
+ async migrate(
108
+ database = "windy",
109
+ allowFailure = false,
110
+ ): Promise<CommandResult> {
111
+ return runCommand(["bun", "run", "db:migrate"], {
112
+ allowFailure,
113
+ env: { ...process.env, DATABASE_URL: this.databaseUrl(database) },
114
+ });
115
+ }
116
+
117
+ async close(): Promise<void> {
118
+ await runCommand(["docker", "rm", "--force", this.container], {
119
+ allowFailure: true,
120
+ });
121
+ }
122
+
123
+ private async psql(sql: string, database: string): Promise<CommandResult> {
124
+ return runCommand(
125
+ [
126
+ "docker",
127
+ "exec",
128
+ "--interactive",
129
+ this.container,
130
+ "psql",
131
+ "--set",
132
+ "ON_ERROR_STOP=1",
133
+ "--username",
134
+ "windy",
135
+ "--dbname",
136
+ database,
137
+ "--tuples-only",
138
+ "--no-align",
139
+ ],
140
+ { stdin: sql },
141
+ );
142
+ }
143
+
144
+ private async waitUntilReady(): Promise<void> {
145
+ for (let attempt = 0; attempt < 60; attempt += 1) {
146
+ const [result, logs] = await Promise.all([
147
+ runCommand(
148
+ [
149
+ "docker",
150
+ "exec",
151
+ this.container,
152
+ "pg_isready",
153
+ "--username",
154
+ "windy",
155
+ "--dbname",
156
+ "windy",
157
+ ],
158
+ { allowFailure: true },
159
+ ),
160
+ runCommand(["docker", "logs", this.container], {
161
+ allowFailure: true,
162
+ }),
163
+ ]);
164
+ if (
165
+ result.exitCode === 0 &&
166
+ `${logs.stdout}\n${logs.stderr}`.includes(
167
+ "PostgreSQL init process complete; ready for start up.",
168
+ )
169
+ ) {
170
+ return;
171
+ }
172
+ await Bun.sleep(500);
173
+ }
174
+ throw new Error("PostgreSQL 未在 30 秒内就绪");
175
+ }
176
+ }
177
+
178
+ export function expectEqual(
179
+ actual: string,
180
+ expected: string,
181
+ label: string,
182
+ ): void {
183
+ if (actual !== expected) {
184
+ throw new Error(`${label}:期望 ${expected},实际 ${actual}`);
185
+ }
186
+ }
187
+
188
+ export function expect(condition: unknown, label: string): asserts condition {
189
+ if (!condition) throw new Error(label);
190
+ }
191
+
192
+ export function sqlLiteral(value: string): string {
193
+ return `'${value.replaceAll("'", "''")}'`;
194
+ }
195
+
196
+ function quoteIdentifier(value: string): string {
197
+ if (!/^[a-z][a-z0-9_]*$/.test(value)) {
198
+ throw new Error(`不安全的数据库标识符:${value}`);
199
+ }
200
+ return `"${value}"`;
201
+ }