Merge remote-tracking branch 'origin/master' into feat/todo-multi-in-progress

This commit is contained in:
Chinesezjc
2026-07-27 23:17:37 +08:00
456 changed files with 8495 additions and 10470 deletions

View File

@@ -1,12 +1,18 @@
# Replay counterpart to goal.cordis.yml; only the live model is replaced.
# Replay counterpart to goal.cordis.yml. It includes cordis.yml directly because
# a config patch cannot target an entry behind a nested include, then restates
# the goal overlay while replacing the live model with keyless replay.
- id: base
name: '@cordisjs/plugin-include'
config:
path: ./goal.cordis.yml
path: ./cordis.yml
patches:
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
disabled: true
- insert:
- id: goal
name: '@deepseek-ai/dsh-goal'
- id: tool-goal
name: '@deepseek-ai/dsh-tool-goal'
- id: llm-replay
name: '@deepseek-ai/dsh-llm-replay'

View File

@@ -314,12 +314,12 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('Code Mode: real model writes a p
ctx = await codeModeHarness(workdir)
const agent = ctx.agentLoop.create(SessionId('e2e-code-mode'), { provider: 'deepseek', model: 'deepseek-v4-flash' })
agent.followup([{
agent.followup({ content: [{
type: 'text',
text: 'Using one run_code program: run `echo alpha-7` with the bash tool, run `echo beta-9` with the bash tool, '
+ 'then write both outputs joined by a plus sign into combined.txt (bash heredoc or redirect), '
+ 'and return only the joined string.',
}])
}], source: { kind: 'user' } })
await waitForIdle(ctx, agent)
const events: SessionEvent[] = [...agent.session.events]
@@ -366,21 +366,17 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('Code Mode: real model writes a p
agentOptions: { provider: 'deepseek', model: 'deepseek-v4-flash' },
})
handle.agent.followup([{
handle.agent.followup({ content: [{
type: 'text',
text: 'Use one run_code program to call tools.read on pkg/deep/task.txt. After it finishes, answer: Code Mode workspace handshake?',
}])
}], source: { kind: 'user' } })
await waitForIdle(ctx, handle.agent)
const events: SessionEvent[] = [...handle.agent.session.events]
const dispatch = events.find(event => event.type === 'tool/code-dispatch' && event.data.name === 'read')
const outerResult = events.find(event => event.type === 'tool/result')
const workspaceContext = events.find(event => event.type === 'user/message'
&& event.data.source.kind === 'plugin'
&& typeof event.data.meta === 'object'
&& event.data.meta !== null
&& !Array.isArray(event.data.meta)
&& event.data.meta.kind === 'workspace-instructions')
&& event.data.source.kind === 'workspace-instructions')
expect(dispatch).toBeDefined()
expect(outerResult).toBeDefined()
expect(workspaceContext).toBeDefined()

View File

@@ -56,12 +56,12 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('coding task: fix a failing test
ctx = await codingHarness(workdir, { persona: SYSTEM_PROMPT })
const agent = ctx.agentLoop.create(SessionId('e2e-task'), { provider: 'deepseek', model: 'deepseek-v4-flash' })
agent.followup([{
agent.followup({ content: [{
type: 'text',
text: 'In the current directory, `node add.test.js` fails because add.js has a bug. '
+ 'Fix add.js so the test passes, run `node add.test.js` to verify, and report the result. '
+ 'Do not modify add.test.js.',
}])
}], source: { kind: 'user' } })
await waitForIdle(ctx, agent)
// The agent claims success…

View File

@@ -46,12 +46,12 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('compaction: a long session compa
})
const agent = ctx.agentLoop.create(SessionId('e2e-compaction'), { provider: 'deepseek', model: 'deepseek-v4-flash' })
agent.followup([{
agent.followup({ content: [{
type: 'text',
text: 'Read file1.txt, file2.txt, file3.txt, and file4.txt one at a '
+ 'time using cat (a separate bash command for each). After reading all four, tell me how '
+ 'many files you read and the number mentioned in file1.txt.',
}])
}], source: { kind: 'user' } })
await waitForIdle(ctx, agent)
const events = [...agent.session.events]

