create-windy 0.4.1 → 0.5.1

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 (174) hide show
  1. package/dist/cli.js +292 -125
  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/system/operations.test.ts +54 -0
  96. package/template/apps/server/src/system/operations.ts +23 -1
  97. package/template/apps/server/src/system/seed.test.ts +4 -0
  98. package/template/apps/server/src/system/system-resource-monitoring.test.ts +82 -0
  99. package/template/apps/server/src/system/system-resource-monitoring.ts +300 -0
  100. package/template/apps/web/src/layout/AppSidebar.vue +6 -1
  101. package/template/apps/web/src/layout/AppSidebar.webtest.ts +2 -0
  102. package/template/apps/web/src/pages/auth/LoginPage.vue +6 -1
  103. package/template/apps/web/src/pages/settings/BrandingSettingsSection.vue +20 -3
  104. package/template/apps/web/src/pages/settings/BrandingSettingsSection.webtest.ts +80 -0
  105. package/template/apps/web/src/pages/system/AiRuntimePage.vue +129 -0
  106. package/template/apps/web/src/pages/system/SystemOperationsPage.vue +2 -1
  107. package/template/apps/web/src/pages/system/ai-runtime-presenter.ts +60 -0
  108. package/template/apps/web/src/pages/system/ai-runtime-presenter.webtest.ts +48 -0
  109. package/template/apps/web/src/pages/system/audit-time-range.ts +34 -2
  110. package/template/apps/web/src/pages/system/components/AuditLogFilters.vue +4 -3
  111. package/template/apps/web/src/pages/system/components/AuditLogFilters.webtest.ts +26 -1
  112. package/template/apps/web/src/pages/system/components/OperationGpuMonitor.vue +98 -0
  113. package/template/apps/web/src/pages/system/components/OperationGpuMonitor.webtest.ts +61 -0
  114. package/template/apps/web/src/pages/system/components/OperationServiceMonitor.vue +53 -0
  115. package/template/apps/web/src/pages/system/components/OperationServiceMonitor.webtest.ts +20 -1
  116. package/template/apps/web/src/pages/system/components/SystemResourcePage.webtest.ts +14 -1
  117. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeActivityChart.vue +85 -0
  118. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeCharts.webtest.ts +82 -0
  119. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeFilters.vue +98 -0
  120. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeFilters.webtest.ts +27 -0
  121. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunDetailDialog.vue +168 -0
  122. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeRunTable.vue +130 -0
  123. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeSummaryCards.vue +82 -0
  124. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeSummaryCards.webtest.ts +102 -0
  125. package/template/apps/web/src/pages/system/components/ai-runtime/AiRuntimeTokenByModelChart.vue +101 -0
  126. package/template/apps/web/src/pages/system/composables/useAiRuntimeReport.ts +185 -0
  127. package/template/apps/web/src/pages/system/composables/useAiRuntimeReport.webtest.ts +158 -0
  128. package/template/apps/web/src/pages/system/composables/useSystemResource.ts +21 -7
  129. package/template/apps/web/src/router/error-navigation.ts +22 -0
  130. package/template/apps/web/src/router/index.ts +12 -23
  131. package/template/apps/web/src/router/platform-admin-route-bindings.ts +4 -0
  132. package/template/apps/web/src/services/ai-runtime-api.ts +164 -0
  133. package/template/apps/web/src/services/ai-runtime-api.webtest.ts +111 -0
  134. package/template/apps/web/src/services/operations-api.ts +28 -0
  135. package/template/docker-compose.agent-debug.yml +1 -1
  136. package/template/docs/architecture/ai-runtime.md +2 -1
  137. package/template/docs/architecture/module-host.md +3 -0
  138. package/template/docs/platform/agent-run-attestation.md +65 -0
  139. package/template/docs/platform/agent-runtime-observability.md +135 -0
  140. package/template/docs/platform/agent-runtime.md +47 -3
  141. package/template/docs/platform/operations-overview.md +13 -0
  142. package/template/docs/platform/platform-authentication.md +4 -3
  143. package/template/packages/config/package.json +1 -1
  144. package/template/packages/database/drizzle/0045_tiny_cassandra_nova.sql +65 -0
  145. package/template/packages/database/drizzle/0046_tranquil_living_mummy.sql +6 -0
  146. package/template/packages/database/drizzle/0047_oval_luke_cage.sql +18 -0
  147. package/template/packages/database/drizzle/meta/0045_snapshot.json +8814 -0
  148. package/template/packages/database/drizzle/meta/0046_snapshot.json +8820 -0
  149. package/template/packages/database/drizzle/meta/0047_snapshot.json +8835 -0
  150. package/template/packages/database/drizzle/meta/_journal.json +21 -0
  151. package/template/packages/database/package.json +1 -1
  152. package/template/packages/database/src/agent-runtime-schema.test.ts +54 -0
  153. package/template/packages/database/src/schema/agent-runtime.ts +114 -0
  154. package/template/packages/jobs/package.json +1 -1
  155. package/template/packages/modules/package.json +1 -1
  156. package/template/packages/modules/src/system-admin-routes.ts +10 -0
  157. package/template/packages/modules/src/system-admin-ui-catalog.ts +1 -1
  158. package/template/packages/modules/src/system-api-control-plane.ts +17 -1
  159. package/template/packages/modules/src/system-audit-actions.ts +10 -0
  160. package/template/packages/modules/src/system-features.ts +8 -0
  161. package/template/packages/modules/src/system-module-catalog.test.ts +35 -0
  162. package/template/packages/modules/src/system-module-catalog.ts +15 -4
  163. package/template/packages/modules/src/system-modules-access.test.ts +69 -0
  164. package/template/packages/modules/src/system-modules.ts +13 -0
  165. package/template/packages/modules/src/system-permissions.ts +2 -0
  166. package/template/packages/server-sdk/index.ts +11 -0
  167. package/template/packages/server-sdk/package.json +2 -1
  168. package/template/packages/server-sdk/src/ai-operation-port.ts +5 -0
  169. package/template/packages/server-sdk/src/debug-session-provider.ts +63 -0
  170. package/template/packages/server-sdk/src/module-host.ts +5 -0
  171. package/template/packages/shared/index.ts +3 -0
  172. package/template/packages/shared/package.json +1 -1
  173. package/template/packages/shared/src/ai-runtime-report.ts +134 -0
  174. package/template/scripts/lib/postgres-regression.ts +201 -0
