@cortexkit/opencode-magic-context 0.43.0 → 0.43.2
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/dist/{announcement-8mgn61fw.js → announcement-1a8bvswd.js} +2 -1
- package/dist/{conflict-warning-hook-t2vb0wnx.js → conflict-warning-hook-hyk9y29x.js} +6 -4
- package/dist/{derive-budgets-0sg5vp61.js → derive-budgets-b8ybssh9.js} +3 -2
- package/dist/features/magic-context/dreamer/classify.d.ts +12 -0
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts +7 -4
- package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts +3 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts +3 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts +4 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/memory/verification-paths.d.ts.map +1 -1
- package/dist/features/magic-context/store-generation-rebase.d.ts +62 -1
- package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/checker.d.ts +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +6 -0
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts +7 -0
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +2 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +60 -8
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +3 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +1 -0
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +2 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts +1 -0
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +9 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-8w1skpnm.js → index-0ccmyzbj.js} +6 -6
- package/dist/{index-ntbmt6rq.js → index-4b30nf6z.js} +1 -1
- package/dist/{index-rpz2me0v.js → index-6j8th2hd.js} +2 -2
- package/dist/{index-99sfbrrf.js → index-6w9p73jz.js} +1 -1
- package/dist/{index-4ftb5hcq.js → index-6z9g64js.js} +7 -1
- package/dist/{index-9skq8m9y.js → index-9r1cbh9e.js} +1 -1
- package/dist/{index-ykg9sdzz.js → index-bmzt6xgy.js} +3 -3
- package/dist/{safe-notification-target-fepvcbsj.js → index-febg06dy.js} +6 -7
- package/dist/{index-d0dh7v0f.js → index-g6hpfkqa.js} +361 -118
- package/dist/{index-rvwvdq59.js → index-jgnag7sa.js} +38 -4
- package/dist/{index-w2ety11c.js → index-pa67brzn.js} +3 -3
- package/dist/{index-ygwdyntq.js → index-tdrv6nd0.js} +6 -4
- package/dist/{index-qp20p2py.js → index-wgzyeyf5.js} +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +801 -240
- package/dist/{message-time-backfill-gzjer78y.js → message-time-backfill-0ccvyk9n.js} +3 -2
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/{read-session-chunk-ec3jkvhg.js → read-session-chunk-53a7qbrh.js} +4 -3
- package/dist/{recomp-orchestrator-6akjp11f.js → recomp-orchestrator-adsgqgse.js} +9 -7
- package/dist/safe-notification-target-vrkjrbgb.js +10 -0
- package/dist/{send-session-notification-f6gwkesy.js → send-session-notification-e28r4xx2.js} +7 -3
- package/dist/shared/data-path.d.ts.map +1 -1
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/opencode-db-path.d.ts.map +1 -1
- package/dist/shared/test-fake-executable.d.ts +38 -0
- package/dist/shared/test-fake-executable.d.ts.map +1 -0
- package/dist/shared/test-temp-dir.d.ts +1 -1
- package/dist/shared/test-temp-dir.d.ts.map +1 -1
- package/dist/shared/user-facing-codes.d.ts +10 -0
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/{task-config-ex4nt0q0.js → task-config-mgf5nsh3.js} +1 -1
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/hidden-child.d.ts +6 -0
- package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/refusal.d.ts +9 -1
- package/dist/v2/hooks/refusal.d.ts.map +1 -1
- package/dist/v2/hooks/restore-rows.d.ts +29 -0
- package/dist/v2/hooks/restore-rows.d.ts.map +1 -0
- package/dist/v2/hooks/types.d.ts +1 -0
- package/dist/v2/hooks/types.d.ts.map +1 -1
- package/dist/v2/hooks/update-check.d.ts +8 -0
- package/dist/v2/hooks/update-check.d.ts.map +1 -1
- package/dist/v2/host-service.d.ts +1 -1
- package/dist/v2/host-service.d.ts.map +1 -1
- package/dist/v2/server.js +1171 -366
- package/dist/v2/store-reader.d.ts +8 -0
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/wrapup-orchestrator-8xzbpvm8.js +18 -0
- package/package.json +2 -1
- package/src/features/magic-context/dreamer/task-registry.ts +1 -1
- package/src/shared/data-path.ts +6 -6
- package/src/shared/model-suggestion-retry.test.ts +43 -0
- package/src/shared/model-suggestion-retry.ts +17 -0
- package/src/shared/opencode-db-path.test.ts +18 -0
- package/src/shared/opencode-db-path.ts +5 -2
- package/src/shared/test-fake-executable.test.ts +54 -0
- package/src/shared/test-fake-executable.ts +110 -0
- package/src/shared/test-temp-dir.ts +3 -0
- package/src/shared/user-facing-codes.ts +11 -0
- package/dist/wrapup-orchestrator-5akc87gr.js +0 -16
package/dist/v2/server.js
CHANGED
|
@@ -1675,8 +1675,15 @@ function getHarness() {
|
|
|
1675
1675
|
}
|
|
1676
1676
|
var currentHarness = "opencode", harnessLocked = false;
|
|
1677
1677
|
|
|
1678
|
+
// src/shared/test-temp-dir.ts
|
|
1679
|
+
var STALE_TEMP_DIR_AGE_MS, registeredTempDirs;
|
|
1680
|
+
var init_test_temp_dir = __esm(() => {
|
|
1681
|
+
STALE_TEMP_DIR_AGE_MS = 60 * 60 * 1000;
|
|
1682
|
+
registeredTempDirs = new Set;
|
|
1683
|
+
});
|
|
1684
|
+
|
|
1678
1685
|
// src/shared/data-path.ts
|
|
1679
|
-
import { existsSync as existsSync2, mkdirSync,
|
|
1686
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
1680
1687
|
import * as os from "node:os";
|
|
1681
1688
|
import * as path from "node:path";
|
|
1682
1689
|
function getDataDir() {
|
|
@@ -1764,7 +1771,9 @@ function getLegacyOpenCodeMagicContextStorageDir() {
|
|
|
1764
1771
|
return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
1765
1772
|
}
|
|
1766
1773
|
var GITIGNORE_GUARD_OPEN = "# >>> cortexkit:magic-context", GITIGNORE_GUARD_CLOSE = "# <<< cortexkit:magic-context";
|
|
1767
|
-
var init_data_path = () => {
|
|
1774
|
+
var init_data_path = __esm(() => {
|
|
1775
|
+
init_test_temp_dir();
|
|
1776
|
+
});
|
|
1768
1777
|
|
|
1769
1778
|
// src/shared/harness-provider-map.ts
|
|
1770
1779
|
function remapProviderPrefix(ref, map) {
|
|
@@ -8994,7 +9003,7 @@ var init_task_registry = __esm(() => {
|
|
|
8994
9003
|
"maintain-docs": {
|
|
8995
9004
|
requiresTools: true,
|
|
8996
9005
|
transport: "tool-loop",
|
|
8997
|
-
toolLoopPurpose: "needs
|
|
9006
|
+
toolLoopPurpose: "needs read-only file tools to investigate documentation corrections"
|
|
8998
9007
|
},
|
|
8999
9008
|
"evaluate-smart-notes": { requiresTools: false, transport: "single-shot" },
|
|
9000
9009
|
"review-user-memories": { requiresTools: false, transport: "single-shot" },
|
|
@@ -15440,7 +15449,7 @@ var HOST_UNSERVED_ROW = "hostUnservedRow";
|
|
|
15440
15449
|
// src/shared/opencode-db-path.ts
|
|
15441
15450
|
import { existsSync as existsSync8, readdirSync, statSync as statSync7 } from "node:fs";
|
|
15442
15451
|
import { homedir as homedir8 } from "node:os";
|
|
15443
|
-
import { isAbsolute as isAbsolute4, join as join8 } from "node:path";
|
|
15452
|
+
import { isAbsolute as isAbsolute4, join as join8, resolve as resolve4 } from "node:path";
|
|
15444
15453
|
function openCodeDataDir(env = process.env, dataHome) {
|
|
15445
15454
|
return join8(dataHome ?? env.XDG_DATA_HOME ?? join8(homedir8(), ".local", "share"), "opencode");
|
|
15446
15455
|
}
|
|
@@ -15520,7 +15529,7 @@ function resolveV2Fresh(dataDir, channel, env) {
|
|
|
15520
15529
|
const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
|
|
15521
15530
|
const explicit = env.OPENCODE_DB !== undefined;
|
|
15522
15531
|
return {
|
|
15523
|
-
path: filename === ":memory:" ? filename :
|
|
15532
|
+
path: filename === ":memory:" ? filename : resolve4(dataDir, filename),
|
|
15524
15533
|
source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
|
|
15525
15534
|
channel: explicit ? null : channel
|
|
15526
15535
|
};
|
|
@@ -18005,6 +18014,8 @@ function hasCountableParts(message) {
|
|
|
18005
18014
|
case "step-start":
|
|
18006
18015
|
case "step-finish":
|
|
18007
18016
|
return true;
|
|
18017
|
+
case "file":
|
|
18018
|
+
return typeof p.url === "string" && p.url.startsWith("data:image/");
|
|
18008
18019
|
default:
|
|
18009
18020
|
return false;
|
|
18010
18021
|
}
|
|
@@ -25201,9 +25212,22 @@ function visitMessageContentFields(value, visitor) {
|
|
|
25201
25212
|
}
|
|
25202
25213
|
return visitor.field(LKG_SNAPSHOT_UNDEFINED);
|
|
25203
25214
|
}
|
|
25215
|
+
function contentSnapshotValue(value) {
|
|
25216
|
+
if (!value || typeof value !== "object")
|
|
25217
|
+
return value;
|
|
25218
|
+
const message = value;
|
|
25219
|
+
const info = message.info;
|
|
25220
|
+
const summary = info?.summary;
|
|
25221
|
+
if (!Array.isArray(message.parts) || info?.role !== "user" || summary === null || typeof summary !== "object" || Array.isArray(summary) || Object.keys(summary).length !== 1 || !Array.isArray(summary.diffs) || summary.diffs.length !== 0)
|
|
25222
|
+
return value;
|
|
25223
|
+
return {
|
|
25224
|
+
...message,
|
|
25225
|
+
info: Object.fromEntries(Object.entries(info).filter(([key]) => key !== "summary"))
|
|
25226
|
+
};
|
|
25227
|
+
}
|
|
25204
25228
|
function messageContentFields(message) {
|
|
25205
25229
|
const fields = [];
|
|
25206
|
-
const complete = visitMessageContentFields(message, {
|
|
25230
|
+
const complete = visitMessageContentFields(contentSnapshotValue(message), {
|
|
25207
25231
|
field(value) {
|
|
25208
25232
|
fields.push(value);
|
|
25209
25233
|
return true;
|
|
@@ -25269,7 +25293,7 @@ function lkgContentFields(value) {
|
|
|
25269
25293
|
fields.push(LKG_SNAPSHOT_UNDEFINED);
|
|
25270
25294
|
};
|
|
25271
25295
|
try {
|
|
25272
|
-
visit(value);
|
|
25296
|
+
visit(contentSnapshotValue(value));
|
|
25273
25297
|
return fields;
|
|
25274
25298
|
} catch {
|
|
25275
25299
|
return null;
|
|
@@ -26109,7 +26133,7 @@ import {
|
|
|
26109
26133
|
statSync as statSync9,
|
|
26110
26134
|
unlinkSync as unlinkSync2
|
|
26111
26135
|
} from "node:fs";
|
|
26112
|
-
import { basename as basename3, dirname as dirname6, join as join9, resolve as
|
|
26136
|
+
import { basename as basename3, dirname as dirname6, join as join9, resolve as resolve5 } from "node:path";
|
|
26113
26137
|
function getSchemaFenceRejection() {
|
|
26114
26138
|
return lastSchemaFenceRejection;
|
|
26115
26139
|
}
|
|
@@ -26426,7 +26450,7 @@ function isDefaultSharedDatabasePath(dbPath) {
|
|
|
26426
26450
|
if (!process.env.XDG_DATA_HOME && (process.env.MAGIC_CONTEXT_TEST_DATA_DIR || false)) {
|
|
26427
26451
|
return false;
|
|
26428
26452
|
}
|
|
26429
|
-
return
|
|
26453
|
+
return resolve5(dbPath) === resolve5(join9(getMagicContextStorageDir(), "context.db"));
|
|
26430
26454
|
}
|
|
26431
26455
|
function migrationBlockingPiPids(dbPath, discovery, discoveredPiPids) {
|
|
26432
26456
|
if (isDefaultSharedDatabasePath(dbPath))
|
|
@@ -28992,6 +29016,7 @@ function emptyOutcome(status, generation, previousGeneration) {
|
|
|
28992
29016
|
previousGeneration,
|
|
28993
29017
|
compartmentsRebased: 0,
|
|
28994
29018
|
compartmentsUnresolved: 0,
|
|
29019
|
+
compartmentsDerived: 0,
|
|
28995
29020
|
compartmentsResolvedAgain: 0,
|
|
28996
29021
|
recompCompartmentsRebased: 0,
|
|
28997
29022
|
recompCompartmentsUnresolved: 0,
|
|
@@ -29045,6 +29070,12 @@ function readCoordinateRebaseNotice(db, sessionId) {
|
|
|
29045
29070
|
if (record.generation !== "v1" && record.generation !== "v2")
|
|
29046
29071
|
return null;
|
|
29047
29072
|
const count = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
29073
|
+
const ranges = (value) => Array.isArray(value) ? value.flatMap((entry) => {
|
|
29074
|
+
if (!entry || typeof entry !== "object")
|
|
29075
|
+
return [];
|
|
29076
|
+
const { sequence, start, end } = entry;
|
|
29077
|
+
return typeof sequence === "number" && typeof start === "number" && typeof end === "number" ? [{ sequence, start, end }] : [];
|
|
29078
|
+
}) : [];
|
|
29048
29079
|
return {
|
|
29049
29080
|
generation: record.generation,
|
|
29050
29081
|
previousGeneration: record.previousGeneration === "v1" || record.previousGeneration === "v2" ? record.previousGeneration : null,
|
|
@@ -29053,7 +29084,10 @@ function readCoordinateRebaseNotice(db, sessionId) {
|
|
|
29053
29084
|
discardedReductions: count(record.discardedReductions),
|
|
29054
29085
|
droppedDepthRows: count(record.droppedDepthRows),
|
|
29055
29086
|
healedGaps: count(record.healedGaps),
|
|
29056
|
-
narrativeGaps: count(record.narrativeGaps)
|
|
29087
|
+
narrativeGaps: count(record.narrativeGaps),
|
|
29088
|
+
derivedCompartments: ranges(record.derivedCompartments),
|
|
29089
|
+
unresolvedCompartmentRanges: ranges(record.unresolvedCompartmentRanges),
|
|
29090
|
+
neighbourRecoveryAt: typeof record.neighbourRecoveryAt === "number" && Number.isFinite(record.neighbourRecoveryAt) ? record.neighbourRecoveryAt : null
|
|
29057
29091
|
};
|
|
29058
29092
|
} catch {
|
|
29059
29093
|
return null;
|
|
@@ -29090,36 +29124,62 @@ function readCompartmentRows(db, table, sessionId) {
|
|
|
29090
29124
|
return db.prepare(`SELECT id, sequence, start_message, end_message, start_message_id, end_message_id, rebase_status
|
|
29091
29125
|
FROM ${table} WHERE session_id = ? ORDER BY sequence ASC`).all(sessionId).filter(isCompartmentCoordinateRow);
|
|
29092
29126
|
}
|
|
29127
|
+
function resolveAnchor(messageId, resolveOrdinal) {
|
|
29128
|
+
return messageId && messageId.length > 0 ? resolveOrdinal(messageId) : undefined;
|
|
29129
|
+
}
|
|
29093
29130
|
function planCompartments(rows, table, projection) {
|
|
29094
|
-
|
|
29095
|
-
|
|
29096
|
-
|
|
29097
|
-
|
|
29098
|
-
|
|
29099
|
-
|
|
29100
|
-
|
|
29101
|
-
|
|
29102
|
-
|
|
29103
|
-
|
|
29104
|
-
|
|
29105
|
-
|
|
29106
|
-
|
|
29107
|
-
|
|
29108
|
-
status: "unresolved",
|
|
29109
|
-
previousStatus
|
|
29110
|
-
};
|
|
29111
|
-
}
|
|
29112
|
-
return {
|
|
29131
|
+
const resolveOrdinal = (messageId) => projection.ordinalById.get(messageId);
|
|
29132
|
+
return recoverFromNeighbours(rows, table, rows.map((row) => ({
|
|
29133
|
+
start: resolveAnchor(row.start_message_id, resolveOrdinal),
|
|
29134
|
+
end: resolveAnchor(row.end_message_id, resolveOrdinal)
|
|
29135
|
+
})));
|
|
29136
|
+
}
|
|
29137
|
+
function recoverFromNeighbours(rows, table, known) {
|
|
29138
|
+
const plans = rows.map((row, index) => {
|
|
29139
|
+
const own = known[index] ?? { start: undefined, end: undefined };
|
|
29140
|
+
const previousEnd = index === 0 ? 0 : known[index - 1]?.end;
|
|
29141
|
+
const nextStart = index === rows.length - 1 ? undefined : known[index + 1]?.start;
|
|
29142
|
+
const start = own.start ?? (previousEnd === undefined ? undefined : previousEnd + 1);
|
|
29143
|
+
const end = own.end ?? (nextStart === undefined ? undefined : nextStart - 1);
|
|
29144
|
+
const base = {
|
|
29113
29145
|
table,
|
|
29114
29146
|
id: row.id,
|
|
29147
|
+
sequence: row.sequence,
|
|
29115
29148
|
previousStart: row.start_message,
|
|
29116
29149
|
previousEnd: row.end_message,
|
|
29117
|
-
|
|
29118
|
-
|
|
29119
|
-
|
|
29120
|
-
|
|
29150
|
+
previousStatus: row.rebase_status === "unresolved" ? "unresolved" : "ok"
|
|
29151
|
+
};
|
|
29152
|
+
if (start !== undefined && end !== undefined && start <= end) {
|
|
29153
|
+
return {
|
|
29154
|
+
...base,
|
|
29155
|
+
start,
|
|
29156
|
+
end,
|
|
29157
|
+
status: "ok",
|
|
29158
|
+
derived: own.start === undefined || own.end === undefined
|
|
29159
|
+
};
|
|
29160
|
+
}
|
|
29161
|
+
return {
|
|
29162
|
+
...base,
|
|
29163
|
+
start: start ?? row.start_message,
|
|
29164
|
+
end: end ?? row.end_message,
|
|
29165
|
+
status: "unresolved",
|
|
29166
|
+
derived: false
|
|
29121
29167
|
};
|
|
29122
29168
|
});
|
|
29169
|
+
for (let index = 0;index < plans.length; index += 1) {
|
|
29170
|
+
const plan = plans[index];
|
|
29171
|
+
if (plan?.status !== "unresolved")
|
|
29172
|
+
continue;
|
|
29173
|
+
const previous = plans[index - 1];
|
|
29174
|
+
const next = plans[index + 1];
|
|
29175
|
+
if (previous?.status === "ok" && plan.start <= previous.end) {
|
|
29176
|
+
plan.start = previous.end + 1;
|
|
29177
|
+
}
|
|
29178
|
+
if (next?.status === "ok" && plan.end >= next.start) {
|
|
29179
|
+
plan.end = next.start - 1;
|
|
29180
|
+
}
|
|
29181
|
+
}
|
|
29182
|
+
return plans;
|
|
29123
29183
|
}
|
|
29124
29184
|
function healNonNarrativeCompartmentGaps(plans, projection) {
|
|
29125
29185
|
let healed = 0;
|
|
@@ -29150,7 +29210,10 @@ function healNonNarrativeCompartmentGaps(plans, projection) {
|
|
|
29150
29210
|
return { healed, narrative };
|
|
29151
29211
|
}
|
|
29152
29212
|
function compartmentPlanChanges(plan) {
|
|
29153
|
-
return plan.status !== plan.previousStatus || plan.
|
|
29213
|
+
return plan.status !== plan.previousStatus || plan.start !== plan.previousStart || plan.end !== plan.previousEnd;
|
|
29214
|
+
}
|
|
29215
|
+
function rangeNotes(plans, predicate) {
|
|
29216
|
+
return plans.filter((plan) => plan.table === "compartments" && predicate(plan)).map((plan) => ({ sequence: plan.sequence, start: plan.start, end: plan.end }));
|
|
29154
29217
|
}
|
|
29155
29218
|
function planNotes(db, sessionId, projection) {
|
|
29156
29219
|
const rows = db.prepare("SELECT id, anchor_ordinal, anchor_block_id FROM notes WHERE session_id = ? AND anchor_ordinal IS NOT NULL").all(sessionId);
|
|
@@ -29236,7 +29299,14 @@ function rebaseSessionCoordinates(args) {
|
|
|
29236
29299
|
}
|
|
29237
29300
|
const previousGeneration = readCoordinateGeneration(db, sessionId);
|
|
29238
29301
|
if (previousGeneration === generation) {
|
|
29239
|
-
|
|
29302
|
+
const outcome = emptyOutcome("unchanged", generation, previousGeneration);
|
|
29303
|
+
const repair = repairStampedSessionOnce(db, sessionId, args.readMessages);
|
|
29304
|
+
if (repair !== null && repair.rowsRewritten > 0) {
|
|
29305
|
+
outcome.status = "repaired";
|
|
29306
|
+
outcome.compartmentsDerived = repair.derived.length;
|
|
29307
|
+
outcome.compartmentsUnresolved = repair.unresolved.length;
|
|
29308
|
+
}
|
|
29309
|
+
return outcome;
|
|
29240
29310
|
}
|
|
29241
29311
|
const impliedGeneration = previousGeneration ?? generationImpliedByHarness(db, sessionId) ?? generation;
|
|
29242
29312
|
if (impliedGeneration === generation) {
|
|
@@ -29300,6 +29370,8 @@ function rebaseSessionCoordinates(args) {
|
|
|
29300
29370
|
if (plan.table === "compartments") {
|
|
29301
29371
|
outcome.compartmentsRebased += rebased;
|
|
29302
29372
|
outcome.compartmentsUnresolved += unresolved;
|
|
29373
|
+
if (rebased === 1 && plan.derived)
|
|
29374
|
+
outcome.compartmentsDerived += 1;
|
|
29303
29375
|
if (rebased === 1 && plan.previousStatus === "unresolved")
|
|
29304
29376
|
outcome.compartmentsResolvedAgain += 1;
|
|
29305
29377
|
} else {
|
|
@@ -29356,7 +29428,10 @@ function rebaseSessionCoordinates(args) {
|
|
|
29356
29428
|
discardedReductions: outcome.queuedReductionsDiscarded,
|
|
29357
29429
|
droppedDepthRows: outcome.compressionDepthRowsDropped,
|
|
29358
29430
|
healedGaps: outcome.healedGaps,
|
|
29359
|
-
narrativeGaps: outcome.narrativeGaps
|
|
29431
|
+
narrativeGaps: outcome.narrativeGaps,
|
|
29432
|
+
derivedCompartments: rangeNotes(compartmentPlans, (plan) => plan.status === "ok" && plan.derived),
|
|
29433
|
+
unresolvedCompartmentRanges: rangeNotes(compartmentPlans, (plan) => plan.status === "unresolved"),
|
|
29434
|
+
neighbourRecoveryAt: Date.now()
|
|
29360
29435
|
});
|
|
29361
29436
|
db.exec("COMMIT");
|
|
29362
29437
|
committed = true;
|
|
@@ -29374,10 +29449,114 @@ function rebaseSessionCoordinates(args) {
|
|
|
29374
29449
|
sessionLog(sessionId, formatRebaseLogLine(outcome, performance.now() - startedAt));
|
|
29375
29450
|
return outcome;
|
|
29376
29451
|
}
|
|
29452
|
+
function recoverUnresolvedCompartments(args) {
|
|
29453
|
+
const { db, sessionId } = args;
|
|
29454
|
+
const rows = readCompartmentRows(db, "compartments", sessionId);
|
|
29455
|
+
const result = { rowsRewritten: 0, derived: [], unresolved: [] };
|
|
29456
|
+
if (!rows.some((row) => row.rebase_status === "unresolved"))
|
|
29457
|
+
return result;
|
|
29458
|
+
const known = rows.map((row) => {
|
|
29459
|
+
if (row.rebase_status !== "unresolved") {
|
|
29460
|
+
return { start: row.start_message, end: row.end_message };
|
|
29461
|
+
}
|
|
29462
|
+
return {
|
|
29463
|
+
start: resolveAnchor(row.start_message_id, args.resolveOrdinal),
|
|
29464
|
+
end: resolveAnchor(row.end_message_id, args.resolveOrdinal)
|
|
29465
|
+
};
|
|
29466
|
+
});
|
|
29467
|
+
const plans = recoverFromNeighbours(rows, "compartments", known);
|
|
29468
|
+
const wasUnresolved = (plan) => plan.previousStatus === "unresolved";
|
|
29469
|
+
result.derived = rangeNotes(plans, (plan) => wasUnresolved(plan) && plan.status === "ok" && plan.derived);
|
|
29470
|
+
result.unresolved = rangeNotes(plans, (plan) => plan.status === "unresolved");
|
|
29471
|
+
const changed = plans.filter(compartmentPlanChanges);
|
|
29472
|
+
const now = Date.now();
|
|
29473
|
+
db.exec("BEGIN IMMEDIATE");
|
|
29474
|
+
let committed = false;
|
|
29475
|
+
try {
|
|
29476
|
+
for (const plan of changed) {
|
|
29477
|
+
db.prepare("UPDATE compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?").run(plan.start, plan.end, plan.status, plan.id);
|
|
29478
|
+
}
|
|
29479
|
+
const previous = readCoordinateRebaseNotice(db, sessionId);
|
|
29480
|
+
const generation = previous?.generation ?? readCoordinateGeneration(db, sessionId);
|
|
29481
|
+
if (generation !== null) {
|
|
29482
|
+
const derivedSequences = new Set(result.derived.map((note) => note.sequence));
|
|
29483
|
+
const notice = {
|
|
29484
|
+
generation,
|
|
29485
|
+
previousGeneration: previous?.previousGeneration ?? null,
|
|
29486
|
+
at: previous?.at ?? now,
|
|
29487
|
+
unresolvedCompartments: result.unresolved.length,
|
|
29488
|
+
discardedReductions: previous?.discardedReductions ?? 0,
|
|
29489
|
+
droppedDepthRows: previous?.droppedDepthRows ?? 0,
|
|
29490
|
+
healedGaps: previous?.healedGaps ?? 0,
|
|
29491
|
+
narrativeGaps: previous?.narrativeGaps ?? 0,
|
|
29492
|
+
derivedCompartments: [
|
|
29493
|
+
...(previous?.derivedCompartments ?? []).filter((note) => !derivedSequences.has(note.sequence)),
|
|
29494
|
+
...result.derived
|
|
29495
|
+
],
|
|
29496
|
+
unresolvedCompartmentRanges: result.unresolved,
|
|
29497
|
+
neighbourRecoveryAt: now
|
|
29498
|
+
};
|
|
29499
|
+
ensureSessionMetaRow(db, sessionId);
|
|
29500
|
+
db.prepare("UPDATE session_meta SET coordinate_rebase_notice = ? WHERE session_id = ?").run(JSON.stringify(notice), sessionId);
|
|
29501
|
+
}
|
|
29502
|
+
db.exec("COMMIT");
|
|
29503
|
+
committed = true;
|
|
29504
|
+
} finally {
|
|
29505
|
+
if (!committed) {
|
|
29506
|
+
try {
|
|
29507
|
+
db.exec("ROLLBACK");
|
|
29508
|
+
} catch {}
|
|
29509
|
+
}
|
|
29510
|
+
}
|
|
29511
|
+
result.rowsRewritten = changed.length;
|
|
29512
|
+
sessionLog(sessionId, `INFO compartment neighbour recovery (${args.reason}) rows_rewritten=${changed.length} ` + `derived=${result.derived.map((note) => `${note.start}-${note.end}`).join(",") || "none"} ` + `unresolved=${result.unresolved.map((note) => `${note.start}-${note.end}`).join(",") || "none"}`);
|
|
29513
|
+
return result;
|
|
29514
|
+
}
|
|
29515
|
+
function unresolvedRowBreaksTiling(rows) {
|
|
29516
|
+
let expectedStart = 1;
|
|
29517
|
+
for (let index = 0;index < rows.length; index += 1) {
|
|
29518
|
+
const row = rows[index];
|
|
29519
|
+
if (!row)
|
|
29520
|
+
continue;
|
|
29521
|
+
const broken = row.start_message !== expectedStart || row.end_message < row.start_message;
|
|
29522
|
+
const touchesUnresolved = row.rebase_status === "unresolved" || rows[index - 1]?.rebase_status === "unresolved";
|
|
29523
|
+
if (broken && touchesUnresolved)
|
|
29524
|
+
return true;
|
|
29525
|
+
expectedStart = row.end_message + 1;
|
|
29526
|
+
}
|
|
29527
|
+
return false;
|
|
29528
|
+
}
|
|
29529
|
+
function repairStampedSessionOnce(db, sessionId, readMessages) {
|
|
29530
|
+
let checked = repairCheckedSessions.get(db);
|
|
29531
|
+
if (!checked) {
|
|
29532
|
+
checked = new Set;
|
|
29533
|
+
repairCheckedSessions.set(db, checked);
|
|
29534
|
+
}
|
|
29535
|
+
if (checked.has(sessionId))
|
|
29536
|
+
return null;
|
|
29537
|
+
checked.add(sessionId);
|
|
29538
|
+
const rows = readCompartmentRows(db, "compartments", sessionId);
|
|
29539
|
+
if (!rows.some((row) => row.rebase_status === "unresolved"))
|
|
29540
|
+
return null;
|
|
29541
|
+
if (readCoordinateRebaseNotice(db, sessionId)?.neighbourRecoveryAt != null)
|
|
29542
|
+
return null;
|
|
29543
|
+
if (!unresolvedRowBreaksTiling(rows))
|
|
29544
|
+
return null;
|
|
29545
|
+
let ordinalById = null;
|
|
29546
|
+
return recoverUnresolvedCompartments({
|
|
29547
|
+
db,
|
|
29548
|
+
sessionId,
|
|
29549
|
+
resolveOrdinal: (messageId) => {
|
|
29550
|
+
ordinalById ??= buildProjection(readMessages(sessionId)).ordinalById;
|
|
29551
|
+
return ordinalById.get(messageId);
|
|
29552
|
+
},
|
|
29553
|
+
reason: "stamped-session repair"
|
|
29554
|
+
});
|
|
29555
|
+
}
|
|
29377
29556
|
function formatRebaseLogLine(outcome, elapsedMs) {
|
|
29378
29557
|
const rowsRewritten = outcome.compartmentsRebased + outcome.recompCompartmentsRebased + outcome.notesRebased + outcome.notesCleared + (outcome.priorBoundaryRebased ? 1 : 0) + (outcome.recompPartialRangeRebased ? 1 : 0);
|
|
29379
29558
|
const unresolved = outcome.compartmentsUnresolved + outcome.recompCompartmentsUnresolved;
|
|
29380
|
-
return `INFO store-generation-rebase ${outcome.previousGeneration ?? "unrecorded"}->${outcome.generation} ` + `rows_rewritten=${rowsRewritten} unresolved=${unresolved} ` + `index_rows_rebuilt=${outcome.indexRowsRebuilt} drops_discarded=${outcome.queuedReductionsDiscarded} ` + `healed_gaps=${outcome.healedGaps} narrative_gaps=${outcome.narrativeGaps} ` + `ms=${Math.round(elapsedMs)} ` + `(chunk_windows_deleted=${outcome.chunkEmbeddingsDeleted} depth_rows_dropped=${outcome.compressionDepthRowsDropped} ` + `part_tags_folded=${outcome.partTagsFolded} lkg_slots_dropped=${outcome.lkgSlotsDropped} ` + `frozen_part_entries_dropped=${outcome.frozenPartEntriesDropped})`;
|
|
29559
|
+
return `INFO store-generation-rebase ${outcome.previousGeneration ?? "unrecorded"}->${outcome.generation} ` + `rows_rewritten=${rowsRewritten} unresolved=${unresolved} derived=${outcome.compartmentsDerived} ` + `index_rows_rebuilt=${outcome.indexRowsRebuilt} drops_discarded=${outcome.queuedReductionsDiscarded} ` + `healed_gaps=${outcome.healedGaps} narrative_gaps=${outcome.narrativeGaps} ` + `ms=${Math.round(elapsedMs)} ` + `(chunk_windows_deleted=${outcome.chunkEmbeddingsDeleted} depth_rows_dropped=${outcome.compressionDepthRowsDropped} ` + `part_tags_folded=${outcome.partTagsFolded} lkg_slots_dropped=${outcome.lkgSlotsDropped} ` + `frozen_part_entries_dropped=${outcome.frozenPartEntriesDropped})`;
|
|
29381
29560
|
}
|
|
29382
29561
|
function planPriorBoundary(db, sessionId, plans) {
|
|
29383
29562
|
const row = db.prepare("SELECT prior_boundary_ordinal FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
@@ -29421,11 +29600,13 @@ function indexDisagreesWithProjection(db, sessionId, projection) {
|
|
|
29421
29600
|
)`, sessionId);
|
|
29422
29601
|
return orphanedMapRows > 0;
|
|
29423
29602
|
}
|
|
29603
|
+
var repairCheckedSessions;
|
|
29424
29604
|
var init_store_generation_rebase = __esm(async () => {
|
|
29425
29605
|
init_logger();
|
|
29426
29606
|
init_storage_meta_shared();
|
|
29427
29607
|
init_storage_tags();
|
|
29428
29608
|
await init_message_index();
|
|
29609
|
+
repairCheckedSessions = new WeakMap;
|
|
29429
29610
|
});
|
|
29430
29611
|
|
|
29431
29612
|
// src/hooks/magic-context/derive-budgets.ts
|
|
@@ -73985,7 +74166,12 @@ async function runGit(cwd, args) {
|
|
|
73985
74166
|
encoding: "utf8"
|
|
73986
74167
|
});
|
|
73987
74168
|
return String(result.stdout);
|
|
73988
|
-
} catch {
|
|
74169
|
+
} catch (error) {
|
|
74170
|
+
if (error.killed || error.code === "ETIMEDOUT") {
|
|
74171
|
+
throw new Error(`Git verification command timed out after ${GIT_TIMEOUT_MS2}ms`, {
|
|
74172
|
+
cause: error
|
|
74173
|
+
});
|
|
74174
|
+
}
|
|
73989
74175
|
return null;
|
|
73990
74176
|
}
|
|
73991
74177
|
}
|
|
@@ -74408,6 +74594,45 @@ var init_note_nudger = __esm(() => {
|
|
|
74408
74594
|
lastDeliveredAt = new Map;
|
|
74409
74595
|
});
|
|
74410
74596
|
|
|
74597
|
+
// src/shared/safe-notification-target.ts
|
|
74598
|
+
function isDefaultSessionTitle(title) {
|
|
74599
|
+
return DEFAULT_TITLE_RE.test(title);
|
|
74600
|
+
}
|
|
74601
|
+
async function readSessionTitle(client, sessionId) {
|
|
74602
|
+
try {
|
|
74603
|
+
const c = client;
|
|
74604
|
+
if (typeof c.session?.get !== "function")
|
|
74605
|
+
return null;
|
|
74606
|
+
const raw = await Promise.resolve(c.session.get({ path: { id: sessionId } }));
|
|
74607
|
+
const obj = raw;
|
|
74608
|
+
const title = obj && typeof obj === "object" ? obj.data?.title ?? obj.title : undefined;
|
|
74609
|
+
return typeof title === "string" ? title : null;
|
|
74610
|
+
} catch {
|
|
74611
|
+
return null;
|
|
74612
|
+
}
|
|
74613
|
+
}
|
|
74614
|
+
async function waitForSafeNotificationTarget(client, sessionId, options) {
|
|
74615
|
+
const attempts = Math.max(1, options?.attempts ?? 4);
|
|
74616
|
+
const delayMs = options?.delayMs ?? 15000;
|
|
74617
|
+
for (let attempt = 0;attempt < attempts; attempt += 1) {
|
|
74618
|
+
const title = await readSessionTitle(client, sessionId);
|
|
74619
|
+
if (title === null)
|
|
74620
|
+
return "safe";
|
|
74621
|
+
if (!isDefaultSessionTitle(title))
|
|
74622
|
+
return "safe";
|
|
74623
|
+
if (attempt < attempts - 1) {
|
|
74624
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
74625
|
+
}
|
|
74626
|
+
}
|
|
74627
|
+
log(`[magic-context] notification skipped: session ${sessionId} still has its default title (would suppress title generation); will retry on a later startup`);
|
|
74628
|
+
return "skip";
|
|
74629
|
+
}
|
|
74630
|
+
var DEFAULT_TITLE_RE;
|
|
74631
|
+
var init_safe_notification_target = __esm(() => {
|
|
74632
|
+
init_logger();
|
|
74633
|
+
DEFAULT_TITLE_RE = /^(New session - |Child session - )\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
74634
|
+
});
|
|
74635
|
+
|
|
74411
74636
|
// src/shared/rpc-notifications.ts
|
|
74412
74637
|
function registerNotificationSink(sink) {
|
|
74413
74638
|
sinks.add(sink);
|
|
@@ -74508,45 +74733,6 @@ var init_rpc_notifications = __esm(() => {
|
|
|
74508
74733
|
sinks = new Set;
|
|
74509
74734
|
});
|
|
74510
74735
|
|
|
74511
|
-
// src/shared/safe-notification-target.ts
|
|
74512
|
-
function isDefaultSessionTitle(title) {
|
|
74513
|
-
return DEFAULT_TITLE_RE.test(title);
|
|
74514
|
-
}
|
|
74515
|
-
async function readSessionTitle(client, sessionId) {
|
|
74516
|
-
try {
|
|
74517
|
-
const c = client;
|
|
74518
|
-
if (typeof c.session?.get !== "function")
|
|
74519
|
-
return null;
|
|
74520
|
-
const raw = await Promise.resolve(c.session.get({ path: { id: sessionId } }));
|
|
74521
|
-
const obj = raw;
|
|
74522
|
-
const title = obj && typeof obj === "object" ? obj.data?.title ?? obj.title : undefined;
|
|
74523
|
-
return typeof title === "string" ? title : null;
|
|
74524
|
-
} catch {
|
|
74525
|
-
return null;
|
|
74526
|
-
}
|
|
74527
|
-
}
|
|
74528
|
-
async function waitForSafeNotificationTarget(client, sessionId, options) {
|
|
74529
|
-
const attempts = Math.max(1, options?.attempts ?? 4);
|
|
74530
|
-
const delayMs = options?.delayMs ?? 15000;
|
|
74531
|
-
for (let attempt = 0;attempt < attempts; attempt += 1) {
|
|
74532
|
-
const title = await readSessionTitle(client, sessionId);
|
|
74533
|
-
if (title === null)
|
|
74534
|
-
return "safe";
|
|
74535
|
-
if (!isDefaultSessionTitle(title))
|
|
74536
|
-
return "safe";
|
|
74537
|
-
if (attempt < attempts - 1) {
|
|
74538
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
74539
|
-
}
|
|
74540
|
-
}
|
|
74541
|
-
log(`[magic-context] notification skipped: session ${sessionId} still has its default title (would suppress title generation); will retry on a later startup`);
|
|
74542
|
-
return "skip";
|
|
74543
|
-
}
|
|
74544
|
-
var DEFAULT_TITLE_RE;
|
|
74545
|
-
var init_safe_notification_target = __esm(() => {
|
|
74546
|
-
init_logger();
|
|
74547
|
-
DEFAULT_TITLE_RE = /^(New session - |Child session - )\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
74548
|
-
});
|
|
74549
|
-
|
|
74550
74736
|
// src/shared/prompt-context.ts
|
|
74551
74737
|
function isRecord6(value) {
|
|
74552
74738
|
return typeof value === "object" && value !== null;
|
|
@@ -74908,6 +75094,7 @@ async function sendStatusNotification(_client, sessionId, text, params) {
|
|
|
74908
75094
|
var MAX_QUEUED_IGNORED_NOTIFICATIONS = 16, queuedIgnoredNotifications, flushingIgnoredNotifications, idleSessions, lastDeliveredText, activityEpoch, defaultHoldDetector = (sessionId) => !idleSessions.has(sessionId) || shouldHoldIgnoredNotification(sessionId), holdDetector, notificationServerUrl, noticeDeleter, notificationDiagnosticObserverForTests;
|
|
74909
75095
|
var init_send_session_notification = __esm(async () => {
|
|
74910
75096
|
init_logger();
|
|
75097
|
+
init_safe_notification_target();
|
|
74911
75098
|
await init_read_session_db();
|
|
74912
75099
|
queuedIgnoredNotifications = new Map;
|
|
74913
75100
|
flushingIgnoredNotifications = new Set;
|
|
@@ -75052,6 +75239,74 @@ var init_storage_user_memory = __esm(() => {
|
|
|
75052
75239
|
USER_MEMORY_CANDIDATE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
75053
75240
|
});
|
|
75054
75241
|
|
|
75242
|
+
// src/shared/assistant-message-extractor.ts
|
|
75243
|
+
function asSessionMessage(value) {
|
|
75244
|
+
if (!isRecord3(value))
|
|
75245
|
+
return null;
|
|
75246
|
+
const info = value.info;
|
|
75247
|
+
const parts = value.parts;
|
|
75248
|
+
return {
|
|
75249
|
+
info: isRecord3(info) ? {
|
|
75250
|
+
role: typeof info.role === "string" ? info.role : undefined,
|
|
75251
|
+
time: isRecord3(info.time) ? {
|
|
75252
|
+
created: typeof info.time.created === "number" ? info.time.created : undefined
|
|
75253
|
+
} : undefined,
|
|
75254
|
+
error: info.error,
|
|
75255
|
+
finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : undefined
|
|
75256
|
+
} : undefined,
|
|
75257
|
+
parts
|
|
75258
|
+
};
|
|
75259
|
+
}
|
|
75260
|
+
function getCreatedTime(message) {
|
|
75261
|
+
return message.info?.time?.created ?? 0;
|
|
75262
|
+
}
|
|
75263
|
+
function getTextParts(message) {
|
|
75264
|
+
if (!Array.isArray(message.parts))
|
|
75265
|
+
return [];
|
|
75266
|
+
return message.parts.filter((part) => isRecord3(part)).map((part) => ({
|
|
75267
|
+
type: typeof part.type === "string" ? part.type : undefined,
|
|
75268
|
+
text: typeof part.text === "string" ? part.text : undefined
|
|
75269
|
+
})).filter((part) => part.type === "text" && Boolean(part.text));
|
|
75270
|
+
}
|
|
75271
|
+
function getLatestAssistantMessage(messages) {
|
|
75272
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
75273
|
+
return null;
|
|
75274
|
+
return messages.map(asSessionMessage).filter((message) => message !== null).filter((message) => message.info?.role === "assistant").sort((a, b) => getCreatedTime(b) - getCreatedTime(a))[0] ?? null;
|
|
75275
|
+
}
|
|
75276
|
+
function extractLatestAssistantText(messages) {
|
|
75277
|
+
const latest = getLatestAssistantMessage(messages);
|
|
75278
|
+
if (!latest)
|
|
75279
|
+
return null;
|
|
75280
|
+
return getTextParts(latest).map((part) => part.text).join(`
|
|
75281
|
+
`) || null;
|
|
75282
|
+
}
|
|
75283
|
+
function extractLatestAssistantFailure(messages) {
|
|
75284
|
+
const latest = getLatestAssistantMessage(messages);
|
|
75285
|
+
if (!latest || latest.info?.error === undefined || latest.info.error === null)
|
|
75286
|
+
return null;
|
|
75287
|
+
return {
|
|
75288
|
+
error: latest.info.error,
|
|
75289
|
+
finish: latest.info.finish ?? null
|
|
75290
|
+
};
|
|
75291
|
+
}
|
|
75292
|
+
function hasLengthCappedOutput(value) {
|
|
75293
|
+
if (Array.isArray(value))
|
|
75294
|
+
return value.some((item) => hasLengthCappedOutput(item));
|
|
75295
|
+
if (!isRecord3(value))
|
|
75296
|
+
return false;
|
|
75297
|
+
if (value.length_capped === true || value.lengthCapped === true)
|
|
75298
|
+
return true;
|
|
75299
|
+
const finishReason = value.finish_reason ?? value.finishReason ?? value.finish ?? (value.type === "step-finish" ? value.reason : undefined) ?? value.stopReason;
|
|
75300
|
+
if (typeof finishReason === "string") {
|
|
75301
|
+
const normalized = finishReason.toLowerCase();
|
|
75302
|
+
if (normalized === "length" || normalized === "max_tokens" || normalized === "max_output_tokens") {
|
|
75303
|
+
return true;
|
|
75304
|
+
}
|
|
75305
|
+
}
|
|
75306
|
+
return Object.values(value).some((item) => hasLengthCappedOutput(item));
|
|
75307
|
+
}
|
|
75308
|
+
var init_assistant_message_extractor = () => {};
|
|
75309
|
+
|
|
75055
75310
|
// src/shared/resolve-fallbacks.ts
|
|
75056
75311
|
function parseProviderModel(spec) {
|
|
75057
75312
|
const slash = spec.indexOf("/");
|
|
@@ -75343,6 +75598,17 @@ async function attemptAndValidate(client, args, timeoutMs, signal, callContext,
|
|
|
75343
75598
|
};
|
|
75344
75599
|
}
|
|
75345
75600
|
try {
|
|
75601
|
+
if (!extractLatestAssistantText(output)) {
|
|
75602
|
+
const assistantFailure = extractLatestAssistantFailure(output);
|
|
75603
|
+
if (assistantFailure) {
|
|
75604
|
+
const error = new Error(`Host recorded assistant error: ${String(assistantFailure.error)}`);
|
|
75605
|
+
Object.assign(error, {
|
|
75606
|
+
name: "DreamerProviderOutputFailureError",
|
|
75607
|
+
transient: true
|
|
75608
|
+
});
|
|
75609
|
+
throw error;
|
|
75610
|
+
}
|
|
75611
|
+
}
|
|
75346
75612
|
const validated = await options.validateOutput(output, attempt);
|
|
75347
75613
|
return { output, validated, attempt };
|
|
75348
75614
|
} catch (error) {
|
|
@@ -75429,6 +75695,7 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
|
|
|
75429
75695
|
var ABORT_CALL_TIMEOUT_MS = 3000, promptFailureDetails;
|
|
75430
75696
|
var init_model_suggestion_retry = __esm(() => {
|
|
75431
75697
|
init_overflow_detection();
|
|
75698
|
+
init_assistant_message_extractor();
|
|
75432
75699
|
init_logger();
|
|
75433
75700
|
init_redaction();
|
|
75434
75701
|
promptFailureDetails = new WeakMap;
|
|
@@ -75463,14 +75730,14 @@ var CTX_REDUCE_LIGHT_DESCRIPTION = `Stamp an item as no longer needed for the wo
|
|
|
75463
75730
|
|
|
75464
75731
|
// src/shared/prompt-surface-runtime.ts
|
|
75465
75732
|
import { existsSync as existsSync12, readFileSync as readFileSync12, statSync as statSync12 } from "node:fs";
|
|
75466
|
-
import { dirname as dirname8, isAbsolute as isAbsolute5, resolve as
|
|
75733
|
+
import { dirname as dirname8, isAbsolute as isAbsolute5, resolve as resolve6 } from "node:path";
|
|
75467
75734
|
function promptSurfaceHashMaterial(systemContent, preset = "full") {
|
|
75468
75735
|
return preset === "full" ? systemContent : `${systemContent}
|
|
75469
75736
|
\x00magic-context-prompt-surface:${preset}`;
|
|
75470
75737
|
}
|
|
75471
75738
|
function resolveUserConfigDirectory(options) {
|
|
75472
75739
|
if (options.userConfigDirectory)
|
|
75473
|
-
return
|
|
75740
|
+
return resolve6(options.userConfigDirectory);
|
|
75474
75741
|
const sharedBase = cortexKitUserConfigBasePath();
|
|
75475
75742
|
const shared = detectConfigFile(sharedBase);
|
|
75476
75743
|
if (shared.format !== "none")
|
|
@@ -75497,7 +75764,7 @@ function createPromptSurfaceRuntime(options) {
|
|
|
75497
75764
|
const readGuidanceOverride = (configuredPath) => {
|
|
75498
75765
|
if (!configuredPath)
|
|
75499
75766
|
return;
|
|
75500
|
-
const path = isAbsolute5(configuredPath) ? configuredPath :
|
|
75767
|
+
const path = isAbsolute5(configuredPath) ? configuredPath : resolve6(userConfigDirectory, configuredPath);
|
|
75501
75768
|
let content;
|
|
75502
75769
|
try {
|
|
75503
75770
|
if (!statSync12(path).isFile()) {
|
|
@@ -75647,6 +75914,11 @@ var init_user_facing_codes = __esm(() => {
|
|
|
75647
75914
|
sentence: "Some finished background sessions could not be removed from this host.",
|
|
75648
75915
|
action: "They are removed automatically the next time Magic Context runs inside a registered OpenCode service."
|
|
75649
75916
|
},
|
|
75917
|
+
historian_saved_history_misaligned: {
|
|
75918
|
+
code: "MC-H03",
|
|
75919
|
+
sentence: "History compression is paused because this session's saved summaries no longer line up with its messages.",
|
|
75920
|
+
action: "Run /ctx-recomp to rebuild them."
|
|
75921
|
+
},
|
|
75650
75922
|
recomp_unavailable: {
|
|
75651
75923
|
code: "MC-R01",
|
|
75652
75924
|
sentence: "History compression could not be rebuilt.",
|
|
@@ -75817,6 +76089,11 @@ var init_user_facing_codes = __esm(() => {
|
|
|
75817
76089
|
sentence: "History compression is paused while the engine syncs.",
|
|
75818
76090
|
action: "Retry in a moment."
|
|
75819
76091
|
},
|
|
76092
|
+
history_compression_needs_message: {
|
|
76093
|
+
code: "MC-C12",
|
|
76094
|
+
sentence: "History compression has not seen this session since Magic Context reconnected.",
|
|
76095
|
+
action: "Send a message in this session first, then run /ctx-wrapup again."
|
|
76096
|
+
},
|
|
75820
76097
|
context_service_unavailable: {
|
|
75821
76098
|
code: "MC-C10",
|
|
75822
76099
|
sentence: "Magic Context is temporarily unavailable.",
|
|
@@ -77636,74 +77913,6 @@ var init_subagent_token_capture = __esm(() => {
|
|
|
77636
77913
|
init_logger();
|
|
77637
77914
|
});
|
|
77638
77915
|
|
|
77639
|
-
// src/shared/assistant-message-extractor.ts
|
|
77640
|
-
function asSessionMessage(value) {
|
|
77641
|
-
if (!isRecord3(value))
|
|
77642
|
-
return null;
|
|
77643
|
-
const info = value.info;
|
|
77644
|
-
const parts = value.parts;
|
|
77645
|
-
return {
|
|
77646
|
-
info: isRecord3(info) ? {
|
|
77647
|
-
role: typeof info.role === "string" ? info.role : undefined,
|
|
77648
|
-
time: isRecord3(info.time) ? {
|
|
77649
|
-
created: typeof info.time.created === "number" ? info.time.created : undefined
|
|
77650
|
-
} : undefined,
|
|
77651
|
-
error: info.error,
|
|
77652
|
-
finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : undefined
|
|
77653
|
-
} : undefined,
|
|
77654
|
-
parts
|
|
77655
|
-
};
|
|
77656
|
-
}
|
|
77657
|
-
function getCreatedTime(message) {
|
|
77658
|
-
return message.info?.time?.created ?? 0;
|
|
77659
|
-
}
|
|
77660
|
-
function getTextParts(message) {
|
|
77661
|
-
if (!Array.isArray(message.parts))
|
|
77662
|
-
return [];
|
|
77663
|
-
return message.parts.filter((part) => isRecord3(part)).map((part) => ({
|
|
77664
|
-
type: typeof part.type === "string" ? part.type : undefined,
|
|
77665
|
-
text: typeof part.text === "string" ? part.text : undefined
|
|
77666
|
-
})).filter((part) => part.type === "text" && Boolean(part.text));
|
|
77667
|
-
}
|
|
77668
|
-
function getLatestAssistantMessage(messages) {
|
|
77669
|
-
if (!Array.isArray(messages) || messages.length === 0)
|
|
77670
|
-
return null;
|
|
77671
|
-
return messages.map(asSessionMessage).filter((message) => message !== null).filter((message) => message.info?.role === "assistant").sort((a, b) => getCreatedTime(b) - getCreatedTime(a))[0] ?? null;
|
|
77672
|
-
}
|
|
77673
|
-
function extractLatestAssistantText(messages) {
|
|
77674
|
-
const latest = getLatestAssistantMessage(messages);
|
|
77675
|
-
if (!latest)
|
|
77676
|
-
return null;
|
|
77677
|
-
return getTextParts(latest).map((part) => part.text).join(`
|
|
77678
|
-
`) || null;
|
|
77679
|
-
}
|
|
77680
|
-
function extractLatestAssistantFailure(messages) {
|
|
77681
|
-
const latest = getLatestAssistantMessage(messages);
|
|
77682
|
-
if (!latest || latest.info?.error === undefined || latest.info.error === null)
|
|
77683
|
-
return null;
|
|
77684
|
-
return {
|
|
77685
|
-
error: latest.info.error,
|
|
77686
|
-
finish: latest.info.finish ?? null
|
|
77687
|
-
};
|
|
77688
|
-
}
|
|
77689
|
-
function hasLengthCappedOutput(value) {
|
|
77690
|
-
if (Array.isArray(value))
|
|
77691
|
-
return value.some((item) => hasLengthCappedOutput(item));
|
|
77692
|
-
if (!isRecord3(value))
|
|
77693
|
-
return false;
|
|
77694
|
-
if (value.length_capped === true || value.lengthCapped === true)
|
|
77695
|
-
return true;
|
|
77696
|
-
const finishReason = value.finish_reason ?? value.finishReason ?? value.finish ?? (value.type === "step-finish" ? value.reason : undefined) ?? value.stopReason;
|
|
77697
|
-
if (typeof finishReason === "string") {
|
|
77698
|
-
const normalized = finishReason.toLowerCase();
|
|
77699
|
-
if (normalized === "length" || normalized === "max_tokens" || normalized === "max_output_tokens") {
|
|
77700
|
-
return true;
|
|
77701
|
-
}
|
|
77702
|
-
}
|
|
77703
|
-
return Object.values(value).some((item) => hasLengthCappedOutput(item));
|
|
77704
|
-
}
|
|
77705
|
-
var init_assistant_message_extractor = () => {};
|
|
77706
|
-
|
|
77707
77916
|
// src/shared/keep-subagents.ts
|
|
77708
77917
|
function shouldKeepSubagents() {
|
|
77709
77918
|
return keepSubagents;
|
|
@@ -78014,6 +78223,14 @@ function buildHistorianFailureNotice(failureCount, _lastError) {
|
|
|
78014
78223
|
return [heading, "", renderUserFacingFailure("historian_unavailable")].join(`
|
|
78015
78224
|
`);
|
|
78016
78225
|
}
|
|
78226
|
+
function buildStoredCompartmentsInvalidNotice() {
|
|
78227
|
+
return [
|
|
78228
|
+
"## Magic Context — History compression",
|
|
78229
|
+
"",
|
|
78230
|
+
renderUserFacingFailure("historian_saved_history_misaligned")
|
|
78231
|
+
].join(`
|
|
78232
|
+
`);
|
|
78233
|
+
}
|
|
78017
78234
|
function buildHistorianRepairPrompt(originalPrompt, previousOutput, validationError, language) {
|
|
78018
78235
|
const prompt = [
|
|
78019
78236
|
originalPrompt,
|
|
@@ -84697,6 +84914,12 @@ function v2NonNarrativeStoredGapRanges(db, sessionId, compartments) {
|
|
|
84697
84914
|
}
|
|
84698
84915
|
return safeRanges;
|
|
84699
84916
|
}
|
|
84917
|
+
function storedCompartmentFailureBackingOff(db, sessionId, validationError, now = Date.now()) {
|
|
84918
|
+
if (getHistorianFailureState(db, sessionId).lastError !== validationError)
|
|
84919
|
+
return false;
|
|
84920
|
+
const failedAt = loadProtectedTailMeta(db, sessionId).historianDrainFailureAt;
|
|
84921
|
+
return failedAt > 0 && failedAt <= now && now - failedAt < STORED_COMPARTMENT_FAILURE_BACKOFF_MS;
|
|
84922
|
+
}
|
|
84700
84923
|
function shouldSuppressHistorianAlert(sessionId) {
|
|
84701
84924
|
const lastAlert = lastHistorianAlertBySession.get(sessionId);
|
|
84702
84925
|
if (lastAlert && Date.now() - lastAlert < HISTORIAN_ALERT_COOLDOWN_MS) {
|
|
@@ -84819,13 +85042,37 @@ async function runCompartmentAgent(deps) {
|
|
|
84819
85042
|
}
|
|
84820
85043
|
return;
|
|
84821
85044
|
}
|
|
84822
|
-
|
|
84823
|
-
|
|
85045
|
+
let priorCompartments = getCompartments(db, sessionId);
|
|
85046
|
+
let existingValidationError = validateStoredCompartments(priorCompartments, v2NonNarrativeStoredGapRanges(db, sessionId, priorCompartments));
|
|
85047
|
+
const unresolvedInvolved = existingValidationError !== null && priorCompartments.some((compartment) => compartment.rebaseStatus === "unresolved");
|
|
85048
|
+
if (unresolvedInvolved && existingValidationError && storedCompartmentFailureBackingOff(db, sessionId, existingValidationError)) {
|
|
85049
|
+
sessionLog(sessionId, `historian no-op: stored compartments still invalid ("${existingValidationError}"); backing off`);
|
|
85050
|
+
telemetry.status = "noop";
|
|
85051
|
+
telemetry.failureReason = `existing-validation backoff: ${existingValidationError}`;
|
|
85052
|
+
return;
|
|
85053
|
+
}
|
|
85054
|
+
if (unresolvedInvolved && existingValidationError) {
|
|
85055
|
+
const recovery = recoverUnresolvedCompartments({
|
|
85056
|
+
db,
|
|
85057
|
+
sessionId,
|
|
85058
|
+
resolveOrdinal: (messageId) => readRawSessionMessageOrdinalById(sessionId, messageId) ?? undefined,
|
|
85059
|
+
reason: `historian pre-run check failed: ${existingValidationError}`
|
|
85060
|
+
});
|
|
85061
|
+
if (recovery.rowsRewritten > 0) {
|
|
85062
|
+
priorCompartments = getCompartments(db, sessionId);
|
|
85063
|
+
existingValidationError = validateStoredCompartments(priorCompartments, v2NonNarrativeStoredGapRanges(db, sessionId, priorCompartments));
|
|
85064
|
+
}
|
|
85065
|
+
}
|
|
84824
85066
|
if (existingValidationError) {
|
|
84825
85067
|
sessionLog(sessionId, `historian failure: source=existing-validation reason="${existingValidationError}"`);
|
|
84826
85068
|
const failCount = incrementHistorianFailure(db, sessionId, existingValidationError);
|
|
84827
85069
|
telemetry.failureReason = `existing-validation: ${existingValidationError}`;
|
|
84828
|
-
|
|
85070
|
+
if (unresolvedInvolved) {
|
|
85071
|
+
retainDrainReservationForRetryThrottle = true;
|
|
85072
|
+
await notifyHistorianIssue(buildStoredCompartmentsInvalidNotice());
|
|
85073
|
+
} else {
|
|
85074
|
+
await notifyHistorianIssue(buildHistorianFailureNotice(failCount, existingValidationError));
|
|
85075
|
+
}
|
|
84829
85076
|
return;
|
|
84830
85077
|
}
|
|
84831
85078
|
const offset = priorCompartments.length > 0 ? priorCompartments[priorCompartments.length - 1].endMessage + 1 : 1;
|
|
@@ -85308,7 +85555,7 @@ ${chunkText}`,
|
|
|
85308
85555
|
cleanupHistorianStateFile(stateFilePath);
|
|
85309
85556
|
}
|
|
85310
85557
|
}
|
|
85311
|
-
var inconsistentProducerWindows, HISTORIAN_ALERT_COOLDOWN_MS, lastHistorianAlertBySession;
|
|
85558
|
+
var inconsistentProducerWindows, HISTORIAN_ALERT_COOLDOWN_MS, lastHistorianAlertBySession, STORED_COMPARTMENT_FAILURE_BACKOFF_MS;
|
|
85312
85559
|
var init_compartment_runner_incremental = __esm(async () => {
|
|
85313
85560
|
init_compartment_embedding();
|
|
85314
85561
|
init_compartment_events();
|
|
@@ -85351,6 +85598,7 @@ var init_compartment_runner_incremental = __esm(async () => {
|
|
|
85351
85598
|
inconsistentProducerWindows = new Set;
|
|
85352
85599
|
HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
|
|
85353
85600
|
lastHistorianAlertBySession = new Map;
|
|
85601
|
+
STORED_COMPARTMENT_FAILURE_BACKOFF_MS = 30 * 60 * 1000;
|
|
85354
85602
|
});
|
|
85355
85603
|
|
|
85356
85604
|
// src/hooks/magic-context/compartment-runner-recomp.ts
|
|
@@ -106952,6 +107200,8 @@ var TODOWRITE_TOOL = "todowrite";
|
|
|
106952
107200
|
var availabilityBySession = new BoundedSessionMap(1000);
|
|
106953
107201
|
var permissionDeniedBySession = new BoundedSessionMap(2000);
|
|
106954
107202
|
var ctxReducePermissionDenyLogged = new BoundedSessionMap(1000);
|
|
107203
|
+
var ctxReduceSpawnPermissionDenied = new BoundedSessionMap(1000);
|
|
107204
|
+
var ctxReduceSpawnPermissionReads = new Map;
|
|
106955
107205
|
function permissionCacheKey(toolName, sessionId) {
|
|
106956
107206
|
return `${toolName}\x00${sessionId}`;
|
|
106957
107207
|
}
|
|
@@ -106970,6 +107220,12 @@ function verdictFromToolsMap(tools, toolName) {
|
|
|
106970
107220
|
return false;
|
|
106971
107221
|
return null;
|
|
106972
107222
|
}
|
|
107223
|
+
function unfrozenVerdict(sessionId, toolName, mapVerdict) {
|
|
107224
|
+
if (toolName === CTX_REDUCE_TOOL && ctxReduceSpawnPermissionDenied.get(sessionId) === true) {
|
|
107225
|
+
return false;
|
|
107226
|
+
}
|
|
107227
|
+
return mapVerdict ?? true;
|
|
107228
|
+
}
|
|
106973
107229
|
function resolveToolAvailabilityFromMessages(sessionId, toolName, messages) {
|
|
106974
107230
|
if (toolName === CTX_REDUCE_TOOL && !ctxReduceRegisteredGlobally) {
|
|
106975
107231
|
return { callable: false, frozen: true };
|
|
@@ -106981,7 +107237,7 @@ function resolveToolAvailabilityFromMessages(sessionId, toolName, messages) {
|
|
|
106981
107237
|
for (const message of messages) {
|
|
106982
107238
|
if (message.info?.role !== "user")
|
|
106983
107239
|
continue;
|
|
106984
|
-
const verdict = verdictFromToolsMap(message.info.tools, toolName)
|
|
107240
|
+
const verdict = unfrozenVerdict(sessionId, toolName, verdictFromToolsMap(message.info.tools, toolName));
|
|
106985
107241
|
availabilityBySession.set(key, verdict);
|
|
106986
107242
|
return { callable: verdict, frozen: true };
|
|
106987
107243
|
}
|
|
@@ -107004,7 +107260,7 @@ function resolveToolAvailability(sessionId, toolName) {
|
|
|
107004
107260
|
if (!row)
|
|
107005
107261
|
return { callable: true, frozen: false };
|
|
107006
107262
|
const verdict = row.tools === null ? null : verdictFromToolsMap(JSON.parse(row.tools), toolName);
|
|
107007
|
-
const resolved =
|
|
107263
|
+
const resolved = unfrozenVerdict(sessionId, toolName, verdict);
|
|
107008
107264
|
availabilityBySession.set(key, resolved);
|
|
107009
107265
|
return { callable: resolved, frozen: true };
|
|
107010
107266
|
} catch (error) {
|
|
@@ -107120,6 +107376,58 @@ async function resolveToolPermissionDenied(client, sessionId, toolName, activeAg
|
|
|
107120
107376
|
permissionDeniedBySession.set(permissionCacheKey(toolName, sessionId), denied);
|
|
107121
107377
|
return denied;
|
|
107122
107378
|
}
|
|
107379
|
+
function primeCtxReduceSpawnPermission(client, sessionId, spawnAgent) {
|
|
107380
|
+
if (!ctxReduceSpawnPermissionReadNeeded(sessionId))
|
|
107381
|
+
return Promise.resolve();
|
|
107382
|
+
const inFlight = ctxReduceSpawnPermissionReads.get(sessionId);
|
|
107383
|
+
if (inFlight)
|
|
107384
|
+
return inFlight;
|
|
107385
|
+
const read = (async () => {
|
|
107386
|
+
try {
|
|
107387
|
+
const denied = await resolveToolPermissionDenied(client, sessionId, CTX_REDUCE_TOOL, spawnAgent);
|
|
107388
|
+
ctxReduceSpawnPermissionDenied.set(sessionId, denied);
|
|
107389
|
+
if (denied) {
|
|
107390
|
+
sessionLog(sessionId, `ctx_reduce permission is denied for agent=${spawnAgent ?? "(session default)"}; session freezes without ctx_reduce tags, guidance, or nudges`);
|
|
107391
|
+
}
|
|
107392
|
+
} catch (error) {
|
|
107393
|
+
sessionLog(sessionId, "ctx_reduce permission read before freeze failed (fail-open):", error);
|
|
107394
|
+
} finally {
|
|
107395
|
+
ctxReduceSpawnPermissionReads.delete(sessionId);
|
|
107396
|
+
}
|
|
107397
|
+
})();
|
|
107398
|
+
ctxReduceSpawnPermissionReads.set(sessionId, read);
|
|
107399
|
+
return read;
|
|
107400
|
+
}
|
|
107401
|
+
function ctxReduceSpawnPermissionReadNeeded(sessionId) {
|
|
107402
|
+
return ctxReduceRegisteredGlobally && availabilityBySession.get(cacheKey2(CTX_REDUCE_TOOL, sessionId)) === undefined && ctxReduceSpawnPermissionDenied.get(sessionId) === undefined;
|
|
107403
|
+
}
|
|
107404
|
+
function spawnAgentFromMessages(messages) {
|
|
107405
|
+
for (const message of messages) {
|
|
107406
|
+
if (message.info?.role !== "user")
|
|
107407
|
+
continue;
|
|
107408
|
+
const agent = message.info.agent;
|
|
107409
|
+
return typeof agent === "string" && agent.length > 0 ? agent : undefined;
|
|
107410
|
+
}
|
|
107411
|
+
return;
|
|
107412
|
+
}
|
|
107413
|
+
function spawnAgentFromOpenCodeDb(sessionId) {
|
|
107414
|
+
if (!openCodeDbExists())
|
|
107415
|
+
return { persisted: false };
|
|
107416
|
+
try {
|
|
107417
|
+
const row = withReadOnlySessionDb((db) => db.prepare(`SELECT json_extract(data, '$.agent') AS agent FROM message
|
|
107418
|
+
WHERE session_id = ? AND json_extract(data, '$.role') = 'user'
|
|
107419
|
+
ORDER BY time_created ASC LIMIT 1`).get(sessionId));
|
|
107420
|
+
if (!row)
|
|
107421
|
+
return { persisted: false };
|
|
107422
|
+
return {
|
|
107423
|
+
persisted: true,
|
|
107424
|
+
agent: typeof row.agent === "string" && row.agent.length > 0 ? row.agent : undefined
|
|
107425
|
+
};
|
|
107426
|
+
} catch (error) {
|
|
107427
|
+
sessionLog(sessionId, "ctx_reduce spawn agent read failed:", error);
|
|
107428
|
+
return { persisted: false };
|
|
107429
|
+
}
|
|
107430
|
+
}
|
|
107123
107431
|
function todowritePermissionDenied(client, sessionId, activeAgent) {
|
|
107124
107432
|
return resolveToolPermissionDenied(client, sessionId, TODOWRITE_TOOL, activeAgent);
|
|
107125
107433
|
}
|
|
@@ -108022,9 +108330,26 @@ init_window_geometry();
|
|
|
108022
108330
|
init_compartment_storage();
|
|
108023
108331
|
init_session_decision_calibration();
|
|
108024
108332
|
init_logger();
|
|
108333
|
+
await init_storage();
|
|
108334
|
+
|
|
108335
|
+
// src/hooks/magic-context/cache-busting-signals.ts
|
|
108336
|
+
function canConsumeDeferredOnThisPass(args) {
|
|
108337
|
+
if (args.justAwaitedPublication)
|
|
108338
|
+
return true;
|
|
108339
|
+
return args.schedulerDecision === "execute" || args.contextPercentage >= (args.forceMaterializationPercentage ?? escalationBands(65).forceMaterializationPercentage);
|
|
108340
|
+
}
|
|
108341
|
+
function hasReclaimRide(signals) {
|
|
108342
|
+
return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory;
|
|
108343
|
+
}
|
|
108344
|
+
var RECLAIM_RIDE_NAMES = ["hardFold", "force", "explicitFlush", "publishedHistory"];
|
|
108345
|
+
function reclaimRideLabel(signals) {
|
|
108346
|
+
const active = RECLAIM_RIDE_NAMES.filter((name) => signals[name]);
|
|
108347
|
+
return `ride=${active.length > 0 ? active.join("+") : "none"}`;
|
|
108348
|
+
}
|
|
108349
|
+
|
|
108350
|
+
// src/hooks/magic-context/compartment-trigger.ts
|
|
108025
108351
|
init_read_session_true_raw_tokens();
|
|
108026
108352
|
await __promiseAll([
|
|
108027
|
-
init_storage(),
|
|
108028
108353
|
init_protected_tail_boundary(),
|
|
108029
108354
|
init_read_session_chunk()
|
|
108030
108355
|
]);
|
|
@@ -108204,7 +108529,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
|
|
|
108204
108529
|
function formatProjectedPostDropPercentage(value) {
|
|
108205
108530
|
return value === null ? "none" : `${value.toFixed(1)}%`;
|
|
108206
108531
|
}
|
|
108207
|
-
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection) {
|
|
108532
|
+
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection, reclaimRide) {
|
|
108208
108533
|
if (sessionMeta.compartmentInProgress) {
|
|
108209
108534
|
sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
|
|
108210
108535
|
return { shouldFire: false };
|
|
@@ -108262,10 +108587,12 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
108262
108587
|
const canClearReasoning = reasoningProjection?.canClearReasoning ?? modelAcceptsEmptyContent(reasoningProjection?.providerID);
|
|
108263
108588
|
const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession(db, sessionId), clearReasoningAge, sessionMeta.clearedReasoningThroughTag, canClearReasoning);
|
|
108264
108589
|
const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
|
|
108590
|
+
const rideLabel = reclaimRide ? reclaimRideLabel(reclaimRide) : "ride=none";
|
|
108591
|
+
const dropsCanLand = reclaimRide !== undefined && hasReclaimRide(reclaimRide);
|
|
108265
108592
|
const forceMaterializationPercentage = escalationBands(executeThresholdPercentage).forceMaterializationPercentage;
|
|
108266
108593
|
if (usage.percentage >= forceMaterializationPercentage) {
|
|
108267
|
-
if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
|
|
108268
|
-
sessionLog(sessionId, `historian redundancy skip: summarizer not needed this pass — force band is ${forceMaterializationPercentage}%; queued/automatic drops are projected to reclaim to ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%) on
|
|
108594
|
+
if (dropsCanLand && projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
|
|
108595
|
+
sessionLog(sessionId, `historian redundancy skip: summarizer not needed this pass — force band is ${forceMaterializationPercentage}%; queued/automatic drops are projected to reclaim to ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%) on this pass (${rideLabel})`);
|
|
108269
108596
|
return { shouldFire: false };
|
|
108270
108597
|
}
|
|
108271
108598
|
sessionLog(sessionId, `compartment trigger: force-firing at ${usage.percentage.toFixed(1)}% (projected post-drop ${formatProjectedPostDropPercentage(projectedPostDropPercentage)})`);
|
|
@@ -108325,8 +108652,8 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
108325
108652
|
sessionLog(sessionId, `compartment trigger: not firing at ${usage.percentage.toFixed(1)}% — below proactive floor (${proactiveTriggerPercentage}%)`);
|
|
108326
108653
|
return { shouldFire: false };
|
|
108327
108654
|
}
|
|
108328
|
-
if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
|
|
108329
|
-
sessionLog(sessionId, `historian redundancy skip: summarizer not needed this pass — usage is ${usage.percentage.toFixed(1)}%; queued/automatic drops are projected to reclaim to ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%) on
|
|
108655
|
+
if (dropsCanLand && projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
|
|
108656
|
+
sessionLog(sessionId, `historian redundancy skip: summarizer not needed this pass — usage is ${usage.percentage.toFixed(1)}%; queued/automatic drops are projected to reclaim to ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%) on this pass (${rideLabel})`);
|
|
108330
108657
|
return { shouldFire: false };
|
|
108331
108658
|
}
|
|
108332
108659
|
if (!tailInfo.hasProtectedEligibleHead || !tailInfo.isMeaningful) {
|
|
@@ -108869,6 +109196,12 @@ function createSystemPromptHashHandler(deps) {
|
|
|
108869
109196
|
sessionLog(sessionId, "system-prompt-hash session meta load failed:", error);
|
|
108870
109197
|
}
|
|
108871
109198
|
const isSubagentSession = sessionMetaEarly?.isSubagent === true;
|
|
109199
|
+
if (deps.client && ctxReduceSpawnPermissionReadNeeded(sessionId)) {
|
|
109200
|
+
const spawn = spawnAgentFromOpenCodeDb(sessionId);
|
|
109201
|
+
if (spawn.persisted) {
|
|
109202
|
+
await primeCtxReduceSpawnPermission(deps.client, sessionId, spawn.agent);
|
|
109203
|
+
}
|
|
109204
|
+
}
|
|
108872
109205
|
const availability = resolveCtxReduceAvailability(sessionId);
|
|
108873
109206
|
const ctxReduceCallable = availability.callable;
|
|
108874
109207
|
const subagentReduceMode = isSubagentSession && ctxReduceCallable;
|
|
@@ -109081,21 +109414,6 @@ init_harness_provider_map();
|
|
|
109081
109414
|
init_logger();
|
|
109082
109415
|
init_models_dev_cache();
|
|
109083
109416
|
|
|
109084
|
-
// src/hooks/magic-context/cache-busting-signals.ts
|
|
109085
|
-
function canConsumeDeferredOnThisPass(args) {
|
|
109086
|
-
if (args.justAwaitedPublication)
|
|
109087
|
-
return true;
|
|
109088
|
-
return args.schedulerDecision === "execute" || args.contextPercentage >= (args.forceMaterializationPercentage ?? escalationBands(65).forceMaterializationPercentage);
|
|
109089
|
-
}
|
|
109090
|
-
function hasReclaimRide(signals) {
|
|
109091
|
-
return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory;
|
|
109092
|
-
}
|
|
109093
|
-
var RECLAIM_RIDE_NAMES = ["hardFold", "force", "explicitFlush", "publishedHistory"];
|
|
109094
|
-
function reclaimRideLabel(signals) {
|
|
109095
|
-
const active = RECLAIM_RIDE_NAMES.filter((name) => signals[name]);
|
|
109096
|
-
return `ride=${active.length > 0 ? active.join("+") : "none"}`;
|
|
109097
|
-
}
|
|
109098
|
-
|
|
109099
109417
|
// src/hooks/magic-context/caveman-cleanup.ts
|
|
109100
109418
|
init_shared();
|
|
109101
109419
|
await init_storage();
|
|
@@ -115888,7 +116206,7 @@ function rustCaptureDigests(inputs, prior, acceptedInputs) {
|
|
|
115888
116206
|
}
|
|
115889
116207
|
function messageMatchesContentSnapshot(message, snapshot) {
|
|
115890
116208
|
let fieldIndex = 0;
|
|
115891
|
-
const matched = visitMessageContentFields(message, {
|
|
116209
|
+
const matched = visitMessageContentFields(contentSnapshotValue(message), {
|
|
115892
116210
|
field(value) {
|
|
115893
116211
|
if (!Object.is(value, snapshot.fields[fieldIndex]))
|
|
115894
116212
|
return false;
|
|
@@ -116143,6 +116461,7 @@ function ensureState(states, sessionId) {
|
|
|
116143
116461
|
if (!state) {
|
|
116144
116462
|
state = {
|
|
116145
116463
|
initialized: false,
|
|
116464
|
+
baselineSystemHashOmitted: false,
|
|
116146
116465
|
consecutiveFailures: 0,
|
|
116147
116466
|
passCount: 0,
|
|
116148
116467
|
parked: false,
|
|
@@ -117104,6 +117423,7 @@ function createRustModeTransform(deps, options) {
|
|
|
117104
117423
|
}
|
|
117105
117424
|
}
|
|
117106
117425
|
timings.preflight = performance.now() - passStartedAt;
|
|
117426
|
+
resolveCtxReduceAvailabilityFromMessages(sessionId, messages);
|
|
117107
117427
|
const reduceAvailability = resolveCtxReduceAvailability(sessionId);
|
|
117108
117428
|
resolveTodowriteAvailabilityFromMessages(sessionId, messages);
|
|
117109
117429
|
const todoAvailability = resolveTodowriteAvailability(sessionId);
|
|
@@ -117175,6 +117495,8 @@ function createRustModeTransform(deps, options) {
|
|
|
117175
117495
|
}
|
|
117176
117496
|
const effectiveFloor = protectionFloorResolution.floor;
|
|
117177
117497
|
const historianRun = deps.resolveHistorianRun?.();
|
|
117498
|
+
const observedSystemHash = sessionMeta.systemPromptHash ?? "";
|
|
117499
|
+
const rustSystemHash = state.baselineSystemHashOmitted && sessionMeta.cachedM0SystemHash === observedSystemHash ? "" : observedSystemHash;
|
|
117178
117500
|
const passInputs = {
|
|
117179
117501
|
now_ms: requestObservedAtMs,
|
|
117180
117502
|
model_key: modelKey,
|
|
@@ -117196,7 +117518,7 @@ function createRustModeTransform(deps, options) {
|
|
|
117196
117518
|
caveman_min_chars: deps.cavemanTextCompression?.minChars ?? 500,
|
|
117197
117519
|
cache_ttl: sessionMeta.cacheTtl,
|
|
117198
117520
|
is_subagent: sessionMeta.isSubagent,
|
|
117199
|
-
system_prompt_hash:
|
|
117521
|
+
system_prompt_hash: rustSystemHash,
|
|
117200
117522
|
upgrade_state: readUpgradeState(deps.db, sessionId),
|
|
117201
117523
|
tool_present: toolPresent,
|
|
117202
117524
|
todo_tool_present: false,
|
|
@@ -117471,7 +117793,7 @@ function createRustModeTransform(deps, options) {
|
|
|
117471
117793
|
modelKey: modelKey ?? null,
|
|
117472
117794
|
providerId: model?.providerID ?? null,
|
|
117473
117795
|
variant: deps.variantBySession?.get(sessionId),
|
|
117474
|
-
systemPromptHash:
|
|
117796
|
+
systemPromptHash: rustSystemHash,
|
|
117475
117797
|
upgradeState: String(passInputs.upgrade_state ?? "")
|
|
117476
117798
|
};
|
|
117477
117799
|
let body = buildTransformBody({
|
|
@@ -117905,6 +118227,9 @@ function createRustModeTransform(deps, options) {
|
|
|
117905
118227
|
state.ordinalContinuationBase = ordinalContinuationBase;
|
|
117906
118228
|
}
|
|
117907
118229
|
if (!stateSyncRetryBusy) {
|
|
118230
|
+
if (!state.initialized && !observedSystemHash) {
|
|
118231
|
+
state.baselineSystemHashOmitted = true;
|
|
118232
|
+
}
|
|
117908
118233
|
state.initialized = true;
|
|
117909
118234
|
state.seedPassPending = false;
|
|
117910
118235
|
}
|
|
@@ -118701,6 +119026,9 @@ function createTransform(deps) {
|
|
|
118701
119026
|
passOutcome.record("compaction-mode-transition-failure");
|
|
118702
119027
|
sessionLog(sessionId, "compaction mode transition failed (retrying next pass):", error);
|
|
118703
119028
|
}
|
|
119029
|
+
if (deps.client !== undefined && !compactionOff) {
|
|
119030
|
+
await primeCtxReduceSpawnPermission(deps.client, sessionId, spawnAgentFromMessages(messages));
|
|
119031
|
+
}
|
|
118704
119032
|
if (deps.transformMode === "rust") {
|
|
118705
119033
|
if (!rustModeTransform) {
|
|
118706
119034
|
sessionLog(sessionId, "rust transform unavailable; using raw passthrough");
|
|
@@ -119033,7 +119361,12 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
119033
119361
|
const tTrigger = performance.now();
|
|
119034
119362
|
try {
|
|
119035
119363
|
const inMemoryTail = buildTriggerInMemoryTail(db, sessionId, extractInMemoryMessageViews(messages));
|
|
119036
|
-
const triggerResult = checkCompartmentTrigger(db, sessionId, sessionMeta, boundaryUsageForProtectedTail, sessionMeta.lastContextPercentage, boundaryExecuteThreshold, deriveTriggerBudget(boundaryContextLimit, boundaryExecuteThreshold), deps.clearReasoningAge, historianRun?.commitClusterTrigger ?? deps.commitClusterTrigger, undefined, boundaryContextLimit, inMemoryTail, taggerFloor, { providerID: resolvedProviderID }
|
|
119364
|
+
const triggerResult = checkCompartmentTrigger(db, sessionId, sessionMeta, boundaryUsageForProtectedTail, sessionMeta.lastContextPercentage, boundaryExecuteThreshold, deriveTriggerBudget(boundaryContextLimit, boundaryExecuteThreshold), deps.clearReasoningAge, historianRun?.commitClusterTrigger ?? deps.commitClusterTrigger, undefined, boundaryContextLimit, inMemoryTail, taggerFloor, { providerID: resolvedProviderID }, {
|
|
119365
|
+
hardFold: false,
|
|
119366
|
+
force: contextUsageEarly.percentage >= forceMaterializationPercentage && (contextUsageEarly.percentage >= 95 || getEmergencyInputSample(db, sessionId) === 0),
|
|
119367
|
+
explicitFlush: deps.pendingMaterializationSessions.has(sessionId),
|
|
119368
|
+
publishedHistory: isCacheBusting
|
|
119369
|
+
});
|
|
119037
119370
|
if (triggerResult.shouldFire) {
|
|
119038
119371
|
sessionLog(sessionId, `compartment trigger: firing (reason=${triggerResult.reason})`);
|
|
119039
119372
|
updateSessionMeta(db, sessionId, { compartmentInProgress: true });
|
|
@@ -121720,7 +122053,7 @@ import { join as join15 } from "node:path";
|
|
|
121720
122053
|
|
|
121721
122054
|
// src/shared/opencode-config-dir.ts
|
|
121722
122055
|
import { homedir as homedir9 } from "node:os";
|
|
121723
|
-
import { join as join14, resolve as
|
|
122056
|
+
import { join as join14, resolve as resolve7 } from "node:path";
|
|
121724
122057
|
function resolveHomeDir() {
|
|
121725
122058
|
return process.env.HOME?.trim() || homedir9();
|
|
121726
122059
|
}
|
|
@@ -121732,7 +122065,7 @@ function getOpenCodeGlobalConfigDir() {
|
|
|
121732
122065
|
}
|
|
121733
122066
|
function getEnvConfigDir() {
|
|
121734
122067
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
121735
|
-
return envConfigDir ?
|
|
122068
|
+
return envConfigDir ? resolve7(envConfigDir) : undefined;
|
|
121736
122069
|
}
|
|
121737
122070
|
function getOpenCodeConfigDirs() {
|
|
121738
122071
|
const dirs = [getOpenCodeGlobalConfigDir(), join14(resolveHomeDir(), ".opencode")];
|
|
@@ -122771,9 +123104,33 @@ init_tag_content_primitives();
|
|
|
122771
123104
|
var HIDDEN_HISTORIAN_AGENT = "historian";
|
|
122772
123105
|
var HIDDEN_DREAMER_AGENT = "dreamer-classifier";
|
|
122773
123106
|
var HIDDEN_CURATE_AGENT = DREAMER_AGENT;
|
|
123107
|
+
var READ_TOOLS = ["read", "grep", "glob"];
|
|
123108
|
+
var AGENT_TOOLS = {
|
|
123109
|
+
[HIDDEN_HISTORIAN_AGENT]: [],
|
|
123110
|
+
[HIDDEN_DREAMER_AGENT]: [],
|
|
123111
|
+
[HIDDEN_CURATE_AGENT]: ["ctx_memory", "ctx_memory_list"],
|
|
123112
|
+
[DREAMER_MEMORY_MAPPER_AGENT]: READ_TOOLS,
|
|
123113
|
+
[DREAMER_PRIMER_INVESTIGATOR_AGENT]: [...READ_TOOLS, "ctx_search"],
|
|
123114
|
+
[DREAMER_RETROSPECTIVE_AGENT]: ["ctx_search"]
|
|
123115
|
+
};
|
|
123116
|
+
var AGENT_STEPS = {
|
|
123117
|
+
[HIDDEN_CURATE_AGENT]: 150,
|
|
123118
|
+
[DREAMER_MEMORY_MAPPER_AGENT]: 60,
|
|
123119
|
+
[DREAMER_DOCS_AGENT]: 60,
|
|
123120
|
+
[DREAMER_PRIMER_INVESTIGATOR_AGENT]: 40,
|
|
123121
|
+
[DREAMER_RETROSPECTIVE_AGENT]: 40
|
|
123122
|
+
};
|
|
123123
|
+
function hiddenAgentFor(identity) {
|
|
123124
|
+
if (identity.kind === "dreamer-task" && identity.agent === DREAMER_DOCS_AGENT)
|
|
123125
|
+
return DREAMER_MEMORY_MAPPER_AGENT;
|
|
123126
|
+
return identity.kind === "dreamer-task" && AGENT_TOOLS[identity.agent] ? identity.agent : identity.kind === "dreamer-task" ? HIDDEN_DREAMER_AGENT : HIDDEN_HISTORIAN_AGENT;
|
|
123127
|
+
}
|
|
123128
|
+
function hiddenToolLoop(identity) {
|
|
123129
|
+
return identity.kind === "dreamer-task" && AGENT_STEPS[identity.agent] !== undefined;
|
|
123130
|
+
}
|
|
122774
123131
|
async function registerHiddenChildAgents(agent) {
|
|
122775
123132
|
await agent.transform((editor) => {
|
|
122776
|
-
for (const id of
|
|
123133
|
+
for (const id of Object.keys(AGENT_TOOLS)) {
|
|
122777
123134
|
editor.update(id, (config) => {
|
|
122778
123135
|
config.system = "Magic Context hidden completion carrier.";
|
|
122779
123136
|
config.description = "Internal Magic Context hidden completion carrier.";
|
|
@@ -122782,16 +123139,14 @@ async function registerHiddenChildAgents(agent) {
|
|
|
122782
123139
|
config.request.settings = {};
|
|
122783
123140
|
config.request.headers = {};
|
|
122784
123141
|
config.request.body = {};
|
|
123142
|
+
config.steps = AGENT_STEPS[id];
|
|
122785
123143
|
config.permissions = [
|
|
122786
123144
|
{ action: "*", resource: "*", effect: "deny" },
|
|
122787
|
-
...id
|
|
122788
|
-
|
|
122789
|
-
|
|
122790
|
-
|
|
122791
|
-
|
|
122792
|
-
effect: "allow"
|
|
122793
|
-
}
|
|
122794
|
-
] : []
|
|
123145
|
+
...(AGENT_TOOLS[id] ?? []).map((tool) => ({
|
|
123146
|
+
action: tool,
|
|
123147
|
+
resource: "*",
|
|
123148
|
+
effect: "allow"
|
|
123149
|
+
}))
|
|
122795
123150
|
];
|
|
122796
123151
|
});
|
|
122797
123152
|
}
|
|
@@ -122836,15 +123191,21 @@ function calibratedParts(attempt) {
|
|
|
122836
123191
|
class HiddenChildHook {
|
|
122837
123192
|
childIDs = new Set;
|
|
122838
123193
|
attempts = new Map;
|
|
123194
|
+
active = new Map;
|
|
122839
123195
|
registerChild(sessionID) {
|
|
122840
123196
|
this.childIDs.add(sessionID);
|
|
122841
123197
|
}
|
|
122842
123198
|
registerAttempt(marker, attempt) {
|
|
122843
123199
|
this.registerChild(attempt.childSessionId);
|
|
123200
|
+
attempt.marker = marker;
|
|
122844
123201
|
this.attempts.set(marker, attempt);
|
|
122845
123202
|
}
|
|
122846
123203
|
releaseAttempt(marker) {
|
|
123204
|
+
const attempt = this.attempts.get(marker);
|
|
122847
123205
|
this.attempts.delete(marker);
|
|
123206
|
+
if (attempt && this.active.get(attempt.childSessionId) === attempt) {
|
|
123207
|
+
this.active.delete(attempt.childSessionId);
|
|
123208
|
+
}
|
|
122848
123209
|
}
|
|
122849
123210
|
owns(sessionID) {
|
|
122850
123211
|
return this.childIDs.has(sessionID);
|
|
@@ -122855,19 +123216,43 @@ class HiddenChildHook {
|
|
|
122855
123216
|
const raw = newestUserText(draft);
|
|
122856
123217
|
const stripped = raw === undefined ? undefined : stripWellFormedLeadingTagPrefix(raw);
|
|
122857
123218
|
const attempt = (raw !== undefined ? this.attempts.get(raw) : undefined) ?? (stripped && stripped !== raw ? this.attempts.get(stripped) : undefined);
|
|
122858
|
-
|
|
123219
|
+
const current = this.active.get(draft.sessionID);
|
|
123220
|
+
const selected = attempt ?? current;
|
|
123221
|
+
if (!selected || selected.childSessionId !== draft.sessionID || attempt && current && current !== attempt) {
|
|
122859
123222
|
throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Refusing an unregistered prompt on a Magic Context hidden-run session", true);
|
|
122860
123223
|
}
|
|
122861
|
-
if (
|
|
123224
|
+
if (selected.request.signal?.aborted) {
|
|
122862
123225
|
throw new Error("Hidden completion prompt aborted");
|
|
122863
123226
|
}
|
|
122864
|
-
|
|
123227
|
+
if (!selected.shaped) {
|
|
123228
|
+
if (!attempt)
|
|
123229
|
+
throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Hidden child first step requires a registered marker", true);
|
|
123230
|
+
this.active.set(draft.sessionID, selected);
|
|
123231
|
+
}
|
|
123232
|
+
const steps = (selected.steps ?? 0) + 1;
|
|
123233
|
+
const cap = AGENT_STEPS[selected.identity.agent];
|
|
123234
|
+
if (cap !== undefined && steps > cap) {
|
|
123235
|
+
throw new Error(`Hidden agent exceeded its ${cap}-step limit`);
|
|
123236
|
+
}
|
|
123237
|
+
selected.steps = steps;
|
|
123238
|
+
const system = typeof selected.request.body.system === "string" ? selected.request.body.system : selected.identity.system;
|
|
122865
123239
|
draft.system = [{ type: "text", text: system }];
|
|
122866
|
-
|
|
122867
|
-
|
|
122868
|
-
|
|
122869
|
-
|
|
122870
|
-
|
|
123240
|
+
if (!selected.shaped) {
|
|
123241
|
+
draft.messages = [{ role: "user", content: calibratedParts(selected) }];
|
|
123242
|
+
} else {
|
|
123243
|
+
const first = draft.messages[0];
|
|
123244
|
+
const firstText = first && newestUserText({ ...draft, messages: [first] });
|
|
123245
|
+
const normalized = firstText === undefined ? undefined : stripWellFormedLeadingTagPrefix(firstText);
|
|
123246
|
+
if (normalized !== selected.marker) {
|
|
123247
|
+
throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Hidden child history does not begin with this run's registered marker", true);
|
|
123248
|
+
}
|
|
123249
|
+
draft.messages[0] = { ...first, content: calibratedParts(selected) };
|
|
123250
|
+
}
|
|
123251
|
+
draft.options = authoredOptions(selected);
|
|
123252
|
+
const allowed = AGENT_TOOLS[hiddenAgentFor(selected.identity)] ?? [];
|
|
123253
|
+
draft.tools = Object.fromEntries(allowed.flatMap((id) => draft.tools[id] ? [[id, draft.tools[id]]] : []));
|
|
123254
|
+
selected.observedMessages = draft.messages;
|
|
123255
|
+
selected.shaped = true;
|
|
122871
123256
|
return true;
|
|
122872
123257
|
}
|
|
122873
123258
|
}
|
|
@@ -122949,9 +123334,9 @@ function resolveOwnerHostService(owner, env = process.env, pid = process.pid) {
|
|
|
122949
123334
|
}
|
|
122950
123335
|
return own;
|
|
122951
123336
|
}
|
|
122952
|
-
async function removeHostSession(sessionID, owner, env = process.env) {
|
|
123337
|
+
async function removeHostSession(sessionID, owner, env = process.env, fetchSession = fetch) {
|
|
122953
123338
|
const service = resolveOwnerHostService(owner, env);
|
|
122954
|
-
const response = await
|
|
123339
|
+
const response = await fetchSession(`${service.url}/api/session/${encodeURIComponent(sessionID)}`, {
|
|
122955
123340
|
method: "DELETE",
|
|
122956
123341
|
headers: service.headers,
|
|
122957
123342
|
signal: AbortSignal.timeout(60000)
|
|
@@ -123153,6 +123538,37 @@ function settledProviderError(row) {
|
|
|
123153
123538
|
function successfulReusableAssistant(row) {
|
|
123154
123539
|
return row !== undefined && (typeof row.data.finish === "string" || assistantOutcome(row) === "succeeded") && row.data.error === undefined && row.data.tokens !== undefined;
|
|
123155
123540
|
}
|
|
123541
|
+
function toolLoopMessages(attempt) {
|
|
123542
|
+
const messages = attempt.observedMessages ?? [];
|
|
123543
|
+
const results = new Map;
|
|
123544
|
+
for (const message of messages) {
|
|
123545
|
+
if (message.role !== "tool")
|
|
123546
|
+
continue;
|
|
123547
|
+
for (const part of message.content) {
|
|
123548
|
+
if (part.type !== "tool-result" || typeof part.id !== "string")
|
|
123549
|
+
continue;
|
|
123550
|
+
const result = part.result;
|
|
123551
|
+
results.set(part.id, { status: result?.type === "error" ? "error" : "completed" });
|
|
123552
|
+
}
|
|
123553
|
+
}
|
|
123554
|
+
return messages.flatMap((message) => {
|
|
123555
|
+
if (message.role !== "assistant")
|
|
123556
|
+
return [];
|
|
123557
|
+
const parts = message.content.flatMap((part) => {
|
|
123558
|
+
if (part.type !== "tool-call" || typeof part.id !== "string" || typeof part.name !== "string")
|
|
123559
|
+
return [];
|
|
123560
|
+
const result = results.get(part.id);
|
|
123561
|
+
return [
|
|
123562
|
+
{
|
|
123563
|
+
type: "tool",
|
|
123564
|
+
tool: part.name,
|
|
123565
|
+
state: { status: result?.status ?? "pending", input: part.input }
|
|
123566
|
+
}
|
|
123567
|
+
];
|
|
123568
|
+
});
|
|
123569
|
+
return parts.length ? [{ info: { role: "assistant" }, parts }] : [];
|
|
123570
|
+
});
|
|
123571
|
+
}
|
|
123156
123572
|
function assistantText(row) {
|
|
123157
123573
|
const text = (row.data.content ?? []).flatMap((part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []).join("");
|
|
123158
123574
|
return text.length > 0 ? text : null;
|
|
@@ -123404,7 +123820,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
123404
123820
|
}
|
|
123405
123821
|
};
|
|
123406
123822
|
return {
|
|
123407
|
-
capabilities: { tools:
|
|
123823
|
+
capabilities: { tools: true, harness: "opencode2" },
|
|
123408
123824
|
async open(identity) {
|
|
123409
123825
|
const role = roleFor(identity);
|
|
123410
123826
|
const releaseRole = await acquireRole(role);
|
|
@@ -123413,6 +123829,10 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
123413
123829
|
await options.ensureAgent?.();
|
|
123414
123830
|
const head = await resolveHead(identity);
|
|
123415
123831
|
let active = store.read().active[role];
|
|
123832
|
+
if (active && hiddenToolLoop(identity)) {
|
|
123833
|
+
retireChild(active, "fresh-tool-loop-run");
|
|
123834
|
+
active = undefined;
|
|
123835
|
+
}
|
|
123416
123836
|
if (active && active.generation !== generation) {
|
|
123417
123837
|
retireChild(active, "host-generation-changed");
|
|
123418
123838
|
active = undefined;
|
|
@@ -123435,7 +123855,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
123435
123855
|
const title = roleTitle(role);
|
|
123436
123856
|
const created = await host.create({
|
|
123437
123857
|
title,
|
|
123438
|
-
agent: roleAgent(role),
|
|
123858
|
+
agent: hiddenToolLoop(identity) ? hiddenAgentFor(identity) : roleAgent(role),
|
|
123439
123859
|
model: {
|
|
123440
123860
|
providerID: head.providerID,
|
|
123441
123861
|
id: head.modelID,
|
|
@@ -123493,6 +123913,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
123493
123913
|
await switchChildModel(run, requested);
|
|
123494
123914
|
const baseline = withReader(options.openReader, (reader) => reader.latestSequence(run.child.id));
|
|
123495
123915
|
const marker = `mc:hidden:${crypto.randomUUID()}:${crypto.randomUUID()}`;
|
|
123916
|
+
run.completion = undefined;
|
|
123496
123917
|
const attempt = {
|
|
123497
123918
|
childSessionId: run.child.id,
|
|
123498
123919
|
identity: run.identity,
|
|
@@ -123552,6 +123973,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
123552
123973
|
}
|
|
123553
123974
|
run.completion = {
|
|
123554
123975
|
text,
|
|
123976
|
+
...hiddenToolLoop(run.identity) ? { messages: toolLoopMessages(attempt) } : {},
|
|
123555
123977
|
reasoning: null,
|
|
123556
123978
|
usage: reportedInput !== undefined || reportedOutput !== undefined ? {
|
|
123557
123979
|
input: reportedInput ?? 0,
|
|
@@ -123596,7 +124018,9 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
123596
124018
|
return;
|
|
123597
124019
|
try {
|
|
123598
124020
|
const reusable = run.failed && !run.unsettledFailure;
|
|
123599
|
-
if (
|
|
124021
|
+
if (hiddenToolLoop(run.identity)) {
|
|
124022
|
+
retire(run, settlement.promptSettled ? "tool-loop-settled" : "tool-loop-failed");
|
|
124023
|
+
} else if (!run.completion && (run.failed || !settlement.promptSettled) && !reusable) {
|
|
123600
124024
|
retire(run, "hidden-run-failed");
|
|
123601
124025
|
}
|
|
123602
124026
|
} finally {
|
|
@@ -123876,6 +124300,17 @@ class V2StoreReader {
|
|
|
123876
124300
|
range(sessionID, after, through) {
|
|
123877
124301
|
return trackDecodeOperation("range", () => through <= after ? [] : this.all(sessionID, after, undefined, through));
|
|
123878
124302
|
}
|
|
124303
|
+
spanRowStamps(sessionID, after, through) {
|
|
124304
|
+
if (!Number.isSafeInteger(after) || !Number.isSafeInteger(through))
|
|
124305
|
+
throw new Error("Invalid seq span");
|
|
124306
|
+
const rows = this.db.prepare(`SELECT seq, id, time_updated AS updated, length(CAST(data AS BLOB)) AS bytes
|
|
124307
|
+
FROM session_message WHERE session_id = ? AND seq > ? AND seq <= ?
|
|
124308
|
+
ORDER BY seq ASC`).all(sessionID, after, through);
|
|
124309
|
+
const stamps = new Map;
|
|
124310
|
+
for (const row of rows)
|
|
124311
|
+
stamps.set(row.seq, `${row.id}\x00${row.updated ?? ""}\x00${row.bytes ?? ""}`);
|
|
124312
|
+
return stamps;
|
|
124313
|
+
}
|
|
123879
124314
|
rawRowsThrough(sessionID, throughSeq, limit) {
|
|
123880
124315
|
return trackDecodeOperation("rawRowsThrough", () => {
|
|
123881
124316
|
if (!Number.isSafeInteger(throughSeq))
|
|
@@ -125137,13 +125572,13 @@ async function runHiddenSingleShotPrompt(args) {
|
|
|
125137
125572
|
throw new Error(`${args.callContext} returned length-capped output`);
|
|
125138
125573
|
}
|
|
125139
125574
|
const text = completion.text;
|
|
125140
|
-
if (!text)
|
|
125575
|
+
if (!text && !args.allowEmpty)
|
|
125141
125576
|
throw new Error(`${args.callContext} returned no output`);
|
|
125142
|
-
return args.parse(text);
|
|
125577
|
+
return args.parse(text ?? "", completion);
|
|
125143
125578
|
}
|
|
125144
125579
|
});
|
|
125145
125580
|
promptSettled = true;
|
|
125146
|
-
return { validated: run.validated, completion: run.output };
|
|
125581
|
+
return { validated: run.validated, completion: run.output, childSessionId: handle.id };
|
|
125147
125582
|
} finally {
|
|
125148
125583
|
await args.executor.close(handle, {
|
|
125149
125584
|
promptSettled,
|
|
@@ -125891,8 +126326,11 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
125891
126326
|
anchors
|
|
125892
126327
|
});
|
|
125893
126328
|
if (moduleRoute) {
|
|
125894
|
-
const run = await runClassifyThroughModule(args, chunk, anchors, signal);
|
|
125895
|
-
recordInvocation(args, startedAt, {
|
|
126329
|
+
const { accounting, ...run } = await runClassifyThroughModule(args, chunk, anchors, signal);
|
|
126330
|
+
recordInvocation(args, startedAt, {
|
|
126331
|
+
status: "completed",
|
|
126332
|
+
moduleAccounting: accounting
|
|
126333
|
+
});
|
|
125896
126334
|
return run;
|
|
125897
126335
|
}
|
|
125898
126336
|
const executor = resolveHiddenCompletionExecutor(args.hiddenCompletionExecutor, args.client, args.db, args.sessionDirectory, "classify-memories");
|
|
@@ -125994,7 +126432,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
125994
126432
|
task: "classify",
|
|
125995
126433
|
command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash29("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
|
|
125996
126434
|
authority_generation: args.moduleAuthorityGeneration,
|
|
125997
|
-
|
|
126435
|
+
model_chain: resolvedModelChain,
|
|
125998
126436
|
payload: {
|
|
125999
126437
|
prompt_body: prompt,
|
|
126000
126438
|
items: chunk.map((candidate) => ({
|
|
@@ -126015,6 +126453,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
126015
126453
|
if (result.truncated === true) {
|
|
126016
126454
|
throw new Error("classify returned length-capped output");
|
|
126017
126455
|
}
|
|
126456
|
+
const accounting = moduleClassifyAccounting(result);
|
|
126018
126457
|
const parsed = validateClassifyManifest(manifestText, new Set(chunk.map((candidate) => candidate.id)));
|
|
126019
126458
|
const rows = parsed.map((entry) => {
|
|
126020
126459
|
const candidate = chunk.find((item) => item.id === entry.id);
|
|
@@ -126087,7 +126526,39 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
126087
126526
|
throw new Error(`module accepted unknown memory ${moduleId}`);
|
|
126088
126527
|
return candidate.contextMemory.id;
|
|
126089
126528
|
});
|
|
126090
|
-
return {
|
|
126529
|
+
return {
|
|
126530
|
+
classified: acceptedContextIds.length,
|
|
126531
|
+
changed: acceptedContextIds.length,
|
|
126532
|
+
accounting
|
|
126533
|
+
};
|
|
126534
|
+
}
|
|
126535
|
+
function nonNegativeCount(value) {
|
|
126536
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
126537
|
+
}
|
|
126538
|
+
function moduleClassifyAccounting(result) {
|
|
126539
|
+
const accounting = {};
|
|
126540
|
+
const usage = result.usage;
|
|
126541
|
+
if (usage && typeof usage === "object") {
|
|
126542
|
+
const record = usage;
|
|
126543
|
+
accounting.tokens = {
|
|
126544
|
+
input: nonNegativeCount(record.input),
|
|
126545
|
+
output: nonNegativeCount(record.output),
|
|
126546
|
+
cacheRead: nonNegativeCount(record.cache_read),
|
|
126547
|
+
cacheWrite: nonNegativeCount(record.cache_write)
|
|
126548
|
+
};
|
|
126549
|
+
}
|
|
126550
|
+
const diagnostics = result.diagnostics;
|
|
126551
|
+
const model = diagnostics && typeof diagnostics === "object" ? diagnostics.model : undefined;
|
|
126552
|
+
if (typeof model === "string") {
|
|
126553
|
+
const parsed = parseProviderModel(model);
|
|
126554
|
+
if (parsed) {
|
|
126555
|
+
accounting.providerId = parsed.providerID;
|
|
126556
|
+
accounting.modelId = parsed.modelID;
|
|
126557
|
+
} else if (model.trim()) {
|
|
126558
|
+
accounting.modelId = model.trim();
|
|
126559
|
+
}
|
|
126560
|
+
}
|
|
126561
|
+
return accounting;
|
|
126091
126562
|
}
|
|
126092
126563
|
function applyClassifications(args, chunk, manifestText) {
|
|
126093
126564
|
const byId = new Map(chunk.map((m) => [m.id, m]));
|
|
@@ -126132,6 +126603,11 @@ function recordInvocation(args, startedAt, params) {
|
|
|
126132
126603
|
providerId: params.completion.providerId,
|
|
126133
126604
|
modelId: params.completion.modelId
|
|
126134
126605
|
} : {},
|
|
126606
|
+
...params.moduleAccounting ? {
|
|
126607
|
+
tokens: params.moduleAccounting.tokens,
|
|
126608
|
+
providerId: params.moduleAccounting.providerId,
|
|
126609
|
+
modelId: params.moduleAccounting.modelId
|
|
126610
|
+
} : {},
|
|
126135
126611
|
error: params.error
|
|
126136
126612
|
});
|
|
126137
126613
|
}
|
|
@@ -126226,7 +126702,7 @@ import { createHash as createHash30 } from "node:crypto";
|
|
|
126226
126702
|
import {
|
|
126227
126703
|
existsSync as existsSync16,
|
|
126228
126704
|
mkdirSync as mkdirSync11,
|
|
126229
|
-
mkdtempSync
|
|
126705
|
+
mkdtempSync,
|
|
126230
126706
|
readdirSync as readdirSync6,
|
|
126231
126707
|
readFileSync as readFileSync16,
|
|
126232
126708
|
realpathSync as realpathSync4,
|
|
@@ -126333,7 +126809,7 @@ function protectedBytes(text) {
|
|
|
126333
126809
|
].map((match) => match[0]);
|
|
126334
126810
|
}
|
|
126335
126811
|
function diff(name, before, after) {
|
|
126336
|
-
const dir =
|
|
126812
|
+
const dir = mkdtempSync(join17(tmpdir2(), "mc-doc-diff-"));
|
|
126337
126813
|
try {
|
|
126338
126814
|
writeFileSync8(join17(dir, "before"), before);
|
|
126339
126815
|
writeFileSync8(join17(dir, "after"), after);
|
|
@@ -128305,8 +128781,36 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
128305
128781
|
let promptSettled = false;
|
|
128306
128782
|
const startedAt = Date.now();
|
|
128307
128783
|
try {
|
|
128784
|
+
const prompt = buildMapMemoriesPrompt(args.projectIdentity, batch);
|
|
128785
|
+
if (args.hiddenCompletionExecutor) {
|
|
128786
|
+
const run = await runHiddenSingleShotPrompt({
|
|
128787
|
+
executor: args.hiddenCompletionExecutor,
|
|
128788
|
+
parentSessionId: args.parentSessionId,
|
|
128789
|
+
sessionDirectory: args.sessionDirectory,
|
|
128790
|
+
agent: DREAMER_MEMORY_MAPPER_AGENT,
|
|
128791
|
+
system: MAP_MEMORIES_SYSTEM_PROMPT,
|
|
128792
|
+
prompt,
|
|
128793
|
+
title: "magic-context-dream-map-memories",
|
|
128794
|
+
callContext: "dreamer:map-memories",
|
|
128795
|
+
model: args.model,
|
|
128796
|
+
fallbackModels: args.fallbackModels,
|
|
128797
|
+
timeoutMs: sliceMs,
|
|
128798
|
+
signal,
|
|
128799
|
+
parse: (text) => validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)))
|
|
128800
|
+
});
|
|
128801
|
+
recordInvocation2(args, startedAt, {
|
|
128802
|
+
status: "completed",
|
|
128803
|
+
messages: run.completion.messages ?? []
|
|
128804
|
+
});
|
|
128805
|
+
const outcome = await applyParsedBatchMappings(args, batch, run.validated);
|
|
128806
|
+
const returnedIds = new Set(run.validated.map((entry) => entry.id));
|
|
128807
|
+
return { ...outcome, requeue: batch.filter((memory) => !returnedIds.has(memory.id)) };
|
|
128808
|
+
}
|
|
128809
|
+
const client = args.client;
|
|
128810
|
+
if (!client)
|
|
128811
|
+
throw new Error("map-memories requires a client or hidden completion executor");
|
|
128308
128812
|
const createResponse = await createChildSessionWithFence({
|
|
128309
|
-
client
|
|
128813
|
+
client,
|
|
128310
128814
|
db: args.db,
|
|
128311
128815
|
parentSessionId: args.parentSessionId,
|
|
128312
128816
|
title: "magic-context-dream-map-memories",
|
|
@@ -128318,8 +128822,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
128318
128822
|
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
128319
128823
|
if (!agentSessionId)
|
|
128320
128824
|
throw new Error("Could not create map-memories session.");
|
|
128321
|
-
const
|
|
128322
|
-
const run = await promptSyncWithValidatedOutputRetry(args.client, {
|
|
128825
|
+
const run = await promptSyncWithValidatedOutputRetry(client, {
|
|
128323
128826
|
path: { id: agentSessionId },
|
|
128324
128827
|
query: { directory: args.sessionDirectory },
|
|
128325
128828
|
body: {
|
|
@@ -128334,7 +128837,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
128334
128837
|
fallbackModels: args.fallbackModels,
|
|
128335
128838
|
callContext: "dreamer:map-memories",
|
|
128336
128839
|
fetchOutput: async () => {
|
|
128337
|
-
const messagesResponse = await
|
|
128840
|
+
const messagesResponse = await client.session.messages({
|
|
128338
128841
|
path: { id: agentSessionId },
|
|
128339
128842
|
query: { directory: args.sessionDirectory, limit: 100 }
|
|
128340
128843
|
});
|
|
@@ -128377,15 +128880,16 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
128377
128880
|
}
|
|
128378
128881
|
};
|
|
128379
128882
|
} finally {
|
|
128380
|
-
|
|
128381
|
-
|
|
128382
|
-
|
|
128383
|
-
|
|
128384
|
-
|
|
128385
|
-
|
|
128386
|
-
|
|
128387
|
-
|
|
128388
|
-
|
|
128883
|
+
if (agentSessionId && args.client)
|
|
128884
|
+
await teardownChildSession({
|
|
128885
|
+
client: args.client,
|
|
128886
|
+
sessionId: agentSessionId,
|
|
128887
|
+
sessionDirectory: args.sessionDirectory,
|
|
128888
|
+
promptSettled,
|
|
128889
|
+
privacySensitive: true,
|
|
128890
|
+
context: "[dreamer] map-memories",
|
|
128891
|
+
log
|
|
128892
|
+
});
|
|
128389
128893
|
}
|
|
128390
128894
|
}
|
|
128391
128895
|
async function applyParsedBatchMappings(args, batch, parsed) {
|
|
@@ -129001,8 +129505,41 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
129001
129505
|
let promptSettled = false;
|
|
129002
129506
|
const startedAt = Date.now();
|
|
129003
129507
|
try {
|
|
129508
|
+
const prompt = buildInvestigationPrompt(primer, seed.kind, seed.orientation, seed.prePost);
|
|
129509
|
+
if (args.hiddenCompletionExecutor) {
|
|
129510
|
+
const run = await runHiddenSingleShotPrompt({
|
|
129511
|
+
executor: args.hiddenCompletionExecutor,
|
|
129512
|
+
parentSessionId: args.parentSessionId,
|
|
129513
|
+
sessionDirectory: args.sessionDirectory,
|
|
129514
|
+
agent: DREAMER_PRIMER_INVESTIGATOR_AGENT,
|
|
129515
|
+
system: PRIMER_INVESTIGATOR_SYSTEM_PROMPT,
|
|
129516
|
+
prompt,
|
|
129517
|
+
title: "magic-context-dream-refresh-primers",
|
|
129518
|
+
callContext: "dreamer:refresh-primers",
|
|
129519
|
+
model: args.model,
|
|
129520
|
+
fallbackModels: args.fallbackModels,
|
|
129521
|
+
language: args.language,
|
|
129522
|
+
timeoutMs: sliceMs,
|
|
129523
|
+
signal,
|
|
129524
|
+
parse: (text) => parseAnswer([{ info: { role: "assistant" }, parts: [{ type: "text", text }] }], primer.answer)
|
|
129525
|
+
});
|
|
129526
|
+
recordInvocation3(args, startedAt, {
|
|
129527
|
+
status: "completed",
|
|
129528
|
+
messages: run.completion.messages ?? []
|
|
129529
|
+
});
|
|
129530
|
+
const answer = run.validated.trim();
|
|
129531
|
+
if (!answer || investigationToolCallCount(run.completion.messages ?? []) === 0)
|
|
129532
|
+
return false;
|
|
129533
|
+
runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
129534
|
+
updatePrimerAnswer(args.db, primer.id, answer);
|
|
129535
|
+
});
|
|
129536
|
+
return true;
|
|
129537
|
+
}
|
|
129538
|
+
const client = args.client;
|
|
129539
|
+
if (!client)
|
|
129540
|
+
throw new Error("refresh-primers requires a client or hidden completion executor");
|
|
129004
129541
|
const createResponse = await createChildSessionWithFence({
|
|
129005
|
-
client
|
|
129542
|
+
client,
|
|
129006
129543
|
db: args.db,
|
|
129007
129544
|
parentSessionId: args.parentSessionId,
|
|
129008
129545
|
title: "magic-context-dream-refresh-primers",
|
|
@@ -129014,8 +129551,7 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
129014
129551
|
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
129015
129552
|
if (!agentSessionId)
|
|
129016
129553
|
throw new Error("Could not create primer refresh session.");
|
|
129017
|
-
const
|
|
129018
|
-
const run = await promptSyncWithValidatedOutputRetry(args.client, {
|
|
129554
|
+
const run = await promptSyncWithValidatedOutputRetry(client, {
|
|
129019
129555
|
path: { id: agentSessionId },
|
|
129020
129556
|
query: { directory: args.sessionDirectory },
|
|
129021
129557
|
body: {
|
|
@@ -129030,7 +129566,7 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
129030
129566
|
fallbackModels: args.fallbackModels,
|
|
129031
129567
|
callContext: "dreamer:refresh-primers",
|
|
129032
129568
|
fetchOutput: async () => {
|
|
129033
|
-
const messagesResponse = await
|
|
129569
|
+
const messagesResponse = await client.session.messages({
|
|
129034
129570
|
path: { id: agentSessionId },
|
|
129035
129571
|
query: { directory: args.sessionDirectory, limit: 100 }
|
|
129036
129572
|
});
|
|
@@ -129059,15 +129595,16 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
129059
129595
|
recordInvocation3(args, startedAt, { status: failedInvocationStatus(error), error });
|
|
129060
129596
|
throw error;
|
|
129061
129597
|
} finally {
|
|
129062
|
-
|
|
129063
|
-
|
|
129064
|
-
|
|
129065
|
-
|
|
129066
|
-
|
|
129067
|
-
|
|
129068
|
-
|
|
129069
|
-
|
|
129070
|
-
|
|
129598
|
+
if (agentSessionId && args.client)
|
|
129599
|
+
await teardownChildSession({
|
|
129600
|
+
client: args.client,
|
|
129601
|
+
sessionId: agentSessionId,
|
|
129602
|
+
sessionDirectory: args.sessionDirectory,
|
|
129603
|
+
promptSettled,
|
|
129604
|
+
privacySensitive: true,
|
|
129605
|
+
context: "[dreamer] refresh-primers",
|
|
129606
|
+
log
|
|
129607
|
+
});
|
|
129071
129608
|
}
|
|
129072
129609
|
}
|
|
129073
129610
|
function originSessionIdForPrimer(args, primer) {
|
|
@@ -129757,8 +130294,40 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
129757
130294
|
let promptSettled = false;
|
|
129758
130295
|
const startedAt = Date.now();
|
|
129759
130296
|
try {
|
|
130297
|
+
const prompt = buildVerifyPrompt(args.projectIdentity, batch);
|
|
130298
|
+
if (args.hiddenCompletionExecutor) {
|
|
130299
|
+
const run = await runHiddenSingleShotPrompt({
|
|
130300
|
+
executor: args.hiddenCompletionExecutor,
|
|
130301
|
+
parentSessionId: args.parentSessionId,
|
|
130302
|
+
sessionDirectory: args.sessionDirectory,
|
|
130303
|
+
agent: DREAMER_MEMORY_MAPPER_AGENT,
|
|
130304
|
+
system: VERIFY_SYSTEM_PROMPT,
|
|
130305
|
+
prompt,
|
|
130306
|
+
title: "magic-context-dream-verify",
|
|
130307
|
+
callContext: "dreamer:verify",
|
|
130308
|
+
model: args.model,
|
|
130309
|
+
fallbackModels: args.fallbackModels,
|
|
130310
|
+
language: args.language,
|
|
130311
|
+
timeoutMs: sliceMs,
|
|
130312
|
+
signal,
|
|
130313
|
+
parse: (text) => {
|
|
130314
|
+
const providerFailure = providerOutputFailureFromInvalidManifest([], text);
|
|
130315
|
+
if (providerFailure)
|
|
130316
|
+
throw providerFailure;
|
|
130317
|
+
return validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
|
|
130318
|
+
}
|
|
130319
|
+
});
|
|
130320
|
+
recordInvocation4(args, startedAt, {
|
|
130321
|
+
status: "completed",
|
|
130322
|
+
messages: run.completion.messages ?? []
|
|
130323
|
+
});
|
|
130324
|
+
return applyParsedVerifyManifest(args, batch, run.validated);
|
|
130325
|
+
}
|
|
130326
|
+
const client = args.client;
|
|
130327
|
+
if (!client)
|
|
130328
|
+
throw new Error("verify requires a client or hidden completion executor");
|
|
129760
130329
|
const createResponse = await createChildSessionWithFence({
|
|
129761
|
-
client
|
|
130330
|
+
client,
|
|
129762
130331
|
db: args.db,
|
|
129763
130332
|
parentSessionId: args.parentSessionId,
|
|
129764
130333
|
title: "magic-context-dream-verify",
|
|
@@ -129770,8 +130339,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
129770
130339
|
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
129771
130340
|
if (!agentSessionId)
|
|
129772
130341
|
throw new Error("Could not create verify session.");
|
|
129773
|
-
const
|
|
129774
|
-
const run = await promptSyncWithValidatedOutputRetry(args.client, {
|
|
130342
|
+
const run = await promptSyncWithValidatedOutputRetry(client, {
|
|
129775
130343
|
path: { id: agentSessionId },
|
|
129776
130344
|
query: { directory: args.sessionDirectory },
|
|
129777
130345
|
body: {
|
|
@@ -129786,7 +130354,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
129786
130354
|
fallbackModels: args.fallbackModels,
|
|
129787
130355
|
callContext: "dreamer:verify",
|
|
129788
130356
|
fetchOutput: async () => {
|
|
129789
|
-
const messagesResponse = await
|
|
130357
|
+
const messagesResponse = await client.session.messages({
|
|
129790
130358
|
path: { id: agentSessionId },
|
|
129791
130359
|
query: { directory: args.sessionDirectory, limit: 100 }
|
|
129792
130360
|
});
|
|
@@ -129827,15 +130395,16 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
129827
130395
|
providerFailure
|
|
129828
130396
|
};
|
|
129829
130397
|
} finally {
|
|
129830
|
-
|
|
129831
|
-
|
|
129832
|
-
|
|
129833
|
-
|
|
129834
|
-
|
|
129835
|
-
|
|
129836
|
-
|
|
129837
|
-
|
|
129838
|
-
|
|
130398
|
+
if (agentSessionId && args.client)
|
|
130399
|
+
await teardownChildSession({
|
|
130400
|
+
client: args.client,
|
|
130401
|
+
sessionId: agentSessionId,
|
|
130402
|
+
sessionDirectory: args.sessionDirectory,
|
|
130403
|
+
promptSettled,
|
|
130404
|
+
privacySensitive: true,
|
|
130405
|
+
context: "[dreamer] verify",
|
|
130406
|
+
log
|
|
130407
|
+
});
|
|
129839
130408
|
}
|
|
129840
130409
|
}
|
|
129841
130410
|
async function applyParsedVerifyManifest(args, batch, parsed) {
|
|
@@ -130003,6 +130572,8 @@ async function applyParsedVerifyManifest(args, batch, parsed) {
|
|
|
130003
130572
|
async function normalizeFiles(args, rawFiles) {
|
|
130004
130573
|
if (rawFiles.length === 0)
|
|
130005
130574
|
return [];
|
|
130575
|
+
if (args.normalizeFiles)
|
|
130576
|
+
return args.normalizeFiles(rawFiles);
|
|
130006
130577
|
const normalized = await normalizeVerificationFiles({
|
|
130007
130578
|
cwd: args.sessionDirectory,
|
|
130008
130579
|
files: rawFiles
|
|
@@ -130336,7 +130907,8 @@ function createDreamTaskExecutor(deps) {
|
|
|
130336
130907
|
if (config.task === "map-memories") {
|
|
130337
130908
|
const result = await mapMemories({
|
|
130338
130909
|
db,
|
|
130339
|
-
client:
|
|
130910
|
+
client: deps.client,
|
|
130911
|
+
hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
|
|
130340
130912
|
projectIdentity,
|
|
130341
130913
|
parentSessionId: parent,
|
|
130342
130914
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -130373,7 +130945,8 @@ function createDreamTaskExecutor(deps) {
|
|
|
130373
130945
|
const memoryBefore = getMemoryCountsByStatus(db, projectIdentity);
|
|
130374
130946
|
const result = await runVerify({
|
|
130375
130947
|
db,
|
|
130376
|
-
client:
|
|
130948
|
+
client: deps.client,
|
|
130949
|
+
hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
|
|
130377
130950
|
projectIdentity,
|
|
130378
130951
|
parentSessionId: parent,
|
|
130379
130952
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -130474,7 +131047,8 @@ function createDreamTaskExecutor(deps) {
|
|
|
130474
131047
|
if (config.task === "refresh-primers") {
|
|
130475
131048
|
const result = await refreshPrimers({
|
|
130476
131049
|
db,
|
|
130477
|
-
client:
|
|
131050
|
+
client: deps.client,
|
|
131051
|
+
hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
|
|
130478
131052
|
projectIdentity,
|
|
130479
131053
|
parentSessionId: parent,
|
|
130480
131054
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -130742,24 +131316,45 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
130742
131316
|
abortController.abort();
|
|
130743
131317
|
}, ctx.leaseAcquisition);
|
|
130744
131318
|
let childSessionId = null;
|
|
131319
|
+
let hiddenHandle = null;
|
|
130745
131320
|
let promptSettled = false;
|
|
130746
131321
|
try {
|
|
130747
|
-
|
|
130748
|
-
|
|
130749
|
-
|
|
130750
|
-
|
|
130751
|
-
|
|
130752
|
-
|
|
130753
|
-
|
|
130754
|
-
|
|
130755
|
-
|
|
130756
|
-
|
|
130757
|
-
|
|
131322
|
+
if (deps.hiddenCompletionExecutor) {
|
|
131323
|
+
hiddenHandle = await deps.hiddenCompletionExecutor.open({
|
|
131324
|
+
parentSessionId: parent ?? undefined,
|
|
131325
|
+
agent: DREAMER_RETROSPECTIVE_AGENT,
|
|
131326
|
+
kind: "dreamer-task",
|
|
131327
|
+
system: FRICTION_GATE_SYSTEM_PROMPT,
|
|
131328
|
+
model: config.model,
|
|
131329
|
+
configuredModels: [
|
|
131330
|
+
...config.model ? [config.model] : [],
|
|
131331
|
+
...config.fallbackModels ?? []
|
|
131332
|
+
],
|
|
131333
|
+
timeoutMs: Math.max(1, deadline - Date.now()),
|
|
131334
|
+
title: "magic-context-dream-retrospective",
|
|
131335
|
+
directory: deps.sessionDirectory
|
|
131336
|
+
});
|
|
131337
|
+
childSessionId = hiddenHandle.id;
|
|
131338
|
+
} else {
|
|
131339
|
+
const createResponse = await createChildSessionWithFence({
|
|
131340
|
+
client: requireDreamClient(deps.client),
|
|
131341
|
+
db,
|
|
131342
|
+
parentSessionId: parent ?? undefined,
|
|
131343
|
+
title: "magic-context-dream-retrospective",
|
|
131344
|
+
directory: deps.sessionDirectory
|
|
131345
|
+
});
|
|
131346
|
+
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
131347
|
+
childSessionId = typeof created?.id === "string" ? created.id : null;
|
|
131348
|
+
if (!childSessionId)
|
|
131349
|
+
throw new Error("Retrospective could not create its child session.");
|
|
131350
|
+
}
|
|
130758
131351
|
const sessionId = childSessionId;
|
|
131352
|
+
if (!sessionId)
|
|
131353
|
+
throw new Error("Retrospective could not create its child session.");
|
|
130759
131354
|
const runChildTurn = async (system, userText) => {
|
|
130760
131355
|
const remainingMs = Math.max(0, deadline - Date.now());
|
|
130761
131356
|
promptSettled = false;
|
|
130762
|
-
const run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
|
|
131357
|
+
const run = await promptSyncWithValidatedOutputRetry(deps.hiddenCompletionExecutor ? undefined : requireDreamClient(deps.client), {
|
|
130763
131358
|
path: { id: sessionId },
|
|
130764
131359
|
query: { directory: deps.sessionDirectory },
|
|
130765
131360
|
body: {
|
|
@@ -130773,7 +131368,13 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
130773
131368
|
signal: abortController.signal,
|
|
130774
131369
|
fallbackModels: config.fallbackModels,
|
|
130775
131370
|
callContext: "dreamer:retrospective",
|
|
131371
|
+
...hiddenHandle && deps.hiddenCompletionExecutor ? {
|
|
131372
|
+
transport: Object.assign((request) => deps.hiddenCompletionExecutor?.attempt(hiddenHandle, request) ?? Promise.reject(new Error("Hidden transport unavailable")), { childSessionId: hiddenHandle.childSessionId })
|
|
131373
|
+
} : {},
|
|
130776
131374
|
fetchOutput: async () => {
|
|
131375
|
+
if (hiddenHandle && deps.hiddenCompletionExecutor) {
|
|
131376
|
+
return deps.hiddenCompletionExecutor.collect(hiddenHandle, 50);
|
|
131377
|
+
}
|
|
130777
131378
|
const messagesResponse = await requireDreamClient(deps.client).session.messages({
|
|
130778
131379
|
path: { id: sessionId },
|
|
130779
131380
|
query: { directory: deps.sessionDirectory, limit: 50 }
|
|
@@ -130783,14 +131384,15 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
130783
131384
|
});
|
|
130784
131385
|
},
|
|
130785
131386
|
validateOutput: (outputMessages) => {
|
|
130786
|
-
const text = extractLatestAssistantText(outputMessages);
|
|
131387
|
+
const text = hiddenHandle ? outputMessages.text : extractLatestAssistantText(outputMessages);
|
|
130787
131388
|
if (!text)
|
|
130788
131389
|
throw new Error("Retrospective child returned no output.");
|
|
130789
131390
|
return text;
|
|
130790
131391
|
}
|
|
130791
131392
|
});
|
|
130792
131393
|
promptSettled = true;
|
|
130793
|
-
|
|
131394
|
+
const output = hiddenHandle ? run.output.messages ?? [] : run.output;
|
|
131395
|
+
return { ...run, output };
|
|
130794
131396
|
};
|
|
130795
131397
|
const finish = (run, watermark) => {
|
|
130796
131398
|
if (parent && run) {
|
|
@@ -130920,15 +131522,23 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
130920
131522
|
});
|
|
130921
131523
|
} finally {
|
|
130922
131524
|
heartbeat.stop();
|
|
130923
|
-
|
|
130924
|
-
|
|
130925
|
-
|
|
130926
|
-
|
|
130927
|
-
|
|
130928
|
-
|
|
130929
|
-
|
|
130930
|
-
|
|
130931
|
-
|
|
131525
|
+
if (hiddenHandle && deps.hiddenCompletionExecutor) {
|
|
131526
|
+
await deps.hiddenCompletionExecutor.close(hiddenHandle, {
|
|
131527
|
+
promptSettled,
|
|
131528
|
+
privacySensitive: true,
|
|
131529
|
+
context: "[dreamer] retrospective",
|
|
131530
|
+
log
|
|
131531
|
+
});
|
|
131532
|
+
} else
|
|
131533
|
+
await teardownChildSession({
|
|
131534
|
+
client: requireDreamClient(deps.client),
|
|
131535
|
+
sessionId: childSessionId,
|
|
131536
|
+
sessionDirectory: deps.sessionDirectory,
|
|
131537
|
+
promptSettled,
|
|
131538
|
+
privacySensitive: true,
|
|
131539
|
+
context: "[dreamer] retrospective",
|
|
131540
|
+
log
|
|
131541
|
+
});
|
|
130932
131542
|
}
|
|
130933
131543
|
}
|
|
130934
131544
|
async function runAgenticTask(config, ctx, helpers) {
|
|
@@ -131002,72 +131612,107 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
131002
131612
|
docsCurrentTokens: maintainDocsSnapshot ? Math.ceil([...maintainDocsSnapshot.values()].join("").length / 3.5) : 0,
|
|
131003
131613
|
curate: curateMemories && curateCategory ? { category: curateCategory, memories: curateMemories } : undefined
|
|
131004
131614
|
});
|
|
131005
|
-
|
|
131006
|
-
|
|
131007
|
-
|
|
131008
|
-
|
|
131009
|
-
|
|
131010
|
-
|
|
131011
|
-
});
|
|
131012
|
-
const created = normalizeSDKResponse(createResponse, null, {
|
|
131013
|
-
preferResponseOnMissingData: true
|
|
131014
|
-
});
|
|
131015
|
-
childSessionId = typeof created?.id === "string" ? created.id : null;
|
|
131016
|
-
if (!childSessionId)
|
|
131017
|
-
throw new Error("Dreamer could not create its child session.");
|
|
131018
|
-
const sessionId = childSessionId;
|
|
131019
|
-
const remainingMs = Math.max(0, deadline - Date.now());
|
|
131020
|
-
const run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
|
|
131021
|
-
path: { id: sessionId },
|
|
131022
|
-
query: { directory: docsDir },
|
|
131023
|
-
body: {
|
|
131615
|
+
let run;
|
|
131616
|
+
if (deps.hiddenCompletionExecutor) {
|
|
131617
|
+
const hidden = await runHiddenSingleShotPrompt({
|
|
131618
|
+
executor: deps.hiddenCompletionExecutor,
|
|
131619
|
+
parentSessionId: parent ?? undefined,
|
|
131620
|
+
sessionDirectory: docsDir,
|
|
131024
131621
|
agent: task === "maintain-docs" ? DREAMER_DOCS_AGENT : DREAMER_AGENT,
|
|
131025
|
-
system: task === "maintain-docs" ? MAINTAIN_DOCS_SYSTEM_PROMPT :
|
|
131026
|
-
|
|
131027
|
-
|
|
131028
|
-
|
|
131029
|
-
|
|
131030
|
-
|
|
131031
|
-
|
|
131032
|
-
|
|
131033
|
-
|
|
131034
|
-
|
|
131035
|
-
|
|
131036
|
-
|
|
131037
|
-
|
|
131038
|
-
|
|
131039
|
-
|
|
131622
|
+
system: task === "maintain-docs" ? MAINTAIN_DOCS_SYSTEM_PROMPT : CURATE_SYSTEM_PROMPT,
|
|
131623
|
+
prompt: taskPrompt,
|
|
131624
|
+
title: `magic-context-dream-${task}`,
|
|
131625
|
+
callContext: `dreamer:${task}`,
|
|
131626
|
+
allowEmpty: task === "curate",
|
|
131627
|
+
model: config.model,
|
|
131628
|
+
fallbackModels: config.fallbackModels,
|
|
131629
|
+
language: task === "curate" ? config.language ?? deps.language : undefined,
|
|
131630
|
+
timeoutMs: Math.min(Math.max(0, deadline - Date.now()), config.timeoutMinutes * 60 * 1000),
|
|
131631
|
+
signal: abortController.signal,
|
|
131632
|
+
parse: (text, completion) => {
|
|
131633
|
+
if (task !== "curate")
|
|
131634
|
+
return text;
|
|
131635
|
+
const memoryOperations = inspectCurateMemoryOperations(completion.messages);
|
|
131636
|
+
if (text)
|
|
131637
|
+
validateCurateAssistantText(text);
|
|
131638
|
+
if (memoryOperations.totalCalls > 0 && memoryOperations.completedActions.length === 0)
|
|
131639
|
+
throw new Error("Curate returned no completed ctx_memory tool result.");
|
|
131640
|
+
if (!text && memoryOperations.completedActions.length === 0)
|
|
131641
|
+
throw new Error("Dreamer returned no assistant output.");
|
|
131642
|
+
return { text: text || null, memoryOperations };
|
|
131643
|
+
}
|
|
131644
|
+
});
|
|
131645
|
+
childSessionId = hidden.childSessionId;
|
|
131646
|
+
run = { output: hidden.completion.messages ?? [], validated: hidden.validated };
|
|
131647
|
+
promptSettled = true;
|
|
131648
|
+
} else {
|
|
131649
|
+
const createResponse = await createChildSessionWithFence({
|
|
131650
|
+
client: requireDreamClient(deps.client),
|
|
131651
|
+
db,
|
|
131652
|
+
parentSessionId: parent ?? undefined,
|
|
131653
|
+
title: `magic-context-dream-${task}`,
|
|
131654
|
+
directory: docsDir
|
|
131655
|
+
});
|
|
131656
|
+
const created = normalizeSDKResponse(createResponse, null, {
|
|
131657
|
+
preferResponseOnMissingData: true
|
|
131658
|
+
});
|
|
131659
|
+
childSessionId = typeof created?.id === "string" ? created.id : null;
|
|
131660
|
+
if (!childSessionId)
|
|
131661
|
+
throw new Error("Dreamer could not create its child session.");
|
|
131662
|
+
const sessionId = childSessionId;
|
|
131663
|
+
const remainingMs = Math.max(0, deadline - Date.now());
|
|
131664
|
+
run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
|
|
131665
|
+
path: { id: sessionId },
|
|
131666
|
+
query: { directory: docsDir },
|
|
131667
|
+
body: {
|
|
131668
|
+
agent: task === "maintain-docs" ? DREAMER_DOCS_AGENT : DREAMER_AGENT,
|
|
131669
|
+
system: task === "maintain-docs" ? MAINTAIN_DOCS_SYSTEM_PROMPT : withContentLanguageDirective(CURATE_SYSTEM_PROMPT, config.language ?? deps.language),
|
|
131670
|
+
...modelBodyField(config.model),
|
|
131671
|
+
parts: [{ type: "text", text: taskPrompt, synthetic: true }]
|
|
131672
|
+
}
|
|
131673
|
+
}, {
|
|
131674
|
+
timeoutMs: Math.min(remainingMs, config.timeoutMinutes * 60 * 1000),
|
|
131675
|
+
signal: abortController.signal,
|
|
131676
|
+
fallbackModels: config.fallbackModels,
|
|
131677
|
+
callContext: `dreamer:${task}`,
|
|
131678
|
+
fetchOutput: async () => {
|
|
131679
|
+
const messagesResponse = await requireDreamClient(deps.client).session.messages({
|
|
131680
|
+
path: { id: sessionId },
|
|
131681
|
+
query: {
|
|
131682
|
+
directory: docsDir,
|
|
131683
|
+
...task === "curate" ? {} : { limit: 50 }
|
|
131684
|
+
}
|
|
131685
|
+
});
|
|
131686
|
+
return normalizeSDKResponse(messagesResponse, [], {
|
|
131687
|
+
preferResponseOnMissingData: true
|
|
131688
|
+
});
|
|
131689
|
+
},
|
|
131690
|
+
validateOutput: (messages) => {
|
|
131691
|
+
const text = extractLatestAssistantText(messages);
|
|
131692
|
+
if (task !== "curate") {
|
|
131693
|
+
if (!text)
|
|
131694
|
+
throw new Error("Dreamer returned no assistant output.");
|
|
131695
|
+
return text;
|
|
131696
|
+
}
|
|
131697
|
+
const memoryOperations = inspectCurateMemoryOperations(messages);
|
|
131698
|
+
if (text)
|
|
131699
|
+
validateCurateAssistantText(text);
|
|
131700
|
+
if (memoryOperations.completedActions.length > 0) {
|
|
131701
|
+
return { text, memoryOperations };
|
|
131040
131702
|
}
|
|
131041
|
-
});
|
|
131042
|
-
return normalizeSDKResponse(messagesResponse, [], {
|
|
131043
|
-
preferResponseOnMissingData: true
|
|
131044
|
-
});
|
|
131045
|
-
},
|
|
131046
|
-
validateOutput: (messages) => {
|
|
131047
|
-
const text = extractLatestAssistantText(messages);
|
|
131048
|
-
if (task !== "curate") {
|
|
131049
131703
|
if (!text)
|
|
131050
131704
|
throw new Error("Dreamer returned no assistant output.");
|
|
131051
|
-
|
|
131052
|
-
|
|
131053
|
-
|
|
131054
|
-
if (text)
|
|
131055
|
-
validateCurateAssistantText(text);
|
|
131056
|
-
if (memoryOperations.completedActions.length > 0) {
|
|
131705
|
+
if (memoryOperations.totalCalls > 0) {
|
|
131706
|
+
throw new Error("Curate returned no completed ctx_memory tool result.");
|
|
131707
|
+
}
|
|
131057
131708
|
return { text, memoryOperations };
|
|
131058
131709
|
}
|
|
131059
|
-
|
|
131060
|
-
|
|
131061
|
-
|
|
131062
|
-
throw new Error("Curate returned no completed ctx_memory tool result.");
|
|
131063
|
-
}
|
|
131064
|
-
return { text, memoryOperations };
|
|
131065
|
-
}
|
|
131066
|
-
});
|
|
131067
|
-
promptSettled = true;
|
|
131710
|
+
});
|
|
131711
|
+
promptSettled = true;
|
|
131712
|
+
}
|
|
131068
131713
|
if (leaseLost)
|
|
131069
131714
|
throw new Error("Dream lease lost during task");
|
|
131070
|
-
const curateRefused = task === "curate" ? takeCurateSafetyRefusalCount(
|
|
131715
|
+
const curateRefused = task === "curate" ? takeCurateSafetyRefusalCount(childSessionId ?? "") : 0;
|
|
131071
131716
|
if (curateRefused > 0) {
|
|
131072
131717
|
helpers.reportProgress(curateRefused, curateRefused);
|
|
131073
131718
|
log(`[dreamer] curate safety summary: refused=${curateRefused}`);
|
|
@@ -131137,15 +131782,16 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
131137
131782
|
heartbeat.stop();
|
|
131138
131783
|
if (childSessionId)
|
|
131139
131784
|
takeCurateSafetyRefusalCount(childSessionId);
|
|
131140
|
-
|
|
131141
|
-
|
|
131142
|
-
|
|
131143
|
-
|
|
131144
|
-
|
|
131145
|
-
|
|
131146
|
-
|
|
131147
|
-
|
|
131148
|
-
|
|
131785
|
+
if (!deps.hiddenCompletionExecutor)
|
|
131786
|
+
await teardownChildSession({
|
|
131787
|
+
client: requireDreamClient(deps.client),
|
|
131788
|
+
sessionId: childSessionId,
|
|
131789
|
+
sessionDirectory: docsDir,
|
|
131790
|
+
promptSettled,
|
|
131791
|
+
privacySensitive: true,
|
|
131792
|
+
context: `[dreamer] ${task}`,
|
|
131793
|
+
log
|
|
131794
|
+
});
|
|
131149
131795
|
}
|
|
131150
131796
|
}
|
|
131151
131797
|
|
|
@@ -131598,7 +132244,25 @@ async function warmModelLimitCacheFromCatalog(context, options = {}) {
|
|
|
131598
132244
|
}
|
|
131599
132245
|
|
|
131600
132246
|
// src/v2/hooks/payload.ts
|
|
132247
|
+
init_logger();
|
|
131601
132248
|
var HEAD_IDS = ["__magic_context_v2_m0__", "__magic_context_v2_m1__"];
|
|
132249
|
+
var HOST_CONTENT_TYPES = new Set([
|
|
132250
|
+
"text",
|
|
132251
|
+
"media",
|
|
132252
|
+
"tool-call",
|
|
132253
|
+
"tool-result",
|
|
132254
|
+
"reasoning",
|
|
132255
|
+
"compaction",
|
|
132256
|
+
"effort"
|
|
132257
|
+
]);
|
|
132258
|
+
function rejectContentPart(message, part, reason) {
|
|
132259
|
+
const type = typeof part.type === "string" ? part.type : "<missing>";
|
|
132260
|
+
const text = `v2 context omitted a content part the host would reject: type=${type} message=${String(message.info.id ?? "<head>")} reason=${reason}`;
|
|
132261
|
+
if (typeof message.info.sessionID === "string")
|
|
132262
|
+
sessionLog(message.info.sessionID, text);
|
|
132263
|
+
else
|
|
132264
|
+
log(text);
|
|
132265
|
+
}
|
|
131602
132266
|
function isHostInstance(value) {
|
|
131603
132267
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
131604
132268
|
return false;
|
|
@@ -131789,6 +132453,56 @@ function adaptPayload(draft, admittedIDs = new Set) {
|
|
|
131789
132453
|
const part = candidate;
|
|
131790
132454
|
const bridge = bridges.get(part) ?? (part.type === "tool" && typeof part.callID === "string" ? bridgesFor(message)?.get(part.callID) : undefined);
|
|
131791
132455
|
if (!bridge) {
|
|
132456
|
+
if (part.type === "tool") {
|
|
132457
|
+
const state = part.state;
|
|
132458
|
+
if (typeof part.callID !== "string" || typeof part.tool !== "string" || !state || typeof state !== "object") {
|
|
132459
|
+
rejectContentPart(message, part, "tool has no call ID, name, or state");
|
|
132460
|
+
continue;
|
|
132461
|
+
}
|
|
132462
|
+
content.push({
|
|
132463
|
+
type: "tool-call",
|
|
132464
|
+
id: part.callID,
|
|
132465
|
+
name: part.tool,
|
|
132466
|
+
input: state.input
|
|
132467
|
+
});
|
|
132468
|
+
if (state.status === "completed" || state.status === "error") {
|
|
132469
|
+
following.push({
|
|
132470
|
+
role: "tool",
|
|
132471
|
+
content: [
|
|
132472
|
+
{
|
|
132473
|
+
type: "tool-result",
|
|
132474
|
+
id: part.callID,
|
|
132475
|
+
name: part.tool,
|
|
132476
|
+
result: {
|
|
132477
|
+
type: state.status === "error" ? "error" : "text",
|
|
132478
|
+
value: toolStateContent(state)
|
|
132479
|
+
}
|
|
132480
|
+
}
|
|
132481
|
+
]
|
|
132482
|
+
});
|
|
132483
|
+
}
|
|
132484
|
+
continue;
|
|
132485
|
+
}
|
|
132486
|
+
if (part.type === "file") {
|
|
132487
|
+
const mime = part.mime;
|
|
132488
|
+
const url = part.url;
|
|
132489
|
+
const prefix = `data:${mime};base64,`;
|
|
132490
|
+
if (typeof mime !== "string" || !/^image\/(png|jpeg|gif|webp)$/.test(mime) || typeof url !== "string" || !url.startsWith(prefix)) {
|
|
132491
|
+
rejectContentPart(message, part, "file is not an inline supported image");
|
|
132492
|
+
continue;
|
|
132493
|
+
}
|
|
132494
|
+
const asset = hostMediaAsset(url.slice(prefix.length), mime);
|
|
132495
|
+
if (typeof asset === "string") {
|
|
132496
|
+
rejectContentPart(message, part, `host media unavailable: ${asset}`);
|
|
132497
|
+
continue;
|
|
132498
|
+
}
|
|
132499
|
+
content.push({ type: "media", media: asset });
|
|
132500
|
+
continue;
|
|
132501
|
+
}
|
|
132502
|
+
if (!HOST_CONTENT_TYPES.has(String(part.type))) {
|
|
132503
|
+
rejectContentPart(message, part, "unknown host content type");
|
|
132504
|
+
continue;
|
|
132505
|
+
}
|
|
131792
132506
|
const { synthetic: _synthetic, ...clean } = part;
|
|
131793
132507
|
const original = hostPartTypes.has(clean.type) && !containsHostInstance(clean) ? hostParts.get(contentKey(clean)) : undefined;
|
|
131794
132508
|
content.push(original ?? clean);
|
|
@@ -131796,14 +132510,23 @@ function adaptPayload(draft, admittedIDs = new Set) {
|
|
|
131796
132510
|
}
|
|
131797
132511
|
const state = part.state;
|
|
131798
132512
|
if (bridge.native) {
|
|
131799
|
-
const
|
|
131800
|
-
const
|
|
131801
|
-
|
|
131802
|
-
|
|
131803
|
-
|
|
131804
|
-
|
|
132513
|
+
const native = bridge.native;
|
|
132514
|
+
const callID = String(native.id ?? native.callID ?? part.callID);
|
|
132515
|
+
const name = String(native.name ?? native.tool ?? part.tool);
|
|
132516
|
+
content.push({ type: "tool-call", id: callID, name, input: state.input });
|
|
132517
|
+
if (state.status === "completed" || state.status === "error") {
|
|
132518
|
+
following.push({
|
|
132519
|
+
role: "tool",
|
|
132520
|
+
content: [
|
|
132521
|
+
{
|
|
132522
|
+
type: "tool-result",
|
|
132523
|
+
id: callID,
|
|
132524
|
+
name,
|
|
132525
|
+
result: { type: "text", value: state.output }
|
|
132526
|
+
}
|
|
132527
|
+
]
|
|
132528
|
+
});
|
|
131805
132529
|
}
|
|
131806
|
-
content.push({ ...bridge.native, state: nextState });
|
|
131807
132530
|
continue;
|
|
131808
132531
|
}
|
|
131809
132532
|
if (bridge.call)
|
|
@@ -131857,13 +132580,18 @@ class V2ContextRefusal extends Error {
|
|
|
131857
132580
|
this.name = "V2ContextRefusal";
|
|
131858
132581
|
}
|
|
131859
132582
|
}
|
|
131860
|
-
|
|
132583
|
+
var INTERRUPT_CONFIRMATION_TIMEOUT_MS = 2000;
|
|
132584
|
+
var systemTimers = {
|
|
132585
|
+
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
132586
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
132587
|
+
};
|
|
132588
|
+
async function interruptBeforeProvider(session, sessionID, timers = systemTimers) {
|
|
131861
132589
|
let timer;
|
|
131862
132590
|
try {
|
|
131863
132591
|
const result = await Promise.race([
|
|
131864
132592
|
session.interrupt({ sessionID }),
|
|
131865
132593
|
new Promise((_, reject) => {
|
|
131866
|
-
timer = setTimeout(() => reject(new Error(
|
|
132594
|
+
timer = timers.setTimeout(() => reject(new Error(`interrupt exceeded ${INTERRUPT_CONFIRMATION_TIMEOUT_MS} ms`)), INTERRUPT_CONFIRMATION_TIMEOUT_MS);
|
|
131867
132595
|
})
|
|
131868
132596
|
]);
|
|
131869
132597
|
if (result.interrupted !== true)
|
|
@@ -131871,10 +132599,80 @@ async function interruptBeforeProvider(session, sessionID) {
|
|
|
131871
132599
|
} catch (cause) {
|
|
131872
132600
|
throw new V2ContextRefusal(undefined, { cause });
|
|
131873
132601
|
} finally {
|
|
131874
|
-
|
|
132602
|
+
if (timer !== undefined)
|
|
132603
|
+
timers.clearTimeout(timer);
|
|
131875
132604
|
}
|
|
131876
132605
|
}
|
|
131877
132606
|
|
|
132607
|
+
// src/v2/hooks/restore-rows.ts
|
|
132608
|
+
class RestoredRowCache {
|
|
132609
|
+
capacity;
|
|
132610
|
+
sessions = new Map;
|
|
132611
|
+
constructor(capacity = 16) {
|
|
132612
|
+
this.capacity = capacity;
|
|
132613
|
+
}
|
|
132614
|
+
rows(reader, sessionID, after, through) {
|
|
132615
|
+
if (through <= after)
|
|
132616
|
+
return [];
|
|
132617
|
+
const kept = this.sessions.get(sessionID) ?? new Map;
|
|
132618
|
+
const stamps = reader.spanRowStamps(sessionID, after, through);
|
|
132619
|
+
const runs = [];
|
|
132620
|
+
let previous = after;
|
|
132621
|
+
let open;
|
|
132622
|
+
for (const [seq, stamp] of stamps) {
|
|
132623
|
+
if (kept.get(seq)?.stamp === stamp) {
|
|
132624
|
+
open = undefined;
|
|
132625
|
+
} else if (open) {
|
|
132626
|
+
open.through = seq;
|
|
132627
|
+
} else {
|
|
132628
|
+
open = { after: previous, through: seq };
|
|
132629
|
+
runs.push(open);
|
|
132630
|
+
}
|
|
132631
|
+
previous = seq;
|
|
132632
|
+
}
|
|
132633
|
+
const fresh = new Map;
|
|
132634
|
+
for (const run of runs)
|
|
132635
|
+
for (const row of readPages(reader, sessionID, run.after, run.through))
|
|
132636
|
+
fresh.set(row.seq, row);
|
|
132637
|
+
const next = new Map;
|
|
132638
|
+
const rows = [];
|
|
132639
|
+
for (const [seq, stamp] of stamps) {
|
|
132640
|
+
const row = fresh.get(seq) ?? kept.get(seq)?.row;
|
|
132641
|
+
if (!row)
|
|
132642
|
+
continue;
|
|
132643
|
+
next.set(seq, { stamp, row });
|
|
132644
|
+
rows.push(row);
|
|
132645
|
+
}
|
|
132646
|
+
this.sessions.delete(sessionID);
|
|
132647
|
+
this.sessions.set(sessionID, next);
|
|
132648
|
+
while (this.sessions.size > this.capacity) {
|
|
132649
|
+
const oldest = this.sessions.keys().next().value;
|
|
132650
|
+
if (oldest === undefined)
|
|
132651
|
+
break;
|
|
132652
|
+
this.sessions.delete(oldest);
|
|
132653
|
+
}
|
|
132654
|
+
return structuredClone(rows);
|
|
132655
|
+
}
|
|
132656
|
+
forget(sessionID) {
|
|
132657
|
+
this.sessions.delete(sessionID);
|
|
132658
|
+
}
|
|
132659
|
+
clear() {
|
|
132660
|
+
this.sessions.clear();
|
|
132661
|
+
}
|
|
132662
|
+
}
|
|
132663
|
+
function readPages(reader, sessionID, after, through) {
|
|
132664
|
+
const rows = [];
|
|
132665
|
+
let cursor = after;
|
|
132666
|
+
while (cursor < through) {
|
|
132667
|
+
const page = reader.page(sessionID, { after: cursor, through, limit: 100 });
|
|
132668
|
+
rows.push(...page.rows);
|
|
132669
|
+
if (page.rows.length < 100 || page.cursor === undefined)
|
|
132670
|
+
break;
|
|
132671
|
+
cursor = page.cursor;
|
|
132672
|
+
}
|
|
132673
|
+
return rows;
|
|
132674
|
+
}
|
|
132675
|
+
|
|
131878
132676
|
// src/hooks/magic-context/live-session-state.ts
|
|
131879
132677
|
function createLiveSessionState() {
|
|
131880
132678
|
return {
|
|
@@ -145711,7 +146509,7 @@ import { isAbsolute as isAbsolute7 } from "node:path";
|
|
|
145711
146509
|
// ../retina-local-fs/src/path-fence.ts
|
|
145712
146510
|
import { lstat as lstat2, readlink, realpath as realpath2 } from "node:fs/promises";
|
|
145713
146511
|
import { homedir as homedir12 } from "node:os";
|
|
145714
|
-
import { basename as basename4, dirname as dirname10, isAbsolute as isAbsolute6, join as join20, relative, resolve as
|
|
146512
|
+
import { basename as basename4, dirname as dirname10, isAbsolute as isAbsolute6, join as join20, relative, resolve as resolve8, sep } from "node:path";
|
|
145715
146513
|
|
|
145716
146514
|
// ../retina-local-fs/src/errors.ts
|
|
145717
146515
|
class ProviderError extends Error {
|
|
@@ -145727,7 +146525,7 @@ class ProviderError extends Error {
|
|
|
145727
146525
|
async function resolveAndFenceProviderPath(configuredPath, options) {
|
|
145728
146526
|
const { home, dataDirectory } = await resolveFenceRoots(options);
|
|
145729
146527
|
const expanded = configuredPath.startsWith("~/") ? join20(home, configuredPath.slice(2)) : configuredPath === "~" ? home : configuredPath;
|
|
145730
|
-
const absolute = isAbsolute6(expanded) ?
|
|
146528
|
+
const absolute = isAbsolute6(expanded) ? resolve8(expanded) : resolve8(options.cwd ?? process.cwd(), expanded);
|
|
145731
146529
|
const canonical = await canonicalPath(absolute, options.allowMissing);
|
|
145732
146530
|
if (isFencedPath(canonical, home, dataDirectory)) {
|
|
145733
146531
|
throw new ProviderError("fenced_path", `Refusing fenced path: ${canonical}`);
|
|
@@ -145735,14 +146533,14 @@ async function resolveAndFenceProviderPath(configuredPath, options) {
|
|
|
145735
146533
|
return canonical;
|
|
145736
146534
|
}
|
|
145737
146535
|
async function resolveFenceRoots(options) {
|
|
145738
|
-
const configuredHomePath =
|
|
146536
|
+
const configuredHomePath = resolve8(options.homeDirectory ?? process.env.HOME ?? homedir12());
|
|
145739
146537
|
let home;
|
|
145740
146538
|
try {
|
|
145741
146539
|
home = await realpath2(configuredHomePath);
|
|
145742
146540
|
} catch (error) {
|
|
145743
146541
|
throw fsError(configuredHomePath, error);
|
|
145744
146542
|
}
|
|
145745
|
-
const configuredDataDirectory =
|
|
146543
|
+
const configuredDataDirectory = resolve8(options.dataDirectory ?? process.env.XDG_DATA_HOME ?? join20(home, ".local", "share"));
|
|
145746
146544
|
const dataDirectory = await canonicalPath(configuredDataDirectory, true);
|
|
145747
146545
|
return { home, dataDirectory };
|
|
145748
146546
|
}
|
|
@@ -145760,7 +146558,7 @@ async function canonicalPath(path, allowMissing) {
|
|
|
145760
146558
|
const metadata = await lstat2(candidate);
|
|
145761
146559
|
if (metadata.isSymbolicLink()) {
|
|
145762
146560
|
const target = await readlink(candidate);
|
|
145763
|
-
const resolvedTarget =
|
|
146561
|
+
const resolvedTarget = resolve8(dirname10(candidate), target);
|
|
145764
146562
|
return canonicalPath(join20(resolvedTarget, ...suffix), true);
|
|
145765
146563
|
}
|
|
145766
146564
|
} catch (candidateError) {
|
|
@@ -145784,8 +146582,8 @@ async function canonicalPath(path, allowMissing) {
|
|
|
145784
146582
|
}
|
|
145785
146583
|
}
|
|
145786
146584
|
}
|
|
145787
|
-
function isFencedPath(canonicalPath, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join20(
|
|
145788
|
-
const cortexkitRoot = join20(
|
|
146585
|
+
function isFencedPath(canonicalPath, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join20(resolve8(homeDirectory), ".local", "share")) {
|
|
146586
|
+
const cortexkitRoot = join20(resolve8(dataDirectory), "cortexkit");
|
|
145789
146587
|
const relativeToCortexkit = relative(cortexkitRoot, canonicalPath);
|
|
145790
146588
|
const insideCortexkit = relativeToCortexkit !== "" && relativeToCortexkit !== ".." && !relativeToCortexkit.startsWith(`..${sep}`) && !isAbsolute6(relativeToCortexkit);
|
|
145791
146589
|
const parts = insideCortexkit ? relativeToCortexkit.split(sep) : [];
|
|
@@ -147258,6 +148056,7 @@ async function registerContext(context) {
|
|
|
147258
148056
|
const historyRefreshSessions = new Set;
|
|
147259
148057
|
const pendingMaterializationSessions = new Set;
|
|
147260
148058
|
const lastHeuristicsTurnId = new Map;
|
|
148059
|
+
const restoredRows = new RestoredRowCache;
|
|
147261
148060
|
const rawProviders = new Map;
|
|
147262
148061
|
let passDuties;
|
|
147263
148062
|
let toolDuties;
|
|
@@ -147418,6 +148217,7 @@ async function registerContext(context) {
|
|
|
147418
148217
|
historyRefreshSessions.delete(sessionID);
|
|
147419
148218
|
pendingMaterializationSessions.delete(sessionID);
|
|
147420
148219
|
lastHeuristicsTurnId.delete(sessionID);
|
|
148220
|
+
restoredRows.forget(sessionID);
|
|
147421
148221
|
systemPromptRefreshSessions.delete(sessionID);
|
|
147422
148222
|
systemPrompt?.clearSession(sessionID);
|
|
147423
148223
|
tagger.cleanup(sessionID);
|
|
@@ -147642,7 +148442,7 @@ async function registerContext(context) {
|
|
|
147642
148442
|
const servedBoundary = boundaryID ? servedBoundaryRow(reader, draft.sessionID, boundaryID) : null;
|
|
147643
148443
|
const boundary = servedBoundary?.seq ?? reader.sequenceForId(draft.sessionID, boundaryID) ?? (reader.earliestSequence(draft.sessionID) ?? 0) - 1;
|
|
147644
148444
|
const present = new Set(draft.messages.map((message) => message.id));
|
|
147645
|
-
const restored =
|
|
148445
|
+
const restored = restoredRows.rows(reader, draft.sessionID, boundary, cut.seq).filter((row) => !present.has(row.id)).flatMap((row) => restoreRow(row, draft.model, hostUsesMediaAssets() ? {
|
|
147646
148446
|
asset: hostMediaAsset,
|
|
147647
148447
|
unavailable: (detail) => sessionLog(draft.sessionID, `v2 restore: attachment replaced by a note row=${detail.rowID} name=${JSON.stringify(detail.name ?? null)} mediaType=${detail.mediaType} reason=${JSON.stringify(detail.reason)}`)
|
|
147648
148448
|
} : undefined));
|
|
@@ -147795,6 +148595,7 @@ ${baseline}
|
|
|
147795
148595
|
for (const release of rawProviders.values())
|
|
147796
148596
|
release();
|
|
147797
148597
|
rawProviders.clear();
|
|
148598
|
+
restoredRows.clear();
|
|
147798
148599
|
}
|
|
147799
148600
|
};
|
|
147800
148601
|
}
|
|
@@ -147857,7 +148658,7 @@ async function getLatestVersion(channel = "latest", options = {}) {
|
|
|
147857
148658
|
try {
|
|
147858
148659
|
if (options.signal?.aborted)
|
|
147859
148660
|
return null;
|
|
147860
|
-
const response = await fetch(buildRegistryUrl(options.registryUrl ?? NPM_REGISTRY_URL), {
|
|
148661
|
+
const response = await (options.fetch ?? fetch)(buildRegistryUrl(options.registryUrl ?? NPM_REGISTRY_URL), {
|
|
147861
148662
|
signal: controller.signal,
|
|
147862
148663
|
headers: { Accept: "application/json" }
|
|
147863
148664
|
});
|
|
@@ -147895,6 +148696,9 @@ function packageInfo() {
|
|
|
147895
148696
|
directory = parent;
|
|
147896
148697
|
}
|
|
147897
148698
|
}
|
|
148699
|
+
function formatUpdateAvailableMessage(latest, current) {
|
|
148700
|
+
return `Magic Context ${latest} is available (running ${current}). To install it, open /plugins, select Magic Context and press ctrl+u, or run \`opencode plugin update\`. A version-pinned plugin entry must be changed in your OpenCode config instead.`;
|
|
148701
|
+
}
|
|
147898
148702
|
function startUpdateChecks(context, check = (signal) => {
|
|
147899
148703
|
return packageInfo().development ? Promise.resolve(null) : getLatestVersion("latest", { signal });
|
|
147900
148704
|
}) {
|
|
@@ -147909,10 +148713,11 @@ function startUpdateChecks(context, check = (signal) => {
|
|
|
147909
148713
|
continue;
|
|
147910
148714
|
await context.storage.set("version-check-at", Date.now());
|
|
147911
148715
|
const latest = await check(controller.signal);
|
|
147912
|
-
const
|
|
147913
|
-
|
|
148716
|
+
const current = packageInfo().version;
|
|
148717
|
+
const comparison = latest ? compareSemverCore(latest, current) : null;
|
|
148718
|
+
if (latest && !controller.signal.aborted && comparison !== null && comparison > 0) {
|
|
147914
148719
|
pushNotification("toast", {
|
|
147915
|
-
message:
|
|
148720
|
+
message: formatUpdateAvailableMessage(latest, current),
|
|
147916
148721
|
variant: "info"
|
|
147917
148722
|
});
|
|
147918
148723
|
}
|