picocode-core 0.9.123 → 0.9.125
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 +1 -1
- package/src/tools/bash.js +2 -1
- package/src/tools/edit.js +2 -1
- package/src/tools/glob.js +2 -1
- package/src/tools/grep.js +2 -1
- package/src/tools/index.js +15 -7
- package/src/tools/read.js +2 -1
- package/src/tools/recorder.js +8 -0
- package/src/tools/web.js +3 -1
- package/src/tools/write.js +2 -1
package/package.json
CHANGED
package/src/tools/bash.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeParam } from './recorder.js'
|
|
1
2
|
import { spawn } from 'node:child_process'
|
|
2
3
|
import { stripAnsi, createSgrTracker } from '../ansi.js'
|
|
3
4
|
|
|
@@ -67,7 +68,7 @@ export function createBash({ cwd, env, recorder, signal, shells, sessionId, sess
|
|
|
67
68
|
command: { type: 'string', description: 'the command to run' },
|
|
68
69
|
timeout: { type: 'number', description: 'optional foreground timeout in milliseconds; commands still running after 150 seconds are backgrounded instead', optional: true },
|
|
69
70
|
background: { type: 'boolean', description: 'run in the background and return a shell id immediately', optional: true },
|
|
70
|
-
description:
|
|
71
|
+
description: describeParam,
|
|
71
72
|
},
|
|
72
73
|
execute: ({ command, timeout, background, description }) => {
|
|
73
74
|
if (background && shells) {
|
package/src/tools/edit.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeParam } from './recorder.js'
|
|
1
2
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
2
3
|
import { resolve } from 'node:path'
|
|
3
4
|
import { makeReversibleEdit } from '../reversible-edit.js'
|
|
@@ -54,7 +55,7 @@ export function createEdit({ cwd, recorder, tracker }) {
|
|
|
54
55
|
name: 'edit',
|
|
55
56
|
description: 'Replace oldText with newText in a file. oldText must appear exactly once unless replaceAll is set.',
|
|
56
57
|
schema: {
|
|
57
|
-
description:
|
|
58
|
+
description: describeParam,
|
|
58
59
|
path: { type: 'string', description: 'file path, relative to the working directory or absolute' },
|
|
59
60
|
oldText: { type: 'string', description: 'exact text to replace, must be unique in the file' },
|
|
60
61
|
newText: { type: 'string', description: 'replacement text' },
|
package/src/tools/glob.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeParam } from './recorder.js'
|
|
1
2
|
import { execFile } from 'node:child_process'
|
|
2
3
|
import fg from 'fast-glob'
|
|
3
4
|
|
|
@@ -18,7 +19,7 @@ export function createGlob({ cwd, recorder }) {
|
|
|
18
19
|
name: 'glob',
|
|
19
20
|
description: 'Find files matching a glob pattern, relative to the working directory. Respects .gitignore; use bash to look inside ignored paths.',
|
|
20
21
|
schema: {
|
|
21
|
-
description:
|
|
22
|
+
description: describeParam,
|
|
22
23
|
pattern: { type: 'string', description: 'glob pattern, e.g. src/**/*.js' },
|
|
23
24
|
maxResults: { type: 'number', description: 'cap on returned paths, default 200', optional: true },
|
|
24
25
|
},
|
package/src/tools/grep.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeParam } from './recorder.js'
|
|
1
2
|
import { execFile } from 'node:child_process'
|
|
2
3
|
import { relative, resolve } from 'node:path'
|
|
3
4
|
|
|
@@ -16,7 +17,7 @@ export function createGrep({ cwd, recorder }) {
|
|
|
16
17
|
name: 'grep',
|
|
17
18
|
description: 'Search file contents with a regex using ripgrep. mode "content" returns matching lines, "files" returns matching file paths, "count" returns per-file match counts.',
|
|
18
19
|
schema: {
|
|
19
|
-
description:
|
|
20
|
+
description: describeParam,
|
|
20
21
|
pattern: { type: 'string', description: 'regex pattern' },
|
|
21
22
|
path: { type: 'string', description: 'file or directory to search, defaults to the working directory', optional: true },
|
|
22
23
|
mode: { type: 'string', enum: ['content', 'files', 'count'], optional: true },
|
package/src/tools/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRecorder, recorded } from './recorder.js'
|
|
1
|
+
import { createRecorder, describeParam, recorded } from './recorder.js'
|
|
2
2
|
import { createRead } from './read.js'
|
|
3
3
|
import { createWrite } from './write.js'
|
|
4
4
|
import { createEdit } from './edit.js'
|
|
@@ -32,6 +32,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
32
32
|
name: 'shell_output',
|
|
33
33
|
description: 'Read recent output from a background shell started with bash background: true. Use only when intermediate output is needed to diagnose a suspected problem or make a decision before the shell exits. Do not use for routine progress polling; completion is delivered automatically, so if no independent work remains, end your turn and wait.',
|
|
34
34
|
schema: {
|
|
35
|
+
description: describeParam,
|
|
35
36
|
id: { type: 'string', description: 'the shell id' },
|
|
36
37
|
tail: { type: 'number', description: 'how many trailing lines to return, default 100', optional: true },
|
|
37
38
|
},
|
|
@@ -47,6 +48,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
47
48
|
name: 'shell_kill',
|
|
48
49
|
description: 'Stop a background shell by id.',
|
|
49
50
|
schema: {
|
|
51
|
+
description: describeParam,
|
|
50
52
|
id: { type: 'string', description: 'the shell id' },
|
|
51
53
|
},
|
|
52
54
|
execute: ({ id }) => shells.kill(id, 'model'),
|
|
@@ -60,7 +62,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
60
62
|
name: 'schedule_wakeup',
|
|
61
63
|
description: 'Schedule a one-time wake-up: after the delay you receive a system notification carrying your note and can act on it. For a recurring loop, schedule the next wake-up at the end of each one. Do not use this to poll a background shell; its exit already notifies you. Wake-ups are lost if pico exits.',
|
|
62
64
|
schema: {
|
|
63
|
-
description:
|
|
65
|
+
description: describeParam,
|
|
64
66
|
delaySeconds: { type: 'number', description: 'seconds from now, minimum 5' },
|
|
65
67
|
note: { type: 'string', description: 'what to do when you wake up; written to your future self' },
|
|
66
68
|
},
|
|
@@ -73,6 +75,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
73
75
|
name: 'cancel_wakeup',
|
|
74
76
|
description: 'Cancel a pending wake-up by id.',
|
|
75
77
|
schema: {
|
|
78
|
+
description: describeParam,
|
|
76
79
|
id: { type: 'string', description: 'the wake-up id' },
|
|
77
80
|
},
|
|
78
81
|
execute: ({ id }) => wakeups.cancel(id),
|
|
@@ -80,7 +83,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
80
83
|
{
|
|
81
84
|
name: 'list_wakeups',
|
|
82
85
|
description: 'List your pending scheduled wake-ups: id, when each fires, and its note.',
|
|
83
|
-
schema: {},
|
|
86
|
+
schema: { description: describeParam },
|
|
84
87
|
execute: () => ({
|
|
85
88
|
wakeups: wakeups.list().map((w) => ({
|
|
86
89
|
id: w.id,
|
|
@@ -98,6 +101,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
98
101
|
name: 'ask_user',
|
|
99
102
|
description: 'Ask the user one or more focused questions when their answers are genuinely needed to continue. Supports free text, one choice, or multiple choices. Do not ask questions you can answer from available context.',
|
|
100
103
|
schema: {
|
|
104
|
+
description: describeParam,
|
|
101
105
|
questions: {
|
|
102
106
|
type: 'array',
|
|
103
107
|
description: 'questions to present, in order',
|
|
@@ -146,6 +150,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
146
150
|
name: 'agent_plan',
|
|
147
151
|
description: 'Declare the background worker budget for the current assistant turn before starting any workers. The main agent is excluded. Set count to the number of workers you intend to start this turn; collecting a worker does not restore budget. Interpret any user-requested count semantically; otherwise use the configured default.',
|
|
148
152
|
schema: {
|
|
153
|
+
description: describeParam,
|
|
149
154
|
count: { type: 'integer', description: `background workers permitted this turn, excluding the main agent (1-${maxAgentStarts || 100})` },
|
|
150
155
|
reason: { type: 'string', description: 'brief explanation of how the count follows the user request or research scope' },
|
|
151
156
|
},
|
|
@@ -162,7 +167,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
162
167
|
description: 'Start one background worker, consuming one unit of the current turn\'s agent_plan budget. Workers do not receive the parent conversation, only the supplied prompt and their available project context and tools. Make the prompt self-contained by including all conversation-specific terms, goals, constraints, and decisions the worker cannot discover itself. Collected or completed workers do not restore budget within that turn. Continue only independent work until you collect its result with agent_collect.',
|
|
163
168
|
schema: {
|
|
164
169
|
prompt: { type: 'string', description: 'complete, self-contained task and desired output, including necessary context from the parent conversation' },
|
|
165
|
-
description:
|
|
170
|
+
description: describeParam,
|
|
166
171
|
tools: { type: 'array', items: { type: 'string' }, description: 'tool names to allow; omit for the configured worker tools', optional: true },
|
|
167
172
|
},
|
|
168
173
|
execute: ({ prompt, description, tools }) => {
|
|
@@ -176,13 +181,13 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
176
181
|
{
|
|
177
182
|
name: 'agent_list',
|
|
178
183
|
description: 'List background agents and their current status.',
|
|
179
|
-
schema: {},
|
|
184
|
+
schema: { description: describeParam },
|
|
180
185
|
execute: () => ({ agents: agents.list().map(({ id, description, model, status }) => ({ id, description, model, status })) }),
|
|
181
186
|
},
|
|
182
187
|
{
|
|
183
188
|
name: 'agent_collect',
|
|
184
189
|
description: 'Collect background agent results. Waits for any selected agents that are still running.',
|
|
185
|
-
schema: { ids: { type: 'array', items: { type: 'string' }, description: 'agent ids whose results to collect' } },
|
|
190
|
+
schema: { description: describeParam, ids: { type: 'array', items: { type: 'string' }, description: 'agent ids whose results to collect' } },
|
|
186
191
|
execute: async ({ ids }) => {
|
|
187
192
|
const requested = (ids || []).map(String)
|
|
188
193
|
const collected = await agents.collect(requested)
|
|
@@ -203,7 +208,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
203
208
|
{
|
|
204
209
|
name: 'agent_cancel',
|
|
205
210
|
description: 'Cancel a queued or running background agent.',
|
|
206
|
-
schema: { id: { type: 'string', description: 'agent id' } },
|
|
211
|
+
schema: { description: describeParam, id: { type: 'string', description: 'agent id' } },
|
|
207
212
|
execute: ({ id }) => ({ cancelled: agents.cancel(id) }),
|
|
208
213
|
},
|
|
209
214
|
)
|
|
@@ -214,6 +219,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
214
219
|
name: 'deliberate',
|
|
215
220
|
description: 'Evaluate competing approaches, challenge a proposal, or reach a consequential decision under genuine uncertainty through a bounded, evidence-seeking exchange between two full tool-using agents. When the user requests deliberation, call this tool immediately with a self-contained brief: do not research first or approximate deliberation with multiple ordinary agents. Its participants own all supporting research. Use ordinary agents when independent work can be divided and collected. Do not deliberate routine implementation or questions answerable through direct research.',
|
|
216
221
|
schema: {
|
|
222
|
+
description: describeParam,
|
|
217
223
|
brief: { type: 'string', description: 'self-contained decision, relevant context, constraints, and desired outcome' },
|
|
218
224
|
rounds: { type: 'integer', description: 'number of proposer-reviewer exchanges (1-5, default 3)', optional: true },
|
|
219
225
|
},
|
|
@@ -242,6 +248,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
242
248
|
name: 'recall',
|
|
243
249
|
description: 'Load the full content of a saved memory by name. Your memory index is in the system prompt.',
|
|
244
250
|
schema: {
|
|
251
|
+
description: describeParam,
|
|
245
252
|
name: { type: 'string', description: 'the memory name from the index' },
|
|
246
253
|
},
|
|
247
254
|
execute: async ({ name }) => {
|
|
@@ -261,6 +268,7 @@ export function createToolset({ cwd, env, tracker, skills, shells, sessionId, se
|
|
|
261
268
|
.map((s) => `- ${s.name}: ${s.description}`)
|
|
262
269
|
.join('\n')}`,
|
|
263
270
|
schema: {
|
|
271
|
+
description: describeParam,
|
|
264
272
|
name: { type: 'string', description: 'skill name' },
|
|
265
273
|
},
|
|
266
274
|
execute: async ({ name }) => {
|
package/src/tools/read.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeParam } from './recorder.js'
|
|
1
2
|
import { readFile } from 'node:fs/promises'
|
|
2
3
|
import { resolve } from 'node:path'
|
|
3
4
|
|
|
@@ -17,7 +18,7 @@ export function createRead({ cwd, recorder, tracker }) {
|
|
|
17
18
|
name: 'read',
|
|
18
19
|
description: 'Read a file. Returns line-numbered content. Use offset/limit for large files.',
|
|
19
20
|
schema: {
|
|
20
|
-
description:
|
|
21
|
+
description: describeParam,
|
|
21
22
|
path: { type: 'string', description: 'file path, relative to the working directory or absolute' },
|
|
22
23
|
offset: { type: 'number', description: '1-indexed line to start from', optional: true },
|
|
23
24
|
limit: { type: 'number', description: 'max lines to return', optional: true },
|
package/src/tools/recorder.js
CHANGED
|
@@ -7,6 +7,13 @@ function collapseHomePath(value) {
|
|
|
7
7
|
return value
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
// every built-in tool takes this parameter; it is the line the human sees
|
|
11
|
+
// in the transcript while the call runs
|
|
12
|
+
export const describeParam = {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'what this call is doing, in present tense, a few words shown to the human watching, e.g. "Creating the test file" or "Collecting the worker results"',
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
export function defaultTitle(name, args = {}) {
|
|
11
18
|
const candidate = args.path || args.command || args.pattern || args.url || args.name
|
|
12
19
|
if (typeof candidate === 'string' && candidate) return collapseHomePath(candidate)
|
|
@@ -24,6 +31,7 @@ export function createRecorder(onChange) {
|
|
|
24
31
|
this.pending = {
|
|
25
32
|
callId: this.currentCall?.id ?? null,
|
|
26
33
|
name,
|
|
34
|
+
args,
|
|
27
35
|
title: defaultTitle(name, args),
|
|
28
36
|
description: args.description,
|
|
29
37
|
status: 'done',
|
package/src/tools/web.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeParam } from './recorder.js'
|
|
1
2
|
const DEFAULT_SLICE_CHARS = 24000
|
|
2
3
|
const MAX_SLICE_CHARS = 100000
|
|
3
4
|
|
|
@@ -34,7 +35,7 @@ export function createWebTools({ dredge, recorder, signal }) {
|
|
|
34
35
|
'Search the web. Google-style operators work: site:, filetype:pdf, quoted phrases. Returns ranked results; pass a result url to web_fetch to read it.',
|
|
35
36
|
schema: {
|
|
36
37
|
q: { type: 'string', description: 'the search query' },
|
|
37
|
-
description:
|
|
38
|
+
description: describeParam,
|
|
38
39
|
},
|
|
39
40
|
execute: async ({ q }) => {
|
|
40
41
|
recorder.extra({ title: q })
|
|
@@ -58,6 +59,7 @@ export function createWebTools({ dredge, recorder, signal }) {
|
|
|
58
59
|
description:
|
|
59
60
|
'Fetch a url and read it as clean markdown (html, pdf, docx, and textual formats like json). Long documents arrive in slices: the result says which slice you have (e.g. "slice 1 of 12") and next_cursor continues from there. Every slice you fetch permanently occupies conversation context, so only walk cursors for content you actually need, and raise maxChars only when the task genuinely needs a bigger window.',
|
|
60
61
|
schema: {
|
|
62
|
+
description: describeParam,
|
|
61
63
|
url: { type: 'string', description: 'the url to fetch' },
|
|
62
64
|
cursor: { type: 'string', description: 'pagination cursor from a previous web_fetch of the same url', optional: true },
|
|
63
65
|
maxChars: { type: 'number', description: `slice size in characters, default ${DEFAULT_SLICE_CHARS}, max ${MAX_SLICE_CHARS}`, optional: true },
|
package/src/tools/write.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeParam } from './recorder.js'
|
|
1
2
|
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
2
3
|
import { dirname, resolve } from 'node:path'
|
|
3
4
|
import { makeWriteEdit } from '../reversible-edit.js'
|
|
@@ -8,7 +9,7 @@ export function createWrite({ cwd, recorder, tracker }) {
|
|
|
8
9
|
name: 'write',
|
|
9
10
|
description: 'Write content to a file, creating it and any parent directories if needed. Overwrites existing content.',
|
|
10
11
|
schema: {
|
|
11
|
-
description:
|
|
12
|
+
description: describeParam,
|
|
12
13
|
path: { type: 'string', description: 'file path, relative to the working directory or absolute' },
|
|
13
14
|
content: { type: 'string', description: 'the full file content to write' },
|
|
14
15
|
},
|