dsh-researchly 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.en.md +31 -0
- package/README.md +30 -2
- package/cordis.yml +4 -0
- package/lib/index.js +338 -0
- package/package.json +36 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 tongfun
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Researchly
|
|
2
|
+
|
|
3
|
+
[中文](README.md) | English
|
|
4
|
+
|
|
5
|
+
> Even with Li Lou’s keen eyesight and Gongshu’s skill, one cannot make true squares and circles without a square and compass. — *Mencius*, “Li Lou I”
|
|
6
|
+
|
|
7
|
+
A DeepSeek Harness plugin that draws on George Pólya’s *How to Solve It* to guide agents through mathematical and physical research in four stages: understand, plan, execute, and review.
|
|
8
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
This plugin guides the root agent through a strict, four-stage process for mathematical and physical research, aiming to reduce hallucinations and errors. If execution or review reveals a problem, the agent returns one or two stages to reconsider its approach. Only the problem statement and phase completion markers are kept in memory; research notes, summaries, and revision history are not stored.
|
|
12
|
+
|
|
13
|
+
## The four stages
|
|
14
|
+
|
|
15
|
+
To investigate a mathematical or physical problem, first establish what is sought, then devise a plan, carry it out, and finally review the result. The four stages are:
|
|
16
|
+
|
|
17
|
+
1. **Understand (`understand`)** — clarify the problem, distinguish the known from the unknown, examine the conditions, and state the notation conventions.
|
|
18
|
+
2. **Plan (`plan`)** — seek connections between the known and the unknown, and use them to devise an approach.
|
|
19
|
+
3. **Execute (`execute`)** — follow the plan step by step, checking the reasoning at each step; if an obstruction prevents completing the calculation, return to the planning stage and revise the plan.
|
|
20
|
+
4. **Review (`look_back`)** — verify the result, examine special cases, and try an independent derivation by another route.
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart TB
|
|
24
|
+
U["1. Understand"] --> P["2. Plan"] --> E["3. Execute"] --> L["4. Review"]
|
|
25
|
+
|
|
26
|
+
E -.->|"calculation obstructed"| P
|
|
27
|
+
L -.->|"execution error, omission, gap in reasoning, or insufficient precision"| E
|
|
28
|
+
L -.->|"invalid assumption, unsuitable method, or overlooked significant factor"| P
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
When a problem requires returning to an earlier stage, call `reopen` before marking the current phase complete. The target phase and all subsequent phases must be completed again. Only the three return paths shown above are allowed; once all four phases are complete, `reopen` can no longer be used. The model decides which phase to return to based on the cause; the tool checks that the transition is allowed and supplies the corresponding guidance.
|
package/README.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Researchly
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
中文 | [English](README.en.md)
|
|
4
|
+
|
|
5
|
+
> 离娄之明,公输子之巧,不以规矩,不能成方圆。——《孟子·离娄上》
|
|
6
|
+
|
|
7
|
+
本插件供 DeepSeek Harness 使用,参考 George Pólya 的书 *How to Solve It* 的方法,引导智能体依理解、规划、执行、复核四步研究数学、物理问题。
|
|
8
|
+
|
|
9
|
+
## 用途
|
|
10
|
+
|
|
11
|
+
本插件引导主智能体按严格的流程研究数学、物理问题,减轻幻觉,减少错误,依次完成四个阶段;执行或复核时若发现问题,便退回前一步或前两步,重新研究。内存中只保留题目及各阶段是否完成的记录,不保存研究笔记、摘要或历次修订。
|
|
12
|
+
|
|
13
|
+
## 求解的四个阶段
|
|
14
|
+
|
|
15
|
+
研究数学、物理问题,先须认清所求为何,继而拟定计划,加以执行,最后复核所得的结果。四步的要点如下:
|
|
16
|
+
|
|
17
|
+
1. **understand(理解)** — 弄清题意,分辨已知与未知,审察条件,并说明符号约定。
|
|
18
|
+
2. **plan(规划)** — 寻求已知与未知之间的联系,据以拟定求解的办法。
|
|
19
|
+
3. **execute(执行)** — 依计划逐步进行,随时检查每一步的根据;若计算受阻,不能完成,便退回第二步,重拟计划。
|
|
20
|
+
4. **look_back(复核)** — 检验所得的结果,考察特殊情形,并试从另一途径独立推导。
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart TB
|
|
24
|
+
U["1. 理解"] --> P["2. 规划"] --> E["3. 执行"] --> L["4. 复核"]
|
|
25
|
+
|
|
26
|
+
E -.->|"计算受阻"| P
|
|
27
|
+
L -.->|"执行有误、有所遗漏、论证不周或精度不足"| E
|
|
28
|
+
L -.->|"假设不成立、方法不合用或漏计重要因素"| P
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
发现问题而须退回时,应在本阶段尚未标为完成之前调用 `reopen`。从退回的阶段起,以下各阶段均须重新完成。退回的途径只限图中三种;四步全部完成以后,便不能再用此法退回。应退至哪一步,由模型按问题的原因决定;工具则检查这一转换是否合乎规定,并换用相应的提示词。
|
package/cordis.yml
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
2
|
+
//#region src/state.ts
|
|
3
|
+
/**
|
|
4
|
+
* Pure workflow state and transitions for the Researchly plugin.
|
|
5
|
+
*
|
|
6
|
+
* Keeping this logic free of Cordis makes the phase gates easy to test and
|
|
7
|
+
* easy to reason about: each function receives a snapshot and returns the next
|
|
8
|
+
* snapshot instead of mutating shared state.
|
|
9
|
+
*
|
|
10
|
+
* @module dsh-researchly/state
|
|
11
|
+
*/
|
|
12
|
+
const PHASES = [
|
|
13
|
+
"understand",
|
|
14
|
+
"plan",
|
|
15
|
+
"execute",
|
|
16
|
+
"look_back"
|
|
17
|
+
];
|
|
18
|
+
const PHASE_TITLES = {
|
|
19
|
+
understand: "Understanding the problem",
|
|
20
|
+
plan: "Devising a plan",
|
|
21
|
+
execute: "Carrying out, checking, and revising",
|
|
22
|
+
look_back: "Looking back"
|
|
23
|
+
};
|
|
24
|
+
/** Detailed phase-specific instructions, shown when that phase becomes active. */
|
|
25
|
+
const PHASE_GUIDANCE = {
|
|
26
|
+
understand: `## Phase: Understanding the problem
|
|
27
|
+
|
|
28
|
+
- Identify the principal parts: the unknown, the data, and the condition.
|
|
29
|
+
- Clarify every word, definition, and convention. Search for unfamiliar terms.
|
|
30
|
+
- Resolve physical and mathematical conventions explicitly, for example metric
|
|
31
|
+
signature, index order, coefficient conventions, and branch choices.
|
|
32
|
+
- Decide whether the condition is sufficient, insufficient, redundant, or
|
|
33
|
+
contradictory. If it is insufficient, say exactly what is missing.
|
|
34
|
+
- Use search and reference tools when definitions or conventions are uncertain.`,
|
|
35
|
+
plan: `## Phase: Devising a plan
|
|
36
|
+
|
|
37
|
+
- Find a connection between the data and the unknown.
|
|
38
|
+
- Ask whether you have seen the same or a related problem before.
|
|
39
|
+
- Look at the unknown and think of familiar problems with the same kind of
|
|
40
|
+
unknown.
|
|
41
|
+
- Use relevant theorems, properties, solved examples, and methods.
|
|
42
|
+
- Introduce auxiliary elements, approximations, or analogous problems when the
|
|
43
|
+
direct connection is not visible.
|
|
44
|
+
- Check that the plan uses all the data and the whole condition.
|
|
45
|
+
- When returning here after an obstruction or a failed check, revise the plan
|
|
46
|
+
before completing this phase and returning to execution. First try to repair
|
|
47
|
+
the direct approach or choose a materially different direct approach.
|
|
48
|
+
- If direct approaches repeatedly reach the same obstruction, use an auxiliary
|
|
49
|
+
problem: simplify, specialise, generalise, relax part of the condition,
|
|
50
|
+
change representation, or extract a transferable result.
|
|
51
|
+
- Delegate independent exploration of candidate methods to focused subagents
|
|
52
|
+
when useful.`,
|
|
53
|
+
execute: `## Phase: Carrying out, checking, and revising
|
|
54
|
+
|
|
55
|
+
1. Carry out the plan and check why each step is valid. A formal proof is not
|
|
56
|
+
necessary for every step; provide further justification when validity is unclear.
|
|
57
|
+
2. If an obstruction prevents completing the calculation, identify it and call
|
|
58
|
+
research_workflow with action "reopen" and phase "plan". Do not mark execute
|
|
59
|
+
complete when the calculation cannot be completed.
|
|
60
|
+
3. Revise the plan in Step 2, then complete plan before resuming execution.
|
|
61
|
+
- Use computation tools for symbolic or numerical work, and delegate independent
|
|
62
|
+
calculations to focused subagents when helpful.`,
|
|
63
|
+
look_back: `## Phase: Looking back
|
|
64
|
+
|
|
65
|
+
- Check the result with special and limiting cases.
|
|
66
|
+
- Test dimensional consistency and expected signs or limits.
|
|
67
|
+
- Check the argument step by step.
|
|
68
|
+
- Try to derive the result differently, or see it at a glance.
|
|
69
|
+
- If checking reveals execution errors, omissions, gaps in the argument, or
|
|
70
|
+
insufficient precision within the existing plan, return to Step 3 to correct
|
|
71
|
+
or complete the affected steps. Examples: the plan requires second order, but
|
|
72
|
+
only first order was calculated; a boundary condition was omitted.
|
|
73
|
+
- If checking reveals invalid key assumptions, inapplicable methods, or missing
|
|
74
|
+
essential contributions in the existing plan, return to Step 2 to revise the
|
|
75
|
+
plan. Examples: non-degenerate perturbation theory was planned, but the energy
|
|
76
|
+
levels are degenerate; a neglected interaction is of the same order as retained
|
|
77
|
+
terms.
|
|
78
|
+
- To return to Step 3 or Step 2, call research_workflow with action "reopen" and
|
|
79
|
+
phase "execute" or "plan", respectively. Explain the cause in your response.
|
|
80
|
+
Do not complete look_back after a failed check; repeat the affected phases and
|
|
81
|
+
check the corrected result before completing look_back.
|
|
82
|
+
- Use a subagent for an independent verification when a different perspective
|
|
83
|
+
would be valuable.`
|
|
84
|
+
};
|
|
85
|
+
function assertPhase(phase) {
|
|
86
|
+
if (!PHASES.includes(phase)) throw new Error(`unknown phase "${phase}"`);
|
|
87
|
+
}
|
|
88
|
+
/** Start a new problem from a non-empty problem statement. */
|
|
89
|
+
function startWorkflow(problem) {
|
|
90
|
+
const trimmed = problem.trim();
|
|
91
|
+
if (trimmed.length === 0) throw new Error("problem must be a non-empty description of the research problem");
|
|
92
|
+
return {
|
|
93
|
+
problem: trimmed,
|
|
94
|
+
completed: []
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** Whether every phase has been completed. */
|
|
98
|
+
function isWorkflowComplete(state) {
|
|
99
|
+
return state.completed.length === PHASES.length;
|
|
100
|
+
}
|
|
101
|
+
/** The first incomplete phase, or undefined when the workflow is complete. */
|
|
102
|
+
function nextPhase(state) {
|
|
103
|
+
return PHASES.find((phase) => !state.completed.includes(phase));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Mark one phase complete.
|
|
107
|
+
*
|
|
108
|
+
* Phases must be completed in the order defined by {@link PHASES}. Duplicate
|
|
109
|
+
* and out-of-order completions are programmer/model errors, so they throw.
|
|
110
|
+
*/
|
|
111
|
+
function completeWorkflowPhase(state, phase) {
|
|
112
|
+
assertPhase(phase);
|
|
113
|
+
if (state.completed.includes(phase)) throw new Error(`phase "${phase}" is already complete`);
|
|
114
|
+
const phaseIndex = PHASES.indexOf(phase);
|
|
115
|
+
const missing = PHASES.slice(0, phaseIndex).find((candidate) => !state.completed.includes(candidate));
|
|
116
|
+
if (missing !== void 0) throw new Error(`phase "${phase}" cannot complete before "${missing}"`);
|
|
117
|
+
return {
|
|
118
|
+
...state,
|
|
119
|
+
completed: [...state.completed, phase]
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** Reopen an earlier phase from the current, unfinished phase. */
|
|
123
|
+
function reopenWorkflowPhase(state, phase) {
|
|
124
|
+
assertPhase(phase);
|
|
125
|
+
const current = nextPhase(state);
|
|
126
|
+
if (!(current === "execute" && phase === "plan" || current === "look_back" && (phase === "execute" || phase === "plan"))) throw new Error(`transition from "${current ?? "complete"}" to "${phase}" is not allowed`);
|
|
127
|
+
return {
|
|
128
|
+
...state,
|
|
129
|
+
completed: PHASES.slice(0, PHASES.indexOf(phase))
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** Render a compact current-state block for the runtime context snapshot. */
|
|
133
|
+
function renderWorkflowStatus(state) {
|
|
134
|
+
const complete = isWorkflowComplete(state);
|
|
135
|
+
const completed = state.completed.length === 0 ? "(none)" : state.completed.map((phase) => PHASE_TITLES[phase]).join(" -> ");
|
|
136
|
+
const current = nextPhase(state);
|
|
137
|
+
return [
|
|
138
|
+
complete ? "Research workflow complete:" : "Active research workflow:",
|
|
139
|
+
`Problem: ${state.problem}`,
|
|
140
|
+
`Completed phases: ${completed}`,
|
|
141
|
+
complete ? "Status: complete" : `Next required phase: ${PHASE_TITLES[current]}`
|
|
142
|
+
].join("\n");
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/index.ts
|
|
146
|
+
const name = "researchly";
|
|
147
|
+
const inject = ["tools", "systemPrompt"];
|
|
148
|
+
const TOOL_NAME = "research_workflow";
|
|
149
|
+
const WORKFLOW_SUMMARY = `# Research workflow
|
|
150
|
+
|
|
151
|
+
You are solving a mathematical or physical research problem. Work through the following four phases in order. Present a final solution after the workflow status reports that all four phases are complete:
|
|
152
|
+
|
|
153
|
+
1. Understanding the problem
|
|
154
|
+
2. Devising a plan
|
|
155
|
+
3. Carrying out, checking, and revising
|
|
156
|
+
4. Looking back
|
|
157
|
+
|
|
158
|
+
The runtime context provides the detailed instructions for whichever phase is currently active.
|
|
159
|
+
|
|
160
|
+
- Use the available tools appropriate to each phase: search or read references, run symbolic or numerical computations, inspect files, and query the web.
|
|
161
|
+
|
|
162
|
+
## Workflow tool protocol
|
|
163
|
+
|
|
164
|
+
- Call \`${TOOL_NAME}\` with action \`start\` before working on a research problem.
|
|
165
|
+
- Call action \`phase_complete\` with the current \`phase\` only after it is genuinely finished, in the order: understand, plan, execute, look_back.
|
|
166
|
+
- If execution is obstructed, call action \`reopen\` with phase \`plan\` before revising the plan.
|
|
167
|
+
- If a check fails, call action \`reopen\` with phase \`execute\` for problems within the existing plan, or \`plan\` for problems with the plan itself. Explain the cause in your response. Do not mark the failed phase complete.
|
|
168
|
+
- After reopening a phase, complete it and the following phases again, including looking back. Use \`reopen\` rather than restarting the problem.
|
|
169
|
+
- Call action \`status\` whenever you need to see the current workflow state.
|
|
170
|
+
- Use action \`abandon\` only when the user explicitly stops the problem.`;
|
|
171
|
+
function isRootAgent(agent) {
|
|
172
|
+
return agent.session.header.origin !== "subagent";
|
|
173
|
+
}
|
|
174
|
+
function completedPhases(state) {
|
|
175
|
+
return [...state.completed];
|
|
176
|
+
}
|
|
177
|
+
function remainingPhases(state) {
|
|
178
|
+
return PHASES.filter((phase) => !state.completed.includes(phase));
|
|
179
|
+
}
|
|
180
|
+
function resultFor(message, state, active = state !== void 0 && !isWorkflowComplete(state)) {
|
|
181
|
+
return {
|
|
182
|
+
message,
|
|
183
|
+
active,
|
|
184
|
+
...state === void 0 ? {} : { problem: state.problem },
|
|
185
|
+
completed: state === void 0 ? [] : completedPhases(state),
|
|
186
|
+
remaining: state === void 0 ? [...PHASES] : remainingPhases(state)
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function requireActive(workflows, agent) {
|
|
190
|
+
const state = workflows.get(agent.id);
|
|
191
|
+
if (state === void 0) throw new Error(`no active research workflow; call ${TOOL_NAME} with action "start" first`);
|
|
192
|
+
if (isWorkflowComplete(state)) throw new Error(`this research workflow is already complete; call ${TOOL_NAME} with action "start" to begin a new problem`);
|
|
193
|
+
return state;
|
|
194
|
+
}
|
|
195
|
+
function requirePhase(value) {
|
|
196
|
+
if (typeof value !== "string" || !PHASES.includes(value)) throw new Error(`phase must be one of: ${PHASES.join(", ")}`);
|
|
197
|
+
return value;
|
|
198
|
+
}
|
|
199
|
+
function apply(ctx) {
|
|
200
|
+
const workflows = /* @__PURE__ */ new Map();
|
|
201
|
+
ctx.systemPrompt.section({
|
|
202
|
+
name: "research:workflow",
|
|
203
|
+
order: ctx.systemPrompt.getSectionOrder("PLAN_POLICY") + 10,
|
|
204
|
+
text: `Use \`research_workflow\` only when at least one of the following is true:
|
|
205
|
+
1. User explicitly asks to use it. In that case, call \`research_workflow\` with action "start". 2. The task is obviously beyond ordinary textbook exercise level: solving it requires a non-standard method, several connected steps, resolving ambiguous definitions/conventions, or checking the result through non-trivial limits. 3. The task has a real research background: it asks you to verify, apply, or extend a result from a paper/research context, or it's part of an ongoing research project.
|
|
206
|
+
Do NOT use this tool for ordinary exercise-level work such as a direct integral, easy simplification/substitution, standard equation, or a textbook proof whose method is already clear.`
|
|
207
|
+
});
|
|
208
|
+
ctx.systemPrompt.context({
|
|
209
|
+
name: "research:workflow-status",
|
|
210
|
+
order: ctx.systemPrompt.getContextOrder("SUBAGENT_DELEGATION") + 10,
|
|
211
|
+
text: (context) => {
|
|
212
|
+
const agent = context.agent;
|
|
213
|
+
if (agent === void 0 || !isRootAgent(agent)) return "";
|
|
214
|
+
const state = workflows.get(agent.id);
|
|
215
|
+
if (state === void 0) return "";
|
|
216
|
+
const status = renderWorkflowStatus(state);
|
|
217
|
+
const phase = nextPhase(state);
|
|
218
|
+
const guidance = phase === void 0 ? status : `${status}\n\n${PHASE_GUIDANCE[phase]}`;
|
|
219
|
+
return `${WORKFLOW_SUMMARY}\n\n${guidance}`;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
ctx.on("agent/disposed", ({ agent }) => {
|
|
223
|
+
workflows.delete(agent.id);
|
|
224
|
+
});
|
|
225
|
+
ctx.on("agent/turn-stopping", ({ agent }) => {
|
|
226
|
+
if (!isRootAgent(agent)) return;
|
|
227
|
+
const state = workflows.get(agent.id);
|
|
228
|
+
if (state === void 0 || isWorkflowComplete(state)) return;
|
|
229
|
+
const phase = nextPhase(state);
|
|
230
|
+
if (phase === void 0) return;
|
|
231
|
+
agent.steer({
|
|
232
|
+
content: [{
|
|
233
|
+
type: "text",
|
|
234
|
+
text: `The research workflow is still active. Work on "${PHASE_TITLES[phase]}" and call ${TOOL_NAME} with action "phase_complete" only when it is finished. If execution is obstructed, reopen "plan"; if a check fails, reopen "execute" or "plan" according to the cause. Do not mark a failed phase complete. Use action "abandon" only if the user has explicitly stopped this problem.`
|
|
235
|
+
}],
|
|
236
|
+
source: {
|
|
237
|
+
kind: "plugin",
|
|
238
|
+
plugin: name
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
ctx.tools.register(defineTool({
|
|
243
|
+
name: TOOL_NAME,
|
|
244
|
+
description: `Guide a four-phase research workflow. Call start, then complete phases in order: understand, plan, execute, look_back. Use reopen to return from execute to plan, or from look_back to execute or plan. Use status to inspect progress, and abandon only when the user explicitly stops the problem.`,
|
|
245
|
+
parameters: {
|
|
246
|
+
action: {
|
|
247
|
+
type: "string",
|
|
248
|
+
required: true,
|
|
249
|
+
enum: [
|
|
250
|
+
"start",
|
|
251
|
+
"status",
|
|
252
|
+
"phase_complete",
|
|
253
|
+
"reopen",
|
|
254
|
+
"abandon"
|
|
255
|
+
],
|
|
256
|
+
description: "The workflow action to perform."
|
|
257
|
+
},
|
|
258
|
+
problem: {
|
|
259
|
+
type: "string",
|
|
260
|
+
description: "Required for action \"start\": the research problem to solve."
|
|
261
|
+
},
|
|
262
|
+
phase: {
|
|
263
|
+
type: "string",
|
|
264
|
+
enum: [...PHASES],
|
|
265
|
+
description: "Required for \"phase_complete\": the current phase. Required for \"reopen\": the earlier phase to return to (plan or execute)."
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
output: {
|
|
269
|
+
schema: {
|
|
270
|
+
type: "object",
|
|
271
|
+
additionalProperties: false,
|
|
272
|
+
properties: {
|
|
273
|
+
message: {
|
|
274
|
+
type: "string",
|
|
275
|
+
required: true
|
|
276
|
+
},
|
|
277
|
+
active: {
|
|
278
|
+
type: "boolean",
|
|
279
|
+
required: true
|
|
280
|
+
},
|
|
281
|
+
problem: { type: "string" },
|
|
282
|
+
completed: {
|
|
283
|
+
type: "array",
|
|
284
|
+
required: true,
|
|
285
|
+
items: { type: "string" }
|
|
286
|
+
},
|
|
287
|
+
remaining: {
|
|
288
|
+
type: "array",
|
|
289
|
+
required: true,
|
|
290
|
+
items: { type: "string" }
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
render: (_args, value) => [{
|
|
295
|
+
type: "text",
|
|
296
|
+
text: value.message
|
|
297
|
+
}]
|
|
298
|
+
},
|
|
299
|
+
async execute(args, exec) {
|
|
300
|
+
const agent = exec.agent;
|
|
301
|
+
if (agent === void 0) throw new Error(`${TOOL_NAME} requires a calling agent`);
|
|
302
|
+
if (!isRootAgent(agent)) throw new Error(`${TOOL_NAME} is only available to the root researcher; subagents should work on focused delegated subtasks`);
|
|
303
|
+
const action = args.action;
|
|
304
|
+
if (action === "start") {
|
|
305
|
+
if (typeof args.problem !== "string") throw new Error("action \"start\" requires a non-empty problem");
|
|
306
|
+
const previous = workflows.get(agent.id);
|
|
307
|
+
if (previous !== void 0 && !isWorkflowComplete(previous)) throw new Error("a research workflow is already active; call status first, or abandon it explicitly");
|
|
308
|
+
const state = startWorkflow(args.problem);
|
|
309
|
+
workflows.set(agent.id, state);
|
|
310
|
+
return resultFor("Research workflow started. Complete the phases in order: understand, plan, execute, look_back.", state, true);
|
|
311
|
+
}
|
|
312
|
+
if (action === "status") {
|
|
313
|
+
const state = workflows.get(agent.id);
|
|
314
|
+
if (state === void 0) return resultFor("No active research workflow.", void 0, false);
|
|
315
|
+
const complete = isWorkflowComplete(state);
|
|
316
|
+
return resultFor(complete ? "Research workflow is complete." : `Active research workflow. Next required phase: ${nextPhase(state)}.`, state, !complete);
|
|
317
|
+
}
|
|
318
|
+
if (action === "abandon") return resultFor(workflows.delete(agent.id) ? "Research workflow abandoned." : "No active research workflow to abandon.", void 0, false);
|
|
319
|
+
const state = requireActive(workflows, agent);
|
|
320
|
+
if (action === "reopen") {
|
|
321
|
+
const phase = requirePhase(args.phase);
|
|
322
|
+
const next = reopenWorkflowPhase(state, phase);
|
|
323
|
+
workflows.set(agent.id, next);
|
|
324
|
+
return resultFor(`Returned to phase "${phase}". Complete this phase and all following phases again.`, next, true);
|
|
325
|
+
}
|
|
326
|
+
if (action === "phase_complete") {
|
|
327
|
+
const phase = requirePhase(args.phase);
|
|
328
|
+
const next = completeWorkflowPhase(state, phase);
|
|
329
|
+
workflows.set(agent.id, next);
|
|
330
|
+
if (isWorkflowComplete(next)) return resultFor("All four research phases are complete. You may now present the final answer after looking back over the result.", next, false);
|
|
331
|
+
return resultFor(`Phase "${phase}" complete. Next required phase: ${nextPhase(next)}.`, next, true);
|
|
332
|
+
}
|
|
333
|
+
throw new Error(`unsupported workflow action: ${String(action)}`);
|
|
334
|
+
}
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
//#endregion
|
|
338
|
+
export { apply, inject, name };
|
package/package.json
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-researchly",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"packageManager": "pnpm@11.28.5",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/index.js",
|
|
7
|
+
"exports": "./lib/index.js",
|
|
8
|
+
"files": ["lib", "cordis.yml"],
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=24.9.0",
|
|
11
|
+
"dsh": "^0.2.2-rc.1"
|
|
12
|
+
},
|
|
13
|
+
"dsh": {
|
|
14
|
+
"bundle": {
|
|
15
|
+
"patch": "./cordis.yml"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsdown --config-loader native",
|
|
20
|
+
"prepare": "pnpm run build",
|
|
21
|
+
"test": "node --experimental-transform-types --test --test-isolation=none src/*.test.ts",
|
|
22
|
+
"test:state": "node --experimental-strip-types --test --test-isolation=none src/state.test.ts"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@deepseek-ai/cordis": "~4.1.0",
|
|
26
|
+
"@deepseek-ai/dsh-agent": "^0.2.2-rc.1",
|
|
27
|
+
"@deepseek-ai/dsh-system-prompt": "^0.2.2-rc.1",
|
|
28
|
+
"@deepseek-ai/dsh-tools": "^0.2.2-rc.1"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@deepseek-ai/cordis": "4.1.0",
|
|
32
|
+
"@deepseek-ai/dsh-agent": "0.2.2-rc.1",
|
|
33
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.2-rc.1",
|
|
34
|
+
"@deepseek-ai/dsh-tools": "0.2.2-rc.1",
|
|
35
|
+
"tsdown": "0.22.2"
|
|
36
|
+
},
|
|
37
|
+
"license": "MIT"
|
|
38
|
+
}
|