@whispering233/ai-editor-server 0.0.29 → 0.0.32
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/client-dist/assets/index-BlZjI169.js +523 -0
- package/client-dist/assets/{index-0zEqGbv5.css → index-DUmFZL7d.css} +1 -1
- package/client-dist/index.html +3 -3
- package/dist/backup.d.ts +13 -12
- package/dist/backup.d.ts.map +1 -1
- package/dist/backup.js +73 -57
- package/dist/backup.js.map +1 -1
- package/dist/chat-runtime.d.ts +44 -0
- package/dist/chat-runtime.d.ts.map +1 -0
- package/dist/chat-runtime.js +102 -0
- package/dist/chat-runtime.js.map +1 -0
- package/dist/consistency.js +1 -1
- package/dist/consistency.js.map +1 -1
- package/dist/debug.d.ts +1 -1
- package/dist/debug.d.ts.map +1 -1
- package/dist/debug.js +3 -3
- package/dist/debug.js.map +1 -1
- package/dist/http-dispatcher.d.ts +30 -0
- package/dist/http-dispatcher.d.ts.map +1 -0
- package/dist/http-dispatcher.js +101 -0
- package/dist/http-dispatcher.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/middleware/error.d.ts +2 -2
- package/dist/middleware/error.d.ts.map +1 -1
- package/dist/middleware/error.js +2 -2
- package/dist/middleware/error.js.map +1 -1
- package/dist/middleware/project.d.ts +3 -3
- package/dist/middleware/project.d.ts.map +1 -1
- package/dist/middleware/project.js +10 -6
- package/dist/middleware/project.js.map +1 -1
- package/dist/model-runtime.d.ts +41 -0
- package/dist/model-runtime.d.ts.map +1 -0
- package/dist/model-runtime.js +81 -0
- package/dist/model-runtime.js.map +1 -0
- package/dist/reference-files.d.ts +4 -4
- package/dist/reference-files.d.ts.map +1 -1
- package/dist/reference-files.js +5 -5
- package/dist/reference-files.js.map +1 -1
- package/dist/routes/chat.d.ts +36 -73
- package/dist/routes/chat.d.ts.map +1 -1
- package/dist/routes/chat.js +390 -373
- package/dist/routes/chat.js.map +1 -1
- package/dist/routes/delta.js +6 -6
- package/dist/routes/delta.js.map +1 -1
- package/dist/routes/entity.js +9 -9
- package/dist/routes/entity.js.map +1 -1
- package/dist/routes/names.js +3 -3
- package/dist/routes/names.js.map +1 -1
- package/dist/routes/outline.js +6 -6
- package/dist/routes/outline.js.map +1 -1
- package/dist/routes/project.d.ts +1 -1
- package/dist/routes/project.js +20 -20
- package/dist/routes/project.js.map +1 -1
- package/dist/routes/proposal.js +6 -6
- package/dist/routes/proposal.js.map +1 -1
- package/dist/routes/reference.js +1 -1
- package/dist/routes/reference.js.map +1 -1
- package/dist/routes/relation.js +1 -1
- package/dist/routes/relation.js.map +1 -1
- package/dist/routes/settings.d.ts +0 -53
- package/dist/routes/settings.d.ts.map +1 -1
- package/dist/routes/settings.js +159 -194
- package/dist/routes/settings.js.map +1 -1
- package/dist/routes/trash.js +4 -4
- package/dist/routes/trash.js.map +1 -1
- package/package.json +8 -6
- package/client-dist/assets/index-DMtHdMMq.js +0 -521
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300000;
|
|
2
|
+
/** HTTP 空闲超时可选项(设置页/文档用;0 = 关闭超时) */
|
|
3
|
+
export declare const HTTP_IDLE_TIMEOUT_CHOICES: readonly [{
|
|
4
|
+
readonly label: "30 sec";
|
|
5
|
+
readonly timeoutMs: 30000;
|
|
6
|
+
}, {
|
|
7
|
+
readonly label: "1 min";
|
|
8
|
+
readonly timeoutMs: 60000;
|
|
9
|
+
}, {
|
|
10
|
+
readonly label: "2 min";
|
|
11
|
+
readonly timeoutMs: 120000;
|
|
12
|
+
}, {
|
|
13
|
+
readonly label: "5 min";
|
|
14
|
+
readonly timeoutMs: 300000;
|
|
15
|
+
}, {
|
|
16
|
+
readonly label: "disabled";
|
|
17
|
+
readonly timeoutMs: 0;
|
|
18
|
+
}];
|
|
19
|
+
/** 解析空闲超时配置:字符串("disabled" / 数字串)/ 数字;非法 → undefined */
|
|
20
|
+
export declare function parseHttpIdleTimeoutMs(value: unknown): number | undefined;
|
|
21
|
+
/** 空闲超时的人类可读标签(非法值 → "<n> sec" 形态) */
|
|
22
|
+
export declare function formatHttpIdleTimeoutMs(timeoutMs: number): string;
|
|
23
|
+
/** 把 `httpProxy` 设置写入环境(仅在未设置时;供 EnvHttpProxyAgent 读取) */
|
|
24
|
+
export declare function applyHttpProxySettings(httpProxy: string | undefined): void;
|
|
25
|
+
/**
|
|
26
|
+
* 安装全局 undici dispatcher(启动时调用一次;设置变更后可再次调用覆盖)。
|
|
27
|
+
* @param timeoutMs 空闲超时(`bodyTimeout`/`headersTimeout`),缺省 5 分钟
|
|
28
|
+
*/
|
|
29
|
+
export declare function configureHttpDispatcher(timeoutMs?: number): void;
|
|
30
|
+
//# sourceMappingURL=http-dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-dispatcher.d.ts","sourceRoot":"","sources":["../src/http-dispatcher.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAKpD,qCAAqC;AACrC,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;EAM5B,CAAC;AAKX,wDAAwD;AACxD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CASzE;AAED,sCAAsC;AACtC,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,0DAA0D;AAC1D,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAK1E;AAyBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAqC,GAAG,IAAI,CAyB9F"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// 出站 HTTP dispatcher(嵌入 pi 运行时必需的一环)
|
|
2
|
+
//
|
|
3
|
+
// 为什么需要它:pi CLI 启动时会安装自己的 undici dispatcher(`pi-coding-agent` 的
|
|
4
|
+
// `core/http-dispatcher.ts`,未从包根导出),其中两项对本机/弱网环境是必需的:
|
|
5
|
+
// 1. `connect.autoSelectFamilyAttemptTimeout = 2000`——Node 默认 250ms 会让
|
|
6
|
+
// 「IPv6 可达性黑洞」的链路上快速放弃、整连接 ETIMEDOUT(实测:不装 dispatcher 时
|
|
7
|
+
// 对 opencode.ai 的 fetch 稳定 1.4s 超时,装了即 200);
|
|
8
|
+
// 2. 环境代理支持(`EnvHttpProxyAgent`,配合 `httpProxy` 设置/`HTTP(S)_PROXY`)。
|
|
9
|
+
// 不装 dispatcher 时 pi 的 SDK 走 Node 自带 fetch/连接策略,于是「pi CLI 能连、本仓不能连」。
|
|
10
|
+
//
|
|
11
|
+
// 实现与 pi 0.85.1 的同名模块保持同构(pi-web 也以拷贝方式复用该模块),差异仅:
|
|
12
|
+
// 不做一次性守卫(允许设置热更新后重新安装),注释指向本仓语境。
|
|
13
|
+
import { EventEmitter } from "node:events";
|
|
14
|
+
import * as undici from "undici";
|
|
15
|
+
export const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300_000;
|
|
16
|
+
/** Node 默认 250ms 在高延迟/黑洞链路上会过早终止连接尝试(见文件头注释) */
|
|
17
|
+
const DEFAULT_AUTO_SELECT_FAMILY_ATTEMPT_TIMEOUT_MS = 2_000;
|
|
18
|
+
/** HTTP 空闲超时可选项(设置页/文档用;0 = 关闭超时) */
|
|
19
|
+
export const HTTP_IDLE_TIMEOUT_CHOICES = [
|
|
20
|
+
{ label: "30 sec", timeoutMs: 30_000 },
|
|
21
|
+
{ label: "1 min", timeoutMs: 60_000 },
|
|
22
|
+
{ label: "2 min", timeoutMs: 120_000 },
|
|
23
|
+
{ label: "5 min", timeoutMs: 300_000 },
|
|
24
|
+
{ label: "disabled", timeoutMs: 0 },
|
|
25
|
+
];
|
|
26
|
+
const originalGlobalFetch = globalThis.fetch;
|
|
27
|
+
const ignoreUndiciDispatcherError = () => { };
|
|
28
|
+
/** 解析空闲超时配置:字符串("disabled" / 数字串)/ 数字;非法 → undefined */
|
|
29
|
+
export function parseHttpIdleTimeoutMs(value) {
|
|
30
|
+
if (typeof value === "string") {
|
|
31
|
+
const trimmed = value.trim();
|
|
32
|
+
if (trimmed.toLowerCase() === "disabled")
|
|
33
|
+
return 0;
|
|
34
|
+
if (trimmed.length === 0)
|
|
35
|
+
return undefined;
|
|
36
|
+
return parseHttpIdleTimeoutMs(Number(trimmed));
|
|
37
|
+
}
|
|
38
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
|
|
39
|
+
return undefined;
|
|
40
|
+
return Math.floor(value);
|
|
41
|
+
}
|
|
42
|
+
/** 空闲超时的人类可读标签(非法值 → "<n> sec" 形态) */
|
|
43
|
+
export function formatHttpIdleTimeoutMs(timeoutMs) {
|
|
44
|
+
return HTTP_IDLE_TIMEOUT_CHOICES.find((item) => item.timeoutMs === timeoutMs)?.label ?? `${timeoutMs / 1000} sec`;
|
|
45
|
+
}
|
|
46
|
+
/** 把 `httpProxy` 设置写入环境(仅在未设置时;供 EnvHttpProxyAgent 读取) */
|
|
47
|
+
export function applyHttpProxySettings(httpProxy) {
|
|
48
|
+
const proxy = httpProxy?.trim();
|
|
49
|
+
if (!proxy)
|
|
50
|
+
return;
|
|
51
|
+
process.env.HTTP_PROXY ??= proxy;
|
|
52
|
+
process.env.HTTPS_PROXY ??= proxy;
|
|
53
|
+
}
|
|
54
|
+
/** undici 在终止响应体时可能发出 Client 级 error:挂空监听防 EventEmitter 未处理错误打挂进程 */
|
|
55
|
+
function withUndiciErrorListener(dispatcher) {
|
|
56
|
+
if (dispatcher instanceof EventEmitter) {
|
|
57
|
+
EventEmitter.prototype.on.call(dispatcher, "error", ignoreUndiciDispatcherError);
|
|
58
|
+
}
|
|
59
|
+
return dispatcher;
|
|
60
|
+
}
|
|
61
|
+
function createUndiciClient(origin, options) {
|
|
62
|
+
return withUndiciErrorListener(new undici.Client(origin, options));
|
|
63
|
+
}
|
|
64
|
+
function createUndiciOriginDispatcher(origin, options) {
|
|
65
|
+
const dispatcherOptions = options;
|
|
66
|
+
if (dispatcherOptions.connections === 1)
|
|
67
|
+
return createUndiciClient(origin, dispatcherOptions);
|
|
68
|
+
return withUndiciErrorListener(new undici.Pool(origin, {
|
|
69
|
+
...dispatcherOptions,
|
|
70
|
+
factory: createUndiciClient,
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 安装全局 undici dispatcher(启动时调用一次;设置变更后可再次调用覆盖)。
|
|
75
|
+
* @param timeoutMs 空闲超时(`bodyTimeout`/`headersTimeout`),缺省 5 分钟
|
|
76
|
+
*/
|
|
77
|
+
export function configureHttpDispatcher(timeoutMs = DEFAULT_HTTP_IDLE_TIMEOUT_MS) {
|
|
78
|
+
const normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);
|
|
79
|
+
if (normalizedTimeoutMs === undefined) {
|
|
80
|
+
throw new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);
|
|
81
|
+
}
|
|
82
|
+
const dispatcher = withUndiciErrorListener(new undici.EnvHttpProxyAgent({
|
|
83
|
+
allowH2: false,
|
|
84
|
+
// HTTP origin 仍走 CONNECT 隧道(与 pi 行为一致)
|
|
85
|
+
proxyTunnel: true,
|
|
86
|
+
bodyTimeout: normalizedTimeoutMs,
|
|
87
|
+
headersTimeout: normalizedTimeoutMs,
|
|
88
|
+
connect: {
|
|
89
|
+
autoSelectFamilyAttemptTimeout: DEFAULT_AUTO_SELECT_FAMILY_ATTEMPT_TIMEOUT_MS,
|
|
90
|
+
},
|
|
91
|
+
clientFactory: createUndiciClient,
|
|
92
|
+
factory: createUndiciOriginDispatcher,
|
|
93
|
+
}));
|
|
94
|
+
undici.setGlobalDispatcher(dispatcher);
|
|
95
|
+
// fetch 与 dispatcher 用同一 undici 实现(否则 Node 自带 fetch 可能读到未解压响应);
|
|
96
|
+
// 若调用方在模块加载后主动替换过 fetch,则尊重该覆盖。
|
|
97
|
+
if (globalThis.fetch === originalGlobalFetch) {
|
|
98
|
+
undici.install?.();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=http-dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-dispatcher.js","sourceRoot":"","sources":["../src/http-dispatcher.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface StartServerOptions {
|
|
|
9
9
|
port?: number;
|
|
10
10
|
/**
|
|
11
11
|
* dev 态:端口被占直接报错(Vite proxy 写死 3456,自动 +1 会造成 proxy 与实际监听不一致,
|
|
12
|
-
|
|
12
|
+
*);默认取 NODE_ENV === "development"
|
|
13
13
|
*/
|
|
14
14
|
dev?: boolean;
|
|
15
15
|
/** 启动后打开浏览器(默认非 dev 态开启;测试传 false) */
|
|
@@ -26,7 +26,7 @@ export interface ServerHandle {
|
|
|
26
26
|
port: number;
|
|
27
27
|
/** 启动时检测到的项目(目录含 project.json);null = 待命(前端引导 create/open) */
|
|
28
28
|
project: ProjectContext | null;
|
|
29
|
-
/**
|
|
29
|
+
/** 关闭服务并释放数据库连接 */
|
|
30
30
|
close: () => Promise<void>;
|
|
31
31
|
}
|
|
32
32
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAkBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAkBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWzE,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAUjC,qCAAqC;AACrC,eAAO,MAAM,YAAY,OAAO,CAAC;AAuBjC,MAAM,WAAW,kBAAkB;IAClC,iCAAiC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACf;;;MAGE;IACD,GAAG,CAAC,EAAE,OAAO,CAAC;IACf,sCAAsC;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;IACvB,yDAAyD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,IAAI,CAAC;QAAE,SAAS,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IAC3C,MAAM,EAAE,UAAU,CAAC;IACpB,6BAA6B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC7D,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,mBAAmB;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMzD;AAmBD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CA+J9G;AAcD,gDAAgD;AAChD,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/D;AAID;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAK1E"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @whispering233/ai-editor-server 入口(T6.1 服务骨架)
|
|
3
3
|
//
|
|
4
|
-
//
|
|
4
|
+
// 职责(第 307-336 行「构建与部署」):
|
|
5
5
|
// - startServer(projectRoot, opts?):检测/初始化项目→ 装配 Hono(错误中间件 +
|
|
6
6
|
// 来源校验 + 项目上下文 + /api/v1/health 探活)→ 端口策略监听(dev 被占报错 / 生产 +1)→
|
|
7
7
|
// 可选打开浏览器(127.0.0.1,禁 localhost)
|
|
8
|
-
// - SPA 静态托管:client/dist 静态文件 + 非 /api GET fallback 到 index.html
|
|
8
|
+
// - SPA 静态托管:client/dist 静态文件 + 非 /api GET fallback 到 index.html(单进程架构)
|
|
9
9
|
// - 直接执行(node packages/server/dist/index.js [projectRoot])时自动启动;业务路由(routes/)
|
|
10
10
|
// 留到切片 1 挂载(结构预留:health 旁并列注册即可)
|
|
11
11
|
// - bin 入口(打包安装):package.json "bin": {"ai-editor": "dist/index.js"}——
|
|
@@ -22,6 +22,8 @@ import { createAdaptorServer } from "@hono/node-server";
|
|
|
22
22
|
import { errorHandler, fail, ok } from "./middleware/error.js";
|
|
23
23
|
import { stopAutoBackup } from "./backup.js";
|
|
24
24
|
import { initDebugConfig, isCategoryEnabled } from "./debug.js";
|
|
25
|
+
import { applyHttpProxySettings, configureHttpDispatcher } from "./http-dispatcher.js";
|
|
26
|
+
import { getSettingsManager } from "./model-runtime.js";
|
|
25
27
|
import { chatRoutes } from "./routes/chat.js";
|
|
26
28
|
import { deltaRoutes } from "./routes/delta.js";
|
|
27
29
|
import { entityRoutes } from "./routes/entity.js";
|
|
@@ -111,11 +113,17 @@ export async function startServer(projectRoot, options = {}) {
|
|
|
111
113
|
// 五类别 chat/request/stream/usage/http;文件不存在/非法 JSON/结构不符 → 全关;
|
|
112
114
|
// 不阻断启动。运行中改配置文件不生效——热加载 YAGNI)
|
|
113
115
|
initDebugConfig(root);
|
|
116
|
+
// 出站 HTTP dispatcher(嵌入 pi 运行时的必需环节,见 http-dispatcher.ts 文件头):
|
|
117
|
+
// 装 undici dispatcher 以拿到 pi CLI 同款行为(IPv6 黑洞链路的 autoSelectFamily 退避 +
|
|
118
|
+
// 环境代理支持 + 可配 HTTP 空闲超时);不装 → 部分网络下 provider 请求稳定 ETIMEDOUT。
|
|
119
|
+
const settings = getSettingsManager();
|
|
120
|
+
applyHttpProxySettings(settings.getGlobalSettings().httpProxy);
|
|
121
|
+
configureHttpDispatcher(settings.getHttpIdleTimeoutMs());
|
|
114
122
|
// 检测语义(设计缺陷修复):不再无条件初始化——待命态下 GET /project/config → 409
|
|
115
123
|
// NO_PROJECT_OPEN,前端引导「新建/打开项目」(client store loadConfig 已处理该错误码)
|
|
116
124
|
const project = detectProject(root);
|
|
117
125
|
if (project !== null) {
|
|
118
|
-
setCurrentProject(project); //
|
|
126
|
+
setCurrentProject(project); // 启动即打开(部署场景);null 则保持待命
|
|
119
127
|
// S4.2 启动一致性校验:以大纲节点软删为准补标 DB 关联记录
|
|
120
128
|
//(先 DB 后 JSON 崩溃窗口的幽灵形态兜底,幂等;无软删节点不输出日志)
|
|
121
129
|
logSoftDeleteReconcile(reconcileSoftDelete(project));
|
|
@@ -155,7 +163,7 @@ export async function startServer(projectRoot, options = {}) {
|
|
|
155
163
|
app.route("/api/v1/reference", referenceRoutes); // 参考资料专属端点(scan)
|
|
156
164
|
// Delta 路由(S5.3):追加 / 按节点查询 / compute 状态计算
|
|
157
165
|
app.route("/api/v1/delta", deltaRoutes);
|
|
158
|
-
// 对话路由(U3):会话列表 /
|
|
166
|
+
// 对话路由(U3):会话列表 / 消息历史(按项目隔离;POST SSE 端点属后续切片)
|
|
159
167
|
app.route("/api/v1/chat", chatRoutes);
|
|
160
168
|
// 提案路由(S7.5):confirm/reject(仅内存提案 + 快照重校验 + 项目绑定)
|
|
161
169
|
app.route("/api/v1/proposal", proposalRoutes);
|
|
@@ -275,7 +283,7 @@ const isDirectRun = process.argv[1] !== undefined &&
|
|
|
275
283
|
if (isDirectRun) {
|
|
276
284
|
const projectRoot = process.argv[2] ?? process.cwd();
|
|
277
285
|
const dev = process.env.NODE_ENV === "development";
|
|
278
|
-
// AI_EDITOR_PORT
|
|
286
|
+
// AI_EDITOR_PORT 环境变量可覆盖默认端口(端口策略;测试/多实例场景用,
|
|
279
287
|
// 如打包安装冒烟与 dev server 并存时指定独立端口);非法值(NaN/越界)回退默认 3456
|
|
280
288
|
const port = parsePortEnv(process.env.AI_EDITOR_PORT);
|
|
281
289
|
const handle = await startServer(projectRoot, { dev, ...(port !== undefined ? { port } : {}) });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,gDAAgD;AAChD,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,12 +5,12 @@ import type { ErrorCode } from "@whispering233/ai-editor-shared";
|
|
|
5
5
|
export declare const SERVER_ERROR_CODES: readonly ["INTERNAL_ERROR", "FORBIDDEN", "NOT_FOUND", "NO_PROJECT_OPEN", "PROJECT_ALREADY_EXISTS", "LLM_API_KEY_MISSING"];
|
|
6
6
|
export type ServerErrorCode = (typeof SERVER_ERROR_CODES)[number];
|
|
7
7
|
export type ApiErrorCode = ErrorCode | ServerErrorCode;
|
|
8
|
-
/**
|
|
8
|
+
/** 成功响应包裹 */
|
|
9
9
|
export declare function ok<T>(data: T): {
|
|
10
10
|
success: true;
|
|
11
11
|
data: T;
|
|
12
12
|
};
|
|
13
|
-
/**
|
|
13
|
+
/** 错误响应包裹;fields 仅 VALIDATION_ERROR 附带(校验失败字段路径) */
|
|
14
14
|
export declare function fail(code: ApiErrorCode, message: string, fields?: string[]): {
|
|
15
15
|
success: false;
|
|
16
16
|
error: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/middleware/error.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,wCAAwC;AACxC,eAAO,MAAM,kBAAkB,2HAOrB,CAAC;AACX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,eAAe,CAAC;AAEvD,
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/middleware/error.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,wCAAwC;AACxC,eAAO,MAAM,kBAAkB,2HAOrB,CAAC;AACX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,eAAe,CAAC;AAEvD,aAAa;AACb,wBAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,CAEzD;AAED,oDAAoD;AACpD,wBAAgB,IAAI,CAClB,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CAAE,CAEvF;AAED;;;GAGG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;gBAChB,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM;CAM9E;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,YAAY,CAgB3C"}
|
package/dist/middleware/error.js
CHANGED
|
@@ -15,11 +15,11 @@ export const SERVER_ERROR_CODES = [
|
|
|
15
15
|
"PROJECT_ALREADY_EXISTS",
|
|
16
16
|
"LLM_API_KEY_MISSING", // S7.6:POST /chat 未配置 DeepSeek key——400
|
|
17
17
|
];
|
|
18
|
-
/**
|
|
18
|
+
/** 成功响应包裹 */
|
|
19
19
|
export function ok(data) {
|
|
20
20
|
return { success: true, data };
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
22
|
+
/** 错误响应包裹;fields 仅 VALIDATION_ERROR 附带(校验失败字段路径) */
|
|
23
23
|
export function fail(code, message, fields) {
|
|
24
24
|
return { success: false, error: { code, message, ...(fields ? { fields } : {}) } };
|
|
25
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/middleware/error.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,EAAE;AACF,6EAA6E;AAC7E,wDAAwD;AACxD,uEAAuE;AACvE,sFAAsF;AACtF,wDAAwD;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAK/B,wCAAwC;AACxC,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,gBAAgB;IAChB,WAAW;IACX,WAAW;IACX,iBAAiB;IACjB,wBAAwB;IACxB,qBAAqB,EAAE,wCAAwC;CACvD,CAAC;AAKX,
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/middleware/error.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,EAAE;AACF,6EAA6E;AAC7E,wDAAwD;AACxD,uEAAuE;AACvE,sFAAsF;AACtF,wDAAwD;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAK/B,wCAAwC;AACxC,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,gBAAgB;IAChB,WAAW;IACX,WAAW;IACX,iBAAiB;IACjB,wBAAwB;IACxB,qBAAqB,EAAE,wCAAwC;CACvD,CAAC;AAKX,aAAa;AACb,MAAM,UAAU,EAAE,CAAI,IAAO;IAC3B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,IAAI,CAClB,IAAkB,EAClB,OAAe,EACf,MAAiB;IAEjB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;AACrF,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,MAAM,CAAuB;IAC7B,IAAI,CAAe;IAC5B,YAAY,MAA4B,EAAE,IAAkB,EAAE,OAAe;QAC3E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAChB,IAAI,GAAG,YAAY,SAAS,EAAE,CAAC;YAC7B,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YACjC,4EAA4E;YACvE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/D,OAAO,CAAC,CAAC,IAAI,CACX,IAAI,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,CAAC,EACpE,GAAG,CACJ,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACtC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7F,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -3,7 +3,7 @@ import type { ProjectFileConfig } from "@whispering233/ai-editor-shared";
|
|
|
3
3
|
import { type Db } from "@whispering233/ai-editor-db";
|
|
4
4
|
/** data.db 文件名(项目根目录) */
|
|
5
5
|
export declare const DATA_DB_FILE_NAME = "data.db";
|
|
6
|
-
/** 项目上下文:内存中单一 currentProject
|
|
6
|
+
/** 项目上下文:内存中单一 currentProject(所有 API 共享) */
|
|
7
7
|
export interface ProjectContext {
|
|
8
8
|
root: string;
|
|
9
9
|
config: ProjectFileConfig;
|
|
@@ -32,7 +32,7 @@ export declare function getCurrentProject(): ProjectContext | null;
|
|
|
32
32
|
*/
|
|
33
33
|
export declare function requireCurrentProject(): ProjectContext;
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* 检测并打开项目(启动流程 ④ 修订——设计缺陷修复):
|
|
36
36
|
* project.json 存在 → openDatabase 打开,返回项目上下文(打开语义,部署场景「启动即用」);
|
|
37
37
|
* project.json 不存在 → **返回 null(待命)**——不初始化、不建任何文件(含目录),
|
|
38
38
|
* 由前端 Dashboard 引导走 POST /project/create 或 /project/open(S1.4 开/建页;
|
|
@@ -56,7 +56,7 @@ export declare function detectProject(root: string): ProjectContext | null;
|
|
|
56
56
|
* @returns 已打开的项目上下文(调用方负责 closeProject;create 路由创建后即关闭)
|
|
57
57
|
*/
|
|
58
58
|
export declare function initProject(root: string, configOverride?: Partial<Pick<ProjectFileConfig, "name" | "language">>): ProjectContext;
|
|
59
|
-
/**
|
|
59
|
+
/** 关闭项目:释放数据库连接(WAL + synchronous=FULL 已即时落盘) */
|
|
60
60
|
export declare function closeProject(project: ProjectContext): void;
|
|
61
61
|
/**
|
|
62
62
|
* 来源校验中间件:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/middleware/project.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,OAAO,EAA+C,KAAK,EAAE,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/middleware/project.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,OAAO,EAA+C,KAAK,EAAE,EAAE,MAAM,6BAA6B,CAAC;AASnG,yBAAyB;AACzB,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAK3C,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,EAAE,EAAE,EAAE,CAAC;CACR;AAED,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,8BAA8B;AAC9B,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC;IAAE,SAAS,EAAE,gBAAgB,CAAA;CAAE,CAAC,GAAG,cAAc,CAEtF;AAWD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI,CAUtE;AAED,uBAAuB;AACvB,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAEzD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,cAAc,CAKtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAUjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,GACrE,cAAc,CAoBhB;AAED,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAE1D;AAYD;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,iBAAiB,CASzD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,CAQrD"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// 项目上下文中间件(T6.1 + S1.2)
|
|
2
2
|
//
|
|
3
|
-
//
|
|
3
|
+
// 职责(第 121-122 行 middleware/project.ts「项目路径注入」):
|
|
4
4
|
// 1. detectProject:检测 project.json——存在则打开(部署场景「启动即用」);不存在返回
|
|
5
5
|
// null 待命(不初始化、不建文件,由前端 Dashboard 引导 create/open;S1.4 开/建页依赖)
|
|
6
6
|
// initProject:显式初始化三文件(S1.2 create 路由专用,含建目录 + user_version)
|
|
7
|
-
// 2. currentProject 内存单例(S1.2
|
|
7
|
+
// 2. currentProject 内存单例(S1.2):create/open 切换、close 清空,
|
|
8
8
|
// 模块级可变状态由路由(routes/project.ts)读写,projectMiddleware 从状态注入 Hono 上下文
|
|
9
9
|
// 3. 来源校验:全部请求校验 Origin(缺失时退化为 Host)的 host
|
|
10
10
|
// ∈ {127.0.0.1, localhost, ::1},不匹配拒绝 403;**不校验端口**
|
|
@@ -19,6 +19,7 @@ import { SCHEMA_VERSION } from "@whispering233/ai-editor-db";
|
|
|
19
19
|
import { nowIso } from "@whispering233/ai-editor-db";
|
|
20
20
|
import { HttpError, fail } from "./error.js";
|
|
21
21
|
import { migratePromptToAgents, startAutoBackup, stopAutoBackup } from "../backup.js";
|
|
22
|
+
import { disposeProjectRuntime } from "../chat-runtime.js";
|
|
22
23
|
/** data.db 文件名(项目根目录) */
|
|
23
24
|
export const DATA_DB_FILE_NAME = "data.db";
|
|
24
25
|
/** 来源白名单 host(仅允许本机访问;IPv6 ::1 去括号后比对) */
|
|
@@ -29,7 +30,7 @@ export function getProject(c) {
|
|
|
29
30
|
}
|
|
30
31
|
// ============ currentProject 内存单例(S1.2) ============
|
|
31
32
|
//
|
|
32
|
-
//
|
|
33
|
+
// 语义:单进程内存中只有一个 currentProject,所有 API 调用共享;
|
|
33
34
|
// create/open 切换它、close 清空它。多项目并发打开不在 MVP 范围(backlog)。
|
|
34
35
|
// 模块级可变状态 + 显式读写函数:路由层可读可写,中间件只读注入。
|
|
35
36
|
/** 当前打开的项目(null = 无) */
|
|
@@ -41,6 +42,9 @@ let currentProject = null;
|
|
|
41
42
|
* 调度器 tick 内重读 config 自行跟随。
|
|
42
43
|
*/
|
|
43
44
|
export function setCurrentProject(project) {
|
|
45
|
+
// 旧项目的对话运行时在此释放:中止在途流 → dispose 会话订阅 → 清空提案仓
|
|
46
|
+
//(单点覆盖 create/open/close/restore 全部切换路径,见 chat-runtime.ts)
|
|
47
|
+
disposeProjectRuntime();
|
|
44
48
|
currentProject = project;
|
|
45
49
|
if (project !== null) {
|
|
46
50
|
startAutoBackup(project);
|
|
@@ -64,7 +68,7 @@ export function requireCurrentProject() {
|
|
|
64
68
|
return currentProject;
|
|
65
69
|
}
|
|
66
70
|
/**
|
|
67
|
-
*
|
|
71
|
+
* 检测并打开项目(启动流程 ④ 修订——设计缺陷修复):
|
|
68
72
|
* project.json 存在 → openDatabase 打开,返回项目上下文(打开语义,部署场景「启动即用」);
|
|
69
73
|
* project.json 不存在 → **返回 null(待命)**——不初始化、不建任何文件(含目录),
|
|
70
74
|
* 由前端 Dashboard 引导走 POST /project/create 或 /project/open(S1.4 开/建页;
|
|
@@ -101,7 +105,7 @@ export function initProject(root, configOverride) {
|
|
|
101
105
|
mkdirSync(root, { recursive: true });
|
|
102
106
|
const now = nowIso();
|
|
103
107
|
const config = {
|
|
104
|
-
id: generateProjectId(), // proj- 前缀(
|
|
108
|
+
id: generateProjectId(), // proj- 前缀(id 约定)
|
|
105
109
|
name: basename(root),
|
|
106
110
|
language: "zh",
|
|
107
111
|
schema_version: SCHEMA_VERSION,
|
|
@@ -118,7 +122,7 @@ export function initProject(root, configOverride) {
|
|
|
118
122
|
setUserVersion(db, SCHEMA_VERSION); // 与 project.json/outline.json 的 schema_version 同步
|
|
119
123
|
return { root, config, db };
|
|
120
124
|
}
|
|
121
|
-
/**
|
|
125
|
+
/** 关闭项目:释放数据库连接(WAL + synchronous=FULL 已即时落盘) */
|
|
122
126
|
export function closeProject(project) {
|
|
123
127
|
closeDatabase(project.db);
|
|
124
128
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/middleware/project.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/middleware/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ModelRuntime, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { type ProjectRuntime } from "@whispering233/ai-editor-agent";
|
|
3
|
+
/**
|
|
4
|
+
* 思考强度类型:直接从 pi 的 setter 签名取(pi-coding-agent 包根不导出该类型),
|
|
5
|
+
* 避免跨包手工声明一份可能漂移的联合类型。
|
|
6
|
+
*/
|
|
7
|
+
export type ThinkingLevel = Parameters<SettingsManager["setDefaultThinkingLevel"]>[0];
|
|
8
|
+
/** pi 未配置 defaultThinkingLevel 时的行为与 pi 自身缺省一致(coding-agent core/defaults.ts) */
|
|
9
|
+
export declare const PI_DEFAULT_THINKING_LEVEL: ThinkingLevel;
|
|
10
|
+
/**
|
|
11
|
+
* pi 模型/凭据运行时(懒创建;缺省读 `~/.pi/agent` 的 auth.json / models.json)。
|
|
12
|
+
* 创建期不联网(`allowNetwork` 未开启)——远端目录刷新由 pi 的本地缓存语义承担。
|
|
13
|
+
*/
|
|
14
|
+
export declare function getModelRuntime(): Promise<ModelRuntime>;
|
|
15
|
+
/**
|
|
16
|
+
* 全局 settings(激活模型 / 思考强度 / 重试 / 压缩参数)。
|
|
17
|
+
* `projectTrusted: false`:项目目录可能来自他人,其中的 `.pi/settings.json` 不参与配置;
|
|
18
|
+
* 因此本实例只读写 `~/.pi/agent/settings.json`。
|
|
19
|
+
*/
|
|
20
|
+
export declare function getSettingsManager(): SettingsManager;
|
|
21
|
+
/** 重置单例(测试隔离:HOME / 环境变量变化后必须重建) */
|
|
22
|
+
export declare function resetModelRuntime(): void;
|
|
23
|
+
/** 本地重载模型目录与凭据可用性(不联网):外部编辑 models.json / 环境变量变化后立即可见 */
|
|
24
|
+
export declare function reloadModelRuntime(runtime: ModelRuntime): Promise<void>;
|
|
25
|
+
/** 激活模型选择(provider + model 成对) */
|
|
26
|
+
export interface ActiveModelSelection {
|
|
27
|
+
provider: string;
|
|
28
|
+
modelId: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 激活模型解析(GET /settings/llm 展示与 PUT 校验共用):
|
|
32
|
+
* pi settings 的 defaultProvider+defaultModel → 首个有凭据的可用模型 → null(什么都没配)。
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveActiveSelection(runtime: ModelRuntime, settings: SettingsManager): Promise<ActiveModelSelection | null>;
|
|
35
|
+
/**
|
|
36
|
+
* 把 pi settings 的当前激活模型 / 思考强度应用到既有会话(「配置变更仅影响新请求」落地)。
|
|
37
|
+
* 会话池按项目+会话复用时,设置页改过的模型必须在本轮生效,否则 UI 改了模型而对话仍用旧模型。
|
|
38
|
+
* 最佳努力:任何失败都不阻断本轮(chat 路由仍会做凭据预检并给出明确错误)。
|
|
39
|
+
*/
|
|
40
|
+
export declare function applyActiveSettings(runtime: ProjectRuntime): Promise<void>;
|
|
41
|
+
//# sourceMappingURL=model-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-runtime.d.ts","sourceRoot":"","sources":["../src/model-runtime.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEtF;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,eAAe,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtF,iFAAiF;AACjF,eAAO,MAAM,yBAAyB,EAAE,aAAwB,CAAC;AAKjE;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAGvD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAGpD;AAED,oCAAoC;AACpC,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED,yDAAyD;AACzD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;AAED,kCAAkC;AAClC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAQtC;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBhF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// server:pi 运行时的进程级单例(模型目录 + 凭据 + 全局 settings)
|
|
2
|
+
//
|
|
3
|
+
// 为什么单例:模型目录(内置目录 + `~/.pi/agent/models.json` 覆盖 + 远端 overlay 缓存)、
|
|
4
|
+
// 凭据(`~/.pi/agent/auth.json`)、运行参数(`~/.pi/agent/settings.json`)都只有一份真相源,
|
|
5
|
+
// 每请求/每项目各建一份会重复建目录、重复刷可用性,且设置端点与对话端点会读到不同快照。
|
|
6
|
+
//
|
|
7
|
+
// 配置所有权在 pi(docs/design/config.md):本模块只做「懒创建 + 复用 + 测试重置」,
|
|
8
|
+
// 不缓存、不镜像任何自建配置;项目目录内的 `.pi/` 一律不参与(`projectTrusted: false`)。
|
|
9
|
+
import { ModelRuntime, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
10
|
+
import { resolveAgentDir } from "@whispering233/ai-editor-agent";
|
|
11
|
+
/** pi 未配置 defaultThinkingLevel 时的行为与 pi 自身缺省一致(coding-agent core/defaults.ts) */
|
|
12
|
+
export const PI_DEFAULT_THINKING_LEVEL = "medium";
|
|
13
|
+
let runtimePromise;
|
|
14
|
+
let settingsManager;
|
|
15
|
+
/**
|
|
16
|
+
* pi 模型/凭据运行时(懒创建;缺省读 `~/.pi/agent` 的 auth.json / models.json)。
|
|
17
|
+
* 创建期不联网(`allowNetwork` 未开启)——远端目录刷新由 pi 的本地缓存语义承担。
|
|
18
|
+
*/
|
|
19
|
+
export function getModelRuntime() {
|
|
20
|
+
runtimePromise ??= ModelRuntime.create();
|
|
21
|
+
return runtimePromise;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 全局 settings(激活模型 / 思考强度 / 重试 / 压缩参数)。
|
|
25
|
+
* `projectTrusted: false`:项目目录可能来自他人,其中的 `.pi/settings.json` 不参与配置;
|
|
26
|
+
* 因此本实例只读写 `~/.pi/agent/settings.json`。
|
|
27
|
+
*/
|
|
28
|
+
export function getSettingsManager() {
|
|
29
|
+
settingsManager ??= SettingsManager.create(process.cwd(), resolveAgentDir(), { projectTrusted: false });
|
|
30
|
+
return settingsManager;
|
|
31
|
+
}
|
|
32
|
+
/** 重置单例(测试隔离:HOME / 环境变量变化后必须重建) */
|
|
33
|
+
export function resetModelRuntime() {
|
|
34
|
+
runtimePromise = undefined;
|
|
35
|
+
settingsManager = undefined;
|
|
36
|
+
}
|
|
37
|
+
/** 本地重载模型目录与凭据可用性(不联网):外部编辑 models.json / 环境变量变化后立即可见 */
|
|
38
|
+
export async function reloadModelRuntime(runtime) {
|
|
39
|
+
await runtime.refresh({ allowNetwork: false });
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 激活模型解析(GET /settings/llm 展示与 PUT 校验共用):
|
|
43
|
+
* pi settings 的 defaultProvider+defaultModel → 首个有凭据的可用模型 → null(什么都没配)。
|
|
44
|
+
*/
|
|
45
|
+
export async function resolveActiveSelection(runtime, settings) {
|
|
46
|
+
const provider = settings.getDefaultProvider();
|
|
47
|
+
const modelId = settings.getDefaultModel();
|
|
48
|
+
if (provider !== undefined && modelId !== undefined && runtime.getModel(provider, modelId) !== undefined) {
|
|
49
|
+
return { provider, modelId };
|
|
50
|
+
}
|
|
51
|
+
const first = (await runtime.getAvailable())[0];
|
|
52
|
+
return first === undefined ? null : { provider: first.provider, modelId: first.id };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 把 pi settings 的当前激活模型 / 思考强度应用到既有会话(「配置变更仅影响新请求」落地)。
|
|
56
|
+
* 会话池按项目+会话复用时,设置页改过的模型必须在本轮生效,否则 UI 改了模型而对话仍用旧模型。
|
|
57
|
+
* 最佳努力:任何失败都不阻断本轮(chat 路由仍会做凭据预检并给出明确错误)。
|
|
58
|
+
*/
|
|
59
|
+
export async function applyActiveSettings(runtime) {
|
|
60
|
+
const { modelRuntime, settingsManager: settings, session } = runtime;
|
|
61
|
+
try {
|
|
62
|
+
const selection = await resolveActiveSelection(modelRuntime, settings);
|
|
63
|
+
if (selection !== null) {
|
|
64
|
+
const current = session.model;
|
|
65
|
+
if (current === undefined || current.id !== selection.modelId || current.provider !== selection.provider) {
|
|
66
|
+
const next = modelRuntime.getModel(selection.provider, selection.modelId);
|
|
67
|
+
if (next !== undefined)
|
|
68
|
+
await session.setModel(next);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// 思考强度:per-model 覆盖优先于全局缺省(与 pi 的模型切换语义一致)
|
|
72
|
+
const level = settings.getModelThinkingLevel(selection?.provider ?? "", selection?.modelId ?? "") ??
|
|
73
|
+
settings.getDefaultThinkingLevel();
|
|
74
|
+
if (level !== undefined && session.thinkingLevel !== level)
|
|
75
|
+
session.setThinkingLevel(level);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// 最佳努力:见函数注释
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=model-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-runtime.js","sourceRoot":"","sources":["../src/model-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,9 +7,9 @@ export declare const REFERENCE_TRASH_DIR = ".trash";
|
|
|
7
7
|
/** 文件 mtime 比对容差(毫秒):**仅防御 ISO 毫秒截断 roundtrip**(mtimeMs 浮点 → toISOString
|
|
8
8
|
* 毫秒截断 → getTime 可能差亚毫秒)。与备份体系 1s 容差语义相反——备份容差防「mtime 未刷新
|
|
9
9
|
* 误判有变更」,scan 容差过大会**漏检真实外部修改**(1s 内的改动检测不到),故取最小值。
|
|
10
|
-
* 应用内写入:writeFileAtomic 后 stat 与 scan 读取的 mtime
|
|
10
|
+
* 应用内写入:writeFileAtomic 后 stat 与 scan 读取的 mtime 必然一致(同一文件),严格相等即可。*/
|
|
11
11
|
export declare const REFERENCE_MTIME_TOLERANCE_MS = 2;
|
|
12
|
-
/**
|
|
12
|
+
/** 原子写(同款:临时文件 + fsync + rename;参考资料 md 文件同样禁止直接覆盖) */
|
|
13
13
|
export declare function writeFileAtomic(filePath: string, data: string): void;
|
|
14
14
|
/** 确保 references/ 与 references/.trash/ 存在(幂等) */
|
|
15
15
|
export declare function ensureReferenceDirs(root: string): void;
|
|
@@ -62,8 +62,8 @@ export interface ScanReferenceResult {
|
|
|
62
62
|
* 列表页打开项目提示条用,不触发索引写入/软删) */
|
|
63
63
|
export declare function countUnsyncedReferenceFiles(root: string, db: Db): number;
|
|
64
64
|
/**
|
|
65
|
-
* 扫描重建参考资料索引(POST /api/v1/reference/scan
|
|
66
|
-
* 规则(
|
|
65
|
+
* 扫描重建参考资料索引(POST /api/v1/reference/scan)。
|
|
66
|
+
* 规则(2026-08 修订:软删文件归 .trash/,references/ 下缺失即视为外部删除):
|
|
67
67
|
* 1. 遍历 references/ 顶层 *.md(排除 .trash/):
|
|
68
68
|
* - 非软删索引匹配(kind='file' 且 file_name === 文件名)→ mtime 一致(容差内)跳过;
|
|
69
69
|
* 不一致 → 以文件为准更新(title/category/tags/content/file_mtime/updated_at)
|