@rynfar/meridian 1.67.0 → 1.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{cli-35jx6vmy.js → cli-x1sv3bqf.js} +2445 -1070
- package/dist/{cli-n8t34zmq.js → cli-zdbv40d5.js} +45 -10
- package/dist/cli.js +7 -7
- package/dist/meridian/index.js +252 -0
- package/dist/meridian/package.json +6 -0
- package/dist/meridian-v2/index.js +334 -0
- package/dist/meridian-v2/package.json +6 -0
- package/dist/proxy/adapter.d.ts +35 -0
- package/dist/proxy/adapter.d.ts.map +1 -1
- package/dist/proxy/adapters/claudecode.d.ts +23 -0
- package/dist/proxy/adapters/claudecode.d.ts.map +1 -1
- package/dist/proxy/adapters/opencode.d.ts.map +1 -1
- package/dist/proxy/adapters/passthrough.d.ts.map +1 -1
- package/dist/proxy/adapters/pi.d.ts.map +1 -1
- package/dist/proxy/errors.d.ts +2 -0
- package/dist/proxy/errors.d.ts.map +1 -1
- package/dist/proxy/idleStallCeiling.d.ts +74 -0
- package/dist/proxy/idleStallCeiling.d.ts.map +1 -0
- package/dist/proxy/messages.d.ts +7 -4
- package/dist/proxy/messages.d.ts.map +1 -1
- package/dist/proxy/openai.d.ts +12 -0
- package/dist/proxy/openai.d.ts.map +1 -1
- package/dist/proxy/openaiResponses.d.ts +106 -3
- package/dist/proxy/openaiResponses.d.ts.map +1 -1
- package/dist/proxy/passthroughEarlyStop.d.ts +20 -5
- package/dist/proxy/passthroughEarlyStop.d.ts.map +1 -1
- package/dist/proxy/passthroughTools.d.ts +82 -3
- package/dist/proxy/passthroughTools.d.ts.map +1 -1
- package/dist/proxy/query.d.ts +43 -10
- package/dist/proxy/query.d.ts.map +1 -1
- package/dist/proxy/replay.d.ts +24 -0
- package/dist/proxy/replay.d.ts.map +1 -0
- package/dist/proxy/sdkFeatures.d.ts +1 -1
- package/dist/proxy/sdkFeatures.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/cache.d.ts +20 -3
- package/dist/proxy/session/cache.d.ts.map +1 -1
- package/dist/proxy/session/lineage.d.ts +73 -3
- package/dist/proxy/session/lineage.d.ts.map +1 -1
- package/dist/proxy/session/processIncarnation.d.ts +55 -0
- package/dist/proxy/session/processIncarnation.d.ts.map +1 -1
- package/dist/proxy/sessionLifecycle.d.ts +6 -0
- package/dist/proxy/sessionLifecycle.d.ts.map +1 -1
- package/dist/proxy/setup.d.ts +14 -4
- package/dist/proxy/setup.d.ts.map +1 -1
- package/dist/proxy/streamIdleGuard.d.ts +7 -3
- package/dist/proxy/streamIdleGuard.d.ts.map +1 -1
- package/dist/proxy/structuredOutput.d.ts +6 -1
- package/dist/proxy/structuredOutput.d.ts.map +1 -1
- package/dist/proxy/transforms/codex.d.ts +12 -0
- package/dist/proxy/transforms/codex.d.ts.map +1 -1
- package/dist/proxy/turnOutcome.d.ts +2 -0
- package/dist/proxy/turnOutcome.d.ts.map +1 -1
- package/dist/server.js +2 -2
- package/dist/{setup-8fwgwhqh.js → setup-b3ymd9z8.js} +5 -3
- package/dist/telemetry/index.d.ts.map +1 -1
- package/package.json +7 -7
- package/plugin/meridian/index.js +1 -0
- package/plugin/meridian/package.json +6 -0
- package/plugin/meridian-v2/index.js +1 -0
- package/plugin/meridian-v2/package.json +6 -0
- package/plugin/meridian-v2.ts +1 -1
- package/plugin/meridian.ts +1 -1
|
@@ -637,7 +637,7 @@ var init_priorityAttestation = __esm(() => {
|
|
|
637
637
|
|
|
638
638
|
// src/proxy/setup.ts
|
|
639
639
|
var import_cross_spawn = __toESM(require_cross_spawn(), 1);
|
|
640
|
-
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
640
|
+
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
641
641
|
import { homedir as homedir2, platform as platform2 } from "os";
|
|
642
642
|
import { basename, dirname as dirname2, join as join2 } from "path";
|
|
643
643
|
import { fileURLToPath } from "url";
|
|
@@ -720,6 +720,15 @@ class UnparseableConfigError extends Error {
|
|
|
720
720
|
}
|
|
721
721
|
}
|
|
722
722
|
|
|
723
|
+
class MissingV1PluginError extends Error {
|
|
724
|
+
expectedPath;
|
|
725
|
+
constructor(expectedPath) {
|
|
726
|
+
super(`OpenCode V1 plugin bundle not found at ${expectedPath}`);
|
|
727
|
+
this.expectedPath = expectedPath;
|
|
728
|
+
this.name = "MissingV1PluginError";
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
723
732
|
class MissingV2PluginError extends Error {
|
|
724
733
|
expectedPath;
|
|
725
734
|
constructor(expectedPath) {
|
|
@@ -771,21 +780,47 @@ function siblingOpencodeConfigPath(configPath) {
|
|
|
771
780
|
return;
|
|
772
781
|
}
|
|
773
782
|
function findPluginPath(fromUrl) {
|
|
774
|
-
const
|
|
775
|
-
|
|
783
|
+
const entryPath = fileURLToPath(fromUrl);
|
|
784
|
+
const dir = dirname2(entryPath);
|
|
785
|
+
if (entryPath.endsWith(".ts")) {
|
|
786
|
+
const sourcePlugin = join2(dir, "..", "plugin", "meridian");
|
|
787
|
+
if (hasPluginPackageEntry(sourcePlugin))
|
|
788
|
+
return sourcePlugin;
|
|
789
|
+
throw new MissingV1PluginError(sourcePlugin);
|
|
790
|
+
}
|
|
791
|
+
const bundledPlugin = join2(dir, "meridian");
|
|
792
|
+
if (hasPluginPackageEntry(bundledPlugin))
|
|
793
|
+
return bundledPlugin;
|
|
794
|
+
throw new MissingV1PluginError(bundledPlugin);
|
|
795
|
+
}
|
|
796
|
+
var SUPPORTED_OPENCODE_V2_VERSIONS = new Set([
|
|
797
|
+
"0.0.0-beta-18314",
|
|
798
|
+
"0.0.0-beta-18866"
|
|
799
|
+
]);
|
|
800
|
+
function hasPluginPackageEntry(path) {
|
|
801
|
+
try {
|
|
802
|
+
if (!statSync(join2(path, "index.js"), { throwIfNoEntry: false })?.isFile())
|
|
803
|
+
return false;
|
|
804
|
+
const manifest = JSON.parse(readFileSync2(join2(path, "package.json"), "utf8"));
|
|
805
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest))
|
|
806
|
+
return false;
|
|
807
|
+
const fields = manifest;
|
|
808
|
+
return fields.type === "module" && fields.main === "./index.js";
|
|
809
|
+
} catch {
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
776
812
|
}
|
|
777
|
-
var SUPPORTED_OPENCODE_V2_VERSION = "0.0.0-beta-18314";
|
|
778
813
|
function findV2PluginPath(fromUrl) {
|
|
779
814
|
const entryPath = fileURLToPath(fromUrl);
|
|
780
815
|
const dir = dirname2(entryPath);
|
|
781
816
|
if (entryPath.endsWith(".ts")) {
|
|
782
|
-
const sourcePlugin = join2(dir, "..", "plugin", "meridian-v2
|
|
783
|
-
if (
|
|
817
|
+
const sourcePlugin = join2(dir, "..", "plugin", "meridian-v2");
|
|
818
|
+
if (hasPluginPackageEntry(sourcePlugin))
|
|
784
819
|
return sourcePlugin;
|
|
785
820
|
throw new MissingV2PluginError(sourcePlugin);
|
|
786
821
|
}
|
|
787
|
-
const bundledPlugin = join2(dir, "meridian-v2
|
|
788
|
-
if (
|
|
822
|
+
const bundledPlugin = join2(dir, "meridian-v2");
|
|
823
|
+
if (hasPluginPackageEntry(bundledPlugin))
|
|
789
824
|
return bundledPlugin;
|
|
790
825
|
throw new MissingV2PluginError(bundledPlugin);
|
|
791
826
|
}
|
|
@@ -840,7 +875,7 @@ function isMeridianEntry(entry) {
|
|
|
840
875
|
const packageName = pluginEntryPackage(entry);
|
|
841
876
|
if (!packageName)
|
|
842
877
|
return false;
|
|
843
|
-
return STALE_PATTERNS.some((pattern) => packageName.includes(pattern)) || packageName.includes("meridian.ts") || packageName.includes("meridian-v2.") || packageName.includes("@rynfar/meridian");
|
|
878
|
+
return STALE_PATTERNS.some((pattern) => packageName.includes(pattern)) || packageName.includes("meridian.ts") || packageName.includes("meridian-v2.") || packageName.endsWith("/meridian-v2") || /[\\/]meridian$/.test(packageName) || packageName.includes("@rynfar/meridian");
|
|
844
879
|
}
|
|
845
880
|
function checkPluginConfigured(configPath, expectedPluginPath) {
|
|
846
881
|
const selectedPath = configPath ?? findOpencodeConfigPath();
|
|
@@ -936,4 +971,4 @@ function runSetup(pluginPath, configPath, generation = "v1") {
|
|
|
936
971
|
return { configPath: path, pluginPath, alreadyConfigured, removedStale, created: false };
|
|
937
972
|
}
|
|
938
973
|
|
|
939
|
-
export { LRUMap, PRIORITY_ATTESTATION_HEADER, verifyPriorityAttestation, init_priorityAttestation, UnparseableConfigError, MissingV2PluginError, DuplicateMeridianConfigError, findOpencodeConfigPath, findPluginPath,
|
|
974
|
+
export { LRUMap, PRIORITY_ATTESTATION_HEADER, verifyPriorityAttestation, init_priorityAttestation, UnparseableConfigError, MissingV1PluginError, MissingV2PluginError, DuplicateMeridianConfigError, findOpencodeConfigPath, findPluginPath, SUPPORTED_OPENCODE_V2_VERSIONS, findV2PluginPath, classifyOpenCodeVersion, detectOpenCodeGeneration, pluginPathForGeneration, checkPluginConfigured, clearPluginlessWarnings, notePluginlessOpenCodeRequest, runSetup };
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startProxyServer
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-x1sv3bqf.js";
|
|
5
5
|
import"./cli-5jxyma6z.js";
|
|
6
6
|
import"./cli-sry5aqdj.js";
|
|
7
7
|
import"./cli-8yp89fan.js";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./cli-9e5cxp89.js";
|
|
11
11
|
import"./cli-khhjyk04.js";
|
|
12
12
|
import"./cli-vj9cv18n.js";
|
|
13
|
-
import"./cli-
|
|
13
|
+
import"./cli-zdbv40d5.js";
|
|
14
14
|
import {
|
|
15
15
|
__require
|
|
16
16
|
} from "./cli-p9swy5t3.js";
|
|
@@ -91,9 +91,9 @@ if (args[0] === "setup") {
|
|
|
91
91
|
MissingV2PluginError,
|
|
92
92
|
pluginPathForGeneration,
|
|
93
93
|
runSetup,
|
|
94
|
-
|
|
94
|
+
SUPPORTED_OPENCODE_V2_VERSIONS,
|
|
95
95
|
UnparseableConfigError
|
|
96
|
-
} = await import("./setup-
|
|
96
|
+
} = await import("./setup-b3ymd9z8.js");
|
|
97
97
|
const forceV1 = args.includes("--v1");
|
|
98
98
|
const forceV2 = args.includes("--v2");
|
|
99
99
|
if (forceV1 && forceV2) {
|
|
@@ -117,9 +117,9 @@ if (args[0] === "setup") {
|
|
|
117
117
|
console.error("Could not find an OpenCode V2 beta. Install the pinned beta or pass --opencode-bin <path>.");
|
|
118
118
|
process.exit(1);
|
|
119
119
|
}
|
|
120
|
-
if (detected.generation === "v2" && detected.version
|
|
120
|
+
if (detected.generation === "v2" && !SUPPORTED_OPENCODE_V2_VERSIONS.has(detected.version ?? "")) {
|
|
121
121
|
console.error(`OpenCode V2 ${detected.version ?? "unknown"} is not supported by this Meridian build.`);
|
|
122
|
-
console.error(`Install
|
|
122
|
+
console.error(`Install a supported OpenCode beta (${[...SUPPORTED_OPENCODE_V2_VERSIONS].join(", ")}), then re-run meridian setup --v2.`);
|
|
123
123
|
process.exit(1);
|
|
124
124
|
}
|
|
125
125
|
let pluginPath;
|
|
@@ -205,7 +205,7 @@ async function runCli(start = startProxyServer, runAuthCheck = async () => {
|
|
|
205
205
|
return execFile(claudePath, ["auth", "status"], { timeout: 5000 });
|
|
206
206
|
}) {
|
|
207
207
|
try {
|
|
208
|
-
const { findOpencodeConfigPath, checkPluginConfigured, findPluginPath } = await import("./setup-
|
|
208
|
+
const { findOpencodeConfigPath, checkPluginConfigured, findPluginPath } = await import("./setup-b3ymd9z8.js");
|
|
209
209
|
const configPath = findOpencodeConfigPath();
|
|
210
210
|
const { existsSync } = await import("fs");
|
|
211
211
|
if (existsSync(configPath) && !checkPluginConfigured(configPath)) {
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// plugin/priority-attestation.ts
|
|
2
|
+
import { createHash, createHmac } from "node:crypto";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
var PRIORITY_ATTESTATION_HEADER = "x-meridian-opencode-turn";
|
|
7
|
+
var PRIORITY_ATTESTATION_KEY_ENV = "MERIDIAN_OPENCODE_ATTESTATION_KEY";
|
|
8
|
+
var PRIORITY_ATTESTATION_KEY_FILE = "opencode-turn.key";
|
|
9
|
+
var TOKEN_PREFIX = "v1";
|
|
10
|
+
var MAC_DOMAIN = "meridian.opencode.turn.v1\x00";
|
|
11
|
+
var TURN_DOMAIN = "meridian.opencode.human.v1\x00";
|
|
12
|
+
var MAX_HEADER_BYTES = 768;
|
|
13
|
+
var MAX_PAYLOAD_BYTES = 384;
|
|
14
|
+
var TURN_DIGEST_PATTERN = /^[A-Za-z0-9_-]{43}$/;
|
|
15
|
+
var SAFE_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
16
|
+
function configDirectory() {
|
|
17
|
+
return process.env.MERIDIAN_CONFIG_DIR ?? join(homedir(), ".config", "meridian");
|
|
18
|
+
}
|
|
19
|
+
function priorityAttestationKeyPath() {
|
|
20
|
+
return join(configDirectory(), PRIORITY_ATTESTATION_KEY_FILE);
|
|
21
|
+
}
|
|
22
|
+
function isSafeAgentId(value) {
|
|
23
|
+
return value.length >= 1 && value.length <= 64 && value.trim() === value && /^[\x20-\x7E]+$/.test(value);
|
|
24
|
+
}
|
|
25
|
+
function decodeCanonicalBase64Url(raw) {
|
|
26
|
+
if (!/^[A-Za-z0-9_-]+$/.test(raw))
|
|
27
|
+
return;
|
|
28
|
+
const decoded = Buffer.from(raw, "base64url");
|
|
29
|
+
return decoded.toString("base64url") === raw ? decoded : undefined;
|
|
30
|
+
}
|
|
31
|
+
function decodePriorityAttestationKey(raw) {
|
|
32
|
+
if (raw === undefined)
|
|
33
|
+
return;
|
|
34
|
+
const normalized = raw.trim();
|
|
35
|
+
const decoded = decodeCanonicalBase64Url(normalized);
|
|
36
|
+
return decoded?.length === 32 ? decoded : undefined;
|
|
37
|
+
}
|
|
38
|
+
function loadPriorityAttestationKey() {
|
|
39
|
+
const fromEnv = process.env[PRIORITY_ATTESTATION_KEY_ENV];
|
|
40
|
+
if (fromEnv !== undefined)
|
|
41
|
+
return decodePriorityAttestationKey(fromEnv);
|
|
42
|
+
try {
|
|
43
|
+
return decodePriorityAttestationKey(readFileSync(priorityAttestationKeyPath(), "utf8"));
|
|
44
|
+
} catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function computePriorityTurnDigest(input) {
|
|
49
|
+
if (!SAFE_ID_PATTERN.test(input.sessionId) || !SAFE_ID_PATTERN.test(input.humanMessageId)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
return createHash("sha256").update(TURN_DOMAIN).update(input.generation).update("\x00").update(input.sessionId).update("\x00").update(input.humanMessageId).digest("base64url");
|
|
53
|
+
}
|
|
54
|
+
function createPriorityAttestation(input, key = loadPriorityAttestationKey() ?? Buffer.alloc(0)) {
|
|
55
|
+
if (key.length !== 32)
|
|
56
|
+
return;
|
|
57
|
+
if (!SAFE_ID_PATTERN.test(input.sessionId) || !isSafeAgentId(input.agentId))
|
|
58
|
+
return;
|
|
59
|
+
const turnDigest = computePriorityTurnDigest(input);
|
|
60
|
+
if (!turnDigest || !TURN_DIGEST_PATTERN.test(turnDigest))
|
|
61
|
+
return;
|
|
62
|
+
const issuedAt = input.issuedAt;
|
|
63
|
+
if (!Number.isSafeInteger(issuedAt) || issuedAt < 0)
|
|
64
|
+
return;
|
|
65
|
+
const payload = JSON.stringify({
|
|
66
|
+
v: 1,
|
|
67
|
+
g: input.generation,
|
|
68
|
+
s: input.sessionId,
|
|
69
|
+
a: input.agentId,
|
|
70
|
+
t: turnDigest,
|
|
71
|
+
iat: issuedAt
|
|
72
|
+
});
|
|
73
|
+
if (Buffer.byteLength(payload) > MAX_PAYLOAD_BYTES)
|
|
74
|
+
return;
|
|
75
|
+
const encodedPayload = Buffer.from(payload).toString("base64url");
|
|
76
|
+
const mac = createHmac("sha256", key).update(MAC_DOMAIN).update(payload).digest("base64url");
|
|
77
|
+
const token = `${TOKEN_PREFIX}.${encodedPayload}.${mac}`;
|
|
78
|
+
return Buffer.byteLength(token) <= MAX_HEADER_BYTES ? token : undefined;
|
|
79
|
+
}
|
|
80
|
+
function deleteHeader(headers, name) {
|
|
81
|
+
if (headers instanceof Headers) {
|
|
82
|
+
headers.delete(name);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const lower = name.toLowerCase();
|
|
86
|
+
for (const key of Object.keys(headers)) {
|
|
87
|
+
if (key.toLowerCase() === lower)
|
|
88
|
+
delete headers[key];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function getHeader(headers, name) {
|
|
92
|
+
if (headers instanceof Headers)
|
|
93
|
+
return headers.get(name) ?? undefined;
|
|
94
|
+
const lower = name.toLowerCase();
|
|
95
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
96
|
+
if (key.toLowerCase() === lower)
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
function setHeader(headers, name, value) {
|
|
102
|
+
deleteHeader(headers, name);
|
|
103
|
+
if (headers instanceof Headers)
|
|
104
|
+
headers.set(name, value);
|
|
105
|
+
else
|
|
106
|
+
headers[name] = value;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// plugin/meridian.ts
|
|
110
|
+
var BUILTIN_AGENT_MODES = {
|
|
111
|
+
build: "primary",
|
|
112
|
+
plan: "primary",
|
|
113
|
+
general: "subagent",
|
|
114
|
+
explore: "subagent",
|
|
115
|
+
title: "subagent",
|
|
116
|
+
summary: "subagent",
|
|
117
|
+
compaction: "subagent"
|
|
118
|
+
};
|
|
119
|
+
var INTERNAL_AGENT_IDS = new Set(["title", "summary", "compaction"]);
|
|
120
|
+
var ROOT_SESSION_CACHE_MAX = 256;
|
|
121
|
+
var ROOT_SESSION_CACHE_TTL_MS = 5000;
|
|
122
|
+
var LOOKUP_TIMEOUT_MS = 250;
|
|
123
|
+
function isRecord(value) {
|
|
124
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
125
|
+
}
|
|
126
|
+
async function withTimeout(pending, timeoutMs) {
|
|
127
|
+
let timer;
|
|
128
|
+
const timedOut = new Promise((resolve) => {
|
|
129
|
+
timer = setTimeout(() => resolve(undefined), timeoutMs);
|
|
130
|
+
timer.unref?.();
|
|
131
|
+
});
|
|
132
|
+
try {
|
|
133
|
+
return await Promise.race([pending, timedOut]);
|
|
134
|
+
} finally {
|
|
135
|
+
if (timer)
|
|
136
|
+
clearTimeout(timer);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
var MeridianPlugin = async (pluginInput) => {
|
|
140
|
+
let configAgents = {};
|
|
141
|
+
const rootSessionCache = new Map;
|
|
142
|
+
const resolve = (agent) => {
|
|
143
|
+
if (typeof agent === "object" && agent !== null) {
|
|
144
|
+
return { name: agent.name ?? "unknown", mode: agent.mode ?? "primary" };
|
|
145
|
+
}
|
|
146
|
+
const name = String(agent);
|
|
147
|
+
return { name, mode: configAgents[name]?.mode ?? BUILTIN_AGENT_MODES[name] ?? "primary" };
|
|
148
|
+
};
|
|
149
|
+
const isStrictVisiblePrimary = (agent) => {
|
|
150
|
+
const name = typeof agent === "string" ? agent : agent.name;
|
|
151
|
+
if (!name || INTERNAL_AGENT_IDS.has(name))
|
|
152
|
+
return false;
|
|
153
|
+
if (typeof agent === "object") {
|
|
154
|
+
return agent.mode === "primary" && agent.hidden !== true;
|
|
155
|
+
}
|
|
156
|
+
const configured = configAgents[name];
|
|
157
|
+
if (configured)
|
|
158
|
+
return configured.mode === "primary" && configured.hidden !== true;
|
|
159
|
+
return BUILTIN_AGENT_MODES[name] === "primary";
|
|
160
|
+
};
|
|
161
|
+
const isRootSession = async (sessionID) => {
|
|
162
|
+
const cached = rootSessionCache.get(sessionID);
|
|
163
|
+
if (cached && cached.expiresAt > Date.now())
|
|
164
|
+
return cached.pending;
|
|
165
|
+
const pending = (async () => {
|
|
166
|
+
if (!isRecord(pluginInput) || !isRecord(pluginInput.client))
|
|
167
|
+
return false;
|
|
168
|
+
const sessionApi = pluginInput.client.session;
|
|
169
|
+
if (!isRecord(sessionApi) || typeof sessionApi.get !== "function")
|
|
170
|
+
return false;
|
|
171
|
+
const controller = new AbortController;
|
|
172
|
+
try {
|
|
173
|
+
const lookup = Promise.resolve(Reflect.apply(sessionApi.get, sessionApi, [
|
|
174
|
+
{ path: { id: sessionID }, signal: controller.signal }
|
|
175
|
+
]));
|
|
176
|
+
const result = await withTimeout(lookup, LOOKUP_TIMEOUT_MS);
|
|
177
|
+
if (!isRecord(result))
|
|
178
|
+
return false;
|
|
179
|
+
const data = isRecord(result.data) ? result.data : result;
|
|
180
|
+
return data.id === sessionID && data.parentID === undefined && data.fork === undefined;
|
|
181
|
+
} catch {
|
|
182
|
+
return false;
|
|
183
|
+
} finally {
|
|
184
|
+
controller.abort();
|
|
185
|
+
}
|
|
186
|
+
})();
|
|
187
|
+
rootSessionCache.delete(sessionID);
|
|
188
|
+
rootSessionCache.set(sessionID, { expiresAt: Date.now() + ROOT_SESSION_CACHE_TTL_MS, pending });
|
|
189
|
+
while (rootSessionCache.size > ROOT_SESSION_CACHE_MAX) {
|
|
190
|
+
const oldest = rootSessionCache.keys().next().value;
|
|
191
|
+
if (oldest === undefined)
|
|
192
|
+
break;
|
|
193
|
+
rootSessionCache.delete(oldest);
|
|
194
|
+
}
|
|
195
|
+
const eligible = await pending;
|
|
196
|
+
if (!eligible && rootSessionCache.get(sessionID)?.pending === pending)
|
|
197
|
+
rootSessionCache.delete(sessionID);
|
|
198
|
+
return eligible;
|
|
199
|
+
};
|
|
200
|
+
return {
|
|
201
|
+
config: (cfg) => {
|
|
202
|
+
const next = {};
|
|
203
|
+
for (const [name, def] of Object.entries(cfg?.agent ?? {})) {
|
|
204
|
+
if (!def)
|
|
205
|
+
continue;
|
|
206
|
+
next[name] = {
|
|
207
|
+
...typeof def.mode === "string" ? { mode: def.mode } : {},
|
|
208
|
+
...typeof def.hidden === "boolean" ? { hidden: def.hidden } : {}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
configAgents = next;
|
|
212
|
+
},
|
|
213
|
+
"chat.headers": async (incoming, output) => {
|
|
214
|
+
deleteHeader(output.headers, PRIORITY_ATTESTATION_HEADER);
|
|
215
|
+
if (incoming.model.providerID !== "anthropic")
|
|
216
|
+
return;
|
|
217
|
+
setHeader(output.headers, "x-opencode-session", incoming.sessionID);
|
|
218
|
+
setHeader(output.headers, "x-opencode-request", incoming.message.id);
|
|
219
|
+
const { name, mode } = resolve(incoming.agent);
|
|
220
|
+
const safeName = name.replace(/[^\x20-\x7E]/g, "").trim() || "unknown";
|
|
221
|
+
setHeader(output.headers, "x-opencode-agent-mode", mode === "subagent" ? "subagent" : "primary");
|
|
222
|
+
setHeader(output.headers, "x-opencode-agent-name", safeName);
|
|
223
|
+
if (getHeader(output.headers, "x-meridian-profile") !== undefined)
|
|
224
|
+
return;
|
|
225
|
+
if (safeName !== name || !isStrictVisiblePrimary(incoming.agent))
|
|
226
|
+
return;
|
|
227
|
+
const createdAt = incoming.message.time?.created;
|
|
228
|
+
if (typeof createdAt !== "number" || !Number.isSafeInteger(createdAt) || createdAt < 0)
|
|
229
|
+
return;
|
|
230
|
+
const issuedAt = Math.floor(createdAt / 1000);
|
|
231
|
+
if (incoming.message.sessionID !== undefined && incoming.message.sessionID !== incoming.sessionID)
|
|
232
|
+
return;
|
|
233
|
+
if (!await isRootSession(incoming.sessionID))
|
|
234
|
+
return;
|
|
235
|
+
if (!isStrictVisiblePrimary(incoming.agent))
|
|
236
|
+
return;
|
|
237
|
+
const token = createPriorityAttestation({
|
|
238
|
+
generation: "oc1",
|
|
239
|
+
sessionId: incoming.sessionID,
|
|
240
|
+
agentId: safeName,
|
|
241
|
+
humanMessageId: incoming.message.id,
|
|
242
|
+
issuedAt
|
|
243
|
+
});
|
|
244
|
+
if (token)
|
|
245
|
+
setHeader(output.headers, PRIORITY_ATTESTATION_HEADER, token);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
var meridian_default = MeridianPlugin;
|
|
250
|
+
export {
|
|
251
|
+
meridian_default as default
|
|
252
|
+
};
|