@harness-nexus/cli 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon/acp/adapters.d.ts +7 -0
- package/dist/daemon/acp/adapters.d.ts.map +1 -0
- package/dist/daemon/acp/adapters.js +34 -0
- package/dist/daemon/acp/adapters.js.map +1 -0
- package/dist/daemon/acp/agent-connection.d.ts +45 -0
- package/dist/daemon/acp/agent-connection.d.ts.map +1 -0
- package/dist/daemon/acp/agent-connection.js +158 -0
- package/dist/daemon/acp/agent-connection.js.map +1 -0
- package/dist/daemon/chat.d.ts +22 -0
- package/dist/daemon/chat.d.ts.map +1 -0
- package/dist/daemon/chat.js +280 -0
- package/dist/daemon/chat.js.map +1 -0
- package/dist/daemon/client.d.ts +23 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +117 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/jobs.d.ts +19 -0
- package/dist/daemon/jobs.d.ts.map +1 -0
- package/dist/daemon/jobs.js +65 -0
- package/dist/daemon/jobs.js.map +1 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +481 -0
- package/dist/index.js.map +1 -0
- package/dist/install/adapter-factory.d.ts +24 -0
- package/dist/install/adapter-factory.d.ts.map +1 -0
- package/dist/install/adapter-factory.js +80 -0
- package/dist/install/adapter-factory.js.map +1 -0
- package/dist/install/adapters/codex.d.ts +16 -0
- package/dist/install/adapters/codex.d.ts.map +1 -0
- package/dist/install/adapters/codex.js +172 -0
- package/dist/install/adapters/codex.js.map +1 -0
- package/dist/install/adapters/deepseek.d.ts +26 -0
- package/dist/install/adapters/deepseek.d.ts.map +1 -0
- package/dist/install/adapters/deepseek.js +246 -0
- package/dist/install/adapters/deepseek.js.map +1 -0
- package/dist/install/adapters/hermes.d.ts +16 -0
- package/dist/install/adapters/hermes.d.ts.map +1 -0
- package/dist/install/adapters/hermes.js +267 -0
- package/dist/install/adapters/hermes.js.map +1 -0
- package/dist/install/adapters/stub.d.ts +2 -0
- package/dist/install/adapters/stub.d.ts.map +1 -0
- package/dist/install/adapters/stub.js +22 -0
- package/dist/install/adapters/stub.js.map +1 -0
- package/dist/install/install-state.d.ts +31 -0
- package/dist/install/install-state.d.ts.map +1 -0
- package/dist/install/install-state.js +29 -0
- package/dist/install/install-state.js.map +1 -0
- package/dist/install/installer.d.ts +16 -0
- package/dist/install/installer.d.ts.map +1 -0
- package/dist/install/installer.js +96 -0
- package/dist/install/installer.js.map +1 -0
- package/dist/install/planner.d.ts +26 -0
- package/dist/install/planner.d.ts.map +1 -0
- package/dist/install/planner.js +25 -0
- package/dist/install/planner.js.map +1 -0
- package/dist/install/registry.d.ts +21 -0
- package/dist/install/registry.d.ts.map +1 -0
- package/dist/install/registry.js +31 -0
- package/dist/install/registry.js.map +1 -0
- package/dist/install/resolver.d.ts +15 -0
- package/dist/install/resolver.d.ts.map +1 -0
- package/dist/install/resolver.js +57 -0
- package/dist/install/resolver.js.map +1 -0
- package/dist/install/types.d.ts +93 -0
- package/dist/install/types.d.ts.map +1 -0
- package/dist/install/types.js +2 -0
- package/dist/install/types.js.map +1 -0
- package/dist/install/uninstaller.d.ts +29 -0
- package/dist/install/uninstaller.d.ts.map +1 -0
- package/dist/install/uninstaller.js +107 -0
- package/dist/install/uninstaller.js.map +1 -0
- package/dist/inventory/common.d.ts +86 -0
- package/dist/inventory/common.d.ts.map +1 -0
- package/dist/inventory/common.js +137 -0
- package/dist/inventory/common.js.map +1 -0
- package/dist/inventory/scan.d.ts +23 -0
- package/dist/inventory/scan.d.ts.map +1 -0
- package/dist/inventory/scan.js +117 -0
- package/dist/inventory/scan.js.map +1 -0
- package/dist/inventory/scanners/claude-code.d.ts +3 -0
- package/dist/inventory/scanners/claude-code.d.ts.map +1 -0
- package/dist/inventory/scanners/claude-code.js +191 -0
- package/dist/inventory/scanners/claude-code.js.map +1 -0
- package/dist/inventory/scanners/codex.d.ts +14 -0
- package/dist/inventory/scanners/codex.d.ts.map +1 -0
- package/dist/inventory/scanners/codex.js +201 -0
- package/dist/inventory/scanners/codex.js.map +1 -0
- package/dist/inventory/scanners/deepseek.d.ts +9 -0
- package/dist/inventory/scanners/deepseek.d.ts.map +1 -0
- package/dist/inventory/scanners/deepseek.js +200 -0
- package/dist/inventory/scanners/deepseek.js.map +1 -0
- package/dist/inventory/scanners/hermes.d.ts +3 -0
- package/dist/inventory/scanners/hermes.d.ts.map +1 -0
- package/dist/inventory/scanners/hermes.js +194 -0
- package/dist/inventory/scanners/hermes.js.map +1 -0
- package/dist/inventory/types.d.ts +33 -0
- package/dist/inventory/types.d.ts.map +1 -0
- package/dist/inventory/types.js +2 -0
- package/dist/inventory/types.js.map +1 -0
- package/dist/mcp/serve.d.ts +8 -0
- package/dist/mcp/serve.d.ts.map +1 -0
- package/dist/mcp/serve.js +118 -0
- package/dist/mcp/serve.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ResolvedProfile } from './types.js';
|
|
2
|
+
export interface ResolveOptions {
|
|
3
|
+
/** Base URL of the Harness Nexus server. */
|
|
4
|
+
server: string;
|
|
5
|
+
/** PAT (or JWT) authenticating against the server. */
|
|
6
|
+
token: string;
|
|
7
|
+
/** The profile id to resolve. */
|
|
8
|
+
profileId: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Fetch the profile + every entry's artifact. Throws `RESOLVE_FAILED` if the
|
|
12
|
+
* profile or any referenced resource is missing or the request errors.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveProfile(opts: ResolveOptions): Promise<ResolvedProfile>;
|
|
15
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/install/resolver.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAoB,eAAe,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAwCnF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProfileResolver — fetches a profile and resolves every entry's `resourceId`
|
|
3
|
+
* into its concrete artifact via the SDK against a running Harness Nexus server.
|
|
4
|
+
*
|
|
5
|
+
* A profile is a reference bundle: `entries[].resourceId` points at a server-side
|
|
6
|
+
* `McpServer` (for `kind: 'mcp'`) or `Resource` (other kinds). The resolver
|
|
7
|
+
* dereferences them so adapters can emit target-native files. This is the only
|
|
8
|
+
* outbound path in the CLI; there is no local-manifest fallback (a profile's
|
|
9
|
+
* resource bodies and the aggregated `/mcp` endpoint both require the server).
|
|
10
|
+
*
|
|
11
|
+
* See `docs/design/phase-3-install.md` Part 4.
|
|
12
|
+
*/
|
|
13
|
+
import { HarnessNexusClient, HarnessNexusError } from '@harness-nexus/sdk';
|
|
14
|
+
import { InstallError } from '../errors.js';
|
|
15
|
+
/**
|
|
16
|
+
* Fetch the profile + every entry's artifact. Throws `RESOLVE_FAILED` if the
|
|
17
|
+
* profile or any referenced resource is missing or the request errors.
|
|
18
|
+
*/
|
|
19
|
+
export async function resolveProfile(opts) {
|
|
20
|
+
const client = new HarnessNexusClient({ baseUrl: opts.server, token: opts.token });
|
|
21
|
+
let profile;
|
|
22
|
+
try {
|
|
23
|
+
({ profile } = await client.getProfile(opts.profileId));
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
throw new InstallError(`Failed to fetch profile '${opts.profileId}': ${describeError(e)}`, 'RESOLVE_FAILED', e);
|
|
27
|
+
}
|
|
28
|
+
const artifacts = [];
|
|
29
|
+
for (const [index, entry] of profile.entries.entries()) {
|
|
30
|
+
try {
|
|
31
|
+
if (entry.kind === 'mcp') {
|
|
32
|
+
// MCP entries reference a McpServer.id. Fetch the full server list once
|
|
33
|
+
// and find by id (there is no single-get MCP endpoint in the SDK today).
|
|
34
|
+
const servers = await client.listMcpServers();
|
|
35
|
+
const server = servers.find((s) => s.id === entry.resourceId);
|
|
36
|
+
if (!server) {
|
|
37
|
+
throw new Error(`MCP server '${entry.resourceId}' not found`);
|
|
38
|
+
}
|
|
39
|
+
artifacts.push({ entryId: entry.resourceId, kind: 'mcp', mcpServer: server });
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const { resource } = await client.getResource(entry.resourceId);
|
|
43
|
+
artifacts.push({ entryId: entry.resourceId, kind: entry.kind, resource });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
throw new InstallError(`Failed to resolve profile entry #${index} (kind=${entry.kind}, id=${entry.resourceId}): ${describeError(e)}`, 'RESOLVE_FAILED', e);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { profile, artifacts };
|
|
51
|
+
}
|
|
52
|
+
function describeError(e) {
|
|
53
|
+
if (e instanceof HarnessNexusError)
|
|
54
|
+
return `${e.code}: ${e.message}`;
|
|
55
|
+
return e instanceof Error ? e.message : String(e);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/install/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAY5C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAoB;IACvD,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAEnF,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,CAAC,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,YAAY,CACpB,4BAA4B,IAAI,CAAC,SAAS,MAAM,aAAa,CAAC,CAAC,CAAC,EAAE,EAClE,gBAAgB,EAChB,CAAC,CACF,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAuB,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACzB,wEAAwE;gBACxE,yEAAyE;gBACzE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,UAAU,CAAC,CAAC;gBACzE,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,CAAC,UAAU,aAAa,CAAC,CAAC;gBAChE,CAAC;gBACD,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAChE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,YAAY,CACpB,oCAAoC,KAAK,UAAU,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC,UAAU,MAAM,aAAa,CAAC,CAAC,CAAC,EAAE,EAC7G,gBAAgB,EAChB,CAAC,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAC/B,IAAI,CAAC,YAAY,iBAAiB;QAAE,OAAO,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;IACrE,OAAO,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core install-pipeline types. Mirrors the ECC adapter pattern (see
|
|
3
|
+
* `docs/research/phase-3-ecc-install-patterns.md`): a `TargetAdapter` turns a
|
|
4
|
+
* resolved profile into an `InstallPlan` (a list of file operations, NO writes);
|
|
5
|
+
* the installer materializes the plan.
|
|
6
|
+
*
|
|
7
|
+
* Phase 3.3 ships these types + a stub adapter + the plan/apply machinery. Real
|
|
8
|
+
* target adapters (Hermes/CC/Codex) arrive in 3.4–3.6.
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentTarget, Profile, McpServer, Resource } from '@harness-nexus/core';
|
|
11
|
+
/** Where an adapter installs: a user home dir (`~/.xxx`) or a project root. */
|
|
12
|
+
export type AdapterKind = 'home' | 'project';
|
|
13
|
+
/** A single filesystem operation the installer can materialize. */
|
|
14
|
+
export type Operation = {
|
|
15
|
+
kind: 'copy-file';
|
|
16
|
+
/** Absolute source path (a resolved profile artifact on disk). */
|
|
17
|
+
sourcePath: string;
|
|
18
|
+
/** Absolute destination path in the target tool's layout. */
|
|
19
|
+
destinationPath: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'write-file';
|
|
22
|
+
/** Inline content to write (generated by the adapter). */
|
|
23
|
+
content: string;
|
|
24
|
+
destinationPath: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'merge-json';
|
|
27
|
+
/** The JSON value to deep-merge into the destination file. */
|
|
28
|
+
mergePayload: unknown;
|
|
29
|
+
destinationPath: string;
|
|
30
|
+
};
|
|
31
|
+
/** The output of planning — a serializable, dry-runnable description of an install. */
|
|
32
|
+
export interface InstallPlan {
|
|
33
|
+
adapter: {
|
|
34
|
+
id: string;
|
|
35
|
+
target: AgentTarget;
|
|
36
|
+
kind: AdapterKind;
|
|
37
|
+
};
|
|
38
|
+
/** Root dir the adapter writes into (e.g. ~/.hermes, ~/.codex). */
|
|
39
|
+
targetRoot: string;
|
|
40
|
+
/** Where the install-state ledger is written. */
|
|
41
|
+
installStatePath: string;
|
|
42
|
+
operations: Operation[];
|
|
43
|
+
/** True if any operation carries a decrypted direct-mode credential. */
|
|
44
|
+
sensitive: boolean;
|
|
45
|
+
}
|
|
46
|
+
/** Input passed to an adapter's resolve/plan/validate methods. */
|
|
47
|
+
export interface ResolveInput {
|
|
48
|
+
/** Override the adapter's default home/project root. */
|
|
49
|
+
outDir?: string;
|
|
50
|
+
/** The OS home dir (defaults to os.homedir()). */
|
|
51
|
+
homeDir?: string;
|
|
52
|
+
}
|
|
53
|
+
/** A non-fatal adapter validation finding. severity 'error' blocks planning. */
|
|
54
|
+
export interface ValidationIssue {
|
|
55
|
+
severity: 'error' | 'warning';
|
|
56
|
+
code: string;
|
|
57
|
+
message: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A profile entry resolved to its concrete artifact. MCP entries resolve to a
|
|
61
|
+
* McpServer row; other kinds resolve to a Resource. Used by adapters to emit
|
|
62
|
+
* target-native files.
|
|
63
|
+
*/
|
|
64
|
+
export type ResolvedArtifact = {
|
|
65
|
+
entryId: string;
|
|
66
|
+
kind: 'mcp';
|
|
67
|
+
mcpServer: McpServer;
|
|
68
|
+
} | {
|
|
69
|
+
entryId: string;
|
|
70
|
+
kind: Exclude<Profile['entries'][number]['kind'], 'mcp'>;
|
|
71
|
+
resource: Resource;
|
|
72
|
+
};
|
|
73
|
+
/** A profile plus every entry's artifact, fetched from the server. */
|
|
74
|
+
export interface ResolvedProfile {
|
|
75
|
+
profile: Profile;
|
|
76
|
+
artifacts: ResolvedArtifact[];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A target adapter — one per Agent tool. Produced by `createTargetAdapter`.
|
|
80
|
+
* The contract: turn a resolved profile into an install plan, no writes.
|
|
81
|
+
*/
|
|
82
|
+
export interface TargetAdapter {
|
|
83
|
+
readonly id: string;
|
|
84
|
+
readonly target: AgentTarget;
|
|
85
|
+
readonly kind: AdapterKind;
|
|
86
|
+
/** Resolve the root dir files land under (honors `outDir` override). */
|
|
87
|
+
resolveRoot(input: ResolveInput): string;
|
|
88
|
+
/** Plan file operations for a resolved profile. Does NOT write. */
|
|
89
|
+
planOperations(resolved: ResolvedProfile, input: ResolveInput): InstallPlan;
|
|
90
|
+
/** Gate before planning; 'error' severity blocks. */
|
|
91
|
+
validate(input: ResolveInput): ValidationIssue[];
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/install/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAErF,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7C,mEAAmE;AACnE,MAAM,MAAM,SAAS,GACjB;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,eAAe,EAAE,MAAM,CAAC;CACzB,GACD;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB,GACD;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,8DAA8D;IAC9D,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEN,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;IAChE,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GACtD;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;IACzD,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEN,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,wEAAwE;IACxE,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAAC;IACzC,mEAAmE;IACnE,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,GAAG,WAAW,CAAC;IAC5E,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,eAAe,EAAE,CAAC;CAClD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/install/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type InstallState } from './install-state.js';
|
|
2
|
+
import type { AgentTarget } from '@harness-nexus/core';
|
|
3
|
+
import type { ResolveInput } from './types.js';
|
|
4
|
+
/** What uninstall will do to one destination path. */
|
|
5
|
+
export interface UninstallStep {
|
|
6
|
+
destinationPath: string;
|
|
7
|
+
action: 'restore' | 'delete';
|
|
8
|
+
/** Pre-install content to restore (null → the file is ours to delete). */
|
|
9
|
+
previousContent: string | null;
|
|
10
|
+
/** True when the current file was modified after our install (→ .hnx.bak). */
|
|
11
|
+
conflicts: boolean;
|
|
12
|
+
/** False when the file is already gone — nothing to do at apply time. */
|
|
13
|
+
exists: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface UninstallPlan {
|
|
16
|
+
targetRoot: string;
|
|
17
|
+
installStatePath: string;
|
|
18
|
+
profile: InstallState['profile'];
|
|
19
|
+
installedAt: string;
|
|
20
|
+
steps: UninstallStep[];
|
|
21
|
+
}
|
|
22
|
+
/** Read the ledger for a target root and compute the reverse steps. */
|
|
23
|
+
export declare function planUninstall(opts: {
|
|
24
|
+
target: AgentTarget;
|
|
25
|
+
input?: ResolveInput;
|
|
26
|
+
}): UninstallPlan | null;
|
|
27
|
+
/** Execute an uninstall plan (see module doc for semantics). */
|
|
28
|
+
export declare function applyUninstall(plan: UninstallPlan): number;
|
|
29
|
+
//# sourceMappingURL=uninstaller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstaller.d.ts","sourceRoot":"","sources":["../../src/install/uninstaller.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAoB,KAAK,YAAY,EAAwB,MAAM,oBAAoB,CAAC;AAE/F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,0EAA0E;IAC1E,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,8EAA8E;IAC9E,SAAS,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AASD,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB,GAAG,aAAa,GAAG,IAAI,CA2BvB;AAED,gEAAgE;AAChE,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CA4B1D"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uninstaller — reverses an `hnx install --apply` using the install-state
|
|
3
|
+
* ledger (Phase 3.5 loose ends; the ledger's "enabling uninstall" promise from
|
|
4
|
+
* 3.3 finally cashed in).
|
|
5
|
+
*
|
|
6
|
+
* Semantics:
|
|
7
|
+
* - For every ledger operation, in REVERSE order (later writes depended on
|
|
8
|
+
* earlier ones, so undoing last-first restores the original state):
|
|
9
|
+
* destination had a pre-install snapshot → restore it;
|
|
10
|
+
* destination did not exist → delete the file we created.
|
|
11
|
+
* - If the current file content differs from what we last wrote (the user
|
|
12
|
+
* edited it after install), the current content is preserved next to it as
|
|
13
|
+
* `<file>.hnx.bak` before restoring — user edits are never silently lost.
|
|
14
|
+
* - Empty directories created by the install are pruned up to (but excluding)
|
|
15
|
+
* the target root; the ledger file itself is removed last.
|
|
16
|
+
*
|
|
17
|
+
* This is why the Hermes adapter records its config.yaml merge as a single
|
|
18
|
+
* write-file op with a full pre-merge snapshot (3.4): uninstall rolls the
|
|
19
|
+
* `mcp_servers:` entries back without touching the user's other config —
|
|
20
|
+
* unlike `hermes plugins remove`, which leaves stale config behind.
|
|
21
|
+
*/
|
|
22
|
+
import fs from 'node:fs';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import { InstallError } from '../errors.js';
|
|
25
|
+
import { readInstallState } from './install-state.js';
|
|
26
|
+
import { getAdapter } from './registry.js';
|
|
27
|
+
/** The exact bytes the install last wrote to a destination, for drift checks. */
|
|
28
|
+
function writtenContent(op) {
|
|
29
|
+
if (op.kind === 'write-file')
|
|
30
|
+
return op.content;
|
|
31
|
+
if (op.kind === 'merge-json')
|
|
32
|
+
return `${JSON.stringify(op.mergePayload, null, 2)}\n`;
|
|
33
|
+
return ''; // copy-file: drift check not meaningful; restore/delete regardless
|
|
34
|
+
}
|
|
35
|
+
/** Read the ledger for a target root and compute the reverse steps. */
|
|
36
|
+
export function planUninstall(opts) {
|
|
37
|
+
const adapter = getAdapter(opts.target);
|
|
38
|
+
const root = adapter.resolveRoot(opts.input ?? {});
|
|
39
|
+
const installStatePath = path.join(root, 'harness-nexus-install-state.json');
|
|
40
|
+
const state = readInstallState(installStatePath);
|
|
41
|
+
if (!state)
|
|
42
|
+
return null;
|
|
43
|
+
const steps = [];
|
|
44
|
+
for (const op of [...state.operations].reverse()) {
|
|
45
|
+
const exists = fs.existsSync(op.destinationPath);
|
|
46
|
+
const current = exists ? fs.readFileSync(op.destinationPath, 'utf8') : null;
|
|
47
|
+
const conflicts = exists && current !== null && current !== writtenContent(op);
|
|
48
|
+
steps.push({
|
|
49
|
+
destinationPath: op.destinationPath,
|
|
50
|
+
action: op.previousContent != null ? 'restore' : 'delete',
|
|
51
|
+
previousContent: op.previousContent ?? null,
|
|
52
|
+
conflicts,
|
|
53
|
+
exists,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
targetRoot: root,
|
|
58
|
+
installStatePath,
|
|
59
|
+
profile: state.profile,
|
|
60
|
+
installedAt: state.installedAt,
|
|
61
|
+
steps,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Execute an uninstall plan (see module doc for semantics). */
|
|
65
|
+
export function applyUninstall(plan) {
|
|
66
|
+
let touched = 0;
|
|
67
|
+
try {
|
|
68
|
+
for (const step of plan.steps) {
|
|
69
|
+
if (!step.exists)
|
|
70
|
+
continue;
|
|
71
|
+
if (step.conflicts) {
|
|
72
|
+
fs.copyFileSync(step.destinationPath, `${step.destinationPath}.hnx.bak`);
|
|
73
|
+
}
|
|
74
|
+
if (step.action === 'restore') {
|
|
75
|
+
fs.writeFileSync(step.destinationPath, step.previousContent, 'utf8');
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
fs.rmSync(step.destinationPath);
|
|
79
|
+
}
|
|
80
|
+
pruneEmptyDirs(path.dirname(step.destinationPath), plan.targetRoot);
|
|
81
|
+
touched += 1;
|
|
82
|
+
}
|
|
83
|
+
if (fs.existsSync(plan.installStatePath)) {
|
|
84
|
+
fs.rmSync(plan.installStatePath);
|
|
85
|
+
touched += 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
throw new InstallError(`Failed to uninstall: ${e.message} (ledger left in place — re-run to continue)`, 'APPLY_FAILED', e);
|
|
90
|
+
}
|
|
91
|
+
return touched;
|
|
92
|
+
}
|
|
93
|
+
/** Remove empty directories from `dir` up to (excluding) `stop`. */
|
|
94
|
+
function pruneEmptyDirs(dir, stop) {
|
|
95
|
+
let current = path.resolve(dir);
|
|
96
|
+
const top = path.resolve(stop);
|
|
97
|
+
while (current.startsWith(top) && current !== top) {
|
|
98
|
+
try {
|
|
99
|
+
fs.rmdirSync(current); // fails with ENOTEMPTY if the dir has content — stop there
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
current = path.dirname(current);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=uninstaller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstaller.js","sourceRoot":"","sources":["../../src/install/uninstaller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { InventoryItemKind } from '@harness-nexus/shared';
|
|
2
|
+
/**
|
|
3
|
+
* Shared scanner plumbing (Phase 8 C3). Each target scanner discovers items
|
|
4
|
+
* from the same ground-truth locations its install adapter writes; this module
|
|
5
|
+
* owns the cross-target conventions: bounded text reads, summaries/previews,
|
|
6
|
+
* install-ledger platform detection, and MCP secret redaction.
|
|
7
|
+
* See docs/design/phase-8-c3.md.
|
|
8
|
+
*/
|
|
9
|
+
/** Hard cap for one importable artifact body (per item). */
|
|
10
|
+
export declare const MAX_ITEM_BYTES: number;
|
|
11
|
+
/** Platform-written MCP entry names start with this (shim + emitter convention). */
|
|
12
|
+
export declare const PLATFORM_MCP_PREFIX = "harness-nexus";
|
|
13
|
+
/** True iff the MCP entry name is one we wrote (shim entries, marketplaces). */
|
|
14
|
+
export declare function isPlatformMcpName(name: string): boolean;
|
|
15
|
+
/** Wire `meta` for a normalized MCP config entry (undefined-free per target). */
|
|
16
|
+
export declare function mcpMeta(entry: RawMcpEntryLike): {
|
|
17
|
+
transport?: 'stdio' | 'sse' | 'http';
|
|
18
|
+
command?: string;
|
|
19
|
+
url?: string;
|
|
20
|
+
};
|
|
21
|
+
/** Minimal structural shape the scanners normalize config entries to. */
|
|
22
|
+
export interface RawMcpEntryLike {
|
|
23
|
+
type?: string;
|
|
24
|
+
command?: string;
|
|
25
|
+
url?: string;
|
|
26
|
+
}
|
|
27
|
+
/** An item as discovered by a scanner, before wire-shaping (scan.ts does that). */
|
|
28
|
+
export interface DiscoveredItem {
|
|
29
|
+
kind: InventoryItemKind;
|
|
30
|
+
name: string;
|
|
31
|
+
/** Absolute file path (content kinds) or skill directory (skills). */
|
|
32
|
+
absPath: string;
|
|
33
|
+
/** Display path relative to the agent home. */
|
|
34
|
+
relPath: string;
|
|
35
|
+
importable: boolean;
|
|
36
|
+
note?: string | undefined;
|
|
37
|
+
summary?: string | undefined;
|
|
38
|
+
preview?: string | undefined;
|
|
39
|
+
meta?: {
|
|
40
|
+
multi?: boolean | undefined;
|
|
41
|
+
transport?: 'stdio' | 'sse' | 'http' | undefined;
|
|
42
|
+
command?: string | undefined;
|
|
43
|
+
url?: string | undefined;
|
|
44
|
+
} | undefined;
|
|
45
|
+
/** Extra evidence for origin:'platform' beyond the ledger (scanner-specific). */
|
|
46
|
+
platform?: boolean | undefined;
|
|
47
|
+
}
|
|
48
|
+
export type BoundedText = {
|
|
49
|
+
ok: true;
|
|
50
|
+
content: string;
|
|
51
|
+
} | {
|
|
52
|
+
ok: false;
|
|
53
|
+
error: string;
|
|
54
|
+
};
|
|
55
|
+
/** Read a text file with size + binary guards (an artifact that fails is never importable). */
|
|
56
|
+
export declare function readTextBounded(file: string): BoundedText;
|
|
57
|
+
/** List a skill directory's files (recursive, relative paths, sorted, dirs skipped). */
|
|
58
|
+
export declare function skillDirFiles(dir: string): string[];
|
|
59
|
+
/** Strip YAML frontmatter if present. */
|
|
60
|
+
export declare function stripFrontmatter(content: string): string;
|
|
61
|
+
/** First meaningful line of a markdown doc (after frontmatter), ≤120 chars. */
|
|
62
|
+
export declare function summarize(content: string): string | undefined;
|
|
63
|
+
/** ≤200-char single-line preview (after frontmatter). */
|
|
64
|
+
export declare function previewOf(content: string): string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* The install-state ledger hnx writes into each agent home. Its operation
|
|
67
|
+
* destination paths are the authoritative "platform wrote this" set — origin
|
|
68
|
+
* detection never guesses from content.
|
|
69
|
+
*/
|
|
70
|
+
export interface LedgerInfo {
|
|
71
|
+
platformPaths: Set<string>;
|
|
72
|
+
installedProfile: string | null;
|
|
73
|
+
}
|
|
74
|
+
export declare function readLedger(home: string): LedgerInfo;
|
|
75
|
+
/**
|
|
76
|
+
* True iff the item and a ledger-written path overlap in either direction —
|
|
77
|
+
* the item is a skill DIR while ledger operations record the FILEs inside it.
|
|
78
|
+
*/
|
|
79
|
+
export declare function isPlatformPath(absPath: string, ledger: LedgerInfo): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Redact a secret-carrying map (MCP env values, header values) to
|
|
82
|
+
* `${cred:<KEY>}` placeholders — the KEY survives so the user can fill the
|
|
83
|
+
* credential in; the plaintext NEVER crosses the wire to the server.
|
|
84
|
+
*/
|
|
85
|
+
export declare function redactSecretMap(values: Record<string, string> | undefined): Record<string, string> | undefined;
|
|
86
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/inventory/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Shared scanner plumbing (Phase 8 C3). Each target scanner discovers items
|
|
5
|
+
* from the same ground-truth locations its install adapter writes; this module
|
|
6
|
+
* owns the cross-target conventions: bounded text reads, summaries/previews,
|
|
7
|
+
* install-ledger platform detection, and MCP secret redaction.
|
|
8
|
+
* See docs/design/phase-8-c3.md.
|
|
9
|
+
*/
|
|
10
|
+
/** Hard cap for one importable artifact body (per item). */
|
|
11
|
+
export const MAX_ITEM_BYTES = 256 * 1024;
|
|
12
|
+
/** Platform-written MCP entry names start with this (shim + emitter convention). */
|
|
13
|
+
export const PLATFORM_MCP_PREFIX = 'harness-nexus';
|
|
14
|
+
/** True iff the MCP entry name is one we wrote (shim entries, marketplaces). */
|
|
15
|
+
export function isPlatformMcpName(name) {
|
|
16
|
+
return name === PLATFORM_MCP_PREFIX || name.startsWith(`${PLATFORM_MCP_PREFIX}-`);
|
|
17
|
+
}
|
|
18
|
+
/** Wire `meta` for a normalized MCP config entry (undefined-free per target). */
|
|
19
|
+
export function mcpMeta(entry) {
|
|
20
|
+
const transport = entry.command ? 'stdio' : entry.type === 'sse' ? 'sse' : 'http';
|
|
21
|
+
return {
|
|
22
|
+
transport,
|
|
23
|
+
...(entry.command ? { command: entry.command } : {}),
|
|
24
|
+
...(entry.url ? { url: entry.url } : {}),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Read a text file with size + binary guards (an artifact that fails is never importable). */
|
|
28
|
+
export function readTextBounded(file) {
|
|
29
|
+
let stat;
|
|
30
|
+
try {
|
|
31
|
+
stat = fs.statSync(file);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { ok: false, error: 'unreadable' };
|
|
35
|
+
}
|
|
36
|
+
if (!stat.isFile())
|
|
37
|
+
return { ok: false, error: 'not-a-file' };
|
|
38
|
+
if (stat.size > MAX_ITEM_BYTES)
|
|
39
|
+
return { ok: false, error: 'too-large' };
|
|
40
|
+
let content;
|
|
41
|
+
try {
|
|
42
|
+
content = fs.readFileSync(file, 'utf8');
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return { ok: false, error: 'unreadable' };
|
|
46
|
+
}
|
|
47
|
+
if (content.slice(0, 512).includes('\u0000'))
|
|
48
|
+
return { ok: false, error: 'binary' };
|
|
49
|
+
return { ok: true, content };
|
|
50
|
+
}
|
|
51
|
+
/** List a skill directory's files (recursive, relative paths, sorted, dirs skipped). */
|
|
52
|
+
export function skillDirFiles(dir) {
|
|
53
|
+
const out = [];
|
|
54
|
+
const walk = (rel) => {
|
|
55
|
+
for (const entry of fs
|
|
56
|
+
.readdirSync(path.join(dir, rel), { withFileTypes: true })
|
|
57
|
+
.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
58
|
+
if (entry.isDirectory())
|
|
59
|
+
walk(path.join(rel, entry.name));
|
|
60
|
+
else if (entry.isFile())
|
|
61
|
+
out.push(path.join(rel, entry.name));
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
walk('');
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
/** Strip YAML frontmatter if present. */
|
|
68
|
+
export function stripFrontmatter(content) {
|
|
69
|
+
if (!content.startsWith('---'))
|
|
70
|
+
return content;
|
|
71
|
+
const end = content.indexOf('\n---', 3);
|
|
72
|
+
if (end === -1)
|
|
73
|
+
return content;
|
|
74
|
+
return content.slice(content.indexOf('\n', end + 1) + 1);
|
|
75
|
+
}
|
|
76
|
+
/** First meaningful line of a markdown doc (after frontmatter), ≤120 chars. */
|
|
77
|
+
export function summarize(content) {
|
|
78
|
+
const body = stripFrontmatter(content);
|
|
79
|
+
for (const raw of body.split('\n')) {
|
|
80
|
+
const line = raw.trim();
|
|
81
|
+
if (!line || line.startsWith('#') || line === '---')
|
|
82
|
+
continue;
|
|
83
|
+
return line.slice(0, 120);
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
/** ≤200-char single-line preview (after frontmatter). */
|
|
88
|
+
export function previewOf(content) {
|
|
89
|
+
const body = stripFrontmatter(content).trim();
|
|
90
|
+
if (!body)
|
|
91
|
+
return undefined;
|
|
92
|
+
return body.replace(/\s+/g, ' ').slice(0, 200);
|
|
93
|
+
}
|
|
94
|
+
export function readLedger(home) {
|
|
95
|
+
const info = { platformPaths: new Set(), installedProfile: null };
|
|
96
|
+
const ledgerPath = path.join(home, 'harness-nexus-install-state.json');
|
|
97
|
+
try {
|
|
98
|
+
const raw = JSON.parse(fs.readFileSync(ledgerPath, 'utf8'));
|
|
99
|
+
for (const op of raw.operations ?? []) {
|
|
100
|
+
if (op.destinationPath)
|
|
101
|
+
info.platformPaths.add(path.resolve(op.destinationPath));
|
|
102
|
+
}
|
|
103
|
+
info.installedProfile = raw.profile?.name ?? null;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// absent or unreadable — no ledger evidence
|
|
107
|
+
}
|
|
108
|
+
return info;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* True iff the item and a ledger-written path overlap in either direction —
|
|
112
|
+
* the item is a skill DIR while ledger operations record the FILEs inside it.
|
|
113
|
+
*/
|
|
114
|
+
export function isPlatformPath(absPath, ledger) {
|
|
115
|
+
for (const p of ledger.platformPaths) {
|
|
116
|
+
if (absPath === p ||
|
|
117
|
+
absPath.startsWith(`${p}${path.sep}`) ||
|
|
118
|
+
p.startsWith(`${absPath}${path.sep}`)) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Redact a secret-carrying map (MCP env values, header values) to
|
|
126
|
+
* `${cred:<KEY>}` placeholders — the KEY survives so the user can fill the
|
|
127
|
+
* credential in; the plaintext NEVER crosses the wire to the server.
|
|
128
|
+
*/
|
|
129
|
+
export function redactSecretMap(values) {
|
|
130
|
+
if (!values)
|
|
131
|
+
return undefined;
|
|
132
|
+
const out = {};
|
|
133
|
+
for (const key of Object.keys(values))
|
|
134
|
+
out[key] = `\${cred:${key}}`;
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/inventory/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AgentTarget, InventoryItem, InventorySnapshot } from '@harness-nexus/shared';
|
|
2
|
+
import type { PayloadItem, TargetScanner } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Inventory scan entry point (Phase 8 C3). Owns the cross-scanner assembly:
|
|
5
|
+
* origin resolution (ledger paths + scanner markers), (kind, name) dedupe,
|
|
6
|
+
* snapshot shaping, and the collect fan-out. Kept in lockstep with the
|
|
7
|
+
* server's SCANNABLE_TARGETS (modules/inventory.ts).
|
|
8
|
+
*/
|
|
9
|
+
export declare const SCANNERS: TargetScanner[];
|
|
10
|
+
export declare function scannerFor(target: AgentTarget): TargetScanner | undefined;
|
|
11
|
+
/** Scan one target. A missing agent home still reports an (empty) snapshot. */
|
|
12
|
+
export declare function scanTarget(target: AgentTarget, homeDir?: string): InventorySnapshot;
|
|
13
|
+
/** Scan every supported target (daemon start / default scan request). */
|
|
14
|
+
export declare function scanAllTargets(homeDir?: string): InventorySnapshot[];
|
|
15
|
+
/**
|
|
16
|
+
* Collect bodies for a selection. Paths are re-derived by a FRESH discover —
|
|
17
|
+
* the daemon never trusts server-supplied paths.
|
|
18
|
+
*/
|
|
19
|
+
export declare function collectItems(target: AgentTarget, selections: readonly {
|
|
20
|
+
kind: InventoryItem['kind'];
|
|
21
|
+
name: string;
|
|
22
|
+
}[], homeDir?: string): Promise<PayloadItem[]>;
|
|
23
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/inventory/scan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM3F,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7D;;;;;GAKG;AAEH,eAAO,MAAM,QAAQ,EAAE,aAAa,EAKnC,CAAC;AAEF,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,SAAS,CAEzE;AAgBD,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,SAAY,GAAG,iBAAiB,CAyCtF;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,OAAO,SAAY,GAAG,iBAAiB,EAAE,CAEvE;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,SAAS;IAAE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,EACpE,OAAO,SAAY,GAClB,OAAO,CAAC,WAAW,EAAE,CAAC,CAiCxB"}
|