opencode-swarm 7.166.0 → 7.166.1
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/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
- package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
- package/dist/cli/{coder-settlement-ydg2jfrk.js → coder-settlement-x0h3h6vd.js} +8 -8
- package/dist/cli/{config-doctor-drqx6tzc.js → config-doctor-pjcjeh8f.js} +5 -5
- package/dist/cli/{core-x6sftfwt.js → core-v11pd1yk.js} +4 -4
- package/dist/cli/{curator-drift-2vwtkegg.js → curator-drift-jpdfwae9.js} +3 -3
- package/dist/cli/{curator-llm-factory-7znajprp.js → curator-llm-factory-da5q3gg6.js} +26 -26
- package/dist/cli/{curator-kg2h8jjf.js → curator-ssvd7evd.js} +26 -26
- package/dist/cli/{dispatch-c7xjt7js.js → dispatch-591v13pp.js} +3 -3
- package/dist/cli/{evidence-summary-service-ry5ebnmq.js → evidence-summary-service-mw6tnsp9.js} +10 -10
- package/dist/cli/{gate-evidence-qgeceqy8.js → gate-evidence-jymaxb82.js} +6 -6
- package/dist/cli/{guardrail-explain-jdv4n2j3.js → guardrail-explain-eva1yrtf.js} +27 -27
- package/dist/cli/{guardrail-log-s7c3rpde.js → guardrail-log-kzq2sktb.js} +6 -6
- package/dist/cli/{guardrail-reset-4nmy7xas.js → guardrail-reset-ea1g3g7d.js} +26 -26
- package/dist/cli/{hive-promoter-w5tsgttc.js → hive-promoter-ghjbgsms.js} +26 -26
- package/dist/cli/{index-hrkamw9q.js → index-066xxa4q.js} +3 -3
- package/dist/cli/{index-qkq56zyr.js → index-0g5v4s0x.js} +59 -8
- package/dist/cli/{index-a0d4fp6r.js → index-0tc0pcmh.js} +1 -1
- package/dist/cli/{index-359djbj1.js → index-13egyjgv.js} +5 -5
- package/dist/cli/{index-8bdk7124.js → index-1zqf2pny.js} +1 -1
- package/dist/cli/{index-8d90gzaz.js → index-2sqgbmtq.js} +1 -1
- package/dist/cli/{index-30f4fe30.js → index-2y4kargd.js} +1 -1
- package/dist/cli/{index-an89qzd9.js → index-399nq780.js} +522 -636
- package/dist/cli/{index-ejf6w8vw.js → index-3tyym20r.js} +2 -2
- package/dist/cli/{index-mg43w8p2.js → index-52xdezsh.js} +12 -3
- package/dist/cli/{index-a5w71m8f.js → index-6rff2h8x.js} +1 -1
- package/dist/cli/{index-p04pa9c9.js → index-8fr2wn18.js} +2 -2
- package/dist/cli/{index-anxs69ad.js → index-bfr392e7.js} +1 -1
- package/dist/cli/{index-fywshabz.js → index-bkd3450m.js} +4 -4
- package/dist/cli/{index-289epdpc.js → index-crjx4sx0.js} +28 -28
- package/dist/cli/{index-z6xqpmqg.js → index-ee6ydtfe.js} +1 -1
- package/dist/cli/{index-2rm5x9ps.js → index-fc1dqzjp.js} +2 -2
- package/dist/cli/{index-4mpdy32j.js → index-gerkwyrr.js} +1 -1
- package/dist/cli/{index-9hy5q7gp.js → index-gr8ppbq3.js} +2 -2
- package/dist/cli/{index-rkn17q5e.js → index-j29nkq5d.js} +5 -5
- package/dist/cli/{index-2dvk153d.js → index-k5w284js.js} +5 -5
- package/dist/cli/{index-apxaa755.js → index-nph5g4em.js} +3 -3
- package/dist/cli/{index-52jfm5s0.js → index-w11whwn3.js} +2 -2
- package/dist/cli/{index-nb924ar6.js → index-wf12wckd.js} +2 -2
- package/dist/cli/{index-czr3jcg6.js → index-xezfx7ge.js} +1 -1
- package/dist/cli/{index-8m12y79g.js → index-xwkn5hse.js} +2 -2
- package/dist/cli/{index-bw7r2b2m.js → index-ybcxvv17.js} +1 -1
- package/dist/cli/{index-8n62bphd.js → index-yt25kpvz.js} +2 -2
- package/dist/cli/{index-jc9cxh90.js → index-zha9bdj9.js} +4 -4
- package/dist/cli/index-zpsr8rpc.js +68 -0
- package/dist/cli/index.js +26 -26
- package/dist/cli/{knowledge-escalator-xdzmr31d.js → knowledge-escalator-3pjed4tq.js} +10 -10
- package/dist/cli/{knowledge-events-1t1t0bv7.js → knowledge-events-a5dwkg30.js} +8 -8
- package/dist/cli/{knowledge-store-m2snb0xg.js → knowledge-store-h85efsak.js} +1 -1
- package/dist/cli/{knowledge-validator-tf7yq2pd.js → knowledge-validator-76qrf1ev.js} +2 -2
- package/dist/cli/{model-preflight-3s1c0zpc.js → model-preflight-b3b5pgsc.js} +2 -2
- package/dist/cli/{pending-delegations-jr8hwxrz.js → pending-delegations-zgwfqfac.js} +5 -5
- package/dist/cli/{pr-subscriptions-ca1xmf9r.js → pr-subscriptions-fzy3ks1k.js} +5 -5
- package/dist/cli/{pr-workflow-gate-fb1dj0zx.js → pr-workflow-gate-1gtsn7f0.js} +26 -26
- package/dist/cli/{scan-cursor-3gdvy0ym.js → scan-cursor-ahwkxa8j.js} +2 -2
- package/dist/cli/{schema-mzb1354k.js → schema-27sedbfk.js} +3 -3
- package/dist/cli/{scope-persistence-c4n21b5n.js → scope-persistence-q792yfxh.js} +7 -7
- package/dist/cli/{skill-generator-dvpvwt8k.js → skill-generator-g8wbjw6v.js} +11 -11
- package/dist/cli/{snapshot-coordination-init-g7v63zcm.js → snapshot-coordination-init-y6spakwm.js} +26 -26
- package/dist/cli/{worktree-collision-ownership-k15qrpy9.js → worktree-collision-ownership-pmpnftkd.js} +6 -6
- package/dist/cli/{worktree-isolation-y7ec1pm5.js → worktree-isolation-4053n0px.js} +26 -26
- package/dist/git/pr.d.ts +4 -2
- package/dist/git/safe-ref.d.ts +51 -0
- package/dist/index.js +154 -154
- package/dist/tools/co-change-analyzer.d.ts +7 -0
- package/dist/tools/gh-evidence.d.ts +15 -8
- package/dist/tools/pkg-audit.d.ts +23 -0
- package/dist/utils/gh-executable.d.ts +106 -0
- package/dist/utils/merge.d.ts +26 -0
- package/package.json +1 -1
- package/dist/cli/index-zjygnfay.js +0 -33
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import * as child_process from 'node:child_process';
|
|
1
2
|
import type { tool } from '@opencode-ai/plugin';
|
|
2
3
|
import type { SwarmKnowledgeEntry } from '../hooks/knowledge-types.js';
|
|
4
|
+
/** Lazy-bind so mock.module can intercept at call time (#330); all internal
|
|
5
|
+
* calls route through _internals.getExecFileAsync so tests can replace the
|
|
6
|
+
* seam directly (PRR-020). */
|
|
7
|
+
declare function getExecFileAsync(): typeof child_process.execFile.__promisify__;
|
|
3
8
|
export interface CoChangeEntry {
|
|
4
9
|
fileA: string;
|
|
5
10
|
fileB: string;
|
|
@@ -55,4 +60,6 @@ export declare const _internals: {
|
|
|
55
60
|
detectDarkMatter: typeof detectDarkMatter;
|
|
56
61
|
darkMatterToKnowledgeEntries: typeof darkMatterToKnowledgeEntries;
|
|
57
62
|
formatDarkMatterOutput: typeof formatDarkMatterOutput;
|
|
63
|
+
getExecFileAsync: typeof getExecFileAsync;
|
|
58
64
|
};
|
|
65
|
+
export {};
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import type { ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
2
2
|
import { resolveExecutableFromPath, runExternalTool } from '../utils/external-tool-runner';
|
|
3
|
+
import { resolveGhExecutable } from '../utils/gh-executable';
|
|
3
4
|
interface GhBinaryCandidateOptions {
|
|
4
|
-
env?:
|
|
5
|
+
env?: NodeJS.ProcessEnv;
|
|
5
6
|
platform?: NodeJS.Platform;
|
|
6
7
|
}
|
|
7
8
|
export declare function resolveGhBinaryCandidates(options?: GhBinaryCandidateOptions): string[];
|
|
8
9
|
/**
|
|
9
|
-
* Resolve the `gh` binary
|
|
10
|
-
* C1b) so other call sites that need a `gh` executable — e.g.
|
|
11
|
-
* `src/commands/pr-monitor-status.ts` — reuse this resolver
|
|
12
|
-
* spawning a bare `'gh'` literal or inventing a second gh resolver.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
10
|
+
* Resolve the `gh` binary for the gh_evidence tool. Exported (issue #2236
|
|
11
|
+
* hardening, lane C1b) so other call sites that need a `gh` executable — e.g.
|
|
12
|
+
* `src/git/pr.ts`, `src/commands/pr-monitor-status.ts` — reuse this resolver
|
|
13
|
+
* instead of spawning a bare `'gh'` literal or inventing a second gh resolver.
|
|
14
|
+
*
|
|
15
|
+
* Issue #2476 AC1: delegates to the hardened twin of the git resolver
|
|
16
|
+
* (`src/utils/gh-executable.ts`) — absolute-candidate-first ordering,
|
|
17
|
+
* absoluteness requirement, `gh --version` probe, bounded budget, caching.
|
|
18
|
+
* Returns `null` when nothing validated (the resolver's bare-`'gh'` terminal
|
|
19
|
+
* fallback maps here to null so the tool renders its gh-not-found guidance
|
|
20
|
+
* exactly as a scan-miss did before); callers that spawn directly should use
|
|
21
|
+
* `resolveGhExecutable()` instead, which never returns null.
|
|
16
22
|
*/
|
|
17
23
|
export declare function resolveGhBinary(): string | null;
|
|
18
24
|
/**
|
|
@@ -26,6 +32,7 @@ export declare const gh_evidence: ToolDefinition;
|
|
|
26
32
|
export declare const _internals: {
|
|
27
33
|
resolveGhBinaryCandidates: typeof resolveGhBinaryCandidates;
|
|
28
34
|
resolveExecutableFromPath: typeof resolveExecutableFromPath;
|
|
35
|
+
resolveGhExecutable: typeof resolveGhExecutable;
|
|
29
36
|
resolveGhBinary: typeof resolveGhBinary;
|
|
30
37
|
runExternalTool: typeof runExternalTool;
|
|
31
38
|
};
|
|
@@ -9,7 +9,30 @@ import { bunSpawn } from '../utils/bun-compat';
|
|
|
9
9
|
* functions gate strictly on a non-zero exit and were dispositioned
|
|
10
10
|
* SAFE-EXIT-CHECK by that sweep.
|
|
11
11
|
*/
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the spawn command prefix for a package-audit binary (issue #2476
|
|
14
|
+
* AC5). On POSIX (or when resolution fails) the bare name is returned -- the
|
|
15
|
+
* historical behavior, which works there. On win32 the absolute candidate is
|
|
16
|
+
* resolved via resolveExecutableFromPath (.exe/.cmd/.bat variants); a
|
|
17
|
+
* `.cmd`/`.bat` hit cannot be spawned directly by Node (EINVAL since the
|
|
18
|
+
* CVE-2024-27980 hardening), so it is routed through cmd.exe as
|
|
19
|
+
* `/d /s /c call "<resolved>"` -- everything after `/c` is cmd's own command
|
|
20
|
+
* line, the repo-documented windowsVerbatimArguments pattern. Empirically
|
|
21
|
+
* verified on Windows (node & Bun): a bare quoted tail `"<path>"` is mangled
|
|
22
|
+
* by cmd's /s quote-stripping (the last quote in the line is removed), while
|
|
23
|
+
* the `call` prefix keeps the quoted path intact for paths containing spaces
|
|
24
|
+
* such as C:\Program Files. Callers append their fixed literal arguments
|
|
25
|
+
* (`audit --json`) as separate argv elements; verbatim joining keeps them
|
|
26
|
+
* outside the quoted path. The only interpolated value is the resolved
|
|
27
|
+
* ABSOLUTE path, rejected when it contains any cmd metacharacter
|
|
28
|
+
* (`" & | < > ^ ! %`) so the verbatim command line degrades to the bare-name
|
|
29
|
+
* fallback rather than through any cmd re-interpretation; the remaining
|
|
30
|
+
* tokens are fixed literals.
|
|
31
|
+
*/
|
|
32
|
+
declare function resolveAuditCommandDefault(name: 'npm' | 'cargo'): string[];
|
|
12
33
|
export declare const _internals: {
|
|
13
34
|
bunSpawn: typeof bunSpawn;
|
|
35
|
+
resolveAuditCommand: typeof resolveAuditCommandDefault;
|
|
14
36
|
};
|
|
15
37
|
export declare const pkg_audit: ReturnType<typeof tool>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for "what absolute path do we invoke for gh" — the
|
|
3
|
+
* gh twin of `resolveGitExecutable()` in `src/utils/git-executable.ts`
|
|
4
|
+
* (issue #2476 AC1 / source issue #2262).
|
|
5
|
+
*
|
|
6
|
+
* The pre-fix resolver (`resolveGhBinaryCandidates` in
|
|
7
|
+
* `src/tools/gh-evidence.ts` + `resolveExecutableFromPath`) put the bare
|
|
8
|
+
* name FIRST, so a full PATH scan for `gh` beat every ProgramFiles absolute
|
|
9
|
+
* candidate; accepted any stat-able regular file (a 20-byte text file named
|
|
10
|
+
* gh.exe passed); and had no `gh --version` behavioral probe, no budget, and
|
|
11
|
+
* no cache. That matters MORE than the git case: `gh` runs with the user's
|
|
12
|
+
* GitHub token, so a hijack is credential theft in addition to code
|
|
13
|
+
* execution.
|
|
14
|
+
*
|
|
15
|
+
* Contract (mirrors git-executable.ts; deviations called out inline):
|
|
16
|
+
*
|
|
17
|
+
* 1. explicit override — the `OPENCODE_SWARM_GH_BINARY` env var ONLY.
|
|
18
|
+
* There is deliberately NO config-file `gh.binary` key: the config path
|
|
19
|
+
* is the attack surface `enforceGitBinaryProvenance` exists to strip
|
|
20
|
+
* for git, and gh never had one. Env-only keeps every override
|
|
21
|
+
* user-controlled by construction.
|
|
22
|
+
* 2. platform absolute candidates (win32 ProgramFiles/LOCALAPPDATA — the
|
|
23
|
+
* set `resolveGhBinaryCandidates` already knew — plus darwin/linux
|
|
24
|
+
* install locations, which the old resolver lacked entirely);
|
|
25
|
+
* 3. ALL PATH matches for `gh` (win32: `.exe`/`.cmd`/`.bat` variants);
|
|
26
|
+
* 4. bare `'gh'` LAST, unprobed, so a host that works via plain PATH
|
|
27
|
+
* lookup never regresses.
|
|
28
|
+
*
|
|
29
|
+
* Each non-bare candidate must be ABSOLUTE and is validated once with
|
|
30
|
+
* `gh --version` (bounded, explicit cwd) whose output must match
|
|
31
|
+
* GH_VERSION_PATTERN — exit 0 alone does not accept a candidate. NOT AN
|
|
32
|
+
* ANTI-TAMPERING CONTROL (a hostile program can print `gh version 2.x`); it
|
|
33
|
+
* stops ACCIDENTS — a non-gh that merely exits 0, a broken shim. The
|
|
34
|
+
* trust-boundary control is that no repository-controlled value can name a
|
|
35
|
+
* candidate at all (env-only override).
|
|
36
|
+
*
|
|
37
|
+
* Bounded probing (AGENTS.md invariant 1): per-probe timeout 250 ms, total
|
|
38
|
+
* first-resolution budget 1000 ms. gh resolution is LAZY (tool/ghExec call
|
|
39
|
+
* paths, never plugin init), so the sync API below is sufficient — there is
|
|
40
|
+
* no init-path need for an async variant.
|
|
41
|
+
*
|
|
42
|
+
* NEVER throws: both non-accepting outcomes (budget exhausted, every
|
|
43
|
+
* candidate rejected) return the bare `'gh'` fallback, memoized with a 60 s
|
|
44
|
+
* TTL so a host that installs gh mid-session recovers (same rationale as
|
|
45
|
+
* git-executable.ts — a slash-less spawn does not resolve against the PATH
|
|
46
|
+
* this module enumerates, so "gh is missing" is not a state this resolver
|
|
47
|
+
* may report).
|
|
48
|
+
*/
|
|
49
|
+
import { spawnSync } from 'node:child_process';
|
|
50
|
+
/** Env var escape hatch — a blocked user can set this without editing files. */
|
|
51
|
+
export declare const GH_BINARY_ENV_VAR = "OPENCODE_SWARM_GH_BINARY";
|
|
52
|
+
/**
|
|
53
|
+
* `gh --version` prints `gh version 2.74.0 (2025-...)` — a fixed format
|
|
54
|
+
* string in gh's own root command. Same accident-not-attacker contract as
|
|
55
|
+
* `GIT_VERSION_PATTERN` (see git-executable.ts); anchored to the first line.
|
|
56
|
+
*/
|
|
57
|
+
export declare const GH_VERSION_PATTERN: RegExp;
|
|
58
|
+
export type GhResolutionCandidateSource = 'override' | 'platform' | 'path';
|
|
59
|
+
export interface GhResolutionAttempt {
|
|
60
|
+
source: GhResolutionCandidateSource;
|
|
61
|
+
candidate: string;
|
|
62
|
+
accepted: boolean;
|
|
63
|
+
/** Rejection reason; absent when `accepted` is true. */
|
|
64
|
+
reason?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface GhResolutionDescription {
|
|
67
|
+
resolved: boolean;
|
|
68
|
+
resolvedPath?: string;
|
|
69
|
+
attempts: GhResolutionAttempt[];
|
|
70
|
+
overrideValue?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Windows install locations, kept in one place so the legacy
|
|
74
|
+
* `resolveGhBinaryCandidates` export in gh-evidence.ts can share the set.
|
|
75
|
+
* Paths are built with native separators via path.join by the caller.
|
|
76
|
+
*/
|
|
77
|
+
export declare function windowsGhAbsoluteCandidates(env: NodeJS.ProcessEnv): string[];
|
|
78
|
+
/**
|
|
79
|
+
* Resolve the gh executable to invoke. Lazy, memoized, bounded by
|
|
80
|
+
* TOTAL_BUDGET_MS, never throws. Returns a validated absolute path or the
|
|
81
|
+
* bare `'gh'` fallback.
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveGhExecutable(): string;
|
|
84
|
+
/** Exported for tests; clears the memoized cache (and bumps the generation). */
|
|
85
|
+
export declare function resetGhExecutableCache(): void;
|
|
86
|
+
/**
|
|
87
|
+
* TEST-ONLY seam — NOT a production API, do not call from `src/`. Pre-seeds
|
|
88
|
+
* the resolver cache with an explicit "success" entry so
|
|
89
|
+
* `resolveGhExecutable()` returns `value` with zero probe spawns. Distinct
|
|
90
|
+
* from gh-evidence.ts's `__seedGhBinaryForTests` (which pins only that
|
|
91
|
+
* wrapper's legacy layer): neither bypasses the other.
|
|
92
|
+
*/
|
|
93
|
+
export declare function __seedGhExecutableForTests(value: string): void;
|
|
94
|
+
/** Diagnostic surface: candidates tried in the most recent probe cycle. */
|
|
95
|
+
export declare function describeGhResolution(): GhResolutionDescription;
|
|
96
|
+
/**
|
|
97
|
+
* DI seam for testability (repo convention — see git-executable.ts).
|
|
98
|
+
* `platform`/`env` let tests drive every platform branch regardless of the
|
|
99
|
+
* host OS; `now` makes the TTL and budget deterministically testable.
|
|
100
|
+
*/
|
|
101
|
+
export declare const _internals: {
|
|
102
|
+
spawnSync: typeof spawnSync;
|
|
103
|
+
platform: () => NodeJS.Platform;
|
|
104
|
+
env: () => NodeJS.ProcessEnv;
|
|
105
|
+
now: () => number;
|
|
106
|
+
};
|
package/dist/utils/merge.d.ts
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
export declare const MAX_MERGE_DEPTH = 10;
|
|
2
|
+
/**
|
|
3
|
+
* Keys that must never be merged, at any depth (issue #2476 AC2 / source
|
|
4
|
+
* issue #2264). `JSON.parse` creates `__proto__` as an OWN ENUMERABLE data
|
|
5
|
+
* property (CreateDataProperty, not [[Set]]), so `Object.keys(override)`
|
|
6
|
+
* yields it and the plain assignment below would invoke the
|
|
7
|
+
* `Object.prototype.__proto__` setter and reparent the merged object.
|
|
8
|
+
* `constructor`/`prototype` are the sibling prototype-pollution carriers.
|
|
9
|
+
* Only the OVERRIDE side is checked: that is the untrusted side at every
|
|
10
|
+
* production call site (repo-supplied project config over user config at
|
|
11
|
+
* `src/config/loader.ts`; user scoring config over defaults at
|
|
12
|
+
* `src/config/constants.ts`) — `base` is either caller-built defaults or an
|
|
13
|
+
* already-vetted earlier merge.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DANGEROUS_MERGE_KEYS: ReadonlySet<string>;
|
|
16
|
+
/** Typed, fail-closed rejection of a dangerous merge key (issue #2476 AC2). */
|
|
17
|
+
export declare class DangerousMergeKeyError extends Error {
|
|
18
|
+
readonly key: string;
|
|
19
|
+
readonly path: string;
|
|
20
|
+
constructor(key: string, path: string);
|
|
21
|
+
}
|
|
2
22
|
/**
|
|
3
23
|
* Deep merge two objects, with override values taking precedence.
|
|
24
|
+
*
|
|
25
|
+
* Throws `DangerousMergeKeyError` when the override object carries
|
|
26
|
+
* `__proto__`, `constructor`, or `prototype` at ANY depth (issue #2476 AC2).
|
|
27
|
+
* The config loader catches this at the repo-supplied project-config merge
|
|
28
|
+
* and continues with user-level config only; other callers get the typed
|
|
29
|
+
* throw as fail-closed semantics.
|
|
4
30
|
*/
|
|
5
31
|
export declare function deepMerge<T extends Record<string, unknown>>(base?: T, override?: T): T | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.166.
|
|
3
|
+
"version": "7.166.1",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
__esm
|
|
4
|
-
} from "./index-a76rekgs.js";
|
|
5
|
-
|
|
6
|
-
// src/utils/merge.ts
|
|
7
|
-
function deepMergeInternal(base, override, depth) {
|
|
8
|
-
if (depth >= MAX_MERGE_DEPTH) {
|
|
9
|
-
throw new Error(`deepMerge exceeded maximum depth of ${MAX_MERGE_DEPTH}`);
|
|
10
|
-
}
|
|
11
|
-
const result = { ...base };
|
|
12
|
-
for (const key of Object.keys(override)) {
|
|
13
|
-
const baseVal = base[key];
|
|
14
|
-
const overrideVal = override[key];
|
|
15
|
-
if (typeof baseVal === "object" && baseVal !== null && typeof overrideVal === "object" && overrideVal !== null && !Array.isArray(baseVal) && !Array.isArray(overrideVal)) {
|
|
16
|
-
result[key] = deepMergeInternal(baseVal, overrideVal, depth + 1);
|
|
17
|
-
} else {
|
|
18
|
-
result[key] = overrideVal;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return result;
|
|
22
|
-
}
|
|
23
|
-
function deepMerge(base, override) {
|
|
24
|
-
if (!base)
|
|
25
|
-
return override;
|
|
26
|
-
if (!override)
|
|
27
|
-
return base;
|
|
28
|
-
return deepMergeInternal(base, override, 0);
|
|
29
|
-
}
|
|
30
|
-
var MAX_MERGE_DEPTH = 10;
|
|
31
|
-
var init_merge = () => {};
|
|
32
|
-
|
|
33
|
-
export { MAX_MERGE_DEPTH, deepMerge, init_merge };
|