View File

@@ -59,7 +59,7 @@ export const inject = ['llm']
/** Register the keyless `cli-mock` adapter. */
export function apply(ctx: Context): void {
ctx.llm.registerAdapter(['cli-mock'], new CliMockAdapter())
ctx.on('agent/request', async (_agent, _turn, step, _config, _signal, next) => {
ctx.on('agent/request', async (_agent, _turn, step, _signal, next) => {
const config = await next()
return step === 2 ? { ...config, reasoningEffort: OFF } : config
})

View File

@@ -7,7 +7,7 @@ export const name = 'seed-goal'
export const inject = ['goals']
export function apply(ctx: Context): void {
ctx.on('agent/pre-step', (agent) => {
ctx.on('agent/step', (agent) => {
if (ctx.goals.get(agent) !== undefined) return
ctx.goals.create(agent, {
objective: 'Prove the composed goal survives in the session log',

View File

@@ -30,7 +30,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('full loop: real model + real bas
ctx = await codingHarness(workdir, { persona: SYSTEM_PROMPT })
const agent = ctx.agentLoop.create(SessionId('e2e-loop'), { provider: 'deepseek', model: 'deepseek-v4-flash' })
agent.followup([{ type: 'text', text: 'Run `echo e2e-ok` with the bash tool and tell me its exact output.' }])
agent.followup({ content: [{ type: 'text', text: 'Run `echo e2e-ok` with the bash tool and tell me its exact output.' }], source: { kind: 'user' } })
await waitForIdle(ctx, agent)
const events = [...agent.session.events]

View File

@@ -272,14 +272,16 @@ describe('headless stream-json snapshots', () => {
const goalChanges = records.filter((record) => {
if (record.type !== 'user/message') return false
const data = record.data as JsonObject | undefined
const meta = data?.meta as JsonObject | undefined
return meta?.kind === 'goal/change'
const source = data?.source as JsonObject | undefined
const change = source?.change as JsonObject | undefined
return source?.kind === 'goal' && change?.kind === 'goal/change'
})
expect(goalChanges).toHaveLength(1)
const data = goalChanges[0]?.data as JsonObject | undefined
const meta = data?.meta as JsonObject | undefined
const goal = meta?.goal as JsonObject | undefined
expect(meta?.operation).toBe('create')
const source = data?.source as JsonObject | undefined
const change = source?.change as JsonObject | undefined
const goal = change?.goal as JsonObject | undefined
expect(change?.operation).toBe('create')
expect(goal).toMatchObject({
objective: 'Finish the headless goal-tool snapshot proof',
phase: 'active',

View File

@@ -41,7 +41,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('resume: continue a persisted ses
sessionId: SESSION_ID,
agentOptions: { provider: 'deepseek', model: 'deepseek-v4-flash' },
})).agent
first.followup([{ type: 'text', text: `Remember this code for later: ${SECRET}. Just acknowledge it.` }])
first.followup({ content: [{ type: 'text', text: `Remember this code for later: ${SECRET}. Just acknowledge it.` }], source: { kind: 'user' } })
await waitForIdle(ctx, first)
await ctx.fiber.dispose()
ctx = undefined
@@ -58,7 +58,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('resume: continue a persisted ses
// The prior user turn is in the rehydrated log before the model is asked.
expect(JSON.stringify(resumed.session.deriveMessages())).toContain(SECRET)
resumed.followup([{ type: 'text', text: 'What was the code I asked you to remember? Reply with just the code.' }])
resumed.followup({ content: [{ type: 'text', text: 'What was the code I asked you to remember? Reply with just the code.' }], source: { kind: 'user' } })
await waitForIdle(ctx, resumed)
// The model recalls it — only possible from the resumed history.

View File

@@ -21,7 +21,7 @@
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":20,"time":0,"data":{"turn":1,"step":2,"content":[{"type":"tool-call","id":"call_goal_create","name":"create_goal","arguments":"{\"objective\":\"Finish the headless goal-tool snapshot proof\",\"max_goal_rounds\":7}"}],"provenance":{"provider":"deepseek","model":"deepseek-v4-flash"},"usage":{"inputTokens":20,"outputTokens":8}},"sourceEventSeqs":[15,16,17,18,19],"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":21,"time":0,"data":{"turn":1,"step":2,"callId":"call_goal_create","name":"create_goal","arguments":"{\"objective\":\"Finish the headless goal-tool snapshot proof\",\"max_goal_rounds\":7}"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":22,"time":0,"data":{"turn":1,"step":2,"callId":"call_goal_create","content":[{"type":"text","text":"{\"goal\":{\"id\":\"goal-{{sessionId}}\",\"revision\":1,\"objective\":\"Finish the headless goal-tool snapshot proof\",\"phase\":\"active\",\"roundsStarted\":0,\"maxGoalRounds\":7},\"activation\":\"armed\"}"}],"isError":false},"sourceEventSeqs":[21],"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":23,"time":0,"data":{"content":[{"type":"text","text":"<goal_state>{\"goal\":{\"id\":\"goal-{{sessionId}}\",\"revision\":1,\"objective\":\"Finish the headless goal-tool snapshot proof\",\"phase\":\"active\",\"maxGoalRounds\":7},\"roundsStarted\":0,\"createdAt\":0,\"updatedAt\":0}</goal_state>"}],"source":{"kind":"goal","goalId":"goal-{{sessionId}}","revision":1,"round":0},"meta":{"kind":"goal/change","version":1,"operation":"create","goal":{"id":"goal-{{sessionId}}","revision":1,"objective":"Finish the headless goal-tool snapshot proof","phase":"active","maxGoalRounds":7},"roundsStarted":0,"createdAt":0,"updatedAt":0}},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":23,"time":0,"data":{"content":[{"type":"text","text":"<goal_state>{\"goal\":{\"id\":\"goal-{{sessionId}}\",\"revision\":1,\"objective\":\"Finish the headless goal-tool snapshot proof\",\"phase\":\"active\",\"maxGoalRounds\":7},\"roundsStarted\":0,\"createdAt\":0,\"updatedAt\":0}</goal_state>"}],"source":{"kind":"goal","goalId":"goal-{{sessionId}}","revision":1,"round":0,"change":{"kind":"goal/change","version":1,"operation":"create","goal":{"id":"goal-{{sessionId}}","revision":1,"objective":"Finish the headless goal-tool snapshot proof","phase":"active","maxGoalRounds":7},"roundsStarted":0,"createdAt":0,"updatedAt":0}}},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/end","seq":24,"time":0,"data":{"turn":1,"step":2}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":25,"time":0,"data":{"turn":1,"step":3}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":26,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}

View File

@@ -28,11 +28,11 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('todo_write: real model records a
ctx = await codingHarness(workdir, { persona: TODO_SYSTEM_PROMPT })
const agent = ctx.agentLoop.create(SessionId('e2e-todo'), { provider: 'deepseek', model: 'deepseek-v4-flash' })
agent.followup([{ type: 'text', text:
agent.followup({ content: [{ type: 'text', text:
'Use the todo_write tool to record a plan of exactly three steps for work '
+ 'running in parallel: "inspect the failing test" (in_progress), '
+ '"watch the background build" (in_progress), then "apply the fix" (pending). '
+ 'Send all three in one todo_write call, then reply with the single word DONE.' }])
+ 'Send all three in one todo_write call, then reply with the single word DONE.' }], source: { kind: 'user' } })
await waitForIdle(ctx, agent)
const events = [...agent.session.events]