create-windy 0.2.25 → 0.2.27
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.
- package/dist/cli.js +52 -1
- package/package.json +1 -1
- package/template/.windy-template.json +2 -2
- package/template/apps/server/src/agent/data-scope-routes.test.ts +5 -8
- package/template/apps/server/src/agent/routes.test.ts +4 -7
- package/template/apps/server/src/agent/tool-registry.test.ts +5 -8
- package/template/apps/server/src/foundation.ts +7 -1
- package/template/apps/server/src/http-app.test.ts +5 -2
- package/template/apps/server/src/license/runtime-service.test.ts +2 -5
- package/template/apps/server/src/mcp/adapter.test.ts +2 -5
- package/template/apps/server/src/module-bootstrap.ts +11 -2
- package/template/apps/server/src/module-migrations.test.ts +43 -0
- package/template/apps/server/src/module-migrations.ts +19 -0
- package/template/apps/web/src/router/shared-scaffold-neutrality.webtest.ts +14 -0
- package/template/docs/architecture/module-manifest-composition.md +11 -0
- package/template/docs/platform/agent-runtime.md +3 -3
- package/template/packages/database/drizzle/0032_marvelous_pepper_potts.sql +2 -0
- package/template/packages/database/drizzle/meta/0032_snapshot.json +7399 -0
- package/template/packages/database/drizzle/meta/_journal.json +7 -0
- package/template/packages/database/index.ts +1 -0
- package/template/packages/database/package.json +4 -1
- package/template/packages/database/src/postgres-module-migrations.integration.test.ts +170 -0
- package/template/packages/database/src/postgres-module-migrations.ts +69 -0
- package/template/packages/database/src/runner.test.ts +5 -1
- package/template/packages/database/src/runner.ts +17 -2
- package/template/packages/database/src/schema/migration-history.ts +3 -0
- package/template/packages/database/src/sql-store.test.ts +7 -1
- package/template/packages/database/src/sql-store.ts +13 -3
- package/template/packages/database/src/store.ts +2 -0
package/dist/cli.js
CHANGED
|
@@ -4058,10 +4058,28 @@ import { join as join12 } from "node:path";
|
|
|
4058
4058
|
|
|
4059
4059
|
// src/update/process.ts
|
|
4060
4060
|
import { spawn as spawn3 } from "node:child_process";
|
|
4061
|
+
var LOCAL_GIT_ENVIRONMENT_VARIABLES = [
|
|
4062
|
+
"GIT_ALTERNATE_OBJECT_DIRECTORIES",
|
|
4063
|
+
"GIT_CONFIG",
|
|
4064
|
+
"GIT_CONFIG_PARAMETERS",
|
|
4065
|
+
"GIT_CONFIG_COUNT",
|
|
4066
|
+
"GIT_OBJECT_DIRECTORY",
|
|
4067
|
+
"GIT_DIR",
|
|
4068
|
+
"GIT_WORK_TREE",
|
|
4069
|
+
"GIT_IMPLICIT_WORK_TREE",
|
|
4070
|
+
"GIT_GRAFT_FILE",
|
|
4071
|
+
"GIT_INDEX_FILE",
|
|
4072
|
+
"GIT_NO_REPLACE_OBJECTS",
|
|
4073
|
+
"GIT_REPLACE_REF_BASE",
|
|
4074
|
+
"GIT_PREFIX",
|
|
4075
|
+
"GIT_SHALLOW_FILE",
|
|
4076
|
+
"GIT_COMMON_DIR"
|
|
4077
|
+
];
|
|
4061
4078
|
async function captureProcess(command, args, cwd, inherit = false) {
|
|
4062
4079
|
return await new Promise((resolve4, reject) => {
|
|
4063
4080
|
const child = spawn3(command, args, {
|
|
4064
4081
|
cwd,
|
|
4082
|
+
env: withoutParentGitRepository(process.env),
|
|
4065
4083
|
stdio: inherit ? "inherit" : ["ignore", "pipe", "pipe"]
|
|
4066
4084
|
});
|
|
4067
4085
|
let stdout2 = "";
|
|
@@ -4080,6 +4098,13 @@ async function assertProcess(command, args, cwd, inherit = false) {
|
|
|
4080
4098
|
}
|
|
4081
4099
|
return result;
|
|
4082
4100
|
}
|
|
4101
|
+
function withoutParentGitRepository(source) {
|
|
4102
|
+
const environment = { ...source };
|
|
4103
|
+
for (const key of LOCAL_GIT_ENVIRONMENT_VARIABLES) {
|
|
4104
|
+
delete environment[key];
|
|
4105
|
+
}
|
|
4106
|
+
return environment;
|
|
4107
|
+
}
|
|
4083
4108
|
|
|
4084
4109
|
// src/update/transaction.ts
|
|
4085
4110
|
import {
|
|
@@ -4309,7 +4334,9 @@ var recipes = [
|
|
|
4309
4334
|
{ id: "starter-0.2.21-to-0.2.22", from: "0.2.21", to: "0.2.22" },
|
|
4310
4335
|
{ id: "starter-0.2.22-to-0.2.23", from: "0.2.22", to: "0.2.23" },
|
|
4311
4336
|
{ id: "starter-0.2.23-to-0.2.24", from: "0.2.23", to: "0.2.24" },
|
|
4312
|
-
{ id: "starter-0.2.24-to-0.2.25", from: "0.2.24", to: "0.2.25" }
|
|
4337
|
+
{ id: "starter-0.2.24-to-0.2.25", from: "0.2.24", to: "0.2.25" },
|
|
4338
|
+
{ id: "starter-0.2.25-to-0.2.26", from: "0.2.25", to: "0.2.26" },
|
|
4339
|
+
{ id: "starter-0.2.26-to-0.2.27", from: "0.2.26", to: "0.2.27" }
|
|
4313
4340
|
];
|
|
4314
4341
|
function resolveRecipeChain(sourceVersion, targetVersion) {
|
|
4315
4342
|
if (sourceVersion === targetVersion)
|
|
@@ -4431,6 +4458,9 @@ var correctCoreDescription = "创建时未选择 `work-order` 示例模块,当
|
|
|
4431
4458
|
var wrongExampleRow = /^\|\s*示例工单\s*\|\s*已包含\s*\|$/m;
|
|
4432
4459
|
var correctCoreRow = /^\|\s*示例工单\s*\|\s*未包含\s*\|$/m;
|
|
4433
4460
|
function repairKnownDerivedFile(input) {
|
|
4461
|
+
const neutralRouterRepair = repairKnown026Downstream(input);
|
|
4462
|
+
if (neutralRouterRepair !== undefined)
|
|
4463
|
+
return neutralRouterRepair;
|
|
4434
4464
|
const downstreamRepair = repairKnown023Downstream(input);
|
|
4435
4465
|
if (downstreamRepair !== undefined)
|
|
4436
4466
|
return downstreamRepair;
|
|
@@ -4451,6 +4481,27 @@ function repairKnownDerivedFile(input) {
|
|
|
4451
4481
|
}
|
|
4452
4482
|
return input.content.replace(wrongExampleDescription, correctCoreDescription).replace(wrongExampleRow, targetRow);
|
|
4453
4483
|
}
|
|
4484
|
+
function repairKnown026Downstream(input) {
|
|
4485
|
+
if (input.sourceVersion !== "0.2.26")
|
|
4486
|
+
return;
|
|
4487
|
+
if (input.path === "apps/web/src/router/index.ts" && input.targetContent.includes("@/pages/auth/LoginPage.vue")) {
|
|
4488
|
+
return replaceKnown(input.content, 'import LoginPage from "@/app/auth/LijianLoginPage.vue";', 'import LoginPage from "@/pages/auth/LoginPage.vue";');
|
|
4489
|
+
}
|
|
4490
|
+
if (input.path !== "apps/web/src/router/router-test-fixtures.ts" || input.targetContent.includes("lijian.")) {
|
|
4491
|
+
return;
|
|
4492
|
+
}
|
|
4493
|
+
const replacements2 = [
|
|
4494
|
+
["lijian.case.read", "case.read"],
|
|
4495
|
+
["lijian.evidence.read", "evidence.read"],
|
|
4496
|
+
["lijian.case", "case"],
|
|
4497
|
+
["lijian.evidence.import", "evidence.import"],
|
|
4498
|
+
["lijian.evidence", "evidence"]
|
|
4499
|
+
];
|
|
4500
|
+
if (!replacements2.every(([source]) => input.content.includes(source))) {
|
|
4501
|
+
return;
|
|
4502
|
+
}
|
|
4503
|
+
return replacements2.reduce((content, [source, target]) => content.replaceAll(source, target), input.content);
|
|
4504
|
+
}
|
|
4454
4505
|
function repairKnown023Downstream(input) {
|
|
4455
4506
|
if (input.sourceVersion !== "0.2.23" || known023DownstreamHashes.get(input.path) !== contentHash(input.content)) {
|
|
4456
4507
|
return;
|
package/package.json
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { buildScopeContext } from "../data-access/context.js";
|
|
3
|
-
import {
|
|
4
|
-
createFoundationSnapshot,
|
|
5
|
-
loadFoundationModules,
|
|
6
|
-
} from "../foundation.js";
|
|
3
|
+
import { createFoundationSnapshot, loadSystemModules } from "../foundation.js";
|
|
7
4
|
import { createServerRuntime } from "../runtime.js";
|
|
8
5
|
import { FakeRouteApp } from "../system/route-test-app.js";
|
|
9
6
|
import { createSystemRepositories } from "../system/seed.js";
|
|
@@ -31,13 +28,13 @@ describe("Agent Tool data scope", () => {
|
|
|
31
28
|
expect(
|
|
32
29
|
() =>
|
|
33
30
|
new GovernedToolRegistry(
|
|
34
|
-
|
|
31
|
+
loadSystemModules(),
|
|
35
32
|
missing as ModuleToolHandlers,
|
|
36
33
|
runtime,
|
|
37
34
|
),
|
|
38
35
|
).toThrow("缺少 Handler");
|
|
39
36
|
expect(
|
|
40
|
-
() => new GovernedToolRegistry(
|
|
37
|
+
() => new GovernedToolRegistry(loadSystemModules(), extra, runtime),
|
|
41
38
|
).toThrow("Handler 未声明");
|
|
42
39
|
});
|
|
43
40
|
|
|
@@ -67,7 +64,7 @@ describe("Agent Tool data scope", () => {
|
|
|
67
64
|
registerAgentRoutes(
|
|
68
65
|
app,
|
|
69
66
|
new GovernedToolRegistry(
|
|
70
|
-
|
|
67
|
+
loadSystemModules(),
|
|
71
68
|
createSystemToolHandlers(repositories, runtime),
|
|
72
69
|
runtime,
|
|
73
70
|
),
|
|
@@ -102,7 +99,7 @@ describe("Agent Tool data scope", () => {
|
|
|
102
99
|
registerAgentRoutes(
|
|
103
100
|
app,
|
|
104
101
|
new GovernedToolRegistry(
|
|
105
|
-
|
|
102
|
+
loadSystemModules(),
|
|
106
103
|
createSystemToolHandlers(createSystemRepositories(snapshot), runtime),
|
|
107
104
|
runtime,
|
|
108
105
|
),
|
|
@@ -3,10 +3,7 @@ import {
|
|
|
3
3
|
entitlementKey,
|
|
4
4
|
type FeatureFlagDefinition,
|
|
5
5
|
} from "@southwind-ai/shared";
|
|
6
|
-
import {
|
|
7
|
-
createFoundationSnapshot,
|
|
8
|
-
loadFoundationModules,
|
|
9
|
-
} from "../foundation.js";
|
|
6
|
+
import { createFoundationSnapshot, loadSystemModules } from "../foundation.js";
|
|
10
7
|
import { createServerRuntime } from "../runtime.js";
|
|
11
8
|
import type { RouteApp } from "../system/routes.js";
|
|
12
9
|
import { createSystemRepositories } from "../system/seed.js";
|
|
@@ -42,7 +39,7 @@ class FakeRouteApp implements RouteApp {
|
|
|
42
39
|
function routeFixture(features?: FeatureFlagDefinition[]) {
|
|
43
40
|
const runtime = createServerRuntime({ WINDY_DEV_ADMIN_TOKEN: "token_1" });
|
|
44
41
|
const app = new FakeRouteApp();
|
|
45
|
-
const modules =
|
|
42
|
+
const modules = loadSystemModules();
|
|
46
43
|
if (features) {
|
|
47
44
|
modules[0] = { ...modules[0]!, features };
|
|
48
45
|
}
|
|
@@ -67,7 +64,7 @@ describe("agent routes", () => {
|
|
|
67
64
|
createSystemRepositories(createFoundationSnapshot()),
|
|
68
65
|
runtime,
|
|
69
66
|
);
|
|
70
|
-
const manifestKeys =
|
|
67
|
+
const manifestKeys = loadSystemModules().flatMap((module) =>
|
|
71
68
|
module.tools.map(({ key }) => key),
|
|
72
69
|
);
|
|
73
70
|
|
|
@@ -198,7 +195,7 @@ describe("agent routes", () => {
|
|
|
198
195
|
registerAgentRoutes(
|
|
199
196
|
app,
|
|
200
197
|
new GovernedToolRegistry(
|
|
201
|
-
|
|
198
|
+
loadSystemModules(),
|
|
202
199
|
createSystemToolHandlers(repositories, runtime),
|
|
203
200
|
runtime,
|
|
204
201
|
),
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import type { ModuleToolHandlers } from "./tool-registry.js";
|
|
3
|
-
import {
|
|
4
|
-
createFoundationSnapshot,
|
|
5
|
-
loadFoundationModules,
|
|
6
|
-
} from "../foundation.js";
|
|
3
|
+
import { createFoundationSnapshot, loadSystemModules } from "../foundation.js";
|
|
7
4
|
import { createServerRuntime } from "../runtime.js";
|
|
8
5
|
import { createSystemRepositories } from "../system/seed.js";
|
|
9
6
|
import { createSystemToolHandlers } from "./routes.js";
|
|
@@ -30,7 +27,7 @@ describe("Governed Tool Registry", () => {
|
|
|
30
27
|
},
|
|
31
28
|
});
|
|
32
29
|
const registry = new GovernedToolRegistry(
|
|
33
|
-
|
|
30
|
+
loadSystemModules(),
|
|
34
31
|
handlers,
|
|
35
32
|
fixture.runtime,
|
|
36
33
|
);
|
|
@@ -56,7 +53,7 @@ describe("Governed Tool Registry", () => {
|
|
|
56
53
|
}),
|
|
57
54
|
});
|
|
58
55
|
const registry = new GovernedToolRegistry(
|
|
59
|
-
|
|
56
|
+
loadSystemModules(),
|
|
60
57
|
invalidOutput,
|
|
61
58
|
fixture.runtime,
|
|
62
59
|
);
|
|
@@ -72,7 +69,7 @@ describe("Governed Tool Registry", () => {
|
|
|
72
69
|
expect(
|
|
73
70
|
() =>
|
|
74
71
|
new GovernedToolRegistry(
|
|
75
|
-
|
|
72
|
+
loadSystemModules(),
|
|
76
73
|
mismatchedScope,
|
|
77
74
|
fixture.runtime,
|
|
78
75
|
),
|
|
@@ -104,7 +101,7 @@ async function createFixture() {
|
|
|
104
101
|
runtime,
|
|
105
102
|
);
|
|
106
103
|
const registry = new GovernedToolRegistry(
|
|
107
|
-
|
|
104
|
+
loadSystemModules(),
|
|
108
105
|
handlers,
|
|
109
106
|
runtime,
|
|
110
107
|
);
|
|
@@ -45,6 +45,12 @@ export function loadFoundationModules(): ModuleManifest[] {
|
|
|
45
45
|
return registry.list();
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
export function loadSystemModules(): ModuleManifest[] {
|
|
49
|
+
const registry = createModuleRegistry();
|
|
50
|
+
for (const factory of systemModuleFactories) registry.register(factory);
|
|
51
|
+
return registry.list();
|
|
52
|
+
}
|
|
53
|
+
|
|
48
54
|
function collectMenus(modules: ModuleManifest[]): MenuNode[] {
|
|
49
55
|
return composeModuleMenus(modules);
|
|
50
56
|
}
|
|
@@ -71,8 +77,8 @@ function collectAuditActions(modules: ModuleManifest[]): string[] {
|
|
|
71
77
|
|
|
72
78
|
export function createFoundationSnapshot(
|
|
73
79
|
config: PlatformConfig = loadPlatformConfig(),
|
|
80
|
+
modules: ModuleManifest[] = loadFoundationModules(),
|
|
74
81
|
): FoundationSnapshot {
|
|
75
|
-
const modules = loadFoundationModules();
|
|
76
82
|
const catalogs = validateCapabilityCatalogs(
|
|
77
83
|
modules,
|
|
78
84
|
resolveLicenseCatalog(config.license.versions),
|
|
@@ -39,8 +39,11 @@ describe("platform HTTP app observability", () => {
|
|
|
39
39
|
/^[A-Za-z0-9._-]{1,128}$/,
|
|
40
40
|
);
|
|
41
41
|
expect(
|
|
42
|
-
records.filter(
|
|
43
|
-
|
|
42
|
+
records.filter(
|
|
43
|
+
({ event, statusCode }) =>
|
|
44
|
+
event === "http.request.completed" && statusCode === 404,
|
|
45
|
+
),
|
|
46
|
+
).toHaveLength(2);
|
|
44
47
|
expect(observability.metrics.render()).toContain(
|
|
45
48
|
'windy_http_requests_total{method="GET",status_class="4xx"} 2',
|
|
46
49
|
);
|
|
@@ -18,10 +18,7 @@ import {
|
|
|
18
18
|
} from "../agent/routes.js";
|
|
19
19
|
import { GovernedToolRegistry } from "../agent/tool-registry.js";
|
|
20
20
|
import { runGuardedBackgroundTask } from "../background/task-guard.js";
|
|
21
|
-
import {
|
|
22
|
-
createFoundationSnapshot,
|
|
23
|
-
loadFoundationModules,
|
|
24
|
-
} from "../foundation.js";
|
|
21
|
+
import { createFoundationSnapshot, loadSystemModules } from "../foundation.js";
|
|
25
22
|
import {
|
|
26
23
|
evaluateRestrictedHttpRequest,
|
|
27
24
|
licenseRestrictedResponse,
|
|
@@ -266,7 +263,7 @@ function createFixture(
|
|
|
266
263
|
registerAgentRoutes(
|
|
267
264
|
app,
|
|
268
265
|
new GovernedToolRegistry(
|
|
269
|
-
|
|
266
|
+
loadSystemModules(),
|
|
270
267
|
createSystemToolHandlers(repositories, runtime),
|
|
271
268
|
runtime,
|
|
272
269
|
),
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test } from "bun:test";
|
|
2
2
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
3
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
4
|
-
import {
|
|
5
|
-
createFoundationSnapshot,
|
|
6
|
-
loadFoundationModules,
|
|
7
|
-
} from "../foundation.js";
|
|
4
|
+
import { createFoundationSnapshot, loadSystemModules } from "../foundation.js";
|
|
8
5
|
import { createServerRuntime } from "../runtime.js";
|
|
9
6
|
import { createSystemRepositories } from "../system/seed.js";
|
|
10
7
|
import { createSystemToolHandlers } from "../agent/routes.js";
|
|
@@ -104,7 +101,7 @@ describe("Platform MCP Adapter", () => {
|
|
|
104
101
|
});
|
|
105
102
|
|
|
106
103
|
function createFixture() {
|
|
107
|
-
const modules =
|
|
104
|
+
const modules = loadSystemModules();
|
|
108
105
|
const runtime = createServerRuntime(
|
|
109
106
|
{},
|
|
110
107
|
{
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
createFoundationSnapshot,
|
|
7
7
|
loadFoundationModules,
|
|
8
8
|
} from "./foundation.js";
|
|
9
|
+
import { runInstalledModuleMigrations } from "./module-migrations.js";
|
|
9
10
|
import {
|
|
10
11
|
attachInstalledBusinessModules,
|
|
11
12
|
installedBusinessModules,
|
|
@@ -27,17 +28,24 @@ export async function bootstrapServerModules(
|
|
|
27
28
|
platformConfig: PlatformConfig,
|
|
28
29
|
persistence: ServerPersistence | undefined,
|
|
29
30
|
) {
|
|
31
|
+
const foundationModules = loadFoundationModules();
|
|
32
|
+
const foundationSnapshot = createFoundationSnapshot(
|
|
33
|
+
platformConfig,
|
|
34
|
+
foundationModules,
|
|
35
|
+
);
|
|
36
|
+
const moduleMigrationReport = await runInstalledModuleMigrations(
|
|
37
|
+
foundationModules,
|
|
38
|
+
persistence?.pool,
|
|
39
|
+
);
|
|
30
40
|
// @windy-module system.configuration begin
|
|
31
41
|
const configurationRuntime = await bootstrapModuleConfiguration(
|
|
32
42
|
platformConfig,
|
|
33
43
|
persistence?.configVersionRepository,
|
|
34
44
|
);
|
|
35
45
|
// @windy-module system.configuration end
|
|
36
|
-
const foundationSnapshot = createFoundationSnapshot(platformConfig);
|
|
37
46
|
// @windy-module system.configuration begin
|
|
38
47
|
configurationRuntime.bindFoundation(foundationSnapshot);
|
|
39
48
|
// @windy-module system.configuration end
|
|
40
|
-
const foundationModules = loadFoundationModules();
|
|
41
49
|
const moduleHosts = await initializeModuleHosts({
|
|
42
50
|
modules: foundationModules,
|
|
43
51
|
installations: installedBusinessModules,
|
|
@@ -78,6 +86,7 @@ export async function bootstrapServerModules(
|
|
|
78
86
|
foundationModules,
|
|
79
87
|
foundationSnapshot,
|
|
80
88
|
moduleHosts,
|
|
89
|
+
moduleMigrationReport,
|
|
81
90
|
systemRepositories,
|
|
82
91
|
};
|
|
83
92
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import type { ModuleManifest } from "@southwind-ai/modules";
|
|
3
|
+
import { runInstalledModuleMigrations } from "./module-migrations.js";
|
|
4
|
+
|
|
5
|
+
describe("Server Module Migration 启动 seam", () => {
|
|
6
|
+
test("没有显式 bundle 时不占用 PostgreSQL 连接", async () => {
|
|
7
|
+
let connected = false;
|
|
8
|
+
const result = await runInstalledModuleMigrations([manifest()], {
|
|
9
|
+
async connect() {
|
|
10
|
+
connected = true;
|
|
11
|
+
throw new Error("不应获取连接");
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
expect(result).toBeUndefined();
|
|
16
|
+
expect(connected).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("未配置 PostgreSQL 时保留纯结构校验启动路径", async () => {
|
|
20
|
+
const result = await runInstalledModuleMigrations([manifest()], undefined);
|
|
21
|
+
expect(result).toBeUndefined();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
function manifest(): ModuleManifest {
|
|
26
|
+
return {
|
|
27
|
+
name: "customer-domain",
|
|
28
|
+
version: "1.0.0",
|
|
29
|
+
label: "客户领域",
|
|
30
|
+
description: "测试模块",
|
|
31
|
+
menus: [],
|
|
32
|
+
adminRoutes: [],
|
|
33
|
+
permissions: [],
|
|
34
|
+
apiPermissions: [],
|
|
35
|
+
features: [],
|
|
36
|
+
migrations: [],
|
|
37
|
+
schemaExports: [],
|
|
38
|
+
tasks: [],
|
|
39
|
+
tools: [],
|
|
40
|
+
providers: [],
|
|
41
|
+
auditActions: [],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runPostgresMigrationBundles,
|
|
3
|
+
type MigrationRunReport,
|
|
4
|
+
type PostgresTransactionPool,
|
|
5
|
+
} from "@southwind-ai/database";
|
|
6
|
+
import type { ModuleManifest } from "@southwind-ai/modules";
|
|
7
|
+
import { normalizeManifestBundles } from "@southwind-ai/shared";
|
|
8
|
+
|
|
9
|
+
export async function runInstalledModuleMigrations(
|
|
10
|
+
modules: readonly ModuleManifest[],
|
|
11
|
+
pool: PostgresTransactionPool | undefined,
|
|
12
|
+
): Promise<MigrationRunReport | undefined> {
|
|
13
|
+
const bundledModules = modules.filter((module) => module.migrationBundle);
|
|
14
|
+
if (!pool || bundledModules.length === 0) return undefined;
|
|
15
|
+
return runPostgresMigrationBundles({
|
|
16
|
+
pool,
|
|
17
|
+
bundles: normalizeManifestBundles(bundledModules),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import routerSource from "./index.ts?raw";
|
|
3
|
+
import fixtureSource from "./router-test-fixtures.ts?raw";
|
|
4
|
+
|
|
5
|
+
describe("Router shared-scaffold 中性契约", () => {
|
|
6
|
+
test("平台登录页与测试快照不固化下游产品命名", () => {
|
|
7
|
+
expect(routerSource).toContain(
|
|
8
|
+
'import LoginPage from "@/pages/auth/LoginPage.vue";',
|
|
9
|
+
);
|
|
10
|
+
expect(`${routerSource}\n${fixtureSource}`).not.toMatch(
|
|
11
|
+
/LijianLoginPage|lijian\./,
|
|
12
|
+
);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -45,6 +45,17 @@ Manifest 当前覆盖:
|
|
|
45
45
|
|
|
46
46
|
这种边界允许宿主替换实现,同时保持 Manifest 的能力语义稳定。
|
|
47
47
|
|
|
48
|
+
## Capability Key 重命名边界
|
|
49
|
+
|
|
50
|
+
平台当前没有 Module、Feature、Permission、Task、Tool、Operation 或 API Key 的通用
|
|
51
|
+
rename/alias seam。Composition、Guard、history 和审计都按 Manifest 中的精确稳定 Key
|
|
52
|
+
工作,不会把旧 Key 静默映射到新 Key。
|
|
53
|
+
|
|
54
|
+
产品需要硬切命名时,应在停机窗口一次性更新 Manifest、Host 实现、调用方、持久化权限
|
|
55
|
+
和任务数据,并通过 project-owned forward Migration 完成 schema/data rename。若产品
|
|
56
|
+
确实需要跨版本兼容期,应先单独设计带期限、冲突规则和审计语义的 alias 契约;当前
|
|
57
|
+
平台不会为某个下游产品内置别名。
|
|
58
|
+
|
|
48
59
|
## 分批落地
|
|
49
60
|
|
|
50
61
|
- 第一批:类型、声明级验证和失败回归。
|
|
@@ -126,13 +126,13 @@ SSE 事件包括 `output.delta`、`tool.requested`、`tool.completed`、usage,
|
|
|
126
126
|
`run.completed`、`run.failed` 或 `run.cancelled` 终态。断线后使用已确认 sequence 作为
|
|
127
127
|
cursor 恢复;不要重新创建 Run 或重复执行 Tool。
|
|
128
128
|
|
|
129
|
-
## 从 create-windy 0.2.
|
|
129
|
+
## 从 create-windy 0.2.25 或更早版本升级
|
|
130
130
|
|
|
131
131
|
先检查计划,再应用连续 recipe:
|
|
132
132
|
|
|
133
133
|
```bash
|
|
134
|
-
bunx --bun create-windy@0.2.
|
|
135
|
-
bunx --bun create-windy@0.2.
|
|
134
|
+
bunx --bun create-windy@0.2.26 update --check
|
|
135
|
+
bunx --bun create-windy@0.2.26 update
|
|
136
136
|
bun install
|
|
137
137
|
```
|
|
138
138
|
|