@senior-skills/node 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/archive.d.ts +25 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/archive.js +101 -0
- package/dist/archive.js.map +1 -0
- package/dist/config-store.d.ts +27 -0
- package/dist/config-store.d.ts.map +1 -0
- package/dist/config-store.js +155 -0
- package/dist/config-store.js.map +1 -0
- package/dist/file-system.d.ts +40 -0
- package/dist/file-system.d.ts.map +1 -0
- package/dist/file-system.js +189 -0
- package/dist/file-system.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +51 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +215 -0
- package/dist/runtime.js.map +1 -0
- package/dist/selection-prompt.d.ts +21 -0
- package/dist/selection-prompt.d.ts.map +1 -0
- package/dist/selection-prompt.js +75 -0
- package/dist/selection-prompt.js.map +1 -0
- package/dist/tool-updater.d.ts +20 -0
- package/dist/tool-updater.d.ts.map +1 -0
- package/dist/tool-updater.js +96 -0
- package/dist/tool-updater.js.map +1 -0
- package/dist/update-state.d.ts +10 -0
- package/dist/update-state.d.ts.map +1 -0
- package/dist/update-state.js +70 -0
- package/dist/update-state.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ArchiveEntry, type ArchiveReader } from '@senior-skills/core';
|
|
2
|
+
/**
|
|
3
|
+
* Reads `.tar.gz` payloads into memory.
|
|
4
|
+
*
|
|
5
|
+
* This class only *parses*; it deliberately makes no safety decisions. Entry paths, link
|
|
6
|
+
* types and sizes are handed to the installer exactly as the archive recorded them, so every
|
|
7
|
+
* rejection rule lives in one reviewed place (`SafeExtractor`) instead of being split across
|
|
8
|
+
* a parser and a consumer.
|
|
9
|
+
*
|
|
10
|
+
* The one thing enforced here is resource exhaustion: decompression stops as soon as the
|
|
11
|
+
* output exceeds the configured budget, which is what makes a gzip bomb a fast error rather
|
|
12
|
+
* than an out-of-memory kill.
|
|
13
|
+
*/
|
|
14
|
+
export interface ArchiveLimits {
|
|
15
|
+
readonly maxEntries: number;
|
|
16
|
+
readonly maxEntryBytes: number;
|
|
17
|
+
readonly maxTotalBytes: number;
|
|
18
|
+
}
|
|
19
|
+
export declare const DEFAULT_ARCHIVE_LIMITS: ArchiveLimits;
|
|
20
|
+
export declare class NodeArchiveReader implements ArchiveReader {
|
|
21
|
+
private readonly limits;
|
|
22
|
+
constructor(limits?: ArchiveLimits);
|
|
23
|
+
read(data: Uint8Array): Promise<readonly ArchiveEntry[]>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=archive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,eAAO,MAAM,sBAAsB,EAAE,aAIpC,CAAC;AAEF,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAE3B,MAAM,GAAE,aAAsC;IAIpD,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;CAyG/D"}
|
package/dist/archive.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { createGunzip } from 'node:zlib';
|
|
3
|
+
import * as tar from 'tar';
|
|
4
|
+
import { AgentSkillsError, ErrorCode, } from '@senior-skills/core';
|
|
5
|
+
export const DEFAULT_ARCHIVE_LIMITS = {
|
|
6
|
+
maxEntries: 5_000,
|
|
7
|
+
maxEntryBytes: 16 * 1024 * 1024,
|
|
8
|
+
maxTotalBytes: 64 * 1024 * 1024,
|
|
9
|
+
};
|
|
10
|
+
export class NodeArchiveReader {
|
|
11
|
+
limits;
|
|
12
|
+
constructor(limits = DEFAULT_ARCHIVE_LIMITS) {
|
|
13
|
+
this.limits = limits;
|
|
14
|
+
}
|
|
15
|
+
async read(data) {
|
|
16
|
+
const entries = [];
|
|
17
|
+
let totalBytes = 0;
|
|
18
|
+
const parser = new tar.Parser({
|
|
19
|
+
// Never let the parser itself resolve or strip anything; we want the raw recorded path.
|
|
20
|
+
strict: false,
|
|
21
|
+
});
|
|
22
|
+
const finished = new Promise((resolve, reject) => {
|
|
23
|
+
parser.on('entry', (entry) => {
|
|
24
|
+
if (entries.length >= this.limits.maxEntries) {
|
|
25
|
+
reject(new AgentSkillsError(ErrorCode.UNSAFE_ARCHIVE, `Archive contains more than ${this.limits.maxEntries} entries`, { data: { maxEntries: this.limits.maxEntries } }));
|
|
26
|
+
entry.resume();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const chunks = [];
|
|
30
|
+
let size = 0;
|
|
31
|
+
entry.on('data', (chunk) => {
|
|
32
|
+
size += chunk.length;
|
|
33
|
+
totalBytes += chunk.length;
|
|
34
|
+
if (size > this.limits.maxEntryBytes) {
|
|
35
|
+
reject(new AgentSkillsError(ErrorCode.UNSAFE_ARCHIVE, `Archive entry "${entry.path}" exceeds ${this.limits.maxEntryBytes} bytes`, { data: { path: entry.path, maxEntryBytes: this.limits.maxEntryBytes } }));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (totalBytes > this.limits.maxTotalBytes) {
|
|
39
|
+
reject(new AgentSkillsError(ErrorCode.UNSAFE_ARCHIVE, `Archive expands to more than ${this.limits.maxTotalBytes} bytes`, {
|
|
40
|
+
details: ['This is the signature of a decompression bomb.'],
|
|
41
|
+
data: { maxTotalBytes: this.limits.maxTotalBytes },
|
|
42
|
+
}));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
chunks.push(chunk);
|
|
46
|
+
});
|
|
47
|
+
entry.on('end', () => {
|
|
48
|
+
entries.push({
|
|
49
|
+
path: String(entry.path),
|
|
50
|
+
type: toEntryType(entry.type),
|
|
51
|
+
size,
|
|
52
|
+
mode: entry.mode ?? 0,
|
|
53
|
+
...(entry.linkpath == null ? {} : { linkTarget: String(entry.linkpath) }),
|
|
54
|
+
bytes: new Uint8Array(Buffer.concat(chunks)),
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
parser.on('error', (cause) => reject(new AgentSkillsError(ErrorCode.UNSAFE_ARCHIVE, 'Could not read archive', {
|
|
59
|
+
details: [cause.message],
|
|
60
|
+
hints: ['The download may be truncated or is not a valid .tar.gz'],
|
|
61
|
+
cause,
|
|
62
|
+
})));
|
|
63
|
+
parser.on('end', () => resolve());
|
|
64
|
+
});
|
|
65
|
+
const gunzip = createGunzip();
|
|
66
|
+
gunzip.on('error', () => {
|
|
67
|
+
/* surfaced through the pipeline promise below */
|
|
68
|
+
});
|
|
69
|
+
await Promise.all([
|
|
70
|
+
finished,
|
|
71
|
+
new Promise((resolve, reject) => {
|
|
72
|
+
Readable.from([Buffer.from(data)])
|
|
73
|
+
.pipe(gunzip)
|
|
74
|
+
.on('error', (cause) => reject(new AgentSkillsError(ErrorCode.UNSAFE_ARCHIVE, 'Could not decompress archive', {
|
|
75
|
+
details: [cause.message],
|
|
76
|
+
cause,
|
|
77
|
+
})))
|
|
78
|
+
.pipe(parser)
|
|
79
|
+
.on('finish', () => resolve())
|
|
80
|
+
.on('error', reject);
|
|
81
|
+
}),
|
|
82
|
+
]);
|
|
83
|
+
return entries;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function toEntryType(type) {
|
|
87
|
+
switch (type) {
|
|
88
|
+
case 'File':
|
|
89
|
+
case 'OldFile':
|
|
90
|
+
case 'ContiguousFile':
|
|
91
|
+
return 'file';
|
|
92
|
+
case 'Directory':
|
|
93
|
+
return 'directory';
|
|
94
|
+
case 'SymbolicLink':
|
|
95
|
+
case 'Link':
|
|
96
|
+
return 'symlink';
|
|
97
|
+
default:
|
|
98
|
+
return 'other';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,SAAS,GAGV,MAAM,qBAAqB,CAAC;AAoB7B,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,UAAU,EAAE,KAAK;IACjB,aAAa,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;IAC/B,aAAa,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;CAChC,CAAC;AAEF,MAAM,OAAO,iBAAiB;IACX,MAAM,CAAgB;IAEvC,YAAY,SAAwB,sBAAsB;QACxD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAgB;QACzB,MAAM,OAAO,GAAmB,EAAE,CAAC;QACnC,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;YAC5B,wFAAwF;YACxF,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC3B,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;oBAC7C,MAAM,CACJ,IAAI,gBAAgB,CAClB,SAAS,CAAC,cAAc,EACxB,8BAA8B,IAAI,CAAC,MAAM,CAAC,UAAU,UAAU,EAC9D,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CACjD,CACF,CAAC;oBACF,KAAK,CAAC,MAAM,EAAE,CAAC;oBACf,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAa,EAAE,CAAC;gBAC5B,IAAI,IAAI,GAAG,CAAC,CAAC;gBAEb,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;oBACjC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;oBACrB,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC;oBAC3B,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;wBACrC,MAAM,CACJ,IAAI,gBAAgB,CAClB,SAAS,CAAC,cAAc,EACxB,kBAAkB,KAAK,CAAC,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,aAAa,QAAQ,EAC1E,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,CACzE,CACF,CAAC;wBACF,OAAO;oBACT,CAAC;oBACD,IAAI,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;wBAC3C,MAAM,CACJ,IAAI,gBAAgB,CAClB,SAAS,CAAC,cAAc,EACxB,gCAAgC,IAAI,CAAC,MAAM,CAAC,aAAa,QAAQ,EACjE;4BACE,OAAO,EAAE,CAAC,gDAAgD,CAAC;4BAC3D,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE;yBACnD,CACF,CACF,CAAC;wBACF,OAAO;oBACT,CAAC;oBACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC,CAAC,CAAC;gBAEH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACnB,OAAO,CAAC,IAAI,CAAC;wBACX,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;wBACxB,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC;wBAC7B,IAAI;wBACJ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC;wBACrB,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACzE,KAAK,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;qBAC7C,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE,CAClC,MAAM,CACJ,IAAI,gBAAgB,CAAC,SAAS,CAAC,cAAc,EAAE,wBAAwB,EAAE;gBACvE,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;gBACxB,KAAK,EAAE,CAAC,yDAAyD,CAAC;gBAClE,KAAK;aACN,CAAC,CACH,CACF,CAAC;YACF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,iDAAiD;QACnD,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,QAAQ;YACR,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACpC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;qBAC/B,IAAI,CAAC,MAAM,CAAC;qBACZ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE,CAC5B,MAAM,CACJ,IAAI,gBAAgB,CAAC,SAAS,CAAC,cAAc,EAAE,8BAA8B,EAAE;oBAC7E,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;oBACxB,KAAK;iBACN,CAAC,CACH,CACF;qBACA,IAAI,CAAC,MAAM,CAAC;qBACZ,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;qBAC7B,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzB,CAAC,CAAC;SACH,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,SAAS,WAAW,CAAC,IAAwB;IAC3C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM,CAAC;QACZ,KAAK,SAAS,CAAC;QACf,KAAK,gBAAgB;YACnB,OAAO,MAAM,CAAC;QAChB,KAAK,WAAW;YACd,OAAO,WAAW,CAAC;QACrB,KAAK,cAAc,CAAC;QACpB,KAAK,MAAM;YACT,OAAO,SAAS,CAAC;QACnB;YACE,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type AgentSkillsConfig, type ConfigStore, type Environment, type FileSystem, type RegistryConfig, type RegistryKind } from '@senior-skills/core';
|
|
2
|
+
export declare const CONFIG_SCHEMA_VERSION = 1;
|
|
3
|
+
export declare const CONFIG_DIRNAME = ".senior-skills";
|
|
4
|
+
export declare const CONFIG_FILENAME = "config.json";
|
|
5
|
+
/** Overrides the whole `~/.senior-skills` directory. Primarily how the tests stay hermetic. */
|
|
6
|
+
export declare const HOME_ENV_VAR = "SENIOR_SKILLS_HOME";
|
|
7
|
+
export declare const OFFICIAL_REGISTRY: RegistryConfig;
|
|
8
|
+
export declare function defaultConfig(): AgentSkillsConfig;
|
|
9
|
+
/**
|
|
10
|
+
* JSON configuration in `~/.senior-skills/config.json`.
|
|
11
|
+
*
|
|
12
|
+
* Written atomically: a half-flushed config would be worse than none, since the registry list
|
|
13
|
+
* is what determines where the tool downloads executable-adjacent content from.
|
|
14
|
+
*/
|
|
15
|
+
export declare class FileConfigStore implements ConfigStore {
|
|
16
|
+
private readonly fs;
|
|
17
|
+
private readonly env;
|
|
18
|
+
constructor(fs: FileSystem, env: Environment);
|
|
19
|
+
location(): string;
|
|
20
|
+
load(): Promise<AgentSkillsConfig>;
|
|
21
|
+
save(config: AgentSkillsConfig): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export declare function configHome(fs: FileSystem, env: Environment): string;
|
|
24
|
+
export declare function cacheHome(fs: FileSystem, env: Environment): string;
|
|
25
|
+
/** Kind can be declared, but is inferred from the URL when omitted — the common case. */
|
|
26
|
+
export declare function inferKind(declared: unknown, url: string): RegistryKind;
|
|
27
|
+
//# sourceMappingURL=config-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAE7B,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAC/C,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,+FAA+F;AAC/F,eAAO,MAAM,YAAY,uBAAuB,CAAC;AAEjD,eAAO,MAAM,iBAAiB,EAAE,cAK/B,CAAC;AAEF,wBAAgB,aAAa,IAAI,iBAAiB,CAOjD;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;gBAEtB,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW;IAK5C,QAAQ,IAAI,MAAM;IAIZ,IAAI,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAyClC,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CAOrD;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAInE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAElE;AA4CD,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAYtE"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { AgentSkillsError, ErrorCode, } from '@senior-skills/core';
|
|
2
|
+
export const CONFIG_SCHEMA_VERSION = 1;
|
|
3
|
+
export const CONFIG_DIRNAME = '.senior-skills';
|
|
4
|
+
export const CONFIG_FILENAME = 'config.json';
|
|
5
|
+
/** Overrides the whole `~/.senior-skills` directory. Primarily how the tests stay hermetic. */
|
|
6
|
+
export const HOME_ENV_VAR = 'SENIOR_SKILLS_HOME';
|
|
7
|
+
export const OFFICIAL_REGISTRY = {
|
|
8
|
+
name: 'official',
|
|
9
|
+
url: 'https://github.com/robsonkades/senior-skills.git',
|
|
10
|
+
kind: 'git',
|
|
11
|
+
trusted: true,
|
|
12
|
+
};
|
|
13
|
+
export function defaultConfig() {
|
|
14
|
+
return {
|
|
15
|
+
schemaVersion: CONFIG_SCHEMA_VERSION,
|
|
16
|
+
registries: [OFFICIAL_REGISTRY],
|
|
17
|
+
agents: {},
|
|
18
|
+
cache: { ttlSeconds: 3600 },
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* JSON configuration in `~/.senior-skills/config.json`.
|
|
23
|
+
*
|
|
24
|
+
* Written atomically: a half-flushed config would be worse than none, since the registry list
|
|
25
|
+
* is what determines where the tool downloads executable-adjacent content from.
|
|
26
|
+
*/
|
|
27
|
+
export class FileConfigStore {
|
|
28
|
+
fs;
|
|
29
|
+
env;
|
|
30
|
+
constructor(fs, env) {
|
|
31
|
+
this.fs = fs;
|
|
32
|
+
this.env = env;
|
|
33
|
+
}
|
|
34
|
+
location() {
|
|
35
|
+
return this.fs.join(configHome(this.fs, this.env), CONFIG_FILENAME);
|
|
36
|
+
}
|
|
37
|
+
async load() {
|
|
38
|
+
const path = this.location();
|
|
39
|
+
if (!(await this.fs.exists(path)))
|
|
40
|
+
return defaultConfig();
|
|
41
|
+
let raw;
|
|
42
|
+
try {
|
|
43
|
+
raw = JSON.parse(await this.fs.readTextFile(path));
|
|
44
|
+
}
|
|
45
|
+
catch (cause) {
|
|
46
|
+
throw new AgentSkillsError(ErrorCode.USAGE, `Could not parse ${path}`, {
|
|
47
|
+
details: [cause instanceof Error ? cause.message : String(cause)],
|
|
48
|
+
hints: [`Fix the JSON, or delete ${path} to fall back to defaults`],
|
|
49
|
+
cause,
|
|
50
|
+
data: { path },
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
54
|
+
throw new AgentSkillsError(ErrorCode.USAGE, `${path} must be a JSON object`, {
|
|
55
|
+
data: { path },
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const doc = raw;
|
|
59
|
+
const registries = readRegistries(doc['registries'], path);
|
|
60
|
+
return {
|
|
61
|
+
schemaVersion: typeof doc['schemaVersion'] === 'number' ? doc['schemaVersion'] : CONFIG_SCHEMA_VERSION,
|
|
62
|
+
// An empty list is a deliberate choice (offline / local-only), not a reason to
|
|
63
|
+
// silently reinstate the official registry.
|
|
64
|
+
registries,
|
|
65
|
+
agents: readAgents(doc['agents']),
|
|
66
|
+
cache: {
|
|
67
|
+
ttlSeconds: typeof doc['cache']?.['ttlSeconds'] === 'number'
|
|
68
|
+
? doc['cache']['ttlSeconds']
|
|
69
|
+
: 3600,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async save(config) {
|
|
74
|
+
const path = this.location();
|
|
75
|
+
const staging = `${path}.tmp-${process.pid}`;
|
|
76
|
+
await this.fs.mkdirp(this.fs.dirname(path));
|
|
77
|
+
await this.fs.writeFile(staging, `${JSON.stringify(config, null, 2)}\n`);
|
|
78
|
+
await this.fs.rename(staging, path);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export function configHome(fs, env) {
|
|
82
|
+
const override = env.env()[HOME_ENV_VAR];
|
|
83
|
+
if (override !== undefined && override.trim() !== '')
|
|
84
|
+
return fs.resolve(override);
|
|
85
|
+
return fs.join(env.homeDir(), CONFIG_DIRNAME);
|
|
86
|
+
}
|
|
87
|
+
export function cacheHome(fs, env) {
|
|
88
|
+
return fs.join(configHome(fs, env), 'cache');
|
|
89
|
+
}
|
|
90
|
+
function readRegistries(value, path) {
|
|
91
|
+
if (value === undefined)
|
|
92
|
+
return defaultConfig().registries;
|
|
93
|
+
if (!Array.isArray(value)) {
|
|
94
|
+
throw new AgentSkillsError(ErrorCode.USAGE, `${path}: "registries" must be an array`, {
|
|
95
|
+
data: { path },
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const seen = new Set();
|
|
99
|
+
const registries = [];
|
|
100
|
+
for (const entry of value) {
|
|
101
|
+
if (entry === null || typeof entry !== 'object')
|
|
102
|
+
continue;
|
|
103
|
+
const record = entry;
|
|
104
|
+
const name = record['name'];
|
|
105
|
+
const url = record['url'];
|
|
106
|
+
if (typeof name !== 'string' || typeof url !== 'string')
|
|
107
|
+
continue;
|
|
108
|
+
if (seen.has(name)) {
|
|
109
|
+
throw new AgentSkillsError(ErrorCode.REGISTRY_DUPLICATE, `${path}: duplicate registry "${name}"`, {
|
|
110
|
+
hints: ['Registry names must be unique; precedence is decided by list order'],
|
|
111
|
+
data: { path, name },
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
seen.add(name);
|
|
115
|
+
registries.push({
|
|
116
|
+
name,
|
|
117
|
+
url,
|
|
118
|
+
kind: inferKind(record['kind'], url),
|
|
119
|
+
trusted: record['trusted'] !== false,
|
|
120
|
+
...(typeof record['ref'] === 'string' ? { ref: record['ref'] } : {}),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return registries;
|
|
124
|
+
}
|
|
125
|
+
/** Kind can be declared, but is inferred from the URL when omitted — the common case. */
|
|
126
|
+
export function inferKind(declared, url) {
|
|
127
|
+
if (declared === 'git' || declared === 'http' || declared === 'local')
|
|
128
|
+
return declared;
|
|
129
|
+
if (url.startsWith('file://') ||
|
|
130
|
+
/^[a-zA-Z]:[\\/]/.test(url) ||
|
|
131
|
+
url.startsWith('/') ||
|
|
132
|
+
url.startsWith('.')) {
|
|
133
|
+
return 'local';
|
|
134
|
+
}
|
|
135
|
+
if (url.endsWith('.git') || url.includes('github.com') || url.includes('gitlab.'))
|
|
136
|
+
return 'git';
|
|
137
|
+
return 'http';
|
|
138
|
+
}
|
|
139
|
+
function readAgents(value) {
|
|
140
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
141
|
+
return {};
|
|
142
|
+
const agents = {};
|
|
143
|
+
for (const [id, raw] of Object.entries(value)) {
|
|
144
|
+
if (raw === null || typeof raw !== 'object')
|
|
145
|
+
continue;
|
|
146
|
+
const record = raw;
|
|
147
|
+
agents[id] = {
|
|
148
|
+
enabled: record['enabled'] !== false,
|
|
149
|
+
...(typeof record['globalRoot'] === 'string' ? { globalRoot: record['globalRoot'] } : {}),
|
|
150
|
+
...(typeof record['projectRoot'] === 'string' ? { projectRoot: record['projectRoot'] } : {}),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return agents;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=config-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.js","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type DirEntry, type FileStat, type FileSystem } from '@senior-skills/core';
|
|
2
|
+
/**
|
|
3
|
+
* The real filesystem.
|
|
4
|
+
*
|
|
5
|
+
* Every `node:fs` call in the entire project lives in this class. Errors are translated into
|
|
6
|
+
* {@link AgentSkillsError} here so no higher layer ever has to interpret an `EACCES`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class NodeFileSystem implements FileSystem {
|
|
9
|
+
readonly separator: "/" | "\\";
|
|
10
|
+
readFile(target: string): Promise<Uint8Array>;
|
|
11
|
+
readTextFile(target: string): Promise<string>;
|
|
12
|
+
writeFile(target: string, data: Uint8Array | string): Promise<void>;
|
|
13
|
+
exists(target: string): Promise<boolean>;
|
|
14
|
+
lstat(target: string): Promise<FileStat>;
|
|
15
|
+
stat(target: string): Promise<FileStat>;
|
|
16
|
+
readDir(target: string): Promise<readonly DirEntry[]>;
|
|
17
|
+
mkdirp(target: string): Promise<void>;
|
|
18
|
+
remove(target: string): Promise<void>;
|
|
19
|
+
rename(from: string, to: string): Promise<void>;
|
|
20
|
+
copyFile(from: string, to: string): Promise<void>;
|
|
21
|
+
realpath(target: string): Promise<string>;
|
|
22
|
+
readlink(target: string): Promise<string>;
|
|
23
|
+
makeTempDir(parent: string, prefix: string): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Probes writability without writing.
|
|
26
|
+
*
|
|
27
|
+
* `fs.access(W_OK)` is unreliable on Windows for directories, so a failed probe there falls
|
|
28
|
+
* back to a create-and-delete on a uniquely named entry rather than reporting a false
|
|
29
|
+
* negative that would block a perfectly good install.
|
|
30
|
+
*/
|
|
31
|
+
isWritable(target: string): Promise<boolean>;
|
|
32
|
+
join(...parts: readonly string[]): string;
|
|
33
|
+
resolve(...parts: readonly string[]): string;
|
|
34
|
+
dirname(target: string): string;
|
|
35
|
+
basename(target: string): string;
|
|
36
|
+
relative(from: string, to: string): string;
|
|
37
|
+
isAbsolute(target: string): boolean;
|
|
38
|
+
private guard;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=file-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system.d.ts","sourceRoot":"","sources":["../src/file-system.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAE7B;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,UAAU;IAC/C,QAAQ,CAAC,SAAS,aAAY;IAExB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI7C,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI7C,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASxC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIxC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIvC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC;IAYrD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAOlE;;;;;;OAMG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBlD,IAAI,CAAC,GAAG,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM;IAIzC,OAAO,CAAC,GAAG,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM;IAI5C,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAI/B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIhC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM;IAI1C,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;YAIrB,KAAK;CAOpB"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { AgentSkillsError, ErrorCode, } from '@senior-skills/core';
|
|
5
|
+
/**
|
|
6
|
+
* The real filesystem.
|
|
7
|
+
*
|
|
8
|
+
* Every `node:fs` call in the entire project lives in this class. Errors are translated into
|
|
9
|
+
* {@link AgentSkillsError} here so no higher layer ever has to interpret an `EACCES`.
|
|
10
|
+
*/
|
|
11
|
+
export class NodeFileSystem {
|
|
12
|
+
separator = path.sep;
|
|
13
|
+
async readFile(target) {
|
|
14
|
+
return this.guard(target, 'read', async () => new Uint8Array(await fs.readFile(target)));
|
|
15
|
+
}
|
|
16
|
+
async readTextFile(target) {
|
|
17
|
+
return this.guard(target, 'read', () => fs.readFile(target, 'utf8'));
|
|
18
|
+
}
|
|
19
|
+
async writeFile(target, data) {
|
|
20
|
+
return this.guard(target, 'write', async () => {
|
|
21
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
22
|
+
await fs.writeFile(target, data);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async exists(target) {
|
|
26
|
+
try {
|
|
27
|
+
await fs.access(target, constants.F_OK);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async lstat(target) {
|
|
35
|
+
return this.guard(target, 'stat', async () => toStat(await fs.lstat(target)));
|
|
36
|
+
}
|
|
37
|
+
async stat(target) {
|
|
38
|
+
return this.guard(target, 'stat', async () => toStat(await fs.stat(target)));
|
|
39
|
+
}
|
|
40
|
+
async readDir(target) {
|
|
41
|
+
return this.guard(target, 'read', async () => {
|
|
42
|
+
const entries = await fs.readdir(target, { withFileTypes: true });
|
|
43
|
+
return entries.map((entry) => ({
|
|
44
|
+
name: entry.name,
|
|
45
|
+
isFile: entry.isFile(),
|
|
46
|
+
isDirectory: entry.isDirectory(),
|
|
47
|
+
isSymbolicLink: entry.isSymbolicLink(),
|
|
48
|
+
}));
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async mkdirp(target) {
|
|
52
|
+
return this.guard(target, 'create', async () => {
|
|
53
|
+
await fs.mkdir(target, { recursive: true });
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async remove(target) {
|
|
57
|
+
return this.guard(target, 'remove', async () => {
|
|
58
|
+
await fs.rm(target, { recursive: true, force: true });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async rename(from, to) {
|
|
62
|
+
return this.guard(to, 'rename', async () => {
|
|
63
|
+
await fs.mkdir(path.dirname(to), { recursive: true });
|
|
64
|
+
await fs.rename(from, to);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async copyFile(from, to) {
|
|
68
|
+
return this.guard(to, 'copy', async () => {
|
|
69
|
+
await fs.mkdir(path.dirname(to), { recursive: true });
|
|
70
|
+
await fs.copyFile(from, to);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async realpath(target) {
|
|
74
|
+
return this.guard(target, 'resolve', () => fs.realpath(target));
|
|
75
|
+
}
|
|
76
|
+
async readlink(target) {
|
|
77
|
+
return this.guard(target, 'read', () => fs.readlink(target));
|
|
78
|
+
}
|
|
79
|
+
async makeTempDir(parent, prefix) {
|
|
80
|
+
return this.guard(parent, 'create', async () => {
|
|
81
|
+
await fs.mkdir(parent, { recursive: true });
|
|
82
|
+
return fs.mkdtemp(path.join(parent, prefix));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Probes writability without writing.
|
|
87
|
+
*
|
|
88
|
+
* `fs.access(W_OK)` is unreliable on Windows for directories, so a failed probe there falls
|
|
89
|
+
* back to a create-and-delete on a uniquely named entry rather than reporting a false
|
|
90
|
+
* negative that would block a perfectly good install.
|
|
91
|
+
*/
|
|
92
|
+
async isWritable(target) {
|
|
93
|
+
try {
|
|
94
|
+
await fs.access(target, constants.W_OK);
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
if (process.platform !== 'win32')
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
const probe = path.join(target, `.senior-skills-write-probe-${process.pid}-${Date.now()}`);
|
|
102
|
+
try {
|
|
103
|
+
await fs.writeFile(probe, '');
|
|
104
|
+
await fs.rm(probe, { force: true });
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
join(...parts) {
|
|
112
|
+
return path.join(...parts);
|
|
113
|
+
}
|
|
114
|
+
resolve(...parts) {
|
|
115
|
+
return path.resolve(...parts);
|
|
116
|
+
}
|
|
117
|
+
dirname(target) {
|
|
118
|
+
return path.dirname(target);
|
|
119
|
+
}
|
|
120
|
+
basename(target) {
|
|
121
|
+
return path.basename(target);
|
|
122
|
+
}
|
|
123
|
+
relative(from, to) {
|
|
124
|
+
return path.relative(from, to);
|
|
125
|
+
}
|
|
126
|
+
isAbsolute(target) {
|
|
127
|
+
return path.isAbsolute(target);
|
|
128
|
+
}
|
|
129
|
+
async guard(target, action, work) {
|
|
130
|
+
try {
|
|
131
|
+
return await work();
|
|
132
|
+
}
|
|
133
|
+
catch (cause) {
|
|
134
|
+
throw translate(cause, target, action);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function toStat(stats) {
|
|
139
|
+
return {
|
|
140
|
+
isFile: stats.isFile(),
|
|
141
|
+
isDirectory: stats.isDirectory(),
|
|
142
|
+
isSymbolicLink: stats.isSymbolicLink(),
|
|
143
|
+
size: stats.size,
|
|
144
|
+
mtimeMs: stats.mtimeMs,
|
|
145
|
+
mode: stats.mode,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function translate(cause, target, action) {
|
|
149
|
+
const code = cause?.code;
|
|
150
|
+
if (code === 'EACCES' || code === 'EPERM') {
|
|
151
|
+
return new AgentSkillsError(ErrorCode.PERMISSION_DENIED, `Permission denied: cannot ${action} ${target}`, {
|
|
152
|
+
hints: [
|
|
153
|
+
'Check the directory permissions',
|
|
154
|
+
process.platform === 'win32'
|
|
155
|
+
? 'On Windows, a file open in another program can also cause this'
|
|
156
|
+
: 'Avoid sudo; install into a directory you own, or use --project',
|
|
157
|
+
],
|
|
158
|
+
cause,
|
|
159
|
+
data: { path: target, action, errno: code },
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
if (code === 'ENOENT') {
|
|
163
|
+
return new AgentSkillsError(ErrorCode.IO_ERROR, `No such file or directory: ${target}`, {
|
|
164
|
+
cause,
|
|
165
|
+
data: { path: target, action, errno: code },
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (code === 'ENOSPC') {
|
|
169
|
+
return new AgentSkillsError(ErrorCode.IO_ERROR, `No space left on device while trying to ${action} ${target}`, {
|
|
170
|
+
cause,
|
|
171
|
+
data: { path: target, action, errno: code },
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (code === 'EXDEV') {
|
|
175
|
+
// The installer stages beside the target precisely to avoid this; seeing it means an
|
|
176
|
+
// assumption broke, so say so rather than silently degrading to a copy.
|
|
177
|
+
return new AgentSkillsError(ErrorCode.INSTALL_FAILED, `Cannot ${action} ${target}: source and destination are on different filesystems`, {
|
|
178
|
+
hints: ['Report this: staging is meant to happen on the destination filesystem'],
|
|
179
|
+
cause,
|
|
180
|
+
data: { path: target, action, errno: code },
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return new AgentSkillsError(ErrorCode.IO_ERROR, `Failed to ${action} ${target}`, {
|
|
184
|
+
details: [cause instanceof Error ? cause.message : String(cause)],
|
|
185
|
+
cause,
|
|
186
|
+
data: { path: target, action, ...(code === undefined ? {} : { errno: code }) },
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=file-system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system.js","sourceRoot":"","sources":["../src/file-system.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@senior-skills/node` — Node.js implementations of the infrastructure ports.
|
|
3
|
+
*
|
|
4
|
+
* This is the only package that imports `node:fs`, `node:child_process`, `fetch` or `tar`.
|
|
5
|
+
* Swapping it out is how the rest of the system would run on a different runtime.
|
|
6
|
+
*/
|
|
7
|
+
export { NodeFileSystem } from './file-system.ts';
|
|
8
|
+
export { FileUpdateStateStore } from './update-state.ts';
|
|
9
|
+
export { NpmToolUpdater } from './tool-updater.ts';
|
|
10
|
+
export { NodeSelectionPrompt } from './selection-prompt.ts';
|
|
11
|
+
export { ConsoleLogger, NodeCommandRunner, NodeEnvironment, NodeHasher, NodeHttpClient, SystemClock, } from './runtime.ts';
|
|
12
|
+
export { DEFAULT_ARCHIVE_LIMITS, NodeArchiveReader, type ArchiveLimits } from './archive.ts';
|
|
13
|
+
export { CONFIG_DIRNAME, CONFIG_FILENAME, CONFIG_SCHEMA_VERSION, FileConfigStore, HOME_ENV_VAR, OFFICIAL_REGISTRY, cacheHome, configHome, defaultConfig, inferKind, } from './config-store.ts';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,cAAc,EACd,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,UAAU,EACV,aAAa,EACb,SAAS,GACV,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@senior-skills/node` — Node.js implementations of the infrastructure ports.
|
|
3
|
+
*
|
|
4
|
+
* This is the only package that imports `node:fs`, `node:child_process`, `fetch` or `tar`.
|
|
5
|
+
* Swapping it out is how the rest of the system would run on a different runtime.
|
|
6
|
+
*/
|
|
7
|
+
export { NodeFileSystem } from "./file-system.js";
|
|
8
|
+
export { FileUpdateStateStore } from "./update-state.js";
|
|
9
|
+
export { NpmToolUpdater } from "./tool-updater.js";
|
|
10
|
+
export { NodeSelectionPrompt } from "./selection-prompt.js";
|
|
11
|
+
export { ConsoleLogger, NodeCommandRunner, NodeEnvironment, NodeHasher, NodeHttpClient, SystemClock, } from "./runtime.js";
|
|
12
|
+
export { DEFAULT_ARCHIVE_LIMITS, NodeArchiveReader } from "./archive.js";
|
|
13
|
+
export { CONFIG_DIRNAME, CONFIG_FILENAME, CONFIG_SCHEMA_VERSION, FileConfigStore, HOME_ENV_VAR, OFFICIAL_REGISTRY, cacheHome, configHome, defaultConfig, inferKind, } from "./config-store.js";
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,cAAc,EACd,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAsB,MAAM,cAAc,CAAC;AAC7F,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,UAAU,EACV,aAAa,EACb,SAAS,GACV,MAAM,mBAAmB,CAAC"}
|