picocode-core 0.9.195 → 0.9.196
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 +2 -2
- package/src/agent.js +4 -2
- package/src/codex-models.js +4 -1
- package/src/controller.js +39 -1
- package/src/derive.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "picocode-core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.196",
|
|
4
4
|
"description": "The agent runtime behind pico: sessions, tools, subagents, MCP, memory, and model access",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
28
|
-
"@prsm/ai": "^1.
|
|
28
|
+
"@prsm/ai": "^1.10.0",
|
|
29
29
|
"diff": "^7.0.0",
|
|
30
30
|
"globby": "^16.2.4",
|
|
31
31
|
"proper-lockfile": "^4.1.2",
|
package/src/agent.js
CHANGED
|
@@ -58,10 +58,11 @@ export function compactionHistory(history, prompt) {
|
|
|
58
58
|
return hydrateImages([...history.filter((m) => m.role !== 'system'), { role: 'user', content: prompt }])
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export async function compactHistory({ history, modelName, auth, prompt, signal, onStream }) {
|
|
61
|
+
export async function compactHistory({ history, modelName, speed, auth, prompt, signal, onStream }) {
|
|
62
62
|
const out = await compose(
|
|
63
63
|
model({
|
|
64
64
|
model: modelName,
|
|
65
|
+
...(speed && { speed }),
|
|
65
66
|
...(auth?.apiKey && { apiKey: auth.apiKey }),
|
|
66
67
|
...(auth?.headers && { headers: auth.headers }),
|
|
67
68
|
}),
|
|
@@ -102,7 +103,7 @@ function estimateTokens(value) {
|
|
|
102
103
|
return Math.ceil(JSON.stringify(value ?? '').length / 4)
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
export async function runTurn({ history, tools, recorder, modelName, effort, auth, system, signal, onStream, beforeRequest, stallMs = STALL_MS }) {
|
|
106
|
+
export async function runTurn({ history, tools, recorder, modelName, effort, speed, auth, system, signal, onStream, beforeRequest, stallMs = STALL_MS }) {
|
|
106
107
|
const collected = []
|
|
107
108
|
let roundText = ''
|
|
108
109
|
let usageSeen = null
|
|
@@ -201,6 +202,7 @@ export async function runTurn({ history, tools, recorder, modelName, effort, aut
|
|
|
201
202
|
return { ...request, history: [...request.history, ...messages] }
|
|
202
203
|
},
|
|
203
204
|
...(effort && { effort }),
|
|
205
|
+
...(speed && { speed }),
|
|
204
206
|
...(auth?.apiKey && { apiKey: auth.apiKey }),
|
|
205
207
|
...(auth?.headers && { headers: auth.headers }),
|
|
206
208
|
})({ ...ctx, history: hydratedHistory, abortSignal: internal.signal })
|
package/src/codex-models.js
CHANGED
|
@@ -18,6 +18,7 @@ export function mapCodexModels(entries) {
|
|
|
18
18
|
desc: `${m.description || m.label || m.slug} · via ChatGPT plan`,
|
|
19
19
|
price: null,
|
|
20
20
|
effort: true,
|
|
21
|
+
speed: (m.service_tiers || []).some(tier => ['priority', 'fast'].includes(tier.id)) || (m.additional_speed_tiers || []).includes('fast'),
|
|
21
22
|
context: m.context_window || null,
|
|
22
23
|
}))
|
|
23
24
|
}
|
|
@@ -27,7 +28,7 @@ export async function loadCodexModels(credentials, { force = false, fetcher = fe
|
|
|
27
28
|
try {
|
|
28
29
|
cached = JSON.parse(await readFile(cacheFile(), 'utf-8'))
|
|
29
30
|
} catch {}
|
|
30
|
-
if (!force && cached && Date.now() - cached.at < TTL) return mapCodexModels(cached.models)
|
|
31
|
+
if (!force && cached && Date.now() - cached.at < TTL && cached.models.every(model => Array.isArray(model.service_tiers) || Array.isArray(model.additional_speed_tiers))) return mapCodexModels(cached.models)
|
|
31
32
|
if (!credentials) return mapCodexModels(cached?.models || [])
|
|
32
33
|
|
|
33
34
|
try {
|
|
@@ -42,6 +43,8 @@ export async function loadCodexModels(credentials, { force = false, fetcher = fe
|
|
|
42
43
|
const data = await response.json()
|
|
43
44
|
const models = (data.models || []).map((m) => ({
|
|
44
45
|
slug: m.slug,
|
|
46
|
+
service_tiers: m.service_tiers || [],
|
|
47
|
+
additional_speed_tiers: m.additional_speed_tiers || [],
|
|
45
48
|
description: m.description,
|
|
46
49
|
label: m.label || m.display_name,
|
|
47
50
|
context_window: m.context_window || m.max_context_window || null,
|
package/src/controller.js
CHANGED
|
@@ -36,6 +36,11 @@ import { MAX_DELIBERATION_ROUNDS } from './deliberation.js'
|
|
|
36
36
|
import { buildUserContent, finalizeUserContent, inputTextFromContent, mediaTypeFor, stashImages } from './attachments.js'
|
|
37
37
|
import { settlePending } from './pending.js'
|
|
38
38
|
|
|
39
|
+
export const SPEED_LEVELS = [
|
|
40
|
+
{ key: 'standard', usage: '1x usage' },
|
|
41
|
+
{ key: 'fast', usage: '2.5x usage' },
|
|
42
|
+
]
|
|
43
|
+
|
|
39
44
|
export const EFFORT_LEVELS = [
|
|
40
45
|
{ key: null, desc: 'let the provider decide how much to think' },
|
|
41
46
|
{ key: 'low', desc: 'quick answers, minimal thinking' },
|
|
@@ -114,6 +119,8 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
114
119
|
defaultModel: boot.initialModel,
|
|
115
120
|
effort: boot.initialEffort,
|
|
116
121
|
defaultEffort: boot.initialEffort,
|
|
122
|
+
speedDefaults: { ...boot.speedDefaults },
|
|
123
|
+
speed: boot.speedDefaults?.[boot.initialModel.name] === 'fast' ? 'fast' : 'standard',
|
|
117
124
|
busy: false,
|
|
118
125
|
compacting: false,
|
|
119
126
|
compactOutcome: null,
|
|
@@ -293,6 +300,9 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
293
300
|
// by file needs to hear about it
|
|
294
301
|
emit('session', state.session)
|
|
295
302
|
}
|
|
303
|
+
if (!state.events.some(event => event.type === 'speed')) {
|
|
304
|
+
state.events.push(makeEvent('speed', { to: state.speed }))
|
|
305
|
+
}
|
|
296
306
|
while (state.persisted < state.events.length) {
|
|
297
307
|
state.session.append(state.events[state.persisted])
|
|
298
308
|
state.persisted++
|
|
@@ -350,6 +360,7 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
350
360
|
recorder,
|
|
351
361
|
modelName: worker.name,
|
|
352
362
|
effort: worker.effort ? 'low' : null,
|
|
363
|
+
...(worker.provider === 'codex' && { speed: 'standard' }),
|
|
353
364
|
auth,
|
|
354
365
|
system: context.system,
|
|
355
366
|
signal,
|
|
@@ -421,6 +432,7 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
421
432
|
recorder: toolset.recorder,
|
|
422
433
|
modelName: roleWorkers[role].name,
|
|
423
434
|
effort: roleWorkers[role].effort ? 'low' : null,
|
|
435
|
+
...(roleWorkers[role].provider === 'codex' && { speed: 'standard' }),
|
|
424
436
|
auth: roleAuths[role],
|
|
425
437
|
system: context.system,
|
|
426
438
|
signal: workerSignal,
|
|
@@ -606,6 +618,7 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
606
618
|
const raw = await compactHistory({
|
|
607
619
|
history: current.providerHistory,
|
|
608
620
|
modelName: state.model.name,
|
|
621
|
+
...(state.model.provider === 'codex' && { speed: speedApplies() ? state.speed : 'standard' }),
|
|
609
622
|
auth,
|
|
610
623
|
prompt: compactionPrompt(instructions),
|
|
611
624
|
signal: controller.signal,
|
|
@@ -828,6 +841,7 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
828
841
|
recorder,
|
|
829
842
|
modelName: state.model.name,
|
|
830
843
|
effort: effortApplies() ? state.effort ?? 'auto' : null,
|
|
844
|
+
...(state.model.provider === 'codex' && { speed: speedApplies() ? state.speed : 'standard' }),
|
|
831
845
|
auth,
|
|
832
846
|
system: context.system,
|
|
833
847
|
signal: controller.signal,
|
|
@@ -946,7 +960,7 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
946
960
|
set({ queued: [...state.expedited, ...state.queued], expedited: [] })
|
|
947
961
|
}
|
|
948
962
|
|
|
949
|
-
function resetConversation({ model, effort } = {}) {
|
|
963
|
+
function resetConversation({ model, effort, speed } = {}) {
|
|
950
964
|
state.session = null
|
|
951
965
|
state.events = []
|
|
952
966
|
state.persisted = 0
|
|
@@ -958,6 +972,7 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
958
972
|
state.peerPaused = false
|
|
959
973
|
state.model = model ?? state.defaultModel
|
|
960
974
|
state.effort = effort === undefined ? state.defaultEffort : effort
|
|
975
|
+
state.speed = speed ?? defaultSpeed(state.model)
|
|
961
976
|
}
|
|
962
977
|
|
|
963
978
|
async function newSession() {
|
|
@@ -1192,6 +1207,7 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
1192
1207
|
reDerive()
|
|
1193
1208
|
restoreModelFromSession()
|
|
1194
1209
|
state.effort = state.derived.effort === undefined ? state.defaultEffort : state.derived.effort
|
|
1210
|
+
state.speed = state.derived.speed ?? 'standard'
|
|
1195
1211
|
state.sent = userEntries(state.derived).map((e) => ({ text: recallText(e), at: header.createdAt }))
|
|
1196
1212
|
changed()
|
|
1197
1213
|
emit('session', state.session)
|
|
@@ -1319,6 +1335,8 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
1319
1335
|
}
|
|
1320
1336
|
persist(makeEvent('model_switch', { from: state.model.name, to: pick.name }))
|
|
1321
1337
|
state.model = pick
|
|
1338
|
+
state.speed = defaultSpeed(pick)
|
|
1339
|
+
persist(makeEvent('speed', { to: state.speed }))
|
|
1322
1340
|
if (asDefault) {
|
|
1323
1341
|
state.defaultModel = pick
|
|
1324
1342
|
writeConfig({ defaultModel: pick.name }).catch(() => {})
|
|
@@ -1335,6 +1353,23 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
1335
1353
|
switchModel(pick, { note: adhoc ? ' (not in catalog, pricing unknown)' : '' })
|
|
1336
1354
|
}
|
|
1337
1355
|
|
|
1356
|
+
const defaultSpeed = model => state.speedDefaults[model.name] === 'fast' ? 'fast' : 'standard'
|
|
1357
|
+
const speedApplies = () => state.model.provider === 'codex' && !!state.model.speed
|
|
1358
|
+
|
|
1359
|
+
function applySpeed(next, { asDefault = false } = {}) {
|
|
1360
|
+
if (!speedApplies()) return flash(`${state.model.name} does not support Fast mode`)
|
|
1361
|
+
if (!SPEED_LEVELS.some(level => level.key === next)) return flash('usage: /speed <standard|fast>')
|
|
1362
|
+
persist(makeEvent('speed', { to: next }))
|
|
1363
|
+
state.speed = next
|
|
1364
|
+
if (asDefault) {
|
|
1365
|
+
state.speedDefaults[state.model.name] = next
|
|
1366
|
+
writeConfig({ speedDefaults: { [state.model.name]: next } }).catch(error => flash(`speed default failed: ${errorText(error, 80)}`))
|
|
1367
|
+
}
|
|
1368
|
+
changed()
|
|
1369
|
+
flash(`speed: ${next}`)
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
const speedCommand = arg => applySpeed(arg.toLowerCase())
|
|
1338
1373
|
const effortApplies = () => !!state.model.effort
|
|
1339
1374
|
|
|
1340
1375
|
function setEffort(next, { asDefault = false } = {}) {
|
|
@@ -1714,6 +1749,9 @@ export function createController({ boot, run = runTurn, peerDirectory } = {}) {
|
|
|
1714
1749
|
resolveModel,
|
|
1715
1750
|
switchModel,
|
|
1716
1751
|
switchModelByName,
|
|
1752
|
+
speedApplies,
|
|
1753
|
+
applySpeed,
|
|
1754
|
+
speedCommand,
|
|
1717
1755
|
effortApplies,
|
|
1718
1756
|
setEffort,
|
|
1719
1757
|
setEffortByName,
|
package/src/derive.js
CHANGED
|
@@ -196,6 +196,7 @@ export function deriveState(events) {
|
|
|
196
196
|
historyEventIds: [],
|
|
197
197
|
model: null,
|
|
198
198
|
effort: undefined,
|
|
199
|
+
speed: undefined,
|
|
199
200
|
usage: spentUsage,
|
|
200
201
|
usageByModel: spentUsageByModel,
|
|
201
202
|
usageActive: emptyUsage(),
|
|
@@ -310,6 +311,9 @@ export function deriveState(events) {
|
|
|
310
311
|
case 'model_switch':
|
|
311
312
|
state.model = event.data.to
|
|
312
313
|
break
|
|
314
|
+
case 'speed':
|
|
315
|
+
state.speed = event.data.to
|
|
316
|
+
break
|
|
313
317
|
case 'effort':
|
|
314
318
|
state.effort = event.data.to
|
|
315
319
|
break
|