@cortexkit/opencode-magic-context 0.35.0 → 0.36.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/README.md +9 -5
- package/dist/agents/hidden-agent-registrations.d.ts +10 -2
- package/dist/agents/hidden-agent-registrations.d.ts.map +1 -1
- package/dist/agents/permissions.d.ts +21 -3
- package/dist/agents/permissions.d.ts.map +1 -1
- package/dist/{announcement-gms2nhya.js → announcement-6c1g4es4.js} +2 -2
- package/dist/config/schema/agent-overrides.d.ts +1 -1
- package/dist/config/schema/magic-context.d.ts +19 -9
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-p2pmhvn7.js → conflict-warning-hook-dw9fs934.js} +4 -4
- package/dist/{derive-budgets-9crp0cvd.js → derive-budgets-88mxk2w1.js} +3 -3
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +2 -0
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -0
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/condition-compiler.d.ts +37 -0
- package/dist/features/magic-context/smart-notes/condition-compiler.d.ts.map +1 -0
- package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
- package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/storage.d.ts +3 -3
- package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-notes.d.ts +13 -0
- package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-prompt.d.ts +6 -6
- package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +3 -0
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +15 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-state-sync.d.ts +6 -0
- package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-transport.d.ts +9 -0
- package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
- package/dist/hooks/magic-context/raw-fallback-context-limit.d.ts +10 -0
- package/dist/hooks/magic-context/raw-fallback-context-limit.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +7 -2
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/{index-8aaadh98.js → index-37rt2bka.js} +2 -2
- package/dist/{index-4anesz49.js → index-3nfgbsp4.js} +103 -56
- package/dist/{index-fcyvznch.js → index-3tnkymva.js} +47 -4
- package/dist/{index-k1esqfwk.js → index-f1tnb3vm.js} +1 -1
- package/dist/{index-kvrcg31b.js → index-mmrhhk9a.js} +8 -1
- package/dist/{index-cn960ffd.js → index-nsx2n9eg.js} +3 -3
- package/dist/{index-dmr999a2.js → index-qf20mv7e.js} +1 -1
- package/dist/{index-73xz0247.js → index-tsgs7td8.js} +1 -1
- package/dist/{index-ry8rh8cv.js → index-wgvxkqpx.js} +5 -4
- package/dist/index-z8v31d85.js +2892 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +822 -119
- package/dist/plugin/dream-timer.d.ts +1 -0
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +5 -5
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-zc915ceq.js → recomp-orchestrator-7wbbvf87.js} +7 -7
- package/dist/{safe-notification-target-q9jk5n44.js → safe-notification-target-c11fdda2.js} +3 -3
- package/dist/{send-session-notification-6njqewzk.js → send-session-notification-bgtf4853.js} +4 -4
- package/dist/shared/data-path.d.ts +27 -0
- package/dist/shared/data-path.d.ts.map +1 -1
- package/dist/shared/harness-provider-map.d.ts +23 -20
- package/dist/shared/harness-provider-map.d.ts.map +1 -1
- package/dist/shared/prompt-surface-a1-golden.d.ts +28 -0
- package/dist/shared/prompt-surface-a1-golden.d.ts.map +1 -0
- package/dist/shared/prompt-surface-runtime.d.ts +15 -2
- package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +13 -0
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/{storage-meta-session-53cjs6mr.js → storage-meta-session-kh5egr11.js} +4 -4
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/agents/hidden-agent-registrations.ts +49 -1
- package/src/agents/permissions.ts +91 -3
- package/src/config/compaction-accessor-guard.test.ts +9 -4
- package/src/config/schema/magic-context.test.ts +2 -0
- package/src/config/schema/magic-context.ts +15 -0
- package/src/shared/data-path.test.ts +65 -9
- package/src/shared/data-path.ts +66 -1
- package/src/shared/harness-provider-map.test.ts +42 -1
- package/src/shared/harness-provider-map.ts +48 -26
- package/src/shared/prompt-surface-a1-golden.ts +41 -0
- package/src/shared/prompt-surface-runtime.ts +13 -5
- package/src/shared/sqlite.test.ts +32 -0
- package/src/shared/sqlite.ts +85 -9
- package/dist/index-h8mk7vpa.js +0 -135318
package/dist/index.js
CHANGED
|
@@ -25,6 +25,14 @@ import {
|
|
|
25
25
|
GLOBAL_USER_PROFILE_PROJECT_PATH,
|
|
26
26
|
HISTORIAN_EDITOR_SYSTEM_PROMPT,
|
|
27
27
|
LATEST_SUPPORTED_VERSION,
|
|
28
|
+
LKG_SNAPSHOT_ARRAY,
|
|
29
|
+
LKG_SNAPSHOT_BOOLEAN,
|
|
30
|
+
LKG_SNAPSHOT_KEY,
|
|
31
|
+
LKG_SNAPSHOT_NULL,
|
|
32
|
+
LKG_SNAPSHOT_NUMBER,
|
|
33
|
+
LKG_SNAPSHOT_OBJECT,
|
|
34
|
+
LKG_SNAPSHOT_STRING,
|
|
35
|
+
LKG_SNAPSHOT_UNDEFINED,
|
|
28
36
|
MARKER_SUMMARY_TEXT,
|
|
29
37
|
MAX_EXECUTE_THRESHOLD,
|
|
30
38
|
MagicContextConfigSchema,
|
|
@@ -230,6 +238,7 @@ import {
|
|
|
230
238
|
isPidAlive,
|
|
231
239
|
isProviderOverflowReconfirmed,
|
|
232
240
|
lkgContentDigest,
|
|
241
|
+
lkgContentDigestFromFields,
|
|
233
242
|
loadCompartmentChunkEmbeddingsForSearch,
|
|
234
243
|
loadPersistedUsage,
|
|
235
244
|
loadProjectCommitEmbeddings,
|
|
@@ -382,7 +391,7 @@ import {
|
|
|
382
391
|
upsertCommits,
|
|
383
392
|
verificationFileExists,
|
|
384
393
|
withContentLanguageDirective
|
|
385
|
-
} from "./index-
|
|
394
|
+
} from "./index-3nfgbsp4.js";
|
|
386
395
|
import {
|
|
387
396
|
deriveHistorianChunkTokens,
|
|
388
397
|
deriveTriggerBudget,
|
|
@@ -394,7 +403,7 @@ import {
|
|
|
394
403
|
setOutputReserveConfig,
|
|
395
404
|
setStoragePrivatePermissionEnforcement,
|
|
396
405
|
shouldEnforcePrivateStoragePermissions
|
|
397
|
-
} from "./index-
|
|
406
|
+
} from "./index-wgvxkqpx.js";
|
|
398
407
|
import {
|
|
399
408
|
modelBodyField,
|
|
400
409
|
resolveFallbackChain
|
|
@@ -406,7 +415,7 @@ import {
|
|
|
406
415
|
getErrorMessage,
|
|
407
416
|
sendIgnoredMessage,
|
|
408
417
|
sendUserPrompt
|
|
409
|
-
} from "./index-
|
|
418
|
+
} from "./index-nsx2n9eg.js";
|
|
410
419
|
import {
|
|
411
420
|
ToolMutationBatch,
|
|
412
421
|
advanceToolReclaimWatermark,
|
|
@@ -463,7 +472,7 @@ import {
|
|
|
463
472
|
textMentionsRecentCommit,
|
|
464
473
|
updateSessionMeta,
|
|
465
474
|
withRawSessionMessageCache
|
|
466
|
-
} from "./index-
|
|
475
|
+
} from "./index-z8v31d85.js";
|
|
467
476
|
import {
|
|
468
477
|
Database,
|
|
469
478
|
closeQuietly,
|
|
@@ -472,12 +481,12 @@ import {
|
|
|
472
481
|
isMidTurn,
|
|
473
482
|
openCodeDbExists,
|
|
474
483
|
withReadOnlySessionDb
|
|
475
|
-
} from "./index-
|
|
484
|
+
} from "./index-3tnkymva.js";
|
|
476
485
|
import {
|
|
477
486
|
cleanupConflictWarnings,
|
|
478
487
|
detectConflicts,
|
|
479
488
|
sendConflictWarning
|
|
480
|
-
} from "./index-
|
|
489
|
+
} from "./index-37rt2bka.js";
|
|
481
490
|
import {
|
|
482
491
|
detectConfigFile,
|
|
483
492
|
parseJsonc,
|
|
@@ -491,7 +500,7 @@ import {
|
|
|
491
500
|
isValidSemver,
|
|
492
501
|
markAnnouncementSeen,
|
|
493
502
|
shouldShowAnnouncement
|
|
494
|
-
} from "./index-
|
|
503
|
+
} from "./index-qf20mv7e.js";
|
|
495
504
|
import {
|
|
496
505
|
acknowledgeNotifications,
|
|
497
506
|
drainNotifications,
|
|
@@ -499,17 +508,17 @@ import {
|
|
|
499
508
|
pushNotification,
|
|
500
509
|
registerNotificationSink
|
|
501
510
|
} from "./index-d62ypazr.js";
|
|
502
|
-
import"./index-
|
|
511
|
+
import"./index-tsgs7td8.js";
|
|
503
512
|
import {
|
|
504
513
|
log,
|
|
505
514
|
sessionLog
|
|
506
|
-
} from "./index-
|
|
515
|
+
} from "./index-f1tnb3vm.js";
|
|
507
516
|
import {
|
|
508
517
|
getDataDir,
|
|
509
518
|
getHarness,
|
|
510
519
|
getMagicContextStorageDir,
|
|
511
520
|
getOpenCodeStorageDir
|
|
512
|
-
} from "./index-
|
|
521
|
+
} from "./index-mmrhhk9a.js";
|
|
513
522
|
import {
|
|
514
523
|
resolvePromptContext
|
|
515
524
|
} from "./index-szf8w1p5.js";
|
|
@@ -8370,6 +8379,49 @@ function buildAllowOnlyPermission(allowedTools, agentLabel) {
|
|
|
8370
8379
|
}
|
|
8371
8380
|
return permission;
|
|
8372
8381
|
}
|
|
8382
|
+
function isPermissionAction(value) {
|
|
8383
|
+
return value === "ask" || value === "allow" || value === "deny";
|
|
8384
|
+
}
|
|
8385
|
+
function isPermissionMap(value) {
|
|
8386
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
8387
|
+
}
|
|
8388
|
+
function denyTaskRoutingToAgents(permission, internalAgentIds) {
|
|
8389
|
+
const configured = isPermissionAction(permission) ? { "*": permission } : isPermissionMap(permission) ? permission : {};
|
|
8390
|
+
const { task, ...otherPermissions } = configured;
|
|
8391
|
+
const configuredTask = isPermissionAction(task) ? { "*": task } : isPermissionMap(task) ? task : {};
|
|
8392
|
+
const internalAgentIdSet = new Set(internalAgentIds);
|
|
8393
|
+
const retainedTask = Object.fromEntries(Object.entries(configuredTask).filter(([agentId]) => !internalAgentIdSet.has(agentId)));
|
|
8394
|
+
return {
|
|
8395
|
+
...otherPermissions,
|
|
8396
|
+
task: {
|
|
8397
|
+
...retainedTask,
|
|
8398
|
+
...Object.fromEntries(internalAgentIds.map((agentId) => [agentId, "deny"]))
|
|
8399
|
+
}
|
|
8400
|
+
};
|
|
8401
|
+
}
|
|
8402
|
+
var BUILTIN_TASK_CALLER_IDS = ["build", "plan"];
|
|
8403
|
+
function isTaskRoutingCaller(agentId, config) {
|
|
8404
|
+
const mode = config.mode;
|
|
8405
|
+
if (mode === "primary")
|
|
8406
|
+
return true;
|
|
8407
|
+
if (mode === "subagent" || mode === "all")
|
|
8408
|
+
return false;
|
|
8409
|
+
return agentId === "build" || agentId === "plan";
|
|
8410
|
+
}
|
|
8411
|
+
function denyTaskRoutingToCallerAgents(agentConfigs, internalAgentIds) {
|
|
8412
|
+
const result = { ...agentConfigs };
|
|
8413
|
+
const candidateIds = new Set([...BUILTIN_TASK_CALLER_IDS, ...Object.keys(agentConfigs)]);
|
|
8414
|
+
for (const agentId of candidateIds) {
|
|
8415
|
+
const agentConfig = agentConfigs[agentId] ?? {};
|
|
8416
|
+
if (!isTaskRoutingCaller(agentId, agentConfig))
|
|
8417
|
+
continue;
|
|
8418
|
+
result[agentId] = {
|
|
8419
|
+
...agentConfig,
|
|
8420
|
+
permission: denyTaskRoutingToAgents(agentConfig.permission, internalAgentIds)
|
|
8421
|
+
};
|
|
8422
|
+
}
|
|
8423
|
+
return result;
|
|
8424
|
+
}
|
|
8373
8425
|
function applyDisallowedTools(defaults, disallowed) {
|
|
8374
8426
|
if (disallowed.includes("*"))
|
|
8375
8427
|
return [];
|
|
@@ -8380,11 +8432,15 @@ function applyDisallowedTools(defaults, disallowed) {
|
|
|
8380
8432
|
function clampHiddenAgentStepLimit(value, cap) {
|
|
8381
8433
|
return typeof value === "number" && Number.isFinite(value) ? Math.min(value, cap) : cap;
|
|
8382
8434
|
}
|
|
8435
|
+
var HIDDEN_AGENT_DESCRIPTION = "Internal Magic Context maintenance agent. Not for general tasks — do not select for user work.";
|
|
8383
8436
|
function buildHiddenAgentRegistrations(args) {
|
|
8384
8437
|
const historianAllowedTools = applyDisallowedTools(["read", "aft_outline", "aft_zoom", "aft_search"], args.historianDisallowed);
|
|
8385
8438
|
return [
|
|
8386
8439
|
{
|
|
8387
8440
|
id: "dreamer",
|
|
8441
|
+
mode: "primary",
|
|
8442
|
+
hidden: true,
|
|
8443
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8388
8444
|
prompt: args.dreamerPrompt,
|
|
8389
8445
|
allowedTools: ["ctx_memory"],
|
|
8390
8446
|
maxSteps: 150,
|
|
@@ -8393,6 +8449,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8393
8449
|
},
|
|
8394
8450
|
{
|
|
8395
8451
|
id: "dreamer-docs",
|
|
8452
|
+
mode: "primary",
|
|
8453
|
+
hidden: true,
|
|
8454
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8396
8455
|
prompt: args.dreamerPrompt,
|
|
8397
8456
|
allowedTools: [
|
|
8398
8457
|
"read",
|
|
@@ -8411,6 +8470,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8411
8470
|
},
|
|
8412
8471
|
{
|
|
8413
8472
|
id: "dreamer-reviewer",
|
|
8473
|
+
mode: "primary",
|
|
8474
|
+
hidden: true,
|
|
8475
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8414
8476
|
prompt: args.dreamerPrompt,
|
|
8415
8477
|
allowedTools: [],
|
|
8416
8478
|
maxSteps: 4,
|
|
@@ -8419,6 +8481,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8419
8481
|
},
|
|
8420
8482
|
{
|
|
8421
8483
|
id: "dreamer-retrospective",
|
|
8484
|
+
mode: "primary",
|
|
8485
|
+
hidden: true,
|
|
8486
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8422
8487
|
prompt: args.dreamerPrompt,
|
|
8423
8488
|
allowedTools: ["ctx_search"],
|
|
8424
8489
|
maxSteps: 40,
|
|
@@ -8427,6 +8492,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8427
8492
|
},
|
|
8428
8493
|
{
|
|
8429
8494
|
id: "dreamer-primer-investigator",
|
|
8495
|
+
mode: "primary",
|
|
8496
|
+
hidden: true,
|
|
8497
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8430
8498
|
prompt: args.dreamerPrompt,
|
|
8431
8499
|
allowedTools: [
|
|
8432
8500
|
"read",
|
|
@@ -8443,6 +8511,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8443
8511
|
},
|
|
8444
8512
|
{
|
|
8445
8513
|
id: "dreamer-memory-mapper",
|
|
8514
|
+
mode: "primary",
|
|
8515
|
+
hidden: true,
|
|
8516
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8446
8517
|
prompt: args.dreamerPrompt,
|
|
8447
8518
|
allowedTools: ["read", "grep", "glob", "aft_outline", "aft_zoom", "aft_search"],
|
|
8448
8519
|
maxSteps: 60,
|
|
@@ -8451,6 +8522,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8451
8522
|
},
|
|
8452
8523
|
{
|
|
8453
8524
|
id: "dreamer-classifier",
|
|
8525
|
+
mode: "primary",
|
|
8526
|
+
hidden: true,
|
|
8527
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8454
8528
|
prompt: args.dreamerPrompt,
|
|
8455
8529
|
allowedTools: [],
|
|
8456
8530
|
maxSteps: 4,
|
|
@@ -8459,6 +8533,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8459
8533
|
},
|
|
8460
8534
|
{
|
|
8461
8535
|
id: "smart-note-compiler",
|
|
8536
|
+
mode: "primary",
|
|
8537
|
+
hidden: true,
|
|
8538
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8462
8539
|
prompt: args.smartNoteCompilerPrompt,
|
|
8463
8540
|
allowedTools: [],
|
|
8464
8541
|
maxSteps: 8,
|
|
@@ -8467,6 +8544,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8467
8544
|
},
|
|
8468
8545
|
{
|
|
8469
8546
|
id: "historian",
|
|
8547
|
+
mode: "primary",
|
|
8548
|
+
hidden: true,
|
|
8549
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8470
8550
|
prompt: args.historianPrompt,
|
|
8471
8551
|
allowedTools: historianAllowedTools,
|
|
8472
8552
|
maxSteps: 40,
|
|
@@ -8474,6 +8554,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8474
8554
|
},
|
|
8475
8555
|
{
|
|
8476
8556
|
id: "historian-recomp",
|
|
8557
|
+
mode: "primary",
|
|
8558
|
+
hidden: true,
|
|
8559
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8477
8560
|
prompt: args.historianRecompPrompt ?? args.historianPrompt,
|
|
8478
8561
|
allowedTools: historianAllowedTools,
|
|
8479
8562
|
maxSteps: 40,
|
|
@@ -8481,6 +8564,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8481
8564
|
},
|
|
8482
8565
|
{
|
|
8483
8566
|
id: "historian-editor",
|
|
8567
|
+
mode: "primary",
|
|
8568
|
+
hidden: true,
|
|
8569
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8484
8570
|
prompt: args.historianEditorPrompt,
|
|
8485
8571
|
allowedTools: historianAllowedTools,
|
|
8486
8572
|
maxSteps: 40,
|
|
@@ -8488,6 +8574,9 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8488
8574
|
},
|
|
8489
8575
|
{
|
|
8490
8576
|
id: "sidekick",
|
|
8577
|
+
mode: "primary",
|
|
8578
|
+
hidden: true,
|
|
8579
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
8491
8580
|
prompt: args.sidekickPrompt,
|
|
8492
8581
|
allowedTools: ["ctx_search", "aft_outline", "aft_zoom"],
|
|
8493
8582
|
maxSteps: 40,
|
|
@@ -8495,7 +8584,7 @@ function buildHiddenAgentRegistrations(args) {
|
|
|
8495
8584
|
}
|
|
8496
8585
|
];
|
|
8497
8586
|
}
|
|
8498
|
-
function buildHiddenAgentConfig(prompt, allowedTools, maxSteps, overrides, agentLabel, lockPermissions = false) {
|
|
8587
|
+
function buildHiddenAgentConfig(prompt, allowedTools, maxSteps, overrides, agentLabel, lockPermissions = false, description) {
|
|
8499
8588
|
const {
|
|
8500
8589
|
permission: overridePermission,
|
|
8501
8590
|
tools: overrideTools,
|
|
@@ -8522,8 +8611,9 @@ function buildHiddenAgentConfig(prompt, allowedTools, maxSteps, overrides, agent
|
|
|
8522
8611
|
...basePermission,
|
|
8523
8612
|
...lockPermissions ? {} : overridePermission ?? {}
|
|
8524
8613
|
},
|
|
8525
|
-
mode: "
|
|
8526
|
-
hidden: true
|
|
8614
|
+
mode: "primary",
|
|
8615
|
+
hidden: true,
|
|
8616
|
+
...description !== undefined ? { description } : {}
|
|
8527
8617
|
};
|
|
8528
8618
|
}
|
|
8529
8619
|
|
|
@@ -11485,6 +11575,7 @@ var CONNECT_BACKOFF_INITIAL_MS = 1000;
|
|
|
11485
11575
|
var CONNECT_BACKOFF_MAX_MS = 30000;
|
|
11486
11576
|
var HANDSHAKE_TIMEOUT_MS = 2000;
|
|
11487
11577
|
var MODULE_SEND_TIMEOUT_MS = 15000;
|
|
11578
|
+
var TRANSFORM_SEND_TIMEOUT_MS = 5000;
|
|
11488
11579
|
var SERIAL_LANE_MAX_WAITERS = 16;
|
|
11489
11580
|
var SERIAL_LANE_MIN_REMAINING_MS = 25;
|
|
11490
11581
|
var CANONICAL_ROOT_CACHE_MAX_ENTRIES = 256;
|
|
@@ -11520,15 +11611,21 @@ function isConnectionFailure(error) {
|
|
|
11520
11611
|
if (error instanceof SocketClosedError || error instanceof SocketTimeoutError || error instanceof StaleRouteHandleError || isConsumerReconnectTransient(error) || isStaleOrDeadRouteFailure(error)) {
|
|
11521
11612
|
return true;
|
|
11522
11613
|
}
|
|
11523
|
-
return errorChainSome(error, (current) =>
|
|
11524
|
-
"
|
|
11525
|
-
"
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11530
|
-
|
|
11531
|
-
|
|
11614
|
+
return errorChainSome(error, (current) => {
|
|
11615
|
+
const code = typeof current.code === "string" ? current.code : "";
|
|
11616
|
+
const message = typeof current.message === "string" ? current.message : "";
|
|
11617
|
+
return [
|
|
11618
|
+
"ENOENT",
|
|
11619
|
+
"ECONNREFUSED",
|
|
11620
|
+
"ECONNRESET",
|
|
11621
|
+
"EPIPE",
|
|
11622
|
+
"ETIMEDOUT",
|
|
11623
|
+
"request_deadline",
|
|
11624
|
+
"deadline_exceeded_no_drop_observed",
|
|
11625
|
+
"connection_dropped",
|
|
11626
|
+
"SUBC_CONNECTION_BACKOFF"
|
|
11627
|
+
].includes(code) || /\bclient closed\b|\bconnection closed\b|\bclosed the connection\b/i.test(message);
|
|
11628
|
+
});
|
|
11532
11629
|
}
|
|
11533
11630
|
|
|
11534
11631
|
class SubcModuleTransport {
|
|
@@ -11546,7 +11643,20 @@ class SubcModuleTransport {
|
|
|
11546
11643
|
authorityBindRoot = "";
|
|
11547
11644
|
backoffMs = CONNECT_BACKOFF_INITIAL_MS;
|
|
11548
11645
|
connectionGeneration = 0;
|
|
11646
|
+
stateSyncCapabilityCache = null;
|
|
11647
|
+
getCachedStateSyncCapabilities() {
|
|
11648
|
+
const cached = this.stateSyncCapabilityCache;
|
|
11649
|
+
if (!cached || cached.generation !== this.connectionGeneration)
|
|
11650
|
+
return;
|
|
11651
|
+
return cached.capabilities;
|
|
11652
|
+
}
|
|
11653
|
+
invalidateStateSyncCapabilities() {
|
|
11654
|
+
this.stateSyncCapabilityCache = null;
|
|
11655
|
+
}
|
|
11549
11656
|
async stateSyncCapabilities(args) {
|
|
11657
|
+
const cached = this.getCachedStateSyncCapabilities();
|
|
11658
|
+
if (cached)
|
|
11659
|
+
return cached;
|
|
11550
11660
|
const response = await this.call({
|
|
11551
11661
|
sessionId: args.sessionId,
|
|
11552
11662
|
projectRoot: args.projectRoot,
|
|
@@ -11556,7 +11666,9 @@ class SubcModuleTransport {
|
|
|
11556
11666
|
const raw = isRecord(response) ? response : {};
|
|
11557
11667
|
const value = isRecord(raw.result) ? raw.result : raw;
|
|
11558
11668
|
const epochs = isRecord(value.epochs) ? value.epochs : {};
|
|
11559
|
-
|
|
11669
|
+
const capabilities = { state_sync_deltas: epochs.state_sync_deltas === true };
|
|
11670
|
+
this.stateSyncCapabilityCache = { generation: this.connectionGeneration, capabilities };
|
|
11671
|
+
return capabilities;
|
|
11560
11672
|
}
|
|
11561
11673
|
constructor(connectionFile, moduleId = DEFAULT_MODULE_ID, requestTimeoutMs = MODULE_SEND_TIMEOUT_MS, routeSessionPrefix = "") {
|
|
11562
11674
|
this.connectionFile = connectionFile ?? getDefaultConnectionFile();
|
|
@@ -11564,11 +11676,31 @@ class SubcModuleTransport {
|
|
|
11564
11676
|
this.requestTimeoutMs = requestTimeoutMs;
|
|
11565
11677
|
this.routeSessionPrefix = routeSessionPrefix;
|
|
11566
11678
|
}
|
|
11567
|
-
|
|
11568
|
-
const error = new Error(
|
|
11679
|
+
deadlineError(detail) {
|
|
11680
|
+
const error = new Error(`module transport deadline expired ${detail}`);
|
|
11569
11681
|
error.code = "ETIMEDOUT";
|
|
11570
11682
|
return error;
|
|
11571
11683
|
}
|
|
11684
|
+
laneTimeoutError() {
|
|
11685
|
+
return this.deadlineError("while queued");
|
|
11686
|
+
}
|
|
11687
|
+
async beforeDeadline(operation, deadlineMs, detail) {
|
|
11688
|
+
const remainingMs = deadlineMs - Date.now();
|
|
11689
|
+
if (remainingMs <= 0)
|
|
11690
|
+
throw this.deadlineError(detail);
|
|
11691
|
+
let timer;
|
|
11692
|
+
try {
|
|
11693
|
+
return await Promise.race([
|
|
11694
|
+
operation,
|
|
11695
|
+
new Promise((_resolve, reject) => {
|
|
11696
|
+
timer = setTimeout(() => reject(this.deadlineError(detail)), remainingMs);
|
|
11697
|
+
})
|
|
11698
|
+
]);
|
|
11699
|
+
} finally {
|
|
11700
|
+
if (timer)
|
|
11701
|
+
clearTimeout(timer);
|
|
11702
|
+
}
|
|
11703
|
+
}
|
|
11572
11704
|
laneRelease() {
|
|
11573
11705
|
let released = false;
|
|
11574
11706
|
return () => {
|
|
@@ -11646,8 +11778,9 @@ class SubcModuleTransport {
|
|
|
11646
11778
|
});
|
|
11647
11779
|
}
|
|
11648
11780
|
async call(args) {
|
|
11649
|
-
const
|
|
11650
|
-
const
|
|
11781
|
+
const attemptTimeoutMs = args.timeoutMs ?? (args.method === "transform" ? Math.min(this.requestTimeoutMs, TRANSFORM_SEND_TIMEOUT_MS) : this.requestTimeoutMs);
|
|
11782
|
+
const laneDeadlineMs = Date.now() + attemptTimeoutMs;
|
|
11783
|
+
const releaseLane = await this.acquireCorrectnessLane(args.sessionId, args.signal, laneDeadlineMs);
|
|
11651
11784
|
const onAbort = () => this.invalidateConnection();
|
|
11652
11785
|
args.signal?.addEventListener("abort", onAbort, { once: true });
|
|
11653
11786
|
try {
|
|
@@ -11657,21 +11790,18 @@ class SubcModuleTransport {
|
|
|
11657
11790
|
if (args.signal?.aborted) {
|
|
11658
11791
|
throw args.signal.reason ?? new Error("module transport call aborted");
|
|
11659
11792
|
}
|
|
11660
|
-
const
|
|
11661
|
-
|
|
11662
|
-
throw this.laneTimeoutError();
|
|
11663
|
-
ensuredRoute = await this.ensureRoute(args.sessionId, args.projectRoot);
|
|
11793
|
+
const attemptDeadlineMs = Date.now() + attemptTimeoutMs;
|
|
11794
|
+
ensuredRoute = await this.ensureRoute(args.sessionId, args.projectRoot, attemptDeadlineMs);
|
|
11664
11795
|
if (args.signal?.aborted) {
|
|
11665
11796
|
throw args.signal.reason ?? new Error("module transport call aborted");
|
|
11666
11797
|
}
|
|
11667
|
-
return await ensuredRoute.client.request(ensuredRoute.route, args.body, {
|
|
11798
|
+
return await this.beforeDeadline(ensuredRoute.client.request(ensuredRoute.route, args.body, {
|
|
11668
11799
|
priority: Priority.Background,
|
|
11669
11800
|
admissionClass: AdmissionClass.Normal,
|
|
11670
|
-
timeoutMs: Math.max(1,
|
|
11671
|
-
});
|
|
11801
|
+
timeoutMs: Math.max(1, attemptDeadlineMs - Date.now())
|
|
11802
|
+
}), attemptDeadlineMs, "waiting for the module response");
|
|
11672
11803
|
} catch (error) {
|
|
11673
|
-
|
|
11674
|
-
if (staleOrDeadRoute) {
|
|
11804
|
+
if (isConnectionFailure(error)) {
|
|
11675
11805
|
if (ensuredRoute) {
|
|
11676
11806
|
this.dropRoute(ensuredRoute.routeKey, ensuredRoute.route);
|
|
11677
11807
|
this.invalidateConnection(ensuredRoute.client);
|
|
@@ -11680,8 +11810,6 @@ class SubcModuleTransport {
|
|
|
11680
11810
|
}
|
|
11681
11811
|
if (attempt === 0 && !args.signal?.aborted)
|
|
11682
11812
|
continue;
|
|
11683
|
-
} else if (isConnectionFailure(error)) {
|
|
11684
|
-
this.invalidateConnection(ensuredRoute?.client);
|
|
11685
11813
|
}
|
|
11686
11814
|
throw error;
|
|
11687
11815
|
}
|
|
@@ -11783,7 +11911,7 @@ class SubcModuleTransport {
|
|
|
11783
11911
|
this.invalidateConnection(client);
|
|
11784
11912
|
}
|
|
11785
11913
|
}
|
|
11786
|
-
async ensureRoute(sessionId, rawProjectRoot) {
|
|
11914
|
+
async ensureRoute(sessionId, rawProjectRoot, deadlineMs = Date.now() + this.requestTimeoutMs) {
|
|
11787
11915
|
const projectRoot = this.canonicalRoot(rawProjectRoot);
|
|
11788
11916
|
const routeKey = `${sessionId}\x00${projectRoot}`;
|
|
11789
11917
|
const client = await this.ensureConnected();
|
|
@@ -11800,7 +11928,7 @@ class SubcModuleTransport {
|
|
|
11800
11928
|
harness: getHarness(),
|
|
11801
11929
|
session: `${this.routeSessionPrefix}${sessionId}`
|
|
11802
11930
|
};
|
|
11803
|
-
const route = await client.routeOpen(target, identity);
|
|
11931
|
+
const route = await this.beforeDeadline(client.routeOpen(target, identity), deadlineMs, "opening the module route");
|
|
11804
11932
|
if (this.client !== client || generation !== this.connectionGeneration) {
|
|
11805
11933
|
await client.closeRoute(route).catch(() => {
|
|
11806
11934
|
return;
|
|
@@ -11877,6 +12005,7 @@ class SubcModuleTransport {
|
|
|
11877
12005
|
if (client && this.client && client !== this.client)
|
|
11878
12006
|
return;
|
|
11879
12007
|
this.connectionGeneration += 1;
|
|
12008
|
+
this.invalidateStateSyncCapabilities();
|
|
11880
12009
|
this.client = null;
|
|
11881
12010
|
this.routes.clear();
|
|
11882
12011
|
client?.close();
|
|
@@ -15030,16 +15159,16 @@ function claimExpectedState(db, expected) {
|
|
|
15030
15159
|
WHERE id = ? AND type = 'smart' AND status = 'pending'
|
|
15031
15160
|
AND content = ? AND surface_condition IS ? AND updated_at = ?${statusClause}`).run(...params).changes > 0;
|
|
15032
15161
|
}
|
|
15033
|
-
function getDueCompiledSmartNoteChecks(db, projectPath, now, limit) {
|
|
15034
|
-
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && (note.checkQuarantinedUntil === null || note.checkQuarantinedUntil <= now) && (note.checkNextDueAt === null || note.checkNextDueAt <= now)).sort((a, b) => (a.checkNextDueAt ?? 0) - (b.checkNextDueAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
|
|
15162
|
+
function getDueCompiledSmartNoteChecks(db, projectPath, now, limit, retinaHandoff = false) {
|
|
15163
|
+
return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && (note.checkQuarantinedUntil === null || note.checkQuarantinedUntil <= now) && (note.checkNextDueAt === null || note.checkNextDueAt <= now)).sort((a, b) => (a.checkNextDueAt ?? 0) - (b.checkNextDueAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
|
|
15035
15164
|
}
|
|
15036
|
-
function getSmartNotesNeedingCompilation(db, projectPath, now, limit) {
|
|
15037
|
-
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => (note.checkNextDueAt === null || note.checkNextDueAt <= now) && (note.checkStatus === "uncompiled" || note.checkStatus === "failing" || note.compiledCheck === null || note.policyVersion !== SMART_NOTE_CHECK_POLICY_VERSION)).sort((a, b) => a.createdAt - b.createdAt || a.id - b.id).slice(0, Math.max(1, limit));
|
|
15165
|
+
function getSmartNotesNeedingCompilation(db, projectPath, now, limit, retinaHandoff = false) {
|
|
15166
|
+
return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => (note.checkNextDueAt === null || note.checkNextDueAt <= now) && (note.checkStatus === "uncompiled" || note.checkStatus === "failing" || note.compiledCheck === null || note.policyVersion !== SMART_NOTE_CHECK_POLICY_VERSION)).sort((a, b) => a.createdAt - b.createdAt || a.id - b.id).slice(0, Math.max(1, limit));
|
|
15038
15167
|
}
|
|
15039
|
-
function getStaleCompiledSmartNotes(db, projectPath, now, limit) {
|
|
15168
|
+
function getStaleCompiledSmartNotes(db, projectPath, now, limit, retinaHandoff = false) {
|
|
15040
15169
|
const staleBefore = now - SMART_NOTE_CHECK_MAX_STALENESS_MS;
|
|
15041
15170
|
const livenessBefore = now - SMART_NOTE_CHECK_LIVENESS_RECHECK_MS;
|
|
15042
|
-
return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && note.checkFalseSinceAt !== null && note.checkFalseSinceAt <= staleBefore && (note.checkLastLivenessAt === null || note.checkLastLivenessAt <= livenessBefore)).sort((a, b) => (a.checkFalseSinceAt ?? 0) - (b.checkFalseSinceAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
|
|
15171
|
+
return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && note.checkFalseSinceAt !== null && note.checkFalseSinceAt <= staleBefore && (note.checkLastLivenessAt === null || note.checkLastLivenessAt <= livenessBefore)).sort((a, b) => (a.checkFalseSinceAt ?? 0) - (b.checkFalseSinceAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
|
|
15043
15172
|
}
|
|
15044
15173
|
function storeCompiledSmartNoteCheck(db, args) {
|
|
15045
15174
|
db.prepare(`UPDATE notes
|
|
@@ -15135,7 +15264,7 @@ var MAX_FAILURES_BEFORE_REAUTHOR = 3;
|
|
|
15135
15264
|
async function runDueCompiledSmartNoteChecks(args) {
|
|
15136
15265
|
const startedAt = Date.now();
|
|
15137
15266
|
const now = args.now ?? startedAt;
|
|
15138
|
-
const due = getDueCompiledSmartNoteChecks(args.db, args.projectIdentity, now, args.maxChecks ?? DEFAULT_MAX_CHECKS);
|
|
15267
|
+
const due = getDueCompiledSmartNoteChecks(args.db, args.projectIdentity, now, args.maxChecks ?? DEFAULT_MAX_CHECKS, args.retinaHandoff);
|
|
15139
15268
|
let ran = 0;
|
|
15140
15269
|
let surfaced = 0;
|
|
15141
15270
|
let failed = 0;
|
|
@@ -15265,7 +15394,8 @@ async function evaluateSmartNotes(args) {
|
|
|
15265
15394
|
const projectRoot = args.sessionDirectory ?? args.projectIdentity;
|
|
15266
15395
|
const moduleBridge = getModuleNoteEvaluationBridge(args.projectIdentity);
|
|
15267
15396
|
await moduleBridge?.sync();
|
|
15268
|
-
const
|
|
15397
|
+
const pendingNotes = () => getPendingSmartNotes(args.db, args.projectIdentity).filter((note) => !args.retinaHandoff || note.compileStatus !== "compiled");
|
|
15398
|
+
const pendingAtStart = pendingNotes().length;
|
|
15269
15399
|
if (pendingAtStart === 0) {
|
|
15270
15400
|
log("[dreamer] smart notes: no pending notes");
|
|
15271
15401
|
return { surfaced: 0, pending: 0, ran: false };
|
|
@@ -15289,7 +15419,7 @@ async function evaluateSmartNotes(args) {
|
|
|
15289
15419
|
let didWork = false;
|
|
15290
15420
|
try {
|
|
15291
15421
|
if (moduleBridge) {
|
|
15292
|
-
const candidates2 =
|
|
15422
|
+
const candidates2 = pendingNotes().slice(0, MAX_COMPILE_PER_RUN);
|
|
15293
15423
|
for (const note of candidates2) {
|
|
15294
15424
|
if (Date.now() >= args.deadline)
|
|
15295
15425
|
break;
|
|
@@ -15310,7 +15440,7 @@ async function evaluateSmartNotes(args) {
|
|
|
15310
15440
|
surfaced += 1;
|
|
15311
15441
|
}
|
|
15312
15442
|
await moduleBridge.sync();
|
|
15313
|
-
const pending2 =
|
|
15443
|
+
const pending2 = pendingNotes().length;
|
|
15314
15444
|
return { surfaced, pending: pending2, ran: didWork };
|
|
15315
15445
|
}
|
|
15316
15446
|
const dueRun = await runDueCompiledSmartNoteChecks({
|
|
@@ -15320,11 +15450,12 @@ async function evaluateSmartNotes(args) {
|
|
|
15320
15450
|
maxChecks: 10,
|
|
15321
15451
|
sweepBudgetMs: 1e4,
|
|
15322
15452
|
leaseHeld,
|
|
15323
|
-
signal: leaseAbortController.signal
|
|
15453
|
+
signal: leaseAbortController.signal,
|
|
15454
|
+
retinaHandoff: args.retinaHandoff
|
|
15324
15455
|
});
|
|
15325
15456
|
surfaced += dueRun.surfaced;
|
|
15326
15457
|
didWork ||= dueRun.ran > 0;
|
|
15327
|
-
const candidates = getSmartNotesNeedingCompilation(args.db, args.projectIdentity, Date.now(), MAX_COMPILE_PER_RUN);
|
|
15458
|
+
const candidates = getSmartNotesNeedingCompilation(args.db, args.projectIdentity, Date.now(), MAX_COMPILE_PER_RUN, args.retinaHandoff);
|
|
15328
15459
|
for (const note of candidates) {
|
|
15329
15460
|
if (Date.now() >= args.deadline)
|
|
15330
15461
|
break;
|
|
@@ -15334,7 +15465,7 @@ async function evaluateSmartNotes(args) {
|
|
|
15334
15465
|
if (compiled)
|
|
15335
15466
|
surfaced += 1;
|
|
15336
15467
|
}
|
|
15337
|
-
const stale = getStaleCompiledSmartNotes(args.db, args.projectIdentity, Date.now(), MAX_FALLBACK_PER_RUN);
|
|
15468
|
+
const stale = getStaleCompiledSmartNotes(args.db, args.projectIdentity, Date.now(), MAX_FALLBACK_PER_RUN, args.retinaHandoff);
|
|
15338
15469
|
for (const note of stale) {
|
|
15339
15470
|
if (Date.now() >= args.deadline)
|
|
15340
15471
|
break;
|
|
@@ -15344,7 +15475,7 @@ async function evaluateSmartNotes(args) {
|
|
|
15344
15475
|
if (met)
|
|
15345
15476
|
surfaced += 1;
|
|
15346
15477
|
}
|
|
15347
|
-
const fallbackNotes =
|
|
15478
|
+
const fallbackNotes = pendingNotes().filter((note) => note.checkStatus === "fallback").slice(0, MAX_FALLBACK_PER_RUN);
|
|
15348
15479
|
for (const note of fallbackNotes) {
|
|
15349
15480
|
if (Date.now() >= args.deadline)
|
|
15350
15481
|
break;
|
|
@@ -17879,7 +18010,8 @@ function createDreamTaskExecutor(deps) {
|
|
|
17879
18010
|
leaseKey,
|
|
17880
18011
|
deadline,
|
|
17881
18012
|
model: config.model,
|
|
17882
|
-
fallbackModels: config.fallbackModels
|
|
18013
|
+
fallbackModels: config.fallbackModels,
|
|
18014
|
+
retinaHandoff: deps.retinaHandoff
|
|
17883
18015
|
});
|
|
17884
18016
|
recordRun("completed", null, {
|
|
17885
18017
|
smartNotesSurfaced: result.surfaced,
|
|
@@ -19095,6 +19227,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
|
|
|
19095
19227
|
dreamerModel: dreamerConfig.model,
|
|
19096
19228
|
mural: reg.mural,
|
|
19097
19229
|
memoryInjectionBudgetTokens: reg.memoryInjectionBudgetTokens,
|
|
19230
|
+
retinaHandoff: reg.retinaHandoff,
|
|
19098
19231
|
transformMode: reg.transformMode,
|
|
19099
19232
|
moduleClient: reg.moduleClient,
|
|
19100
19233
|
onProgress: (progress, completedTask) => reg.onDreamerProgress?.(progress, completedTask)
|
|
@@ -19138,7 +19271,8 @@ async function runCompiledSmartNoteSweep(reg, db) {
|
|
|
19138
19271
|
const result = await runDueCompiledSmartNoteChecks({
|
|
19139
19272
|
db,
|
|
19140
19273
|
projectIdentity: reg.projectIdentity,
|
|
19141
|
-
projectRoot: reg.directory
|
|
19274
|
+
projectRoot: reg.directory,
|
|
19275
|
+
retinaHandoff: reg.retinaHandoff
|
|
19142
19276
|
});
|
|
19143
19277
|
if (result.ran > 0) {
|
|
19144
19278
|
log(`[dreamer] compiled smart-note sweep ${reg.projectIdentity}: ran=${result.ran} surfaced=${result.surfaced} logic_failed=${result.failed} network_failed=${result.networkFailed}`);
|
|
@@ -25013,7 +25147,7 @@ function readAuthoritySeqMismatch(error) {
|
|
|
25013
25147
|
async function syncModuleState(args) {
|
|
25014
25148
|
let force = args.force;
|
|
25015
25149
|
const adoption = args.options?.authoritySeqAdoption ?? { used: false };
|
|
25016
|
-
let stateSyncDeltas = args.options?.stateSyncDeltas;
|
|
25150
|
+
let stateSyncDeltas = args.options?.stateSyncDeltas ?? args.client.getCachedStateSyncCapabilities?.()?.state_sync_deltas;
|
|
25017
25151
|
if (stateSyncDeltas === undefined && args.client.stateSyncCapabilities) {
|
|
25018
25152
|
try {
|
|
25019
25153
|
stateSyncDeltas = (await args.client.stateSyncCapabilities({
|
|
@@ -25072,6 +25206,20 @@ async function syncModuleState(args) {
|
|
|
25072
25206
|
}
|
|
25073
25207
|
}
|
|
25074
25208
|
|
|
25209
|
+
// src/hooks/magic-context/raw-fallback-context-limit.ts
|
|
25210
|
+
class RawFallbackContextLimitError extends Error {
|
|
25211
|
+
estimatedTokens;
|
|
25212
|
+
contextLimitTokens;
|
|
25213
|
+
code = "RAW_FALLBACK_CONTEXT_LIMIT";
|
|
25214
|
+
recoverable = true;
|
|
25215
|
+
constructor(estimatedTokens, contextLimitTokens, options) {
|
|
25216
|
+
super(`Magic Context could not safely serve the raw prompt: the best local estimate is ${estimatedTokens.toLocaleString()} tokens, above the known ${contextLimitTokens.toLocaleString()}-token context limit. Retry the turn so the module can reconnect.`, options);
|
|
25217
|
+
this.estimatedTokens = estimatedTokens;
|
|
25218
|
+
this.contextLimitTokens = contextLimitTokens;
|
|
25219
|
+
this.name = "RawFallbackContextLimitError";
|
|
25220
|
+
}
|
|
25221
|
+
}
|
|
25222
|
+
|
|
25075
25223
|
// src/hooks/magic-context/todo-view.ts
|
|
25076
25224
|
import { createHash as createHash11 } from "node:crypto";
|
|
25077
25225
|
var TODO_STATUS_PENDING = "pending";
|
|
@@ -29283,34 +29431,26 @@ function updateFnv1a32(hash, value) {
|
|
|
29283
29431
|
}
|
|
29284
29432
|
return next;
|
|
29285
29433
|
}
|
|
29286
|
-
var SNAPSHOT_ARRAY = Symbol("array");
|
|
29287
|
-
var SNAPSHOT_OBJECT = Symbol("object");
|
|
29288
|
-
var SNAPSHOT_KEY = Symbol("key");
|
|
29289
|
-
var SNAPSHOT_STRING = Symbol("string");
|
|
29290
|
-
var SNAPSHOT_NUMBER = Symbol("number");
|
|
29291
|
-
var SNAPSHOT_BOOLEAN = Symbol("boolean");
|
|
29292
|
-
var SNAPSHOT_NULL = Symbol("null");
|
|
29293
|
-
var SNAPSHOT_UNDEFINED = Symbol("undefined");
|
|
29294
29434
|
function isSnapshotObjectChild(value) {
|
|
29295
29435
|
return value !== undefined && typeof value !== "function" && typeof value !== "symbol";
|
|
29296
29436
|
}
|
|
29297
29437
|
function visitMessageContentFields(value, visitor) {
|
|
29298
29438
|
if (value === null)
|
|
29299
|
-
return visitor.field(
|
|
29439
|
+
return visitor.field(LKG_SNAPSHOT_NULL);
|
|
29300
29440
|
if (typeof value === "string") {
|
|
29301
|
-
return visitor.field(
|
|
29441
|
+
return visitor.field(LKG_SNAPSHOT_STRING) && visitor.field(value);
|
|
29302
29442
|
}
|
|
29303
29443
|
if (typeof value === "number") {
|
|
29304
|
-
return visitor.field(
|
|
29444
|
+
return visitor.field(LKG_SNAPSHOT_NUMBER) && visitor.field(value);
|
|
29305
29445
|
}
|
|
29306
29446
|
if (typeof value === "boolean") {
|
|
29307
|
-
return visitor.field(
|
|
29447
|
+
return visitor.field(LKG_SNAPSHOT_BOOLEAN) && visitor.field(value);
|
|
29308
29448
|
}
|
|
29309
29449
|
if (value === undefined || typeof value === "function" || typeof value === "symbol") {
|
|
29310
|
-
return visitor.field(
|
|
29450
|
+
return visitor.field(LKG_SNAPSHOT_UNDEFINED);
|
|
29311
29451
|
}
|
|
29312
29452
|
if (Array.isArray(value)) {
|
|
29313
|
-
if (!visitor.field(
|
|
29453
|
+
if (!visitor.field(LKG_SNAPSHOT_ARRAY) || !visitor.field(value.length))
|
|
29314
29454
|
return false;
|
|
29315
29455
|
for (const item of value) {
|
|
29316
29456
|
if (!visitMessageContentFields(item, visitor))
|
|
@@ -29319,7 +29459,7 @@ function visitMessageContentFields(value, visitor) {
|
|
|
29319
29459
|
return true;
|
|
29320
29460
|
}
|
|
29321
29461
|
if (typeof value === "object") {
|
|
29322
|
-
if (!visitor.field(
|
|
29462
|
+
if (!visitor.field(LKG_SNAPSHOT_OBJECT))
|
|
29323
29463
|
return false;
|
|
29324
29464
|
const objectToken = visitor.beginObject();
|
|
29325
29465
|
if (objectToken === undefined)
|
|
@@ -29332,13 +29472,13 @@ function visitMessageContentFields(value, visitor) {
|
|
|
29332
29472
|
if (!isSnapshotObjectChild(child))
|
|
29333
29473
|
continue;
|
|
29334
29474
|
entryCount += 1;
|
|
29335
|
-
if (!visitor.field(
|
|
29475
|
+
if (!visitor.field(LKG_SNAPSHOT_KEY) || !visitor.field(key) || !visitMessageContentFields(child, visitor)) {
|
|
29336
29476
|
return false;
|
|
29337
29477
|
}
|
|
29338
29478
|
}
|
|
29339
29479
|
return visitor.endObject(objectToken, entryCount);
|
|
29340
29480
|
}
|
|
29341
|
-
return visitor.field(
|
|
29481
|
+
return visitor.field(LKG_SNAPSHOT_UNDEFINED);
|
|
29342
29482
|
}
|
|
29343
29483
|
function messageContentFields(message) {
|
|
29344
29484
|
const fields = [];
|
|
@@ -29549,7 +29689,10 @@ function ensureState(states, sessionId) {
|
|
|
29549
29689
|
memoryAuthorityProject: null,
|
|
29550
29690
|
memoryAuthorityRoot: null,
|
|
29551
29691
|
memoryAuthorityReady: false,
|
|
29552
|
-
authorityMemorySyncSkipLogged: false
|
|
29692
|
+
authorityMemorySyncSkipLogged: false,
|
|
29693
|
+
lkgCaptureSequence: 0,
|
|
29694
|
+
lkgLastCapturedRowVersion: 0,
|
|
29695
|
+
lkgSyncCaptureRequired: false
|
|
29553
29696
|
};
|
|
29554
29697
|
states.set(sessionId, state);
|
|
29555
29698
|
}
|
|
@@ -29863,6 +30006,7 @@ function buildTransformBody(args) {
|
|
|
29863
30006
|
function createRustModeTransform(deps, options) {
|
|
29864
30007
|
const states = new Map;
|
|
29865
30008
|
const wireCaches = new Map;
|
|
30009
|
+
const scheduleLkgCapture = options.scheduleLkgCapture ?? ((capture) => setImmediate(capture));
|
|
29866
30010
|
const timeoutMs = Math.max(1, options.moduleTimeoutMs ?? RUST_SEND_TIMEOUT_MS);
|
|
29867
30011
|
const logStage = (sessionId, stage, startedAt, timings, extra) => {
|
|
29868
30012
|
const elapsed = Math.max(0, performance.now() - startedAt);
|
|
@@ -29981,28 +30125,50 @@ function createRustModeTransform(deps, options) {
|
|
|
29981
30125
|
sessionLog(sessionId, "lkg_replay_served");
|
|
29982
30126
|
return true;
|
|
29983
30127
|
};
|
|
29984
|
-
const
|
|
29985
|
-
|
|
29986
|
-
|
|
29987
|
-
|
|
30128
|
+
const prepareRustCapture = (state, sessionId, input, inputSnapshots, response, responseRowVersion) => {
|
|
30129
|
+
state.lkgCaptureSequence += 1;
|
|
30130
|
+
const inputIds = input.map((message) => message.info.id);
|
|
30131
|
+
if (inputIds.some((id) => typeof id !== "string") || new Set(inputIds).size !== inputIds.length || inputIds.length === 0 || inputSnapshots.length !== inputIds.length) {
|
|
30132
|
+
return null;
|
|
29988
30133
|
}
|
|
29989
|
-
const inputContentDigests = input.map((message) => lkgContentDigest(message));
|
|
29990
|
-
if (inputContentDigests.some((digest) => digest === null))
|
|
29991
|
-
return false;
|
|
29992
30134
|
const native = response.native_messages;
|
|
29993
30135
|
const jsonPrefix = typeof native === "string" ? native : JSON.stringify(native);
|
|
29994
30136
|
if (typeof jsonPrefix !== "string")
|
|
29995
|
-
return
|
|
30137
|
+
return null;
|
|
29996
30138
|
const keys = resolveLkgModelKeys(input);
|
|
29997
|
-
return
|
|
30139
|
+
return {
|
|
30140
|
+
sessionId,
|
|
30141
|
+
inputIds,
|
|
30142
|
+
inputSnapshots,
|
|
29998
30143
|
jsonPrefix,
|
|
29999
|
-
inputIdSeq: ids,
|
|
30000
|
-
inputContentDigests,
|
|
30001
|
-
lastInputMessageId: ids[ids.length - 1],
|
|
30002
30144
|
modelKey: keys.modelKey,
|
|
30003
30145
|
providerKey: keys.providerKey,
|
|
30004
|
-
capturedAt: Date.now()
|
|
30146
|
+
capturedAt: Date.now(),
|
|
30147
|
+
rowVersion: responseRowVersion,
|
|
30148
|
+
captureSequence: state.lkgCaptureSequence
|
|
30149
|
+
};
|
|
30150
|
+
};
|
|
30151
|
+
const commitRustCapture = (state, plan) => {
|
|
30152
|
+
if (states.get(plan.sessionId) !== state || plan.captureSequence !== state.lkgCaptureSequence || plan.rowVersion < state.lkgLastCapturedRowVersion) {
|
|
30153
|
+
return "superseded";
|
|
30154
|
+
}
|
|
30155
|
+
const inputContentDigests = plan.inputSnapshots.map((snapshot) => lkgContentDigestFromFields(snapshot.fields));
|
|
30156
|
+
const captured = captureSlot(plan.sessionId, {
|
|
30157
|
+
jsonPrefix: plan.jsonPrefix,
|
|
30158
|
+
inputIdSeq: plan.inputIds,
|
|
30159
|
+
inputContentDigests,
|
|
30160
|
+
lastInputMessageId: plan.inputIds[plan.inputIds.length - 1],
|
|
30161
|
+
modelKey: plan.modelKey,
|
|
30162
|
+
providerKey: plan.providerKey,
|
|
30163
|
+
capturedAt: plan.capturedAt,
|
|
30164
|
+
rowVersion: plan.rowVersion,
|
|
30165
|
+
captureSequence: plan.captureSequence
|
|
30005
30166
|
});
|
|
30167
|
+
if (!captured)
|
|
30168
|
+
throw new Error("LKG slot rejected the prepared snapshot");
|
|
30169
|
+
state.lkgLastCapturedRowVersion = plan.rowVersion;
|
|
30170
|
+
state.lkgSyncCaptureRequired = false;
|
|
30171
|
+
return "captured";
|
|
30006
30172
|
};
|
|
30007
30173
|
const run = async (sessionId, messages, output, sessionMeta) => {
|
|
30008
30174
|
const passStartedAt = performance.now();
|
|
@@ -30060,6 +30226,30 @@ function createRustModeTransform(deps, options) {
|
|
|
30060
30226
|
const hasProviderProof = overflowState.detectedContextLimit > 0 && detectedLimitMatchesModel || isProviderOverflowReconfirmed(sessionId);
|
|
30061
30227
|
emergencyFailClosed ||= overflowState.needsEmergencyRecovery && overflowState.emergencyRecoveryOrigin === "provider_overflow" && hasProviderProof;
|
|
30062
30228
|
}
|
|
30229
|
+
const serveRawFallback = (cause) => {
|
|
30230
|
+
const contextLimit = resolvedContextLimit ?? (overflowState && overflowState.detectedContextLimit > 0 ? overflowState.detectedContextLimit : undefined);
|
|
30231
|
+
if (contextLimit !== undefined) {
|
|
30232
|
+
try {
|
|
30233
|
+
const estimate = estimateFinalWireInputTokens({
|
|
30234
|
+
messages,
|
|
30235
|
+
systemPromptTokens: sessionMeta.systemPromptTokens,
|
|
30236
|
+
providerID: model?.providerID,
|
|
30237
|
+
modelID: model?.modelID,
|
|
30238
|
+
agentName: deps.getNotificationParams?.(sessionId)?.agent
|
|
30239
|
+
});
|
|
30240
|
+
if (estimate.tokens > contextLimit) {
|
|
30241
|
+
sessionLog(sessionId, `raw_fallback_over_context_limit estimated=${estimate.tokens} limit=${contextLimit}`);
|
|
30242
|
+
throw new RawFallbackContextLimitError(estimate.tokens, contextLimit, {
|
|
30243
|
+
cause
|
|
30244
|
+
});
|
|
30245
|
+
}
|
|
30246
|
+
} catch (error) {
|
|
30247
|
+
if (error instanceof RawFallbackContextLimitError)
|
|
30248
|
+
throw error;
|
|
30249
|
+
}
|
|
30250
|
+
}
|
|
30251
|
+
replaceMessagesInPlace(output, messages);
|
|
30252
|
+
};
|
|
30063
30253
|
const finishPass = (applied, served = true) => {
|
|
30064
30254
|
const elapsedAt = applied && appliedAt !== undefined ? appliedAt : performance.now();
|
|
30065
30255
|
const elapsedMs = Math.max(0, elapsedAt - passStartedAt);
|
|
@@ -30090,11 +30280,19 @@ function createRustModeTransform(deps, options) {
|
|
|
30090
30280
|
servedFrom = typeof response.served_from === "string" ? response.served_from : "unknown";
|
|
30091
30281
|
materializeReason = typeof response.materialize_reason === "string" && response.materialize_reason.length > 0 ? response.materialize_reason : "none";
|
|
30092
30282
|
const timings2 = isRecord3(response.timings) ? response.timings : undefined;
|
|
30093
|
-
const
|
|
30094
|
-
|
|
30283
|
+
const applyOnceTotal = timings2?.total;
|
|
30284
|
+
const handlerTotal = timings2?.handler_total;
|
|
30285
|
+
moduleElapsedMs = typeof handlerTotal === "number" && Number.isFinite(handlerTotal) ? handlerTotal : typeof applyOnceTotal === "number" && Number.isFinite(applyOnceTotal) ? applyOnceTotal : 0;
|
|
30095
30286
|
rowVersion = typeof response.row_version === "number" && Number.isSafeInteger(response.row_version) ? response.row_version : 0;
|
|
30287
|
+
if (timings2 && (typeof timings2.handler_total === "number" || typeof timings2.native_cache_reused_messages === "number" || typeof timings2.native_cache_encoded_messages === "number")) {
|
|
30288
|
+
const stage = (name) => {
|
|
30289
|
+
const value = timings2[name];
|
|
30290
|
+
return typeof value === "number" && Number.isFinite(value) ? value.toFixed(1) : "n/a";
|
|
30291
|
+
};
|
|
30292
|
+
sessionLog(sessionId, `rust module stages: handler=${stage("handler_total")} apply_once=${stage("total")} ` + `request_to_handler=${stage("request_observed_to_handler")} ` + `projection=${stage("projection")} selection=${stage("selection")} ` + `build_output=${stage("build_output")} store_commit=${stage("store_commit")} ` + `post_attach=${stage("post_attach")} response_encode=${stage("response_encode")} ` + `native_cache_reused=${stage("native_cache_reused_messages")} ` + `native_cache_encoded=${stage("native_cache_encoded_messages")}`);
|
|
30293
|
+
}
|
|
30096
30294
|
if (timings2 && moduleElapsedMs >= 1000) {
|
|
30097
|
-
const detail = Object.entries(timings2).filter(([key, value]) => key !== "total" && typeof value === "number").map(([key, value]) => `${key}:${value.toFixed(1)}`).join(" ");
|
|
30295
|
+
const detail = Object.entries(timings2).filter(([key, value]) => key !== "total" && key !== "handler_total" && typeof value === "number").map(([key, value]) => `${key}:${value.toFixed(1)}`).join(" ");
|
|
30098
30296
|
if (detail)
|
|
30099
30297
|
sessionLog(sessionId, `rust module stages (slow pass): ${detail}`);
|
|
30100
30298
|
}
|
|
@@ -30108,7 +30306,12 @@ function createRustModeTransform(deps, options) {
|
|
|
30108
30306
|
servedFrom = "lkg";
|
|
30109
30307
|
} else {
|
|
30110
30308
|
servedFrom = "raw";
|
|
30111
|
-
|
|
30309
|
+
try {
|
|
30310
|
+
serveRawFallback();
|
|
30311
|
+
} catch (error) {
|
|
30312
|
+
finishPass(false, false);
|
|
30313
|
+
throw error;
|
|
30314
|
+
}
|
|
30112
30315
|
}
|
|
30113
30316
|
finishPass(false);
|
|
30114
30317
|
return;
|
|
@@ -30268,10 +30471,12 @@ function createRustModeTransform(deps, options) {
|
|
|
30268
30471
|
};
|
|
30269
30472
|
}
|
|
30270
30473
|
}
|
|
30474
|
+
const getCachedStateSyncCapabilities = options.moduleClient.getCachedStateSyncCapabilities;
|
|
30271
30475
|
const stateSyncCapabilities = options.moduleClient.stateSyncCapabilities;
|
|
30272
30476
|
const stateSyncResult = await syncModuleState({
|
|
30273
30477
|
client: {
|
|
30274
30478
|
call: callModule,
|
|
30479
|
+
getCachedStateSyncCapabilities: getCachedStateSyncCapabilities ? () => getCachedStateSyncCapabilities.call(options.moduleClient) : undefined,
|
|
30275
30480
|
stateSyncCapabilities: stateSyncCapabilities ? (capabilityArgs) => stateSyncCapabilities.call(options.moduleClient, capabilityArgs) : undefined
|
|
30276
30481
|
},
|
|
30277
30482
|
state,
|
|
@@ -30396,6 +30601,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30396
30601
|
throw new Error("rust module returned no transform response");
|
|
30397
30602
|
captureResponseTelemetry(response);
|
|
30398
30603
|
if (isNeedFullSync(response)) {
|
|
30604
|
+
options.moduleClient.invalidateStateSyncCapabilities?.();
|
|
30399
30605
|
state.forceFullWire = true;
|
|
30400
30606
|
if (wireDelta) {
|
|
30401
30607
|
const retryOrdinalStartedAt = performance.now();
|
|
@@ -30549,13 +30755,43 @@ function createRustModeTransform(deps, options) {
|
|
|
30549
30755
|
}
|
|
30550
30756
|
logStage(sessionId, "apply", applyStartedAt, timings);
|
|
30551
30757
|
const lkgSnapshotStartedAt = performance.now();
|
|
30552
|
-
|
|
30553
|
-
|
|
30554
|
-
|
|
30555
|
-
|
|
30758
|
+
const capturePlan = prepareRustCapture(state, sessionId, messages, pendingWireCache.rawContentSnapshots, response, rowVersion);
|
|
30759
|
+
let captureMode = "async";
|
|
30760
|
+
const captureFailed = (mode, error) => {
|
|
30761
|
+
if (states.get(sessionId) !== state || capturePlan && capturePlan.captureSequence !== state.lkgCaptureSequence) {
|
|
30762
|
+
return;
|
|
30763
|
+
}
|
|
30764
|
+
dropSlot(sessionId, `lkg_${mode}_capture_failed`);
|
|
30765
|
+
state.lkgSyncCaptureRequired = true;
|
|
30766
|
+
sessionLog(sessionId, `LKG ${mode.toUpperCase()} CAPTURE FAILED; forcing synchronous capture on the next applied pass:`, error);
|
|
30767
|
+
};
|
|
30768
|
+
if (!capturePlan) {
|
|
30769
|
+
captureMode = "declined";
|
|
30770
|
+
captureFailed("async", new Error("LKG snapshot preparation was rejected"));
|
|
30771
|
+
} else if (state.lkgSyncCaptureRequired) {
|
|
30772
|
+
captureMode = "sync_recovery";
|
|
30773
|
+
try {
|
|
30774
|
+
commitRustCapture(state, capturePlan);
|
|
30775
|
+
} catch (error) {
|
|
30776
|
+
captureFailed("sync", error);
|
|
30777
|
+
}
|
|
30778
|
+
} else {
|
|
30779
|
+
try {
|
|
30780
|
+
scheduleLkgCapture(() => {
|
|
30781
|
+
const asyncStartedAt = performance.now();
|
|
30782
|
+
try {
|
|
30783
|
+
const result = commitRustCapture(state, capturePlan);
|
|
30784
|
+
logTransformTiming(sessionId, "rust.lkg_snapshot_async", asyncStartedAt, `result=${result} row_version=${capturePlan.rowVersion}`);
|
|
30785
|
+
} catch (error) {
|
|
30786
|
+
captureFailed("async", error);
|
|
30787
|
+
}
|
|
30788
|
+
});
|
|
30789
|
+
} catch (error) {
|
|
30790
|
+
captureMode = "schedule_failed";
|
|
30791
|
+
captureFailed("async", error);
|
|
30556
30792
|
}
|
|
30557
30793
|
}
|
|
30558
|
-
logStage(sessionId, "lkgSnapshot", lkgSnapshotStartedAt, timings,
|
|
30794
|
+
logStage(sessionId, "lkgSnapshot", lkgSnapshotStartedAt, timings, `mode=${captureMode} row_version=${rowVersion}`);
|
|
30559
30795
|
const applyReplaceStartedAt = performance.now();
|
|
30560
30796
|
replaceMessagesInPlace(output, appliedMessages);
|
|
30561
30797
|
logStage(sessionId, "apply", applyReplaceStartedAt, timings);
|
|
@@ -30662,13 +30898,19 @@ function createRustModeTransform(deps, options) {
|
|
|
30662
30898
|
throw new EmergencyFailClosedError("Rust Magic Context was unavailable at a provider-proven context limit", { cause: error });
|
|
30663
30899
|
}
|
|
30664
30900
|
const replayed = replayLastGood(sessionId, messages, output, sessionMeta.systemPromptTokens);
|
|
30665
|
-
if (!replayed)
|
|
30666
|
-
replaceMessagesInPlace(output, messages);
|
|
30667
30901
|
servedFrom = replayed ? "lkg" : "raw";
|
|
30668
30902
|
if (decision.toLowerCase() !== "need_full_sync")
|
|
30669
30903
|
decision = "error";
|
|
30670
30904
|
materializeReason = "none";
|
|
30671
30905
|
markFailure(sessionId, state, error);
|
|
30906
|
+
if (!replayed) {
|
|
30907
|
+
try {
|
|
30908
|
+
serveRawFallback(error);
|
|
30909
|
+
} catch (rawFallbackError) {
|
|
30910
|
+
finishPass(false, false);
|
|
30911
|
+
throw rawFallbackError;
|
|
30912
|
+
}
|
|
30913
|
+
}
|
|
30672
30914
|
finishPass(false);
|
|
30673
30915
|
return;
|
|
30674
30916
|
}
|
|
@@ -34092,6 +34334,7 @@ function createMagicContextHook(deps) {
|
|
|
34092
34334
|
}),
|
|
34093
34335
|
userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreaming),
|
|
34094
34336
|
language: deps.config.language,
|
|
34337
|
+
retinaHandoff: deps.config.smart_notes?.retina_handoff === true,
|
|
34095
34338
|
transformMode: deps.config.transform_mode,
|
|
34096
34339
|
moduleClient: rustModeModuleClient,
|
|
34097
34340
|
onProgress: (progress, completedTask) => {
|
|
@@ -34177,6 +34420,7 @@ function createMagicContextHook(deps) {
|
|
|
34177
34420
|
language: deps.config.language,
|
|
34178
34421
|
mural: deps.config.mural,
|
|
34179
34422
|
memoryInjectionBudgetTokens: deps.config.memory?.injection_budget_tokens,
|
|
34423
|
+
retinaHandoff: deps.config.smart_notes?.retina_handoff === true,
|
|
34180
34424
|
transformMode: deps.config.transform_mode,
|
|
34181
34425
|
moduleClient: rustModeModuleClient,
|
|
34182
34426
|
onProgress: (progress, completedTask) => {
|
|
@@ -34405,6 +34649,8 @@ function createMessagesTransformHandler(args) {
|
|
|
34405
34649
|
await magicContext?.["experimental.chat.messages.transform"]?.(input, output);
|
|
34406
34650
|
return output.messages;
|
|
34407
34651
|
} catch (error) {
|
|
34652
|
+
if (error instanceof RawFallbackContextLimitError)
|
|
34653
|
+
throw error;
|
|
34408
34654
|
if (error instanceof EmergencyFailClosedError || isFailClosedBlockingError(error)) {
|
|
34409
34655
|
if (!args.compactionOff)
|
|
34410
34656
|
throw error;
|
|
@@ -35144,7 +35390,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35144
35390
|
}
|
|
35145
35391
|
});
|
|
35146
35392
|
const buildManagedCtx = async (db) => {
|
|
35147
|
-
const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await import("./derive-budgets-
|
|
35393
|
+
const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await import("./derive-budgets-88mxk2w1.js");
|
|
35148
35394
|
const { resolveFallbackChain: resolveFallbackChain2 } = await import("./resolve-fallbacks-5n5tvge1.js");
|
|
35149
35395
|
const { userMemoryCollectionEnabled: userMemoryCollectionEnabled2 } = await import("./task-config-gbp7r23g.js");
|
|
35150
35396
|
const DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
|
|
@@ -35171,8 +35417,8 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35171
35417
|
const db = getDb();
|
|
35172
35418
|
if (!db)
|
|
35173
35419
|
return { ok: false, error: "db unavailable" };
|
|
35174
|
-
const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-
|
|
35175
|
-
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-
|
|
35420
|
+
const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-7wbbvf87.js");
|
|
35421
|
+
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-bgtf4853.js");
|
|
35176
35422
|
log(`[rpc] recomp requested for session ${sessionId}`);
|
|
35177
35423
|
const ctx = await buildManagedCtx(db);
|
|
35178
35424
|
runManagedRecomp2(ctx, sessionId).then((message) => {
|
|
@@ -35187,8 +35433,8 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35187
35433
|
const db = getDb();
|
|
35188
35434
|
if (!db)
|
|
35189
35435
|
return { ok: false, error: "db unavailable" };
|
|
35190
|
-
const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-
|
|
35191
|
-
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-
|
|
35436
|
+
const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-7wbbvf87.js");
|
|
35437
|
+
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-bgtf4853.js");
|
|
35192
35438
|
log(`[rpc] session-upgrade requested for session ${sessionId}`);
|
|
35193
35439
|
const ctx = await buildManagedCtx(db);
|
|
35194
35440
|
runManagedUpgrade2(ctx, sessionId).then((message) => {
|
|
@@ -35204,7 +35450,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35204
35450
|
if (!db)
|
|
35205
35451
|
return { ok: false, error: "db unavailable" };
|
|
35206
35452
|
try {
|
|
35207
|
-
const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-
|
|
35453
|
+
const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-kh5egr11.js");
|
|
35208
35454
|
updateSessionMeta2(db, sessionId, { upgradeRemindedAt: Date.now() });
|
|
35209
35455
|
return { ok: true };
|
|
35210
35456
|
} catch (error) {
|
|
@@ -36160,6 +36406,447 @@ Smart notes: pass surface_condition and the note stays hidden until a background
|
|
|
36160
36406
|
Example: ctx_note(action="write", content="Re-run the perf benchmark once the boundary rework ships", surface_condition="When the latest release tag is >= v0.23.0")`;
|
|
36161
36407
|
// src/tools/ctx-note/tools.ts
|
|
36162
36408
|
import { tool as tool3 } from "@opencode-ai/plugin";
|
|
36409
|
+
|
|
36410
|
+
// src/features/magic-context/smart-notes/condition-compiler.ts
|
|
36411
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
36412
|
+
import { isAbsolute as isAbsolute4 } from "node:path";
|
|
36413
|
+
|
|
36414
|
+
// ../retina-local-fs/src/path-fence.ts
|
|
36415
|
+
import { lstat as lstat2, readlink, realpath as realpath2 } from "node:fs/promises";
|
|
36416
|
+
import { homedir as homedir4 } from "node:os";
|
|
36417
|
+
import { basename, dirname as dirname4, isAbsolute as isAbsolute3, join as join6, relative, resolve as resolve3, sep } from "node:path";
|
|
36418
|
+
|
|
36419
|
+
// ../retina-local-fs/src/errors.ts
|
|
36420
|
+
class ProviderError extends Error {
|
|
36421
|
+
code;
|
|
36422
|
+
constructor(code, message) {
|
|
36423
|
+
super(message);
|
|
36424
|
+
this.code = code;
|
|
36425
|
+
this.name = "ProviderError";
|
|
36426
|
+
}
|
|
36427
|
+
}
|
|
36428
|
+
|
|
36429
|
+
// ../retina-local-fs/src/path-fence.ts
|
|
36430
|
+
async function resolveAndFenceProviderPath(configuredPath, options) {
|
|
36431
|
+
const configuredHomePath = resolve3(options.homeDirectory ?? process.env.HOME ?? homedir4());
|
|
36432
|
+
let home;
|
|
36433
|
+
try {
|
|
36434
|
+
home = await realpath2(configuredHomePath);
|
|
36435
|
+
} catch (error) {
|
|
36436
|
+
throw fsError(configuredHomePath, error);
|
|
36437
|
+
}
|
|
36438
|
+
const expanded = configuredPath.startsWith("~/") ? join6(home, configuredPath.slice(2)) : configuredPath === "~" ? home : configuredPath;
|
|
36439
|
+
const absolute = isAbsolute3(expanded) ? resolve3(expanded) : resolve3(options.cwd ?? process.cwd(), expanded);
|
|
36440
|
+
const canonical = await canonicalPath(absolute, options.allowMissing);
|
|
36441
|
+
if (isFencedPath(canonical, home)) {
|
|
36442
|
+
throw new ProviderError("fenced_path", `Refusing fenced path: ${canonical}`);
|
|
36443
|
+
}
|
|
36444
|
+
return canonical;
|
|
36445
|
+
}
|
|
36446
|
+
async function canonicalPath(path6, allowMissing) {
|
|
36447
|
+
try {
|
|
36448
|
+
return await realpath2(path6);
|
|
36449
|
+
} catch (error) {
|
|
36450
|
+
if (!allowMissing || !isMissingError(error)) {
|
|
36451
|
+
throw fsError(path6, error);
|
|
36452
|
+
}
|
|
36453
|
+
const suffix = [];
|
|
36454
|
+
let candidate = path6;
|
|
36455
|
+
while (true) {
|
|
36456
|
+
try {
|
|
36457
|
+
const metadata = await lstat2(candidate);
|
|
36458
|
+
if (metadata.isSymbolicLink()) {
|
|
36459
|
+
const target = await readlink(candidate);
|
|
36460
|
+
const resolvedTarget = resolve3(dirname4(candidate), target);
|
|
36461
|
+
return canonicalPath(join6(resolvedTarget, ...suffix), true);
|
|
36462
|
+
}
|
|
36463
|
+
} catch (candidateError) {
|
|
36464
|
+
if (!isMissingError(candidateError)) {
|
|
36465
|
+
throw fsError(path6, candidateError);
|
|
36466
|
+
}
|
|
36467
|
+
}
|
|
36468
|
+
const parent = dirname4(candidate);
|
|
36469
|
+
if (parent === candidate) {
|
|
36470
|
+
throw fsError(path6, error);
|
|
36471
|
+
}
|
|
36472
|
+
suffix.unshift(basename(candidate));
|
|
36473
|
+
candidate = parent;
|
|
36474
|
+
try {
|
|
36475
|
+
return join6(await realpath2(candidate), ...suffix);
|
|
36476
|
+
} catch (parentError) {
|
|
36477
|
+
if (!isMissingError(parentError)) {
|
|
36478
|
+
throw fsError(path6, parentError);
|
|
36479
|
+
}
|
|
36480
|
+
}
|
|
36481
|
+
}
|
|
36482
|
+
}
|
|
36483
|
+
}
|
|
36484
|
+
function isFencedPath(canonicalPath2, homeDirectory) {
|
|
36485
|
+
const home = resolve3(homeDirectory);
|
|
36486
|
+
const cortexkitRoot = join6(home, ".local", "share", "cortexkit");
|
|
36487
|
+
const relativeToCortexkit = relative(cortexkitRoot, canonicalPath2);
|
|
36488
|
+
const insideCortexkit = relativeToCortexkit !== "" && relativeToCortexkit !== ".." && !relativeToCortexkit.startsWith(`..${sep}`) && !isAbsolute3(relativeToCortexkit);
|
|
36489
|
+
const parts = insideCortexkit ? relativeToCortexkit.split(sep) : [];
|
|
36490
|
+
const pathParts = canonicalPath2.split(sep).filter(Boolean);
|
|
36491
|
+
const name = basename(canonicalPath2);
|
|
36492
|
+
const catalogDirectoryCarveIn = pathParts.includes("catalog");
|
|
36493
|
+
const moduleBinCarveIn = parts.length >= 2 && parts[1] === "bin";
|
|
36494
|
+
const catalogJsonCarveIn = name.endsWith(".json") && name.includes("catalog");
|
|
36495
|
+
if (catalogDirectoryCarveIn || moduleBinCarveIn || catalogJsonCarveIn) {
|
|
36496
|
+
return false;
|
|
36497
|
+
}
|
|
36498
|
+
const inFencedRoot = insideCortexkit && ["plexus", "claustrum", "staging"].includes(parts[0] ?? "");
|
|
36499
|
+
const fencedBasename = name.includes("binding-key") || name.endsWith(".handle");
|
|
36500
|
+
const plexusStore = insideCortexkit && parts[0] === "plexus" && name.startsWith("store.db");
|
|
36501
|
+
return inFencedRoot || fencedBasename || plexusStore;
|
|
36502
|
+
}
|
|
36503
|
+
function fsError(path6, error) {
|
|
36504
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
36505
|
+
return new ProviderError("unreadable_path", `Could not read ${path6}: ${message}`);
|
|
36506
|
+
}
|
|
36507
|
+
function isMissingError(error) {
|
|
36508
|
+
return error !== null && typeof error === "object" && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
|
|
36509
|
+
}
|
|
36510
|
+
|
|
36511
|
+
// ../retina-local-fs/src/provider.ts
|
|
36512
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
36513
|
+
import { promisify as promisify3 } from "node:util";
|
|
36514
|
+
var execFileAsync3 = promisify3(execFile3);
|
|
36515
|
+
function parseSemver(value) {
|
|
36516
|
+
const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);
|
|
36517
|
+
if (!match) {
|
|
36518
|
+
throw new ProviderError("invalid_config", `Invalid semantic version: ${value}`);
|
|
36519
|
+
}
|
|
36520
|
+
return {
|
|
36521
|
+
major: Number(match[1]),
|
|
36522
|
+
minor: Number(match[2]),
|
|
36523
|
+
patch: Number(match[3]),
|
|
36524
|
+
prerelease: match[4] ? match[4].split(".").map((part) => /^\d+$/.test(part) ? Number(part) : part) : []
|
|
36525
|
+
};
|
|
36526
|
+
}
|
|
36527
|
+
function validateProviderConfig(input) {
|
|
36528
|
+
try {
|
|
36529
|
+
return { success: true, config: parseConfig(input) };
|
|
36530
|
+
} catch (error) {
|
|
36531
|
+
return {
|
|
36532
|
+
success: false,
|
|
36533
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
36534
|
+
};
|
|
36535
|
+
}
|
|
36536
|
+
}
|
|
36537
|
+
function parseConfig(value) {
|
|
36538
|
+
const config = requireObject(value, "config");
|
|
36539
|
+
if ("any" in config) {
|
|
36540
|
+
requireOnlyKeys(config, ["any"], "compound config");
|
|
36541
|
+
if (!Array.isArray(config.any) || config.any.length < 1 || config.any.length > 4) {
|
|
36542
|
+
invalid("config.any must contain between 1 and 4 predicates");
|
|
36543
|
+
}
|
|
36544
|
+
return { any: config.any.map(parseAtomicPredicate) };
|
|
36545
|
+
}
|
|
36546
|
+
return parseAtomicPredicate(config);
|
|
36547
|
+
}
|
|
36548
|
+
function parseAtomicPredicate(value) {
|
|
36549
|
+
const predicate = requireObject(value, "predicate");
|
|
36550
|
+
if (typeof predicate.kind !== "string") {
|
|
36551
|
+
invalid("predicate.kind must be a string");
|
|
36552
|
+
}
|
|
36553
|
+
switch (predicate.kind) {
|
|
36554
|
+
case "file_contains":
|
|
36555
|
+
requireOnlyKeys(predicate, ["kind", "path", "needle", "absent", "resolved_path_exists"], predicate.kind);
|
|
36556
|
+
return {
|
|
36557
|
+
kind: predicate.kind,
|
|
36558
|
+
path: requireString(predicate.path, "path"),
|
|
36559
|
+
needle: requireString(predicate.needle, "needle", true),
|
|
36560
|
+
...optionalBoolean(predicate.absent, "absent") === undefined ? {} : { absent: predicate.absent },
|
|
36561
|
+
...predicateAudit(predicate)
|
|
36562
|
+
};
|
|
36563
|
+
case "path_exists":
|
|
36564
|
+
requireOnlyKeys(predicate, ["kind", "path", "gone", "resolved_path_exists"], predicate.kind);
|
|
36565
|
+
return {
|
|
36566
|
+
kind: predicate.kind,
|
|
36567
|
+
path: requireString(predicate.path, "path"),
|
|
36568
|
+
...optionalBoolean(predicate.gone, "gone") === undefined ? {} : { gone: predicate.gone },
|
|
36569
|
+
...predicateAudit(predicate)
|
|
36570
|
+
};
|
|
36571
|
+
case "mtime_after":
|
|
36572
|
+
requireOnlyKeys(predicate, ["kind", "path", "since_ms", "resolved_path_exists"], predicate.kind);
|
|
36573
|
+
return {
|
|
36574
|
+
kind: predicate.kind,
|
|
36575
|
+
path: requireString(predicate.path, "path"),
|
|
36576
|
+
since_ms: requireFiniteNumber(predicate.since_ms, "since_ms"),
|
|
36577
|
+
...predicateAudit(predicate)
|
|
36578
|
+
};
|
|
36579
|
+
case "git_commit_after":
|
|
36580
|
+
requireOnlyKeys(predicate, ["kind", "repo_path", "ref", "sha", "resolved_path_exists"], predicate.kind);
|
|
36581
|
+
return {
|
|
36582
|
+
kind: predicate.kind,
|
|
36583
|
+
repo_path: requireString(predicate.repo_path, "repo_path"),
|
|
36584
|
+
sha: requireString(predicate.sha, "sha"),
|
|
36585
|
+
...predicate.ref === undefined ? {} : { ref: requireString(predicate.ref, "ref") },
|
|
36586
|
+
...predicateAudit(predicate)
|
|
36587
|
+
};
|
|
36588
|
+
case "git_tag_matching": {
|
|
36589
|
+
requireOnlyKeys(predicate, ["kind", "repo_path", "pattern", "above", "resolved_path_exists"], predicate.kind);
|
|
36590
|
+
const above = predicate.above === undefined ? undefined : requireString(predicate.above, "above");
|
|
36591
|
+
if (above !== undefined) {
|
|
36592
|
+
parseSemver(above);
|
|
36593
|
+
}
|
|
36594
|
+
return {
|
|
36595
|
+
kind: predicate.kind,
|
|
36596
|
+
repo_path: requireString(predicate.repo_path, "repo_path"),
|
|
36597
|
+
pattern: requireString(predicate.pattern, "pattern"),
|
|
36598
|
+
...above === undefined ? {} : { above },
|
|
36599
|
+
...predicateAudit(predicate)
|
|
36600
|
+
};
|
|
36601
|
+
}
|
|
36602
|
+
default:
|
|
36603
|
+
invalid(`Unsupported predicate kind: ${predicate.kind}`);
|
|
36604
|
+
}
|
|
36605
|
+
}
|
|
36606
|
+
function requireObject(value, field) {
|
|
36607
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
36608
|
+
invalid(`${field} must be an object`);
|
|
36609
|
+
}
|
|
36610
|
+
return value;
|
|
36611
|
+
}
|
|
36612
|
+
function requireOnlyKeys(value, allowed, field) {
|
|
36613
|
+
const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
|
|
36614
|
+
if (unknown.length > 0) {
|
|
36615
|
+
invalid(`${field} contains unknown field(s): ${unknown.join(", ")}`);
|
|
36616
|
+
}
|
|
36617
|
+
}
|
|
36618
|
+
function requireString(value, field, allowEmpty = false) {
|
|
36619
|
+
if (typeof value !== "string" || !allowEmpty && value.length === 0) {
|
|
36620
|
+
invalid(`${field} must be ${allowEmpty ? "a string" : "a non-empty string"}`);
|
|
36621
|
+
}
|
|
36622
|
+
return value;
|
|
36623
|
+
}
|
|
36624
|
+
function predicateAudit(predicate) {
|
|
36625
|
+
const exists = optionalBoolean(predicate.resolved_path_exists, "resolved_path_exists");
|
|
36626
|
+
return exists === undefined ? {} : { resolved_path_exists: exists };
|
|
36627
|
+
}
|
|
36628
|
+
function optionalBoolean(value, field) {
|
|
36629
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
36630
|
+
invalid(`${field} must be a boolean`);
|
|
36631
|
+
}
|
|
36632
|
+
return value;
|
|
36633
|
+
}
|
|
36634
|
+
function requireFiniteNumber(value, field) {
|
|
36635
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
36636
|
+
invalid(`${field} must be a finite number`);
|
|
36637
|
+
}
|
|
36638
|
+
return value;
|
|
36639
|
+
}
|
|
36640
|
+
function invalid(message) {
|
|
36641
|
+
throw new ProviderError("invalid_config", message);
|
|
36642
|
+
}
|
|
36643
|
+
|
|
36644
|
+
// src/features/magic-context/smart-notes/condition-compiler.ts
|
|
36645
|
+
var RETINA_LOCAL_FS_PROVIDER = "local-fs";
|
|
36646
|
+
var VALUE = String.raw`(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\S+)`;
|
|
36647
|
+
async function compileSurfaceCondition(surfaceCondition, options) {
|
|
36648
|
+
const parsed = parseCondition(surfaceCondition, options.projectPath);
|
|
36649
|
+
if (parsed === null)
|
|
36650
|
+
return { status: "plain" };
|
|
36651
|
+
const now = (options.now ?? Date.now)();
|
|
36652
|
+
const resolvePath = options.resolvePath ?? (async (path6) => {
|
|
36653
|
+
const resolved = await resolveAndFenceProviderPath(path6, {
|
|
36654
|
+
allowMissing: true,
|
|
36655
|
+
homeDirectory: options.homeDirectory,
|
|
36656
|
+
cwd: options.projectPath
|
|
36657
|
+
});
|
|
36658
|
+
return { path: resolved, exists: existsSync11(resolved) };
|
|
36659
|
+
});
|
|
36660
|
+
let predicates;
|
|
36661
|
+
try {
|
|
36662
|
+
predicates = [];
|
|
36663
|
+
for (const predicate of parsed) {
|
|
36664
|
+
predicates.push(await resolvePredicate(predicate, resolvePath, now));
|
|
36665
|
+
}
|
|
36666
|
+
} catch (error) {
|
|
36667
|
+
const code = error !== null && typeof error === "object" && "code" in error ? error.code : undefined;
|
|
36668
|
+
return {
|
|
36669
|
+
status: "refused",
|
|
36670
|
+
reason: code === "fenced_path" ? "fenced path" : "path resolution failed"
|
|
36671
|
+
};
|
|
36672
|
+
}
|
|
36673
|
+
const candidate = predicates.length === 1 ? predicates[0] : { any: predicates };
|
|
36674
|
+
const validation = validateProviderConfig(candidate);
|
|
36675
|
+
if (!validation.success) {
|
|
36676
|
+
return {
|
|
36677
|
+
status: "refused",
|
|
36678
|
+
reason: `provider schema: ${singleLine(validation.reason)}`.slice(0, 180)
|
|
36679
|
+
};
|
|
36680
|
+
}
|
|
36681
|
+
return {
|
|
36682
|
+
status: "compiled",
|
|
36683
|
+
provider: RETINA_LOCAL_FS_PROVIDER,
|
|
36684
|
+
config: validation.config,
|
|
36685
|
+
compiledAt: now
|
|
36686
|
+
};
|
|
36687
|
+
}
|
|
36688
|
+
function conditionCompileStorageFields(result) {
|
|
36689
|
+
if (result.status === "compiled") {
|
|
36690
|
+
return {
|
|
36691
|
+
compiledProvider: result.provider,
|
|
36692
|
+
compiledConfig: JSON.stringify(result.config),
|
|
36693
|
+
compiledAt: result.compiledAt,
|
|
36694
|
+
compileStatus: result.status
|
|
36695
|
+
};
|
|
36696
|
+
}
|
|
36697
|
+
return {
|
|
36698
|
+
compiledProvider: null,
|
|
36699
|
+
compiledConfig: null,
|
|
36700
|
+
compiledAt: null,
|
|
36701
|
+
compileStatus: result.status
|
|
36702
|
+
};
|
|
36703
|
+
}
|
|
36704
|
+
function conditionCompileReplySuffix(result) {
|
|
36705
|
+
if (result.status === "compiled") {
|
|
36706
|
+
return `
|
|
36707
|
+
- Retina provider: ${result.provider}`;
|
|
36708
|
+
}
|
|
36709
|
+
if (result.status === "refused") {
|
|
36710
|
+
return `
|
|
36711
|
+
- Retina compile refused: ${result.reason}`;
|
|
36712
|
+
}
|
|
36713
|
+
return "";
|
|
36714
|
+
}
|
|
36715
|
+
function parseCondition(surfaceCondition, projectPath) {
|
|
36716
|
+
const trimmed = surfaceCondition.trim();
|
|
36717
|
+
const either = trimmed.match(/^either\s+(.+)$/i);
|
|
36718
|
+
if (!either) {
|
|
36719
|
+
const predicate = parseAtomicCondition(trimmed, projectPath);
|
|
36720
|
+
return predicate ? [predicate] : null;
|
|
36721
|
+
}
|
|
36722
|
+
const clauses = splitOrClauses(either[1]);
|
|
36723
|
+
if (clauses.length < 2)
|
|
36724
|
+
return null;
|
|
36725
|
+
const predicates = clauses.map((clause) => parseAtomicCondition(clause, projectPath));
|
|
36726
|
+
return predicates.every((predicate) => predicate !== null) ? predicates : null;
|
|
36727
|
+
}
|
|
36728
|
+
function parseAtomicCondition(text, projectPath) {
|
|
36729
|
+
const fileContains = text.match(new RegExp(`^(?:when\\s+)?file\\s+(${VALUE})\\s+(no longer contains|contains)\\s+(.+)$`, "i"));
|
|
36730
|
+
if (fileContains) {
|
|
36731
|
+
const needle = unquote(fileContains[3].trim());
|
|
36732
|
+
if (needle === null)
|
|
36733
|
+
return null;
|
|
36734
|
+
return {
|
|
36735
|
+
kind: "file_contains",
|
|
36736
|
+
path: unquote(fileContains[1]) ?? fileContains[1],
|
|
36737
|
+
needle,
|
|
36738
|
+
...fileContains[2].toLowerCase() === "no longer contains" ? { absent: true } : {}
|
|
36739
|
+
};
|
|
36740
|
+
}
|
|
36741
|
+
const commit = text.match(new RegExp(`^(?:when\\s+)?(?:repo(?:sitory)?\\s+)?(${VALUE})\\s+has\\s+a\\s+commit\\s+(?:after|newer than)\\s+([0-9a-f]{7,64})$`, "i"));
|
|
36742
|
+
if (commit) {
|
|
36743
|
+
return {
|
|
36744
|
+
kind: "git_commit_after",
|
|
36745
|
+
repo_path: unquote(commit[1]) ?? commit[1],
|
|
36746
|
+
sha: commit[2]
|
|
36747
|
+
};
|
|
36748
|
+
}
|
|
36749
|
+
const tag = text.match(new RegExp(`^(?:when\\s+)?a\\s+tag\\s+(?:(?:matching\\s+(${VALUE})(?:\\s+above\\s+semver\\s+(${VALUE}))?)|(?:above\\s+semver\\s+(${VALUE})))\\s+appears(?:\\s+in\\s+(?:repo(?:sitory)?\\s+)?(${VALUE}))?$`, "i"));
|
|
36750
|
+
if (tag) {
|
|
36751
|
+
const pattern = tag[1] ? unquote(tag[1]) : "*";
|
|
36752
|
+
const above = unquote(tag[2] ?? tag[3] ?? "");
|
|
36753
|
+
const repoPath = tag[4] ? unquote(tag[4]) : projectPath;
|
|
36754
|
+
if (pattern === null || above === null || repoPath === null)
|
|
36755
|
+
return null;
|
|
36756
|
+
return {
|
|
36757
|
+
kind: "git_tag_matching",
|
|
36758
|
+
repo_path: repoPath,
|
|
36759
|
+
pattern,
|
|
36760
|
+
...above.length > 0 ? { above } : {}
|
|
36761
|
+
};
|
|
36762
|
+
}
|
|
36763
|
+
const mtime = text.match(new RegExp(`^(?:when\\s+)?(?:file\\s+)?(${VALUE})\\s+(changes|is rebuilt|mtime moves)$`, "i"));
|
|
36764
|
+
if (mtime) {
|
|
36765
|
+
return {
|
|
36766
|
+
kind: "mtime_after",
|
|
36767
|
+
path: unquote(mtime[1]) ?? mtime[1]
|
|
36768
|
+
};
|
|
36769
|
+
}
|
|
36770
|
+
const pathExists = text.match(new RegExp(`^(?:when\\s+)?(?:path\\s+)?(${VALUE})\\s+(exists|is gone)$`, "i"));
|
|
36771
|
+
if (pathExists) {
|
|
36772
|
+
return {
|
|
36773
|
+
kind: "path_exists",
|
|
36774
|
+
path: unquote(pathExists[1]) ?? pathExists[1],
|
|
36775
|
+
...pathExists[2].toLowerCase() === "is gone" ? { gone: true } : {}
|
|
36776
|
+
};
|
|
36777
|
+
}
|
|
36778
|
+
return null;
|
|
36779
|
+
}
|
|
36780
|
+
async function resolvePredicate(predicate, resolvePath, now) {
|
|
36781
|
+
const configuredPath = "repo_path" in predicate ? predicate.repo_path : predicate.path;
|
|
36782
|
+
const resolved = await resolvePath(configuredPath);
|
|
36783
|
+
const sourceIsResolvable = isAbsolute4(configuredPath) || configuredPath === "~" || configuredPath.startsWith("~/");
|
|
36784
|
+
const audit = sourceIsResolvable && resolved.exists ? {} : { resolved_path_exists: false };
|
|
36785
|
+
switch (predicate.kind) {
|
|
36786
|
+
case "file_contains":
|
|
36787
|
+
return { ...predicate, path: resolved.path, ...audit };
|
|
36788
|
+
case "path_exists":
|
|
36789
|
+
return { ...predicate, path: resolved.path, ...audit };
|
|
36790
|
+
case "mtime_after":
|
|
36791
|
+
return { kind: predicate.kind, path: resolved.path, since_ms: now, ...audit };
|
|
36792
|
+
case "git_commit_after":
|
|
36793
|
+
return { ...predicate, repo_path: resolved.path, ...audit };
|
|
36794
|
+
case "git_tag_matching":
|
|
36795
|
+
return { ...predicate, repo_path: resolved.path, ...audit };
|
|
36796
|
+
}
|
|
36797
|
+
}
|
|
36798
|
+
function splitOrClauses(text) {
|
|
36799
|
+
const clauses = [];
|
|
36800
|
+
let start = 0;
|
|
36801
|
+
let quote = null;
|
|
36802
|
+
let escaped = false;
|
|
36803
|
+
for (let index = 0;index < text.length; index += 1) {
|
|
36804
|
+
const character = text[index];
|
|
36805
|
+
if (escaped) {
|
|
36806
|
+
escaped = false;
|
|
36807
|
+
continue;
|
|
36808
|
+
}
|
|
36809
|
+
if (quote && character === "\\") {
|
|
36810
|
+
escaped = true;
|
|
36811
|
+
continue;
|
|
36812
|
+
}
|
|
36813
|
+
if (character === '"' || character === "'") {
|
|
36814
|
+
quote = quote === character ? null : quote === null ? character : quote;
|
|
36815
|
+
continue;
|
|
36816
|
+
}
|
|
36817
|
+
if (quote !== null)
|
|
36818
|
+
continue;
|
|
36819
|
+
const separator = text.slice(index).match(/^\s+or\s+/i);
|
|
36820
|
+
if (!separator)
|
|
36821
|
+
continue;
|
|
36822
|
+
clauses.push(text.slice(start, index).trim());
|
|
36823
|
+
index += separator[0].length - 1;
|
|
36824
|
+
start = index + 1;
|
|
36825
|
+
}
|
|
36826
|
+
clauses.push(text.slice(start).trim());
|
|
36827
|
+
return clauses.filter(Boolean);
|
|
36828
|
+
}
|
|
36829
|
+
function unquote(value) {
|
|
36830
|
+
if (value.length < 2)
|
|
36831
|
+
return value;
|
|
36832
|
+
const quote = value[0];
|
|
36833
|
+
if (quote !== '"' && quote !== "'" || value.at(-1) !== quote)
|
|
36834
|
+
return value;
|
|
36835
|
+
if (quote === '"') {
|
|
36836
|
+
try {
|
|
36837
|
+
const parsed = JSON.parse(value);
|
|
36838
|
+
return typeof parsed === "string" ? parsed : null;
|
|
36839
|
+
} catch {
|
|
36840
|
+
return null;
|
|
36841
|
+
}
|
|
36842
|
+
}
|
|
36843
|
+
return value.slice(1, -1).replace(/\\'/g, "'").replace(/\\\\/g, "\\");
|
|
36844
|
+
}
|
|
36845
|
+
function singleLine(value) {
|
|
36846
|
+
return value.replace(/\s+/g, " ").trim();
|
|
36847
|
+
}
|
|
36848
|
+
|
|
36849
|
+
// src/tools/ctx-note/tools.ts
|
|
36163
36850
|
function captureAnchorOrdinal(db, sessionId) {
|
|
36164
36851
|
try {
|
|
36165
36852
|
const ordinal = getLastIndexedOrdinal(db, sessionId);
|
|
@@ -36385,16 +37072,21 @@ function createCtxNoteTool(deps) {
|
|
|
36385
37072
|
if (!projectIdentity) {
|
|
36386
37073
|
return "Error: Could not resolve project identity for smart note.";
|
|
36387
37074
|
}
|
|
37075
|
+
const surfaceCondition = args.surface_condition.trim();
|
|
37076
|
+
const compilation = await compileSurfaceCondition(surfaceCondition, {
|
|
37077
|
+
projectPath: toolContext.directory
|
|
37078
|
+
});
|
|
36388
37079
|
const note2 = addNote(deps.db, "smart", {
|
|
36389
37080
|
content,
|
|
36390
37081
|
projectPath: projectIdentity,
|
|
36391
37082
|
sessionId,
|
|
36392
|
-
surfaceCondition
|
|
36393
|
-
anchorOrdinal
|
|
37083
|
+
surfaceCondition,
|
|
37084
|
+
anchorOrdinal,
|
|
37085
|
+
...conditionCompileStorageFields(compilation)
|
|
36394
37086
|
});
|
|
36395
37087
|
return `Created smart note #${note2.id}. Dreamer will evaluate the condition during nightly runs:
|
|
36396
37088
|
- Content: ${content}
|
|
36397
|
-
- Condition: ${
|
|
37089
|
+
- Condition: ${surfaceCondition}${conditionCompileReplySuffix(compilation)}`;
|
|
36398
37090
|
}
|
|
36399
37091
|
const note = addNote(deps.db, "session", { sessionId, content, anchorOrdinal });
|
|
36400
37092
|
return `Saved session note #${note.id}.`;
|
|
@@ -36421,8 +37113,15 @@ function createCtxNoteTool(deps) {
|
|
|
36421
37113
|
const updates = {};
|
|
36422
37114
|
if (args.content?.trim())
|
|
36423
37115
|
updates.content = args.content.trim();
|
|
36424
|
-
|
|
36425
|
-
|
|
37116
|
+
let compilation;
|
|
37117
|
+
if (args.surface_condition?.trim()) {
|
|
37118
|
+
const surfaceCondition = args.surface_condition.trim();
|
|
37119
|
+
updates.surfaceCondition = surfaceCondition;
|
|
37120
|
+
compilation = await compileSurfaceCondition(surfaceCondition, {
|
|
37121
|
+
projectPath: toolContext.directory
|
|
37122
|
+
});
|
|
37123
|
+
Object.assign(updates, conditionCompileStorageFields(compilation));
|
|
37124
|
+
}
|
|
36426
37125
|
if (!updates.content && !updates.surfaceCondition) {
|
|
36427
37126
|
return "Error: Provide 'content' and/or 'surface_condition' to update.";
|
|
36428
37127
|
}
|
|
@@ -36443,7 +37142,7 @@ function createCtxNoteTool(deps) {
|
|
|
36443
37142
|
parts.push(`Condition: ${updates.surfaceCondition}`);
|
|
36444
37143
|
return `Updated note #${noteId}:
|
|
36445
37144
|
${parts.join(`
|
|
36446
|
-
`)}`;
|
|
37145
|
+
`)}${compilation ? conditionCompileReplySuffix(compilation) : ""}`;
|
|
36447
37146
|
}
|
|
36448
37147
|
const limit = typeof args.limit === "number" && args.limit > 0 ? Math.floor(args.limit) : DEFAULT_READ_LIMIT;
|
|
36449
37148
|
const offset = typeof args.offset === "number" && args.offset > 0 ? Math.floor(args.offset) : 0;
|
|
@@ -37012,7 +37711,7 @@ import {
|
|
|
37012
37711
|
unlinkSync,
|
|
37013
37712
|
writeFileSync as writeFileSync4
|
|
37014
37713
|
} from "node:fs";
|
|
37015
|
-
import { dirname as
|
|
37714
|
+
import { dirname as dirname5 } from "node:path";
|
|
37016
37715
|
var MAX_BODY_BYTES = 1048576;
|
|
37017
37716
|
var WS_AUTH_TIMEOUT_MS = 5000;
|
|
37018
37717
|
var WS_CLOSE_UNAUTHORIZED = 4401;
|
|
@@ -37086,7 +37785,7 @@ class MagicContextRpcServer {
|
|
|
37086
37785
|
this.port = server.port ?? 0;
|
|
37087
37786
|
try {
|
|
37088
37787
|
this.warnIfOtherLiveInstance();
|
|
37089
|
-
const dir =
|
|
37788
|
+
const dir = dirname5(this.portFilePath);
|
|
37090
37789
|
const enforcePrivatePermissions = shouldEnforcePrivateStoragePermissions();
|
|
37091
37790
|
if (enforcePrivatePermissions) {
|
|
37092
37791
|
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
@@ -37319,7 +38018,7 @@ var server = async (ctx) => {
|
|
|
37319
38018
|
`);
|
|
37320
38019
|
setTimeout(async () => {
|
|
37321
38020
|
try {
|
|
37322
|
-
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-
|
|
38021
|
+
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-bgtf4853.js");
|
|
37323
38022
|
const clientWithSessions = ctx.client;
|
|
37324
38023
|
const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
|
|
37325
38024
|
const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
|
|
@@ -37463,6 +38162,7 @@ var server = async (ctx) => {
|
|
|
37463
38162
|
memoryEnabled: pluginConfig.memory?.enabled === true,
|
|
37464
38163
|
memoryInjectionBudgetTokens: pluginConfig.memory?.injection_budget_tokens,
|
|
37465
38164
|
mural: pluginConfig.mural,
|
|
38165
|
+
retinaHandoff: pluginConfig.smart_notes.retina_handoff,
|
|
37466
38166
|
gitCommitIndexing: pluginConfig.memory.git_commit_indexing?.enabled ? {
|
|
37467
38167
|
enabled: true,
|
|
37468
38168
|
since_days: pluginConfig.memory.git_commit_indexing.since_days,
|
|
@@ -37500,7 +38200,7 @@ var server = async (ctx) => {
|
|
|
37500
38200
|
{
|
|
37501
38201
|
const fence = getSchemaFenceRejection();
|
|
37502
38202
|
if (fence) {
|
|
37503
|
-
import("./conflict-warning-hook-
|
|
38203
|
+
import("./conflict-warning-hook-dw9fs934.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
|
|
37504
38204
|
}
|
|
37505
38205
|
}
|
|
37506
38206
|
if (conflictResult?.hasConflict) {
|
|
@@ -37518,10 +38218,10 @@ var server = async (ctx) => {
|
|
|
37518
38218
|
ANNOUNCEMENT_FEATURES: ANNOUNCEMENT_FEATURES2,
|
|
37519
38219
|
ANNOUNCEMENT_FOOTER: ANNOUNCEMENT_FOOTER2,
|
|
37520
38220
|
markAnnouncementSeen: markAnnouncementSeen2
|
|
37521
|
-
} = await import("./announcement-
|
|
38221
|
+
} = await import("./announcement-6c1g4es4.js");
|
|
37522
38222
|
if (shouldShowAnnouncement2()) {
|
|
37523
38223
|
setTimeout(() => {
|
|
37524
|
-
import("./conflict-warning-hook-
|
|
38224
|
+
import("./conflict-warning-hook-dw9fs934.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION2, ANNOUNCEMENT_FEATURES2, ANNOUNCEMENT_FOOTER2, markAnnouncementSeen2)).catch(() => {});
|
|
37525
38225
|
}, 8000);
|
|
37526
38226
|
}
|
|
37527
38227
|
} catch {}
|
|
@@ -37648,14 +38348,17 @@ var server = async (ctx) => {
|
|
|
37648
38348
|
historianDisallowed: pluginConfig.historian?.disallowed_tools ?? []
|
|
37649
38349
|
});
|
|
37650
38350
|
const agentConfig = { ...config.agent ?? {} };
|
|
38351
|
+
const agentConfigRecord = agentConfig;
|
|
38352
|
+
const internalAgentIds = registrations.map((registration) => registration.id);
|
|
37651
38353
|
for (const reg of registrations) {
|
|
37652
38354
|
if (typeof reg.prompt !== "string" || reg.prompt.length === 0) {
|
|
37653
38355
|
log(`[magic-context] skipping hidden agent '${reg.id}' — prompt unavailable at config time (dir=${ctx.directory}); will re-register on a later complete pass`);
|
|
37654
38356
|
continue;
|
|
37655
38357
|
}
|
|
37656
|
-
|
|
38358
|
+
agentConfigRecord[reg.id] = buildHiddenAgentConfig(reg.prompt, reg.allowedTools, reg.maxSteps, reg.overrides, reg.id, reg.lockPermissions === true, reg.description);
|
|
37657
38359
|
}
|
|
37658
|
-
|
|
38360
|
+
const callerAgentConfig = denyTaskRoutingToCallerAgents(agentConfigRecord, internalAgentIds);
|
|
38361
|
+
config.agent = callerAgentConfig;
|
|
37659
38362
|
} catch (error) {
|
|
37660
38363
|
const e = error;
|
|
37661
38364
|
log(`[magic-context] config hook failed (commands/agents NOT registered; transform still active): ${e?.message ?? error}`, e?.stack ? { stackHead: e.stack.split(`
|