@sensigo/realm-cli 0.12.0 → 0.13.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/agent/run-attach.d.ts +24 -0
- package/dist/agent/run-attach.d.ts.map +1 -0
- package/dist/agent/run-attach.js +77 -0
- package/dist/agent/run-attach.js.map +1 -0
- package/dist/commands/agent.d.ts +13 -0
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +38 -8
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/init.d.ts +2 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +42 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/inspect.d.ts +1 -0
- package/dist/commands/inspect.d.ts.map +1 -1
- package/dist/commands/inspect.js +93 -1
- package/dist/commands/inspect.js.map +1 -1
- package/dist/commands/listen.d.ts +11 -0
- package/dist/commands/listen.d.ts.map +1 -1
- package/dist/commands/listen.js +36 -1
- package/dist/commands/listen.js.map +1 -1
- package/dist/commands/mcp.d.ts +2 -1
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +12 -5
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/register.d.ts +6 -0
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +20 -1
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +12 -0
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/serve.d.ts +6 -0
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +17 -4
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +25 -1
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +53 -8
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +6 -1
- package/dist/commands/watch.js.map +1 -1
- package/dist/extensions/extension-identity.d.ts +63 -0
- package/dist/extensions/extension-identity.d.ts.map +1 -0
- package/dist/extensions/extension-identity.js +218 -0
- package/dist/extensions/extension-identity.js.map +1 -0
- package/dist/extensions/load-project-extensions.d.ts +36 -0
- package/dist/extensions/load-project-extensions.d.ts.map +1 -0
- package/dist/extensions/load-project-extensions.js +358 -0
- package/dist/extensions/load-project-extensions.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +4 -4
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
// realm validate <path> — validates a workflow YAML file without registering it.
|
|
2
|
+
//
|
|
3
|
+
// Strictness asymmetry (documented): extension-free workflows validate through the EXACT
|
|
4
|
+
// from-string path used before project extensions existed (byte-identical behavior).
|
|
5
|
+
// Workflows declaring `extensions:` (or validated with --extensions-module) go through
|
|
6
|
+
// file-based loading so extension modules can be resolved, then a SECOND pass validates
|
|
7
|
+
// step `config` against each resolved adapter's `config_schema` (two-pass).
|
|
2
8
|
import { Command } from 'commander';
|
|
3
9
|
import { join } from 'node:path';
|
|
4
10
|
import { readFileSync } from 'node:fs';
|
|
5
|
-
import {
|
|
11
|
+
import { load } from 'js-yaml';
|
|
12
|
+
import { loadWorkflowFromString, loadWorkflowFromFile, WorkflowError } from '@sensigo/realm';
|
|
13
|
+
import { loadProjectExtensions } from '../extensions/load-project-extensions.js';
|
|
14
|
+
/** Pre-scan: does the YAML carry a top-level `extensions` key? (Parse errors → false; the
|
|
15
|
+
* real loader below reports them with its existing error surface.) */
|
|
16
|
+
function hasTopLevelExtensions(content) {
|
|
17
|
+
try {
|
|
18
|
+
const raw = load(content);
|
|
19
|
+
return (typeof raw === 'object' &&
|
|
20
|
+
raw !== null &&
|
|
21
|
+
!Array.isArray(raw) &&
|
|
22
|
+
'extensions' in raw);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
6
28
|
export const validateCommand = new Command('validate')
|
|
7
29
|
.argument('<path>', 'Path to workflow directory or workflow.yaml file')
|
|
30
|
+
.option('--extensions-module <path>', "Extensions module that REPLACES the workflow's declared 'extensions' modules (repair/override)")
|
|
8
31
|
.description('Validate a workflow YAML file')
|
|
9
|
-
.action((inputPath) => {
|
|
32
|
+
.action(async (inputPath, opts) => {
|
|
10
33
|
const filePath = inputPath.endsWith('.yaml') || inputPath.endsWith('.yml')
|
|
11
34
|
? inputPath
|
|
12
35
|
: join(inputPath, 'workflow.yaml');
|
|
@@ -20,16 +43,38 @@ export const validateCommand = new Command('validate')
|
|
|
20
43
|
process.exit(1);
|
|
21
44
|
return;
|
|
22
45
|
}
|
|
46
|
+
if (!hasTopLevelExtensions(content) && opts.extensionsModule === undefined) {
|
|
47
|
+
// Extension-free: the exact current from-string path — byte-identical behavior.
|
|
48
|
+
try {
|
|
49
|
+
const definition = loadWorkflowFromString(content);
|
|
50
|
+
console.log(`Valid: ${definition.id} v${definition.version} (${Object.keys(definition.steps).length} steps)`);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err instanceof WorkflowError) {
|
|
54
|
+
console.error(`Invalid: ${err.message}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Extensions declared (or an override supplied): file-based two-pass validation.
|
|
23
62
|
try {
|
|
24
|
-
|
|
63
|
+
// Pass 1: structural validation + extension resolution metadata (source_dir/trust_root).
|
|
64
|
+
const definition = loadWorkflowFromFile(filePath);
|
|
65
|
+
const { registry, manifest } = await loadProjectExtensions(definition, opts.extensionsModule !== undefined ? { overrideModule: opts.extensionsModule } : {});
|
|
66
|
+
// Pass 2: step config validated against each resolved adapter's config_schema.
|
|
67
|
+
loadWorkflowFromFile(filePath, registry);
|
|
25
68
|
console.log(`Valid: ${definition.id} v${definition.version} (${Object.keys(definition.steps).length} steps)`);
|
|
69
|
+
if (manifest.modules.length > 0) {
|
|
70
|
+
console.log(`Extensions: ${manifest.modules.map((m) => m.declared).join(', ')} ` +
|
|
71
|
+
`(adapters: ${manifest.adapters.length}, handlers: ${manifest.handlers.length}, ` +
|
|
72
|
+
`processors: ${manifest.processors.length})`);
|
|
73
|
+
}
|
|
26
74
|
}
|
|
27
75
|
catch (err) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
throw err;
|
|
76
|
+
console.error(`Invalid: ${err instanceof Error ? err.message : String(err)}`);
|
|
77
|
+
process.exit(1);
|
|
33
78
|
}
|
|
34
79
|
});
|
|
35
80
|
//# sourceMappingURL=validate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AA+BxD;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,iBAAiB,EACxB,MAAM,CAAC,EAAE,WAAW,EACpB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CA4Df;AAED,eAAO,MAAM,YAAY,SAoBrB,CAAC"}
|
package/dist/commands/watch.js
CHANGED
|
@@ -3,16 +3,21 @@ import { watch, existsSync } from 'node:fs';
|
|
|
3
3
|
import { join, dirname, resolve } from 'node:path';
|
|
4
4
|
import { Command } from 'commander';
|
|
5
5
|
import { loadWorkflowFromFile, WorkflowError } from '@sensigo/realm';
|
|
6
|
+
import { loadWorkflowForRegistration } from './register.js';
|
|
6
7
|
/**
|
|
7
8
|
* Attempts to load and register a workflow YAML file.
|
|
8
9
|
* Logs the result (success or validation error) to stdout/stderr.
|
|
10
|
+
* Like `realm workflow register`, each (re-)registration mints the trust decision: when the
|
|
11
|
+
* workflow declares `extensions:`, the modules load + duck-validate and step config gets the
|
|
12
|
+
* config_schema two-pass BEFORE persisting. NOTE: long-lived watch processes keep the FIRST
|
|
13
|
+
* imported content of each module path (ESM cache) — restart watch to pick up module changes.
|
|
9
14
|
* @param filePath Path to the workflow YAML file.
|
|
10
15
|
* @param store The registrar to register into.
|
|
11
16
|
*/
|
|
12
17
|
async function registerFile(filePath, store) {
|
|
13
18
|
const timestamp = new Date().toISOString();
|
|
14
19
|
try {
|
|
15
|
-
const definition =
|
|
20
|
+
const definition = await loadWorkflowForRegistration(filePath);
|
|
16
21
|
await store.register(definition);
|
|
17
22
|
console.log(`[${timestamp}] Registered: ${definition.id} v${definition.version} (${Object.keys(definition.steps).length} steps)`);
|
|
18
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ExtensionIdentityEntry, ExtensionIdentityModule, ExtensionIdentitySignals } from '@sensigo/realm';
|
|
2
|
+
import { extensionIdentityDiffers } from '@sensigo/realm';
|
|
3
|
+
/** The one sweep-rule version this module can compute. Comparison ALWAYS recomputes under
|
|
4
|
+
* the RECORDED rule string — a future rules change must add a new version, never mutate v1. */
|
|
5
|
+
export declare const DIR_TREE_V1_RULES = "dir_tree_v1: include .js,.mjs,.cjs,.ts,.mts,.cts,.json; exclude dirs node_modules,.git; skip symlinks; sort by relpath; sha256(relpath\\0filehash); caps 2000 files/50MB";
|
|
6
|
+
/** Compares two identity entries — tree_hash + per-module entry hashes + override flag. */
|
|
7
|
+
export { extensionIdentityDiffers as identityDiffers };
|
|
8
|
+
export interface ComputeIdentityInput {
|
|
9
|
+
declared: string;
|
|
10
|
+
resolved: string;
|
|
11
|
+
format: ExtensionIdentityModule['format'];
|
|
12
|
+
}
|
|
13
|
+
export interface ComputeIdentityOptions {
|
|
14
|
+
/** Trust root for the advisory signals (package.json version, .git HEAD). */
|
|
15
|
+
trustRoot?: string;
|
|
16
|
+
/** Set when --extensions-module replaced the declared modules. */
|
|
17
|
+
overrideActive?: boolean;
|
|
18
|
+
/** Injected for tests; defaults to `new Date().toISOString()`. */
|
|
19
|
+
capturedAt?: string;
|
|
20
|
+
/** Injected for tests; defaults to `process.pid`. */
|
|
21
|
+
pid?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Computes the dir_tree_v1 identity of a set of loaded extension modules: per-module
|
|
25
|
+
* sha256 entry hashes plus a deterministic directory-tree fingerprint over the deduped
|
|
26
|
+
* parent directories of the resolved entries. Pure fs + crypto — never loads code.
|
|
27
|
+
*/
|
|
28
|
+
export declare function computeExtensionIdentity(modules: ComputeIdentityInput[], opts?: ComputeIdentityOptions): ExtensionIdentityEntry;
|
|
29
|
+
/**
|
|
30
|
+
* Builds an identity entry that records a capture/load FAILURE — the failure is itself
|
|
31
|
+
* evidence (WorkflowContextSnapshot.error precedent). Modules/tree are empty placeholders.
|
|
32
|
+
*/
|
|
33
|
+
export declare function errorExtensionIdentityEntry(message: string, opts?: Pick<ComputeIdentityOptions, 'capturedAt' | 'pid' | 'overrideActive'>): ExtensionIdentityEntry;
|
|
34
|
+
/** Per-component result of a --check-drift recomputation against current disk state. */
|
|
35
|
+
export interface RecomputeResult {
|
|
36
|
+
comparable: true;
|
|
37
|
+
/** Per recorded module: current entry hash (undefined = file unreadable/missing). */
|
|
38
|
+
modules: Array<{
|
|
39
|
+
resolved: string;
|
|
40
|
+
recorded_hash: string;
|
|
41
|
+
current_hash?: string;
|
|
42
|
+
}>;
|
|
43
|
+
tree: {
|
|
44
|
+
recorded_hash: string;
|
|
45
|
+
current_hash: string;
|
|
46
|
+
current_truncated: boolean;
|
|
47
|
+
};
|
|
48
|
+
signals?: ExtensionIdentitySignals;
|
|
49
|
+
}
|
|
50
|
+
export interface RecomputeNotComparable {
|
|
51
|
+
comparable: false;
|
|
52
|
+
reason: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Recomputes an entry's identity from CURRENT disk state STRICTLY under the entry's
|
|
56
|
+
* RECORDED rules and roots — an unknown rules version yields an explicit cannot-compare
|
|
57
|
+
* rather than a guess (a rules change must never manufacture phantom drift).
|
|
58
|
+
* Pure fs + crypto — never loads code.
|
|
59
|
+
*/
|
|
60
|
+
export declare function recomputeIdentity(entry: ExtensionIdentityEntry, opts?: {
|
|
61
|
+
trustRoot?: string;
|
|
62
|
+
}): RecomputeResult | RecomputeNotComparable;
|
|
63
|
+
//# sourceMappingURL=extension-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension-identity.d.ts","sourceRoot":"","sources":["../../src/extensions/extension-identity.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;gGACgG;AAChG,eAAO,MAAM,iBAAiB,6KAC8I,CAAC;AAO7K,2FAA2F;AAC3F,OAAO,EAAE,wBAAwB,IAAI,eAAe,EAAE,CAAC;AAEvD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,sBAAsB;IACrC,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAyHD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,oBAAoB,EAAE,EAC/B,IAAI,GAAE,sBAA2B,GAChC,sBAAsB,CAqBxB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,IAAI,CAAC,sBAAsB,EAAE,YAAY,GAAG,KAAK,GAAG,gBAAgB,CAAM,GAC/E,sBAAsB,CAiBxB;AAED,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,IAAI,CAAC;IACjB,qFAAqF;IACrF,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnF,IAAI,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,OAAO,CAAA;KAAE,CAAC;IAClF,OAAO,CAAC,EAAE,wBAAwB,CAAC;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,KAAK,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,sBAAsB,EAC7B,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,eAAe,GAAG,sBAAsB,CAkC1C"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// extension-identity.ts — PURE fingerprint + compare for extension-code drift evidence
|
|
2
|
+
// (issue #119). This module is STRUCTURALLY incapable of loading code: no dynamic import,
|
|
3
|
+
// no module-require creation, anywhere. It only reads bytes (fs), hashes them (crypto),
|
|
4
|
+
// and manipulates paths — which is exactly why read-only commands (`realm run inspect
|
|
5
|
+
// --check-drift`) may use it without ever gaining the capability to execute project code.
|
|
6
|
+
// A structural test (read-only-no-extensions.test.ts) enforces this.
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
9
|
+
import { dirname, join, relative, sep } from 'node:path';
|
|
10
|
+
import { extensionIdentityDiffers } from '@sensigo/realm';
|
|
11
|
+
/** The one sweep-rule version this module can compute. Comparison ALWAYS recomputes under
|
|
12
|
+
* the RECORDED rule string — a future rules change must add a new version, never mutate v1. */
|
|
13
|
+
export const DIR_TREE_V1_RULES = 'dir_tree_v1: include .js,.mjs,.cjs,.ts,.mts,.cts,.json; exclude dirs node_modules,.git; skip symlinks; sort by relpath; sha256(relpath\\0filehash); caps 2000 files/50MB';
|
|
14
|
+
const INCLUDED_EXTENSIONS = new Set(['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts', '.json']);
|
|
15
|
+
const EXCLUDED_DIR_NAMES = new Set(['node_modules', '.git']);
|
|
16
|
+
const MAX_FILES = 2000;
|
|
17
|
+
const MAX_TOTAL_BYTES = 50 * 1024 * 1024;
|
|
18
|
+
/** Compares two identity entries — tree_hash + per-module entry hashes + override flag. */
|
|
19
|
+
export { extensionIdentityDiffers as identityDiffers };
|
|
20
|
+
function sha256Hex(data) {
|
|
21
|
+
return createHash('sha256').update(data).digest('hex');
|
|
22
|
+
}
|
|
23
|
+
function fileExtension(path) {
|
|
24
|
+
const base = path.slice(path.lastIndexOf(sep) + 1);
|
|
25
|
+
const dot = base.lastIndexOf('.');
|
|
26
|
+
return dot === -1 ? '' : base.slice(dot);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Deterministically enumerates the relative paths of sweep-eligible files under `root`
|
|
30
|
+
* per dir_tree_v1: included extensions only, `node_modules`/`.git` directories excluded at
|
|
31
|
+
* any depth, symlinks (files and directories) skipped, sorted by relative path.
|
|
32
|
+
* Enumeration is cap-free — caps apply at the hashing stage so the truncated fingerprint
|
|
33
|
+
* covers a DETERMINISTIC prefix of the sorted listing.
|
|
34
|
+
*/
|
|
35
|
+
function enumerateTreeFiles(root) {
|
|
36
|
+
const relPaths = [];
|
|
37
|
+
const walk = (dir) => {
|
|
38
|
+
let entries;
|
|
39
|
+
try {
|
|
40
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return; // unreadable directory — skipped (deterministic for a given tree state)
|
|
44
|
+
}
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
const full = join(dir, entry.name);
|
|
47
|
+
if (entry.isSymbolicLink())
|
|
48
|
+
continue; // dir_tree_v1: symlinks skipped
|
|
49
|
+
if (entry.isDirectory()) {
|
|
50
|
+
if (EXCLUDED_DIR_NAMES.has(entry.name))
|
|
51
|
+
continue;
|
|
52
|
+
walk(full);
|
|
53
|
+
}
|
|
54
|
+
else if (entry.isFile()) {
|
|
55
|
+
if (INCLUDED_EXTENSIONS.has(fileExtension(entry.name))) {
|
|
56
|
+
relPaths.push(relative(root, full));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
walk(root);
|
|
62
|
+
return relPaths.sort();
|
|
63
|
+
}
|
|
64
|
+
/** Hashes the sorted file listing of `roots` under the dir_tree_v1 caps. */
|
|
65
|
+
function sweepTree(roots) {
|
|
66
|
+
// Enumerate everything first (cheap), THEN hash under caps — the truncation point is a
|
|
67
|
+
// deterministic prefix of the sorted listing, so truncated hashes stay comparable.
|
|
68
|
+
const perRoot = roots.map((root) => enumerateTreeFiles(root).map((rel) => ({ root, rel })));
|
|
69
|
+
const allFiles = perRoot.flat();
|
|
70
|
+
const lines = [];
|
|
71
|
+
let totalBytes = 0;
|
|
72
|
+
let truncated = false;
|
|
73
|
+
for (const file of allFiles) {
|
|
74
|
+
if (lines.length >= MAX_FILES || totalBytes >= MAX_TOTAL_BYTES) {
|
|
75
|
+
truncated = true;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
let bytes;
|
|
79
|
+
try {
|
|
80
|
+
bytes = readFileSync(join(file.root, file.rel));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// File disappeared between enumeration and hashing — record it as unreadable
|
|
84
|
+
// (deterministic for a given tree state; a vanishing file IS a tree change).
|
|
85
|
+
lines.push(`${file.rel}\u0000<unreadable>`);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
totalBytes += bytes.length;
|
|
89
|
+
lines.push(`${file.rel}\u0000${sha256Hex(bytes)}`);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
file_count: lines.length,
|
|
93
|
+
total_bytes: totalBytes,
|
|
94
|
+
tree_hash: sha256Hex(lines.join('\n')),
|
|
95
|
+
truncated,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** Advisory signals — each independently fail-soft to undefined; never compared. */
|
|
99
|
+
function collectSignals(trustRoot) {
|
|
100
|
+
if (trustRoot === undefined)
|
|
101
|
+
return undefined;
|
|
102
|
+
const signals = {};
|
|
103
|
+
try {
|
|
104
|
+
const pkg = JSON.parse(readFileSync(join(trustRoot, 'package.json'), 'utf8'));
|
|
105
|
+
if (typeof pkg.version === 'string')
|
|
106
|
+
signals.package_version = pkg.version;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// fail-soft
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
// Read .git/HEAD; dereference ONE ref file. No child processes, ever.
|
|
113
|
+
const head = readFileSync(join(trustRoot, '.git', 'HEAD'), 'utf8').trim();
|
|
114
|
+
if (head.startsWith('ref: ')) {
|
|
115
|
+
const refPath = head.slice('ref: '.length).trim();
|
|
116
|
+
const refValue = readFileSync(join(trustRoot, '.git', refPath), 'utf8').trim();
|
|
117
|
+
if (refValue !== '')
|
|
118
|
+
signals.git_head = refValue;
|
|
119
|
+
}
|
|
120
|
+
else if (head !== '') {
|
|
121
|
+
signals.git_head = head; // detached HEAD — the hash itself
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// fail-soft (packed refs, no .git, unreadable — all acceptable)
|
|
126
|
+
}
|
|
127
|
+
return signals.package_version === undefined && signals.git_head === undefined
|
|
128
|
+
? undefined
|
|
129
|
+
: signals;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Computes the dir_tree_v1 identity of a set of loaded extension modules: per-module
|
|
133
|
+
* sha256 entry hashes plus a deterministic directory-tree fingerprint over the deduped
|
|
134
|
+
* parent directories of the resolved entries. Pure fs + crypto — never loads code.
|
|
135
|
+
*/
|
|
136
|
+
export function computeExtensionIdentity(modules, opts = {}) {
|
|
137
|
+
const moduleEntries = modules.map((m) => ({
|
|
138
|
+
declared: m.declared,
|
|
139
|
+
resolved: m.resolved,
|
|
140
|
+
entry_hash: sha256Hex(readFileSync(m.resolved)),
|
|
141
|
+
format: m.format,
|
|
142
|
+
}));
|
|
143
|
+
const roots = [...new Set(modules.map((m) => dirname(m.resolved)))].sort();
|
|
144
|
+
const tree = sweepTree(roots);
|
|
145
|
+
const signals = collectSignals(opts.trustRoot);
|
|
146
|
+
return {
|
|
147
|
+
captured_at: opts.capturedAt ?? new Date().toISOString(),
|
|
148
|
+
pid: opts.pid ?? process.pid,
|
|
149
|
+
modules: moduleEntries,
|
|
150
|
+
tree: { roots, rules: DIR_TREE_V1_RULES, ...tree },
|
|
151
|
+
...(signals !== undefined ? { signals } : {}),
|
|
152
|
+
coverage: 'dir_tree_v1',
|
|
153
|
+
...(opts.overrideActive === true ? { override_active: true } : {}),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Builds an identity entry that records a capture/load FAILURE — the failure is itself
|
|
158
|
+
* evidence (WorkflowContextSnapshot.error precedent). Modules/tree are empty placeholders.
|
|
159
|
+
*/
|
|
160
|
+
export function errorExtensionIdentityEntry(message, opts = {}) {
|
|
161
|
+
return {
|
|
162
|
+
captured_at: opts.capturedAt ?? new Date().toISOString(),
|
|
163
|
+
pid: opts.pid ?? process.pid,
|
|
164
|
+
modules: [],
|
|
165
|
+
tree: {
|
|
166
|
+
roots: [],
|
|
167
|
+
rules: DIR_TREE_V1_RULES,
|
|
168
|
+
file_count: 0,
|
|
169
|
+
total_bytes: 0,
|
|
170
|
+
tree_hash: '',
|
|
171
|
+
truncated: false,
|
|
172
|
+
},
|
|
173
|
+
coverage: 'dir_tree_v1',
|
|
174
|
+
...(opts.overrideActive === true ? { override_active: true } : {}),
|
|
175
|
+
error: message,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Recomputes an entry's identity from CURRENT disk state STRICTLY under the entry's
|
|
180
|
+
* RECORDED rules and roots — an unknown rules version yields an explicit cannot-compare
|
|
181
|
+
* rather than a guess (a rules change must never manufacture phantom drift).
|
|
182
|
+
* Pure fs + crypto — never loads code.
|
|
183
|
+
*/
|
|
184
|
+
export function recomputeIdentity(entry, opts = {}) {
|
|
185
|
+
if (entry.tree.rules !== DIR_TREE_V1_RULES) {
|
|
186
|
+
return {
|
|
187
|
+
comparable: false,
|
|
188
|
+
reason: `cannot compare (unknown rules '${entry.tree.rules}')`,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const modules = entry.modules.map((m) => {
|
|
192
|
+
let currentHash;
|
|
193
|
+
try {
|
|
194
|
+
currentHash = sha256Hex(readFileSync(m.resolved));
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
currentHash = undefined;
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
resolved: m.resolved,
|
|
201
|
+
recorded_hash: m.entry_hash,
|
|
202
|
+
...(currentHash !== undefined ? { current_hash: currentHash } : {}),
|
|
203
|
+
};
|
|
204
|
+
});
|
|
205
|
+
const tree = sweepTree(entry.tree.roots);
|
|
206
|
+
const signals = collectSignals(opts.trustRoot);
|
|
207
|
+
return {
|
|
208
|
+
comparable: true,
|
|
209
|
+
modules,
|
|
210
|
+
tree: {
|
|
211
|
+
recorded_hash: entry.tree.tree_hash,
|
|
212
|
+
current_hash: tree.tree_hash,
|
|
213
|
+
current_truncated: tree.truncated,
|
|
214
|
+
},
|
|
215
|
+
...(signals !== undefined ? { signals } : {}),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=extension-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension-identity.js","sourceRoot":"","sources":["../../src/extensions/extension-identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ExtensionRegistry } from '@sensigo/realm';
|
|
2
|
+
import type { ExtensionManifest, WorkflowDefinition } from '@sensigo/realm';
|
|
3
|
+
export interface LoadProjectExtensionsOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Operator-typed module path that REPLACES the workflow's declared extension modules
|
|
6
|
+
* (repair/override tool). Containment does not apply to an operator-typed path.
|
|
7
|
+
*/
|
|
8
|
+
overrideModule?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface LoadedProjectExtensions {
|
|
11
|
+
registry: ExtensionRegistry;
|
|
12
|
+
manifest: ExtensionManifest;
|
|
13
|
+
}
|
|
14
|
+
/** @internal Test-only: clears the process-lifetime registry cache. */
|
|
15
|
+
export declare function clearProjectExtensionsCache(): void;
|
|
16
|
+
/**
|
|
17
|
+
* Loads the project extension modules declared by a workflow definition (or an operator
|
|
18
|
+
* override) and returns a registry (defaults + extensions applied) plus a manifest of what
|
|
19
|
+
* was loaded. No `extensions` on the definition and no override → `createDefaultRegistry()`
|
|
20
|
+
* plus an empty manifest — the byte-identical fallback, cached process-wide.
|
|
21
|
+
*
|
|
22
|
+
* Precedence: defaults < legacy env-gated built-ins (applied by `realm agent`, see agent.ts)
|
|
23
|
+
* < declared extensions < --extensions-module override.
|
|
24
|
+
*
|
|
25
|
+
* CONTRACT: returned registries are shared process-lifetime cache entries. The only
|
|
26
|
+
* permitted mutation is `getOrCreateRateLimiter` (serve bucket persistence, by design);
|
|
27
|
+
* any tier composition on top requires `ExtensionRegistry.clone()`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function loadProjectExtensions(definition: WorkflowDefinition, opts?: LoadProjectExtensionsOptions): Promise<LoadedProjectExtensions>;
|
|
30
|
+
/**
|
|
31
|
+
* Builds a `registryProvider` for the MCP server (serve / mcp stdio): resolves each
|
|
32
|
+
* definition's extensions through the process-lifetime loader cache. An operator override
|
|
33
|
+
* replaces declared modules for EVERY definition served by this process.
|
|
34
|
+
*/
|
|
35
|
+
export declare function makeRegistryProvider(overrideModule?: string): (definition: WorkflowDefinition) => Promise<ExtensionRegistry>;
|
|
36
|
+
//# sourceMappingURL=load-project-extensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-project-extensions.d.ts","sourceRoot":"","sources":["../../src/extensions/load-project-extensions.ts"],"names":[],"mappings":"AAeA,OAAO,EAAyB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAsB,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGhG,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,CAAC;CAC7B;AAiBD,uEAAuE;AACvE,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AA4BD;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,kBAAkB,EAC9B,IAAI,CAAC,EAAE,4BAA4B,GAClC,OAAO,CAAC,uBAAuB,CAAC,CA0ElC;AA4SD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,CAAC,EAAE,MAAM,GACtB,CAAC,UAAU,EAAE,kBAAkB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAQhE"}
|