personal-bot 0.2.4 → 0.2.6
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/CONTEXT.md +9 -7
- package/README.md +15 -8
- package/README.zh-CN.md +15 -8
- package/docs/README.md +3 -1
- package/docs/agent-collaboration.md +27 -13
- package/docs/architecture-guidelines.md +2 -2
- package/docs/capability-design.md +6 -4
- package/docs/dsh-implementation-plan.md +158 -0
- package/docs/dsh-support-proposal.md +314 -0
- package/docs/dsh.md +103 -0
- package/docs/file-storage.md +14 -9
- package/docs/history.md +29 -18
- package/docs/installation-design.md +3 -1
- package/docs/interaction-design.md +13 -0
- package/docs/release.md +3 -3
- package/docs/subagent-upgrade-proposal.md +3 -3
- package/docs/technical-design.md +29 -15
- package/docs/validation.md +49 -3
- package/lib/client.js +1071 -0
- package/lib/common/files.d.ts +2 -0
- package/lib/common/files.js +44 -0
- package/lib/common/json.d.ts +6 -0
- package/lib/common/json.js +16 -0
- package/lib/common/markdown.d.ts +5 -0
- package/lib/common/markdown.js +26 -0
- package/lib/common/paths.d.ts +1 -0
- package/lib/common/paths.js +2 -0
- package/lib/common/validation.d.ts +3 -0
- package/lib/common/validation.js +14 -0
- package/lib/common/version.d.ts +3 -0
- package/lib/common/version.js +13 -0
- package/lib/dsh.d.ts +4 -0
- package/lib/dsh.js +22 -0
- package/lib/extension/dsh/agent-events.d.ts +24 -0
- package/lib/extension/dsh/agent-events.js +242 -0
- package/lib/extension/dsh/agent-runtime.d.ts +49 -0
- package/lib/extension/dsh/agent-runtime.js +348 -0
- package/lib/extension/dsh/command.d.ts +4 -0
- package/lib/extension/dsh/command.js +83 -0
- package/lib/extension/dsh/files.d.ts +5 -0
- package/lib/extension/dsh/files.js +67 -0
- package/lib/extension/dsh/history.d.ts +15 -0
- package/lib/extension/dsh/history.js +88 -0
- package/lib/extension/dsh/management.d.ts +21 -0
- package/lib/extension/dsh/management.js +217 -0
- package/lib/extension/dsh/workspace.d.ts +48 -0
- package/lib/extension/dsh/workspace.js +290 -0
- package/lib/integrations/agent-resources.d.ts +1 -0
- package/lib/integrations/agent-resources.js +18 -0
- package/lib/integrations/dsh/dsh-agents.d.ts +30 -0
- package/lib/integrations/dsh/dsh-agents.js +104 -0
- package/lib/integrations/dsh/history-summary.d.ts +11 -0
- package/lib/integrations/dsh/history-summary.js +40 -0
- package/lib/integrations/dsh/history.d.ts +16 -0
- package/lib/integrations/dsh/history.js +156 -0
- package/lib/integrations/dsh/input.d.ts +21 -0
- package/lib/integrations/dsh/input.js +62 -0
- package/lib/integrations/dsh/messages.d.ts +36 -0
- package/lib/integrations/dsh/messages.js +11 -0
- package/lib/integrations/dsh/notifications.d.ts +8 -0
- package/lib/integrations/dsh/notifications.js +55 -0
- package/lib/integrations/dsh/resources.d.ts +10 -0
- package/lib/integrations/dsh/resources.js +41 -0
- package/lib/integrations/dsh/schema.d.ts +7 -0
- package/lib/integrations/dsh/schema.js +28 -0
- package/lib/integrations/dsh/session.d.ts +14 -0
- package/lib/integrations/dsh/session.js +59 -0
- package/lib/integrations/history-summary.d.ts +2 -0
- package/lib/integrations/history-summary.js +21 -0
- package/lib/integrations/process.d.ts +14 -0
- package/lib/integrations/process.js +48 -0
- package/lib/integrations/python-activation.d.ts +2 -0
- package/lib/integrations/python-activation.js +29 -0
- package/lib/integrations/team-context.d.ts +18 -0
- package/lib/integrations/team-context.js +57 -0
- package/lib/model/agent.d.ts +92 -0
- package/lib/model/agent.js +1 -0
- package/lib/model/history.d.ts +43 -0
- package/lib/model/history.js +1 -0
- package/lib/model/team.d.ts +85 -0
- package/lib/model/team.js +1 -0
- package/lib/services/agents/agent-notices.d.ts +13 -0
- package/lib/services/agents/agent-notices.js +25 -0
- package/lib/services/agents/agent-run.d.ts +39 -0
- package/lib/services/agents/agent-run.js +138 -0
- package/lib/services/agents/agent-service.d.ts +166 -0
- package/lib/services/agents/agent-service.js +325 -0
- package/lib/services/agents/team-service.d.ts +168 -0
- package/lib/services/agents/team-service.js +343 -0
- package/lib/services/history/history-service.d.ts +103 -0
- package/lib/services/history/history-service.js +269 -0
- package/lib/services/workspace/python-environment-service.d.ts +15 -0
- package/lib/services/workspace/python-environment-service.js +50 -0
- package/lib/services/workspace/workspace-files.d.ts +2 -0
- package/lib/services/workspace/workspace-files.js +17 -0
- package/lib/services/workspace/workspace-preparation.d.ts +2 -0
- package/lib/services/workspace/workspace-preparation.js +18 -0
- package/lib/storage/agent-files.d.ts +30 -0
- package/lib/storage/agent-files.js +166 -0
- package/lib/storage/atomic-json.d.ts +11 -0
- package/lib/storage/atomic-json.js +101 -0
- package/lib/storage/file-access.d.ts +2 -0
- package/lib/storage/file-access.js +26 -0
- package/lib/storage/history-files.d.ts +10 -0
- package/lib/storage/history-files.js +63 -0
- package/lib/storage/team-files.d.ts +16 -0
- package/lib/storage/team-files.js +111 -0
- package/lib/tools/agents/actions.d.ts +52 -0
- package/lib/tools/agents/actions.js +49 -0
- package/lib/tools/agents/contract.d.ts +163 -0
- package/lib/tools/agents/contract.js +56 -0
- package/lib/tools/agents/dsh-contract.d.ts +52 -0
- package/lib/tools/agents/dsh-contract.js +15 -0
- package/lib/tools/agents/dsh-tool.d.ts +5 -0
- package/lib/tools/agents/dsh-tool.js +38 -0
- package/lib/tools/history/actions.d.ts +70 -0
- package/lib/tools/history/actions.js +7 -0
- package/lib/tools/history/contract.d.ts +81 -0
- package/lib/tools/history/contract.js +32 -0
- package/lib/tools/history/dsh-tool.d.ts +4 -0
- package/lib/tools/history/dsh-tool.js +22 -0
- package/lib/tools/result.d.ts +18 -0
- package/lib/tools/result.js +10 -0
- package/lib/tools/teams/actions.d.ts +24 -0
- package/lib/tools/teams/actions.js +38 -0
- package/lib/tools/teams/contract.d.ts +232 -0
- package/lib/tools/teams/contract.js +67 -0
- package/lib/tools/teams/dsh-tool.d.ts +8 -0
- package/lib/tools/teams/dsh-tool.js +49 -0
- package/lib/ui/dsh/attachments.d.ts +5 -0
- package/lib/ui/dsh/attachments.js +39 -0
- package/lib/ui/dsh/elements.d.ts +17 -0
- package/lib/ui/dsh/elements.js +79 -0
- package/lib/ui/dsh/index.d.ts +4 -0
- package/lib/ui/dsh/index.js +13 -0
- package/lib/ui/dsh/management.d.ts +4 -0
- package/lib/ui/dsh/management.js +711 -0
- package/lib/ui/dsh/remote.d.ts +15 -0
- package/lib/ui/dsh/remote.js +11 -0
- package/lib/ui/dsh/styles.d.ts +1 -0
- package/lib/ui/dsh/styles.js +132 -0
- package/lib/ui/presentation.d.ts +3 -0
- package/lib/ui/presentation.js +12 -0
- package/npm-shrinkwrap.json +11123 -793
- package/package.json +94 -11
- package/python/README.md +6 -6
- package/resources/agents/coordinator.md +1 -1
- package/resources/dsh/cordis.patch.yml +3 -0
- package/resources/prompts/workspace.md +1 -1
- package/resources/references/compute.md +1 -1
- package/resources/references/task-conductor.md +6 -4
- package/resources/skills/provider-connections/SKILL.md +10 -0
- package/scripts/README.md +9 -1
- package/src/dsh.ts +22 -0
- package/src/extension/agent-events.ts +51 -46
- package/src/extension/agents-command.ts +48 -34
- package/src/extension/command.ts +42 -23
- package/src/extension/dsh/agent-events.ts +148 -0
- package/src/extension/dsh/agent-runtime.ts +251 -0
- package/src/extension/dsh/command.ts +78 -0
- package/src/extension/dsh/files.ts +61 -0
- package/src/extension/dsh/history.ts +69 -0
- package/src/extension/dsh/management.ts +108 -0
- package/src/extension/dsh/workspace.ts +206 -0
- package/src/extension/events.ts +6 -4
- package/src/extension/history.ts +15 -12
- package/src/extension/subagent-entry.ts +34 -63
- package/src/extension/teams-command.ts +53 -46
- package/src/integrations/{pi/agent-resources.ts → agent-resources.ts} +2 -2
- package/src/integrations/dsh/dsh-agents.ts +97 -0
- package/src/integrations/dsh/history-summary.ts +43 -0
- package/src/integrations/dsh/history.ts +76 -0
- package/src/integrations/dsh/input.ts +66 -0
- package/src/integrations/dsh/messages.ts +22 -0
- package/src/integrations/dsh/notifications.ts +46 -0
- package/src/integrations/dsh/resources.ts +44 -0
- package/src/integrations/dsh/schema.ts +26 -0
- package/src/integrations/dsh/session.ts +67 -0
- package/src/integrations/history-summary.ts +20 -0
- package/src/integrations/pi/history.ts +4 -14
- package/src/integrations/pi/pi-agents.ts +17 -6
- package/src/integrations/pi/team-context.ts +6 -58
- package/src/integrations/team-context.ts +60 -0
- package/src/model/agent.ts +2 -0
- package/src/model/history.ts +3 -1
- package/src/pbot.ts +1 -1
- package/src/services/agents/agent-notices.ts +28 -0
- package/src/services/agents/agent-run.ts +114 -0
- package/src/services/agents/agent-service.ts +127 -64
- package/src/services/history/history-service.ts +120 -59
- package/src/storage/agent-files.ts +17 -4
- package/src/storage/history-files.ts +30 -5
- package/src/tools/agents/actions.ts +47 -0
- package/src/tools/agents/contract.ts +8 -5
- package/src/tools/agents/dsh-contract.ts +16 -0
- package/src/tools/agents/dsh-tool.ts +41 -0
- package/src/tools/agents/tool.ts +7 -43
- package/src/tools/history/actions.ts +9 -0
- package/src/tools/history/contract.ts +34 -0
- package/src/tools/history/dsh-tool.ts +22 -0
- package/src/tools/history/tool.ts +7 -30
- package/src/tools/teams/actions.ts +38 -0
- package/src/tools/teams/contract.ts +7 -3
- package/src/tools/teams/dsh-tool.ts +55 -0
- package/src/tools/teams/tool.ts +6 -31
- package/src/ui/agent-display.ts +7 -4
- package/src/ui/dsh/attachments.ts +42 -0
- package/src/ui/dsh/elements.ts +50 -0
- package/src/ui/dsh/index.ts +18 -0
- package/src/ui/dsh/management.ts +412 -0
- package/src/ui/dsh/remote.ts +20 -0
- package/src/ui/dsh/styles.ts +132 -0
- package/src/ui/pi/menu.ts +37 -0
- package/src/ui/pi/reader.ts +46 -0
- package/src/ui/presentation.ts +12 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
2
|
+
import { requireThat } from "../../common/validation.js";
|
|
3
|
+
import { openDshAgent, readDshAgentSession, readDshReport } from "./session.js";
|
|
4
|
+
/** Native handles belong to the execution component, independently of browser observers. */
|
|
5
|
+
export class DshAgents {
|
|
6
|
+
ctx;
|
|
7
|
+
parent;
|
|
8
|
+
composition;
|
|
9
|
+
lifetime;
|
|
10
|
+
kind = "dsh";
|
|
11
|
+
#runs = new Map();
|
|
12
|
+
#closed = false;
|
|
13
|
+
constructor(ctx, parent, composition, lifetime) {
|
|
14
|
+
this.ctx = ctx;
|
|
15
|
+
this.parent = parent;
|
|
16
|
+
this.composition = composition;
|
|
17
|
+
this.lifetime = lifetime;
|
|
18
|
+
}
|
|
19
|
+
available() {
|
|
20
|
+
this.lifetime.throwIfAborted();
|
|
21
|
+
requireThat(!this.#closed && this.ctx.agents.get(this.parent.id) === this.parent, "dsh 父会话或执行组件已关闭。");
|
|
22
|
+
}
|
|
23
|
+
alive(id) {
|
|
24
|
+
const run = this.#runs.get(id);
|
|
25
|
+
return Boolean(this.ctx.agents.get(SessionId(id))) || Boolean(run && (run.closing || !run.handle));
|
|
26
|
+
}
|
|
27
|
+
reference(d, reference) {
|
|
28
|
+
requireThat(reference.host === "dsh" && reference.sessionId === d.agentId, "不能接管其他宿主或其他身份的原生会话。");
|
|
29
|
+
}
|
|
30
|
+
async validateSession(d, reference) {
|
|
31
|
+
this.available();
|
|
32
|
+
this.reference(d, reference);
|
|
33
|
+
requireThat(!this.alive(d.agentId), "原生专家仍被占用,不能恢复。");
|
|
34
|
+
await readDshAgentSession(this.ctx, d);
|
|
35
|
+
requireThat(!this.alive(d.agentId), "原生专家仍被占用,不能恢复。");
|
|
36
|
+
}
|
|
37
|
+
async launch(d, directory, generation, reference, resume, signal) {
|
|
38
|
+
this.available();
|
|
39
|
+
this.reference(d, reference);
|
|
40
|
+
requireThat(!this.alive(d.agentId), "dsh 专家仍在运行或释放中。");
|
|
41
|
+
const previous = this.#runs.get(d.agentId);
|
|
42
|
+
if (previous)
|
|
43
|
+
await this.release(d.agentId, previous.generation);
|
|
44
|
+
signal.throwIfAborted();
|
|
45
|
+
this.available();
|
|
46
|
+
const controller = new AbortController();
|
|
47
|
+
const combined = AbortSignal.any([signal, this.lifetime, controller.signal]);
|
|
48
|
+
const opening = Promise.resolve().then(() => openDshAgent(this.ctx, d, this.parent, resume, this.composition.setup(d, directory, generation), combined));
|
|
49
|
+
const run = { generation, controller, opening };
|
|
50
|
+
this.#runs.set(d.agentId, run);
|
|
51
|
+
try {
|
|
52
|
+
run.handle = await opening;
|
|
53
|
+
if (combined.aborted) {
|
|
54
|
+
await this.release(d.agentId, generation);
|
|
55
|
+
combined.throwIfAborted();
|
|
56
|
+
}
|
|
57
|
+
this.composition.ready(run.handle.agent, generation);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (!run.handle && this.#runs.get(d.agentId) === run)
|
|
61
|
+
this.#runs.delete(d.agentId);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
release(id, generation) {
|
|
66
|
+
const run = this.#runs.get(id);
|
|
67
|
+
if (!run)
|
|
68
|
+
return this.ctx.agents.get(SessionId(id)) ? Promise.reject(new Error("原生专家仍由其他执行实例持有;当前组件不能释放。")) : Promise.resolve();
|
|
69
|
+
if (run.generation !== generation)
|
|
70
|
+
return Promise.resolve();
|
|
71
|
+
if (run.closing)
|
|
72
|
+
return run.closing;
|
|
73
|
+
run.controller.abort();
|
|
74
|
+
run.closing = (async () => {
|
|
75
|
+
const handle = run.handle ?? await run.opening.catch(() => undefined);
|
|
76
|
+
let failure;
|
|
77
|
+
if (handle) {
|
|
78
|
+
try {
|
|
79
|
+
await this.composition.stopping(handle.agent, generation);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
failure = error;
|
|
83
|
+
}
|
|
84
|
+
await handle.dispose();
|
|
85
|
+
}
|
|
86
|
+
if (this.#runs.get(id) === run)
|
|
87
|
+
this.#runs.delete(id);
|
|
88
|
+
if (failure)
|
|
89
|
+
throw failure;
|
|
90
|
+
})();
|
|
91
|
+
return run.closing;
|
|
92
|
+
}
|
|
93
|
+
report(d, reference, position) {
|
|
94
|
+
this.reference(d, reference);
|
|
95
|
+
return readDshReport(this.ctx, d, position);
|
|
96
|
+
}
|
|
97
|
+
async close() {
|
|
98
|
+
this.#closed = true;
|
|
99
|
+
const results = await Promise.allSettled([...this.#runs].map(([id, run]) => this.release(id, run.generation)));
|
|
100
|
+
const errors = results.flatMap(r => r.status === "rejected" ? [r.reason] : []);
|
|
101
|
+
if (errors.length)
|
|
102
|
+
throw new AggregateError(errors, "dsh 专家仍有未释放的执行资源。");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { Agent } from "@deepseek-ai/dsh-agent";
|
|
3
|
+
import type { SessionId } from "@deepseek-ai/dsh-session";
|
|
4
|
+
import type { HistorySummarizer } from "../../model/history.js";
|
|
5
|
+
declare module "@deepseek-ai/dsh-llm" {
|
|
6
|
+
interface LlmRequestPurposeMap {
|
|
7
|
+
"pbot-history": true;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Independent text calls through the host's routing and authentication; no Agent or Session messages. */
|
|
11
|
+
export declare function dshHistorySummarizer(ctx: Context, selection: ReturnType<Agent["model"]["current"]>, sessionId: SessionId): HistorySummarizer;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { BlockAssembler } from "@deepseek-ai/dsh-llm";
|
|
4
|
+
import { resourceRoot } from "../../common/paths.js";
|
|
5
|
+
import { requireThat } from "../../common/validation.js";
|
|
6
|
+
import { reduceHistorySummary } from "../history-summary.js";
|
|
7
|
+
/** Independent text calls through the host's routing and authentication; no Agent or Session messages. */
|
|
8
|
+
export function dshHistorySummarizer(ctx, selection, sessionId) {
|
|
9
|
+
return async (text, signal) => {
|
|
10
|
+
requireThat(selection, "请先选择 dsh 模型。");
|
|
11
|
+
signal.throwIfAborted();
|
|
12
|
+
const system = await readFile(join(resourceRoot, "prompts/history-summary.md"), { encoding: "utf8", signal });
|
|
13
|
+
const prepare = () => ctx.llm.prepareCall({ provider: selection.provider, model: selection.model, maxTokens: 2048 }, signal, (controls, model) => ({ ...controls, ...(model.reasoning?.efforts[0] ? { reasoningEffort: model.reasoning.efforts[0].id } : {}) }));
|
|
14
|
+
let first = await prepare();
|
|
15
|
+
const budget = Math.max(2000, Math.min(24000, Math.floor((first.context?.contextWindow ?? 12000) / 2)));
|
|
16
|
+
const ask = async (content, signal) => {
|
|
17
|
+
signal.throwIfAborted();
|
|
18
|
+
const prepared = first ?? await prepare();
|
|
19
|
+
first = undefined;
|
|
20
|
+
const assembler = new BlockAssembler();
|
|
21
|
+
let finished = false;
|
|
22
|
+
for await (const chunk of prepared.stream({ ...prepared.config, system, sessionId, purpose: "pbot-history", signal, tools: [],
|
|
23
|
+
messages: [{ role: "user", content: [{ type: "text", text: content }] }] })) {
|
|
24
|
+
signal.throwIfAborted();
|
|
25
|
+
assembler.push(chunk);
|
|
26
|
+
if (chunk.type === "finish")
|
|
27
|
+
finished = true;
|
|
28
|
+
}
|
|
29
|
+
signal.throwIfAborted();
|
|
30
|
+
const reason = assembler.finish;
|
|
31
|
+
requireThat(finished && reason.kind === "stop", reason.kind === "error" || reason.kind === "aborted" ? reason.failure.message : "历史摘要未正常结束:" + reason.kind);
|
|
32
|
+
const blocks = assembler.blocks();
|
|
33
|
+
requireThat(!blocks.some(block => block.type === "tool-call"), "历史摘要不能执行工具。");
|
|
34
|
+
const answer = blocks.filter(block => block.type === "text").map(block => block.text).join("\n").trim();
|
|
35
|
+
requireThat(answer, "历史摘要为空。");
|
|
36
|
+
return answer;
|
|
37
|
+
};
|
|
38
|
+
return reduceHistorySummary(budget, ask)(text, signal);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { SessionEvent, SessionHeader } from "@deepseek-ai/dsh-session";
|
|
3
|
+
import type { HistoryLocation, HistorySession, HistorySource } from "../../model/history.js";
|
|
4
|
+
/** Archive questions and the final/partial answer; raw tool records stay in the native log. */
|
|
5
|
+
export declare function projectDshHistory(header: SessionHeader, events: readonly SessionEvent[], name?: string): HistorySession;
|
|
6
|
+
export declare class DshHistory implements HistorySource {
|
|
7
|
+
private readonly ctx;
|
|
8
|
+
private readonly root;
|
|
9
|
+
private readonly relatedSessions;
|
|
10
|
+
readonly host = "dsh";
|
|
11
|
+
constructor(ctx: Context, root: string, relatedSessions?: () => string[]);
|
|
12
|
+
scan(location: HistoryLocation, signal?: AbortSignal): Promise<{
|
|
13
|
+
sessions: HistorySession[];
|
|
14
|
+
warnings: string[];
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
53
|
+
import { realpath } from "node:fs/promises";
|
|
54
|
+
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
55
|
+
import { requireThat } from "../../common/validation.js";
|
|
56
|
+
import { finalDshAnswer } from "./messages.js";
|
|
57
|
+
const text = (content) => content.flatMap(block => block.type === "text" ? [block.text] :
|
|
58
|
+
block.type === "image" ? ["[图片 " + (block.attachment.name ?? block.attachment.attachmentId) + "]"] :
|
|
59
|
+
block.type === "file" ? ["[附件 " + (block.attachment.name ?? block.attachment.attachmentId) + "]"] : []).join("\n");
|
|
60
|
+
/** Archive questions and the final/partial answer; raw tool records stay in the native log. */
|
|
61
|
+
export function projectDshHistory(header, events, name = "") {
|
|
62
|
+
const exchanges = [];
|
|
63
|
+
let users = [], answer;
|
|
64
|
+
const finish = (completed = false) => {
|
|
65
|
+
if (users.length) {
|
|
66
|
+
const entries = [...users, ...(answer ? [answer] : [])];
|
|
67
|
+
const body = answer ? answer.data.message.content.filter(block => block.type === "text").map(block => block.text).join("\n") : "";
|
|
68
|
+
exchanges.push({ entryIds: entries.map(event => "dsh:" + event.seq), from: new Date(users[0].time).toISOString(),
|
|
69
|
+
to: new Date(entries.at(-1).time).toISOString(),
|
|
70
|
+
completed: completed && Boolean(answer && finalDshAnswer(answer).trim()),
|
|
71
|
+
text: users.map(event => (event.data.source.kind === "user" ? "用户:\n" : "协调者要求:\n") + text(event.data.content)).join("\n\n") +
|
|
72
|
+
(body ? "\n\n助手:\n" + body : "") });
|
|
73
|
+
}
|
|
74
|
+
users = [];
|
|
75
|
+
answer = undefined;
|
|
76
|
+
};
|
|
77
|
+
for (const event of events) {
|
|
78
|
+
if (event.type === "turn/start")
|
|
79
|
+
finish();
|
|
80
|
+
else if (event.type === "user/message" && ["user", "pbot-input"].includes(event.data.source.kind))
|
|
81
|
+
users.push(event);
|
|
82
|
+
else if (event.type === "assistant/message" && users.length)
|
|
83
|
+
answer = event;
|
|
84
|
+
else if (event.type === "turn/end")
|
|
85
|
+
finish(event.data.reason.kind === "completed");
|
|
86
|
+
}
|
|
87
|
+
finish();
|
|
88
|
+
return { sessionId: header.id, name: name || exchanges[0]?.text.replace(/\s+/g, " ").slice(0, 80) || "",
|
|
89
|
+
branches: exchanges.length ? [exchanges] : [] };
|
|
90
|
+
}
|
|
91
|
+
export class DshHistory {
|
|
92
|
+
ctx;
|
|
93
|
+
root;
|
|
94
|
+
relatedSessions;
|
|
95
|
+
host = "dsh";
|
|
96
|
+
constructor(ctx, root, relatedSessions = () => []) {
|
|
97
|
+
this.ctx = ctx;
|
|
98
|
+
this.root = root;
|
|
99
|
+
this.relatedSessions = relatedSessions;
|
|
100
|
+
}
|
|
101
|
+
async scan(location, signal) {
|
|
102
|
+
requireThat(location.host === "dsh", "dsh 历史只读取 dsh 原生会话。");
|
|
103
|
+
signal?.throwIfAborted();
|
|
104
|
+
const records = await this.ctx.sessionQuery.listSessions(signal), selected = new Set(), warnings = [];
|
|
105
|
+
try {
|
|
106
|
+
for (const id of this.relatedSessions())
|
|
107
|
+
selected.add(id);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
warnings.push("专家引用:" + String(error));
|
|
111
|
+
}
|
|
112
|
+
if (location.sessionId)
|
|
113
|
+
selected.add(location.sessionId);
|
|
114
|
+
for (const record of records) {
|
|
115
|
+
signal?.throwIfAborted();
|
|
116
|
+
if ((record.header.origin !== "subagent" || !record.header.parentSession) && record.header.cwd &&
|
|
117
|
+
await realpath(record.header.cwd).catch(() => record.header.cwd) === this.root)
|
|
118
|
+
selected.add(record.header.id);
|
|
119
|
+
}
|
|
120
|
+
// Native subagents may use a different cwd while still belonging to a workspace's parent.
|
|
121
|
+
for (let changed = true; changed;) {
|
|
122
|
+
changed = false;
|
|
123
|
+
for (const record of records)
|
|
124
|
+
if (record.header.origin === "subagent" && record.header.parentSession && selected.has(record.header.parentSession) && !selected.has(record.header.id)) {
|
|
125
|
+
selected.add(record.header.id);
|
|
126
|
+
changed = true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const sessions = [];
|
|
130
|
+
for (const id of selected) {
|
|
131
|
+
signal?.throwIfAborted();
|
|
132
|
+
try {
|
|
133
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
134
|
+
try {
|
|
135
|
+
const observation = __addDisposableResource(env_1, await this.ctx.sessionQuery.observeSession(SessionId(id), { ...(signal ? { signal } : {}), projectionMode: "none" }), false);
|
|
136
|
+
const title = await this.ctx.sessionQuery.readTitle(SessionId(id), signal);
|
|
137
|
+
const session = projectDshHistory(observation.header, observation.events, title?.title);
|
|
138
|
+
if (session.branches.length)
|
|
139
|
+
sessions.push(session);
|
|
140
|
+
}
|
|
141
|
+
catch (e_1) {
|
|
142
|
+
env_1.error = e_1;
|
|
143
|
+
env_1.hasError = true;
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
__disposeResources(env_1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
signal?.throwIfAborted();
|
|
151
|
+
warnings.push(id + ": " + String(error));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return { sessions, warnings };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import { type FileBlock, type ImageBlock } from "@deepseek-ai/dsh-llm";
|
|
3
|
+
import type { AgentDescriptor, AgentMessage } from "../../model/agent.js";
|
|
4
|
+
import "./messages.js";
|
|
5
|
+
export declare function dshInput(ctx: Context, d: AgentDescriptor, request: AgentMessage, signal: AbortSignal): Promise<{
|
|
6
|
+
content: import("@deepseek-ai/dsh-attachment").AdmittedPromptContentPart[];
|
|
7
|
+
source: {
|
|
8
|
+
kind: "pbot-input";
|
|
9
|
+
form: "relay";
|
|
10
|
+
requestId: string;
|
|
11
|
+
generation: string;
|
|
12
|
+
parentSessionId: string;
|
|
13
|
+
};
|
|
14
|
+
} & Pick<import("@deepseek-ai/dsh-llm").UserMessage, "role" | "id">>;
|
|
15
|
+
/** Command attachments have already passed native upload admission; the caller never supplies arbitrary references. */
|
|
16
|
+
export declare function dshHumanInput(ctx: Context, cwd: string, text: string, files: readonly string[], attachments: readonly (ImageBlock | FileBlock)[], signal: AbortSignal): Promise<{
|
|
17
|
+
content: import("@deepseek-ai/dsh-attachment").AdmittedPromptContentPart[];
|
|
18
|
+
source: {
|
|
19
|
+
kind: "user";
|
|
20
|
+
};
|
|
21
|
+
} & Pick<import("@deepseek-ai/dsh-llm").UserMessage, "role" | "id">>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { basename, extname } from "node:path";
|
|
2
|
+
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
3
|
+
import { requireThat } from "../../common/validation.js";
|
|
4
|
+
import "./messages.js";
|
|
5
|
+
const imageTypes = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp", ".gif": "image/gif" };
|
|
6
|
+
/** Native file attachments remain verbatim; image admission uses the host's policy. */
|
|
7
|
+
async function contentFor(ctx, cwd, message, files, signal) {
|
|
8
|
+
const content = [];
|
|
9
|
+
let imageCount = 0, imageBytes = 0;
|
|
10
|
+
for (const path of files) {
|
|
11
|
+
signal.throwIfAborted();
|
|
12
|
+
const target = await ctx.fs.resolve(path, { cwd, signal });
|
|
13
|
+
const before = await ctx.fs.stat(target, signal);
|
|
14
|
+
requireThat(before?.type === "file", "附件必须是普通文件:" + path);
|
|
15
|
+
const name = basename(path), mediaType = imageTypes[extname(path).toLowerCase()];
|
|
16
|
+
if (mediaType) {
|
|
17
|
+
const limits = ctx.attachments.imageLimits;
|
|
18
|
+
requireThat(++imageCount <= limits.maxImagesPerMessage &&
|
|
19
|
+
(before.size === undefined || imageBytes + before.size <= limits.maxMessageImageBytes), "图片附件超过宿主消息准入上限。");
|
|
20
|
+
const data = await ctx.fs.readBytes(target, signal, limits.maxImageBytes);
|
|
21
|
+
imageBytes += data.byteLength;
|
|
22
|
+
requireThat(imageBytes <= limits.maxMessageImageBytes, "图片附件超过宿主消息准入上限。");
|
|
23
|
+
content.push({ type: "image", mediaType, name, data: Buffer.from(data).toString("base64") });
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
async function* bytes(file) {
|
|
27
|
+
let offset = 0;
|
|
28
|
+
for (;;) {
|
|
29
|
+
signal.throwIfAborted();
|
|
30
|
+
const chunk = await ctx.fs.readByteRange(file, { offset, length: 256 * 1024 }, signal);
|
|
31
|
+
if (!chunk.length)
|
|
32
|
+
break;
|
|
33
|
+
yield chunk;
|
|
34
|
+
offset += chunk.length;
|
|
35
|
+
}
|
|
36
|
+
requireThat((await ctx.fs.stat(file, signal))?.version === before?.version, "读取期间附件已变化:" + path);
|
|
37
|
+
}
|
|
38
|
+
content.push({ type: "file", attachment: await ctx.attachments.saveFileStream({ data: bytes(target), name, signal }) });
|
|
39
|
+
}
|
|
40
|
+
requireThat((await ctx.fs.stat(target, signal))?.version === before.version, "读取期间附件已变化:" + path);
|
|
41
|
+
content.push({ type: "text", text: "附件原始路径:" + JSON.stringify(path) + "。原生附件保留本次文件内容;需要查看时使用宿主提供的附件路径。" });
|
|
42
|
+
}
|
|
43
|
+
content.push({ type: "text", text: message || "请处理所附文件。" });
|
|
44
|
+
const admitted = await ctx.attachments.admitPromptContent(content);
|
|
45
|
+
signal.throwIfAborted();
|
|
46
|
+
return admitted;
|
|
47
|
+
}
|
|
48
|
+
export async function dshInput(ctx, d, request, signal) {
|
|
49
|
+
const content = await contentFor(ctx, d.cwd, request.message, request.files, signal);
|
|
50
|
+
return createUserMessage({ content, source: { kind: "pbot-input", form: "relay",
|
|
51
|
+
requestId: request.requestId, generation: request.generation, parentSessionId: d.parentSessionId } });
|
|
52
|
+
}
|
|
53
|
+
/** Command attachments have already passed native upload admission; the caller never supplies arbitrary references. */
|
|
54
|
+
export async function dshHumanInput(ctx, cwd, text, files, attachments, signal) {
|
|
55
|
+
requireThat(files.length + attachments.length <= 32, "一次最多附加 32 个文件。");
|
|
56
|
+
requireThat(!files.length || !attachments.length, "一次对话请选择服务器文件或输入框附件,不能同时使用。");
|
|
57
|
+
signal.throwIfAborted();
|
|
58
|
+
const content = attachments.length ? [...attachments, { type: "text", text: text || "请处理所附文件。" }] :
|
|
59
|
+
await contentFor(ctx, cwd, text, files, signal);
|
|
60
|
+
signal.throwIfAborted();
|
|
61
|
+
return createUserMessage({ content, source: { kind: "user" } });
|
|
62
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type UserMessage } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
import type { SessionEvent } from "@deepseek-ai/dsh-session";
|
|
3
|
+
/** Producer metadata travels with native messages and never grants task authorization. */
|
|
4
|
+
declare module "@deepseek-ai/dsh-llm" {
|
|
5
|
+
interface MessageSourceMap {
|
|
6
|
+
"pbot-input": {
|
|
7
|
+
kind: "pbot-input";
|
|
8
|
+
form: "relay";
|
|
9
|
+
requestId: string;
|
|
10
|
+
generation: string;
|
|
11
|
+
parentSessionId: string;
|
|
12
|
+
};
|
|
13
|
+
"pbot-team-context": {
|
|
14
|
+
kind: "pbot-team-context";
|
|
15
|
+
form: "relay";
|
|
16
|
+
teamId: string;
|
|
17
|
+
seqs: number[];
|
|
18
|
+
};
|
|
19
|
+
"pbot-results": {
|
|
20
|
+
kind: "pbot-results";
|
|
21
|
+
form: "notice";
|
|
22
|
+
summary: string;
|
|
23
|
+
keys: string[];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export declare function finalDshAnswer(event: Extract<SessionEvent, {
|
|
28
|
+
type: "assistant/message";
|
|
29
|
+
}>): string;
|
|
30
|
+
export declare function requestSource(message: UserMessage, generation: string): {
|
|
31
|
+
kind: "pbot-input";
|
|
32
|
+
form: "relay";
|
|
33
|
+
requestId: string;
|
|
34
|
+
generation: string;
|
|
35
|
+
parentSessionId: string;
|
|
36
|
+
} | undefined;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { lastAssistantStreamChunk } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
export function finalDshAnswer(event) {
|
|
3
|
+
const { message, interrupted, stream } = event.data;
|
|
4
|
+
if (interrupted || message.content.some(block => block.type === "tool-call") || lastAssistantStreamChunk(stream, "finish")?.reason.kind !== "stop")
|
|
5
|
+
return "";
|
|
6
|
+
return message.content.filter(block => block.type === "text").map(block => block.text).join("\n");
|
|
7
|
+
}
|
|
8
|
+
export function requestSource(message, generation) {
|
|
9
|
+
const source = message.source;
|
|
10
|
+
return source.kind === "pbot-input" && source.generation === generation ? source : undefined;
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SessionEvent } from "@deepseek-ai/dsh-session";
|
|
2
|
+
import type { UserMessage } from "@deepseek-ai/dsh-llm";
|
|
3
|
+
import "./messages.js";
|
|
4
|
+
/** Only committed native context or successful model tool results claim notices.
|
|
5
|
+
* PTC inner reads require their enclosing transport to have committed success. */
|
|
6
|
+
export declare function deliveredDshNotices(events: readonly SessionEvent[]): Set<string>;
|
|
7
|
+
/** Pending inbox entries prevent duplicate submission, but are not delivery receipts. */
|
|
8
|
+
export declare function pendingDshNotices(messages: readonly UserMessage[]): string[];
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { object } from "../../common/json.js";
|
|
2
|
+
import "./messages.js";
|
|
3
|
+
function keys(value, field) {
|
|
4
|
+
if (!object(value))
|
|
5
|
+
return [];
|
|
6
|
+
const items = value[field];
|
|
7
|
+
return Array.isArray(items) && items.every(item => typeof item === "string") ? items : [];
|
|
8
|
+
}
|
|
9
|
+
/** Only committed native context or successful model tool results claim notices.
|
|
10
|
+
* PTC inner reads require their enclosing transport to have committed success. */
|
|
11
|
+
export function deliveredDshNotices(events) {
|
|
12
|
+
const delivered = new Set();
|
|
13
|
+
const reads = new Set(), nested = new Map();
|
|
14
|
+
for (const event of events) {
|
|
15
|
+
if (event.type === "turn/start" || event.type === "step/start" || event.type === "turn/end") {
|
|
16
|
+
reads.clear();
|
|
17
|
+
nested.clear();
|
|
18
|
+
}
|
|
19
|
+
if (event.type === "user/message" && event.data.source.kind === "pbot-results") {
|
|
20
|
+
for (const key of keys(event.data.source, "keys"))
|
|
21
|
+
delivered.add(key);
|
|
22
|
+
}
|
|
23
|
+
if (event.type === "tool/call" && event.data.name === "pbot_agent") {
|
|
24
|
+
try {
|
|
25
|
+
const args = JSON.parse(event.data.arguments);
|
|
26
|
+
if (object(args) && args.action === "read")
|
|
27
|
+
reads.add(event.data.callId);
|
|
28
|
+
}
|
|
29
|
+
catch { /* An invalid call cannot claim a report. */ }
|
|
30
|
+
}
|
|
31
|
+
if (event.type === "tool/ptc-dispatch" && event.data.name === "pbot_agent" && !event.data.isError &&
|
|
32
|
+
object(event.data.arguments) && event.data.arguments.action === "read") {
|
|
33
|
+
const values = nested.get(event.data.rootCallId) ?? [];
|
|
34
|
+
values.push(...keys(event.data.meta, "pbotAgentReadKeys"));
|
|
35
|
+
nested.set(event.data.rootCallId, values);
|
|
36
|
+
}
|
|
37
|
+
if (event.type === "tool/result") {
|
|
38
|
+
const message = event.data.message;
|
|
39
|
+
if (!message.isError) {
|
|
40
|
+
if (reads.has(message.toolCallId))
|
|
41
|
+
for (const key of keys(event.data.meta, "pbotAgentReadKeys"))
|
|
42
|
+
delivered.add(key);
|
|
43
|
+
for (const key of nested.get(message.toolCallId) ?? [])
|
|
44
|
+
delivered.add(key);
|
|
45
|
+
}
|
|
46
|
+
reads.delete(message.toolCallId);
|
|
47
|
+
nested.delete(message.toolCallId);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return delivered;
|
|
51
|
+
}
|
|
52
|
+
/** Pending inbox entries prevent duplicate submission, but are not delivery receipts. */
|
|
53
|
+
export function pendingDshNotices(messages) {
|
|
54
|
+
return messages.flatMap(message => message.source.kind === "pbot-results" ? keys(message.source, "keys") : []);
|
|
55
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { Agent } from "@deepseek-ai/dsh-agent";
|
|
3
|
+
import type { AgentOptions } from "../../model/agent.js";
|
|
4
|
+
export declare function dshResources(ctx: Context, agent: Agent, root: string, role: "coordinator" | "general-purpose", python: () => {
|
|
5
|
+
state: string;
|
|
6
|
+
directory?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
}, check: () => void): Promise<void>;
|
|
9
|
+
/** Map the expert's native loadout; this is not isolation from Bash, CLI, or MCP. */
|
|
10
|
+
export declare function dshExpertTools(ctx: Context, agent: Agent, options: AgentOptions): boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { FileSystemSkillProvider } from "@deepseek-ai/dsh-skill-filesystem";
|
|
4
|
+
import { agentText } from "../agent-resources.js";
|
|
5
|
+
import { resourceRoot } from "../../common/paths.js";
|
|
6
|
+
import { requireThat } from "../../common/validation.js";
|
|
7
|
+
export async function dshResources(ctx, agent, root, role, python, check) {
|
|
8
|
+
let text = await agentText(role, root);
|
|
9
|
+
const workspace = await readFile(join(resourceRoot, "prompts/workspace.md"), "utf8");
|
|
10
|
+
check();
|
|
11
|
+
ctx.systemPrompt.section({ name: "pbot:role", order: 1, text: () => text, interpolate: false });
|
|
12
|
+
ctx.systemPrompt.section({ name: "pbot:workspace", order: 2, text: workspace, interpolate: false });
|
|
13
|
+
ctx.systemPrompt.context({ name: "pbot:environment", order: 300, required: true, interpolate: false,
|
|
14
|
+
text: () => JSON.stringify({ host: "dsh", workspaceRoot: root, cwd: ctx.workingDirectory.get(agent.session), resourceRoot, python: python() }) });
|
|
15
|
+
ctx.skills.registerProvider(control => new FileSystemSkillProvider(ctx, control, {
|
|
16
|
+
providerName: "pbot", includeDefaultRoots: false, customSkillDirs: [join(root, ".agents/skills")],
|
|
17
|
+
bundledSkillDir: join(resourceRoot, "skills"), watch: false,
|
|
18
|
+
}));
|
|
19
|
+
ctx.on("agent/pre-step", async (_payload, next) => {
|
|
20
|
+
check();
|
|
21
|
+
text = await agentText(role, root);
|
|
22
|
+
check();
|
|
23
|
+
return next();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/** Map the expert's native loadout; this is not isolation from Bash, CLI, or MCP. */
|
|
27
|
+
export function dshExpertTools(ctx, agent, options) {
|
|
28
|
+
const names = new Set(ctx.tools.definitions(agent).map(tool => tool.name));
|
|
29
|
+
const forbidden = new Set(["pbot_agent", "pbot_team", "pbot_history", "subagent", "list_subagent_models", "list_agents", "send_message", "interrupt_agent"]);
|
|
30
|
+
if (options.noSkills)
|
|
31
|
+
forbidden.add("skill");
|
|
32
|
+
if (options.tools) {
|
|
33
|
+
for (const name of options.tools)
|
|
34
|
+
requireThat((names.has(name) || name === "pbot_team_message") && !forbidden.has(name), "专家工具不可用:" + name);
|
|
35
|
+
ctx.tools.restrict({ allow: options.tools.filter(name => name !== "pbot_team_message") });
|
|
36
|
+
}
|
|
37
|
+
const deny = [...forbidden].filter(name => names.has(name));
|
|
38
|
+
if (deny.length)
|
|
39
|
+
ctx.tools.restrict({ deny });
|
|
40
|
+
return !options.tools || options.tools.includes("pbot_team_message");
|
|
41
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TSchema } from "typebox";
|
|
2
|
+
import type { JsonSchemaNode } from "@deepseek-ai/dsh-tools";
|
|
3
|
+
/** Remove TypeBox's non-JSON metadata before passing a schema to the native host. */
|
|
4
|
+
export declare function dshParameters(value: TSchema): Record<string, unknown>;
|
|
5
|
+
/** Collaboration result unions are disjoint. rc.1 enforces structural oneOf schemas;
|
|
6
|
+
* the producing tool also validates the complete contract, including these bounds. */
|
|
7
|
+
export declare function dshOutputSchema(value: TSchema): JsonSchemaNode;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { requireThat } from "../../common/validation.js";
|
|
2
|
+
/** Remove TypeBox's non-JSON metadata before passing a schema to the native host. */
|
|
3
|
+
export function dshParameters(value) {
|
|
4
|
+
return JSON.parse(JSON.stringify(value));
|
|
5
|
+
}
|
|
6
|
+
/** Collaboration result unions are disjoint. rc.1 enforces structural oneOf schemas;
|
|
7
|
+
* the producing tool also validates the complete contract, including these bounds. */
|
|
8
|
+
export function dshOutputSchema(value) {
|
|
9
|
+
const bounds = new Set(["minLength", "maxLength", "pattern", "minimum", "maximum", "minItems", "maxItems"]);
|
|
10
|
+
const supported = new Set(["type", "required", "additionalProperties", "enum", "const", "description", "title", "default", "examples"]);
|
|
11
|
+
function convert(node) {
|
|
12
|
+
const result = {};
|
|
13
|
+
for (const [key, item] of Object.entries(node)) {
|
|
14
|
+
if (key === "anyOf")
|
|
15
|
+
result.oneOf = item.map(convert);
|
|
16
|
+
else if (key === "properties")
|
|
17
|
+
result.properties = Object.fromEntries(Object.entries(item).map(([name, child]) => [name, convert(child)]));
|
|
18
|
+
else if (key === "items")
|
|
19
|
+
result.items = convert(item);
|
|
20
|
+
else if (!bounds.has(key)) {
|
|
21
|
+
requireThat(supported.has(key), "dsh 输出 schema 不支持字段:" + key);
|
|
22
|
+
result[key] = item;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
return convert(dshParameters(value));
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { Agent, AgentHandle, AgentSetup } from "@deepseek-ai/dsh-agent";
|
|
3
|
+
import type { SessionHeader } from "@deepseek-ai/dsh-session";
|
|
4
|
+
import type { AgentDescriptor } from "../../model/agent.js";
|
|
5
|
+
/** Read access must neither claim a writer nor activate an Agent. */
|
|
6
|
+
export declare function readDshAgentSession(ctx: Context, d: AgentDescriptor): Promise<{
|
|
7
|
+
header: SessionHeader;
|
|
8
|
+
events: readonly import("@deepseek-ai/dsh-session").SessionEvent[];
|
|
9
|
+
}>;
|
|
10
|
+
/** An empty Agent is not recoverable until this native barrier has materialized it. */
|
|
11
|
+
export declare function flushDshAgent(agent: Agent): Promise<void>;
|
|
12
|
+
export declare function openDshAgent(ctx: Context, d: AgentDescriptor, parent: Agent, resume: boolean, setup: AgentSetup, signal: AbortSignal): Promise<AgentHandle>;
|
|
13
|
+
/** A report refers to one durable turn boundary, never the latest answer. */
|
|
14
|
+
export declare function readDshReport(ctx: Context, d: AgentDescriptor, reference: string): Promise<string>;
|