@yeaft/webchat-agent 0.1.781 → 0.1.786
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/package.json
CHANGED
package/unify/dream-v2/runner.js
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* enumerateGroups() via opts.listGroups()
|
|
9
9
|
* ↓
|
|
10
10
|
* for each group with newCount ≥ MIN_NEW_PER_GROUP (auto)
|
|
11
|
-
* or > 0 (manual)
|
|
11
|
+
* or > 0 (manual)
|
|
12
|
+
* or prior messages in a scoped manual group rerun:
|
|
12
13
|
* loadDiff() via opts.loadGroupDiff(groupId, sinceId)
|
|
13
14
|
* applyOverlap() via opts.loadOverlapPreamble(...)
|
|
14
15
|
* segment() segmentDiff(...)
|
|
@@ -55,7 +56,7 @@ import { tsForBackup, pruneOldSnapshots } from './snapshot.js';
|
|
|
55
56
|
* @typedef {Object} RunDreamOpts
|
|
56
57
|
* @property {string} root — memory root, e.g. ~/.yeaft/memory
|
|
57
58
|
* @property {boolean} [manual=false] — manual trigger overrides newCount<20 skip
|
|
58
|
-
* @property {string[]} [scopeFilter] — optional: only dream these targets
|
|
59
|
+
* @property {string[]} [scopeFilter] — optional: only dream these targets; scoped manual group triggers rerun the current group when there are prior messages but no new cursor delta ('*' allowed)
|
|
59
60
|
* @property {(req: {pass:string, prompt:string, system:string}) => Promise<string>} llm
|
|
60
61
|
* @property {() => Promise<Array<string>>} listGroups — return all group ids (incl. '_no-group')
|
|
61
62
|
* @property {(groupId: string) => Promise<number>} countMessages — total message count for a group
|
|
@@ -112,7 +113,13 @@ export async function runDream(opts) {
|
|
|
112
113
|
const beforeCount = await safeCall(() => opts.countMessages(groupId), 0);
|
|
113
114
|
const newCount = Math.max(0, beforeCount - (state.messageCount || 0));
|
|
114
115
|
|
|
115
|
-
|
|
116
|
+
const rerunScopedManual = !!opts.manual
|
|
117
|
+
&& groupFilter
|
|
118
|
+
&& groupFilter.has(groupId)
|
|
119
|
+
&& newCount === 0
|
|
120
|
+
&& beforeCount > 0;
|
|
121
|
+
|
|
122
|
+
if (newCount === 0 && !rerunScopedManual) {
|
|
116
123
|
groupsReport.push({ groupId, new: 0, status: 'skipped', reason: 'no-new-messages' });
|
|
117
124
|
continue;
|
|
118
125
|
}
|
|
@@ -122,12 +129,13 @@ export async function runDream(opts) {
|
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
onProgress({ phase: 'load-diff', groupId });
|
|
125
|
-
const
|
|
132
|
+
const diffCursor = rerunScopedManual ? null : state.lastDreamMessageId;
|
|
133
|
+
const diffNew = await safeCall(() => opts.loadGroupDiff(groupId, diffCursor), []);
|
|
126
134
|
if (!diffNew || diffNew.length === 0) {
|
|
127
135
|
groupsReport.push({ groupId, new: newCount, status: 'skipped', reason: 'empty-diff' });
|
|
128
136
|
continue;
|
|
129
137
|
}
|
|
130
|
-
const overlapMessages = state.lastDreamMessageId
|
|
138
|
+
const overlapMessages = state.lastDreamMessageId && !rerunScopedManual
|
|
131
139
|
? await safeCall(
|
|
132
140
|
() => opts.loadOverlapPreamble
|
|
133
141
|
? opts.loadOverlapPreamble(groupId, state.lastDreamMessageId, limits.DREAM_OVERLAP)
|
|
@@ -171,7 +179,7 @@ export async function runDream(opts) {
|
|
|
171
179
|
|
|
172
180
|
const tailId = lastMessageId(diffNew);
|
|
173
181
|
processedGroups.push({ groupId, tailId, beforeCount, newCount, segments: segments.length, actions: actions.length });
|
|
174
|
-
groupsReport.push({ groupId, new: newCount, segments: segments.length, actions: actions.length, status: 'triaged' });
|
|
182
|
+
groupsReport.push({ groupId, new: newCount, segments: segments.length, actions: actions.length, status: 'triaged', rerun: rerunScopedManual || undefined });
|
|
175
183
|
}
|
|
176
184
|
|
|
177
185
|
// 3. merge
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Planning Mode
|
|
2
2
|
|
|
3
|
-
You have just entered **planning mode** for the topic below.
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
You have just entered **planning mode** for the topic below. Your job is to
|
|
4
|
+
**think through the work, land a concrete plan via `TodoWrite`, and then
|
|
5
|
+
continue executing the first step in the same turn**. Don't stop after writing
|
|
6
|
+
the plan — keep going.
|
|
6
7
|
|
|
7
8
|
## How to think
|
|
8
9
|
|
|
@@ -20,7 +21,7 @@ a concrete plan**, then hand it off to `TodoWrite` so the steps are tracked.
|
|
|
20
21
|
|
|
21
22
|
## Output shape
|
|
22
23
|
|
|
23
|
-
Reply in
|
|
24
|
+
Reply in three parts, all in the **same turn**:
|
|
24
25
|
|
|
25
26
|
**Part 1 — Plan (prose, short).** 5–10 lines covering the problem, the chosen
|
|
26
27
|
approach, and the key risks. No filler. Skip if the topic is trivial.
|
|
@@ -32,9 +33,15 @@ array. Status rule:
|
|
|
32
33
|
- Use the **imperative** form for `content` ("Write failing test"), and the
|
|
33
34
|
**present-continuous** form for `activeForm` ("Writing failing test").
|
|
34
35
|
|
|
35
|
-
**
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
**Part 3 — Start executing the first step.** Immediately after `TodoWrite`
|
|
37
|
+
returns, begin work on the `in_progress` item by calling whatever tool(s) that
|
|
38
|
+
step needs (bash, file-edit, grep, etc.). Don't end the turn just because the
|
|
39
|
+
plan is written — the plan is the runway, not the destination.
|
|
40
|
+
|
|
41
|
+
**Exception — stop after the plan only if** the very first step is "ask the
|
|
42
|
+
user / wait for input" (e.g. an unresolved unknown that genuinely blocks
|
|
43
|
+
every other step). In that case, call the `ask_user` tool with the
|
|
44
|
+
question and end the turn. Otherwise keep moving.
|
|
38
45
|
|
|
39
46
|
## Tone
|
|
40
47
|
|
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Lightweight planning entry point inspired by Claude Code's plan mode.
|
|
5
5
|
* Unlike Claude Code, we do NOT swap tools or change conversation state —
|
|
6
|
-
* `StartPlan` is a regular tool. Its
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* `StartPlan` is a regular tool. Its job is to push a planning instruction
|
|
7
|
+
* back into the model's tool-result stream so the same turn produces a
|
|
8
|
+
* short prose plan, a `TodoWrite` call to land the steps, and then keeps
|
|
9
|
+
* going by starting the first step. The plan is the runway, not the
|
|
10
|
+
* destination — the loop continues until the work is done (or until the
|
|
11
|
+
* model legitimately needs the user, e.g. an unresolved unknown).
|
|
9
12
|
*
|
|
10
|
-
* Design
|
|
13
|
+
* Design:
|
|
11
14
|
* - Anyone can call it; the tool description tells the LLM when to.
|
|
12
15
|
* - The instruction text comes from one of two places, in order:
|
|
13
16
|
* 1. The active VP's `planInstruction` frontmatter override
|
|
@@ -20,13 +23,16 @@
|
|
|
20
23
|
* are echoed back in the tool result so the planning turn can read
|
|
21
24
|
* them without re-asking the user.
|
|
22
25
|
* - Output is plain text (the instruction + the echo). No side effects,
|
|
23
|
-
* no persistence — the
|
|
24
|
-
*
|
|
26
|
+
* no persistence — the same turn that called StartPlan produces the
|
|
27
|
+
* plan, lands the steps via TodoWrite, and starts executing the first
|
|
28
|
+
* step (unless that first step is "ask the user", which is the one
|
|
29
|
+
* legitimate reason to stop here).
|
|
25
30
|
*
|
|
26
|
-
* The expected integration is TodoWrite:
|
|
27
|
-
* issues a `TodoWrite` call enumerating the 1..N steps
|
|
28
|
-
*
|
|
29
|
-
* the plan materialize without any
|
|
31
|
+
* The expected integration is TodoWrite: during the planning turn the LLM
|
|
32
|
+
* issues a `TodoWrite` call enumerating the 1..N steps, then keeps going
|
|
33
|
+
* and works the first step. The frontend already renders TodoWrite as a
|
|
34
|
+
* checkbox-style list, so the user sees the plan materialize without any
|
|
35
|
+
* new UI.
|
|
30
36
|
*/
|
|
31
37
|
|
|
32
38
|
import { defineTool } from './types.js';
|
|
@@ -36,9 +42,10 @@ export default defineTool({
|
|
|
36
42
|
name: 'StartPlan',
|
|
37
43
|
description: `Enter planning mode for a non-trivial task. Use BEFORE you start working when the request needs multiple steps, has unclear scope, or the user said "make a plan" / "think through this first".
|
|
38
44
|
|
|
39
|
-
This tool
|
|
45
|
+
This tool returns a planning instruction. Use it to land a structured plan, then keep working in the same turn. The expected flow is:
|
|
40
46
|
1. Produce a short prose plan (problem, approach, risks).
|
|
41
47
|
2. Call \`TodoWrite\` with the ordered steps. Mark the first concrete step "in_progress", the rest "pending".
|
|
48
|
+
3. Start executing that first step — call whatever tools the work needs. Do not end the turn just because the plan is written; the plan is the runway.
|
|
42
49
|
|
|
43
50
|
WHEN TO USE:
|
|
44
51
|
- Multi-step implementation (3+ steps), refactor, or open-ended investigation.
|
|
@@ -49,6 +56,8 @@ WHEN NOT TO USE:
|
|
|
49
56
|
- Single trivial change, single command run, lookup-style question.
|
|
50
57
|
- Mid-execution — once you're past the first step, use TodoWrite directly.
|
|
51
58
|
|
|
59
|
+
EXCEPTION — stop after the plan only if the first step is genuinely "ask the user" (an unresolved unknown that blocks every other step). Otherwise keep moving.
|
|
60
|
+
|
|
52
61
|
The tool takes the topic plus optional guiding fields (stuckAt, userProblem, expectedScale, additionalContext) that help you think; they're echoed back verbatim, so don't repeat the full user request in \`topic\`.`,
|
|
53
62
|
parameters: {
|
|
54
63
|
type: 'object',
|
|
@@ -126,7 +135,7 @@ The tool takes the topic plus optional guiding fields (stuckAt, userProblem, exp
|
|
|
126
135
|
lines.push('</guiding-context>');
|
|
127
136
|
}
|
|
128
137
|
lines.push('');
|
|
129
|
-
lines.push('Next: produce the plan
|
|
138
|
+
lines.push('Next: produce the plan, call `TodoWrite` to land the ordered steps, then keep going — start executing the first step in this same turn. Only stop after the plan if the first step is "ask the user".');
|
|
130
139
|
|
|
131
140
|
return lines.join('\n');
|
|
132
141
|
},
|