hunter-harness 0.2.6 → 0.2.8
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/bin.js +270 -85
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { realpathSync } from "node:fs";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
import { createInterface } from "node:readline/promises";
|
|
7
|
+
import { Writable } from "node:stream";
|
|
7
8
|
import { Command, CommanderError } from "commander";
|
|
8
9
|
|
|
9
10
|
// ../contracts/dist/ai-config.js
|
|
@@ -1670,6 +1671,9 @@ function affectedPaths(operation) {
|
|
|
1670
1671
|
}
|
|
1671
1672
|
async function writeJournal(transactionRoot, journal) {
|
|
1672
1673
|
await atomicWriteJson(join3(transactionRoot, "journal.json"), journal);
|
|
1674
|
+
await writeStatus(transactionRoot, journal);
|
|
1675
|
+
}
|
|
1676
|
+
async function writeStatus(transactionRoot, journal) {
|
|
1673
1677
|
await atomicWriteJson(join3(transactionRoot, "status.json"), {
|
|
1674
1678
|
schema_version: 1,
|
|
1675
1679
|
transaction_id: journal.transaction_id,
|
|
@@ -1679,6 +1683,16 @@ async function writeJournal(transactionRoot, journal) {
|
|
|
1679
1683
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1680
1684
|
});
|
|
1681
1685
|
}
|
|
1686
|
+
function journalOperation(operation) {
|
|
1687
|
+
if (operation.operation === "rename") {
|
|
1688
|
+
return {
|
|
1689
|
+
operation: "rename",
|
|
1690
|
+
from_path: operation.from_path,
|
|
1691
|
+
to_path: operation.to_path
|
|
1692
|
+
};
|
|
1693
|
+
}
|
|
1694
|
+
return { operation: operation.operation, path: operation.path };
|
|
1695
|
+
}
|
|
1682
1696
|
async function pruneOlderSuccessful(layout, currentId, kind) {
|
|
1683
1697
|
if (kind === void 0)
|
|
1684
1698
|
return;
|
|
@@ -1799,12 +1813,12 @@ async function runTransaction(projectRoot, rawOperations, options = {}) {
|
|
|
1799
1813
|
const snapshots = await snapshotPaths(projectRoot, transactionRoot, paths);
|
|
1800
1814
|
await stageOperations(transactionRoot, operations);
|
|
1801
1815
|
const journal = {
|
|
1802
|
-
schema_version:
|
|
1816
|
+
schema_version: 2,
|
|
1803
1817
|
transaction_id: transactionId,
|
|
1804
1818
|
...options.kind === void 0 ? {} : { kind: options.kind },
|
|
1805
1819
|
state: "prepared",
|
|
1806
1820
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1807
|
-
operations,
|
|
1821
|
+
operations: operations.map(journalOperation),
|
|
1808
1822
|
snapshots,
|
|
1809
1823
|
applied_count: 0,
|
|
1810
1824
|
failure: null
|
|
@@ -1820,7 +1834,7 @@ async function runTransaction(projectRoot, rawOperations, options = {}) {
|
|
|
1820
1834
|
}
|
|
1821
1835
|
await applyOperation(projectRoot, transactionRoot, operation, index, transactionId);
|
|
1822
1836
|
journal.applied_count = index + 1;
|
|
1823
|
-
await
|
|
1837
|
+
await writeStatus(transactionRoot, journal);
|
|
1824
1838
|
if (options.interruptAfterApply === journal.applied_count) {
|
|
1825
1839
|
journal.state = "interrupted";
|
|
1826
1840
|
journal.failure = "injected interruption";
|
|
@@ -2346,6 +2360,7 @@ async function initializeProject(options) {
|
|
|
2346
2360
|
}
|
|
2347
2361
|
manifests.push({
|
|
2348
2362
|
adapter: agent,
|
|
2363
|
+
profile,
|
|
2349
2364
|
bundle_version: bundle.manifest.bundle_version,
|
|
2350
2365
|
bundle_manifest_hash: bundleHash
|
|
2351
2366
|
});
|
|
@@ -2450,9 +2465,9 @@ async function initializeProject(options) {
|
|
|
2450
2465
|
return byTarget !== 0 ? byTarget : left.block_id.localeCompare(right.block_id);
|
|
2451
2466
|
});
|
|
2452
2467
|
const installedState = {
|
|
2453
|
-
schema_version:
|
|
2454
|
-
profile,
|
|
2468
|
+
schema_version: 4,
|
|
2455
2469
|
adapters: enabledAgents,
|
|
2470
|
+
profiles: Object.fromEntries(enabledAgents.map((agent) => [agent, profile])),
|
|
2456
2471
|
installed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2457
2472
|
manifests,
|
|
2458
2473
|
files: mergedTargets.map((target) => ({
|
|
@@ -2507,17 +2522,35 @@ async function readOptionalText(path) {
|
|
|
2507
2522
|
async function readInstalledState(root) {
|
|
2508
2523
|
const content = await readOptionalText(join6(root, INSTALLED_STATE_PATH));
|
|
2509
2524
|
if (content === "") {
|
|
2510
|
-
return {
|
|
2525
|
+
return {
|
|
2526
|
+
profile: null,
|
|
2527
|
+
schemaVersion: null,
|
|
2528
|
+
adapters: [],
|
|
2529
|
+
profiles: /* @__PURE__ */ new Map(),
|
|
2530
|
+
trusted: /* @__PURE__ */ new Map(),
|
|
2531
|
+
files: [],
|
|
2532
|
+
manifests: [],
|
|
2533
|
+
managedBlocks: []
|
|
2534
|
+
};
|
|
2511
2535
|
}
|
|
2512
2536
|
let parsed;
|
|
2513
2537
|
try {
|
|
2514
2538
|
parsed = JSON.parse(content);
|
|
2515
2539
|
} catch {
|
|
2516
|
-
return {
|
|
2540
|
+
return {
|
|
2541
|
+
profile: null,
|
|
2542
|
+
schemaVersion: null,
|
|
2543
|
+
adapters: [],
|
|
2544
|
+
profiles: /* @__PURE__ */ new Map(),
|
|
2545
|
+
trusted: /* @__PURE__ */ new Map(),
|
|
2546
|
+
files: [],
|
|
2547
|
+
manifests: [],
|
|
2548
|
+
managedBlocks: []
|
|
2549
|
+
};
|
|
2517
2550
|
}
|
|
2518
2551
|
const profile = parseHarnessProfile(parsed.profile);
|
|
2519
2552
|
const trusted = /* @__PURE__ */ new Map();
|
|
2520
|
-
if ((parsed.schema_version === 2 || parsed.schema_version === 3) && Array.isArray(parsed.files)) {
|
|
2553
|
+
if ((parsed.schema_version === 2 || parsed.schema_version === 3 || parsed.schema_version === 4) && Array.isArray(parsed.files)) {
|
|
2521
2554
|
for (const entry of parsed.files) {
|
|
2522
2555
|
if (entry !== null && typeof entry === "object" && "target_path" in entry && "sha256" in entry) {
|
|
2523
2556
|
const target = entry.target_path;
|
|
@@ -2529,8 +2562,42 @@ async function readInstalledState(root) {
|
|
|
2529
2562
|
}
|
|
2530
2563
|
}
|
|
2531
2564
|
const schemaVersion = typeof parsed.schema_version === "number" ? parsed.schema_version : null;
|
|
2532
|
-
const adapters = schemaVersion === 3 && Array.isArray(parsed.adapters) ? sortHarnessAgents(parsed.adapters.filter((value) => value === "claude-code" || value === "codex" || value === "cursor" || value === "codebuddy")) : schemaVersion === 1 || schemaVersion === 2 ? ["claude-code"] : [];
|
|
2533
|
-
|
|
2565
|
+
const adapters = (schemaVersion === 3 || schemaVersion === 4) && Array.isArray(parsed.adapters) ? sortHarnessAgents(parsed.adapters.filter((value) => value === "claude-code" || value === "codex" || value === "cursor" || value === "codebuddy")) : schemaVersion === 1 || schemaVersion === 2 ? ["claude-code"] : [];
|
|
2566
|
+
const profiles = /* @__PURE__ */ new Map();
|
|
2567
|
+
if (schemaVersion === 4 && parsed.profiles !== null && typeof parsed.profiles === "object" && !Array.isArray(parsed.profiles)) {
|
|
2568
|
+
for (const agent of adapters) {
|
|
2569
|
+
const value = parsed.profiles[agent];
|
|
2570
|
+
const agentProfile = parseHarnessProfile(value);
|
|
2571
|
+
if (agentProfile !== null)
|
|
2572
|
+
profiles.set(agent, agentProfile);
|
|
2573
|
+
}
|
|
2574
|
+
} else if (profile !== null) {
|
|
2575
|
+
for (const agent of adapters)
|
|
2576
|
+
profiles.set(agent, profile);
|
|
2577
|
+
}
|
|
2578
|
+
const files = Array.isArray(parsed.files) ? parsed.files.filter((entry) => entry !== null && typeof entry === "object" && typeof entry.target_path === "string" && typeof entry.source_path === "string" && typeof entry.sha256 === "string" && "owner" in entry) : [];
|
|
2579
|
+
const manifests = schemaVersion === 4 && Array.isArray(parsed.manifests) ? parsed.manifests.filter((entry) => entry !== null && typeof entry === "object" && typeof entry.adapter === "string" && typeof entry.profile === "string") : [];
|
|
2580
|
+
const managedBlocks = Array.isArray(parsed.managed_blocks) ? parsed.managed_blocks.filter((entry) => entry !== null && typeof entry === "object" && typeof entry.target_path === "string" && typeof entry.block_id === "string") : [];
|
|
2581
|
+
return {
|
|
2582
|
+
profile,
|
|
2583
|
+
schemaVersion,
|
|
2584
|
+
adapters,
|
|
2585
|
+
profiles,
|
|
2586
|
+
trusted,
|
|
2587
|
+
files,
|
|
2588
|
+
manifests,
|
|
2589
|
+
managedBlocks
|
|
2590
|
+
};
|
|
2591
|
+
}
|
|
2592
|
+
async function readInstalledAgentConfiguration(projectRoot) {
|
|
2593
|
+
const installed = await readInstalledState(resolve4(projectRoot));
|
|
2594
|
+
return {
|
|
2595
|
+
agents: installed.adapters,
|
|
2596
|
+
profiles: Object.fromEntries(installed.adapters.map((agent) => [
|
|
2597
|
+
agent,
|
|
2598
|
+
installed.profiles.get(agent) ?? installed.profile ?? "general"
|
|
2599
|
+
]))
|
|
2600
|
+
};
|
|
2534
2601
|
}
|
|
2535
2602
|
async function readContextIndexBundleHash(root) {
|
|
2536
2603
|
const content = await readOptionalText(join6(root, CONTEXT_INDEX_PATH));
|
|
@@ -2588,16 +2655,18 @@ function conflict(target, reason, oldSha, incomingSha) {
|
|
|
2588
2655
|
function sortByTarget(items) {
|
|
2589
2656
|
return [...items].sort((left, right) => left.target_path.localeCompare(right.target_path));
|
|
2590
2657
|
}
|
|
2591
|
-
async function reconcileContextIndex(root,
|
|
2658
|
+
async function reconcileContextIndex(root, agents, profiles, manifests, codebuddySurface2) {
|
|
2592
2659
|
const existing = await readOptionalText(join6(root, CONTEXT_INDEX_PATH));
|
|
2593
|
-
const context = { profile, codebuddySurface: codebuddySurface2 };
|
|
2594
2660
|
const record = {
|
|
2595
2661
|
schema_version: 2,
|
|
2596
2662
|
project: {
|
|
2597
2663
|
shared_instructions: "AGENTS.md",
|
|
2598
2664
|
adapters: Object.fromEntries(agents.map((agent) => [
|
|
2599
2665
|
agent,
|
|
2600
|
-
getAdapter(agent).contextIndex(
|
|
2666
|
+
getAdapter(agent).contextIndex({
|
|
2667
|
+
profile: profiles.get(agent) ?? "general",
|
|
2668
|
+
codebuddySurface: codebuddySurface2
|
|
2669
|
+
})
|
|
2601
2670
|
]))
|
|
2602
2671
|
},
|
|
2603
2672
|
knowledge: { index: ".harness/knowledge/index.json" },
|
|
@@ -2616,23 +2685,25 @@ async function reconcileContextIndex(root, profile, agents, manifests, codebuddy
|
|
|
2616
2685
|
content: next
|
|
2617
2686
|
};
|
|
2618
2687
|
}
|
|
2619
|
-
async function projectTransitionOperation(root,
|
|
2620
|
-
if (previousProfile === profile && oldAgents.length === agents.length && oldAgents.every((agent, index) => agent === agents[index]))
|
|
2621
|
-
return null;
|
|
2688
|
+
async function projectTransitionOperation(root, agents, profiles, codebuddySurface2) {
|
|
2622
2689
|
const path = ".harness/project.yaml";
|
|
2623
2690
|
const content = await readOptionalText(join6(root, path));
|
|
2624
2691
|
if (content === "")
|
|
2625
2692
|
return null;
|
|
2626
2693
|
const project = parseYaml3(content);
|
|
2694
|
+
const activeProfiles = [...new Set(agents.map((agent) => profiles.get(agent) ?? "general"))].sort();
|
|
2695
|
+
const next = stringifyYaml2({
|
|
2696
|
+
...project,
|
|
2697
|
+
project: { ...project.project, profiles: activeProfiles },
|
|
2698
|
+
adapters: { enabled: agents },
|
|
2699
|
+
...agents.includes("codebuddy") ? { adapter_options: { codebuddy: { surface: codebuddySurface2 } } } : { adapter_options: void 0 }
|
|
2700
|
+
}, { sortMapEntries: true });
|
|
2701
|
+
if (next === content)
|
|
2702
|
+
return null;
|
|
2627
2703
|
return {
|
|
2628
2704
|
operation: "modify",
|
|
2629
2705
|
path,
|
|
2630
|
-
content:
|
|
2631
|
-
...project,
|
|
2632
|
-
project: { ...project.project, profiles: [profile] },
|
|
2633
|
-
adapters: { enabled: agents },
|
|
2634
|
-
...agents.includes("codebuddy") ? { adapter_options: { codebuddy: { surface: codebuddySurface2 } } } : { adapter_options: void 0 }
|
|
2635
|
-
}, { sortMapEntries: true })
|
|
2706
|
+
content: next
|
|
2636
2707
|
};
|
|
2637
2708
|
}
|
|
2638
2709
|
function mergeTargets(targets) {
|
|
@@ -2691,30 +2762,42 @@ function stateWithoutInstalledAt(value) {
|
|
|
2691
2762
|
}
|
|
2692
2763
|
async function refreshProject(options) {
|
|
2693
2764
|
const root = resolve4(options.projectRoot);
|
|
2694
|
-
const profile = options.profile;
|
|
2695
2765
|
const installed = await readInstalledState(root);
|
|
2696
|
-
const previousProfile = installed.profile;
|
|
2697
|
-
const agents = sortHarnessAgents(options.agents);
|
|
2698
2766
|
const oldAgents = installed.adapters.length > 0 ? installed.adapters : ["claude-code"];
|
|
2767
|
+
const selectedAgents = sortHarnessAgents(options.agents);
|
|
2768
|
+
const selectedSet = new Set(selectedAgents);
|
|
2769
|
+
const agents = sortHarnessAgents([...oldAgents, ...selectedAgents]);
|
|
2770
|
+
const profiles = new Map(installed.profiles);
|
|
2771
|
+
if (options.profile !== void 0) {
|
|
2772
|
+
for (const agent of selectedAgents)
|
|
2773
|
+
profiles.set(agent, options.profile);
|
|
2774
|
+
}
|
|
2775
|
+
const profile = options.profile ?? selectedAgents.map((agent) => profiles.get(agent)).find((value) => value !== void 0) ?? installed.profile ?? "general";
|
|
2776
|
+
const previousProfile = selectedAgents.map((agent) => installed.profiles.get(agent)).find((value) => value !== void 0) ?? installed.profile;
|
|
2699
2777
|
const codebuddySurface2 = options.codebuddySurface ?? "both";
|
|
2700
|
-
const context = { profile, codebuddySurface: codebuddySurface2 };
|
|
2701
2778
|
const owned = [];
|
|
2702
2779
|
const manifests = [];
|
|
2703
2780
|
for (const agent of agents) {
|
|
2704
|
-
const
|
|
2781
|
+
const agentProfile = profiles.get(agent) ?? profile;
|
|
2782
|
+
profiles.set(agent, agentProfile);
|
|
2783
|
+
const bundle = await loadAgentBundle(options.resourcesRoot, agentProfile, agent);
|
|
2705
2784
|
manifests.push({
|
|
2706
2785
|
adapter: agent,
|
|
2786
|
+
profile: agentProfile,
|
|
2707
2787
|
bundle_version: bundle.manifest.bundle_version,
|
|
2708
2788
|
bundle_manifest_hash: sha256Bytes(canonicalJson(bundle.manifest.files))
|
|
2709
2789
|
});
|
|
2710
|
-
|
|
2711
|
-
|
|
2790
|
+
if (selectedSet.has(agent)) {
|
|
2791
|
+
const context = { profile: agentProfile, codebuddySurface: codebuddySurface2 };
|
|
2792
|
+
for (const target of managedTargetsFor(getAdapter(agent), bundle, context)) {
|
|
2793
|
+
owned.push({ ...target, owner: agent });
|
|
2794
|
+
}
|
|
2712
2795
|
}
|
|
2713
2796
|
}
|
|
2714
2797
|
const newManaged = mergeTargets(owned);
|
|
2715
2798
|
let trusted = installed.trusted;
|
|
2716
2799
|
let migrationOldPaths = null;
|
|
2717
|
-
if (installed.schemaVersion === 1) {
|
|
2800
|
+
if (installed.schemaVersion === 1 && selectedSet.has("claude-code")) {
|
|
2718
2801
|
const contextHash = await readContextIndexBundleHash(root);
|
|
2719
2802
|
if (contextHash !== null) {
|
|
2720
2803
|
const migrations = await loadMigrationManifests(options.resourcesRoot);
|
|
@@ -2738,12 +2821,18 @@ async function refreshProject(options) {
|
|
|
2738
2821
|
});
|
|
2739
2822
|
}
|
|
2740
2823
|
}
|
|
2741
|
-
} else
|
|
2742
|
-
const oldContext = { profile: previousProfile, codebuddySurface: codebuddySurface2 };
|
|
2824
|
+
} else {
|
|
2743
2825
|
const oldTargets = [];
|
|
2744
|
-
for (const agent of
|
|
2745
|
-
const
|
|
2746
|
-
|
|
2826
|
+
for (const agent of selectedAgents) {
|
|
2827
|
+
const oldProfile = installed.profiles.get(agent) ?? installed.profile;
|
|
2828
|
+
if (!oldAgents.includes(agent) || oldProfile === null || oldProfile === void 0) {
|
|
2829
|
+
continue;
|
|
2830
|
+
}
|
|
2831
|
+
const bundle = await loadAgentBundle(options.resourcesRoot, oldProfile, agent);
|
|
2832
|
+
oldTargets.push(...managedTargetsFor(getAdapter(agent), bundle, {
|
|
2833
|
+
profile: oldProfile,
|
|
2834
|
+
codebuddySurface: codebuddySurface2
|
|
2835
|
+
}));
|
|
2747
2836
|
}
|
|
2748
2837
|
oldOnly = oldTargets.filter((target) => !newTargetSet.has(target.target_path));
|
|
2749
2838
|
}
|
|
@@ -2753,7 +2842,7 @@ async function refreshProject(options) {
|
|
|
2753
2842
|
const unchanged = [];
|
|
2754
2843
|
const conflicts = [];
|
|
2755
2844
|
const ops = [];
|
|
2756
|
-
const newStateFiles =
|
|
2845
|
+
const newStateFiles = installed.files.filter((entry) => entry.owner === "shared" || !selectedSet.has(entry.owner));
|
|
2757
2846
|
for (const target of newManaged) {
|
|
2758
2847
|
const incoming = target.sha256;
|
|
2759
2848
|
const current = await fileHex(join6(root, target.target_path));
|
|
@@ -2801,41 +2890,50 @@ async function refreshProject(options) {
|
|
|
2801
2890
|
}
|
|
2802
2891
|
}
|
|
2803
2892
|
await reconcileMarkdownBlock(root, "AGENTS.md", AGENTS_CORE_BLOCK_ID, AGENTS_MANAGED_BLOCK_CONTENT, false, ops, conflicts, preserved);
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2893
|
+
if (selectedSet.has("claude-code")) {
|
|
2894
|
+
await reconcileMarkdownBlock(root, "CLAUDE.md", CLAUDE_BLOCK_ID, CLAUDE_MANAGED_BLOCK_CONTENT, false, ops, conflicts, preserved);
|
|
2895
|
+
}
|
|
2896
|
+
if (selectedSet.has("codebuddy")) {
|
|
2897
|
+
await reconcileMarkdownBlock(root, "CODEBUDDY.md", CODEBUDDY_BLOCK_ID, CODEBUDDY_MANAGED_BLOCK_CONTENT, false, ops, conflicts, preserved);
|
|
2898
|
+
}
|
|
2899
|
+
const projectOperation = await projectTransitionOperation(root, agents, profiles, codebuddySurface2);
|
|
2807
2900
|
if (projectOperation !== null)
|
|
2808
2901
|
ops.push(projectOperation);
|
|
2809
|
-
const contextOperation = await reconcileContextIndex(root,
|
|
2902
|
+
const contextOperation = await reconcileContextIndex(root, agents, profiles, manifests, codebuddySurface2);
|
|
2810
2903
|
if (contextOperation !== null)
|
|
2811
2904
|
ops.push(contextOperation);
|
|
2812
2905
|
const managedBlocks = [
|
|
2906
|
+
...installed.managedBlocks.filter((entry) => entry.owner !== "shared" && !selectedSet.has(entry.owner)),
|
|
2813
2907
|
{
|
|
2814
2908
|
owner: "shared",
|
|
2815
2909
|
target_path: "AGENTS.md",
|
|
2816
2910
|
block_id: AGENTS_CORE_BLOCK_ID,
|
|
2817
2911
|
content_sha256: createHash5("sha256").update(AGENTS_MANAGED_BLOCK_CONTENT).digest("hex")
|
|
2818
2912
|
},
|
|
2819
|
-
...
|
|
2913
|
+
...selectedSet.has("claude-code") ? [{
|
|
2820
2914
|
owner: "claude-code",
|
|
2821
2915
|
target_path: "CLAUDE.md",
|
|
2822
2916
|
block_id: CLAUDE_BLOCK_ID,
|
|
2823
2917
|
content_sha256: createHash5("sha256").update(CLAUDE_MANAGED_BLOCK_CONTENT).digest("hex")
|
|
2824
2918
|
}] : [],
|
|
2825
|
-
...
|
|
2919
|
+
...selectedSet.has("codebuddy") ? [{
|
|
2826
2920
|
owner: "codebuddy",
|
|
2827
2921
|
target_path: "CODEBUDDY.md",
|
|
2828
2922
|
block_id: CODEBUDDY_BLOCK_ID,
|
|
2829
2923
|
content_sha256: createHash5("sha256").update(CODEBUDDY_MANAGED_BLOCK_CONTENT).digest("hex")
|
|
2830
2924
|
}] : []
|
|
2831
2925
|
].sort((left, right) => left.target_path.localeCompare(right.target_path) || left.block_id.localeCompare(right.block_id));
|
|
2926
|
+
const filesByTarget = new Map(newStateFiles.map((entry) => [entry.target_path, entry]));
|
|
2832
2927
|
const installedState = {
|
|
2833
|
-
schema_version:
|
|
2834
|
-
profile,
|
|
2928
|
+
schema_version: 4,
|
|
2835
2929
|
adapters: agents,
|
|
2930
|
+
profiles: Object.fromEntries(agents.map((agent) => [
|
|
2931
|
+
agent,
|
|
2932
|
+
profiles.get(agent) ?? "general"
|
|
2933
|
+
])),
|
|
2836
2934
|
installed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2837
|
-
manifests,
|
|
2838
|
-
files:
|
|
2935
|
+
manifests: manifests.sort((left, right) => left.adapter.localeCompare(right.adapter)),
|
|
2936
|
+
files: [...filesByTarget.values()].sort((left, right) => left.target_path.localeCompare(right.target_path) || left.source_path.localeCompare(right.source_path)),
|
|
2839
2937
|
managed_blocks: managedBlocks
|
|
2840
2938
|
};
|
|
2841
2939
|
const existingState = await readOptionalText(join6(root, INSTALLED_STATE_PATH));
|
|
@@ -2853,7 +2951,10 @@ async function refreshProject(options) {
|
|
|
2853
2951
|
}
|
|
2854
2952
|
if (!options.dryRun) {
|
|
2855
2953
|
await runTransaction(root, ops, { kind: "refresh" });
|
|
2856
|
-
await pruneEmptyParentDirs(root, removed.map((item2) => item2.target_path), getAdapters(
|
|
2954
|
+
await pruneEmptyParentDirs(root, removed.map((item2) => item2.target_path), getAdapters(selectedAgents).flatMap((adapter) => adapter.pruneBoundaries({
|
|
2955
|
+
profile: profiles.get(adapter.name) ?? profile,
|
|
2956
|
+
codebuddySurface: codebuddySurface2
|
|
2957
|
+
})));
|
|
2857
2958
|
}
|
|
2858
2959
|
return {
|
|
2859
2960
|
profile,
|
|
@@ -3279,6 +3380,17 @@ async function ensureCredentialsGitignore(projectRoot) {
|
|
|
3279
3380
|
}
|
|
3280
3381
|
}
|
|
3281
3382
|
const existing = new Set(content.split("\n").map((line) => line.trim()));
|
|
3383
|
+
const harnessDirectoryIgnored = [
|
|
3384
|
+
".harness",
|
|
3385
|
+
".harness/",
|
|
3386
|
+
"/.harness",
|
|
3387
|
+
"/.harness/",
|
|
3388
|
+
".harness/**",
|
|
3389
|
+
"/.harness/**"
|
|
3390
|
+
].some((line) => existing.has(line));
|
|
3391
|
+
if (harnessDirectoryIgnored) {
|
|
3392
|
+
return;
|
|
3393
|
+
}
|
|
3282
3394
|
const missing = CREDENTIALS_GITIGNORE_LINES.filter((line) => !existing.has(line));
|
|
3283
3395
|
if (missing.length === 0) {
|
|
3284
3396
|
return;
|
|
@@ -3292,11 +3404,21 @@ function resolvePushAuth(input) {
|
|
|
3292
3404
|
const localToken = input.local?.token?.trim();
|
|
3293
3405
|
const token = envToken && envToken.length > 0 ? envToken : localToken && localToken.length > 0 ? localToken : void 0;
|
|
3294
3406
|
const serverUrl = input.serverUrlFlag ?? input.local?.server_url ?? input.projectUrl ?? void 0;
|
|
3407
|
+
const missing = [];
|
|
3295
3408
|
if (serverUrl === void 0 || serverUrl === null || serverUrl.trim() === "") {
|
|
3296
|
-
|
|
3409
|
+
missing.push("url");
|
|
3297
3410
|
}
|
|
3298
3411
|
if (token === void 0) {
|
|
3299
|
-
|
|
3412
|
+
missing.push("token");
|
|
3413
|
+
}
|
|
3414
|
+
if (missing.length > 0) {
|
|
3415
|
+
return {
|
|
3416
|
+
code: missing.includes("url") ? "SERVER_URL_REQUIRED" : "TOKEN_INVALID",
|
|
3417
|
+
missing
|
|
3418
|
+
};
|
|
3419
|
+
}
|
|
3420
|
+
if (serverUrl === void 0 || token === void 0) {
|
|
3421
|
+
throw new Error("push auth resolution invariant failed");
|
|
3300
3422
|
}
|
|
3301
3423
|
return { serverUrl, token };
|
|
3302
3424
|
}
|
|
@@ -3634,9 +3756,6 @@ async function pushProject(options) {
|
|
|
3634
3756
|
if (options.dryRun) {
|
|
3635
3757
|
return { preview, proposalId: null, projectId: project.project.project_id };
|
|
3636
3758
|
}
|
|
3637
|
-
if (options.confirmProposal !== void 0 && !await options.confirmProposal(preview)) {
|
|
3638
|
-
return { preview, proposalId: null, projectId: project.project.project_id, cancelled: true };
|
|
3639
|
-
}
|
|
3640
3759
|
const localCredentials = await readLocalCredentials(root);
|
|
3641
3760
|
const auth = resolvePushAuth({
|
|
3642
3761
|
...options.serverUrl === void 0 ? {} : { serverUrlFlag: options.serverUrl },
|
|
@@ -3648,10 +3767,10 @@ async function pushProject(options) {
|
|
|
3648
3767
|
});
|
|
3649
3768
|
if ("code" in auth) {
|
|
3650
3769
|
if (auth.code === "SERVER_URL_REQUIRED") {
|
|
3651
|
-
throw new PushWorkflowError("server_url is required; use --server-url, project.yaml server.url, or " + CREDENTIALS_HINT, 3, "SERVER_URL_REQUIRED");
|
|
3770
|
+
throw new PushWorkflowError("server_url is required; use --server-url, project.yaml server.url, or " + CREDENTIALS_HINT, 3, "SERVER_URL_REQUIRED", { missing_credentials: auth.missing });
|
|
3652
3771
|
}
|
|
3653
3772
|
const tokenEnv2 = options.tokenEnv ?? project.server.token_env;
|
|
3654
|
-
throw new PushWorkflowError("API token is unset; set " + tokenEnv2 + " or " + CREDENTIALS_HINT, 8, "TOKEN_INVALID");
|
|
3773
|
+
throw new PushWorkflowError("API token is unset; set " + tokenEnv2 + " or " + CREDENTIALS_HINT, 8, "TOKEN_INVALID", { missing_credentials: auth.missing });
|
|
3655
3774
|
}
|
|
3656
3775
|
const serverUrl = auth.serverUrl;
|
|
3657
3776
|
const token = auth.token;
|
|
@@ -3668,6 +3787,9 @@ async function pushProject(options) {
|
|
|
3668
3787
|
if (parsedServerUrl.protocol !== "https:") {
|
|
3669
3788
|
throw new PushWorkflowError("server_url must use HTTPS", 3, "SERVER_URL_INVALID");
|
|
3670
3789
|
}
|
|
3790
|
+
if (options.confirmProposal !== void 0 && !await options.confirmProposal(preview)) {
|
|
3791
|
+
return { preview, proposalId: null, projectId: project.project.project_id, cancelled: true };
|
|
3792
|
+
}
|
|
3671
3793
|
const workflowPath = join10(root, ".harness", "state", "local", "push-workflow.json");
|
|
3672
3794
|
const priorWorkflow = await readOptionalJson(workflowPath);
|
|
3673
3795
|
const provisionalRequestId = priorWorkflow?.local_project_key === project.project.local_project_key ? priorWorkflow.request_id : uuidV7();
|
|
@@ -4568,9 +4690,9 @@ async function detectProject(root) {
|
|
|
4568
4690
|
}
|
|
4569
4691
|
return { status: "valid", config: parsed.data };
|
|
4570
4692
|
}
|
|
4571
|
-
function parseProfile(value
|
|
4693
|
+
function parseProfile(value) {
|
|
4572
4694
|
if (value === void 0 || value === "") {
|
|
4573
|
-
return
|
|
4695
|
+
return void 0;
|
|
4574
4696
|
}
|
|
4575
4697
|
if (value === "1" || value === "general") return "general";
|
|
4576
4698
|
if (value === "2" || value === "java") return "java";
|
|
@@ -4655,7 +4777,7 @@ async function runRefresh(options, dependencies) {
|
|
|
4655
4777
|
let targetProfile;
|
|
4656
4778
|
let targetAgents;
|
|
4657
4779
|
try {
|
|
4658
|
-
targetProfile = parseProfile(options.profile
|
|
4780
|
+
targetProfile = parseProfile(options.profile);
|
|
4659
4781
|
targetAgents = options.agents === void 0 ? refreshAgents(detection.config) : parseAgentsInput(options.agents);
|
|
4660
4782
|
} catch (error) {
|
|
4661
4783
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -4664,12 +4786,12 @@ async function runRefresh(options, dependencies) {
|
|
|
4664
4786
|
return error instanceof InitConfigurationError ? error.exitCode : 3;
|
|
4665
4787
|
}
|
|
4666
4788
|
const dryRun = options.dryRun === true;
|
|
4667
|
-
if ((targetProfile !== currentProfile || targetAgents.some((agent, index) => agent !== refreshAgents(detection.config)[index]) || targetAgents.length !== refreshAgents(detection.config).length) && !dryRun) {
|
|
4789
|
+
if ((targetProfile !== void 0 && targetProfile !== currentProfile || targetAgents.some((agent, index) => agent !== refreshAgents(detection.config)[index]) || targetAgents.length !== refreshAgents(detection.config).length) && !dryRun) {
|
|
4668
4790
|
try {
|
|
4669
4791
|
const preview = await refreshProject({
|
|
4670
4792
|
projectRoot: dependencies.cwd,
|
|
4671
4793
|
resourcesRoot: dependencies.resourcesRoot,
|
|
4672
|
-
profile: targetProfile,
|
|
4794
|
+
...targetProfile === void 0 ? {} : { profile: targetProfile },
|
|
4673
4795
|
agents: targetAgents,
|
|
4674
4796
|
codebuddySurface: codebuddySurface(detection.config),
|
|
4675
4797
|
dryRun: true,
|
|
@@ -4694,7 +4816,7 @@ async function runRefresh(options, dependencies) {
|
|
|
4694
4816
|
return 2;
|
|
4695
4817
|
}
|
|
4696
4818
|
} else if (!options.yes && !dryRun) {
|
|
4697
|
-
const label = targetProfile === currentProfile ? `\u5237\u65B0\u5F53\u524D\u914D\u7F6E\uFF08${currentProfile}\uFF09` : `\
|
|
4819
|
+
const label = targetProfile === currentProfile ? `\u5237\u65B0\u5F53\u524D\u914D\u7F6E\uFF08${currentProfile}\uFF09` : targetProfile === void 0 ? "\u5237\u65B0\u6240\u9009\u5DE5\u5177\u7684\u5F53\u524D\u914D\u7F6E" : `\u66F4\u65B0\u6240\u9009\u5DE5\u5177\u914D\u7F6E\uFF1A${currentProfile} \u2192 ${targetProfile}`;
|
|
4698
4820
|
const answer = await dependencies.prompt(`${label}\uFF1F[y/N]\uFF1A`);
|
|
4699
4821
|
if (!/^(?:y|yes)$/i.test(answer.trim())) {
|
|
4700
4822
|
return 2;
|
|
@@ -4705,7 +4827,7 @@ async function runRefresh(options, dependencies) {
|
|
|
4705
4827
|
const result = await refreshProject({
|
|
4706
4828
|
projectRoot: dependencies.cwd,
|
|
4707
4829
|
resourcesRoot: dependencies.resourcesRoot,
|
|
4708
|
-
profile: targetProfile,
|
|
4830
|
+
...targetProfile === void 0 ? {} : { profile: targetProfile },
|
|
4709
4831
|
agents: targetAgents,
|
|
4710
4832
|
codebuddySurface: codebuddySurface(detection.config),
|
|
4711
4833
|
dryRun,
|
|
@@ -4720,7 +4842,7 @@ async function runRefresh(options, dependencies) {
|
|
|
4720
4842
|
if (result.removed.length > 0) parts.push(`\u5DF2\u5220\u9664 ${result.removed.length} \u4E2A`);
|
|
4721
4843
|
if (result.preserved.length > 0) parts.push(`\u5DF2\u4FDD\u7559 ${result.preserved.length} \u4E2A`);
|
|
4722
4844
|
if (result.unchanged.length > 0) parts.push(`\u65E0\u9700\u53D8\u66F4 ${result.unchanged.length} \u4E2A`);
|
|
4723
|
-
dependencies.stdout(`Harness \u5237\u65B0\uFF08${
|
|
4845
|
+
dependencies.stdout(`Harness \u5237\u65B0\uFF08${result.profile}\uFF09\uFF1A${parts.join("\uFF0C") || "\u6CA1\u6709\u53D8\u66F4"}\u3002
|
|
4724
4846
|
`);
|
|
4725
4847
|
}
|
|
4726
4848
|
return output.exit_code;
|
|
@@ -4750,9 +4872,12 @@ async function runRefresh(options, dependencies) {
|
|
|
4750
4872
|
}
|
|
4751
4873
|
|
|
4752
4874
|
// src/commands/configure.ts
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4875
|
+
var AGENT_LABELS = {
|
|
4876
|
+
"claude-code": "Claude Code",
|
|
4877
|
+
codex: "Codex",
|
|
4878
|
+
cursor: "Cursor",
|
|
4879
|
+
codebuddy: "CodeBuddy"
|
|
4880
|
+
};
|
|
4756
4881
|
async function runFirstInstall(options, dependencies) {
|
|
4757
4882
|
const requestId = uuidV7();
|
|
4758
4883
|
try {
|
|
@@ -4834,21 +4959,40 @@ async function runExistingProject(options, dependencies, currentProfile) {
|
|
|
4834
4959
|
if (options.nonInteractive === true) {
|
|
4835
4960
|
return runRefresh(refreshOptions, dependencies);
|
|
4836
4961
|
}
|
|
4837
|
-
const
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4962
|
+
const installed = await readInstalledAgentConfiguration(dependencies.cwd);
|
|
4963
|
+
const currentAgents = installed.agents.length > 0 ? installed.agents : ["claude-code"];
|
|
4964
|
+
const currentLines = currentAgents.map(
|
|
4965
|
+
(agent) => `- ${AGENT_LABELS[agent]}\uFF1A${installed.profiles[agent] ?? currentProfile}`
|
|
4966
|
+
).join("\n");
|
|
4967
|
+
if (refreshOptions.agents === void 0) {
|
|
4968
|
+
const defaultSelection = currentAgents.map((agent) => String(HARNESS_AGENT_ORDER.indexOf(agent) + 1)).join(",");
|
|
4969
|
+
const answer = await dependencies.prompt(
|
|
4970
|
+
`Hunter Harness \u5F53\u524D\u914D\u7F6E\uFF1A
|
|
4971
|
+
${currentLines}
|
|
4972
|
+
\u8BF7\u9009\u62E9\u672C\u6B21\u8981\u65B0\u589E\u6216\u5237\u65B0\u7684\u5DE5\u5177\uFF08\u53EF\u591A\u9009\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u672A\u9009\u62E9\u7684\u5DE5\u5177\u4FDD\u6301\u4E0D\u53D8\uFF09\uFF1A
|
|
4973
|
+
1. Claude Code
|
|
4974
|
+
2. Codex
|
|
4975
|
+
3. Cursor
|
|
4976
|
+
4. CodeBuddy
|
|
4977
|
+
\u8BF7\u8F93\u5165\u7F16\u53F7 [${defaultSelection}]\uFF0C\u6216\u8F93\u5165 0 \u53D6\u6D88\uFF1A`
|
|
4978
|
+
);
|
|
4979
|
+
if (answer.trim() === "0" || /^c/i.test(answer.trim())) return 2;
|
|
4980
|
+
refreshOptions.agents = answer.trim() === "" ? currentAgents.join(",") : answer.trim();
|
|
4981
|
+
}
|
|
4982
|
+
if (refreshOptions.profile === void 0) {
|
|
4983
|
+
const selected = parseAgentsInput(refreshOptions.agents);
|
|
4984
|
+
const selectedProfiles = new Set(selected.flatMap((agent) => {
|
|
4985
|
+
const profile = installed.profiles[agent];
|
|
4986
|
+
return profile === void 0 ? [] : [profile];
|
|
4987
|
+
}));
|
|
4988
|
+
const defaultProfile = selectedProfiles.size === 1 ? [...selectedProfiles][0] ?? currentProfile : currentProfile;
|
|
4989
|
+
const answer = await dependencies.prompt(
|
|
4990
|
+
`\u8BF7\u9009\u62E9\u6240\u9009\u5DE5\u5177\u4F7F\u7528\u7684 Harness \u914D\u7F6E\uFF1A
|
|
4991
|
+
1. \u901A\u7528
|
|
4992
|
+
2. Java
|
|
4993
|
+
\u8BF7\u8F93\u5165\u7F16\u53F7 [${defaultProfile === "java" ? "2" : "1"}]\uFF1A`
|
|
4994
|
+
);
|
|
4995
|
+
refreshOptions.profile = answer.trim() === "" ? defaultProfile : answer.trim();
|
|
4852
4996
|
}
|
|
4853
4997
|
refreshOptions.confirmed = true;
|
|
4854
4998
|
return runRefresh(refreshOptions, dependencies);
|
|
@@ -4967,7 +5111,9 @@ function errorPayload(error) {
|
|
|
4967
5111
|
}
|
|
4968
5112
|
async function promptForCredentials(dependencies, missing) {
|
|
4969
5113
|
const serverUrl = missing === "token" ? void 0 : (await dependencies.prompt("\u670D\u52A1\u7AEF URL (https://...): ")).trim();
|
|
4970
|
-
const token = missing === "url" ? void 0 : (await dependencies.
|
|
5114
|
+
const token = missing === "url" ? void 0 : (await (dependencies.promptSecret ?? dependencies.prompt)(
|
|
5115
|
+
"API Token\uFF08\u8F93\u5165\u5C06\u9690\u85CF\uFF09: "
|
|
5116
|
+
)).trim();
|
|
4971
5117
|
if ((missing === "url" || missing === "both") && (serverUrl === void 0 || serverUrl === "")) {
|
|
4972
5118
|
return null;
|
|
4973
5119
|
}
|
|
@@ -5076,7 +5222,8 @@ async function runPush(options, dependencies) {
|
|
|
5076
5222
|
return 0;
|
|
5077
5223
|
} catch (error) {
|
|
5078
5224
|
if (attempt === 0 && options.nonInteractive !== true && options.dryRun !== true && error instanceof PushWorkflowError && (error.code === "SERVER_URL_REQUIRED" || error.code === "TOKEN_INVALID")) {
|
|
5079
|
-
const
|
|
5225
|
+
const missingCredentials = error.details?.missing_credentials;
|
|
5226
|
+
const missing = missingCredentials?.includes("url") === true && missingCredentials.includes("token") ? "both" : missingCredentials?.includes("url") === true || error.code === "SERVER_URL_REQUIRED" ? "url" : "token";
|
|
5080
5227
|
dependencies.stderr(
|
|
5081
5228
|
error.message + "\n\u53EF\u5728\u4E0B\u65B9\u5F55\u5165\u5E76\u5199\u5165 .harness/credentials.local.yaml\u3002\n"
|
|
5082
5229
|
);
|
|
@@ -5405,8 +5552,12 @@ async function verifyWorkflowPackageIntegrity(resourcesRoot) {
|
|
|
5405
5552
|
async function monorepoResourcesRoot() {
|
|
5406
5553
|
const here = dirname4(fileURLToPath(import.meta.url));
|
|
5407
5554
|
const candidates = [
|
|
5408
|
-
|
|
5409
|
-
join17(here, "
|
|
5555
|
+
// TypeScript source: packages/cli/src/workflow-data -> packages/workflow-data-harness.
|
|
5556
|
+
join17(here, "../../../workflow-data-harness"),
|
|
5557
|
+
// Bundled CLI: packages/cli/dist -> packages/workflow-data-harness.
|
|
5558
|
+
join17(here, "../../workflow-data-harness"),
|
|
5559
|
+
// Test/build layouts that preserve additional source directory levels.
|
|
5560
|
+
join17(here, "../../../../packages/workflow-data-harness")
|
|
5410
5561
|
];
|
|
5411
5562
|
for (const candidate of candidates) {
|
|
5412
5563
|
if (await pathExists3(join17(candidate, "harness", "manifests"))) return candidate;
|
|
@@ -5414,9 +5565,14 @@ async function monorepoResourcesRoot() {
|
|
|
5414
5565
|
return null;
|
|
5415
5566
|
}
|
|
5416
5567
|
async function siblingWorkflowPackage(cwd) {
|
|
5568
|
+
const here = dirname4(fileURLToPath(import.meta.url));
|
|
5417
5569
|
const candidates = [
|
|
5418
5570
|
join17(cwd, "node_modules", "@hunter-harness", "workflow-harness"),
|
|
5419
|
-
|
|
5571
|
+
// Published layout: node_modules/hunter-harness/dist/bin.js alongside the
|
|
5572
|
+
// scoped workflow package in node_modules/@hunter-harness/workflow-harness.
|
|
5573
|
+
join17(here, "..", "..", "@hunter-harness", "workflow-harness"),
|
|
5574
|
+
// Monorepo bundled layout: packages/cli/dist/bin.js.
|
|
5575
|
+
join17(here, "..", "..", "workflow-data-harness")
|
|
5420
5576
|
];
|
|
5421
5577
|
for (const candidate of candidates) {
|
|
5422
5578
|
if (await pathExists3(join17(candidate, "harness", "manifests"))) return candidate;
|
|
@@ -5537,6 +5693,33 @@ async function readWorkflowFamilyManifest(resourcesRoot) {
|
|
|
5537
5693
|
}
|
|
5538
5694
|
|
|
5539
5695
|
// src/bin.ts
|
|
5696
|
+
async function promptSecret(question, input = process.stdin, output = process.stdout) {
|
|
5697
|
+
if (input.isTTY !== true || output.isTTY !== true) {
|
|
5698
|
+
const terminal2 = createInterface({ input, output });
|
|
5699
|
+
try {
|
|
5700
|
+
return await terminal2.question(question);
|
|
5701
|
+
} finally {
|
|
5702
|
+
terminal2.close();
|
|
5703
|
+
}
|
|
5704
|
+
}
|
|
5705
|
+
output.write(question);
|
|
5706
|
+
const mutedOutput = new Writable({
|
|
5707
|
+
write(_chunk, _encoding, callback) {
|
|
5708
|
+
callback();
|
|
5709
|
+
}
|
|
5710
|
+
});
|
|
5711
|
+
const terminal = createInterface({
|
|
5712
|
+
input,
|
|
5713
|
+
output: mutedOutput,
|
|
5714
|
+
terminal: true
|
|
5715
|
+
});
|
|
5716
|
+
try {
|
|
5717
|
+
return await terminal.question("");
|
|
5718
|
+
} finally {
|
|
5719
|
+
terminal.close();
|
|
5720
|
+
output.write("\n");
|
|
5721
|
+
}
|
|
5722
|
+
}
|
|
5540
5723
|
function defaultDependencies(overrides) {
|
|
5541
5724
|
return {
|
|
5542
5725
|
cwd: overrides.cwd ?? process.cwd(),
|
|
@@ -5551,6 +5734,7 @@ function defaultDependencies(overrides) {
|
|
|
5551
5734
|
terminal.close();
|
|
5552
5735
|
}
|
|
5553
5736
|
}),
|
|
5737
|
+
promptSecret: overrides.promptSecret ?? overrides.prompt ?? promptSecret,
|
|
5554
5738
|
fetch: overrides.fetch ?? globalThis.fetch,
|
|
5555
5739
|
env: overrides.env ?? process.env
|
|
5556
5740
|
};
|
|
@@ -5634,5 +5818,6 @@ if (isDirectCliEntrypoint()) {
|
|
|
5634
5818
|
}
|
|
5635
5819
|
export {
|
|
5636
5820
|
isDirectCliEntrypoint,
|
|
5821
|
+
promptSecret,
|
|
5637
5822
|
runCli
|
|
5638
5823
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hunter-harness",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Local-first, server-governed agent harness",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json && npm run bundle",
|
|
18
|
-
"bundle": "node ../../
|
|
18
|
+
"bundle": "node ../../scripts/bundle-cli.mjs",
|
|
19
19
|
"typecheck": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json --noEmit",
|
|
20
20
|
"prepack": "npm run build"
|
|
21
21
|
},
|