@@ -0,0 +1,164 @@
1
+ import { apiRequest } from "./http";
2
+ import type {
3
+ AiRuntimeActorSummary,
4
+ AiRuntimeAttemptDetail,
5
+ AiRuntimeReportSummary,
6
+ AiRuntimeRunDetail as RuntimeRunDetail,
7
+ AiRuntimeRunListItem,
8
+ PageResult,
9
+ } from "@southwind-ai/shared";
10
+
11
+ export type AiRuntimeRange = "day" | "month" | "retained";
12
+
13
+ export interface AiRuntimeReportQuery {
14
+ readonly range: AiRuntimeRange;
15
+ readonly actorHandle?: string;
16
+ }
17
+
18
+ export type AiRuntimeSummary = AiRuntimeReportSummary;
19
+ export type AiRuntimeModelUsage = AiRuntimeReportSummary["byModel"][number];
20
+ export type AiRuntimeActivity = AiRuntimeReportSummary["activity"][number];
21
+
22
+ export interface AiRuntimeRunItem {
23
+ readonly runId: string;
24
+ readonly operationKey: string;
25
+ readonly actor: AiRuntimeActor | null;
26
+ readonly status: string;
27
+ readonly startedAt?: string;
28
+ readonly finishedAt?: string;
29
+ readonly durationMs?: number;
30
+ readonly attempts: number;
31
+ readonly model?: string;
32
+ readonly totalTokens: number | null;
33
+ readonly cacheStatus: "hit" | "miss" | "unknown";
34
+ readonly traceId?: string;
35
+ readonly safeErrorCode?: string;
36
+ }
37
+
38
+ export interface AiRuntimeAttempt {
39
+ readonly sequence: number;
40
+ readonly deploymentKey: string;
41
+ readonly requestedModel: string;
42
+ readonly reportedModel?: string;
43
+ readonly outcome: string;
44
+ readonly inputTokens: number | null;
45
+ readonly outputTokens: number | null;
46
+ readonly cachedInputTokens: number | null;
47
+ readonly reasoningTokens: number | null;
48
+ readonly totalTokens: number | null;
49
+ readonly cacheStatus: "hit" | "miss" | "unknown";
50
+ readonly firstTokenLatencyMs?: number;
51
+ readonly durationMs?: number;
52
+ readonly safeErrorCode?: string;
53
+ readonly startedAt: string;
54
+ readonly finishedAt?: string;
55
+ }
56
+
57
+ export interface AiRuntimeRunDetail extends AiRuntimeRunItem {
58
+ readonly releaseId?: string;
59
+ readonly attemptItems: readonly AiRuntimeAttempt[];
60
+ }
61
+
62
+ export type AiRuntimeActor = AiRuntimeActorSummary;
63
+ export type AiRuntimePage<T> = PageResult<T>;
64
+
65
+ export function getAiRuntimeSummary(query: AiRuntimeReportQuery) {
66
+ return apiRequest<AiRuntimeSummary>(
67
+ `/system/ai-runtime/summary?${reportParams(query)}`,
68
+ );
69
+ }
70
+
71
+ export function listAiRuntimeRuns(
72
+ query: AiRuntimeReportQuery & { page: number; pageSize: number },
73
+ ): Promise<AiRuntimePage<AiRuntimeRunItem>> {
74
+ const params = reportParams(query);
75
+ params.set("page", String(query.page));
76
+ params.set("pageSize", String(query.pageSize));
77
+ return apiRequest<PageResult<AiRuntimeRunListItem>>(
78
+ `/system/ai-runtime/runs?${params}`,
79
+ ).then((result) => ({
80
+ ...result,
81
+ items: result.items.map(runItem),
82
+ }));
83
+ }
84
+
85
+ export function getAiRuntimeRun(
86
+ runId: string,
87
+ signal?: AbortSignal,
88
+ ): Promise<AiRuntimeRunDetail> {
89
+ return apiRequest<RuntimeRunDetail>(
90
+ `/system/ai-runtime/runs/${encodeURIComponent(runId)}`,
91
+ signal ? { signal } : {},
92
+ ).then(runDetail);
93
+ }
94
+
95
+ export function listAiRuntimeActors(query = "", page = 1, pageSize = 50) {
96
+ const params = new URLSearchParams({
97
+ page: String(page),
98
+ pageSize: String(pageSize),
99
+ });
100
+ if (query.trim()) params.set("q", query.trim());
101
+ return apiRequest<PageResult<AiRuntimeActor>>(
102
+ `/system/ai-runtime/actors?${params}`,
103
+ );
104
+ }
105
+
106
+ function reportParams(query: AiRuntimeReportQuery) {
107
+ const params = new URLSearchParams({ range: query.range });
108
+ if (query.actorHandle) params.set("actorHandle", query.actorHandle);
109
+ return params;
110
+ }
111
+
112
+ function runItem(value: AiRuntimeRunListItem): AiRuntimeRunItem {
113
+ return {
114
+ runId: value.runId,
115
+ operationKey: value.operationKey,
116
+ actor: value.actor,
117
+ status: value.status,
118
+ ...(value.startedAt ? { startedAt: value.startedAt } : {}),
119
+ ...(value.finishedAt ? { finishedAt: value.finishedAt } : {}),
120
+ ...(value.durationMs === null ? {} : { durationMs: value.durationMs }),
121
+ attempts: value.attemptCount,
122
+ model: modelLabel(value.models),
123
+ totalTokens: value.usage.totalTokens,
124
+ cacheStatus: value.cacheStatus,
125
+ };
126
+ }
127
+
128
+ function runDetail(value: RuntimeRunDetail): AiRuntimeRunDetail {
129
+ return {
130
+ ...runItem(value),
131
+ releaseId: value.releaseId,
132
+ traceId: value.traceId,
133
+ ...(value.safeErrorCode ? { safeErrorCode: value.safeErrorCode } : {}),
134
+ attemptItems: value.attempts.map(attemptItem),
135
+ };
136
+ }
137
+
138
+ function attemptItem(value: AiRuntimeAttemptDetail): AiRuntimeAttempt {
139
+ return {
140
+ sequence: value.sequence,
141
+ deploymentKey: value.deploymentKey,
142
+ requestedModel: value.model,
143
+ outcome: value.outcome,
144
+ inputTokens: value.inputTokens,
145
+ outputTokens: value.outputTokens,
146
+ cachedInputTokens: value.cachedInputTokens,
147
+ reasoningTokens: value.reasoningTokens,
148
+ totalTokens: value.totalTokens,
149
+ cacheStatus: value.cacheStatus,
150
+ ...(value.firstTokenLatencyMs === null
151
+ ? {}
152
+ : { firstTokenLatencyMs: value.firstTokenLatencyMs }),
153
+ ...(value.durationMs === null ? {} : { durationMs: value.durationMs }),
154
+ ...(value.safeErrorCode ? { safeErrorCode: value.safeErrorCode } : {}),
155
+ startedAt: value.startedAt,
156
+ ...(value.finishedAt ? { finishedAt: value.finishedAt } : {}),
157
+ };
158
+ }
159
+
160
+ function modelLabel(models: readonly string[]) {
161
+ if (models.length === 0) return undefined;
162
+ if (models.length === 1) return models[0];
163
+ return `${models[0]} 等 ${models.length} 个`;
164
+ }
@@ -0,0 +1,111 @@
1
+ import { beforeEach, describe, expect, test, vi } from "vitest";
2
+
3
+ const mocks = vi.hoisted(() => ({ apiRequest: vi.fn() }));
4
+ vi.mock("./http", () => mocks);
5
+
6
+ import {
7
+ getAiRuntimeRun,
8
+ getAiRuntimeSummary,
9
+ listAiRuntimeActors,
10
+ listAiRuntimeRuns,
11
+ } from "./ai-runtime-api";
12
+
13
+ describe("AI Runtime 报表 API", () => {
14
+ beforeEach(() => mocks.apiRequest.mockReset());
15
+
16
+ test("汇总和列表都传递有界范围与 Actor 筛选", async () => {
17
+ mocks.apiRequest.mockResolvedValueOnce({}).mockResolvedValueOnce({
18
+ items: [
19
+ {
20
+ runId: "run_1",
21
+ operationKey: "customer.answer",
22
+ actor: null,
23
+ status: "completed",
24
+ startedAt: "2026-07-31T00:00:00.000Z",
25
+ finishedAt: null,
26
+ durationMs: null,
27
+ attemptCount: 2,
28
+ models: ["gpt-a", "gpt-b"],
29
+ cacheStatus: "unknown",
30
+ usage: {
31
+ inputTokens: null,
32
+ outputTokens: null,
33
+ cachedInputTokens: null,
34
+ reasoningTokens: null,
35
+ totalTokens: null,
36
+ },
37
+ },
38
+ ],
39
+ total: 1,
40
+ page: 2,
41
+ pageSize: 20,
42
+ });
43
+
44
+ await getAiRuntimeSummary({
45
+ range: "month",
46
+ actorHandle: "actor_opaque",
47
+ });
48
+ const page = await listAiRuntimeRuns({
49
+ range: "month",
50
+ actorHandle: "actor_opaque",
51
+ page: 2,
52
+ pageSize: 20,
53
+ });
54
+
55
+ expect(mocks.apiRequest).toHaveBeenNthCalledWith(
56
+ 1,
57
+ "/system/ai-runtime/summary?range=month&actorHandle=actor_opaque",
58
+ );
59
+ expect(mocks.apiRequest).toHaveBeenNthCalledWith(
60
+ 2,
61
+ "/system/ai-runtime/runs?range=month&actorHandle=actor_opaque&page=2&pageSize=20",
62
+ );
63
+ expect(page.items[0]).toMatchObject({
64
+ attempts: 2,
65
+ model: "gpt-a 等 2 个",
66
+ totalTokens: null,
67
+ cacheStatus: "unknown",
68
+ });
69
+ });
70
+
71
+ test("Run 与 Actor 标识经过 URL 编码", async () => {
72
+ mocks.apiRequest
73
+ .mockResolvedValueOnce({
74
+ runId: "run/with space",
75
+ operationKey: "customer.answer",
76
+ actor: null,
77
+ status: "completed",
78
+ startedAt: null,
79
+ finishedAt: null,
80
+ durationMs: null,
81
+ attemptCount: 0,
82
+ models: [],
83
+ cacheStatus: "unknown",
84
+ usage: {
85
+ inputTokens: null,
86
+ outputTokens: null,
87
+ cachedInputTokens: null,
88
+ reasoningTokens: null,
89
+ totalTokens: null,
90
+ },
91
+ releaseId: "release_1",
92
+ traceId: "trace_1",
93
+ safeErrorCode: null,
94
+ attempts: [],
95
+ })
96
+ .mockResolvedValueOnce({ items: [], total: 0, page: 1, pageSize: 50 });
97
+
98
+ await getAiRuntimeRun("run/with space");
99
+ await listAiRuntimeActors("张 三", 1, 50);
100
+
101
+ expect(mocks.apiRequest).toHaveBeenNthCalledWith(
102
+ 1,
103
+ "/system/ai-runtime/runs/run%2Fwith%20space",
104
+ {},
105
+ );
106
+ expect(mocks.apiRequest).toHaveBeenNthCalledWith(
107
+ 2,
108
+ "/system/ai-runtime/actors?page=1&pageSize=50&q=%E5%BC%A0+%E4%B8%89",
109
+ );
110
+ });
111
+ });
@@ -32,6 +32,34 @@ export interface OperationSnapshot {
32
32
  totalBytes: number;
33
33
  usagePercent: number;
34
34
  };
