@downcity/agent 1.1.317 → 1.1.323
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/agent/Agent.d.ts.map +1 -1
- package/bin/agent/Agent.js +1 -0
- package/bin/agent/Agent.js.map +1 -1
- package/bin/agent/AgentSessions.d.ts +2 -0
- package/bin/agent/AgentSessions.d.ts.map +1 -1
- package/bin/agent/AgentSessions.js +9 -0
- package/bin/agent/AgentSessions.js.map +1 -1
- package/bin/executor/messages/SessionAttachmentMapper.d.ts +15 -7
- package/bin/executor/messages/SessionAttachmentMapper.d.ts.map +1 -1
- package/bin/executor/messages/SessionAttachmentMapper.js +22 -32
- package/bin/executor/messages/SessionAttachmentMapper.js.map +1 -1
- package/bin/executor/types/SessionHistoryMeta.d.ts +2 -0
- package/bin/executor/types/SessionHistoryMeta.d.ts.map +1 -1
- package/bin/index.d.ts +2 -1
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js.map +1 -1
- package/bin/remote/RemoteSession.d.ts +2 -2
- package/bin/remote/RemoteSession.d.ts.map +1 -1
- package/bin/remote/RemoteSession.js +2 -2
- package/bin/remote/RemoteSession.js.map +1 -1
- package/bin/remote/RemoteTransport.d.ts +2 -2
- package/bin/remote/RemoteTransport.d.ts.map +1 -1
- package/bin/remote/transports/HttpRemoteAgentTransport.d.ts +2 -2
- package/bin/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -1
- package/bin/remote/transports/HttpRemoteAgentTransport.js +2 -2
- package/bin/remote/transports/HttpRemoteAgentTransport.js.map +1 -1
- package/bin/remote/transports/RpcClient.d.ts +2 -2
- package/bin/remote/transports/RpcClient.d.ts.map +1 -1
- package/bin/remote/transports/RpcClient.js +2 -2
- package/bin/remote/transports/RpcClient.js.map +1 -1
- package/bin/remote/transports/RpcRemoteAgentTransport.d.ts +2 -2
- package/bin/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -1
- package/bin/remote/transports/RpcRemoteAgentTransport.js +2 -2
- package/bin/remote/transports/RpcRemoteAgentTransport.js.map +1 -1
- package/bin/session/Session.d.ts +6 -4
- package/bin/session/Session.d.ts.map +1 -1
- package/bin/session/Session.js +56 -31
- package/bin/session/Session.js.map +1 -1
- package/bin/session/SessionLoop.d.ts.map +1 -1
- package/bin/session/SessionLoop.js +6 -4
- package/bin/session/SessionLoop.js.map +1 -1
- package/bin/session/SessionMessages.d.ts +9 -3
- package/bin/session/SessionMessages.d.ts.map +1 -1
- package/bin/session/SessionMessages.js +35 -21
- package/bin/session/SessionMessages.js.map +1 -1
- package/bin/session/SessionState.d.ts +23 -10
- package/bin/session/SessionState.d.ts.map +1 -1
- package/bin/session/SessionState.js +129 -51
- package/bin/session/SessionState.js.map +1 -1
- package/bin/session/SessionTitle.d.ts +4 -0
- package/bin/session/SessionTitle.d.ts.map +1 -1
- package/bin/session/SessionTitle.js +5 -1
- package/bin/session/SessionTitle.js.map +1 -1
- package/bin/session/messages/SessionAssistantMessageWriter.d.ts +1 -1
- package/bin/session/messages/SessionAssistantMessageWriter.d.ts.map +1 -1
- package/bin/session/messages/SessionAssistantMessageWriter.js +4 -4
- package/bin/session/messages/SessionAssistantMessageWriter.js.map +1 -1
- package/bin/session/runtime/SessionTitleTask.d.ts +35 -0
- package/bin/session/runtime/SessionTitleTask.d.ts.map +1 -0
- package/bin/session/runtime/SessionTitleTask.js +72 -0
- package/bin/session/runtime/SessionTitleTask.js.map +1 -0
- package/bin/session/storage/Metadata.d.ts.map +1 -1
- package/bin/session/storage/Metadata.js +7 -0
- package/bin/session/storage/Metadata.js.map +1 -1
- package/bin/types/agent/SessionActor.d.ts +3 -3
- package/bin/types/agent/SessionActor.d.ts.map +1 -1
- package/bin/types/agent/SessionTypes.d.ts +20 -0
- package/bin/types/agent/SessionTypes.d.ts.map +1 -1
- package/bin/types/rpc/RpcProtocol.d.ts +2 -1
- package/bin/types/rpc/RpcProtocol.d.ts.map +1 -1
- package/bin/types/sdk/AgentSessionPrompt.d.ts +22 -0
- package/bin/types/sdk/AgentSessionPrompt.d.ts.map +1 -1
- package/bin/types/sdk/AgentSessionPrompt.js.map +1 -1
- package/bin/types/session/SessionCommand.d.ts +2 -0
- package/bin/types/session/SessionCommand.d.ts.map +1 -1
- package/bin/types/session/SessionLocalState.d.ts +3 -0
- package/bin/types/session/SessionLocalState.d.ts.map +1 -1
- package/bin/types/session/SessionMessages.d.ts +5 -0
- package/bin/types/session/SessionMessages.d.ts.map +1 -1
- package/bin/types/session/SessionOptions.d.ts +2 -0
- package/bin/types/session/SessionOptions.d.ts.map +1 -1
- package/bin/types/store/SessionAttachmentStore.d.ts +29 -0
- package/bin/types/store/SessionAttachmentStore.d.ts.map +1 -0
- package/bin/types/store/SessionAttachmentStore.js +15 -0
- package/bin/types/store/SessionAttachmentStore.js.map +1 -0
- package/bin/types/store/SessionStore.d.ts +3 -0
- package/bin/types/store/SessionStore.d.ts.map +1 -1
- package/bin/workspace/store/LocalSessionAttachmentStore.d.ts +25 -0
- package/bin/workspace/store/LocalSessionAttachmentStore.d.ts.map +1 -0
- package/bin/workspace/store/LocalSessionAttachmentStore.js +72 -0
- package/bin/workspace/store/LocalSessionAttachmentStore.js.map +1 -0
- package/bin/workspace/store/LocalSessionStore.d.ts +3 -0
- package/bin/workspace/store/LocalSessionStore.d.ts.map +1 -1
- package/bin/workspace/store/LocalSessionStore.js +8 -1
- package/bin/workspace/store/LocalSessionStore.js.map +1 -1
- package/bin/workspace/store/LocalStorePaths.d.ts +6 -0
- package/bin/workspace/store/LocalStorePaths.d.ts.map +1 -1
- package/bin/workspace/store/LocalStorePaths.js +8 -0
- package/bin/workspace/store/LocalStorePaths.js.map +1 -1
- package/package.json +6 -6
- package/scripts/remote-session-reconnect.test.mjs +25 -0
- package/scripts/session-attachments.test.mjs +101 -0
- package/scripts/session-config-turn-boundary.test.mjs +185 -0
- package/scripts/session-list-title.test.mjs +6 -0
- package/scripts/session-title-event.test.mjs +67 -3
- package/scripts/session-turn-failure.test.mjs +34 -1
- package/src/agent/Agent.ts +1 -0
- package/src/agent/AgentSessions.ts +10 -0
- package/src/executor/messages/SessionAttachmentMapper.ts +24 -37
- package/src/executor/types/SessionHistoryMeta.ts +2 -0
- package/src/index.ts +2 -0
- package/src/remote/RemoteSession.ts +6 -2
- package/src/remote/RemoteTransport.ts +6 -1
- package/src/remote/transports/HttpRemoteAgentTransport.ts +3 -1
- package/src/remote/transports/RpcClient.ts +3 -1
- package/src/remote/transports/RpcRemoteAgentTransport.ts +3 -1
- package/src/session/Session.ts +65 -32
- package/src/session/SessionLoop.ts +6 -3
- package/src/session/SessionMessages.ts +61 -20
- package/src/session/SessionState.ts +150 -59
- package/src/session/SessionTitle.ts +13 -1
- package/src/session/messages/SessionAssistantMessageWriter.ts +7 -3
- package/src/session/runtime/SessionTitleTask.ts +86 -0
- package/src/session/storage/Metadata.ts +10 -0
- package/src/types/agent/SessionActor.ts +3 -2
- package/src/types/agent/SessionTypes.ts +22 -0
- package/src/types/rpc/RpcProtocol.ts +6 -1
- package/src/types/sdk/AgentSessionPrompt.ts +22 -0
- package/src/types/session/SessionCommand.ts +2 -0
- package/src/types/session/SessionLocalState.ts +4 -0
- package/src/types/session/SessionMessages.ts +5 -0
- package/src/types/session/SessionOptions.ts +3 -0
- package/src/types/store/SessionAttachmentStore.ts +29 -0
- package/src/types/store/SessionStore.ts +4 -0
- package/src/workspace/store/LocalSessionAttachmentStore.ts +96 -0
- package/src/workspace/store/LocalSessionStore.ts +13 -0
- package/src/workspace/store/LocalStorePaths.ts +16 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
SessionSegmentSnapshot,
|
|
18
18
|
SessionSegmentSummary,
|
|
19
19
|
} from "@/types/session/SessionSegment.js";
|
|
20
|
+
import type { SessionAttachmentStore } from "@/types/store/SessionAttachmentStore.js";
|
|
20
21
|
|
|
21
22
|
/** 在 Message Store 写事务中创建新消息所需的稳定状态。 */
|
|
22
23
|
export interface SessionMessageCommitState {
|
|
@@ -88,6 +89,9 @@ export interface SessionStore {
|
|
|
88
89
|
/** 当前 Session 的 Message 持久化能力。 */
|
|
89
90
|
readonly messages: SessionMessageStore;
|
|
90
91
|
|
|
92
|
+
/** 当前 Session 的附件持久化能力。 */
|
|
93
|
+
readonly attachments: SessionAttachmentStore;
|
|
94
|
+
|
|
91
95
|
/** 读取 Session Metadata;不存在时返回规范化的初始值。 */
|
|
92
96
|
read_metadata(): Promise<SessionHistoryMetaV1>;
|
|
93
97
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace 内 Session 附件的本地实现。
|
|
3
|
+
*
|
|
4
|
+
* Data URL 在这里解码为文件;Message 层只接收相对 Workspace 根目录的文件引用。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { generate_id } from "@/utils/Id.js";
|
|
9
|
+
import type { FileSystem } from "@/types/workspace/FileSystem.js";
|
|
10
|
+
import type { SessionAttachmentStore } from "@/types/store/SessionAttachmentStore.js";
|
|
11
|
+
|
|
12
|
+
const DATA_URL_PATTERN = /^data:([^;,]+)?((?:;[^;,]+)*),(.*)$/s;
|
|
13
|
+
|
|
14
|
+
const MEDIA_TYPE_EXTENSIONS: Record<string, string> = {
|
|
15
|
+
"image/png": ".png",
|
|
16
|
+
"image/jpeg": ".jpg",
|
|
17
|
+
"image/webp": ".webp",
|
|
18
|
+
"image/gif": ".gif",
|
|
19
|
+
"video/mp4": ".mp4",
|
|
20
|
+
"video/quicktime": ".mov",
|
|
21
|
+
"video/webm": ".webm",
|
|
22
|
+
"application/pdf": ".pdf",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export interface LocalSessionAttachmentStoreOptions {
|
|
26
|
+
/** Workspace 文件能力。 */
|
|
27
|
+
files: FileSystem;
|
|
28
|
+
/** 当前 Session 附件目录的绝对路径。 */
|
|
29
|
+
attachments_dir_path: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Session 附件本地持久化实现。 */
|
|
33
|
+
export class LocalSessionAttachmentStore implements SessionAttachmentStore {
|
|
34
|
+
private readonly files: FileSystem;
|
|
35
|
+
private readonly attachments_dir_path: string;
|
|
36
|
+
|
|
37
|
+
constructor(options: LocalSessionAttachmentStoreOptions) {
|
|
38
|
+
this.files = options.files;
|
|
39
|
+
this.attachments_dir_path = path.resolve(options.attachments_dir_path);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async persist_data_url(input: {
|
|
43
|
+
data_url: string;
|
|
44
|
+
media_type: string;
|
|
45
|
+
filename?: string;
|
|
46
|
+
}): Promise<string> {
|
|
47
|
+
const parsed = parse_data_url(input.data_url, input.media_type);
|
|
48
|
+
const extension = resolve_extension(parsed.media_type, input.filename);
|
|
49
|
+
const attachment_name = `att_${generate_id()}${extension}`;
|
|
50
|
+
const absolute_path = path.join(this.attachments_dir_path, attachment_name);
|
|
51
|
+
await this.files.ensure_directory(this.attachments_dir_path);
|
|
52
|
+
await this.files.write_file_atomically(absolute_path, parsed.bytes);
|
|
53
|
+
return path.relative(this.files.root_path, absolute_path);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function parse_data_url(data_url: string, fallback_media_type: string): {
|
|
58
|
+
media_type: string;
|
|
59
|
+
bytes: Buffer;
|
|
60
|
+
} {
|
|
61
|
+
const match = DATA_URL_PATTERN.exec(String(data_url || "").trim());
|
|
62
|
+
if (!match) throw new Error("Invalid data URL");
|
|
63
|
+
|
|
64
|
+
const media_type = String(match[1] || fallback_media_type || "").trim();
|
|
65
|
+
if (!media_type || !media_type.includes("/")) {
|
|
66
|
+
throw new Error("Data URL requires a valid media type");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const metadata = String(match[2] || "");
|
|
70
|
+
const payload = String(match[3] || "");
|
|
71
|
+
try {
|
|
72
|
+
const normalized_payload = payload.replace(/\s/g, "");
|
|
73
|
+
if (
|
|
74
|
+
metadata.includes(";base64") &&
|
|
75
|
+
(!/^[A-Za-z0-9+/]*={0,2}$/.test(normalized_payload) ||
|
|
76
|
+
normalized_payload.length % 4 === 1)
|
|
77
|
+
) {
|
|
78
|
+
throw new Error("invalid base64 payload");
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
media_type,
|
|
82
|
+
bytes: metadata.includes(";base64")
|
|
83
|
+
? Buffer.from(normalized_payload, "base64")
|
|
84
|
+
: Buffer.from(decodeURIComponent(payload), "utf8"),
|
|
85
|
+
};
|
|
86
|
+
} catch (error) {
|
|
87
|
+
throw new Error(`Invalid data URL payload: ${error instanceof Error ? error.message : String(error)}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function resolve_extension(media_type: string, filename?: string): string {
|
|
92
|
+
const known = MEDIA_TYPE_EXTENSIONS[media_type.toLowerCase()];
|
|
93
|
+
if (known) return known;
|
|
94
|
+
const filename_extension = path.extname(String(filename || "")).toLowerCase();
|
|
95
|
+
return /^[.][a-z0-9]{1,10}$/.test(filename_extension) ? filename_extension : ".bin";
|
|
96
|
+
}
|
|
@@ -12,12 +12,14 @@ import {
|
|
|
12
12
|
get_sdk_agent_session_meta_path,
|
|
13
13
|
get_sdk_agent_session_assistant_message_path,
|
|
14
14
|
get_sdk_agent_session_messages_path,
|
|
15
|
+
get_sdk_agent_session_attachments_dir_path,
|
|
15
16
|
} from "@/workspace/store/LocalStorePaths.js";
|
|
16
17
|
import { normalize_session_metadata } from "@/session/storage/Metadata.js";
|
|
17
18
|
import type { SessionHistoryMetaV1 } from "@/executor/types/SessionHistoryMeta.js";
|
|
18
19
|
import type { SessionStore } from "@/types/store/SessionStore.js";
|
|
19
20
|
import type { FileSystem } from "@/types/workspace/FileSystem.js";
|
|
20
21
|
import type { LocalSessionStoreOptions } from "@/types/store/LocalStore.js";
|
|
22
|
+
import { LocalSessionAttachmentStore } from "@/workspace/store/LocalSessionAttachmentStore.js";
|
|
21
23
|
|
|
22
24
|
/** 本地 Session Store。 */
|
|
23
25
|
export class LocalSessionStore implements SessionStore {
|
|
@@ -27,6 +29,9 @@ export class LocalSessionStore implements SessionStore {
|
|
|
27
29
|
/** 当前 Session 的 JSONL Message Store。 */
|
|
28
30
|
readonly messages: JsonlSessionMessageStore;
|
|
29
31
|
|
|
32
|
+
/** 当前 Session 的附件持久化能力。 */
|
|
33
|
+
readonly attachments: LocalSessionAttachmentStore;
|
|
34
|
+
|
|
30
35
|
/** 当前 Store 与 WorkspaceTools 共用的 Workspace 文件能力。 */
|
|
31
36
|
private readonly files: FileSystem;
|
|
32
37
|
|
|
@@ -51,6 +56,14 @@ export class LocalSessionStore implements SessionStore {
|
|
|
51
56
|
this.session_id,
|
|
52
57
|
),
|
|
53
58
|
});
|
|
59
|
+
this.attachments = new LocalSessionAttachmentStore({
|
|
60
|
+
files: this.files,
|
|
61
|
+
attachments_dir_path: get_sdk_agent_session_attachments_dir_path(
|
|
62
|
+
this.files.root_path,
|
|
63
|
+
this.agent_id,
|
|
64
|
+
this.session_id,
|
|
65
|
+
),
|
|
66
|
+
});
|
|
54
67
|
}
|
|
55
68
|
|
|
56
69
|
/** 读取规范化 Session Metadata。 */
|
|
@@ -161,6 +161,22 @@ export function get_sdk_agent_session_messages_dir_path(
|
|
|
161
161
|
);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* 单个 Session 的附件目录路径。
|
|
166
|
+
*
|
|
167
|
+
* 附件与 Session 目录同生命周期,归档或删除 Session 时随目录一起迁移或清理。
|
|
168
|
+
*/
|
|
169
|
+
export function get_sdk_agent_session_attachments_dir_path(
|
|
170
|
+
workspace_path: string,
|
|
171
|
+
agent_id: string,
|
|
172
|
+
session_id: string,
|
|
173
|
+
): string {
|
|
174
|
+
return path.join(
|
|
175
|
+
get_sdk_agent_session_dir_path(workspace_path, agent_id, session_id),
|
|
176
|
+
"attachments",
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
164
180
|
/**
|
|
165
181
|
* 单个 session 的 Active JSONL 文件路径。
|
|
166
182
|
*/
|