@massa-ai/mcp-client 1.51.0 → 1.53.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/config-cli.js +309 -41
- package/dist/index.js +710 -46
- package/package.json +3 -3
package/dist/config-cli.js
CHANGED
|
@@ -2174,17 +2174,11 @@ function detectRoute(platform, host) {
|
|
|
2174
2174
|
if (route === "file")
|
|
2175
2175
|
return { kind: "proceed" };
|
|
2176
2176
|
if (route === "marketplace") {
|
|
2177
|
-
if (host === "claude")
|
|
2177
|
+
if (host === "claude" || host === "codex")
|
|
2178
2178
|
return { kind: "proceed" };
|
|
2179
|
-
if (host === "codex") {
|
|
2180
|
-
return {
|
|
2181
|
-
kind: "refuse",
|
|
2182
|
-
reason: "codex marketplace-route installs are refused (in-place bundle rewrite would dirty a checkout " + "and break the drift gate) \u2014 use the dev path: MASSA_AI_MODEL_PROFILE + regenerate."
|
|
2183
|
-
};
|
|
2184
|
-
}
|
|
2185
2179
|
return {
|
|
2186
2180
|
kind: "refuse",
|
|
2187
|
-
reason: "
|
|
2181
|
+
reason: "marketplace-route installs need an explicit, supported host before switching " + "(claude and codex proceed; no other host resolves a live write target yet) \u2014 " + "use the dev path: MASSA_AI_MODEL_PROFILE + regenerate."
|
|
2188
2182
|
};
|
|
2189
2183
|
}
|
|
2190
2184
|
return {
|
|
@@ -2383,6 +2377,61 @@ var init_lock = __esm(() => {
|
|
|
2383
2377
|
import fs5 from "fs";
|
|
2384
2378
|
import os5 from "os";
|
|
2385
2379
|
import path9 from "path";
|
|
2380
|
+
function splitPluginKey(pluginKey) {
|
|
2381
|
+
const at = pluginKey.indexOf("@");
|
|
2382
|
+
if (at === -1)
|
|
2383
|
+
return null;
|
|
2384
|
+
const pluginName = pluginKey.slice(0, at);
|
|
2385
|
+
const marketplaceName = pluginKey.slice(at + 1);
|
|
2386
|
+
if (!pluginName || !marketplaceName)
|
|
2387
|
+
return null;
|
|
2388
|
+
return { pluginName, marketplaceName };
|
|
2389
|
+
}
|
|
2390
|
+
function isContainedPath(root, candidate) {
|
|
2391
|
+
const rel = path9.relative(root, candidate);
|
|
2392
|
+
return rel === "" || !rel.startsWith("..") && !path9.isAbsolute(rel);
|
|
2393
|
+
}
|
|
2394
|
+
function resolveDirectorySourceRoot(targetHome, pluginKey) {
|
|
2395
|
+
const split = splitPluginKey(pluginKey);
|
|
2396
|
+
if (!split)
|
|
2397
|
+
return;
|
|
2398
|
+
const { pluginName, marketplaceName } = split;
|
|
2399
|
+
const knownMarketplacesPath = path9.join(targetHome, ".claude", "plugins", "known_marketplaces.json");
|
|
2400
|
+
let known;
|
|
2401
|
+
try {
|
|
2402
|
+
known = JSON.parse(fs5.readFileSync(knownMarketplacesPath, "utf8"));
|
|
2403
|
+
} catch {
|
|
2404
|
+
return;
|
|
2405
|
+
}
|
|
2406
|
+
const entry = known?.[marketplaceName];
|
|
2407
|
+
if (!entry || entry.source?.source !== "directory")
|
|
2408
|
+
return;
|
|
2409
|
+
const installLocation = entry.installLocation;
|
|
2410
|
+
if (!installLocation)
|
|
2411
|
+
return null;
|
|
2412
|
+
const manifestPath = path9.join(installLocation, ".claude-plugin", "marketplace.json");
|
|
2413
|
+
let manifest;
|
|
2414
|
+
try {
|
|
2415
|
+
manifest = JSON.parse(fs5.readFileSync(manifestPath, "utf8"));
|
|
2416
|
+
} catch {
|
|
2417
|
+
return null;
|
|
2418
|
+
}
|
|
2419
|
+
const plugin = manifest.plugins?.find((p) => p?.name === pluginName);
|
|
2420
|
+
const relSource = plugin?.source;
|
|
2421
|
+
if (!relSource)
|
|
2422
|
+
return null;
|
|
2423
|
+
const resolvedInstallLocation = path9.resolve(installLocation);
|
|
2424
|
+
const composed = path9.resolve(resolvedInstallLocation, relSource);
|
|
2425
|
+
if (!isContainedPath(resolvedInstallLocation, composed))
|
|
2426
|
+
return null;
|
|
2427
|
+
try {
|
|
2428
|
+
if (!fs5.existsSync(composed))
|
|
2429
|
+
return null;
|
|
2430
|
+
} catch {
|
|
2431
|
+
return null;
|
|
2432
|
+
}
|
|
2433
|
+
return composed;
|
|
2434
|
+
}
|
|
2386
2435
|
function selectRecord(records) {
|
|
2387
2436
|
if (records.length === 0)
|
|
2388
2437
|
return;
|
|
@@ -2402,6 +2451,9 @@ function selectRecord(records) {
|
|
|
2402
2451
|
function resolveClaudeMarketplaceRoot(opts = {}) {
|
|
2403
2452
|
const targetHome = opts.targetHome ?? os5.homedir();
|
|
2404
2453
|
const pluginKey = opts.pluginKey ?? DEFAULT_PLUGIN_KEY;
|
|
2454
|
+
const directoryResult = resolveDirectorySourceRoot(targetHome, pluginKey);
|
|
2455
|
+
if (directoryResult !== undefined)
|
|
2456
|
+
return directoryResult;
|
|
2405
2457
|
const registryPath = path9.join(targetHome, ".claude", "plugins", "installed_plugins.json");
|
|
2406
2458
|
let records;
|
|
2407
2459
|
try {
|
|
@@ -2433,6 +2485,7 @@ import fs6 from "fs";
|
|
|
2433
2485
|
import path10 from "path";
|
|
2434
2486
|
import os6 from "os";
|
|
2435
2487
|
import crypto4 from "crypto";
|
|
2488
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
2436
2489
|
function namedError3(name, message) {
|
|
2437
2490
|
const err = new SwitchEngineError(message);
|
|
2438
2491
|
err.name = name;
|
|
@@ -2511,6 +2564,46 @@ function matchesGlob(filename, glob) {
|
|
|
2511
2564
|
const suffix = glob.slice(starIdx + 1);
|
|
2512
2565
|
return filename.length >= prefix.length + suffix.length && filename.startsWith(prefix) && filename.endsWith(suffix);
|
|
2513
2566
|
}
|
|
2567
|
+
function matchingFileNames(dir, glob) {
|
|
2568
|
+
return fs6.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && matchesGlob(e.name, glob)).map((e) => e.name);
|
|
2569
|
+
}
|
|
2570
|
+
function detectGitAvailability(dir) {
|
|
2571
|
+
try {
|
|
2572
|
+
const out = execFileSync2("git", ["-C", dir, "rev-parse", "--is-inside-work-tree"], {
|
|
2573
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2574
|
+
});
|
|
2575
|
+
return out.toString().trim() === "true" ? "in-repo" : "not-a-repo";
|
|
2576
|
+
} catch (err) {
|
|
2577
|
+
return err.code === "ENOENT" ? "no-git" : "not-a-repo";
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
function gitTrackedFileNames(dir, filenames) {
|
|
2581
|
+
if (filenames.length === 0)
|
|
2582
|
+
return new Set;
|
|
2583
|
+
try {
|
|
2584
|
+
const out = execFileSync2("git", ["-C", dir, "ls-files", "--", ...filenames], {
|
|
2585
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2586
|
+
});
|
|
2587
|
+
return new Set(out.toString().split(`
|
|
2588
|
+
`).map((line) => line.trim()).filter(Boolean));
|
|
2589
|
+
} catch {
|
|
2590
|
+
return new Set;
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
function checkTrackedPathGuard(activeDir, filenames) {
|
|
2594
|
+
if (filenames.length === 0 || !fs6.existsSync(activeDir))
|
|
2595
|
+
return GUARD_PASS;
|
|
2596
|
+
const availability = detectGitAvailability(activeDir);
|
|
2597
|
+
if (availability === "no-git")
|
|
2598
|
+
return GUARD_UNCHECKED;
|
|
2599
|
+
if (availability === "not-a-repo")
|
|
2600
|
+
return GUARD_PASS;
|
|
2601
|
+
const tracked = gitTrackedFileNames(activeDir, filenames);
|
|
2602
|
+
if (tracked.size === 0)
|
|
2603
|
+
return GUARD_PASS;
|
|
2604
|
+
const offending = filenames.find((name) => tracked.has(name));
|
|
2605
|
+
return { blocked: true, path: path10.join(activeDir, offending), unchecked: false };
|
|
2606
|
+
}
|
|
2514
2607
|
function assertStateWritable(stateFilePath) {
|
|
2515
2608
|
const dir = path10.dirname(stateFilePath);
|
|
2516
2609
|
try {
|
|
@@ -2640,12 +2733,27 @@ function switchProfile(opts) {
|
|
|
2640
2733
|
rows.push({ host: h.host, status: "switched" });
|
|
2641
2734
|
continue;
|
|
2642
2735
|
}
|
|
2736
|
+
const candidateNames = matchingFileNames(h.variantDir, h.layout.activeGlob);
|
|
2737
|
+
const guard = checkTrackedPathGuard(h.layout.activeDir, candidateNames);
|
|
2738
|
+
if (guard.blocked) {
|
|
2739
|
+
rows.push({
|
|
2740
|
+
host: h.host,
|
|
2741
|
+
status: "failed",
|
|
2742
|
+
reason: `refusing to write ${guard.path} \u2014 it is tracked by git and this switch would dirty the checkout`
|
|
2743
|
+
});
|
|
2744
|
+
continue;
|
|
2745
|
+
}
|
|
2643
2746
|
try {
|
|
2644
2747
|
const filesChanged = copyVariant(h.host, h.layout, h.variantDir);
|
|
2645
2748
|
updatePlatform(stateFilePath, h.host, {
|
|
2646
2749
|
modelProfile: { profile: opts.profile, switchedAt: new Date().toISOString() }
|
|
2647
2750
|
});
|
|
2648
|
-
rows.push({
|
|
2751
|
+
rows.push({
|
|
2752
|
+
host: h.host,
|
|
2753
|
+
status: "switched",
|
|
2754
|
+
filesChanged,
|
|
2755
|
+
...guard.unchecked ? { reason: "tracked-path guard could not verify (git unavailable) \u2014 proceeded unchecked" } : {}
|
|
2756
|
+
});
|
|
2649
2757
|
} catch (err) {
|
|
2650
2758
|
rows.push({ host: h.host, status: "failed", reason: err.message });
|
|
2651
2759
|
}
|
|
@@ -2661,7 +2769,7 @@ function orderRows(universe, rows) {
|
|
|
2661
2769
|
const byHost = new Map(rows.map((r) => [r.host, r]));
|
|
2662
2770
|
return HOSTS.filter((h) => universe.includes(h) && byHost.has(h)).map((h) => byHost.get(h));
|
|
2663
2771
|
}
|
|
2664
|
-
var SwitchEngineError, UnknownProfileError = (profile, known) => namedError3("UnknownProfileError", `unknown profile "${profile}" \u2014 installed: ${known.length > 0 ? known.join(", ") : "none"}`), NoHostsDetectedError = () => namedError3("NoHostsDetectedError", "no installed hosts found");
|
|
2772
|
+
var SwitchEngineError, UnknownProfileError = (profile, known) => namedError3("UnknownProfileError", `unknown profile "${profile}" \u2014 installed: ${known.length > 0 ? known.join(", ") : "none"}`), NoHostsDetectedError = () => namedError3("NoHostsDetectedError", "no installed hosts found"), GUARD_PASS, GUARD_UNCHECKED;
|
|
2665
2773
|
var init_engine = __esm(() => {
|
|
2666
2774
|
init_hosts();
|
|
2667
2775
|
init_state();
|
|
@@ -2673,6 +2781,8 @@ var init_engine = __esm(() => {
|
|
|
2673
2781
|
this.name = "SwitchEngineError";
|
|
2674
2782
|
}
|
|
2675
2783
|
};
|
|
2784
|
+
GUARD_PASS = { blocked: false, unchecked: false };
|
|
2785
|
+
GUARD_UNCHECKED = { blocked: false, unchecked: true };
|
|
2676
2786
|
});
|
|
2677
2787
|
|
|
2678
2788
|
// ../../packages/shared/dist/profile-switch/report.js
|
|
@@ -122043,7 +122153,7 @@ var init_context_controller = __esm(() => {
|
|
|
122043
122153
|
});
|
|
122044
122154
|
|
|
122045
122155
|
// ../../packages/core/dist/services/executor/runtime.js
|
|
122046
|
-
import { execFileSync as
|
|
122156
|
+
import { execFileSync as execFileSync3, execSync } from "child_process";
|
|
122047
122157
|
function commandExists(cmd) {
|
|
122048
122158
|
try {
|
|
122049
122159
|
const check2 = isWindows ? `where ${cmd}` : `command -v ${cmd}`;
|
|
@@ -122076,7 +122186,7 @@ function getVersion(cmd, args = ["--version"], deps) {
|
|
|
122076
122186
|
timeout: 5000
|
|
122077
122187
|
}).trim().split(/\r?\n/)[0];
|
|
122078
122188
|
}
|
|
122079
|
-
return
|
|
122189
|
+
return execFileSync3(cmd, args, {
|
|
122080
122190
|
encoding: "utf-8",
|
|
122081
122191
|
stdio: ["pipe", "pipe", "pipe"],
|
|
122082
122192
|
timeout: 5000
|
|
@@ -122217,12 +122327,12 @@ var init_runtime = __esm(() => {
|
|
|
122217
122327
|
|
|
122218
122328
|
// ../../packages/core/dist/services/executor/sandbox.js
|
|
122219
122329
|
import { realpathSync as realpathSync2 } from "fs";
|
|
122220
|
-
import { execFileSync as
|
|
122330
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
122221
122331
|
function isDockerAvailable() {
|
|
122222
122332
|
if (_dockerAvailable !== null)
|
|
122223
122333
|
return _dockerAvailable;
|
|
122224
122334
|
try {
|
|
122225
|
-
|
|
122335
|
+
execFileSync4("docker", ["--version"], { stdio: "pipe", timeout: 5000 });
|
|
122226
122336
|
_dockerAvailable = true;
|
|
122227
122337
|
} catch {
|
|
122228
122338
|
_dockerAvailable = false;
|
|
@@ -122233,7 +122343,7 @@ function isSeatbeltAvailable() {
|
|
|
122233
122343
|
if (_seatbeltAvailable !== null)
|
|
122234
122344
|
return _seatbeltAvailable;
|
|
122235
122345
|
try {
|
|
122236
|
-
|
|
122346
|
+
execFileSync4("sandbox-exec", ["--version"], { stdio: "pipe", timeout: 5000 });
|
|
122237
122347
|
_seatbeltAvailable = true;
|
|
122238
122348
|
} catch {
|
|
122239
122349
|
_seatbeltAvailable = false;
|
|
@@ -122338,7 +122448,7 @@ var init_sandbox = __esm(() => {
|
|
|
122338
122448
|
});
|
|
122339
122449
|
|
|
122340
122450
|
// ../../packages/core/dist/services/executor/executor.js
|
|
122341
|
-
import { spawn, execSync as execSync2, execFileSync as
|
|
122451
|
+
import { spawn, execSync as execSync2, execFileSync as execFileSync5 } from "child_process";
|
|
122342
122452
|
import { mkdtempSync, writeFileSync as writeFileSync2, rmSync, realpathSync as realpathSync3 } from "fs";
|
|
122343
122453
|
import { join as join3, resolve as resolve5, isAbsolute, relative as relative2 } from "path";
|
|
122344
122454
|
import { tmpdir } from "os";
|
|
@@ -122541,7 +122651,7 @@ ${body}`;
|
|
|
122541
122651
|
const binPath = srcPath.replace(/\.rs$/, isWin ? ".exe" : "");
|
|
122542
122652
|
try {
|
|
122543
122653
|
try {
|
|
122544
|
-
|
|
122654
|
+
execFileSync5("rustc", [srcPath, "-o", binPath], {
|
|
122545
122655
|
cwd,
|
|
122546
122656
|
timeout: Math.min(timeout, 60000),
|
|
122547
122657
|
encoding: "utf-8",
|
|
@@ -123516,7 +123626,7 @@ var init_git_ref_validation = __esm(() => {
|
|
|
123516
123626
|
});
|
|
123517
123627
|
|
|
123518
123628
|
// ../../packages/core/dist/services/symbol/impact-analysis.js
|
|
123519
|
-
import { execFileSync as
|
|
123629
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
123520
123630
|
function readBfsCteFlag() {
|
|
123521
123631
|
try {
|
|
123522
123632
|
return Boolean(config.get("impact")?.bfsCteEnabled);
|
|
@@ -123842,19 +123952,19 @@ function defaultDiffRunner(projectPath, scope, baseBranch, since) {
|
|
|
123842
123952
|
let diffRange;
|
|
123843
123953
|
if (since) {
|
|
123844
123954
|
try {
|
|
123845
|
-
ref =
|
|
123955
|
+
ref = execFileSync6("git", ["-C", projectPath, "rev-parse", "--verify", `${since}^{commit}`], {
|
|
123846
123956
|
cwd: projectPath,
|
|
123847
123957
|
encoding: "utf-8",
|
|
123848
123958
|
stdio: ["ignore", "pipe", "pipe"]
|
|
123849
123959
|
}).trim();
|
|
123850
123960
|
} catch {
|
|
123851
|
-
ref =
|
|
123961
|
+
ref = execFileSync6("git", ["-C", projectPath, "rev-list", "-1", `--before=${since}`, "HEAD"], {
|
|
123852
123962
|
cwd: projectPath,
|
|
123853
123963
|
encoding: "utf-8",
|
|
123854
123964
|
stdio: ["ignore", "pipe", "pipe"]
|
|
123855
123965
|
}).trim();
|
|
123856
123966
|
if (!ref) {
|
|
123857
|
-
const emptyTree =
|
|
123967
|
+
const emptyTree = execFileSync6("git", ["hash-object", "-t", "tree", "--stdin"], {
|
|
123858
123968
|
cwd: projectPath,
|
|
123859
123969
|
encoding: "utf-8",
|
|
123860
123970
|
input: "",
|
|
@@ -123866,7 +123976,7 @@ function defaultDiffRunner(projectPath, scope, baseBranch, since) {
|
|
|
123866
123976
|
}
|
|
123867
123977
|
args.push(diffRange ?? `${ref}...HEAD`);
|
|
123868
123978
|
}
|
|
123869
|
-
const out =
|
|
123979
|
+
const out = execFileSync6("git", args, {
|
|
123870
123980
|
cwd: projectPath,
|
|
123871
123981
|
encoding: "utf-8",
|
|
123872
123982
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -123878,7 +123988,7 @@ function defaultDiffRunner(projectPath, scope, baseBranch, since) {
|
|
|
123878
123988
|
let untrackedFiltered = 0;
|
|
123879
123989
|
const merged = new Set(tracked);
|
|
123880
123990
|
if (includeUntracked) {
|
|
123881
|
-
const untracked =
|
|
123991
|
+
const untracked = execFileSync6("git", ["-C", projectPath, "ls-files", "--others", "--exclude-standard"], {
|
|
123882
123992
|
cwd: projectPath,
|
|
123883
123993
|
encoding: "utf-8",
|
|
123884
123994
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -126760,6 +126870,85 @@ var init_scheduler = __esm(() => {
|
|
|
126760
126870
|
};
|
|
126761
126871
|
});
|
|
126762
126872
|
|
|
126873
|
+
// ../../packages/core/dist/data/proposal/proposal-payload-validation.js
|
|
126874
|
+
function isRecord(value) {
|
|
126875
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
126876
|
+
}
|
|
126877
|
+
function isStringArray(value) {
|
|
126878
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
126879
|
+
}
|
|
126880
|
+
function isString(value) {
|
|
126881
|
+
return typeof value === "string";
|
|
126882
|
+
}
|
|
126883
|
+
function isNumber(value) {
|
|
126884
|
+
return typeof value === "number";
|
|
126885
|
+
}
|
|
126886
|
+
function isValidProposalPayload(kind, value) {
|
|
126887
|
+
const rule = PROPOSAL_PAYLOAD_RULES[kind];
|
|
126888
|
+
if (!Object.keys(value).every((key) => rule.allowedKeys.includes(key)))
|
|
126889
|
+
return false;
|
|
126890
|
+
if (rule.requireNonEmpty && Object.keys(value).length === 0)
|
|
126891
|
+
return false;
|
|
126892
|
+
for (const [field, fieldRule] of Object.entries(rule.fields)) {
|
|
126893
|
+
const present = value[field] !== undefined;
|
|
126894
|
+
if (!present) {
|
|
126895
|
+
if (!fieldRule.optional)
|
|
126896
|
+
return false;
|
|
126897
|
+
continue;
|
|
126898
|
+
}
|
|
126899
|
+
if (!fieldRule.validate(value[field]))
|
|
126900
|
+
return false;
|
|
126901
|
+
}
|
|
126902
|
+
return true;
|
|
126903
|
+
}
|
|
126904
|
+
function assertValidProposalPayload(kind, value) {
|
|
126905
|
+
if (!isRecord(value)) {
|
|
126906
|
+
throw new ProposalPayloadValidationError(kind, `proposal payload must be an object for kind "${kind}"`);
|
|
126907
|
+
}
|
|
126908
|
+
if (!isValidProposalPayload(kind, value)) {
|
|
126909
|
+
throw new ProposalPayloadValidationError(kind, `proposal payload is invalid for kind "${kind}"`);
|
|
126910
|
+
}
|
|
126911
|
+
}
|
|
126912
|
+
var PROPOSAL_PAYLOAD_RULES, ProposalPayloadValidationError;
|
|
126913
|
+
var init_proposal_payload_validation = __esm(() => {
|
|
126914
|
+
PROPOSAL_PAYLOAD_RULES = {
|
|
126915
|
+
"memory.create": {
|
|
126916
|
+
allowedKeys: ["content", "type", "level", "importance", "tags"],
|
|
126917
|
+
fields: {
|
|
126918
|
+
content: { optional: false, validate: isString },
|
|
126919
|
+
type: { optional: true, validate: isString },
|
|
126920
|
+
level: { optional: true, validate: isNumber },
|
|
126921
|
+
importance: { optional: true, validate: isNumber },
|
|
126922
|
+
tags: { optional: true, validate: isStringArray }
|
|
126923
|
+
}
|
|
126924
|
+
},
|
|
126925
|
+
"memory.update": {
|
|
126926
|
+
allowedKeys: ["content", "importance", "tags"],
|
|
126927
|
+
requireNonEmpty: true,
|
|
126928
|
+
fields: {
|
|
126929
|
+
content: { optional: true, validate: isString },
|
|
126930
|
+
importance: { optional: true, validate: isNumber },
|
|
126931
|
+
tags: { optional: true, validate: isStringArray }
|
|
126932
|
+
}
|
|
126933
|
+
},
|
|
126934
|
+
"memory.tag": {
|
|
126935
|
+
allowedKeys: ["tags"],
|
|
126936
|
+
fields: {
|
|
126937
|
+
tags: { optional: false, validate: isStringArray }
|
|
126938
|
+
}
|
|
126939
|
+
}
|
|
126940
|
+
};
|
|
126941
|
+
ProposalPayloadValidationError = class ProposalPayloadValidationError extends Error {
|
|
126942
|
+
kind;
|
|
126943
|
+
statusCode = 400;
|
|
126944
|
+
constructor(kind, message) {
|
|
126945
|
+
super(message);
|
|
126946
|
+
this.kind = kind;
|
|
126947
|
+
this.name = "ProposalPayloadValidationError";
|
|
126948
|
+
}
|
|
126949
|
+
};
|
|
126950
|
+
});
|
|
126951
|
+
|
|
126763
126952
|
// ../../packages/core/dist/data/proposal/proposal-contract.js
|
|
126764
126953
|
class MemoryProposalStore {
|
|
126765
126954
|
rows = [];
|
|
@@ -126783,26 +126972,53 @@ class MemoryProposalStore {
|
|
|
126783
126972
|
row.decidedAt = decidedAt ?? Date.now();
|
|
126784
126973
|
return structuredClone(row);
|
|
126785
126974
|
}
|
|
126975
|
+
async create(input) {
|
|
126976
|
+
assertValidProposalPayload(input.kind, input.payload);
|
|
126977
|
+
const record2 = {
|
|
126978
|
+
id: input.id,
|
|
126979
|
+
projectId: input.projectId,
|
|
126980
|
+
kind: input.kind,
|
|
126981
|
+
targetMemoryId: input.targetMemoryId ?? null,
|
|
126982
|
+
payload: input.payload,
|
|
126983
|
+
rationale: input.rationale ?? "",
|
|
126984
|
+
status: "pending",
|
|
126985
|
+
createdAt: input.createdAt ?? Date.now(),
|
|
126986
|
+
decidedAt: null
|
|
126987
|
+
};
|
|
126988
|
+
this.rows.push(structuredClone(record2));
|
|
126989
|
+
return structuredClone(record2);
|
|
126990
|
+
}
|
|
126991
|
+
async update(id, patch) {
|
|
126992
|
+
const row = this.rows.find((item) => item.id === id);
|
|
126993
|
+
if (!row)
|
|
126994
|
+
return null;
|
|
126995
|
+
if (patch.payload !== undefined)
|
|
126996
|
+
assertValidProposalPayload(row.kind, patch.payload);
|
|
126997
|
+
if (patch.rationale !== undefined)
|
|
126998
|
+
row.rationale = patch.rationale;
|
|
126999
|
+
if (patch.payload !== undefined)
|
|
127000
|
+
row.payload = patch.payload;
|
|
127001
|
+
return structuredClone(row);
|
|
127002
|
+
}
|
|
127003
|
+
async delete(id) {
|
|
127004
|
+
const index = this.rows.findIndex((item) => item.id === id);
|
|
127005
|
+
if (index === -1)
|
|
127006
|
+
return null;
|
|
127007
|
+
this.rows.splice(index, 1);
|
|
127008
|
+
return id;
|
|
127009
|
+
}
|
|
126786
127010
|
async journalMode() {
|
|
126787
127011
|
return "memory";
|
|
126788
127012
|
}
|
|
126789
127013
|
}
|
|
126790
127014
|
var PROPOSAL_STATUSES, PROPOSAL_KINDS;
|
|
126791
127015
|
var init_proposal_contract = __esm(() => {
|
|
127016
|
+
init_proposal_payload_validation();
|
|
126792
127017
|
PROPOSAL_STATUSES = ["pending", "approved", "rejected"];
|
|
126793
127018
|
PROPOSAL_KINDS = ["memory.create", "memory.update", "memory.tag"];
|
|
126794
127019
|
});
|
|
126795
127020
|
|
|
126796
127021
|
// ../../packages/core/dist/data/proposal/proposal-repository-pg.js
|
|
126797
|
-
function isRecord(value) {
|
|
126798
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
126799
|
-
}
|
|
126800
|
-
function stringArray(value) {
|
|
126801
|
-
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
126802
|
-
}
|
|
126803
|
-
function validKeys(value, allowed) {
|
|
126804
|
-
return Object.keys(value).every((key) => allowed.includes(key));
|
|
126805
|
-
}
|
|
126806
127022
|
function parsePayload(raw2, kind) {
|
|
126807
127023
|
let value;
|
|
126808
127024
|
try {
|
|
@@ -126813,15 +127029,7 @@ function parsePayload(raw2, kind) {
|
|
|
126813
127029
|
if (!isRecord(value)) {
|
|
126814
127030
|
throw storeCorruption("proposal.payload_json", new TypeError("expected object"));
|
|
126815
127031
|
}
|
|
126816
|
-
|
|
126817
|
-
if (kind === "memory.create") {
|
|
126818
|
-
valid = validKeys(value, ["content", "type", "level", "importance", "tags"]) && typeof value.content === "string" && (value.type === undefined || typeof value.type === "string") && (value.level === undefined || typeof value.level === "number") && (value.importance === undefined || typeof value.importance === "number") && (value.tags === undefined || stringArray(value.tags));
|
|
126819
|
-
} else if (kind === "memory.update") {
|
|
126820
|
-
valid = validKeys(value, ["content", "importance", "tags"]) && Object.keys(value).length > 0 && (value.content === undefined || typeof value.content === "string") && (value.importance === undefined || typeof value.importance === "number") && (value.tags === undefined || stringArray(value.tags));
|
|
126821
|
-
} else {
|
|
126822
|
-
valid = validKeys(value, ["tags"]) && stringArray(value.tags);
|
|
126823
|
-
}
|
|
126824
|
-
if (!valid) {
|
|
127032
|
+
if (!isValidProposalPayload(kind, value)) {
|
|
126825
127033
|
throw storeCorruption("proposal.payload_json", new TypeError("invalid proposal payload"));
|
|
126826
127034
|
}
|
|
126827
127035
|
return value;
|
|
@@ -126955,6 +127163,65 @@ class PgProposalStore {
|
|
|
126955
127163
|
this.mirror.set(id, persisted);
|
|
126956
127164
|
return structuredClone(persisted);
|
|
126957
127165
|
}
|
|
127166
|
+
async create(input) {
|
|
127167
|
+
assertValidProposalPayload(input.kind, input.payload);
|
|
127168
|
+
const record2 = {
|
|
127169
|
+
id: input.id,
|
|
127170
|
+
projectId: input.projectId,
|
|
127171
|
+
kind: input.kind,
|
|
127172
|
+
targetMemoryId: input.targetMemoryId ?? null,
|
|
127173
|
+
payload: input.payload,
|
|
127174
|
+
rationale: input.rationale ?? "",
|
|
127175
|
+
status: "pending",
|
|
127176
|
+
createdAt: input.createdAt ?? Date.now(),
|
|
127177
|
+
decidedAt: null
|
|
127178
|
+
};
|
|
127179
|
+
await this.insert(record2);
|
|
127180
|
+
return record2;
|
|
127181
|
+
}
|
|
127182
|
+
async update(id, patch) {
|
|
127183
|
+
await this.ensureHydrated();
|
|
127184
|
+
const current = this.mirror.get(id);
|
|
127185
|
+
if (!current)
|
|
127186
|
+
return null;
|
|
127187
|
+
if (patch.payload !== undefined) {
|
|
127188
|
+
assertValidProposalPayload(current.kind, patch.payload);
|
|
127189
|
+
}
|
|
127190
|
+
const merged = {
|
|
127191
|
+
...current,
|
|
127192
|
+
...patch.rationale !== undefined ? { rationale: patch.rationale } : {},
|
|
127193
|
+
...patch.payload !== undefined ? { payload: patch.payload } : {}
|
|
127194
|
+
};
|
|
127195
|
+
let rows;
|
|
127196
|
+
try {
|
|
127197
|
+
rows = await this.getClient().$queryRaw`
|
|
127198
|
+
UPDATE proposals
|
|
127199
|
+
SET rationale = ${merged.rationale}, payload_json = ${JSON.stringify(merged.payload)}
|
|
127200
|
+
WHERE id = ${id}
|
|
127201
|
+
RETURNING id, project_id, kind, target_memory_id, payload_json,
|
|
127202
|
+
rationale, status, created_at, decided_at`;
|
|
127203
|
+
} catch (error51) {
|
|
127204
|
+
throw searchBackendUnavailable("proposal_store", error51);
|
|
127205
|
+
}
|
|
127206
|
+
if (!rows[0])
|
|
127207
|
+
return null;
|
|
127208
|
+
const persisted = toRecord(rows[0]);
|
|
127209
|
+
this.mirror.set(id, persisted);
|
|
127210
|
+
return structuredClone(persisted);
|
|
127211
|
+
}
|
|
127212
|
+
async delete(id) {
|
|
127213
|
+
await this.ensureHydrated();
|
|
127214
|
+
let affected;
|
|
127215
|
+
try {
|
|
127216
|
+
affected = await this.getClient().$executeRaw`DELETE FROM proposals WHERE id = ${id}`;
|
|
127217
|
+
} catch (error51) {
|
|
127218
|
+
throw searchBackendUnavailable("proposal_store", error51);
|
|
127219
|
+
}
|
|
127220
|
+
if (affected === 0)
|
|
127221
|
+
return null;
|
|
127222
|
+
this.mirror.delete(id);
|
|
127223
|
+
return id;
|
|
127224
|
+
}
|
|
126958
127225
|
async journalMode() {
|
|
126959
127226
|
await this.ensureHydrated();
|
|
126960
127227
|
return "postgres";
|
|
@@ -126971,6 +127238,7 @@ var init_proposal_repository_pg = __esm(() => {
|
|
|
126971
127238
|
init_alias_resolver();
|
|
126972
127239
|
init_search_diagnostics();
|
|
126973
127240
|
init_proposal_contract();
|
|
127241
|
+
init_proposal_payload_validation();
|
|
126974
127242
|
});
|
|
126975
127243
|
|
|
126976
127244
|
// ../../packages/core/dist/data/proposal/proposal-repository.js
|