picocode-core 0.9.143 → 0.9.145
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/agent.js +2 -1
- package/src/attachments.js +11 -4
- package/src/controller.js +8 -0
- package/src/derive.js +1 -1
- package/src/wakeups.js +4 -3
package/package.json
CHANGED
package/src/agent.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises'
|
|
2
2
|
import { compose, scope, model, noToolsCalled, Inherit, getText } from '@prsm/ai'
|
|
3
|
-
import { fileLabel, mediaTypeFor } from './attachments.js'
|
|
3
|
+
import { fileLabel, mediaTypeFor, selectionLabel } from './attachments.js'
|
|
4
4
|
|
|
5
5
|
// file parts reach the model as a labelled path; it reads them itself
|
|
6
6
|
async function hydratePart(part) {
|
|
7
7
|
if (part.type === 'file') return { type: 'text', text: fileLabel(part.path) }
|
|
8
|
+
if (part.type === 'selection') return { type: 'text', text: selectionLabel(part) }
|
|
8
9
|
if (part.type !== 'image' || part.source?.kind !== 'path') return part
|
|
9
10
|
const mediaType = part.source.mediaType || mediaTypeFor(part.source.path)
|
|
10
11
|
if (!mediaType) return { type: 'text', text: `[image unavailable: ${part.source.path}]` }
|
package/src/attachments.js
CHANGED
|
@@ -71,9 +71,10 @@ export function splitTextByImagePaths(text, exists = existsSync) {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
export const fileLabel = (path) => `[file: ${path}]`
|
|
74
|
+
export const selectionLabel = (part) => `[selection: ${part.path}:${part.fromLine}-${part.toLine}]\n${part.text}\n[/selection]`
|
|
74
75
|
|
|
75
76
|
// [Image #n] and [File #n] placeholders in the composed text stand for
|
|
76
|
-
// attachments; they become image
|
|
77
|
+
// attachments; they become image, file, or selection parts of the user message
|
|
77
78
|
export function buildUserContent(text, attachments) {
|
|
78
79
|
const parts = []
|
|
79
80
|
let last = 0
|
|
@@ -83,9 +84,11 @@ export function buildUserContent(text, attachments) {
|
|
|
83
84
|
if (!attachment) continue
|
|
84
85
|
const before = text.slice(last, match.index)
|
|
85
86
|
if (before) parts.push({ type: 'text', text: before })
|
|
86
|
-
parts.push(attachment.kind === '
|
|
87
|
-
? { type: '
|
|
88
|
-
:
|
|
87
|
+
parts.push(attachment.kind === 'selection'
|
|
88
|
+
? { type: 'selection', path: attachment.path, text: attachment.text, fromLine: attachment.fromLine, toLine: attachment.toLine, ...(Number.isInteger(attachment.fromColumn) ? { fromColumn: attachment.fromColumn } : {}), ...(Number.isInteger(attachment.toColumn) ? { toColumn: attachment.toColumn } : {}) }
|
|
89
|
+
: attachment.kind === 'file'
|
|
90
|
+
? { type: 'file', path: attachment.path }
|
|
91
|
+
: { type: 'image', source: { kind: 'path', path: attachment.path, mediaType: attachment.mediaType } })
|
|
89
92
|
used.push(match[0])
|
|
90
93
|
last = match.index + match[0].length
|
|
91
94
|
}
|
|
@@ -125,6 +128,10 @@ export function inputTextFromContent(content, { attachments, nextId }) {
|
|
|
125
128
|
const placeholder = `[File #${nextId()}]`
|
|
126
129
|
attachments.set(placeholder, { path: part.path, kind: 'file' })
|
|
127
130
|
out += placeholder
|
|
131
|
+
} else if (part.type === 'selection' && part.path) {
|
|
132
|
+
const placeholder = `[File #${nextId()}]`
|
|
133
|
+
attachments.set(placeholder, { path: part.path, text: part.text, fromLine: part.fromLine, toLine: part.toLine, ...(Number.isInteger(part.fromColumn) ? { fromColumn: part.fromColumn } : {}), ...(Number.isInteger(part.toColumn) ? { toColumn: part.toColumn } : {}), kind: 'selection' })
|
|
134
|
+
out += placeholder
|
|
128
135
|
} else {
|
|
129
136
|
out += '[image]'
|
|
130
137
|
}
|
package/src/controller.js
CHANGED
|
@@ -857,6 +857,13 @@ export function createController({ boot }) {
|
|
|
857
857
|
return placeholder
|
|
858
858
|
}
|
|
859
859
|
|
|
860
|
+
function attachSelection({ path, text, fromLine, toLine, fromColumn, toColumn }) {
|
|
861
|
+
if (!existsSync(path) || !text || !Number.isInteger(fromLine) || !Number.isInteger(toLine)) return null
|
|
862
|
+
const placeholder = `[File #${++state.imageCount}]`
|
|
863
|
+
state.attachments.set(placeholder, { path, text, fromLine, toLine, fromColumn, toColumn, kind: 'selection' })
|
|
864
|
+
return placeholder
|
|
865
|
+
}
|
|
866
|
+
|
|
860
867
|
// a project-relative pick: images attach as images, anything else as a
|
|
861
868
|
// file reference
|
|
862
869
|
function attachProjectFile(file) {
|
|
@@ -1325,6 +1332,7 @@ export function createController({ boot }) {
|
|
|
1325
1332
|
recallText,
|
|
1326
1333
|
attachImage,
|
|
1327
1334
|
attachFile,
|
|
1335
|
+
attachSelection,
|
|
1328
1336
|
attachProjectFile,
|
|
1329
1337
|
detachImage,
|
|
1330
1338
|
costSummary,
|
package/src/derive.js
CHANGED
|
@@ -101,7 +101,7 @@ function foldMessage(state, event) {
|
|
|
101
101
|
if (message.role === 'user') {
|
|
102
102
|
const text = Array.isArray(message.content)
|
|
103
103
|
? message.content
|
|
104
|
-
.map((p) => (p.type === 'text' ? p.text : p.type === 'file' ? `[file: ${p.path}]` : `[image: ${String(p.source?.path || '').split('/').pop() || 'attached'}]`))
|
|
104
|
+
.map((p) => (p.type === 'text' ? p.text : p.type === 'file' ? `[file: ${p.path}]` : p.type === 'selection' ? `[selection: ${p.path}:${p.fromLine}-${p.toLine}]` : `[image: ${String(p.source?.path || '').split('/').pop() || 'attached'}]`))
|
|
105
105
|
.join('')
|
|
106
106
|
: String(message.content)
|
|
107
107
|
state.transcript.push({ ...base, kind: 'user', text, content: message.content, ...(event.data.origin ? { origin: event.data.origin } : {}) })
|
package/src/wakeups.js
CHANGED
|
@@ -6,13 +6,14 @@ export function createWakeupManager({ onFire = () => {}, onChange = () => {} } =
|
|
|
6
6
|
schedule(delaySeconds, note) {
|
|
7
7
|
const seconds = Math.max(5, Math.round(delaySeconds))
|
|
8
8
|
const id = String(nextId++)
|
|
9
|
-
const
|
|
9
|
+
const scheduledAt = Date.now()
|
|
10
|
+
const at = scheduledAt + seconds * 1000
|
|
10
11
|
const timer = setTimeout(() => {
|
|
11
12
|
wakeups.delete(id)
|
|
12
13
|
onChange()
|
|
13
14
|
onFire({ id, note, at })
|
|
14
15
|
}, seconds * 1000)
|
|
15
|
-
wakeups.set(id, { id, note, at, timer })
|
|
16
|
+
wakeups.set(id, { id, note, at, scheduledAt, timer })
|
|
16
17
|
onChange()
|
|
17
18
|
return { id, at, seconds }
|
|
18
19
|
},
|
|
@@ -26,7 +27,7 @@ export function createWakeupManager({ onFire = () => {}, onChange = () => {} } =
|
|
|
26
27
|
},
|
|
27
28
|
list() {
|
|
28
29
|
return [...wakeups.values()]
|
|
29
|
-
.map(({ id, note, at }) => ({ id, note, at }))
|
|
30
|
+
.map(({ id, note, at, scheduledAt }) => ({ id, note, at, scheduledAt }))
|
|
30
31
|
.sort((a, b) => a.at - b.at)
|
|
31
32
|
},
|
|
32
33
|
pending() {
|