35
+ cpu: {
36
+ status: "available";
37
+ logicalCores: number;
38
+ hostUsagePercent: number | null;
39
+ processUsagePercent: number | null;
40
+ loadAverage1m: number | null;
41
+ message?: string;
42
+ };
43
+ };
44
+ gpuMonitor: {
45
+ status: "available" | "not-detected" | "unavailable";
46
+ provider: "NVIDIA";
47
+ message: string;
48
+ devices: Array<{
49
+ index: number;
50
+ uuid: string;
51
+ name: string;
52
+ usagePercent: number | null;
53
+ memoryUsedBytes: number | null;
54
+ memoryTotalBytes: number | null;
55
+ memoryUsagePercent: number | null;
56
+ temperatureCelsius: number | null;
57
+ processes: Array<{
58
+ pid: number;
59
+ name: string;
60
+ usedMemoryBytes: number | null;
61
+ }>;
62
+ }>;
35
63
  };
36
64
  databaseMonitor: {
37
65
  status: "healthy" | "not-configured" | "unavailable";
@@ -25,7 +25,7 @@ services:
25
25
  "8000",
26
26
  "--no-reload",
27
27
  "--session_service_uri",
28
- "memory://",
28
+ "windy-debug://v1",
29
29
  "--artifact_service_uri",
30
30
  "memory://",
31
31
  "--logo-text",
@@ -665,7 +665,8 @@ Tool 和终态摘要。业务 Permission、Scope、Execution Grant、Provider
665
665
  Token。项目配置只包含 Operation Key 与当前启用的真实开发数据用户 ID,不能重复或扩大
666
666
  Manifest 的权限、Scope 与 Tool 列表。数据用户用于复用其成员关系和当前 Scope。开发 Wrapper
667
667
  创建的核心主体仍是 `service_adk_debug`,权限只取该用户已有权限与 Operation/allowed
668
- Tools 闭包的精确交集,并且只能调用 canonical Run API;审计不会把它记录成普通用户会话。
668
+ Tools 闭包的精确交集,并且只能调用 canonical Run API 与只读 debug-session GET;
669
+ 审计不会把它记录成普通用户会话。
669
670
 
670
671
  该 Adapter 证明真实业务执行链,不等于把另一进程内的完整 ADK Agent/Workflow 图装入
671
672
  原生 ADK Web。内部节点、Prompt 版本和 replay 若要可视化,必须通过另一个版本化协议
@@ -11,6 +11,9 @@
11
11
  - `registerToolHandlers()`:为 Manifest `tools` 已声明的 Agent Tool 注册类型化 JSON 执行体,输入输出 Schema、`scopeMode` 与 Handler 均接入双向校验;
12
12
  - `registerRolePresets()`:注册角色预设,`permissionKeys` 必须属于本模块 Manifest 权限声明;预设并入内置角色同步(不存在则创建、漂移则非破坏性合并),不改变 4 个内置角色语义;
13
13
  - `registerSearchProviders()`:注册 Manifest `providers` 已声明的搜索 Provider;
14
+ - `registerDebugSessionProviders()`:为 developer-only ADK Web 注册业务会话的只读
15
+ V1 投影;Provider 必须绑定本模块 Agent Operation,并复用该 Operation 的 Feature
16
+ 与 Permission,业务 `sourceId` 不会越过 Host;
14
17
  - `registerUploadPolicy()`:按业务用途注册大小、分片、MIME、扩展名和签名策略;
15
18
  - `registerResourceFileAccessPolicies()`:注册本模块业务资源到平台文件的受限读取
16
19
  Resolver;purpose 必须来自当前模块或 Manifest 显式依赖模块,resourceType、
@@ -0,0 +1,65 @@
1
+ # Agent Run 输入证明
2
+
3
+ 本文说明 Windy 如何把一个 canonical Agent Run 绑定到发起时的受治理输入,以及业务模块
4
+ 如何在后续请求中验证这项绑定。该能力只提供平台级证明,不替业务模块决定会话、案件或
5
+ 消息的业务归属。
6
+
7
+ ## 平台契约
8
+
9
+ Agent Run 启动前,Facade 已完成 Operation、Actor、Scope、DLP 与输入 Schema 治理。
10
+ 授权存储在签发 Run binding 时,对 Provider allowlist 投影中保留原值的输入执行稳定
11
+ JSON canonicalization:
12
+
13
+ - object key 按字典序递归排序;
14
+ - array 保留原顺序;
15
+ - 只接受 JSON 可表达的有限数值;
16
+ - canonical JSON 先计算 SHA-256,再将 digest、binding token hash 与服务端 secret
17
+ 一起计算 HMAC commitment;
18
+ - 数据库只保存 commitment,不保存原始输入。
19
+
20
+ `ModuleAiOperationPort.verifyAgentRun` 同时验证模块 Operation 所有权、Actor/Scope 的
21
+ Run binding,以及调用方重建输入的 commitment。任一条件不匹配都 fail closed,业务层
22
+ 不能从响应中区分 Run 不存在、越权或输入不一致。
23
+
24
+ 同一 idempotency key 只有在 DLP 前 allowlist input commitment 相同的情况下才能复用
25
+ 既有 Run;有损 DLP 结果只用于 Handler 与 Provider 出网,不能作为 exact-input 证明。
26
+ 相同 key 携带不同输入会被拒绝,避免把一个已授权 Run 重新解释成另一项工作,也避免
27
+ 不同原文脱敏为相同占位符后发生承诺碰撞。
28
+
29
+ ## 兼容迁移
30
+
31
+ `agent_run_bindings.input_digest_commitment` 是必填的 64 位十六进制字段。迁移会给旧行写入
32
+ 全零 sentinel,随后移除数据库默认值:
33
+
34
+ - 旧 binding 在原 TTL 内仍可按既有规则读取 result、events 或 cancel;
35
+ - 全零 sentinel 永远不能通过 `verifyAgentRun`;
36
+ - 新 binding 必须由应用写入真实 commitment。
37
+
38
+ 这允许部署期间保持已有 Run 的普通生命周期,同时不会把迁移前未承诺输入的 Run 误认成
39
+ 可验证业务证据。
40
+
41
+ ## Canonical result 状态
42
+
43
+ Module Host 将 Runtime 结果状态转换为稳定错误语义:
44
+
45
+ - `409 RUN_CONFLICT`:Run 尚未完成;
46
+ - `409 RUN_CANCELLED` 或 `409 RUNTIME_UNAVAILABLE`:Run 已进入 canonical 失败终态;
47
+ - `5xx`:Runtime 当前不可用,不能据此推断 Run 已失败;
48
+ - `400/404/422`:请求或 Run 无效;
49
+ - `403`:无权访问。
50
+
51
+ 业务持久化只能把 canonical completed output 或明确的 canonical failure 记为终态。
52
+ 网络错误、Runtime 5xx 和未知 409 必须保持可重试,不能伪造终态。
53
+
54
+ ## 业务模块职责
55
+
56
+ 平台不会接受浏览器声明的业务 scope、会话历史或最终输出。业务模块需要:
57
+
58
+ 1. 从自己的持久化数据重建发起 Run 时的精确输入;
59
+ 2. 调用 `verifyAgentRun` 后再保存“已验证”标记;
60
+ 3. 从服务端 canonical result 保存输出;
61
+ 4. 对迁移前或未验证的业务记录 fail closed;
62
+ 5. 对回放、反馈、摘要和调试投影继续执行领域权限与数据治理。
63
+
64
+ 因此,Windy 提供通用密码学绑定和 Runtime 状态语义;产品仓库保留业务输入重建、授权
65
+ 范围派生与可信记录生命周期。
@@ -0,0 +1,135 @@
1
+ # AI Runtime 用量与运行报表
2
+
3
+ `system.ai-runtime` 为 `system.agent` 提供运行事实、模型用量和缓存覆盖的管理面。它读取
4
+ canonical Agent Run 与每次 Provider Attempt 的独立报表投影,不把管理报表变成新的
5
+ 执行入口,也不以报表写入结果改写 canonical Run 终态。
6
+
7
+ ## 数据边界
8
+
9
+ Agent Server 在 Run 接受、开始、终止以及每次模型或 Tool round 的 Provider Attempt
10
+ 边界写入以下事实:
11
+
12
+ - Run:Operation Key、Release ID、Trace ID、Actor/部门范围标识、状态、开始/结束时间、
13
+ 时长与安全错误码。
14
+ - Attempt:序号、Tool round、Deployment Key、请求模型、Provider 返回模型、状态、
15
+ 首 Token 延迟、时长与安全错误码。Provider 调用期间状态为 `running`;进程恢复时,
16
+ 上一轮遗留的 `running` Attempt 会以恢复时间结束为 `abandoned`。
17
+ - Provider 用量:输入、输出、缓存输入、reasoning 与总 Token;每项无法确认时保持
18
+ `null`,不会用 `0` 伪装为已知事实。
19
+ - 覆盖状态:`provider-reported`、`estimated` 或 `unknown`,以及缓存
20
+ `hit`、`miss` 或 `unknown`。
21
+
22
+ 报表表不保存 Prompt、输出正文、Tool 参数/结果、Artifact 内容、Credential、Secret 或
23
+ Provider 原始响应。Actor ID 和部门 ID 仅用于 Agent Server 与 Server 之间的内部范围
24
+ 过滤;浏览器 DTO 只得到经过当前用户目录重新解析的业务可读 Actor 摘要与随机化的
25
+ opaque handle,不包含平台 Actor 主键。handle 由 Server 使用内部密钥派生的
26
+ AES-GCM key 签发并在每次筛选时校验,篡改、换密钥或越出当前数据范围都会 fail closed。
27
+
28
+ OpenAI-compatible Provider 的 `cached_tokens` 大于同一 Attempt 的
29
+ `prompt_tokens` 时,该缓存事实被视为不可信并回落为 `unknown`,不会截断为 100%。
30
+
31
+ ## 指标口径
32
+
33
+ 管理面提供滚动 `24 小时`、滚动 `30 天`和当前留存期三档范围:
34
+
35
+ - 成功率 = `completed / (completed + failed)`;取消与进行中 Run 不进入分母。
36
+ - Run 数、成功率及 Run 活动日按 `Run.created_at` 落入范围。
37
+ - Token、缓存、模型和首 Token 延迟按 `Attempt.started_at` 落入范围;它们可以来自
38
+ 范围外创建、但在范围内实际调用 Provider 的长 Run。
39
+ - 只有已有 `finished_at` 的 Attempt 进入汇总分母;详情仍实时展示 `running` Attempt。
40
+ - Attempt 缓存命中率 = `hit / (hit + miss)`;`unknown` 不进入分母。
41
+ - 缓存覆盖率 = `(hit + miss) / 已结束 Attempt`。
42
+ - 总 Token 覆盖率 = `total_tokens` 已知的 Attempt 数 / 已结束 Attempt;只上报输入
43
+ Token 不会让总量覆盖率变成 100%。
44
+ - 缓存 Token 比率只纳入同一 Attempt 中输入 Token 与缓存输入 Token 都已知的事实;其
45
+ 配对输入 Token 总数大于 0 时才计算,缓存字段未知不能按零进入分子。
46
+ - `reportingAvailableFrom` 取当前查询中 Run 创建时间与已结束 Attempt 开始时间的最早
47
+ 可见事实;只有两者都为空时才为 `null`。无有效分母的比率为 `null`。
48
+ - 活动趋势按 UTC 日历日合并 Run 创建日与 Attempt 调用日,不代表浏览器所在时区的
49
+ 自然日;某日只要存在一个总 Token 未知的 Attempt,该日 `totalTokens` 就保持
50
+ `null`,不会把部分已知下界展示为完整日总量。
51
+
52
+ 汇总中的 Token 数字是已知事实之和;必须结合覆盖率读取,不能把部分覆盖误解成完整
53
+ 成本。有 Attempt 但某一类 Token 完全未上报时,该聚合字段保持 `null`;范围内没有
54
+ Attempt 时聚合值为真实的 `0`。当前版本不根据 Token 猜测金额,也不把未知字段补成零。
55
+
56
+ ## 权限、范围与审计
57
+
58
+ 浏览器只访问 Server 的受管接口:
59
+
60
+ ```text
61
+ GET /api/system/ai-runtime/summary
62
+ GET /api/system/ai-runtime/runs
63
+ GET /api/system/ai-runtime/runs/:runId
64
+ GET /api/system/ai-runtime/actors
65
+ ```
66
+
67
+ 四条接口同时要求 Feature `system.ai-runtime` 与敏感披露 Permission
68
+ `system.ai-runtime.read`。开发角色不会自动获得该权限;超级管理员或客户显式授权的
69
+ 报表角色才可访问。Server 将当前 Actor 的数据范围转换为显式的 Actor/部门 allowlist
70
+ 后传给 Agent Server;无法形成可执行范围时使用 `none` 并 fail closed。浏览器通过
71
+ `actorHandle` 筛选,Server 验证并解析为内部 Actor ID 后还必须与当前范围取交集。
72
+
73
+ 详情查询先取得内部范围字段,再由 Server 校验对象级范围;越权与不存在统一返回 404。
74
+ 范围校验通过后,Server 删除 Actor ID 和部门 ID,并通过用户目录投影显示名和新的
75
+ opaque handle。报表与列表读取写入关键审计 `agent.runtime.report.read`,详情读取写入
76
+ `agent.runtime.run.read`。
77
+
78
+ ADK Web 的 canonical bridge 仍以专用调试服务身份调用平台,但报表归属使用
79
+ `toModuleActor(context.actor)` 后的真实数据用户,使开发调试用量进入正确的业务范围,
80
+ 而不是泄露或冒充普通登录会话。
81
+
82
+ ## Agent Server 内部接口与指标
83
+
84
+ Server 使用 `AGENT_SERVER_INTERNAL_TOKEN` 访问:
85
+
86
+ ```text
87
+ GET /api/internal/ai-runtime-report/summary
88
+ GET /api/internal/ai-runtime-report/runs
89
+ GET /api/internal/ai-runtime-report/runs/:runId
90
+ ```
91
+
92
+ 汇总和列表必须显式发送 `scopeMode=all|bounded|none`。`bounded` 可重复发送
93
+ `scopeActorId` 与 `scopeDepartmentId`;默认 `none` 不返回任何 Run。详情接口只返回
94
+ 内部 DTO,不能直接暴露给浏览器。
95
+
96
+ `GET /metrics` 只供 Agent Server 内网监控链路抓取,不应通过公网或浏览器路由暴露,并且
97
+ 仅使用低基数标签:
98
+
99
+ - `southwind_agent_runtime_runs_total{outcome}`
100
+ - `southwind_agent_runtime_attempts_total{outcome}`
101
+ - `southwind_agent_runtime_cache_attempts_total{status}`
102
+ - `southwind_agent_runtime_usage_attempts_total{source}`
103
+ - `southwind_agent_runtime_tokens_total{kind,source}`
104
+ - `southwind_agent_runtime_reporting_failures_total{stage}`
105
+
106
+ Prometheus 标签禁止加入 Run ID、Actor、部门、Operation、模型名或错误正文。终态报表写入
107
+ 失败会记录日志与 `stage="run_terminal"` 计数,但 canonical Run 已完成后不会被改写为
108
+ 失败。`approval.required` 把非终态报表切换为 `awaiting-approval`,
109
+ `approval.resolved` 切回 `running`;任何迟到的审批事件都不能让终态回退。Run 与
110
+ Attempt 的所有报表写入都是旁路 best-effort;故障按 `run_ensure`、`run_start`、
111
+ `run_status`、`run_terminal`、`attempt_start` 或 `attempt_terminal` 计数,不会中断
112
+ canonical Run 或 Provider 请求。Attempt 开始写入失败时不再尝试写其终态,因此报表
113
+ 覆盖率必须与 reporting failure 指标一起判断。
114
+
115
+ 终态投影始终在 canonical mutation 后重新读取 Run:事件/输出存储上限或
116
+ complete/cancel 竞争可能改变请求写入的终态,报表只接受 canonical Store 实际持久化的
117
+ 结果。Provider 已经返回完整响应后,即使 Tool 校验、取消或治理后处理把 Attempt 标为
118
+ `blocked`、`cancelled` 或 `failed`,已收到的模型、Token、缓存和首 Token 延迟仍会保留。
119
+
120
+ ## 持久化与留存
121
+
122
+ 生产配置 `AGENT_DATABASE_URL` 时,Agent Server 使用 PostgreSQL 表
123
+ `agent_runtime_report_runs` 与 `agent_runtime_report_attempts`。未配置数据库的本地
124
+ 运行使用进程内存实现,只适合开发与测试;重启后历史会丢失。
125
+
126
+ `AI_RUNTIME_REPORT_RETENTION_DAYS` 控制报表留存,默认 `90`,允许 `1..3650`。
127
+ PostgreSQL 实现在 `ensure_run` 接受新 Run 时清理已过期行;该设置不改变 canonical Run
128
+ Store 的留存策略。生产启动必须把同一个 Report Store 实例同时注入 Engine 与
129
+ `AgentRunService`,保证 Attempt 与 Run 终态进入同一投影和同一组指标。
130
+
131
+ PostgreSQL 汇总在数据库内分别完成 Run、Attempt、模型和 UTC 日历日聚合,Attempt
132
+ 查询使用 `started_at` 索引及当前范围、Actor/部门 scope 约束;活动查询分别聚合范围内
133
+ Run 与 Attempt 后再合并日期,不会先聚合整张 Attempt 表。返回量只随模型数与日期数
134
+ 增长;不会把留存期内全部 Run/Attempt 拉回 Agent Server。运行明细仍按页读取,并只为
135
+ 当前页加载 Attempt。
@@ -228,9 +228,9 @@ Operation Key 与真实开发数据用户注入 Windy-owned `docker-compose.agen
228
228
 
229
229
  - `create-windy` 自动生成独立随机 `ADK_DEBUG_PLATFORM_TOKEN`,无需复制登录 Token;
230
230
  - Server 只在 `NODE_ENV=development` 且加载调试 Compose Wrapper 时创建专用
231
- `service_adk_debug` 身份;该 Token 只在 canonical Run 路径生效,不能访问 Foundation、
232
- Admin 或其它 Server API;即使与普通会话 Token 误碰撞也被视为保留调试凭据,不会
233
- 回退普通认证;
231
+ `service_adk_debug` 身份;该 Token 只在 canonical Run 路径和只读 debug-session
232
+ GET 路径生效,不能访问 Foundation、Admin 或其它 Server API;即使与普通会话 Token
233
+ 误碰撞也被视为保留调试凭据,不会回退普通认证;
234
234
  - Server 每次从用户目录解析 `dataActorId`,复用该用户当前 Scope 和业务成员 ID;只在
235
235
  用户本身拥有完整权限闭包时,向 Module 投影该真实用户。核心 Run、Token 和审计主体仍
236
236
  是 `service_adk_debug`,不会冒充普通用户会话;
@@ -250,6 +250,47 @@ Operation Key 与真实开发数据用户注入 Windy-owned `docker-compose.agen
250
250
  完整的 Prompt/Agent/Workflow 节点图。完整 workflow replay 需要另行定义版本化调试
251
251
  协议,不能从当前事件摘要推断。
252
252
 
253
+ ### 业务调试会话 V1
254
+
255
+ 业务模块可通过 `ModuleHost.registerDebugSessionProviders()` 把已有会话投影到
256
+ `canonical_debug` 的原生 ADK Web 会话列表。该能力是 developer-only 的通用只读
257
+ 接缝,不是业务会话 Repository,也不定义 Copilot、案件或其它领域 DTO:
258
+
259
+ - Provider 必须以本模块命名空间注册,并绑定至少一个本模块 Agent Operation;
260
+ `featureKey` 与 `permissionKey` 必须与绑定 Operation 完全一致,`auditAction` 必须
261
+ 已在同一 Manifest 声明。
262
+ - `list()` 和 `get()` 只接收 Host 投影的当前业务用户、当前配置的唯一 Operation、
263
+ 分页上限、不透明 cursor 与 `AbortSignal`。Provider 应使用稳定 keyset 分页,并在
264
+ 自身 Service/Repository 边界内再次执行对象级授权,只返回完成态的 `user` /
265
+ `assistant` 文本。
266
+ - Server 只向 ADK Web 暴露
267
+ `GET /api/agent/debug/sessions/v1` 与
268
+ `GET /api/agent/debug/sessions/v1/:sessionId`。两条路径复用专用 Debug Bearer,
269
+ 每次请求都重做 License、Feature 与 RBAC Guard;其它 Method 不在 Token 白名单。
270
+ - 业务 `sourceId` 只用于 Provider 回查。Host 签发绑定“投影业务用户 + Operation +
271
+ Provider + sourceId”的 HMAC 不透明 ID;详情读取先重新 list 并重新授权,再调用
272
+ `get()`,不会把可逆 ID、Actor ID、Operation Key、Provider Key 或业务范围 ID
273
+ 返回 ADK。
274
+ - Provider 每页最多返回 100 个会话,Host 会沿不透明 cursor 读取完成后再交给原生
275
+ ADK 列表,不静默丢弃第 101 条及更旧会话;任一分页或 Provider 失败都会拒绝整份
276
+ 业务列表,避免把 partial 结果伪装成完整结果。详情最多 64 条消息,单条最多
277
+ 16,000 字符,总计最多 128,000 字符。重复条目、循环游标、超界、乱序、未知角色、
278
+ 非法时间或 Provider 异常均安全拒绝。
279
+
280
+ ADK 2.5 通过官方 `services.py` Service Registry 加载 `windy-debug://v1` composite
281
+ Session Service。普通 ADK session 继续保存在进程内 `InMemorySessionService`;业务
282
+ 会话在每次详情读取时重新授权并转换为 ADK `Session/Event` 的实时只读投影,不在
283
+ ADK 本地固化,也不复制 Tool、Citation、Run ID、内部
284
+ Operation 或业务对象标识。平台列表暂时不可用时仍返回普通本地 session;已选择的导入
285
+ session 详情不可用时明确失败。
286
+
287
+ 导入 session 在 V1 中严格只读:PATCH/rename 与新消息都会在 `append_event()` 拒绝,
288
+ 在 canonical Tool 再做一次防御性拒绝;DELETE 只在当前 ADK Web 进程创建本地 tombstone,
289
+ 不会删除业务历史。刷新进程后 tombstone 消失。要继续提问必须新建普通本地 ADK
290
+ session;由于当前 canonical bridge 输入仍只有 `{ question }`,平台不会把历史文本冒充
291
+ 成业务 continuation。真正的历史续问需要后续版本定义通用、受权限治理的高层
292
+ Operation 契约。
293
+
253
294
  ## 客户端协议
254
295
 
255
296
  浏览器继续使用 `@southwind-ai/ai-client` 访问同源 Southwind AI Server:
@@ -265,6 +306,9 @@ SSE 事件包括 `output.delta`、`tool.requested`、`tool.completed`、usage,
265
306
  `run.completed`、`run.failed` 或 `run.cancelled` 终态。断线后使用已确认 sequence 作为
266
307
  cursor 恢复;不要重新创建 Run 或重复执行 Tool。
267
308
 
309
+ 运行用量、缓存覆盖、滚动时间范围、数据范围与低基数 Prometheus 指标见
310
+ [AI Runtime 用量与运行报表](./agent-runtime-observability.md)。
311
+
268
312
  ## 升级既有 Starter
269
313
 
270
314
  目标 CLI 会一次解析 source 到 target 的连续 recipe,不需要逐个安装中间 CLI。确认
@@ -6,6 +6,19 @@
6
6
 
7
7
  页面每 5 秒刷新一次基础监控快照,手动刷新会同时刷新已获授权的调度状态。`system.scheduler` Feature 未启用或当前用户没有 `system.scheduler.read` 时,前端不会请求调度接口,避免把符合预期的 Guard 拒绝渲染成加载故障。
8
8
 
9
+ ## CPU 与 GPU 监控
10
+
11
+ CPU 区块同时展示宿主机 CPU 占用、Bun Server 进程占用、逻辑核心数和 1 分钟系统负载。宿主机占用按相邻快照之间的 CPU time 差值计算;进程占用按逻辑核心数归一化为整台机器容量,因此不会因为多核进程把进度条推到 100% 以上。服务刚启动或两次采样间隔不足时显示“采集中”,不会用负载均值冒充实时占用率。
12
+
13
+ GPU 区块首期只探测 NVIDIA,通过只读 `nvidia-smi` 查询:
14
+
15
+ - 每张设备的总体 GPU 利用率、显存占用、显存容量和温度;
16
+ - 当前 NVIDIA 计算进程的 PID、进程名和显存占用,可用于确认同机 AI 服务是否已加载模型、占用了哪张卡及多少显存。
17
+
18
+ 设备利用率是 NVIDIA 驱动采样窗口内的整卡指标,进程明细不是逐进程 SM 利用率。远程 AI 服务的 GPU 不会因为配置了 HTTP Endpoint 自动出现在本机总览中;远端需要由其部署环境提供同类受控指标接口后再接入。字段语义遵循 [NVIDIA System Management Interface](https://docs.nvidia.com/deploy/nvidia-smi/index.html)。
19
+
20
+ 没有 `nvidia-smi`、非 NVIDIA 设备、驱动查询失败或超时时,接口返回稳定的 `not-detected` / `unavailable` 状态,页面明确说明原因而不是显示 0%。容器部署只有在 Server 容器获得 NVIDIA Container Toolkit 的 `utility` 能力、GPU 设备可见且 `nvidia-smi` 位于 `PATH` 时才能读取同宿主机设备和进程;否则保持不可探测状态。
21
+
9
22
  ## 在线会话与 IP
10
23
 
11
24
  “在线”定义为满足以下全部条件的登录会话:
@@ -103,9 +103,10 @@ Web 不提供默认开发 Token。只有 Vite 开发模式同时设置 `VITE_DEV
103
103
  `ADK_DEBUG_PLATFORM_TOKEN`。只有 `bun run dev:adk-web` 加载的开发 Compose Wrapper
104
104
  会把它作为 `WINDY_ADK_DEBUG_TOKEN` 注入 Server,并注入 localhost-only ADK Web;它
105
105
  不会复用 `WINDY_DEV_ADMIN_TOKEN`,也不会启用固定 `dev-admin-token` 或 `user:` 直通。
106
- Server 仅在 canonical Agent Run 路径把它解析成 `service_adk_debug`,权限收敛为项目
107
- 选择的 Operation 与 allowed Tools 权限闭包。该 Token 不进入 Web、Agent Server、
108
- Provider 或生产 Compose;非 development Server 即使误配也会拒绝。
106
+ Server 仅在 canonical Agent Run 路径和只读
107
+ `GET /api/agent/debug/sessions/v1/**` 路径把它解析成 `service_adk_debug`,权限收敛为
108
+ 项目选择的 Operation 与 allowed Tools 权限闭包。该 Token 不进入 Web、Agent
109
+ Server、Provider 或生产 Compose;非 development Server 即使误配也会拒绝。
109
110
 
110
111
  未配置 `DATABASE_URL` 时不会注册真实登录 API;只允许显式的非生产开发直通,不存在内存生产账号或默认生产密码。
111
112
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@southwind-ai/config",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "engines": {