picocode-core 0.9.135 → 0.9.137

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "picocode-core",
3
- "version": "0.9.135",
3
+ "version": "0.9.137",
4
4
  "description": "The agent runtime behind pico: sessions, tools, subagents, MCP, memory, and model access",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -33,25 +33,40 @@ function settleTool(tools, event) {
33
33
  item.fullOutput = event.result === undefined ? null : typeof event.result === 'string' ? event.result : JSON.stringify(event.result, null, 2)
34
34
  }
35
35
 
36
+ // a deliberation reads as turns: each turn owns the tool runs its
37
+ // participant made before speaking. every recorded event carries the
38
+ // speaker's role and round, so a turn opens on its first tool call and
39
+ // closes when its text arrives; a turn with tools and no text is running
36
40
  function deliberationTranscript(agent) {
37
41
  const items = [{ kind: 'user', text: agent.prompt }]
38
42
  const tools = new Map()
43
+ const turns = new Map()
44
+ const turnFor = (role, round) => {
45
+ const key = `${role}:${round}`
46
+ if (!turns.has(key)) {
47
+ const turn = { kind: 'deliberation-turn', role, round, text: null, tools: [], active: agent.status === 'running' }
48
+ turns.set(key, turn)
49
+ items.push(turn)
50
+ }
51
+ return turns.get(key)
52
+ }
39
53
  for (const entry of agent.timeline) {
40
54
  if (entry.kind === 'turn') {
41
- const turn = entry.value
42
- items.push({ kind: 'deliberation-turn', role: turn.role, round: turn.round, text: turn.text })
55
+ const turn = turnFor(entry.value.role, entry.value.round)
56
+ turn.text = entry.value.text
57
+ turn.active = false
43
58
  continue
44
59
  }
45
60
  const event = entry.value
46
61
  if (event.type === 'tool_executing') {
47
62
  const item = toolItem(event.call || {}, event.at)
48
63
  tools.set(item.callId, item)
49
- items.push(item)
64
+ turnFor(event.role, event.round).tools.push(item)
50
65
  }
51
66
  if (event.type === 'tool_complete' || event.type === 'tool_error') settleTool(tools, event)
52
67
  }
53
68
  if (agent.result) {
54
- items.push({ kind: 'deliberation-turn', role: 'synthesis', text: agent.result, interrupted: agent.status === 'cancelled' })
69
+ items.push({ kind: 'deliberation-turn', role: 'synthesis', text: agent.result, tools: [], interrupted: agent.status === 'cancelled' })
55
70
  } else if (agent.error) {
56
71
  items.push({ kind: 'assistant', text: agent.error, interrupted: true })
57
72
  }
package/src/controller.js CHANGED
@@ -28,6 +28,7 @@ import { connectOpenAI, openaiCredentials, disconnectOpenAI } from './openai-aut
28
28
  import { agentScratchDir, ensureDir } from './paths.js'
29
29
  import { loadCodexModels } from './codex-models.js'
30
30
  import { fuzzyScore } from './fuzzy.js'
31
+ import { MAX_DELIBERATION_ROUNDS } from './deliberation.js'
31
32
  import { buildUserContent, finalizeUserContent, inputTextFromContent, mediaTypeFor } from './attachments.js'
32
33
 
33
34
  export const EFFORT_LEVELS = [
@@ -73,8 +74,9 @@ function parallelPrompt(task, agentLimit) {
73
74
  return `Use parallel agents for the following task: ${task}\n\nFirst call agent_plan. Interpret any agent-count instruction in the user's task semantically and declare that count; if the user gave no count, declare the configured default budget of ${agentLimit}. Then use agent_start within that enforced budget to delegate distinct, focused parts of the task to the configured worker model. Collect workers with agent_collect, critically evaluate their results, and synthesize the final response. When useful and the budget permits, use independent workers to check important disputed or weak conclusions. Do not delegate final synthesis. Do not emit progress updates while agents run; Pico displays agent activity automatically.`
74
75
  }
75
76
 
76
- function deliberatePrompt(decision) {
77
- return `Deliberate on the following decision: ${decision}\n\nImmediately call deliberate with a self-contained brief. Do not research first, start ordinary agents, or approximate the deliberation yourself. The deliberation participants own all supporting research.`
77
+ function deliberatePrompt(decision, rounds) {
78
+ const withRounds = rounds ? ` and rounds set to ${rounds}` : ''
79
+ return `Deliberate on the following decision: ${decision}\n\nImmediately call deliberate with a self-contained brief${withRounds}. Do not research first, start ordinary agents, or approximate the deliberation yourself. The deliberation participants own all supporting research.`
78
80
  }
79
81
 
80
82
  function workerSystemPrompt(scratchpad) {
@@ -985,13 +987,16 @@ export function createController({ boot }) {
985
987
  return true
986
988
  }
987
989
 
988
- function sendDeliberate(decision) {
990
+ // rounds, when given, is passed along to the tool call; the tool itself
991
+ // clamps to its 1..5 range
992
+ function sendDeliberate(decision, rounds) {
989
993
  if (!decision) {
990
994
  flash('usage: /deliberate <decision>')
991
995
  return true
992
996
  }
993
997
  if (!modelAvailable(boot.deliberationModel)) return false
994
- send(deliberatePrompt(decision))
998
+ const n = Number(rounds)
999
+ send(deliberatePrompt(decision, Number.isInteger(n) && n >= 1 && n <= MAX_DELIBERATION_ROUNDS ? n : null))
995
1000
  return true
996
1001
  }
997
1002