cuelo 0.5.4 → 0.5.6
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 +8 -8
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.js +1 -1
- package/.next/required-server-files.json +1 -1
- 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.js +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 +4 -4
- package/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- 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 +2 -2
- package/.next/server/app/api/agent/[id]/account/route.js +1 -1
- package/.next/server/app/api/agent/[id]/account/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/events/route.js +1 -1
- package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/route.js +1 -1
- package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/new/route.js +1 -1
- package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/running/route.js +1 -1
- package/.next/server/app/api/agent/running/route.js.nft.json +1 -1
- package/.next/server/app/api/gpt6/handles/route.js +1 -1
- package/.next/server/app/api/gpt6/handles/route.js.nft.json +1 -1
- package/.next/server/app/api/gpt6/mcp/route.js +1 -1
- package/.next/server/app/api/gpt6/mcp/route.js.nft.json +1 -1
- package/.next/server/app/api/gpt6/reply/route.js +1 -1
- package/.next/server/app/api/gpt6/reply/route.js.nft.json +1 -1
- package/.next/server/app/api/gpt6/token/route.js +1 -1
- package/.next/server/app/api/gpt6/token/route.js.nft.json +1 -1
- package/.next/server/app/api/gpt6/web6-session/route.js +1 -1
- package/.next/server/app/api/gpt6/web6-session/route.js.nft.json +1 -1
- package/.next/server/app/api/live/call/[callId]/route.js +1 -1
- package/.next/server/app/api/live/call/[callId]/route.js.nft.json +1 -1
- package/.next/server/app/api/live/events/route.js +1 -1
- package/.next/server/app/api/live/events/route.js.nft.json +1 -1
- package/.next/server/app/api/live/offer/route.js +1 -1
- package/.next/server/app/api/live/offer/route.js.nft.json +1 -1
- package/.next/server/app/api/live/voices/route.js +1 -1
- package/.next/server/app/api/live/voices/route.js.nft.json +1 -1
- package/.next/server/app/api/project-trust/route.js +1 -1
- package/.next/server/app/api/project-trust/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/auto-name/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/auto-name/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/context/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/context/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/state/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/state/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/route.js +1 -1
- package/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/server/app/api/update-maintenance/route.js +2 -2
- package/.next/server/app/api/update-maintenance/route.js.nft.json +1 -1
- package/.next/server/app/api/updates/route.js +1 -1
- package/.next/server/app/favicon.ico/route.js +1 -1
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +6 -6
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/index.segments/_full.segment.rsc +6 -6
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- 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.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 +4 -4
- package/.next/server/app/recover.segments/_full.segment.rsc +4 -4
- package/.next/server/app/recover.segments/_head.segment.rsc +1 -1
- package/.next/server/app/recover.segments/_index.segment.rsc +3 -3
- package/.next/server/app/recover.segments/_tree.segment.rsc +2 -2
- 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 +8 -8
- package/.next/server/chunks/6429.js +3 -3
- 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-61356b8386302172.js → layout-6261ac86255ccc75.js} +1 -1
- package/.next/static/chunks/app/{page-d1291e02ffa77a51.js → page-d101dfa547083afb.js} +2 -2
- package/.next/static/css/{41958fa4965167ad.css → 0282259eb1a6b95f.css} +1 -1
- package/.next/trace +104 -104
- package/.next/trace-build +1 -1
- package/Tools/CUELO_Setup/files/native-runtime-patch.js +1 -1
- package/Tools/OMP_Global_Config/agent/extensions/jev-runtime.ts +10 -3
- package/Tools/OMP_Global_Config/agent/extensions/turn-end-guard.ts +4 -0
- package/Tools/OMP_Global_Config/patches/apply-core-patch.mjs +124 -6
- package/install.mjs +5 -3
- package/package.json +1 -1
- package/public/icons/apple-touch-icon.png +0 -0
- package/public/icons/cuelo-icon.svg +8 -0
- package/public/icons/icon-192.png +0 -0
- package/public/icons/icon-512.png +0 -0
- package/public/sw.js +3 -2
- /package/.next/static/{Xey7BdddcpqFxM5-ikcal → NZvNUVntEzl6V9pD45vuq}/_buildManifest.js +0 -0
- /package/.next/static/{Xey7BdddcpqFxM5-ikcal → NZvNUVntEzl6V9pD45vuq}/_ssgManifest.js +0 -0
package/.next/trace-build
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"name":"run-webpack","duration":
|
|
1
|
+
[{"name":"run-webpack","duration":89649911,"timestamp":688510,"id":14,"parentId":1,"tags":{},"startTime":1790570150388,"traceId":"a6840ff45438012c"},{"name":"run-typescript","duration":13356553,"timestamp":90667751,"id":10641,"parentId":1,"tags":{},"startTime":1790570240367,"traceId":"a6840ff45438012c"},{"name":"static-check","duration":3579393,"timestamp":104233152,"id":10644,"parentId":1,"tags":{},"startTime":1790570253932,"traceId":"a6840ff45438012c"},{"name":"static-generation","duration":9780588,"timestamp":107903437,"id":10790,"parentId":1,"tags":{},"startTime":1790570257602,"traceId":"a6840ff45438012c"},{"name":"collect-build-traces","duration":17435274,"timestamp":107871717,"id":10787,"parentId":1,"tags":{},"startTime":1790570257571,"traceId":"a6840ff45438012c"},{"name":"telemetry-flush","duration":55,"timestamp":125310779,"id":10799,"parentId":1,"tags":{},"startTime":1790570275009,"traceId":"a6840ff45438012c"},{"name":"next-build","duration":124705406,"timestamp":605447,"id":1,"tags":{"buildMode":"default","version":"16.2.12","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1790570150305,"traceId":"a6840ff45438012c"}]
|
|
@@ -9,7 +9,7 @@ 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.5.
|
|
12
|
+
version: '0.5.6',
|
|
13
13
|
distribution: 'cuelo',
|
|
14
14
|
coreVersion: '18.3.5',
|
|
15
15
|
};
|
|
@@ -239,8 +239,15 @@ function textContent(content: unknown): string {
|
|
|
239
239
|
: "";
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
// Windows 기본 curl.exe 는 `-o /dev/null` 을 파일 경로로 받아 쓰지 못하고 응답을 받은 뒤 exit 23 으로 끝난다.
|
|
243
|
+
const WINDOWS_CURL_DEVNULL = /\bcurl(?:\.exe)?\b[^\n;|&]*\s-o\s*\/dev\/null\b/u;
|
|
244
|
+
|
|
245
|
+
function classifyError(content: unknown, input?: unknown): string {
|
|
243
246
|
const text = textContent(content);
|
|
247
|
+
const command = input && typeof input === "object" && "command" in input ? input.command : undefined;
|
|
248
|
+
if (/exited with code 23\b/u.test(text) && typeof command === "string" && WINDOWS_CURL_DEVNULL.test(command)) {
|
|
249
|
+
return "windows-shell";
|
|
250
|
+
}
|
|
244
251
|
for (const [pattern, category] of ERROR_CATEGORY_PATTERNS) {
|
|
245
252
|
if (pattern.test(text)) return category;
|
|
246
253
|
}
|
|
@@ -1468,7 +1475,7 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1468
1475
|
const inputChanged = serializeInput(event.input) !== failure.inputSerialized;
|
|
1469
1476
|
const observation = failure.observation;
|
|
1470
1477
|
const nextAction = failure.category === "windows-shell"
|
|
1471
|
-
? "같은 명령을 그대로 재시도하지 않는다. PowerShell 로직은 write로 .ps1 파일을 만들고 -File <슬래시 절대경로>로 실행한다. .\\x·역슬래시 경로 대신 슬래시 절대경로를 쓴다. cmd /c rd·del 대신 rm 또는 .ps1의 Remove-Item -LiteralPath를 쓴다. `$'\\r'` 구문 오류는 PATH 첫 bash(WSL)가 CRLF .sh를 읽은 것이니 Git Bash(\"C:/Program Files/Git/bin/bash.exe\" <스크립트>)로 실행한다."
|
|
1478
|
+
? "같은 명령을 그대로 재시도하지 않는다. PowerShell 로직은 write로 .ps1 파일을 만들고 -File <슬래시 절대경로>로 실행한다. .\\x·역슬래시 경로 대신 슬래시 절대경로를 쓴다. cmd /c rd·del 대신 rm 또는 .ps1의 Remove-Item -LiteralPath를 쓴다. `$'\\r'` 구문 오류는 PATH 첫 bash(WSL)가 CRLF .sh를 읽은 것이니 Git Bash(\"C:/Program Files/Git/bin/bash.exe\" <스크립트>)로 실행한다. `curl -o /dev/null`의 exit 23은 Windows curl.exe가 /dev/null에 쓰지 못한 것이라 응답은 이미 받았다. `-o NUL`이나 셸 리디렉션 `>/dev/null`로 바꾼다."
|
|
1472
1479
|
: observation.cancelled && !observation.deterministicExitObserved
|
|
1473
1480
|
? "취소 근거 없음: 실행 결과 회수 또는 다음 한 변수 확인. 산출물·로그·프로세스 생존 중 하나를 새로 확인한 뒤 결정한다. stdout 침묵·낮은 CPU·elapsed만으로 stall을 확정하지 않는다."
|
|
1474
1481
|
: RETRY_CATEGORY_NEXT_ACTION[failure.category]
|
|
@@ -1698,7 +1705,7 @@ export function createJevRuntime(deps: JevRuntimeDeps = {}) {
|
|
|
1698
1705
|
if (!EXPLORATION_TOOLS[event.toolName]) {
|
|
1699
1706
|
pendingFailures.set(event.toolName, {
|
|
1700
1707
|
inputSerialized: serializeInput(event.input),
|
|
1701
|
-
category: classifyError(event.content),
|
|
1708
|
+
category: classifyError(event.content, event.input),
|
|
1702
1709
|
interveningTools: [],
|
|
1703
1710
|
observation: readFailureObservation(event.details, event.content),
|
|
1704
1711
|
});
|
|
@@ -313,6 +313,10 @@ export function createTurnEndGuard(
|
|
|
313
313
|
});
|
|
314
314
|
pi.on("agent_end", async (event, ctx) => {
|
|
315
315
|
if (event.willContinue || nudgedThisInput || pendingJudge) return;
|
|
316
|
+
// 사용자 정지·업데이트/재시작 interrupt 가 끊은 턴이다. 여기서 이어 가게 하면 drain 뒤 옛 서버에서 도구가 다시 돈다.
|
|
317
|
+
const lastAssistant = [...event.messages].reverse().find((message) => (message as Message)?.role === "assistant") as
|
|
318
|
+
(Message & { stopReason?: string }) | undefined;
|
|
319
|
+
if (lastAssistant?.stopReason === "aborted") return;
|
|
316
320
|
const hasTodo = todos.some((item) => item.status === "pending" || item.status === "in_progress");
|
|
317
321
|
const last = lastAssistantText(event.messages);
|
|
318
322
|
const soloText = activeInput && !hasTodo && last && !last.hasToolCall && !classifiedSoloThisInput
|
|
@@ -4915,6 +4915,62 @@ function operationFromNative(op: string): Operation | undefined {
|
|
|
4915
4915
|
anchor: "\t\treturn `- ${content}${source}${date}`;\n",
|
|
4916
4916
|
patched: "\t\t// HANSE: recall line carries memory id\n\t\tconst memoryId = result.id ? ` (id: ${result.id})` : \"\";\n\t\treturn `- ${content}${source}${date}${memoryId}`;\n",
|
|
4917
4917
|
},
|
|
4918
|
+
{
|
|
4919
|
+
file: "src/tools/learn.ts",
|
|
4920
|
+
marker: 'import { redactMemorySecrets } from "../memory-backend/redact";',
|
|
4921
|
+
anchor: 'import { localBackend } from "../memory-backend/local-backend";',
|
|
4922
|
+
patched: 'import { localBackend } from "../memory-backend/local-backend";\nimport { redactMemorySecrets } from "../memory-backend/redact";\nimport type { MnemopiSessionState } from "../mnemopi/state";',
|
|
4923
|
+
},
|
|
4924
|
+
{
|
|
4925
|
+
file: "src/tools/learn.ts",
|
|
4926
|
+
marker: '"topic?": type("string").describe("stable topic key',
|
|
4927
|
+
anchor: '\t"context?": type("string").describe("optional source context for the lesson"),',
|
|
4928
|
+
patched: '\t"context?": type("string").describe("optional source context for the lesson"),\n\t"topic?": type("string").describe("stable topic key; later lessons with this key replace the prior project lesson"),',
|
|
4929
|
+
},
|
|
4930
|
+
{
|
|
4931
|
+
file: "src/tools/learn.ts",
|
|
4932
|
+
marker: '"topic?": type("string").describe("stable topic key; later lessons with this key replace the prior project lesson"),\n\t"scope?"',
|
|
4933
|
+
anchor: '\t"scope?": type("\'project\' | \'global\'").describe(',
|
|
4934
|
+
patched: '\t"topic?": type("string").describe("stable topic key; later lessons with this key replace the prior project lesson"),\n\t"scope?": type("\'project\' | \'global\'").describe(',
|
|
4935
|
+
},
|
|
4936
|
+
{
|
|
4937
|
+
file: "src/tools/learn.ts",
|
|
4938
|
+
marker: "// HANSE: topic-key learn upsert",
|
|
4939
|
+
anchor: "export class LearnTool implements AgentTool<LearnSchema> {",
|
|
4940
|
+
patched: `// HANSE: topic-key learn upsert
|
|
4941
|
+
function upsertLearnTopic(
|
|
4942
|
+
state: MnemopiSessionState,
|
|
4943
|
+
params: LearnParams,
|
|
4944
|
+
target: ReturnType<MnemopiSessionState["getScopedRetainTarget"]>,
|
|
4945
|
+
): { id: string; revision: number } {
|
|
4946
|
+
const topic = params.topic!.normalize("NFKC").trim().toLowerCase();
|
|
4947
|
+
if (!topic) throw new Error("Learn topic must not be blank.");
|
|
4948
|
+
if (redactMemorySecrets(topic) !== topic) throw new Error("Learn topic contains a credential.");
|
|
4949
|
+
const db = target.memory.conn;
|
|
4950
|
+
const existing = db.query(
|
|
4951
|
+
"SELECT id, metadata_json FROM working_memory WHERE json_extract(metadata_json, '$.topic_key') = ? ORDER BY timestamp DESC, id DESC LIMIT 1",
|
|
4952
|
+
).get(topic) as { id: string; metadata_json: string } | null;
|
|
4953
|
+
const revision = existing ? (Number(JSON.parse(existing.metadata_json).revision) || 1) + 1 : 1;
|
|
4954
|
+
if (existing) return db.transaction(() => {
|
|
4955
|
+
const content = redactMemorySecrets(params.memory);
|
|
4956
|
+
db.query("UPDATE working_memory SET content = ?, embed_text = NULL, timestamp = ?, metadata_json = ? WHERE id = ?").run(
|
|
4957
|
+
content, new Date().toISOString(),
|
|
4958
|
+
JSON.stringify({ ...JSON.parse(existing.metadata_json), context: params.context == null ? null : redactMemorySecrets(params.context), topic_key: topic, revision }),
|
|
4959
|
+
existing.id,
|
|
4960
|
+
);
|
|
4961
|
+
db.query("DELETE FROM memory_embeddings WHERE memory_id = ?").run(existing.id);
|
|
4962
|
+
return { id: existing.id, revision };
|
|
4963
|
+
})();
|
|
4964
|
+
const id = state.rememberScoped(params.memory, {
|
|
4965
|
+
source: "coding-agent-learn", importance: 0.8,
|
|
4966
|
+
metadata: { session_id: state.sessionId, cwd: state.session.sessionManager.getCwd(), context: params.context ?? null, tool: "learn", topic_key: topic, revision },
|
|
4967
|
+
scope: "bank", extract: true, extractEntities: true, veracity: "tool", memoryType: "fact",
|
|
4968
|
+
}, target);
|
|
4969
|
+
return { id, revision };
|
|
4970
|
+
}
|
|
4971
|
+
|
|
4972
|
+
export class LearnTool implements AgentTool<LearnSchema> {`,
|
|
4973
|
+
},
|
|
4918
4974
|
{
|
|
4919
4975
|
// learn 은 rememberScoped 가 돌려준 기억 id 를 버리고 "Lesson stored." 만 알렸다. 교훈을 뒤에서
|
|
4920
4976
|
// 가리킬 식별자가 없으면 적용·결과를 연결할 수 없다. mnemopi 경로에서만 id 를 싣는다.
|
|
@@ -4923,13 +4979,15 @@ function operationFromNative(op: string): Operation | undefined {
|
|
|
4923
4979
|
file: "src/tools/learn.ts",
|
|
4924
4980
|
marker: "// HANSE: learn reports memory id",
|
|
4925
4981
|
anchor: "\t\t\ttry {\n\t\t\t\tstate.rememberScoped(\n",
|
|
4926
|
-
|
|
4982
|
+
legacyPatched: "\t\t\ttry {\n\t\t\t\t// HANSE: learn reports memory id\n\t\t\t\tconst memoryId = state.rememberScoped(\n",
|
|
4983
|
+
patched: "\t\t\ttry {\n\t\t\t\t// HANSE: learn reports memory id\n\t\t\t\tconst topicResult = params.topic ? upsertLearnTopic(state, params, target ?? state.getScopedRetainTarget()) : undefined;\n\t\t\t\tconst memoryId = topicResult?.id ?? state.rememberScoped(\n",
|
|
4927
4984
|
},
|
|
4928
4985
|
{
|
|
4929
4986
|
file: "src/tools/learn.ts",
|
|
4930
|
-
marker: "memoryMessage = `Lesson stored (id: ${memoryId}
|
|
4987
|
+
marker: "memoryMessage = `Lesson stored (id: ${memoryId}${topicResult ?",
|
|
4931
4988
|
anchor: "\t\t\t\t\ttarget,\n\t\t\t\t);\n\t\t\t} catch (error) {\n",
|
|
4932
|
-
|
|
4989
|
+
legacyPatched: "\t\t\t\t\ttarget,\n\t\t\t\t);\n\t\t\t\tif (memoryId) memoryMessage = `Lesson stored (id: ${memoryId})`;\n\t\t\t} catch (error) {\n",
|
|
4990
|
+
patched: "\t\t\t\t\ttarget,\n\t\t\t\t);\n\t\t\t\tif (memoryId) memoryMessage = `Lesson stored (id: ${memoryId}${topicResult ? `, revision: ${topicResult.revision}` : \"\"})`;\n\t\t\t} catch (error) {\n",
|
|
4933
4991
|
},
|
|
4934
4992
|
{
|
|
4935
4993
|
// 2026-09-27: 자동 주입 <memories> 는 세션 파일에 남지 않아, Main 단독 세션에서 어떤 교훈이 전달됐는지
|
|
@@ -5173,12 +5231,64 @@ function raiseToAutoThinkingFloor(model: Model, level: Effort | undefined, setti
|
|
|
5173
5231
|
this.#thinkingLevelCeiling,
|
|
5174
5232
|
);`,
|
|
5175
5233
|
},
|
|
5234
|
+
{
|
|
5235
|
+
// 2026-09-28 도구 오류 집계: `computer.window(65822)`처럼 숫자 id를 넘기면 필터 객체로 해석돼
|
|
5236
|
+
// 조건이 하나도 걸리지 않아 모든 창이 일치했고("multiple windows match 65822"), `title: /정규식/`은
|
|
5237
|
+
// 안내 없이 TypeError로 죽었다. 필터 값은 문자열만 받고, 아니면 무엇이 틀렸는지 말하는 ToolError를 낸다.
|
|
5238
|
+
file: "src/tools/computer/worker.ts",
|
|
5239
|
+
marker: "function assertWindowFilter(filter: unknown)",
|
|
5240
|
+
anchor: `function matchesFilter(window: DesktopWindow, filter?: WindowFilter): boolean {
|
|
5241
|
+
if (!filter) return true;`,
|
|
5242
|
+
patched: `/** A filter is a plain \`{ id?, app?, title? }\` of strings; anything else used to match every window. */
|
|
5243
|
+
function assertWindowFilter(filter: unknown): asserts filter is WindowFilter | undefined {
|
|
5244
|
+
if (filter === undefined) return;
|
|
5245
|
+
if (filter === null || typeof filter !== "object" || Array.isArray(filter)) {
|
|
5246
|
+
throw new ToolError(\`window filter must be an object like { app?, title?, id? }; got \${filter === null ? "null" : typeof filter}\`);
|
|
5247
|
+
}
|
|
5248
|
+
for (const key of ["id", "app", "title"] as const) {
|
|
5249
|
+
const value = (filter as Record<string, unknown>)[key];
|
|
5250
|
+
if (value !== undefined && typeof value !== "string") {
|
|
5251
|
+
const got = value instanceof RegExp ? \`RegExp \${value}\` : typeof value;
|
|
5252
|
+
throw new ToolError(\`window filter \${key} must be a string (\${key === "id" ? "exact window id" : "case-insensitive substring"}); got \${got}\`);
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
}
|
|
5256
|
+
|
|
5257
|
+
function matchesFilter(window: DesktopWindow, filter?: WindowFilter): boolean {
|
|
5258
|
+
if (!filter) return true;`,
|
|
5259
|
+
},
|
|
5260
|
+
{
|
|
5261
|
+
// 숫자 id는 창 id(숫자 문자열)와 뜻이 하나뿐이라 문자열로 바꿔 id로 찾는다. 그 밖의 값은 위에서 거절한다.
|
|
5262
|
+
file: "src/tools/computer/worker.ts",
|
|
5263
|
+
marker: "const byId = typeof selector === \"number\"",
|
|
5264
|
+
anchor: ` const windows = await nativeCall(signal, () => session.listWindows());
|
|
5265
|
+
const matches =
|
|
5266
|
+
typeof selector === "string"
|
|
5267
|
+
? windows.filter(window => window.id === selector)
|
|
5268
|
+
: windows.filter(window => matchesFilter(window, selector));`,
|
|
5269
|
+
patched: ` const byId = typeof selector === "number" && Number.isSafeInteger(selector) ? String(selector) : selector;
|
|
5270
|
+
if (typeof byId !== "string") assertWindowFilter(byId);
|
|
5271
|
+
const windows = await nativeCall(signal, () => session.listWindows());
|
|
5272
|
+
const matches =
|
|
5273
|
+
typeof byId === "string"
|
|
5274
|
+
? windows.filter(window => window.id === byId)
|
|
5275
|
+
: windows.filter(window => matchesFilter(window, byId));`,
|
|
5276
|
+
},
|
|
5277
|
+
{
|
|
5278
|
+
file: "src/tools/computer/worker.ts",
|
|
5279
|
+
marker: "windows: async (filter?: WindowFilter): Promise<DesktopWindow[]> => {\n\t\t\t\tassertWindowFilter(filter);",
|
|
5280
|
+
anchor: ` windows: async (filter?: WindowFilter): Promise<DesktopWindow[]> => {
|
|
5281
|
+
const { signal } = getContext();`,
|
|
5282
|
+
patched: ` windows: async (filter?: WindowFilter): Promise<DesktopWindow[]> => {
|
|
5283
|
+
assertWindowFilter(filter);
|
|
5284
|
+
const { signal } = getContext();`,
|
|
5285
|
+
},
|
|
5176
5286
|
];
|
|
5177
5287
|
// EDITS 문자열의 줄 끝을 LF로 통일한다. 이 파일의 작업 사본이 CRLF여도 core 파일(LF)과
|
|
5178
5288
|
// 비교·치환이 어긋나지 않는다. core 파일 자체의 줄 끝은 건드리지 않는다.
|
|
5179
5289
|
for (const entry of EDITS) {
|
|
5180
5290
|
for (const candidate of [entry, ...(entry.alternates ?? [])]) {
|
|
5181
|
-
for (const key of ["anchor", "marker", "patched"]) {
|
|
5291
|
+
for (const key of ["anchor", "marker", "patched", "legacyPatched"]) {
|
|
5182
5292
|
if (typeof candidate[key] === "string") candidate[key] = candidate[key].replaceAll("\r\n", "\n");
|
|
5183
5293
|
}
|
|
5184
5294
|
}
|
|
@@ -5200,6 +5310,7 @@ function resolveEdit(entry, target) {
|
|
|
5200
5310
|
const live = present
|
|
5201
5311
|
.map(candidate => {
|
|
5202
5312
|
const text = readFileSync(join(target, candidate.file), "utf8");
|
|
5313
|
+
if (candidate.legacyPatched && text.includes(candidate.legacyPatched)) return { ...candidate, path: join(target, candidate.file), text, status: "legacy" };
|
|
5203
5314
|
if (text.includes(candidate.marker)) return { ...candidate, path: join(target, candidate.file), text, status: "applied" };
|
|
5204
5315
|
if (text.includes(candidate.anchor)) return { ...candidate, path: join(target, candidate.file), text, status: "appliable" };
|
|
5205
5316
|
return undefined;
|
|
@@ -5258,7 +5369,7 @@ function main() {
|
|
|
5258
5369
|
// 적용의 역연산이므로 역순으로 되돌린다. 뒤 항목이 앞 항목의 patched 안쪽을 앵커로
|
|
5259
5370
|
// 쓰는 중첩 편집(completion-bridge.ts)은 정순이면 앞 항목의 patched 가 이미 달라져 있다.
|
|
5260
5371
|
for (const s of [...state].reverse()) {
|
|
5261
|
-
if (s.status !== "applied") {
|
|
5372
|
+
if (s.status !== "applied" && s.status !== "legacy") {
|
|
5262
5373
|
console.log(` 건너뜀 ${s.file} (적용 상태가 아니다)`);
|
|
5263
5374
|
continue;
|
|
5264
5375
|
}
|
|
@@ -5271,6 +5382,11 @@ function main() {
|
|
|
5271
5382
|
console.log(` 복원 ${s.file}`);
|
|
5272
5383
|
continue;
|
|
5273
5384
|
}
|
|
5385
|
+
if (s.legacyPatched && current.includes(s.legacyPatched)) {
|
|
5386
|
+
writeFileSync(s.path, current.replace(s.legacyPatched, s.anchor), "utf8");
|
|
5387
|
+
console.log(` 복원 ${s.file} (옛 패치)`);
|
|
5388
|
+
continue;
|
|
5389
|
+
}
|
|
5274
5390
|
const bak = join(BACKUP, s.file);
|
|
5275
5391
|
if (existsSync(bak) && !readFileSync(bak, "utf8").includes(s.marker)) {
|
|
5276
5392
|
copyFileSync(bak, s.path);
|
|
@@ -5306,7 +5422,9 @@ function main() {
|
|
|
5306
5422
|
// 위와 같은 이유로 스냅샷이 아니라 현재 내용에 얹는다. 앵커 상실 검사는 위에서
|
|
5307
5423
|
// 스냅샷 전체를 보고 이미 끝났으므로 preflight 의 원자성은 그대로다.
|
|
5308
5424
|
const current = readFileSync(s.path, "utf8");
|
|
5309
|
-
|
|
5425
|
+
const from = s.status === "legacy" ? s.legacyPatched : s.anchor;
|
|
5426
|
+
if (!current.includes(from)) throw new Error(`적용 중 앵커가 사라졌다: ${s.file}`);
|
|
5427
|
+
writeFileSync(s.path, current.replace(from, s.patched), "utf8");
|
|
5310
5428
|
console.log(` 적용 ${s.file}`);
|
|
5311
5429
|
}
|
|
5312
5430
|
console.log("적용 완료. CUELO를 재시작해야 반영된다.");
|
package/install.mjs
CHANGED
|
@@ -155,9 +155,10 @@ export function copyHarness(sourceDir, agentDir, entries) {
|
|
|
155
155
|
/**
|
|
156
156
|
* What a new profile's `config.yml` starts with, so the public harness runs the way it is used:
|
|
157
157
|
* local learning and project-scoped memory, the harness's Maker routing (isolated task runs,
|
|
158
|
-
* its roles instead of the bundled agents) and request budget,
|
|
159
|
-
*
|
|
160
|
-
* omp defaults are
|
|
158
|
+
* its roles instead of the bundled agents) and request budget, long `eval` cells that yield
|
|
159
|
+
* to steering (`eval.autoBackground`, off in omp), and nothing that spends provider requests
|
|
160
|
+
* on its own (`autoContinue`, `autoRetain` stay off). Values equal to the omp defaults are
|
|
161
|
+
* left out.
|
|
161
162
|
*/
|
|
162
163
|
export const PROFILE_DEFAULTS = {
|
|
163
164
|
defaultThinkingLevel: "auto",
|
|
@@ -172,6 +173,7 @@ export const PROFILE_DEFAULTS = {
|
|
|
172
173
|
isolation: { enabled: true },
|
|
173
174
|
disabledAgents: ["scout", "sonic", "task", "reviewer", "security-reviewer"],
|
|
174
175
|
},
|
|
176
|
+
eval: { autoBackground: { enabled: true } },
|
|
175
177
|
};
|
|
176
178
|
|
|
177
179
|
/**
|
package/package.json
CHANGED
|
Binary file
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="512" height="512">
|
|
2
|
+
<!-- CUELO 앱 아이콘 원본. icon-192/512·apple-touch-icon·favicon.ico는 이 파일에서 뽑는다. -->
|
|
3
|
+
<rect width="100" height="100" rx="22" fill="#16171b"/>
|
|
4
|
+
<g transform="translate(15 15) scale(0.7)">
|
|
5
|
+
<path d="M77.9 30.5 A34 34 0 0 0 16 50 A26 26 0 0 0 68 50" fill="none" stroke="#eceef2" stroke-width="10" stroke-linecap="round"/>
|
|
6
|
+
<circle cx="42" cy="50" r="8.5" fill="#f5a524"/>
|
|
7
|
+
</g>
|
|
8
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
package/public/sw.js
CHANGED
|
@@ -3,8 +3,9 @@ const CACHE_PREFIX = "pi-web";
|
|
|
3
3
|
// a precached shell file changes without a version change, so the activate
|
|
4
4
|
// handler drops the previous cache instead of serving the stale shell. The
|
|
5
5
|
// SEED surface cutover rewrote /offline.html and /manifest.webmanifest; r3
|
|
6
|
-
// added the offline page's automatic return to the original address
|
|
7
|
-
|
|
6
|
+
// added the offline page's automatic return to the original address; r4
|
|
7
|
+
// replaced the precached app icons with the spiral-lamp logo.
|
|
8
|
+
const SHELL_REVISION = "4";
|
|
8
9
|
const CACHE_VERSION = `${new URL(self.location.href).searchParams.get("v") || "dev"}-r${SHELL_REVISION}`;
|
|
9
10
|
const STATIC_CACHE = `${CACHE_PREFIX}-static-${CACHE_VERSION}`;
|
|
10
11
|
const OFFLINE_URL = "/offline.html";
|
|
File without changes
|
|
File without changes
|