picocode-core 0.9.157 → 0.9.159

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.157",
3
+ "version": "0.9.159",
4
4
  "description": "The agent runtime behind pico: sessions, tools, subagents, MCP, memory, and model access",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/agent.js CHANGED
@@ -5,17 +5,28 @@ import { compose, scope, model, noToolsCalled, Inherit, getText } from '@prsm/ai
5
5
  import { commitLabel, fileLabel, mediaTypeFor, selectionLabel } from './attachments.js'
6
6
 
7
7
  const exec = promisify(execFile)
8
- const COMMIT_PATCH_LIMIT = 60 * 1024
8
+ // a whole patch rides along only while it is small; a bigger commit
9
+ // arrives as its header and stat, and the model pulls the files it cares
10
+ // about with git show. 8KB is a couple of thousand tokens
11
+ const COMMIT_PATCH_LIMIT = 8 * 1024
12
+ const COMMIT_STAT_FILES = 80
13
+ const GIT_SHOW = ['--no-optional-locks', 'show', '--format=%H%nAuthor: %an <%ae>%nDate: %ad%n%n%B']
14
+
15
+ function trimStat(stat) {
16
+ const lines = stat.trimEnd().split('\n')
17
+ if (lines.length <= COMMIT_STAT_FILES + 1) return stat.trimEnd()
18
+ return [...lines.slice(0, COMMIT_STAT_FILES), `... ${lines.length - COMMIT_STAT_FILES - 1} more files`, lines.at(-1)].join('\n')
19
+ }
9
20
 
10
- // a commit part carries the commit itself: its header, stat, and patch,
11
- // cut off past the limit, so the model reads what happened without a
12
- // git call of its own
13
21
  export async function hydrateCommit(part) {
14
22
  const head = commitLabel(part)
23
+ const options = { cwd: part.root, maxBuffer: 64 * 1024 * 1024 }
15
24
  try {
16
- const { stdout } = await exec('git', ['--no-optional-locks', 'show', '--stat', '--patch', '--format=%H%nAuthor: %an <%ae>%nDate: %ad%n%n%B', part.hash], { cwd: part.root, maxBuffer: COMMIT_PATCH_LIMIT * 4 })
17
- const body = stdout.length > COMMIT_PATCH_LIMIT ? `${stdout.slice(0, COMMIT_PATCH_LIMIT)}\n[patch truncated at ${COMMIT_PATCH_LIMIT} bytes]` : stdout
18
- return { type: 'text', text: `${head}\n${body.trimEnd()}\n[/commit]` }
25
+ const { stdout: full } = await exec('git', [...GIT_SHOW, '--stat', '--patch', part.hash], options)
26
+ if (full.length <= COMMIT_PATCH_LIMIT) return { type: 'text', text: `${head}\n${full.trimEnd()}\n[/commit]` }
27
+ const { stdout: stat } = await exec('git', [...GIT_SHOW, '--stat', part.hash], options)
28
+ const note = `[patch omitted: ${Math.round(full.length / 1024)}KB; run git show ${part.hash.slice(0, 7)} -- <path> for the files you need]`
29
+ return { type: 'text', text: `${head}\n${trimStat(stat)}\n${note}\n[/commit]` }
19
30
  } catch {
20
31
  return { type: 'text', text: `${head}\n[commit unavailable]\n[/commit]` }
21
32
  }
package/src/controller.js CHANGED
@@ -361,8 +361,12 @@ export function createController({ boot }) {
361
361
  )
362
362
  })
363
363
 
364
- function noteSystem(text, { wake, agentId, sessionId = state.session?.id, sessionFile = state.session?.file } = {}) {
365
- pendingSystemNotes.push({ text, wake, agentId, sessionId, sessionFile })
364
+ // a note for a session that has not started yet waits for its first
365
+ // message; `ensure` starts the session now so the note is persisted and
366
+ // in view before the first turn, not after it
367
+ function noteSystem(text, { wake, agentId, ensure = false, sessionId = state.session?.id, sessionFile = state.session?.file } = {}) {
368
+ if (ensure && !state.session && !state.busy) ensureSession()
369
+ pendingSystemNotes.push({ text, wake, agentId, sessionId: sessionId ?? state.session?.id, sessionFile: sessionFile ?? state.session?.file })
366
370
  flushSystemNotes()
367
371
  }
368
372