@neat.is/core 0.5.2 → 0.5.4-dev.20260721
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/{chunk-I72HTUOG.js → chunk-4RU3AAOI.js} +2 -2
- package/dist/{chunk-CFDPIMRP.js → chunk-I4NZ7PSN.js} +3 -2
- package/dist/chunk-I4NZ7PSN.js.map +1 -0
- package/dist/{chunk-BI3XKGVG.js → chunk-PEFX3DBR.js} +473 -127
- package/dist/chunk-PEFX3DBR.js.map +1 -0
- package/dist/{chunk-DPEPI2N6.js → chunk-VR73QNJD.js} +293 -22
- package/dist/chunk-VR73QNJD.js.map +1 -0
- package/dist/cli.cjs +1371 -479
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +343 -75
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +879 -310
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +888 -319
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-IDMIH6ZY.js → otel-grpc-TEGOXE6T.js} +3 -3
- package/dist/server.cjs +553 -192
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-BI3XKGVG.js.map +0 -1
- package/dist/chunk-CFDPIMRP.js.map +0 -1
- package/dist/chunk-DPEPI2N6.js.map +0 -1
- /package/dist/{chunk-I72HTUOG.js.map → chunk-4RU3AAOI.js.map} +0 -0
- /package/dist/{otel-grpc-IDMIH6ZY.js.map → otel-grpc-TEGOXE6T.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
PROVIDER_DISPATCH,
|
|
4
3
|
clearDaemonRecord,
|
|
5
|
-
|
|
4
|
+
deprovisionConnector,
|
|
5
|
+
getProviderFieldSchema,
|
|
6
|
+
isPushProvider,
|
|
7
|
+
knownProviderNames,
|
|
6
8
|
portFromListenAddress,
|
|
9
|
+
provisionConnector,
|
|
7
10
|
readDaemonRecord,
|
|
8
11
|
resolveHost,
|
|
9
12
|
resolveNeatVersion,
|
|
10
13
|
validateConnectorEntry,
|
|
11
14
|
writeDaemonRecord
|
|
12
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VR73QNJD.js";
|
|
13
16
|
import {
|
|
14
17
|
buildSearchIndex
|
|
15
18
|
} from "./chunk-BIY46Q6U.js";
|
|
@@ -68,10 +71,10 @@ import {
|
|
|
68
71
|
startPersistLoop,
|
|
69
72
|
startStalenessLoop,
|
|
70
73
|
upsertConnectorEntry
|
|
71
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-PEFX3DBR.js";
|
|
72
75
|
import {
|
|
73
76
|
startOtelGrpcReceiver
|
|
74
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-4RU3AAOI.js";
|
|
75
78
|
import {
|
|
76
79
|
__dirname,
|
|
77
80
|
__require,
|
|
@@ -79,11 +82,11 @@ import {
|
|
|
79
82
|
buildOtelReceiver,
|
|
80
83
|
listenSteppingOtlp,
|
|
81
84
|
readAuthEnv
|
|
82
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-I4NZ7PSN.js";
|
|
83
86
|
|
|
84
87
|
// src/cli.ts
|
|
85
|
-
import
|
|
86
|
-
import { promises as
|
|
88
|
+
import path10 from "path";
|
|
89
|
+
import { promises as fs8 } from "fs";
|
|
87
90
|
|
|
88
91
|
// src/banner.ts
|
|
89
92
|
import path from "path";
|
|
@@ -3566,6 +3569,8 @@ function parseConnectorArgs(args) {
|
|
|
3566
3569
|
positional: [],
|
|
3567
3570
|
skipValidate: false,
|
|
3568
3571
|
plaintext: false,
|
|
3572
|
+
help: false,
|
|
3573
|
+
json: false,
|
|
3569
3574
|
fields: {}
|
|
3570
3575
|
};
|
|
3571
3576
|
const positional = [];
|
|
@@ -3579,6 +3584,14 @@ function parseConnectorArgs(args) {
|
|
|
3579
3584
|
out.plaintext = true;
|
|
3580
3585
|
continue;
|
|
3581
3586
|
}
|
|
3587
|
+
if (arg === "--help" || arg === "-h") {
|
|
3588
|
+
out.help = true;
|
|
3589
|
+
continue;
|
|
3590
|
+
}
|
|
3591
|
+
if (arg === "--json") {
|
|
3592
|
+
out.json = true;
|
|
3593
|
+
continue;
|
|
3594
|
+
}
|
|
3582
3595
|
if (arg.startsWith("--")) {
|
|
3583
3596
|
let flag = arg;
|
|
3584
3597
|
let value;
|
|
@@ -3655,19 +3668,20 @@ function plaintextFields(ref) {
|
|
|
3655
3668
|
async function connectorAdd(args, deps) {
|
|
3656
3669
|
let provider = args.positional[0];
|
|
3657
3670
|
if (!provider && deps.interactive) {
|
|
3658
|
-
provider = (await deps.prompt(`Provider (${
|
|
3671
|
+
provider = (await deps.prompt(`Provider (${knownProviderNames().join(", ")}):`)).trim();
|
|
3659
3672
|
}
|
|
3660
3673
|
if (!provider) {
|
|
3661
3674
|
deps.err("neat connector add: a provider is required (e.g. `neat connector add supabase`)");
|
|
3662
3675
|
return 2;
|
|
3663
3676
|
}
|
|
3664
|
-
const dispatch =
|
|
3677
|
+
const dispatch = getProviderFieldSchema(provider);
|
|
3665
3678
|
if (!dispatch) {
|
|
3666
3679
|
deps.err(
|
|
3667
|
-
`neat connector add: unknown provider "${provider}". known providers: ${
|
|
3680
|
+
`neat connector add: unknown provider "${provider}". known providers: ${knownProviderNames().join(", ")}`
|
|
3668
3681
|
);
|
|
3669
3682
|
return 2;
|
|
3670
3683
|
}
|
|
3684
|
+
const push = isPushProvider(provider);
|
|
3671
3685
|
let project = args.project;
|
|
3672
3686
|
if (project === void 0 && deps.interactive) {
|
|
3673
3687
|
const answer = (await deps.prompt("Project (blank = the project the daemon is bootstrapping):")).trim();
|
|
@@ -3706,7 +3720,7 @@ async function connectorAdd(args, deps) {
|
|
|
3706
3720
|
credential,
|
|
3707
3721
|
...Object.keys(options).length > 0 ? { options } : {}
|
|
3708
3722
|
};
|
|
3709
|
-
if (!args.skipValidate) {
|
|
3723
|
+
if (!push && !args.skipValidate) {
|
|
3710
3724
|
const outcome = await validateConnectorEntry(entry2, deps.env, deps.fetchImpl);
|
|
3711
3725
|
const code = reportPreWriteValidation(outcome, deps);
|
|
3712
3726
|
if (code !== 0) return code;
|
|
@@ -3717,14 +3731,32 @@ async function connectorAdd(args, deps) {
|
|
|
3717
3731
|
`neat connector add: storing a literal secret at rest for ${plaintext.join(", ")} \u2014 prefer an env-var reference like \`$PROVIDER_TOKEN\` (pass --plaintext to silence this).`
|
|
3718
3732
|
);
|
|
3719
3733
|
}
|
|
3734
|
+
if (push) {
|
|
3735
|
+
if (args.skipValidate) {
|
|
3736
|
+
deps.out("note: --skip-validate has no effect for a push provider \u2014 provisioning the drain is the add.");
|
|
3737
|
+
}
|
|
3738
|
+
const outcome = await provisionConnector(entry2, deps.env, deps.fetchImpl);
|
|
3739
|
+
if (outcome.status !== "ok") {
|
|
3740
|
+
deps.err(
|
|
3741
|
+
`neat connector add: could not provision the ${provider} connector \u2014 ${outcome.reason}. Nothing was written.`
|
|
3742
|
+
);
|
|
3743
|
+
return 1;
|
|
3744
|
+
}
|
|
3745
|
+
if (outcome.options) entry2.options = { ...entry2.options ?? {}, ...outcome.options };
|
|
3746
|
+
if (outcome.note) deps.out(`note: ${outcome.note}`);
|
|
3747
|
+
}
|
|
3720
3748
|
const { replaced } = await upsertConnectorEntry(entry2, deps.home);
|
|
3721
3749
|
const verb = replaced ? "updated" : "added";
|
|
3722
3750
|
const where = project ? `project "${project}"` : "the bootstrapping project";
|
|
3723
3751
|
deps.out(`${verb} connector "${id}" (${provider}) for ${where}.`);
|
|
3724
|
-
if (
|
|
3725
|
-
deps.out("
|
|
3752
|
+
if (push) {
|
|
3753
|
+
deps.out("The drain is live \u2014 traces arrive at the daemon's OTLP receiver. No poll or restart needed.");
|
|
3754
|
+
} else {
|
|
3755
|
+
if (args.skipValidate) {
|
|
3756
|
+
deps.out("skipped validation (--skip-validate) \u2014 the credential is checked at the next daemon poll.");
|
|
3757
|
+
}
|
|
3758
|
+
deps.out("Restart the project's daemon (or start it) to begin polling this connector.");
|
|
3726
3759
|
}
|
|
3727
|
-
deps.out("Restart the project's daemon (or start it) to begin polling this connector.");
|
|
3728
3760
|
return 0;
|
|
3729
3761
|
}
|
|
3730
3762
|
function reportPreWriteValidation(outcome, deps) {
|
|
@@ -3750,10 +3782,26 @@ function reportPreWriteValidation(outcome, deps) {
|
|
|
3750
3782
|
return 2;
|
|
3751
3783
|
}
|
|
3752
3784
|
}
|
|
3753
|
-
async function connectorList(deps, filterProject) {
|
|
3785
|
+
async function connectorList(deps, filterProject, json = false) {
|
|
3754
3786
|
const config = await readConnectorsConfig(deps.home);
|
|
3755
3787
|
let entries = config.connectors;
|
|
3756
3788
|
if (filterProject) entries = entries.filter((e) => e.project === filterProject);
|
|
3789
|
+
if (json) {
|
|
3790
|
+
const rows = entries.map((e) => ({
|
|
3791
|
+
id: e.id,
|
|
3792
|
+
provider: e.provider,
|
|
3793
|
+
project: e.project ?? null,
|
|
3794
|
+
kind: isPushProvider(e.provider) ? "push" : "pull",
|
|
3795
|
+
credential: describeCredential(e.credential, deps.env).map((c) => ({
|
|
3796
|
+
...c.field ? { field: c.field } : {},
|
|
3797
|
+
ref: c.display,
|
|
3798
|
+
...c.status ? { status: c.status } : { kind: c.kind }
|
|
3799
|
+
})),
|
|
3800
|
+
...e.options ? { options: e.options } : {}
|
|
3801
|
+
}));
|
|
3802
|
+
deps.out(JSON.stringify(rows, null, 2));
|
|
3803
|
+
return 0;
|
|
3804
|
+
}
|
|
3757
3805
|
if (entries.length === 0) {
|
|
3758
3806
|
deps.out(
|
|
3759
3807
|
filterProject ? `no connectors configured for project "${filterProject}".` : "no connectors configured. run `neat connector add <provider>` to add one."
|
|
@@ -3776,6 +3824,22 @@ async function connectorRemove(deps, id) {
|
|
|
3776
3824
|
deps.err("neat connector remove: missing <id>. run `neat connector list` to see configured ids.");
|
|
3777
3825
|
return 2;
|
|
3778
3826
|
}
|
|
3827
|
+
const config = await readConnectorsConfig(deps.home);
|
|
3828
|
+
const entry2 = config.connectors.find((c) => c.id === id);
|
|
3829
|
+
if (!entry2) {
|
|
3830
|
+
deps.err(`neat connector remove: no connector with id "${id}". run \`neat connector list\` to see configured ids.`);
|
|
3831
|
+
return 1;
|
|
3832
|
+
}
|
|
3833
|
+
if (isPushProvider(entry2.provider)) {
|
|
3834
|
+
const outcome = await deprovisionConnector(entry2, deps.env, deps.fetchImpl);
|
|
3835
|
+
if (outcome.status !== "ok") {
|
|
3836
|
+
deps.err(
|
|
3837
|
+
`neat connector remove: could not delete the ${entry2.provider} drain \u2014 ${outcome.reason}. The entry was kept so you can retry (or delete the drain in the Vercel dashboard, then re-run).`
|
|
3838
|
+
);
|
|
3839
|
+
return 1;
|
|
3840
|
+
}
|
|
3841
|
+
if (outcome.note) deps.out(`note: ${outcome.note}`);
|
|
3842
|
+
}
|
|
3779
3843
|
const removed = await removeConnectorEntry(id, deps.home);
|
|
3780
3844
|
if (!removed) {
|
|
3781
3845
|
deps.err(`neat connector remove: no connector with id "${id}". run \`neat connector list\` to see configured ids.`);
|
|
@@ -3816,13 +3880,20 @@ async function connectorTest(deps, id) {
|
|
|
3816
3880
|
}
|
|
3817
3881
|
function printConnectorUsage(write) {
|
|
3818
3882
|
write("usage: neat connector <add|list|remove|test> [args]");
|
|
3883
|
+
write(` providers: ${knownProviderNames().join(", ")}`);
|
|
3884
|
+
write(" pull (polled): supabase, railway, firebase, cloudflare");
|
|
3885
|
+
write(" push (drains): vercel \u2014 provisions a Vercel trace Drain that forwards");
|
|
3886
|
+
write(" traces to the daemon's OTLP receiver; no app instrumentation");
|
|
3819
3887
|
write(" add <provider> add a connector; validates the credential first (--skip-validate to skip)");
|
|
3820
3888
|
write(" flags: --project <name> --credential/--token <$VAR|value> --id <id>");
|
|
3821
3889
|
write(" --<option> <value> (provider-specific) --plaintext --skip-validate");
|
|
3890
|
+
write(" vercel: neat connector add vercel --token $VERCEL_TOKEN \\");
|
|
3891
|
+
write(" --otel-token $NEAT_OTEL_TOKEN --team-id <teamId> \\");
|
|
3892
|
+
write(" --endpoint https://<public-host>/v1/traces [--project-ids <id,id>]");
|
|
3822
3893
|
write(" list list configured connectors (credentials shown redacted)");
|
|
3823
3894
|
write(" flags: --project <name>");
|
|
3824
|
-
write(" remove <id> remove a connector by id");
|
|
3825
|
-
write(" test <id> re-run
|
|
3895
|
+
write(" remove <id> remove a connector by id (a push provider also has its drain deleted)");
|
|
3896
|
+
write(" test <id> re-run validation for an existing connector (a push provider re-tests its drain)");
|
|
3826
3897
|
}
|
|
3827
3898
|
async function runConnectorCommand(rawArgs, deps = {}) {
|
|
3828
3899
|
const resolved = resolveDeps(deps);
|
|
@@ -3832,11 +3903,15 @@ async function runConnectorCommand(rawArgs, deps = {}) {
|
|
|
3832
3903
|
return 2;
|
|
3833
3904
|
}
|
|
3834
3905
|
const a = parsed.value;
|
|
3906
|
+
if (a.help) {
|
|
3907
|
+
printConnectorUsage(resolved.out);
|
|
3908
|
+
return 0;
|
|
3909
|
+
}
|
|
3835
3910
|
switch (a.subcommand) {
|
|
3836
3911
|
case "add":
|
|
3837
3912
|
return connectorAdd(a, resolved);
|
|
3838
3913
|
case "list":
|
|
3839
|
-
return connectorList(resolved, a.project);
|
|
3914
|
+
return connectorList(resolved, a.project, a.json);
|
|
3840
3915
|
case "remove":
|
|
3841
3916
|
return connectorRemove(resolved, a.positional[0]);
|
|
3842
3917
|
case "test":
|
|
@@ -3852,8 +3927,181 @@ async function runConnectorCommand(rawArgs, deps = {}) {
|
|
|
3852
3927
|
}
|
|
3853
3928
|
}
|
|
3854
3929
|
|
|
3855
|
-
// src/cli
|
|
3930
|
+
// src/hooks-cli.ts
|
|
3856
3931
|
import path8 from "path";
|
|
3932
|
+
import os from "os";
|
|
3933
|
+
import { promises as fs7 } from "fs";
|
|
3934
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3935
|
+
var HOOK_FILENAME = "neat-search-nudge.mjs";
|
|
3936
|
+
var GUIDE_FILENAME = "GRAPH_FIRST.md";
|
|
3937
|
+
var GUIDE_INSTALL_NAME = "neat-graph-first.md";
|
|
3938
|
+
var HOOK_MATCHER = "Grep|Glob|Bash";
|
|
3939
|
+
function moduleDir() {
|
|
3940
|
+
return typeof __dirname !== "undefined" ? __dirname : path8.dirname(fileURLToPath3(import.meta.url));
|
|
3941
|
+
}
|
|
3942
|
+
async function readSkillAsset(rel) {
|
|
3943
|
+
const here = moduleDir();
|
|
3944
|
+
const candidates = [
|
|
3945
|
+
path8.resolve(here, "../../claude-skill", rel),
|
|
3946
|
+
path8.resolve(here, "../../../claude-skill", rel),
|
|
3947
|
+
path8.resolve(here, "../claude-skill", rel)
|
|
3948
|
+
];
|
|
3949
|
+
for (const candidate of candidates) {
|
|
3950
|
+
try {
|
|
3951
|
+
return await fs7.readFile(candidate, "utf8");
|
|
3952
|
+
} catch {
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
throw new Error(
|
|
3956
|
+
`neat hooks: could not find @neat.is/claude-skill/${rel} \u2014 is the package installed?`
|
|
3957
|
+
);
|
|
3958
|
+
}
|
|
3959
|
+
function neatHome() {
|
|
3960
|
+
const override = process.env.NEAT_HOME;
|
|
3961
|
+
if (override && override.length > 0) return path8.resolve(override);
|
|
3962
|
+
return path8.join(os.homedir(), ".neat");
|
|
3963
|
+
}
|
|
3964
|
+
function claudeSettingsPath() {
|
|
3965
|
+
const override = process.env.NEAT_CLAUDE_SETTINGS;
|
|
3966
|
+
if (override && override.length > 0) return path8.resolve(override);
|
|
3967
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? os.homedir();
|
|
3968
|
+
return path8.join(home, ".claude", "settings.json");
|
|
3969
|
+
}
|
|
3970
|
+
function installedHookPath() {
|
|
3971
|
+
return path8.join(neatHome(), "hooks", HOOK_FILENAME);
|
|
3972
|
+
}
|
|
3973
|
+
function isNeatSearchEntry(entry2) {
|
|
3974
|
+
return (entry2.hooks ?? []).some(
|
|
3975
|
+
(h) => typeof h.command === "string" && h.command.includes(HOOK_FILENAME)
|
|
3976
|
+
);
|
|
3977
|
+
}
|
|
3978
|
+
function neatHookEntry(command) {
|
|
3979
|
+
return { matcher: HOOK_MATCHER, hooks: [{ type: "command", command }] };
|
|
3980
|
+
}
|
|
3981
|
+
function hookCommand(scriptPath) {
|
|
3982
|
+
return `node "${scriptPath}"`;
|
|
3983
|
+
}
|
|
3984
|
+
async function runHooks(opts) {
|
|
3985
|
+
if (opts.printHook) {
|
|
3986
|
+
process.stdout.write(await readSkillAsset(`hooks/${HOOK_FILENAME}`));
|
|
3987
|
+
return { exitCode: 0 };
|
|
3988
|
+
}
|
|
3989
|
+
if (opts.printGuide) {
|
|
3990
|
+
process.stdout.write(await readSkillAsset(GUIDE_FILENAME));
|
|
3991
|
+
return { exitCode: 0 };
|
|
3992
|
+
}
|
|
3993
|
+
if (opts.printSettings) {
|
|
3994
|
+
const block = {
|
|
3995
|
+
hooks: { PreToolUse: [neatHookEntry(hookCommand(installedHookPath()))] }
|
|
3996
|
+
};
|
|
3997
|
+
process.stdout.write(JSON.stringify(block, null, 2) + "\n");
|
|
3998
|
+
return { exitCode: 0 };
|
|
3999
|
+
}
|
|
4000
|
+
if (opts.apply) {
|
|
4001
|
+
const hookScript = await readSkillAsset(`hooks/${HOOK_FILENAME}`);
|
|
4002
|
+
const guide = await readSkillAsset(GUIDE_FILENAME);
|
|
4003
|
+
const scriptPath = installedHookPath();
|
|
4004
|
+
await fs7.mkdir(path8.dirname(scriptPath), { recursive: true });
|
|
4005
|
+
await fs7.writeFile(scriptPath, hookScript, { mode: 493 });
|
|
4006
|
+
const guidePath = path8.join(neatHome(), GUIDE_INSTALL_NAME);
|
|
4007
|
+
await fs7.writeFile(guidePath, guide, "utf8");
|
|
4008
|
+
const settingsFile = claudeSettingsPath();
|
|
4009
|
+
let settings = {};
|
|
4010
|
+
try {
|
|
4011
|
+
settings = JSON.parse(await fs7.readFile(settingsFile, "utf8"));
|
|
4012
|
+
} catch (err) {
|
|
4013
|
+
if (err.code !== "ENOENT") {
|
|
4014
|
+
console.error(
|
|
4015
|
+
`neat hooks: failed to read ${settingsFile} \u2014 ${err.message}`
|
|
4016
|
+
);
|
|
4017
|
+
return { exitCode: 1 };
|
|
4018
|
+
}
|
|
4019
|
+
}
|
|
4020
|
+
const hooks = settings.hooks ?? {};
|
|
4021
|
+
const preToolUse = Array.isArray(hooks.PreToolUse) ? [...hooks.PreToolUse] : [];
|
|
4022
|
+
const command = hookCommand(scriptPath);
|
|
4023
|
+
const existingIdx = preToolUse.findIndex(isNeatSearchEntry);
|
|
4024
|
+
if (existingIdx >= 0) {
|
|
4025
|
+
preToolUse[existingIdx] = neatHookEntry(command);
|
|
4026
|
+
} else {
|
|
4027
|
+
preToolUse.push(neatHookEntry(command));
|
|
4028
|
+
}
|
|
4029
|
+
const merged = {
|
|
4030
|
+
...settings,
|
|
4031
|
+
hooks: { ...hooks, PreToolUse: preToolUse }
|
|
4032
|
+
};
|
|
4033
|
+
await fs7.mkdir(path8.dirname(settingsFile), { recursive: true });
|
|
4034
|
+
await fs7.writeFile(settingsFile, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
4035
|
+
console.log(`neat hooks: installed the search-nudge hook`);
|
|
4036
|
+
console.log(` script: ${scriptPath}`);
|
|
4037
|
+
console.log(` settings: ${settingsFile} (PreToolUse \u2192 ${HOOK_MATCHER})`);
|
|
4038
|
+
console.log(` guidance: ${guidePath}`);
|
|
4039
|
+
console.log("");
|
|
4040
|
+
console.log("restart Claude Code to load the hook. On a Grep/Glob or a Bash grep,");
|
|
4041
|
+
console.log("your agent will now be nudged to query NEAT first.");
|
|
4042
|
+
console.log("");
|
|
4043
|
+
console.log("The hook is Claude-Code-specific. For agents on other harnesses, paste");
|
|
4044
|
+
console.log(`the guidance above into your project instructions (CLAUDE.md / AGENTS.md).`);
|
|
4045
|
+
return { exitCode: 0 };
|
|
4046
|
+
}
|
|
4047
|
+
usage();
|
|
4048
|
+
return { exitCode: 0 };
|
|
4049
|
+
}
|
|
4050
|
+
function usage() {
|
|
4051
|
+
console.log("neat hooks \u2014 wire NEAT into your agent so it queries the graph before grepping");
|
|
4052
|
+
console.log("");
|
|
4053
|
+
console.log(" --apply install the Claude Code search-nudge hook and write the");
|
|
4054
|
+
console.log(" graph-first guidance to ~/.neat/, merging into");
|
|
4055
|
+
console.log(" ~/.claude/settings.json without touching your other hooks");
|
|
4056
|
+
console.log(" --print-hook print the hook script to stdout");
|
|
4057
|
+
console.log(" --print-guide print the agent-agnostic graph-first guidance to stdout");
|
|
4058
|
+
console.log(" --print-settings print the settings.json PreToolUse block --apply would add");
|
|
4059
|
+
console.log("");
|
|
4060
|
+
console.log("The hook is a gentle, non-blocking nudge \u2014 searches still run. It is");
|
|
4061
|
+
console.log("Claude-Code-specific; other harnesses get the same steer from the guidance.");
|
|
4062
|
+
}
|
|
4063
|
+
async function runHooksCommand(args) {
|
|
4064
|
+
const opts = {
|
|
4065
|
+
apply: false,
|
|
4066
|
+
printHook: false,
|
|
4067
|
+
printGuide: false,
|
|
4068
|
+
printSettings: false
|
|
4069
|
+
};
|
|
4070
|
+
for (const arg of args) {
|
|
4071
|
+
switch (arg) {
|
|
4072
|
+
case "--apply":
|
|
4073
|
+
opts.apply = true;
|
|
4074
|
+
break;
|
|
4075
|
+
case "--print-hook":
|
|
4076
|
+
opts.printHook = true;
|
|
4077
|
+
break;
|
|
4078
|
+
case "--print-guide":
|
|
4079
|
+
opts.printGuide = true;
|
|
4080
|
+
break;
|
|
4081
|
+
case "--print-settings":
|
|
4082
|
+
opts.printSettings = true;
|
|
4083
|
+
break;
|
|
4084
|
+
case "-h":
|
|
4085
|
+
case "--help":
|
|
4086
|
+
usage();
|
|
4087
|
+
return 0;
|
|
4088
|
+
default:
|
|
4089
|
+
console.error(`neat hooks: unknown flag "${arg}"`);
|
|
4090
|
+
usage();
|
|
4091
|
+
return 2;
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4094
|
+
try {
|
|
4095
|
+
const { exitCode } = await runHooks(opts);
|
|
4096
|
+
return exitCode;
|
|
4097
|
+
} catch (err) {
|
|
4098
|
+
console.error(err.message);
|
|
4099
|
+
return 1;
|
|
4100
|
+
}
|
|
4101
|
+
}
|
|
4102
|
+
|
|
4103
|
+
// src/cli-verbs.ts
|
|
4104
|
+
import path9 from "path";
|
|
3857
4105
|
|
|
3858
4106
|
// src/cli-client.ts
|
|
3859
4107
|
import { Provenance as Provenance2 } from "@neat.is/types";
|
|
@@ -3881,10 +4129,10 @@ function createHttpClient(baseUrl, bearerToken) {
|
|
|
3881
4129
|
const root = baseUrl.replace(/\/$/, "");
|
|
3882
4130
|
const authHeader = bearerToken && bearerToken.length > 0 ? { authorization: `Bearer ${bearerToken}` } : {};
|
|
3883
4131
|
return {
|
|
3884
|
-
async get(
|
|
4132
|
+
async get(path11) {
|
|
3885
4133
|
let res;
|
|
3886
4134
|
try {
|
|
3887
|
-
res = await fetch(`${root}${
|
|
4135
|
+
res = await fetch(`${root}${path11}`, {
|
|
3888
4136
|
headers: { ...authHeader }
|
|
3889
4137
|
});
|
|
3890
4138
|
} catch (err) {
|
|
@@ -3896,16 +4144,16 @@ function createHttpClient(baseUrl, bearerToken) {
|
|
|
3896
4144
|
const body = await res.text().catch(() => "");
|
|
3897
4145
|
throw new HttpError(
|
|
3898
4146
|
res.status,
|
|
3899
|
-
`${res.status} ${res.statusText} on GET ${
|
|
4147
|
+
`${res.status} ${res.statusText} on GET ${path11}: ${body}`,
|
|
3900
4148
|
body
|
|
3901
4149
|
);
|
|
3902
4150
|
}
|
|
3903
4151
|
return await res.json();
|
|
3904
4152
|
},
|
|
3905
|
-
async post(
|
|
4153
|
+
async post(path11, body) {
|
|
3906
4154
|
let res;
|
|
3907
4155
|
try {
|
|
3908
|
-
res = await fetch(`${root}${
|
|
4156
|
+
res = await fetch(`${root}${path11}`, {
|
|
3909
4157
|
method: "POST",
|
|
3910
4158
|
headers: { "content-type": "application/json", ...authHeader },
|
|
3911
4159
|
body: JSON.stringify(body)
|
|
@@ -3919,7 +4167,7 @@ function createHttpClient(baseUrl, bearerToken) {
|
|
|
3919
4167
|
const text = await res.text().catch(() => "");
|
|
3920
4168
|
throw new HttpError(
|
|
3921
4169
|
res.status,
|
|
3922
|
-
`${res.status} ${res.statusText} on POST ${
|
|
4170
|
+
`${res.status} ${res.statusText} on POST ${path11}: ${text}`,
|
|
3923
4171
|
text
|
|
3924
4172
|
);
|
|
3925
4173
|
}
|
|
@@ -3933,12 +4181,12 @@ function projectPath(project, suffix) {
|
|
|
3933
4181
|
}
|
|
3934
4182
|
async function runRootCause(client, input) {
|
|
3935
4183
|
const qs = input.errorId ? `?errorId=${encodeURIComponent(input.errorId)}` : "";
|
|
3936
|
-
const
|
|
4184
|
+
const path11 = projectPath(
|
|
3937
4185
|
input.project,
|
|
3938
4186
|
`/graph/root-cause/${encodeURIComponent(input.errorNode)}${qs}`
|
|
3939
4187
|
);
|
|
3940
4188
|
try {
|
|
3941
|
-
const result = await client.get(
|
|
4189
|
+
const result = await client.get(path11);
|
|
3942
4190
|
const arrowPath = result.traversalPath.join(" \u2190 ");
|
|
3943
4191
|
const provenances = result.edgeProvenances.length ? result.edgeProvenances.join(", ") : "(direct, no edges traversed)";
|
|
3944
4192
|
const summary = `Root cause for ${input.errorNode} is ${result.rootCauseNode}. ` + result.rootCauseReason + (result.fixRecommendation ? ` Recommended fix: ${result.fixRecommendation}.` : "");
|
|
@@ -3964,12 +4212,12 @@ async function runRootCause(client, input) {
|
|
|
3964
4212
|
}
|
|
3965
4213
|
async function runBlastRadius(client, input) {
|
|
3966
4214
|
const qs = input.depth !== void 0 ? `?depth=${input.depth}` : "";
|
|
3967
|
-
const
|
|
4215
|
+
const path11 = projectPath(
|
|
3968
4216
|
input.project,
|
|
3969
4217
|
`/graph/blast-radius/${encodeURIComponent(input.nodeId)}${qs}`
|
|
3970
4218
|
);
|
|
3971
4219
|
try {
|
|
3972
|
-
const result = await client.get(
|
|
4220
|
+
const result = await client.get(path11);
|
|
3973
4221
|
if (result.totalAffected === 0) {
|
|
3974
4222
|
return {
|
|
3975
4223
|
summary: `${result.origin} has no dependents. Nothing else would break if it failed.`
|
|
@@ -4003,12 +4251,12 @@ function formatBlastEntry(n) {
|
|
|
4003
4251
|
}
|
|
4004
4252
|
async function runDependencies(client, input) {
|
|
4005
4253
|
const depth = input.depth ?? 3;
|
|
4006
|
-
const
|
|
4254
|
+
const path11 = projectPath(
|
|
4007
4255
|
input.project,
|
|
4008
4256
|
`/graph/dependencies/${encodeURIComponent(input.nodeId)}?depth=${depth}`
|
|
4009
4257
|
);
|
|
4010
4258
|
try {
|
|
4011
|
-
const result = await client.get(
|
|
4259
|
+
const result = await client.get(path11);
|
|
4012
4260
|
if (result.total === 0) {
|
|
4013
4261
|
return {
|
|
4014
4262
|
summary: depth === 1 ? `${input.nodeId} has no direct dependencies in the graph.` : `${input.nodeId} has no dependencies (BFS to depth ${depth}).`
|
|
@@ -4100,9 +4348,9 @@ function formatDuration(ms) {
|
|
|
4100
4348
|
return `${Math.round(h / 24)}d`;
|
|
4101
4349
|
}
|
|
4102
4350
|
async function runIncidents(client, input) {
|
|
4103
|
-
const
|
|
4351
|
+
const path11 = input.nodeId ? projectPath(input.project, `/incidents/${encodeURIComponent(input.nodeId)}`) : projectPath(input.project, "/incidents");
|
|
4104
4352
|
try {
|
|
4105
|
-
const body = await client.get(
|
|
4353
|
+
const body = await client.get(path11);
|
|
4106
4354
|
const events = body.events;
|
|
4107
4355
|
if (events.length === 0) {
|
|
4108
4356
|
return {
|
|
@@ -4392,7 +4640,7 @@ async function resolveProjectEntry(opts) {
|
|
|
4392
4640
|
const cwd = opts.cwd ?? process.cwd();
|
|
4393
4641
|
const resolvedCwd = await normalizeProjectPath(cwd);
|
|
4394
4642
|
for (const entry2 of entries) {
|
|
4395
|
-
if (resolvedCwd === entry2.path || resolvedCwd.startsWith(`${entry2.path}${
|
|
4643
|
+
if (resolvedCwd === entry2.path || resolvedCwd.startsWith(`${entry2.path}${path9.sep}`)) {
|
|
4396
4644
|
return entry2;
|
|
4397
4645
|
}
|
|
4398
4646
|
}
|
|
@@ -4557,7 +4805,7 @@ function isNpxInvocation() {
|
|
|
4557
4805
|
function commandPrefix() {
|
|
4558
4806
|
return isNpxInvocation() ? "npx neat.is" : "neat";
|
|
4559
4807
|
}
|
|
4560
|
-
function
|
|
4808
|
+
function usage2() {
|
|
4561
4809
|
const neat = commandPrefix();
|
|
4562
4810
|
console.log("Installed via npx? Prefix commands with `npx neat.is`, or install once: `npm i -g neat.is`.");
|
|
4563
4811
|
console.log("");
|
|
@@ -4594,6 +4842,14 @@ function usage() {
|
|
|
4594
4842
|
console.log(" Flags:");
|
|
4595
4843
|
console.log(" --print-config print the JSON snippet to stdout");
|
|
4596
4844
|
console.log(" --apply merge mcpServers.neat into ~/.claude.json");
|
|
4845
|
+
console.log(" hooks Wire NEAT into your agent so it queries the graph before");
|
|
4846
|
+
console.log(" grepping. Installs a gentle Claude Code search-nudge hook and");
|
|
4847
|
+
console.log(" writes agent-agnostic graph-first guidance for other harnesses.");
|
|
4848
|
+
console.log(" Flags:");
|
|
4849
|
+
console.log(" --apply install the hook + guidance");
|
|
4850
|
+
console.log(" --print-hook print the hook script");
|
|
4851
|
+
console.log(" --print-guide print the graph-first guidance");
|
|
4852
|
+
console.log(" --print-settings print the settings.json block --apply adds");
|
|
4597
4853
|
console.log(" deploy Detect the deploy substrate, generate NEAT_AUTH_TOKEN,");
|
|
4598
4854
|
console.log(" emit a docker-compose / systemd / docker run artifact, and");
|
|
4599
4855
|
console.log(" print the OTel env-vars block to paste into your platform.");
|
|
@@ -4606,8 +4862,9 @@ function usage() {
|
|
|
4606
4862
|
console.log(" --dry-run run extraction in-memory; do not write");
|
|
4607
4863
|
console.log(" --no-instrument skip the SDK install apply step");
|
|
4608
4864
|
console.log(" --json emit the delta summary as JSON");
|
|
4609
|
-
console.log(" connector Configure
|
|
4610
|
-
console.log(" firebase, cloudflare).
|
|
4865
|
+
console.log(" connector Configure OBSERVED connectors \u2014 pull (supabase, railway,");
|
|
4866
|
+
console.log(" firebase, cloudflare) and push (vercel, via a trace Drain).");
|
|
4867
|
+
console.log(" Subcommands:");
|
|
4611
4868
|
console.log(" add <provider> add a connector; validates the credential");
|
|
4612
4869
|
console.log(" against the provider first (--skip-validate to skip)");
|
|
4613
4870
|
console.log(" flags: --project <name>, --credential/--token <$VAR|value>,");
|
|
@@ -4838,7 +5095,7 @@ async function buildPatchSections(services, project) {
|
|
|
4838
5095
|
}
|
|
4839
5096
|
async function runInit(opts) {
|
|
4840
5097
|
const written = [];
|
|
4841
|
-
const stat = await
|
|
5098
|
+
const stat = await fs8.stat(opts.scanPath).catch(() => null);
|
|
4842
5099
|
if (!stat || !stat.isDirectory()) {
|
|
4843
5100
|
console.error(`neat init: ${opts.scanPath} is not a directory`);
|
|
4844
5101
|
return { exitCode: 2, writtenFiles: written };
|
|
@@ -4847,13 +5104,13 @@ async function runInit(opts) {
|
|
|
4847
5104
|
printDiscoveryReport(opts, services);
|
|
4848
5105
|
const sections = opts.noInstall ? [] : await buildPatchSections(services, opts.project);
|
|
4849
5106
|
const patch = renderPatch(sections);
|
|
4850
|
-
const patchPath =
|
|
5107
|
+
const patchPath = path10.join(opts.scanPath, "neat.patch");
|
|
4851
5108
|
if (opts.dryRun) {
|
|
4852
|
-
await
|
|
5109
|
+
await fs8.writeFile(patchPath, patch, "utf8");
|
|
4853
5110
|
written.push(patchPath);
|
|
4854
5111
|
console.log(`dry-run: patch written to ${patchPath}`);
|
|
4855
|
-
const gitignorePath =
|
|
4856
|
-
const gitignoreExists = await
|
|
5112
|
+
const gitignorePath = path10.join(opts.scanPath, ".gitignore");
|
|
5113
|
+
const gitignoreExists = await fs8.stat(gitignorePath).then(() => true).catch(() => false);
|
|
4857
5114
|
const verb = gitignoreExists ? "append" : "create";
|
|
4858
5115
|
console.log(`dry-run: would ${verb} ${gitignorePath} (add neat-out/)`);
|
|
4859
5116
|
console.log("rerun without --dry-run to register and snapshot.");
|
|
@@ -4864,9 +5121,9 @@ async function runInit(opts) {
|
|
|
4864
5121
|
const graph = getGraph(graphKey);
|
|
4865
5122
|
const projectPaths = pathsForProject(
|
|
4866
5123
|
graphKey,
|
|
4867
|
-
|
|
5124
|
+
path10.join(opts.scanPath, "neat-out")
|
|
4868
5125
|
);
|
|
4869
|
-
const errorsPath =
|
|
5126
|
+
const errorsPath = path10.join(path10.dirname(opts.outPath), path10.basename(projectPaths.errorsPath));
|
|
4870
5127
|
const result = await extractFromDirectory(graph, opts.scanPath, { errorsPath });
|
|
4871
5128
|
await saveGraphToDisk(graph, opts.outPath);
|
|
4872
5129
|
written.push(opts.outPath);
|
|
@@ -4945,7 +5202,7 @@ async function runInit(opts) {
|
|
|
4945
5202
|
console.log("Run `npm install` (or your language equivalent) to refresh lockfiles.");
|
|
4946
5203
|
}
|
|
4947
5204
|
} else {
|
|
4948
|
-
await
|
|
5205
|
+
await fs8.writeFile(patchPath, patch, "utf8");
|
|
4949
5206
|
written.push(patchPath);
|
|
4950
5207
|
}
|
|
4951
5208
|
}
|
|
@@ -4985,9 +5242,9 @@ var CLAUDE_SKILL_CONFIG = {
|
|
|
4985
5242
|
};
|
|
4986
5243
|
function claudeConfigPath() {
|
|
4987
5244
|
const override = process.env.NEAT_CLAUDE_CONFIG;
|
|
4988
|
-
if (override && override.length > 0) return
|
|
5245
|
+
if (override && override.length > 0) return path10.resolve(override);
|
|
4989
5246
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
4990
|
-
return
|
|
5247
|
+
return path10.join(home, ".claude.json");
|
|
4991
5248
|
}
|
|
4992
5249
|
async function runSkill(opts) {
|
|
4993
5250
|
const snippet = JSON.stringify(CLAUDE_SKILL_CONFIG, null, 2) + "\n";
|
|
@@ -4999,7 +5256,7 @@ async function runSkill(opts) {
|
|
|
4999
5256
|
const target = claudeConfigPath();
|
|
5000
5257
|
let existing = {};
|
|
5001
5258
|
try {
|
|
5002
|
-
existing = JSON.parse(await
|
|
5259
|
+
existing = JSON.parse(await fs8.readFile(target, "utf8"));
|
|
5003
5260
|
} catch (err) {
|
|
5004
5261
|
if (err.code !== "ENOENT") {
|
|
5005
5262
|
console.error(`neat skill: failed to read ${target} \u2014 ${err.message}`);
|
|
@@ -5011,10 +5268,13 @@ async function runSkill(opts) {
|
|
|
5011
5268
|
...existing,
|
|
5012
5269
|
mcpServers: { ...mcp, neat: CLAUDE_SKILL_CONFIG.mcpServers.neat }
|
|
5013
5270
|
};
|
|
5014
|
-
await
|
|
5015
|
-
await
|
|
5271
|
+
await fs8.mkdir(path10.dirname(target), { recursive: true });
|
|
5272
|
+
await fs8.writeFile(target, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
5016
5273
|
console.log(`neat skill: wrote mcpServers.neat to ${target}`);
|
|
5017
5274
|
console.log("restart Claude Code to pick up the new MCP server.");
|
|
5275
|
+
console.log("");
|
|
5276
|
+
console.log("Tip: run `neat hooks --apply` to also install the search-nudge hook, so");
|
|
5277
|
+
console.log("your agent reaches for the graph before it grep-scans the repo.");
|
|
5018
5278
|
return { exitCode: 0 };
|
|
5019
5279
|
}
|
|
5020
5280
|
console.log("neat skill \u2014 Claude Code MCP drop-in for NEAT");
|
|
@@ -5027,13 +5287,16 @@ async function runSkill(opts) {
|
|
|
5027
5287
|
console.log("");
|
|
5028
5288
|
console.log("The MCP server reads NEAT_CORE_URL for the daemon URL \u2014 point it at a");
|
|
5029
5289
|
console.log("non-default daemon by editing that value in the generated config.");
|
|
5290
|
+
console.log("");
|
|
5291
|
+
console.log("See also `neat hooks --apply` \u2014 the search-nudge hook + graph-first guidance");
|
|
5292
|
+
console.log("that steer an agent to query the graph before falling back to text search.");
|
|
5030
5293
|
return { exitCode: 0 };
|
|
5031
5294
|
}
|
|
5032
5295
|
async function main() {
|
|
5033
5296
|
const argv = process.argv.slice(2);
|
|
5034
5297
|
const cmd0 = argv[0];
|
|
5035
5298
|
if (cmd0 === "-h" || cmd0 === "--help") {
|
|
5036
|
-
|
|
5299
|
+
usage2();
|
|
5037
5300
|
process.exit(0);
|
|
5038
5301
|
}
|
|
5039
5302
|
if (cmd0 === "--version" || cmd0 === "-v" || cmd0 === "version") {
|
|
@@ -5045,6 +5308,11 @@ async function main() {
|
|
|
5045
5308
|
if (code !== 0) process.exit(code);
|
|
5046
5309
|
return;
|
|
5047
5310
|
}
|
|
5311
|
+
if (cmd0 === "hooks") {
|
|
5312
|
+
const code = await runHooksCommand(argv.slice(1));
|
|
5313
|
+
if (code !== 0) process.exit(code);
|
|
5314
|
+
return;
|
|
5315
|
+
}
|
|
5048
5316
|
const argvParsed = parseArgs(argv);
|
|
5049
5317
|
if (argvParsed.positional.length === 0) {
|
|
5050
5318
|
const orchestratorCode2 = await tryOrchestrator(process.cwd(), argvParsed);
|
|
@@ -5059,19 +5327,19 @@ async function main() {
|
|
|
5059
5327
|
const target = positional[0];
|
|
5060
5328
|
if (!target) {
|
|
5061
5329
|
console.error("neat init: missing <path>");
|
|
5062
|
-
|
|
5330
|
+
usage2();
|
|
5063
5331
|
process.exit(2);
|
|
5064
5332
|
}
|
|
5065
5333
|
if (apply3 && dryRun) {
|
|
5066
5334
|
console.error("neat init: --apply and --dry-run are mutually exclusive");
|
|
5067
5335
|
process.exit(2);
|
|
5068
5336
|
}
|
|
5069
|
-
const scanPath =
|
|
5337
|
+
const scanPath = path10.resolve(target);
|
|
5070
5338
|
const projectExplicit = parsed.project !== null;
|
|
5071
|
-
const projectName = projectExplicit ? project :
|
|
5339
|
+
const projectName = projectExplicit ? project : path10.basename(scanPath);
|
|
5072
5340
|
const projectKey = projectExplicit ? project : DEFAULT_PROJECT;
|
|
5073
|
-
const fallback = pathsForProject(projectKey,
|
|
5074
|
-
const outPath =
|
|
5341
|
+
const fallback = pathsForProject(projectKey, path10.join(scanPath, "neat-out")).snapshotPath;
|
|
5342
|
+
const outPath = path10.resolve(process.env.NEAT_OUT_PATH ?? fallback);
|
|
5075
5343
|
const result = await runInit({
|
|
5076
5344
|
scanPath,
|
|
5077
5345
|
outPath,
|
|
@@ -5089,24 +5357,24 @@ async function main() {
|
|
|
5089
5357
|
const target = positional[0];
|
|
5090
5358
|
if (!target) {
|
|
5091
5359
|
console.error("neat watch: missing <path>");
|
|
5092
|
-
|
|
5360
|
+
usage2();
|
|
5093
5361
|
process.exit(2);
|
|
5094
5362
|
}
|
|
5095
|
-
const scanPath =
|
|
5096
|
-
const stat = await
|
|
5363
|
+
const scanPath = path10.resolve(target);
|
|
5364
|
+
const stat = await fs8.stat(scanPath).catch(() => null);
|
|
5097
5365
|
if (!stat || !stat.isDirectory()) {
|
|
5098
5366
|
console.error(`neat watch: ${scanPath} is not a directory`);
|
|
5099
5367
|
process.exit(2);
|
|
5100
5368
|
}
|
|
5101
|
-
const projectPaths = pathsForProject(project,
|
|
5102
|
-
const outPath =
|
|
5103
|
-
const errorsPath =
|
|
5104
|
-
process.env.NEAT_ERRORS_PATH ??
|
|
5369
|
+
const projectPaths = pathsForProject(project, path10.join(scanPath, "neat-out"));
|
|
5370
|
+
const outPath = path10.resolve(process.env.NEAT_OUT_PATH ?? projectPaths.snapshotPath);
|
|
5371
|
+
const errorsPath = path10.resolve(
|
|
5372
|
+
process.env.NEAT_ERRORS_PATH ?? path10.join(path10.dirname(outPath), path10.basename(projectPaths.errorsPath))
|
|
5105
5373
|
);
|
|
5106
|
-
const staleEventsPath =
|
|
5107
|
-
process.env.NEAT_STALE_EVENTS_PATH ??
|
|
5374
|
+
const staleEventsPath = path10.resolve(
|
|
5375
|
+
process.env.NEAT_STALE_EVENTS_PATH ?? path10.join(path10.dirname(outPath), path10.basename(projectPaths.staleEventsPath))
|
|
5108
5376
|
);
|
|
5109
|
-
const embeddingsCachePath = process.env.NEAT_EMBEDDINGS_CACHE_PATH ?
|
|
5377
|
+
const embeddingsCachePath = process.env.NEAT_EMBEDDINGS_CACHE_PATH ? path10.resolve(process.env.NEAT_EMBEDDINGS_CACHE_PATH) : void 0;
|
|
5110
5378
|
const handle = await startWatch(getGraph(project), {
|
|
5111
5379
|
scanPath,
|
|
5112
5380
|
outPath,
|
|
@@ -5148,7 +5416,7 @@ async function main() {
|
|
|
5148
5416
|
const name = positional[0];
|
|
5149
5417
|
if (!name) {
|
|
5150
5418
|
console.error("neat pause: missing <name>");
|
|
5151
|
-
|
|
5419
|
+
usage2();
|
|
5152
5420
|
process.exit(2);
|
|
5153
5421
|
}
|
|
5154
5422
|
const daemon = await findDaemonByProject(name);
|
|
@@ -5173,7 +5441,7 @@ async function main() {
|
|
|
5173
5441
|
const name = positional[0];
|
|
5174
5442
|
if (!name) {
|
|
5175
5443
|
console.error("neat resume: missing <name>");
|
|
5176
|
-
|
|
5444
|
+
usage2();
|
|
5177
5445
|
process.exit(2);
|
|
5178
5446
|
}
|
|
5179
5447
|
const daemon = await findDaemonByProject(name);
|
|
@@ -5203,7 +5471,7 @@ async function main() {
|
|
|
5203
5471
|
const name = positional[0];
|
|
5204
5472
|
if (!name) {
|
|
5205
5473
|
console.error("neat uninstall: missing <name>");
|
|
5206
|
-
|
|
5474
|
+
usage2();
|
|
5207
5475
|
process.exit(2);
|
|
5208
5476
|
}
|
|
5209
5477
|
const daemon = await findDaemonByProject(name);
|
|
@@ -5285,15 +5553,15 @@ async function main() {
|
|
|
5285
5553
|
return;
|
|
5286
5554
|
}
|
|
5287
5555
|
console.error(`neat: unknown command "${cmd}"`);
|
|
5288
|
-
|
|
5556
|
+
usage2();
|
|
5289
5557
|
process.exit(1);
|
|
5290
5558
|
}
|
|
5291
5559
|
async function tryOrchestrator(cmd, parsed) {
|
|
5292
|
-
const scanPath =
|
|
5293
|
-
const stat = await
|
|
5560
|
+
const scanPath = path10.resolve(cmd);
|
|
5561
|
+
const stat = await fs8.stat(scanPath).catch(() => null);
|
|
5294
5562
|
if (!stat || !stat.isDirectory()) return null;
|
|
5295
5563
|
const projectExplicit = parsed.project !== null;
|
|
5296
|
-
const projectName = projectExplicit ? parsed.project :
|
|
5564
|
+
const projectName = projectExplicit ? parsed.project : path10.basename(scanPath);
|
|
5297
5565
|
const result = await runOrchestrator({
|
|
5298
5566
|
scanPath,
|
|
5299
5567
|
project: projectName,
|
|
@@ -5549,6 +5817,6 @@ export {
|
|
|
5549
5817
|
runInit,
|
|
5550
5818
|
runQueryVerb,
|
|
5551
5819
|
runSkill,
|
|
5552
|
-
usage
|
|
5820
|
+
usage2 as usage
|
|
5553
5821
|
};
|
|
5554
5822
|
//# sourceMappingURL=cli.js.map
|