picocode-core 0.9.155 → 0.9.156
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/controller.js +30 -28
- package/src/pending.js +8 -0
package/package.json
CHANGED
package/src/controller.js
CHANGED
|
@@ -30,6 +30,7 @@ import { loadCodexModels } from './codex-models.js'
|
|
|
30
30
|
import { fuzzyScore } from './fuzzy.js'
|
|
31
31
|
import { MAX_DELIBERATION_ROUNDS } from './deliberation.js'
|
|
32
32
|
import { buildUserContent, finalizeUserContent, inputTextFromContent, mediaTypeFor, stashImages } from './attachments.js'
|
|
33
|
+
import { settlePending } from './pending.js'
|
|
33
34
|
|
|
34
35
|
export const EFFORT_LEVELS = [
|
|
35
36
|
{ key: null, desc: 'let the provider decide how much to think' },
|
|
@@ -118,6 +119,7 @@ export function createController({ boot }) {
|
|
|
118
119
|
streaming: null,
|
|
119
120
|
queued: [],
|
|
120
121
|
expedited: [],
|
|
122
|
+
views: [],
|
|
121
123
|
sent: [],
|
|
122
124
|
question: null,
|
|
123
125
|
rewindUndo: null,
|
|
@@ -396,16 +398,18 @@ export function createController({ boot }) {
|
|
|
396
398
|
state.streaming = null
|
|
397
399
|
}
|
|
398
400
|
|
|
399
|
-
async function
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
const built = buildUserContent(text, state.attachments)
|
|
403
|
-
const viewed = built.used.length > 0 && built.used.every((placeholder) => deliveredImages.has(placeholder))
|
|
404
|
-
const { content: built2, used } = viewed ? built : finalizeUserContent(text, state.attachments)
|
|
405
|
-
for (const placeholder of used) deliveredImages.delete(placeholder)
|
|
401
|
+
async function persistUserMessage(text, { viewed = false } = {}) {
|
|
402
|
+
// a view label carries the image's path; only user text is scanned
|
|
403
|
+
// for paths, or the viewed image would attach twice
|
|
404
|
+
const { content: built } = viewed ? buildUserContent(text, state.attachments) : finalizeUserContent(text, state.attachments)
|
|
406
405
|
ensureSession()
|
|
407
|
-
const content = state.session.file ? await stashImages(
|
|
406
|
+
const content = state.session.file ? await stashImages(built, sessionAttachmentsDir(boot.root, state.session.id)) : built
|
|
408
407
|
persist(makeEvent('message', { message: { role: 'user', content }, ...(viewed ? { origin: 'view' } : {}) }))
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
async function executeTurn(text, { views = [] } = {}) {
|
|
411
|
+
for (const view of views) await persistUserMessage(view, { viewed: true })
|
|
412
|
+
if (text) await persistUserMessage(text)
|
|
409
413
|
reDerive()
|
|
410
414
|
await runAgentTurn()
|
|
411
415
|
}
|
|
@@ -463,11 +467,12 @@ export function createController({ boot }) {
|
|
|
463
467
|
set({ compacting: false, compactStatus: null, busy: false })
|
|
464
468
|
}
|
|
465
469
|
|
|
466
|
-
if (state.expedited.length > 0 || state.queued.length > 0) {
|
|
467
|
-
const
|
|
468
|
-
|
|
470
|
+
if (state.expedited.length > 0 || state.queued.length > 0 || state.views.length > 0) {
|
|
471
|
+
const settled = settlePending({ ...state, interrupted: controller.signal.aborted })
|
|
472
|
+
set({ expedited: [], queued: settled.queued, views: [] })
|
|
473
|
+
if (settled.recall.length > 0) emit('input', settled.recall.join('\n'))
|
|
469
474
|
else {
|
|
470
|
-
executeTurn(
|
|
475
|
+
executeTurn(settled.messages.join('\n'), { views: settled.views })
|
|
471
476
|
return
|
|
472
477
|
}
|
|
473
478
|
}
|
|
@@ -571,7 +576,7 @@ export function createController({ boot }) {
|
|
|
571
576
|
: item,
|
|
572
577
|
),
|
|
573
578
|
)
|
|
574
|
-
if (state.expedited.length > 0) {
|
|
579
|
+
if (state.expedited.length > 0 || state.views.length > 0) {
|
|
575
580
|
sendAfterToolTriggered = true
|
|
576
581
|
controller.abort()
|
|
577
582
|
}
|
|
@@ -680,18 +685,15 @@ export function createController({ boot }) {
|
|
|
680
685
|
)
|
|
681
686
|
}
|
|
682
687
|
|
|
683
|
-
|
|
684
|
-
const pendingMessages = state.queued
|
|
685
|
-
if (expeditedMessages.length > 0 || pendingMessages.length > 0) {
|
|
686
|
-
set({ expedited: [], queued: [] })
|
|
688
|
+
if (state.expedited.length > 0 || state.queued.length > 0 || state.views.length > 0) {
|
|
687
689
|
// an interrupt is the user taking the wheel: nothing pending may
|
|
688
|
-
// auto-send, expedited or not; it all returns to the composer
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
executeTurn(
|
|
690
|
+
// auto-send, expedited or not; it all returns to the composer, and
|
|
691
|
+
// an image the model asked for is dropped with the turn
|
|
692
|
+
const settled = settlePending({ ...state, afterTool: sendAfterToolTriggered, interrupted: result.interrupted })
|
|
693
|
+
set({ expedited: [], queued: settled.queued, views: [] })
|
|
694
|
+
if (settled.recall.length > 0) emit('input', settled.recall.join('\n'))
|
|
695
|
+
else {
|
|
696
|
+
executeTurn(settled.messages.join('\n'), { views: settled.views })
|
|
695
697
|
return
|
|
696
698
|
}
|
|
697
699
|
}
|
|
@@ -749,6 +751,7 @@ export function createController({ boot }) {
|
|
|
749
751
|
state.rewindUndo = null
|
|
750
752
|
state.queued = []
|
|
751
753
|
state.expedited = []
|
|
754
|
+
state.views = []
|
|
752
755
|
state.sent = []
|
|
753
756
|
state.model = model ?? state.defaultModel
|
|
754
757
|
state.effort = effort === undefined ? state.defaultEffort : effort
|
|
@@ -795,6 +798,7 @@ export function createController({ boot }) {
|
|
|
795
798
|
state.rewindUndo = null
|
|
796
799
|
state.queued = []
|
|
797
800
|
state.expedited = []
|
|
801
|
+
state.views = []
|
|
798
802
|
state.sent = []
|
|
799
803
|
agents.restore(forked.events)
|
|
800
804
|
reDerive()
|
|
@@ -854,12 +858,10 @@ export function createController({ boot }) {
|
|
|
854
858
|
|
|
855
859
|
// an image the model asked to see rides in as an expedited user message,
|
|
856
860
|
// which the tool-completion path sends right after the current call
|
|
857
|
-
const deliveredImages = new Set()
|
|
858
861
|
function deliverImage(path, label) {
|
|
859
862
|
const placeholder = attachImage(path)
|
|
860
863
|
if (!placeholder) return false
|
|
861
|
-
|
|
862
|
-
set({ expedited: [...state.expedited, `${label}\n${placeholder}`] })
|
|
864
|
+
set({ views: [...state.views, `${label}\n${placeholder}`] })
|
|
863
865
|
return true
|
|
864
866
|
}
|
|
865
867
|
|
|
@@ -949,7 +951,7 @@ export function createController({ boot }) {
|
|
|
949
951
|
boot.git.retarget(next.root)
|
|
950
952
|
next.mcp.connectAll()
|
|
951
953
|
emit('mcp', next.mcp.list())
|
|
952
|
-
set({ queued: [], expedited: [] })
|
|
954
|
+
set({ queued: [], expedited: [], views: [] })
|
|
953
955
|
emit('project', boot)
|
|
954
956
|
await resume(meta)
|
|
955
957
|
flash(`switched to ${next.displayCwd}`)
|
package/src/pending.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// what happens to the messages waiting on a turn once it ends. images the
|
|
2
|
+
// model asked to view travel apart from the user's own text, so a view
|
|
3
|
+
// delivery is never folded into a user message
|
|
4
|
+
export function settlePending({ views = [], expedited = [], queued = [], afterTool = false, interrupted = false }) {
|
|
5
|
+
if (interrupted && !afterTool) return { views: [], messages: [], queued: [], recall: [...expedited, ...queued] }
|
|
6
|
+
if (afterTool) return { views, messages: expedited, queued, recall: [] }
|
|
7
|
+
return { views, messages: [...expedited, ...queued], queued: [], recall: [] }
|
|
8
|
+
}
|