cuelo 0.6.9 → 0.7.0
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/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +10 -10
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.js +2 -2
- package/.next/required-server-files.json +2 -2
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/api/updates/route.js +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +4 -4
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/page.js +2 -2
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/recover/page_client-reference-manifest.js +1 -1
- package/.next/server/app/recover.html +1 -1
- package/.next/server/app/recover.rsc +2 -2
- package/.next/server/app/recover.segments/_full.segment.rsc +2 -2
- package/.next/server/app/recover.segments/_head.segment.rsc +1 -1
- package/.next/server/app/recover.segments/_index.segment.rsc +2 -2
- package/.next/server/app/recover.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/recover.segments/recover/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/recover.segments/recover.segment.rsc +1 -1
- package/.next/server/app-paths-manifest.json +10 -10
- package/.next/server/chunks/6429.js +2 -2
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/app/{layout-0082ed8a34057701.js → layout-89b7963cbc4da94d.js} +1 -1
- package/.next/static/chunks/app/{page-ca1d4378b3ad4549.js → page-042cc56cc090bf73.js} +2 -2
- package/.next/trace +105 -105
- package/.next/trace-build +1 -1
- package/README.md +2 -1
- package/Tools/CUELO_Setup/files/native-runtime-patch.js +5 -5
- package/Tools/OMP_Global_Config/patches/apply-core-patch.mjs +113 -55
- package/package.json +7 -7
- /package/.next/static/{4swMbGViH4DcOvsX9-ZTC → JfkwRK2BKBsxwumh964am}/_buildManifest.js +0 -0
- /package/.next/static/{4swMbGViH4DcOvsX9-ZTC → JfkwRK2BKBsxwumh964am}/_ssgManifest.js +0 -0
package/.next/trace-build
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"name":"run-webpack","duration":
|
|
1
|
+
[{"name":"run-webpack","duration":115346157,"timestamp":815400,"id":14,"parentId":1,"tags":{},"startTime":1790828618583,"traceId":"3fb5eebabbbdaa86"},{"name":"run-typescript","duration":19156024,"timestamp":116502438,"id":10735,"parentId":1,"tags":{},"startTime":1790828734272,"traceId":"3fb5eebabbbdaa86"},{"name":"static-check","duration":4633736,"timestamp":135758863,"id":10738,"parentId":1,"tags":{},"startTime":1790828753528,"traceId":"3fb5eebabbbdaa86"},{"name":"static-generation","duration":12729889,"timestamp":140502034,"id":10892,"parentId":1,"tags":{},"startTime":1790828758272,"traceId":"3fb5eebabbbdaa86"},{"name":"collect-build-traces","duration":22205456,"timestamp":140471277,"id":10889,"parentId":1,"tags":{},"startTime":1790828758241,"traceId":"3fb5eebabbbdaa86"},{"name":"telemetry-flush","duration":83,"timestamp":162681492,"id":10901,"parentId":1,"tags":{},"startTime":1790828780451,"traceId":"3fb5eebabbbdaa86"},{"name":"next-build","duration":161988669,"timestamp":692932,"id":1,"tags":{"buildMode":"default","version":"16.2.12","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1790828618461,"traceId":"3fb5eebabbbdaa86"}]
|
package/README.md
CHANGED
|
@@ -39,7 +39,8 @@ CUELO의 목적은 작업 중 확인한 실패와 막힘을 기억·작업 규
|
|
|
39
39
|
- 프로젝트별로 지난 omp 세션을 찾아 이어 가고, 실시간으로 스트리밍되는 대화에서 도구 호출·비용·컨텍스트 사용량을 봅니다.
|
|
40
40
|
- 이전 메시지에서 갈래를 나누거나(세션 안 분기), 별도 세션으로 fork합니다.
|
|
41
41
|
- 작업 공간(프로젝트·worktree)을 바꾸면 그곳에서 마지막으로 열어 둔 세션으로 돌아갑니다.
|
|
42
|
-
- goal 모드의 자동 이어 가기와 todo 진행 상황을 대화창 위에서 확인합니다.
|
|
42
|
+
- goal 모드의 자동 이어 가기와 todo 진행 상황을 대화창 위에서 확인합니다. 실행을 취소하면 자동 이어 가기가 멈추며, 일시정지된 목표는 `/goal resume`으로 재개합니다.
|
|
43
|
+
- 실행 중에 Steer로 지시를 바꾸면, 도구 호출이 없는 모델 요청은 서버의 전환 신호를 기다리지 않고 새 지시로 다시 요청합니다. 이미 보인 답변은 유지하며, 재요청에 따라 사용량이 늘 수 있습니다.
|
|
43
44
|
- 작업 로그 패널에서 이번 턴의 과정 항목과 턴마다 쓴 파일을 따로 봅니다.
|
|
44
45
|
- 입력창에 이미지·문서 외에 음성(받아쓰기), 코드·설정 파일(본문 첨부), 그 밖의 파일(저장 후 경로 첨부)을 붙여넣기·드롭·선택으로 넣습니다. 음성 받아쓰기에는 Google Antigravity 계정이 필요합니다.
|
|
45
46
|
- 에이전트가 생성하거나 확인한 이미지가 그 턴의 대화 흐름에 썸네일로 보이고, 누르면 크게 열립니다.
|
|
@@ -9,12 +9,12 @@ const MEMORY_RE = /(const phase1Model = await resolveMemoryModel\(\{[^}]*?fallba
|
|
|
9
9
|
const MEMORY_DONE = /const phase1Model = await resolveMemoryModel\(\{[^}]*?fallbackRole: "smol"/;
|
|
10
10
|
const EXPECTED = {
|
|
11
11
|
name: 'cuelo',
|
|
12
|
-
version: '0.
|
|
12
|
+
version: '0.7.0',
|
|
13
13
|
distribution: 'cuelo',
|
|
14
|
-
coreVersion: '18.4.
|
|
14
|
+
coreVersion: '18.4.6',
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
// OMP core 18.4.
|
|
17
|
+
// OMP core 18.4.6 `src/sdk.ts`: session-scoped AsyncJobManager for a process
|
|
18
18
|
// that hosts several top-level sessions (CUELO opens one per browser session).
|
|
19
19
|
// Upstream lets only the first top-level session construct a manager; every
|
|
20
20
|
// later one got `asyncJobManager: undefined`, so its `task` calls logged
|
|
@@ -23,7 +23,7 @@ const EXPECTED = {
|
|
|
23
23
|
// fix: it is disposed with its owning session (CUELO idle-shuts sessions
|
|
24
24
|
// after 10 minutes) and would cancel every other session's jobs, and a
|
|
25
25
|
// disposed manager throws on the next register(). Each edit is an exact text
|
|
26
|
-
// anchor of the pristine 18.4.
|
|
26
|
+
// anchor of the pristine 18.4.6 source (also present after core patch) and fails closed when it drifts.
|
|
27
27
|
// `insertBefore` edits keep their anchor (the helper is inserted in front of
|
|
28
28
|
// it), so their anchor count stays 1 after patching.
|
|
29
29
|
const SDK_FILE = path.join('node_modules', '@oh-my-pi', 'pi-coding-agent', 'src', 'sdk.ts');
|
|
@@ -177,7 +177,7 @@ function readNativePackage(target) {
|
|
|
177
177
|
throw new Error(`unexpected native package ${packageJson.name}@${packageJson.version}`);
|
|
178
178
|
}
|
|
179
179
|
if (!build || build.distribution !== EXPECTED.distribution || build.coreVersion !== EXPECTED.coreVersion) {
|
|
180
|
-
throw new Error('native cueloBuild metadata does not match cuelo / core 18.4.
|
|
180
|
+
throw new Error('native cueloBuild metadata does not match cuelo / core 18.4.6');
|
|
181
181
|
}
|
|
182
182
|
return packageJson;
|
|
183
183
|
}
|
|
@@ -8133,8 +8133,8 @@ function parentSubagentServiceTiers(
|
|
|
8133
8133
|
// 계정에서는 400 뒤 재시도로만 복구된다. 내장 모델은 구워진 models.json 값을 그대로 쓰고, 규칙으로 새로 만드는
|
|
8134
8134
|
// 모델(discovery 등)은 rules.json을 쓰므로 두 곳에 prefixBinding과 binding controls(beta)를 같이 채운다.
|
|
8135
8135
|
// binding controls의 provider 범위는 그 버전 upstream Sonnet 5.5 규칙과 같게 둔다: 18.4.4는 Claude API·
|
|
8136
|
-
// Cloudflare·Vertex, 18.4.5
|
|
8137
|
-
// 거절해 Claude API·Cloudflare만(classes/anthropic.kdl:128). wire의 block_binding은 prefixBinding과 binding
|
|
8136
|
+
// Cloudflare·Vertex, 18.4.5·18.4.6은 Vertex가 `thinking.adaptive.block_binding: Extra inputs are not permitted`(400)로
|
|
8137
|
+
// 거절해 Claude API·Cloudflare만(classes/anthropic.kdl:128, 18.4.6은 kdl:129). wire의 block_binding은 prefixBinding과 binding
|
|
8138
8138
|
// controls가 둘 다 참일 때만 나간다(anthropic.ts prefixMismatchBehavior). models.yml은 thinking override의
|
|
8139
8139
|
// prefixBinding을 스키마에서 조용히 버리고 공개 설치에는 없으므로 설정으로 켜지 않는다.
|
|
8140
8140
|
{
|
|
@@ -8144,23 +8144,38 @@ function parentSubagentServiceTiers(
|
|
|
8144
8144
|
patched: '"claude-opus-5-5":{"id":"claude-opus-5-5","name":"Claude Opus 5.5","api":"anthropic-messages","provider":"anthropic","baseUrl":"https://api.anthropic.com","reasoning":true,"input":["text","image"],"cost":{"input":4,"output":20,"cacheRead":0.2,"cacheWrite":5},"contextWindow":1000000,"maxTokens":128000,"int":57.6,"tps":95.2,"thinking":{"mode":"anthropic-adaptive","efforts":["low","medium","high","xhigh","max"],"supportsDisplay":true,"prefixBinding":true},"identity":{"class":"anthropic","family":"opus","revision":"5.5.0"},"requiresGlyphTokenization":true,"tokenizer":"claude-v5","supportsComputerUse":false,"compat":{"officialEndpoint":true,"signingEndpoint":true,"supportsContextManagement":true,"supportsServerCompaction":true,"firstPartyProvider":true,"supportsOutputEffort":true,"disableStrictTools":false,"disableAdaptiveThinking":false,"allowAnthropicHeaderOverrides":false,"supportsEagerToolInputStreaming":true,"supportsLongCacheRetention":true,"supportsMidConversationSystem":true,"supportsTurnScopedSystem":true,"supportsMidConversationToolChanges":true,"supportsPerMessageEffort":true,"supportsThinkingBindingControls":true',
|
|
8145
8145
|
},
|
|
8146
8146
|
{
|
|
8147
|
-
// 모든 provider의 Opus 5.5 규칙 계보에 prefixBinding(Sonnet 5.5
|
|
8148
|
-
// 18.4.4
|
|
8147
|
+
// 모든 provider의 Opus 5.5 규칙 계보에 prefixBinding(Sonnet 5.5 규칙과 같은 모양). 18.4.6은 kdl 한 줄 이동으로
|
|
8148
|
+
// source가 kdl:61이고 규칙 본문은 같다. alternate는 18.4.4·18.4.5 공통 kdl:60 앵커다. 두 후보의 marker는 source가
|
|
8149
|
+
// 달라 서로의 결과·순정본에 들어 있지 않다. 18.4.4 적용본은 kdl:60 patched 바로 뒤에 binding controls 규칙이 붙어
|
|
8150
|
+
// 있어 alternate marker가 그대로 성립한다.
|
|
8149
8151
|
file: "../pi-catalog/src/compat/rules.json",
|
|
8150
|
-
marker: '{"source":"classes/anthropic.kdl:
|
|
8151
|
-
anchor: '{"source":"classes/anthropic.kdl:
|
|
8152
|
-
patched: '{"source":"classes/anthropic.kdl:
|
|
8152
|
+
marker: '{"source":"classes/anthropic.kdl:61","class":"anthropic","family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsForcedToolChoice":false},"thinking":{"prefixBinding":true}}',
|
|
8153
|
+
anchor: '{"source":"classes/anthropic.kdl:61","class":"anthropic","family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsForcedToolChoice":false}}',
|
|
8154
|
+
patched: '{"source":"classes/anthropic.kdl:61","class":"anthropic","family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsForcedToolChoice":false},"thinking":{"prefixBinding":true}}',
|
|
8155
|
+
alternates: [{
|
|
8156
|
+
file: "../pi-catalog/src/compat/rules.json",
|
|
8157
|
+
marker: '{"source":"classes/anthropic.kdl:60","class":"anthropic","family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsForcedToolChoice":false},"thinking":{"prefixBinding":true}}',
|
|
8158
|
+
anchor: '{"source":"classes/anthropic.kdl:60","class":"anthropic","family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsForcedToolChoice":false}}',
|
|
8159
|
+
patched: '{"source":"classes/anthropic.kdl:60","class":"anthropic","family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsForcedToolChoice":false},"thinking":{"prefixBinding":true}}',
|
|
8160
|
+
}],
|
|
8153
8161
|
},
|
|
8154
8162
|
{
|
|
8155
8163
|
// binding controls 규칙은 그 버전의 upstream Sonnet 5.5 binding 규칙 바로 뒤에 같은 provider 범위로 둔다.
|
|
8156
|
-
// 18.4.5: kdl:128(anthropic·cloudflare). alternate 18.4.4:
|
|
8157
|
-
// 18.4.4
|
|
8158
|
-
//
|
|
8164
|
+
// 18.4.6: kdl:129, alternate 18.4.5: kdl:128(둘 다 anthropic·cloudflare, 규칙 본문 동일). alternate 18.4.4:
|
|
8165
|
+
// kdl:106(anthropic·cloudflare·vertex). 18.4.6·18.4.5 후보는 추가 규칙이 같아 marker를 앞 Sonnet 규칙까지 포함한
|
|
8166
|
+
// patched 전체로 둔다(같은 marker면 둘 다 applied라 ambiguous가 된다). 18.4.4 라이브 적용본은 옛 위치(kdl:60 뒤)에
|
|
8167
|
+
// 같은 규칙이 있어 그 alternate marker로 applied이다. 그 적용본의 --revert는 patched가 연속으로 없으므로 엔진의
|
|
8168
|
+
// 백업 경로(~/.omp/core-patch-backup)를 쓴다.
|
|
8159
8169
|
file: "../pi-catalog/src/compat/rules.json",
|
|
8160
|
-
marker: '{"source":"cuelo:opus-5.5-thinking-binding","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsThinkingBindingControls":true}}',
|
|
8161
|
-
anchor: '{"source":"classes/anthropic.kdl:
|
|
8162
|
-
patched: '{"source":"classes/anthropic.kdl:
|
|
8170
|
+
marker: '{"source":"classes/anthropic.kdl:129","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"sonnet","revision":[{"op":">=","revision":"5.5.0"}],"wire":{"supportsThinkingBindingControls":true}},{"source":"cuelo:opus-5.5-thinking-binding","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsThinkingBindingControls":true}}',
|
|
8171
|
+
anchor: '{"source":"classes/anthropic.kdl:129","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"sonnet","revision":[{"op":">=","revision":"5.5.0"}],"wire":{"supportsThinkingBindingControls":true}}',
|
|
8172
|
+
patched: '{"source":"classes/anthropic.kdl:129","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"sonnet","revision":[{"op":">=","revision":"5.5.0"}],"wire":{"supportsThinkingBindingControls":true}},{"source":"cuelo:opus-5.5-thinking-binding","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsThinkingBindingControls":true}}',
|
|
8163
8173
|
alternates: [{
|
|
8174
|
+
file: "../pi-catalog/src/compat/rules.json",
|
|
8175
|
+
marker: '{"source":"classes/anthropic.kdl:128","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"sonnet","revision":[{"op":">=","revision":"5.5.0"}],"wire":{"supportsThinkingBindingControls":true}},{"source":"cuelo:opus-5.5-thinking-binding","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsThinkingBindingControls":true}}',
|
|
8176
|
+
anchor: '{"source":"classes/anthropic.kdl:128","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"sonnet","revision":[{"op":">=","revision":"5.5.0"}],"wire":{"supportsThinkingBindingControls":true}}',
|
|
8177
|
+
patched: '{"source":"classes/anthropic.kdl:128","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"sonnet","revision":[{"op":">=","revision":"5.5.0"}],"wire":{"supportsThinkingBindingControls":true}},{"source":"cuelo:opus-5.5-thinking-binding","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway"],"family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsThinkingBindingControls":true}}',
|
|
8178
|
+
}, {
|
|
8164
8179
|
file: "../pi-catalog/src/compat/rules.json",
|
|
8165
8180
|
marker: '{"source":"cuelo:opus-5.5-thinking-binding","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway","google-vertex"],"family":"opus","revision":[{"op":">=","revision":"5.5.0"},{"op":"<","revision":"6.0.0"}],"wire":{"supportsThinkingBindingControls":true}}',
|
|
8166
8181
|
anchor: '{"source":"classes/anthropic.kdl:106","class":"anthropic","providers":["anthropic","cloudflare-ai-gateway","google-vertex"],"family":"sonnet","revision":[{"op":">=","revision":"5.5.0"}],"wire":{"supportsMidConversationSystem":true,"supportsMidConversationToolChanges":true,"supportsTurnScopedSystem":true,"supportsPerMessageEffort":true,"supportsThinkingBindingControls":true}}',
|
|
@@ -8340,20 +8355,24 @@ function parentSubagentServiceTiers(
|
|
|
8340
8355
|
anchor: 'import { createRatchetPrelude } from "./ratchet/prelude";',
|
|
8341
8356
|
patched: 'import { createRatchetPrelude } from "./ratchet/prelude.ts";',
|
|
8342
8357
|
},
|
|
8343
|
-
// P55. genuine 사용자 steer 가
|
|
8358
|
+
// P55. genuine 사용자 steer 가 진행 중 모델 요청을 끝까지 기다리지 않게 한다(사용자 결정: 즉시 반영, 재추론 사용량 감수).
|
|
8344
8359
|
// 2026-10-01 사용자 관측: Astra(xhigh) 4분짜리 추론 요청 중 넣은 steer 가 그 요청이 끝날 때까지(98.8s·169.6s)
|
|
8345
8360
|
// 큐에 머물렀고, Opus 는 바로 개입되는 것처럼 보였다. Agent.steer 는 큐에만 넣고 모델 스트림은 끊지 않으며
|
|
8346
8361
|
// (도구 실행만 interrupt), Codex native turn lane 은 `response.steer` 를 거절(P48 sticky)하고 SSE·Anthropic 은
|
|
8347
|
-
// live 주입이 없다.
|
|
8348
|
-
//
|
|
8349
|
-
//
|
|
8350
|
-
//
|
|
8351
|
-
//
|
|
8352
|
-
//
|
|
8353
|
-
//
|
|
8362
|
+
// live 주입이 없다. r3(같은 날 두 번째 관측): native 가 steer 를 accept 해도 서버가 다음 output boundary 에서
|
|
8363
|
+
// incomplete(steered)로 멈춰야 진행되는데, 멈추지 않으면 사용자가 직접 취소할 때까지 기다렸다(accept 뒤 9.4s 무응답).
|
|
8364
|
+
// 그래서 tool call 이 아직 없는 요청이면 live 채널 미부착·claim reject·defer·accept 어느 쪽이든 요청 전용
|
|
8365
|
+
// AbortSignal(promptToolAbortController 와 같이 provider signal 에만 병합)로 그 provider 호출을 끊는다. 이미 보인
|
|
8366
|
+
// text 와 완료(_end)된 서명 reasoning 은 stop 으로 commit 하고 아직 스트리밍 중인 tail 만 버린다. 보인 것이 없으면
|
|
8367
|
+
// partial 은 message_end 없이 버린다(context·persist·replay 에 남지 않음, 웹은 다음 message_start 가 live bubble 을
|
|
8368
|
+
// 교체). 같은 run·같은 turn 안에서 steering(채널이 accept 한 것 포함, 정확히 한 번)을 경계 주입해 새 요청을 보낸다.
|
|
8369
|
+
// session/agent/loop abort·goal pause·실행 중 도구는 건드리지 않는다. tool call 이 이미 보였으면 기존대로 boundary
|
|
8370
|
+
// 처리. 내부 IRC/advisory/custom/agent steer·follow-up 은 대상이 아니다.
|
|
8371
|
+
// 회귀: patches/core-steer-stream-test.ts(실제 Agent 루프 + Codex/SSE wire fixture + 실제 AgentSession).
|
|
8354
8372
|
{
|
|
8355
8373
|
file: "../pi-agent-core/src/agent-loop.ts",
|
|
8356
|
-
marker:
|
|
8374
|
+
// r3 marker: r2 적용본(같은 class, 인자 없는 생성자)을 applied 로 보지 않는다.
|
|
8375
|
+
marker: " constructor(readonly committed?: AssistantMessage) {\n super(\"User steering restarted the in-flight model request\");",
|
|
8357
8376
|
anchor: "class HarmonyLeakInterruption extends Error {",
|
|
8358
8377
|
patched: `/** CUELO P55: race token for a request-only restart requested by genuine user steering. */
|
|
8359
8378
|
const STEER_RESTART = Symbol("steer-restart");
|
|
@@ -8366,12 +8385,13 @@ const STEER_RESTART = Symbol("steer-restart");
|
|
|
8366
8385
|
export const STEER_DISCARDED_PARTIAL = Symbol("pi-agent-core.steer-discarded-partial");
|
|
8367
8386
|
|
|
8368
8387
|
/**
|
|
8369
|
-
* CUELO P55: genuine user steering ended the in-flight request
|
|
8370
|
-
*
|
|
8371
|
-
* the steering at this boundary and re-requests in the
|
|
8388
|
+
* CUELO P55: genuine user steering ended the in-flight request. Visible output that already
|
|
8389
|
+
* reached listeners is \`committed\` (stop); otherwise the partial was discarded (never committed,
|
|
8390
|
+
* persisted or replayed). The loop delivers the steering at this boundary and re-requests in the
|
|
8391
|
+
* same run.
|
|
8372
8392
|
*/
|
|
8373
8393
|
class SteeringRestartInterruption extends Error {
|
|
8374
|
-
constructor() {
|
|
8394
|
+
constructor(readonly committed?: AssistantMessage) {
|
|
8375
8395
|
super("User steering restarted the in-flight model request");
|
|
8376
8396
|
this.name = "SteeringRestartInterruption";
|
|
8377
8397
|
}
|
|
@@ -8386,7 +8406,7 @@ function isGenuineUserSteer(message: AgentMessage): boolean {
|
|
|
8386
8406
|
);
|
|
8387
8407
|
}
|
|
8388
8408
|
|
|
8389
|
-
/** CUELO P55: text or a tool call already reached listeners; such a partial is never discarded
|
|
8409
|
+
/** CUELO P55: text or a tool call already reached listeners; such a partial is committed, never discarded. */
|
|
8390
8410
|
function hasVisibleAssistantOutput(message: AssistantMessage | null): boolean {
|
|
8391
8411
|
return (
|
|
8392
8412
|
message?.content.some(
|
|
@@ -8413,7 +8433,7 @@ class HarmonyLeakInterruption extends Error {`,
|
|
|
8413
8433
|
},
|
|
8414
8434
|
{
|
|
8415
8435
|
file: "../pi-agent-core/src/agent-loop.ts",
|
|
8416
|
-
marker: "const
|
|
8436
|
+
marker: "const restartForSteering = async (): Promise<never> => {",
|
|
8417
8437
|
anchor: ` detachAbortListener = () => requestSignal.removeEventListener("abort", onAbort);
|
|
8418
8438
|
}
|
|
8419
8439
|
|
|
@@ -8439,31 +8459,42 @@ class HarmonyLeakInterruption extends Error {`,
|
|
|
8439
8459
|
patched: ` detachAbortListener = () => requestSignal.removeEventListener("abort", onAbort);
|
|
8440
8460
|
}
|
|
8441
8461
|
|
|
8442
|
-
// CUELO P55: genuine user steering ends this request
|
|
8443
|
-
// (
|
|
8444
|
-
//
|
|
8445
|
-
// rejected
|
|
8462
|
+
// CUELO P55: genuine user steering ends this request unless a tool call already streamed
|
|
8463
|
+
// (that turn ends at its normal boundary, tool results first). A pump attached to the channel
|
|
8464
|
+
// may still take the steer live, so the request waits for its claim to settle; once the claim
|
|
8465
|
+
// is accepted, rejected or deferred, the request is replaced: an accepted steer only stops the
|
|
8466
|
+
// response at a server-chosen boundary that may never come.
|
|
8446
8467
|
const steerChannel = providerCall.liveSteering;
|
|
8447
8468
|
let steerRestartClosed = false;
|
|
8448
8469
|
const requestSteerRestart = (): void => {
|
|
8449
8470
|
if (!steerRestartController || steerRestartClosed || steerRestartController.signal.aborted) return;
|
|
8450
|
-
if (
|
|
8451
|
-
if (
|
|
8471
|
+
if (partialMessage?.content.some(block => block.type === "toolCall")) return;
|
|
8472
|
+
if (
|
|
8473
|
+
steerChannel?.attached &&
|
|
8474
|
+
steerChannel.deferred.length === 0 &&
|
|
8475
|
+
!steerChannel.accepted.some(isGenuineUserSteer)
|
|
8476
|
+
) {
|
|
8477
|
+
return;
|
|
8478
|
+
}
|
|
8452
8479
|
steerRestartController.abort();
|
|
8453
8480
|
};
|
|
8454
8481
|
const detachUserSteeringRestart = steerRestartController
|
|
8455
8482
|
? config.onUserSteeringQueued?.(requestSteerRestart)
|
|
8456
8483
|
: undefined;
|
|
8457
8484
|
if (steerRestartController && steerChannel) {
|
|
8458
|
-
steerChannel.
|
|
8459
|
-
if (
|
|
8485
|
+
steerChannel.onClaimSettled = () => {
|
|
8486
|
+
if (
|
|
8487
|
+
steerChannel.accepted.some(isGenuineUserSteer) ||
|
|
8488
|
+
steerChannel.deferred.some(isGenuineUserSteer) ||
|
|
8489
|
+
hasNewUserSteering?.() === true
|
|
8490
|
+
) {
|
|
8460
8491
|
requestSteerRestart();
|
|
8461
8492
|
}
|
|
8462
8493
|
};
|
|
8463
8494
|
}
|
|
8464
8495
|
const detachSteerRestart = (): void => {
|
|
8465
8496
|
detachUserSteeringRestart?.();
|
|
8466
|
-
if (steerChannel) steerChannel.
|
|
8497
|
+
if (steerChannel) steerChannel.onClaimSettled = undefined;
|
|
8467
8498
|
};
|
|
8468
8499
|
let steerRestartRace: Promise<typeof STEER_RESTART> | undefined;
|
|
8469
8500
|
if (steerRestartController) {
|
|
@@ -8471,18 +8502,36 @@ class HarmonyLeakInterruption extends Error {`,
|
|
|
8471
8502
|
steerRestartController.signal.addEventListener("abort", () => resolve(STEER_RESTART), { once: true });
|
|
8472
8503
|
steerRestartRace = promise;
|
|
8473
8504
|
}
|
|
8474
|
-
//
|
|
8475
|
-
//
|
|
8476
|
-
|
|
8505
|
+
// Visible text stays: commit it with the reasoning that completed before it (closed, signed
|
|
8506
|
+
// blocks) and drop only the still-streaming tail. Nothing visible: drop the partial without
|
|
8507
|
+
// message_end, so listeners never receive it as a message and it is not committed, persisted
|
|
8508
|
+
// or replayed (the next message_start replaces the live bubble).
|
|
8509
|
+
const restartForSteering = async (): Promise<never> => {
|
|
8477
8510
|
steerRestartClosed = true;
|
|
8478
8511
|
try {
|
|
8479
8512
|
const cleanup = responseIterator.return?.();
|
|
8480
8513
|
if (cleanup) void cleanup.catch(() => {});
|
|
8481
8514
|
} catch {
|
|
8482
|
-
// Provider cancellation failures cannot resurrect the discarded
|
|
8515
|
+
// Provider cancellation failures cannot resurrect the discarded tail.
|
|
8483
8516
|
}
|
|
8484
8517
|
await speculationCoordinator?.discardAll("user steering restarted the request", "discarded");
|
|
8485
8518
|
speculationSettled = true;
|
|
8519
|
+
if (addedPartial && partialMessage && hasVisibleAssistantOutput(partialMessage)) {
|
|
8520
|
+
const committed = snapshotAssistantMessage({
|
|
8521
|
+
...partialMessage,
|
|
8522
|
+
content: partialMessage.content.filter((block, index) => {
|
|
8523
|
+
if (block.type === "text") return block.text.trim().length > 0;
|
|
8524
|
+
if (block.type === "thinking") return !openBlocks.has(index) && Boolean(block.thinkingSignature);
|
|
8525
|
+
if (block.type === "redactedThinking") return !openBlocks.has(index);
|
|
8526
|
+
return false;
|
|
8527
|
+
}),
|
|
8528
|
+
stopReason: "stop",
|
|
8529
|
+
});
|
|
8530
|
+
context.messages[context.messages.length - 1] = committed;
|
|
8531
|
+
addedPartial = false;
|
|
8532
|
+
stream.push({ type: "message_end", message: snapshotAssistantMessage(committed) });
|
|
8533
|
+
throw new SteeringRestartInterruption(committed);
|
|
8534
|
+
}
|
|
8486
8535
|
if (addedPartial) {
|
|
8487
8536
|
context.messages.pop();
|
|
8488
8537
|
addedPartial = false;
|
|
@@ -8506,10 +8555,10 @@ class HarmonyLeakInterruption extends Error {`,
|
|
|
8506
8555
|
if (result === ABORTED) {
|
|
8507
8556
|
return await finishAbortedStream();
|
|
8508
8557
|
}
|
|
8509
|
-
// A chunk that raced the restart is dropped
|
|
8558
|
+
// A chunk that raced the restart is dropped: it never reached listeners.
|
|
8510
8559
|
if (result === STEER_RESTART || steerRestartController?.signal.aborted) {
|
|
8511
8560
|
if (requestSignal?.aborted) return await finishAbortedStream();
|
|
8512
|
-
return await
|
|
8561
|
+
return await restartForSteering();
|
|
8513
8562
|
}
|
|
8514
8563
|
next = result;
|
|
8515
8564
|
} else {
|
|
@@ -8536,23 +8585,25 @@ class HarmonyLeakInterruption extends Error {`,
|
|
|
8536
8585
|
},
|
|
8537
8586
|
{
|
|
8538
8587
|
file: "../pi-agent-core/src/agent-loop.ts",
|
|
8539
|
-
marker: "if (steerRestartController?.signal.aborted && !requestSignal?.aborted) await
|
|
8588
|
+
marker: "if (steerRestartController?.signal.aborted && !requestSignal?.aborted) await restartForSteering();",
|
|
8540
8589
|
anchor: ` try {
|
|
8541
8590
|
let trailing = await response.result();`,
|
|
8542
|
-
patched: ` // CUELO P55: the iterator ended after a restart was requested;
|
|
8543
|
-
if (steerRestartController?.signal.aborted && !requestSignal?.aborted) await
|
|
8591
|
+
patched: ` // CUELO P55: the iterator ended after a restart was requested; restart instead of finalizing.
|
|
8592
|
+
if (steerRestartController?.signal.aborted && !requestSignal?.aborted) await restartForSteering();
|
|
8544
8593
|
steerRestartClosed = true;
|
|
8545
8594
|
try {
|
|
8546
8595
|
let trailing = await response.result();`,
|
|
8547
8596
|
},
|
|
8548
8597
|
{
|
|
8549
8598
|
file: "../pi-agent-core/src/agent-loop.ts",
|
|
8550
|
-
marker: "if (err
|
|
8599
|
+
marker: "if (err.committed) newMessages.push(err.committed);",
|
|
8551
8600
|
anchor: " if (!(err instanceof HarmonyLeakInterruption)) throw err;",
|
|
8552
8601
|
patched: ` if (err instanceof SteeringRestartInterruption) {
|
|
8553
|
-
// CUELO P55: the
|
|
8602
|
+
// CUELO P55: the committed visible output (if any) is already in context and was
|
|
8603
|
+
// delivered with message_end; a discarded partial never reached either. Deliver the
|
|
8554
8604
|
// steering (plus anything the live channel took for the aborted response) at this
|
|
8555
8605
|
// boundary and re-request inside the same turn and run; run/goal state is untouched.
|
|
8606
|
+
if (err.committed) newMessages.push(err.committed);
|
|
8556
8607
|
const channel = preparedProviderCall.liveSteering;
|
|
8557
8608
|
const taken = channel ? [...channel.accepted.splice(0), ...channel.deferred.splice(0)] : [];
|
|
8558
8609
|
const steering = [...taken, ...((await config.getSteeringMessages?.(signal)) || [])];
|
|
@@ -8569,12 +8620,12 @@ class HarmonyLeakInterruption extends Error {`,
|
|
|
8569
8620
|
},
|
|
8570
8621
|
{
|
|
8571
8622
|
file: "../pi-agent-core/src/live-steering.ts",
|
|
8572
|
-
marker: "
|
|
8623
|
+
marker: " onClaimSettled: (() => void) | undefined;\n",
|
|
8573
8624
|
anchor: " readonly #queue: LiveSteeringQueue;\n",
|
|
8574
8625
|
patched: ` /** CUELO P55: a provider pump pulls from this channel (set on its first wait). */
|
|
8575
8626
|
attached = false;
|
|
8576
|
-
/** CUELO P55: notified after
|
|
8577
|
-
|
|
8627
|
+
/** CUELO P55: notified after a claim settles: input accepted live, rejected, or deferred to the boundary. */
|
|
8628
|
+
onClaimSettled: (() => void) | undefined;
|
|
8578
8629
|
readonly #queue: LiveSteeringQueue;
|
|
8579
8630
|
`,
|
|
8580
8631
|
},
|
|
@@ -8586,15 +8637,22 @@ class HarmonyLeakInterruption extends Error {`,
|
|
|
8586
8637
|
},
|
|
8587
8638
|
{
|
|
8588
8639
|
file: "../pi-agent-core/src/live-steering.ts",
|
|
8589
|
-
marker: " this.deferred.push(...messages);\n this.
|
|
8640
|
+
marker: " this.deferred.push(...messages);\n this.onClaimSettled?.();\n return undefined;",
|
|
8590
8641
|
anchor: " this.deferred.push(...messages);\n return undefined;",
|
|
8591
|
-
patched: " this.deferred.push(...messages);\n this.
|
|
8642
|
+
patched: " this.deferred.push(...messages);\n this.onClaimSettled?.();\n return undefined;",
|
|
8592
8643
|
},
|
|
8593
8644
|
{
|
|
8594
8645
|
file: "../pi-agent-core/src/live-steering.ts",
|
|
8595
|
-
marker: " this.deferred.push(...messages);\n this.
|
|
8646
|
+
marker: " this.deferred.push(...messages);\n this.onClaimSettled?.();\n },",
|
|
8596
8647
|
anchor: " this.deferred.push(...messages);\n },",
|
|
8597
|
-
patched: " this.deferred.push(...messages);\n this.
|
|
8648
|
+
patched: " this.deferred.push(...messages);\n this.onClaimSettled?.();\n },",
|
|
8649
|
+
},
|
|
8650
|
+
{
|
|
8651
|
+
// r3: accept 도 claim 정산이다. 채널이 받은 genuine steer 로 진행 중 요청을 교체한다(위 requestSteerRestart).
|
|
8652
|
+
file: "../pi-agent-core/src/live-steering.ts",
|
|
8653
|
+
marker: " this.accepted.push(...messages);\n this.onClaimSettled?.();\n",
|
|
8654
|
+
anchor: " this.accepted.push(...messages);\n",
|
|
8655
|
+
patched: " this.accepted.push(...messages);\n this.onClaimSettled?.();\n",
|
|
8598
8656
|
},
|
|
8599
8657
|
// P55 r2: 버린 partial 은 Agent#runLoop 의 지역 `partial` 에 마지막 snapshot 으로 남는다(message_end 만 비운다).
|
|
8600
8658
|
// 경계의 steering dequeue 가 던지거나(예: AgentSession usage preflight 의 "Usage preflight cancelled") 비어 있고
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cuelo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "CUELO — open-source AI coding agent workspace and harness for omp (oh-my-pi)",
|
|
5
5
|
"homepage": "https://github.com/gim47656-ship-it/CUELO#readme",
|
|
6
6
|
"repository": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"cueloBuild": {
|
|
32
32
|
"distribution": "cuelo",
|
|
33
|
-
"coreVersion": "18.4.
|
|
33
|
+
"coreVersion": "18.4.6"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=22.19.0",
|
|
@@ -88,11 +88,11 @@
|
|
|
88
88
|
"test:coverage": "bun test --coverage ./app ./components ./hooks ./lib ./public ./bin ./install.test.mjs"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
-
"@oh-my-pi/pi-agent-core": "18.4.
|
|
92
|
-
"@oh-my-pi/pi-ai": "18.4.
|
|
93
|
-
"@oh-my-pi/pi-coding-agent": "18.4.
|
|
94
|
-
"@oh-my-pi/pi-tui": "18.4.
|
|
95
|
-
"@oh-my-pi/pi-utils": "18.4.
|
|
91
|
+
"@oh-my-pi/pi-agent-core": "18.4.6",
|
|
92
|
+
"@oh-my-pi/pi-ai": "18.4.6",
|
|
93
|
+
"@oh-my-pi/pi-coding-agent": "18.4.6",
|
|
94
|
+
"@oh-my-pi/pi-tui": "18.4.6",
|
|
95
|
+
"@oh-my-pi/pi-utils": "18.4.6",
|
|
96
96
|
"@seed-design/css": "2.8.0",
|
|
97
97
|
"@seed-design/react": "2.4.1",
|
|
98
98
|
"@seed-design/tailwind4-theme": "2.4.0",
|
|
File without changes
|
|
File without changes
|