@downcity/agent 1.1.335 → 1.1.338
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/bin/executor/core-engine/CoreEngineContextCompaction.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineContextCompaction.js +14 -64
- package/bin/executor/core-engine/CoreEngineContextCompaction.js.map +1 -1
- package/bin/executor/messages/SessionMessageCodec.js +1 -62
- package/bin/executor/messages/SessionMessageCodec.js.map +1 -1
- package/bin/index.d.ts +1 -1
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js.map +1 -1
- package/bin/session/Session.d.ts.map +1 -1
- package/bin/session/Session.js +23 -2
- package/bin/session/Session.js.map +1 -1
- package/bin/types/agent/SessionTypes.d.ts +9 -1
- package/bin/types/agent/SessionTypes.d.ts.map +1 -1
- package/bin/types/session/SessionMutation.d.ts +15 -2
- package/bin/types/session/SessionMutation.d.ts.map +1 -1
- package/bin/types/session/SessionMutation.js.map +1 -1
- package/bin/workspace/WorkspacePaths.d.ts +0 -22
- package/bin/workspace/WorkspacePaths.d.ts.map +1 -1
- package/bin/workspace/WorkspacePaths.js +2 -30
- package/bin/workspace/WorkspacePaths.js.map +1 -1
- package/package.json +6 -6
- package/scripts/core-engine-context-compaction.test.mjs +4 -4
- package/scripts/session-config-turn-boundary.test.mjs +9 -0
- package/scripts/session-messages.test.mjs +0 -38
- package/src/executor/core-engine/CoreEngineContextCompaction.ts +19 -75
- package/src/executor/messages/SessionMessageCodec.ts +1 -68
- package/src/index.ts +2 -0
- package/src/session/Session.ts +25 -1
- package/src/types/agent/SessionTypes.ts +10 -1
- package/src/types/session/SessionMutation.ts +17 -2
- package/src/workspace/WorkspacePaths.ts +2 -33
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -117,8 +117,8 @@ export type SessionCompactMutation = SessionMutationBase & {
|
|
|
117
117
|
/** 压缩失败时的错误文本。 */
|
|
118
118
|
error?: string;
|
|
119
119
|
};
|
|
120
|
-
/** Session
|
|
121
|
-
export type
|
|
120
|
+
/** Session 标题变化 Mutation。 */
|
|
121
|
+
export type SessionTitleMutation = SessionMutationBase & {
|
|
122
122
|
/** Mutation 层级固定为 session。 */
|
|
123
123
|
variant: "session";
|
|
124
124
|
/** 当前 Session 属性变化类型。 */
|
|
@@ -126,6 +126,19 @@ export type SessionStateMutation = SessionMutationBase & {
|
|
|
126
126
|
/** 当前 Session 最新标题。 */
|
|
127
127
|
title: string;
|
|
128
128
|
};
|
|
129
|
+
/** Session 模型配置变化 Mutation。 */
|
|
130
|
+
export type SessionConfigMutation = SessionMutationBase & {
|
|
131
|
+
/** Mutation 层级固定为 session。 */
|
|
132
|
+
variant: "session";
|
|
133
|
+
/** 当前 Session 属性变化类型。 */
|
|
134
|
+
type: "config";
|
|
135
|
+
/** 当前 Session 已接受的模型可读标签。 */
|
|
136
|
+
model_label?: string;
|
|
137
|
+
/** 当前模型支持的总上下文窗口长度,单位为 token。 */
|
|
138
|
+
model_context_window?: number;
|
|
139
|
+
};
|
|
140
|
+
/** Session 自身属性变化 Mutation。 */
|
|
141
|
+
export type SessionStateMutation = SessionTitleMutation | SessionConfigMutation;
|
|
129
142
|
/** Session 对外唯一实时 Mutation 联合类型。 */
|
|
130
143
|
export type SessionMutation = SessionMessageMutation | SessionPartMutation | SessionDeltaMutation | SessionTurnMutation | SessionCompactMutation | SessionStateMutation;
|
|
131
144
|
/** Session Mutation 订阅回调。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionMutation.d.ts","sourceRoot":"","sources":["../../../src/types/session/SessionMutation.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"SessionMutation.d.ts","sourceRoot":"","sources":["../../../src/types/session/SessionMutation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionMutation.js","sourceRoot":"","sources":["../../../src/types/session/SessionMutation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"SessionMutation.js","sourceRoot":"","sources":["../../../src/types/session/SessionMutation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAqKH,kCAAkC;AAClC,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,SAAS,GAAG,KAAqE,CAAC;IACxF,IAAI,OAAO,SAAS,CAAC,WAAW,KAAK,QAAQ,IAAI,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClG,OAAO,CACL,SAAS,CAAC,OAAO,KAAK,SAAS;QAC/B,SAAS,CAAC,OAAO,KAAK,MAAM;QAC5B,SAAS,CAAC,OAAO,KAAK,OAAO;QAC7B,SAAS,CAAC,OAAO,KAAK,MAAM;QAC5B,SAAS,CAAC,OAAO,KAAK,SAAS;QAC/B,SAAS,CAAC,OAAO,KAAK,SAAS,CAChC,CAAC;AACJ,CAAC"}
|
|
@@ -13,28 +13,6 @@ export declare function get_logs_dir_path(cwd: string): string;
|
|
|
13
13
|
* - 当前使用隐藏命名 `.cache`,避免与用户业务目录混淆。
|
|
14
14
|
*/
|
|
15
15
|
export declare function get_cache_dir_path(cwd: string): string;
|
|
16
|
-
/**
|
|
17
|
-
* 返回 profile 运行态目录路径。
|
|
18
|
-
*
|
|
19
|
-
* 关键点(中文)
|
|
20
|
-
* - 初始化流程会统一创建该目录,并在其中写入 profile 相关文件。
|
|
21
|
-
* - 单独保留目录级 API,避免调用方散落 `path.join(..., "profile")`。
|
|
22
|
-
*/
|
|
23
|
-
export declare function get_downcity_profile_dir_path(cwd: string): string;
|
|
24
|
-
/**
|
|
25
|
-
* 返回 profile 主记忆文件路径。
|
|
26
|
-
*
|
|
27
|
-
* 关键点(中文)
|
|
28
|
-
* - 该文件通常承载主画像或核心长期 profile 信息。
|
|
29
|
-
*/
|
|
30
|
-
export declare function get_downcity_profile_primary_path(cwd: string): string;
|
|
31
|
-
/**
|
|
32
|
-
* 返回 profile 补充记忆文件路径。
|
|
33
|
-
*
|
|
34
|
-
* 关键点(中文)
|
|
35
|
-
* - 该文件用于存放不适合进入主 profile 的补充材料。
|
|
36
|
-
*/
|
|
37
|
-
export declare function get_downcity_profile_other_path(cwd: string): string;
|
|
38
16
|
/**
|
|
39
17
|
* Plugin Schedule JSONL 路径。
|
|
40
18
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkspacePaths.d.ts","sourceRoot":"","sources":["../../src/workspace/WorkspacePaths.ts"],"names":[],"mappings":"AAcA;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED
|
|
1
|
+
{"version":3,"file":"WorkspacePaths.d.ts","sourceRoot":"","sources":["../../src/workspace/WorkspacePaths.ts"],"names":[],"mappings":"AAcA;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/D"}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Workspace 项目路径规则模块。
|
|
3
3
|
*
|
|
4
4
|
* 职责说明(中文)
|
|
5
|
-
* -
|
|
5
|
+
* - 统一管理 Workspace 根目录下的 `.downcity` 运行时状态路径。
|
|
6
6
|
* - 负责把“路径协议”集中到一个模块,避免各领域模块自行拼接字符串。
|
|
7
7
|
* - 为初始化、日志、任务与调试文件等非 Store 子系统提供一致的路径入口。
|
|
8
8
|
*
|
|
9
9
|
* 边界说明(中文)
|
|
10
10
|
* - 这里只负责路径计算,不负责目录创建、文件读写或存在性校验。
|
|
11
|
-
* -
|
|
11
|
+
* - 这里描述的是 Workspace 约定,不涉及 Agent Memory 或平台级全局目录布局。
|
|
12
12
|
*/
|
|
13
13
|
import path from "path";
|
|
14
14
|
/**
|
|
@@ -32,34 +32,6 @@ export function get_logs_dir_path(cwd) {
|
|
|
32
32
|
export function get_cache_dir_path(cwd) {
|
|
33
33
|
return path.join(get_downcity_dir_path(cwd), ".cache");
|
|
34
34
|
}
|
|
35
|
-
/**
|
|
36
|
-
* 返回 profile 运行态目录路径。
|
|
37
|
-
*
|
|
38
|
-
* 关键点(中文)
|
|
39
|
-
* - 初始化流程会统一创建该目录,并在其中写入 profile 相关文件。
|
|
40
|
-
* - 单独保留目录级 API,避免调用方散落 `path.join(..., "profile")`。
|
|
41
|
-
*/
|
|
42
|
-
export function get_downcity_profile_dir_path(cwd) {
|
|
43
|
-
return path.join(get_downcity_dir_path(cwd), "profile");
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* 返回 profile 主记忆文件路径。
|
|
47
|
-
*
|
|
48
|
-
* 关键点(中文)
|
|
49
|
-
* - 该文件通常承载主画像或核心长期 profile 信息。
|
|
50
|
-
*/
|
|
51
|
-
export function get_downcity_profile_primary_path(cwd) {
|
|
52
|
-
return path.join(get_downcity_profile_dir_path(cwd), "Primary.md");
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* 返回 profile 补充记忆文件路径。
|
|
56
|
-
*
|
|
57
|
-
* 关键点(中文)
|
|
58
|
-
* - 该文件用于存放不适合进入主 profile 的补充材料。
|
|
59
|
-
*/
|
|
60
|
-
export function get_downcity_profile_other_path(cwd) {
|
|
61
|
-
return path.join(get_downcity_profile_dir_path(cwd), "other.md");
|
|
62
|
-
}
|
|
63
35
|
/**
|
|
64
36
|
* Plugin Schedule JSONL 路径。
|
|
65
37
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkspacePaths.js","sourceRoot":"","sources":["../../src/workspace/WorkspacePaths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"WorkspacePaths.js","sourceRoot":"","sources":["../../src/workspace/WorkspacePaths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,6BAA6B,CAAC,GAAW;IACvD,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,gBAAgB,CAAC,CAAC;AACjE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B,CAAC,GAAW;IACpD,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAAC,GAAW;IACtD,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CAAC,GAAW;IACrD,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CAAC,GAAW;IACrD,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AACzD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@downcity/agent",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.338",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Downcity Agent 运行时 — 单 Agent 执行壳与本机 RPC 能力",
|
|
6
6
|
"main": "./bin/index.js",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@downcity/shell": "^0.1.
|
|
20
|
-
"@downcity/type": "0.1.
|
|
19
|
+
"@downcity/shell": "^0.1.172",
|
|
20
|
+
"@downcity/type": "0.1.197",
|
|
21
21
|
"ai": "^6.0.193",
|
|
22
22
|
"commander": "^15.0.0",
|
|
23
23
|
"dotenv": "^17.4.2",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"zod": "^4.4.3"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@downcity/sandbox-linux": "^0.1.
|
|
36
|
-
"@downcity/sandbox-macos": "^0.1.
|
|
37
|
-
"@downcity/sandbox-windows-mxc": "^0.1.
|
|
35
|
+
"@downcity/sandbox-linux": "^0.1.35",
|
|
36
|
+
"@downcity/sandbox-macos": "^0.1.35",
|
|
37
|
+
"@downcity/sandbox-windows-mxc": "^0.1.35",
|
|
38
38
|
"@ai-sdk/openai": "^3.0.67",
|
|
39
39
|
"@types/fs-extra": "^11.0.4",
|
|
40
40
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -335,9 +335,9 @@ test("deep compact 删除 reasoning,并完整保留最新并行 tool transacti
|
|
|
335
335
|
const serialized = JSON.stringify(compacted);
|
|
336
336
|
assert.equal(serialized.includes("old reasoning"), false);
|
|
337
337
|
assert.equal(serialized.includes("latest reasoning"), false);
|
|
338
|
-
assert.equal(serialized.includes('"itemId":"rs_latest"'),
|
|
338
|
+
assert.equal(serialized.includes('"itemId":"rs_latest"'), false);
|
|
339
339
|
assert.equal(serialized.includes('"itemId":"msg_latest"'), false);
|
|
340
|
-
assert.equal(serialized.includes('"phase":"final_answer"'),
|
|
340
|
+
assert.equal(serialized.includes('"phase":"final_answer"'), false);
|
|
341
341
|
assert.equal(serialized.includes("latest request"), true);
|
|
342
342
|
assert.equal(serialized.includes("call-a"), true);
|
|
343
343
|
assert.equal(serialized.includes("call-b"), true);
|
|
@@ -359,8 +359,8 @@ test("deep compact 删除 reasoning,并完整保留最新并行 tool transacti
|
|
|
359
359
|
assert.equal(active_tool_text.join("\n").includes("old-call"), false);
|
|
360
360
|
assert.deepEqual([...tool_call_ids].sort(), ["call-a", "call-b"]);
|
|
361
361
|
assert.deepEqual([...tool_result_ids].sort(), ["call-a", "call-b"]);
|
|
362
|
-
assert.equal(serialized.includes('"itemId":"fc_a"'),
|
|
363
|
-
assert.equal(serialized.includes('"resultId":"result_a"'),
|
|
362
|
+
assert.equal(serialized.includes('"itemId":"fc_a"'), false);
|
|
363
|
+
assert.equal(serialized.includes('"resultId":"result_a"'), false);
|
|
364
364
|
});
|
|
365
365
|
|
|
366
366
|
test("单条 assistant 含大量 parts 时也会在消息内部折叠", () => {
|
|
@@ -525,6 +525,15 @@ test("running session model changes apply with steer at the next Session step",
|
|
|
525
525
|
);
|
|
526
526
|
assert.equal(model_actions.length, 1);
|
|
527
527
|
assert.equal(model_actions[0].status, "completed");
|
|
528
|
+
assert.equal(
|
|
529
|
+
mutations.some(
|
|
530
|
+
(mutation) =>
|
|
531
|
+
mutation.variant === "session" &&
|
|
532
|
+
mutation.type === "config" &&
|
|
533
|
+
mutation.model_label === "new-model",
|
|
534
|
+
),
|
|
535
|
+
true,
|
|
536
|
+
);
|
|
528
537
|
assert.equal(
|
|
529
538
|
mutations.some(
|
|
530
539
|
(mutation) =>
|
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
to_executor_history,
|
|
21
21
|
to_executor_ui_message,
|
|
22
22
|
} from "../bin/session/messages/SessionMessageCodec.js";
|
|
23
|
-
import { to_model_messages } from "../bin/executor/messages/SessionMessageCodec.js";
|
|
24
23
|
import { convertToModelMessages } from "ai";
|
|
25
24
|
import { MockLanguageModelV3 } from "ai/test";
|
|
26
25
|
|
|
@@ -1258,43 +1257,6 @@ test("空 Reasoning 携带 Provider metadata 时作为跨轮重放协议 Part
|
|
|
1258
1257
|
assert.deepEqual(assistant.parts[0].provider_metadata, reasoning_metadata);
|
|
1259
1258
|
assert.deepEqual(assistant.parts[1].provider_metadata, message_metadata);
|
|
1260
1259
|
|
|
1261
|
-
const restored = to_executor_ui_message(assistant);
|
|
1262
|
-
const model_messages = await to_model_messages([restored], {});
|
|
1263
|
-
const model_parts = model_messages.flatMap((message) =>
|
|
1264
|
-
Array.isArray(message.content) ? message.content : []
|
|
1265
|
-
);
|
|
1266
|
-
assert.deepEqual(model_parts.map((part) => part.type), ["reasoning", "text"]);
|
|
1267
|
-
assert.deepEqual(model_parts[0].providerOptions, reasoning_metadata);
|
|
1268
|
-
assert.deepEqual(model_parts[1].providerOptions, message_metadata);
|
|
1269
|
-
});
|
|
1270
|
-
|
|
1271
|
-
test("旧 Session 缺少 Reasoning 协议 Part 时移除孤立 msg_* 引用", async () => {
|
|
1272
|
-
const model_messages = await to_model_messages([{
|
|
1273
|
-
id: "assistant-legacy",
|
|
1274
|
-
role: "assistant",
|
|
1275
|
-
metadata: {
|
|
1276
|
-
v: 1,
|
|
1277
|
-
ts: 1,
|
|
1278
|
-
session_id: "legacy-session",
|
|
1279
|
-
source: "egress",
|
|
1280
|
-
kind: "normal",
|
|
1281
|
-
},
|
|
1282
|
-
parts: [{
|
|
1283
|
-
type: "text",
|
|
1284
|
-
text: "已持久化的回复",
|
|
1285
|
-
state: "done",
|
|
1286
|
-
providerMetadata: {
|
|
1287
|
-
openai: { itemId: "msg_orphaned", phase: "final_answer" },
|
|
1288
|
-
},
|
|
1289
|
-
}],
|
|
1290
|
-
}], {});
|
|
1291
|
-
const text_part = model_messages
|
|
1292
|
-
.flatMap((message) => Array.isArray(message.content) ? message.content : [])
|
|
1293
|
-
.find((part) => part.type === "text");
|
|
1294
|
-
assert.equal(text_part.text, "已持久化的回复");
|
|
1295
|
-
assert.deepEqual(text_part.providerOptions, {
|
|
1296
|
-
openai: { phase: "final_answer" },
|
|
1297
|
-
});
|
|
1298
1260
|
});
|
|
1299
1261
|
|
|
1300
1262
|
test("空 Text Start 不会抢占后续 Tool 的真实顺序", async () => {
|
|
@@ -84,9 +84,8 @@ export function deep_compact_model_messages(
|
|
|
84
84
|
const depth = Math.max(0, Math.min(8, Math.floor(compact_depth)));
|
|
85
85
|
const pruned_messages = pruneMessages({
|
|
86
86
|
messages,
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
reasoning: "none",
|
|
87
|
+
// 压缩后只保留语义内容;Provider replay 状态由 Federation 在最终路由后按作用域决定。
|
|
88
|
+
reasoning: "all",
|
|
90
89
|
// 工具事务由本模块按 toolCallId/approvalId 选择;先让 SDK 保留完整关联,
|
|
91
90
|
// 避免 approval response 作为最后一条消息时 SDK 丢掉更早的 tool-call。
|
|
92
91
|
toolCalls: "none",
|
|
@@ -345,8 +344,7 @@ function compact_retained_message(
|
|
|
345
344
|
content: fold_compacted_text(message.content, message_limit),
|
|
346
345
|
} as ModelMessage;
|
|
347
346
|
}
|
|
348
|
-
const
|
|
349
|
-
if (part.type === "reasoning") return false;
|
|
347
|
+
const relevant_parts = message.content.filter((part) => {
|
|
350
348
|
if (part.type === "tool-call" || part.type === "tool-result") {
|
|
351
349
|
return selected_tool_call_ids.has(part.toolCallId);
|
|
352
350
|
}
|
|
@@ -357,26 +355,13 @@ function compact_retained_message(
|
|
|
357
355
|
const tool_call_id = approval_to_tool_call.get(part.approvalId);
|
|
358
356
|
return Boolean(tool_call_id && selected_tool_call_ids.has(tool_call_id));
|
|
359
357
|
}
|
|
360
|
-
return
|
|
358
|
+
return part.type !== "reasoning";
|
|
361
359
|
});
|
|
362
|
-
const requires_provider_reasoning = retained_non_reasoning_parts.some(
|
|
363
|
-
(part) =>
|
|
364
|
-
(part.type === "tool-call" || part.type === "tool-result") &&
|
|
365
|
-
has_openai_item_reference(part as unknown as Record<string, unknown>),
|
|
366
|
-
);
|
|
367
|
-
const relevant_parts = message.content.filter((part) =>
|
|
368
|
-
part.type !== "reasoning" ||
|
|
369
|
-
(requires_provider_reasoning &&
|
|
370
|
-
has_openai_reasoning_replay_data(part as unknown as Record<string, unknown>))
|
|
371
|
-
);
|
|
372
360
|
const part_limit = Math.max(
|
|
373
361
|
MIN_FOLDED_PART_CHARS,
|
|
374
362
|
Math.floor(message_limit / Math.max(1, relevant_parts.length)),
|
|
375
363
|
);
|
|
376
364
|
const content = relevant_parts
|
|
377
|
-
.filter((part) =>
|
|
378
|
-
part.type === "reasoning" || retained_non_reasoning_parts.includes(part)
|
|
379
|
-
)
|
|
380
365
|
.map((part) =>
|
|
381
366
|
compact_model_part(
|
|
382
367
|
part as unknown as Record<string, unknown>,
|
|
@@ -391,29 +376,24 @@ function compact_model_part(
|
|
|
391
376
|
part: Record<string, unknown>,
|
|
392
377
|
part_limit: number,
|
|
393
378
|
): Record<string, unknown> {
|
|
379
|
+
const semantic_part = strip_provider_replay_state(part);
|
|
394
380
|
if (part.type === "text") {
|
|
395
381
|
return {
|
|
396
|
-
...
|
|
382
|
+
...semantic_part,
|
|
397
383
|
text: fold_compacted_text(String(part.text || ""), part_limit),
|
|
398
|
-
...without_openai_item_reference(part),
|
|
399
384
|
};
|
|
400
385
|
}
|
|
401
|
-
if (part.type === "reasoning") {
|
|
402
|
-
// 压缩不保留可见思维文本,但必须保留与最新 Tool 事务关联的
|
|
403
|
-
// Responses API itemId / encrypted content,否则 Provider 会拒绝孤立的 Tool item。
|
|
404
|
-
return { ...part, text: "" };
|
|
405
|
-
}
|
|
406
386
|
if (part.type === "tool-call") {
|
|
407
387
|
return {
|
|
408
|
-
...
|
|
388
|
+
...semantic_part,
|
|
409
389
|
input: fold_compacted_value(part.input, part_limit),
|
|
410
390
|
};
|
|
411
391
|
}
|
|
412
392
|
if (part.type === "tool-result") {
|
|
413
393
|
const serialized_output = safe_stringify(part.output);
|
|
414
|
-
if (serialized_output.length <= part_limit) return
|
|
394
|
+
if (serialized_output.length <= part_limit) return semantic_part;
|
|
415
395
|
return {
|
|
416
|
-
...
|
|
396
|
+
...semantic_part,
|
|
417
397
|
output: {
|
|
418
398
|
type: "text",
|
|
419
399
|
value: fold_compacted_text(serialized_output, part_limit),
|
|
@@ -438,55 +418,19 @@ function compact_model_part(
|
|
|
438
418
|
};
|
|
439
419
|
}
|
|
440
420
|
}
|
|
441
|
-
return
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/** 判断 Part 是否引用 OpenAI Responses API 中已存储的 item。 */
|
|
445
|
-
function has_openai_item_reference(part: Record<string, unknown>): boolean {
|
|
446
|
-
const provider_options = read_record(part.providerOptions);
|
|
447
|
-
const openai_options = read_record(provider_options?.openai);
|
|
448
|
-
return typeof openai_options?.itemId === "string" && openai_options.itemId.length > 0;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/** 判断空 Reasoning 是否仍携带可用于跨轮重放的 Provider 协议数据。 */
|
|
452
|
-
function has_openai_reasoning_replay_data(part: Record<string, unknown>): boolean {
|
|
453
|
-
const provider_options = read_record(part.providerOptions);
|
|
454
|
-
const openai_options = read_record(provider_options?.openai);
|
|
455
|
-
return (
|
|
456
|
-
(typeof openai_options?.itemId === "string" && openai_options.itemId.length > 0) ||
|
|
457
|
-
(typeof openai_options?.reasoningEncryptedContent === "string" &&
|
|
458
|
-
openai_options.reasoningEncryptedContent.length > 0)
|
|
459
|
-
);
|
|
421
|
+
return semantic_part;
|
|
460
422
|
}
|
|
461
423
|
|
|
462
|
-
/**
|
|
463
|
-
|
|
464
|
-
*/
|
|
465
|
-
function without_openai_item_reference(
|
|
424
|
+
/** 压缩后的模型 Part 只作为语义历史传递,不继续携带任何 Provider replay state。 */
|
|
425
|
+
function strip_provider_replay_state(
|
|
466
426
|
part: Record<string, unknown>,
|
|
467
|
-
):
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
const next_provider_options = { ...provider_options };
|
|
475
|
-
if (Object.keys(remaining_openai_options).length > 0) {
|
|
476
|
-
next_provider_options.openai = remaining_openai_options;
|
|
477
|
-
} else {
|
|
478
|
-
delete next_provider_options.openai;
|
|
479
|
-
}
|
|
480
|
-
return Object.keys(next_provider_options).length > 0
|
|
481
|
-
? { providerOptions: next_provider_options }
|
|
482
|
-
: { providerOptions: undefined };
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
/** 安全读取普通 JSON object。 */
|
|
486
|
-
function read_record(value: unknown): Record<string, unknown> | undefined {
|
|
487
|
-
return value && typeof value === "object" && !Array.isArray(value)
|
|
488
|
-
? value as Record<string, unknown>
|
|
489
|
-
: undefined;
|
|
427
|
+
): Record<string, unknown> {
|
|
428
|
+
const {
|
|
429
|
+
providerOptions: _provider_options,
|
|
430
|
+
providerMetadata: _provider_metadata,
|
|
431
|
+
...semantic_part
|
|
432
|
+
} = part;
|
|
433
|
+
return semantic_part;
|
|
490
434
|
}
|
|
491
435
|
|
|
492
436
|
function fold_compacted_value(value: unknown, max_chars: number): unknown {
|
|
@@ -102,72 +102,5 @@ export async function to_model_messages(
|
|
|
102
102
|
// 忽略历史里的不完整工具调用,提升容错性。
|
|
103
103
|
ignoreIncompleteToolCalls: true,
|
|
104
104
|
});
|
|
105
|
-
return
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* 修复旧版 Session 中“只保存 msg_*、未保存必需 rs_*”的孤立 Responses API 引用。
|
|
110
|
-
*
|
|
111
|
-
* 关键点(中文)
|
|
112
|
-
* - reasoning itemId / encrypted content 与 message itemId 存在时,保留 Provider 原子重放。
|
|
113
|
-
* - 只有 message itemId 时,删除该引用并发送已持久化的普通文本,避免 400。
|
|
114
|
-
* - 不修改 Session canonical source,该修复是可重建的 Provider 投影。
|
|
115
|
-
*/
|
|
116
|
-
function repair_orphaned_openai_text_references(
|
|
117
|
-
messages: ModelMessage[],
|
|
118
|
-
): ModelMessage[] {
|
|
119
|
-
return messages.map((message) => {
|
|
120
|
-
if (message.role !== "assistant" || !Array.isArray(message.content)) {
|
|
121
|
-
return message;
|
|
122
|
-
}
|
|
123
|
-
const has_reasoning_replay_data = message.content.some((part) => {
|
|
124
|
-
if (part.type !== "reasoning") return false;
|
|
125
|
-
const openai_options = read_openai_provider_options(part.providerOptions);
|
|
126
|
-
return Boolean(
|
|
127
|
-
(typeof openai_options?.itemId === "string" && openai_options.itemId) ||
|
|
128
|
-
(typeof openai_options?.reasoningEncryptedContent === "string" &&
|
|
129
|
-
openai_options.reasoningEncryptedContent),
|
|
130
|
-
);
|
|
131
|
-
});
|
|
132
|
-
if (has_reasoning_replay_data) return message;
|
|
133
|
-
|
|
134
|
-
let changed = false;
|
|
135
|
-
const content = message.content.map((part) => {
|
|
136
|
-
if (part.type !== "text") return part;
|
|
137
|
-
const provider_options = read_json_record(part.providerOptions);
|
|
138
|
-
const openai_options = read_openai_provider_options(part.providerOptions);
|
|
139
|
-
if (!provider_options || !openai_options || !("itemId" in openai_options)) {
|
|
140
|
-
return part;
|
|
141
|
-
}
|
|
142
|
-
changed = true;
|
|
143
|
-
const { itemId: _item_id, ...remaining_openai_options } = openai_options;
|
|
144
|
-
const next_provider_options = { ...provider_options };
|
|
145
|
-
if (Object.keys(remaining_openai_options).length > 0) {
|
|
146
|
-
next_provider_options.openai = remaining_openai_options;
|
|
147
|
-
} else {
|
|
148
|
-
delete next_provider_options.openai;
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
...part,
|
|
152
|
-
providerOptions: Object.keys(next_provider_options).length > 0
|
|
153
|
-
? next_provider_options
|
|
154
|
-
: undefined,
|
|
155
|
-
};
|
|
156
|
-
});
|
|
157
|
-
return changed ? { ...message, content } as ModelMessage : message;
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/** 读取 Provider options 中的 OpenAI 协议字段。 */
|
|
162
|
-
function read_openai_provider_options(
|
|
163
|
-
value: unknown,
|
|
164
|
-
): Record<string, unknown> | undefined {
|
|
165
|
-
return read_json_record(read_json_record(value)?.openai);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/** 安全读取普通 JSON object。 */
|
|
169
|
-
function read_json_record(value: unknown): Record<string, unknown> | undefined {
|
|
170
|
-
return value && typeof value === "object" && !Array.isArray(value)
|
|
171
|
-
? value as Record<string, unknown>
|
|
172
|
-
: undefined;
|
|
105
|
+
return converted_messages;
|
|
173
106
|
}
|
package/src/index.ts
CHANGED
|
@@ -111,6 +111,7 @@ export {
|
|
|
111
111
|
} from "./types/session/SessionMutation.js";
|
|
112
112
|
export type {
|
|
113
113
|
SessionCompactMutation,
|
|
114
|
+
SessionConfigMutation,
|
|
114
115
|
SessionDeltaMutation,
|
|
115
116
|
SessionMessageMutation,
|
|
116
117
|
SessionMutation,
|
|
@@ -118,6 +119,7 @@ export type {
|
|
|
118
119
|
SessionMutationUnsubscribe,
|
|
119
120
|
SessionPartMutation,
|
|
120
121
|
SessionStateMutation,
|
|
122
|
+
SessionTitleMutation,
|
|
121
123
|
SessionTurnMutation,
|
|
122
124
|
} from "./types/session/SessionMutation.js";
|
|
123
125
|
export type {
|
package/src/session/Session.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { Executor } from "@executor/Executor.js";
|
|
11
11
|
import type { LanguageModel, Tool } from "ai";
|
|
12
12
|
import {
|
|
13
|
+
infer_agent_model_label,
|
|
13
14
|
normalize_agent_model,
|
|
14
15
|
read_agent_model_context_window,
|
|
15
16
|
type AgentModel,
|
|
@@ -300,6 +301,21 @@ export class Session implements AgentSession {
|
|
|
300
301
|
? await this.state.set_approval_mode(next_approval_mode)
|
|
301
302
|
: false;
|
|
302
303
|
if (!model_result && !security_changed) return;
|
|
304
|
+
if (model_result?.changed && publish_mutation) {
|
|
305
|
+
this.events.publish({
|
|
306
|
+
mutation_id: generate_id(),
|
|
307
|
+
variant: "session",
|
|
308
|
+
type: "config",
|
|
309
|
+
session_id: this.id,
|
|
310
|
+
created_at: Date.now(),
|
|
311
|
+
...(model_result.config.model_label
|
|
312
|
+
? { model_label: model_result.config.model_label }
|
|
313
|
+
: {}),
|
|
314
|
+
...(typeof model_result.config.model_context_window === "number"
|
|
315
|
+
? { model_context_window: model_result.config.model_context_window }
|
|
316
|
+
: {}),
|
|
317
|
+
});
|
|
318
|
+
}
|
|
303
319
|
const changed_fields = [
|
|
304
320
|
...(model_result?.changed
|
|
305
321
|
? [`model: ${String(model_result.config.model_label || "configured")}`]
|
|
@@ -510,11 +526,19 @@ export class Session implements AgentSession {
|
|
|
510
526
|
messages: records,
|
|
511
527
|
logger: this.logger,
|
|
512
528
|
});
|
|
529
|
+
const model_label = String(
|
|
530
|
+
metadata_with_title.model_label ||
|
|
531
|
+
infer_agent_model_label(this.get_selected_model()) ||
|
|
532
|
+
"",
|
|
533
|
+
).trim();
|
|
513
534
|
return build_session_info({
|
|
514
535
|
project_root: this.workspace_path,
|
|
515
536
|
agent_id: this.agent_id,
|
|
516
537
|
session_id: this.id,
|
|
517
|
-
metadata:
|
|
538
|
+
metadata: {
|
|
539
|
+
...metadata_with_title,
|
|
540
|
+
...(model_label ? { model_label } : {}),
|
|
541
|
+
},
|
|
518
542
|
messages: records,
|
|
519
543
|
executing: this.is_executing(),
|
|
520
544
|
});
|
|
@@ -110,8 +110,17 @@ export interface AgentSessionSecurityConfig {
|
|
|
110
110
|
|
|
111
111
|
/** 远程 Session 可序列化的动态配置输入。 */
|
|
112
112
|
export interface RemoteSessionSetInput {
|
|
113
|
+
/**
|
|
114
|
+
* 当前远程 Session 使用的宿主模型 ID。
|
|
115
|
+
*
|
|
116
|
+
* 关键点(中文)
|
|
117
|
+
* - 远程边界只传递稳定、可序列化的模型 ID。
|
|
118
|
+
* - 服务端宿主负责把模型 ID 解析为运行时 AgentModel。
|
|
119
|
+
*/
|
|
120
|
+
model_id?: string;
|
|
121
|
+
|
|
113
122
|
/** 当前远程 Session 的安全策略。 */
|
|
114
|
-
security
|
|
123
|
+
security?: AgentSessionSecurityConfig;
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
/** Session 当前安全状态。 */
|
|
@@ -125,8 +125,8 @@ export type SessionCompactMutation = SessionMutationBase & {
|
|
|
125
125
|
error?: string;
|
|
126
126
|
};
|
|
127
127
|
|
|
128
|
-
/** Session
|
|
129
|
-
export type
|
|
128
|
+
/** Session 标题变化 Mutation。 */
|
|
129
|
+
export type SessionTitleMutation = SessionMutationBase & {
|
|
130
130
|
/** Mutation 层级固定为 session。 */
|
|
131
131
|
variant: "session";
|
|
132
132
|
/** 当前 Session 属性变化类型。 */
|
|
@@ -135,6 +135,21 @@ export type SessionStateMutation = SessionMutationBase & {
|
|
|
135
135
|
title: string;
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
+
/** Session 模型配置变化 Mutation。 */
|
|
139
|
+
export type SessionConfigMutation = SessionMutationBase & {
|
|
140
|
+
/** Mutation 层级固定为 session。 */
|
|
141
|
+
variant: "session";
|
|
142
|
+
/** 当前 Session 属性变化类型。 */
|
|
143
|
+
type: "config";
|
|
144
|
+
/** 当前 Session 已接受的模型可读标签。 */
|
|
145
|
+
model_label?: string;
|
|
146
|
+
/** 当前模型支持的总上下文窗口长度,单位为 token。 */
|
|
147
|
+
model_context_window?: number;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/** Session 自身属性变化 Mutation。 */
|
|
151
|
+
export type SessionStateMutation = SessionTitleMutation | SessionConfigMutation;
|
|
152
|
+
|
|
138
153
|
/** Session 对外唯一实时 Mutation 联合类型。 */
|
|
139
154
|
export type SessionMutation =
|
|
140
155
|
| SessionMessageMutation
|