@pipelex/sdk 0.3.1 → 0.5.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/client.d.ts +120 -9
- package/dist/client.js +170 -16
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +62 -0
- package/dist/errors.js +72 -0
- package/dist/errors.js.map +1 -1
- package/dist/hooks/bundle-gather.d.ts +31 -0
- package/dist/hooks/bundle-gather.js +92 -0
- package/dist/hooks/bundle-gather.js.map +1 -0
- package/dist/hooks/check-core.d.ts +111 -0
- package/dist/hooks/check-core.js +224 -0
- package/dist/hooks/check-core.js.map +1 -0
- package/dist/hooks/claude-mthds-check.d.ts +29 -0
- package/dist/hooks/claude-mthds-check.js +220 -0
- package/dist/hooks/claude-mthds-check.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +178 -13
- package/dist/prepare-inputs.d.ts +54 -0
- package/dist/prepare-inputs.js +178 -0
- package/dist/prepare-inputs.js.map +1 -0
- package/dist/runs.d.ts +72 -1
- package/dist/runs.js.map +1 -1
- package/dist/upload.d.ts +66 -0
- package/dist/upload.js +153 -0
- package/dist/upload.js.map +1 -0
- package/package.json +6 -2
package/dist/errors.d.ts
CHANGED
|
@@ -9,6 +9,68 @@ export { PipelineRequestError };
|
|
|
9
9
|
export declare class ClientAuthenticationError extends Error {
|
|
10
10
|
constructor(message: string);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Base class for every failure raised by input preparation (`uploadFile` /
|
|
14
|
+
* `prepareInputs`). Catch this to handle any preparation failure; catch a
|
|
15
|
+
* subclass to branch on the semantic category. All preparation failures are
|
|
16
|
+
* raised BEFORE any run is created — a run never triggers a hidden upload.
|
|
17
|
+
*/
|
|
18
|
+
export declare class InputPreparationError extends PipelineRequestError {
|
|
19
|
+
constructor(message: string, options?: {
|
|
20
|
+
cause?: unknown;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A local asset could not be turned into bytes: a missing or unreadable path, or
|
|
25
|
+
* a path string in a non-Node runtime (path strings are Node-only). `source` is
|
|
26
|
+
* the offending path.
|
|
27
|
+
*/
|
|
28
|
+
export declare class InvalidLocalSourceError extends InputPreparationError {
|
|
29
|
+
readonly source: string;
|
|
30
|
+
constructor(message: string, source: string, options?: {
|
|
31
|
+
cause?: unknown;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The server refused the asset — most commonly a `413` past the service-defined
|
|
36
|
+
* size cap. The SDK does not impose a client-side cap; it surfaces the server's
|
|
37
|
+
* rejection. `filename` and `status` locate it.
|
|
38
|
+
*/
|
|
39
|
+
export declare class RejectedAssetError extends InputPreparationError {
|
|
40
|
+
readonly filename: string;
|
|
41
|
+
readonly status: number;
|
|
42
|
+
constructor(message: string, filename: string, status: number, options?: {
|
|
43
|
+
cause?: unknown;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The configured deployment does not support upload (no `/v1/upload` route, seen
|
|
48
|
+
* as a `404`). Upload is a hosted Pipelex-product capability even though the SDK
|
|
49
|
+
* can be pointed at other base URLs.
|
|
50
|
+
*/
|
|
51
|
+
export declare class UnsupportedUploadCapabilityError extends InputPreparationError {
|
|
52
|
+
constructor(message: string, options?: {
|
|
53
|
+
cause?: unknown;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/** Upload was not authorized — a `401`/`403` from the upload route. */
|
|
57
|
+
export declare class UploadAuthenticationError extends InputPreparationError {
|
|
58
|
+
readonly status: number;
|
|
59
|
+
constructor(message: string, status: number, options?: {
|
|
60
|
+
cause?: unknown;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A network or server fault reaching the upload route — an unreachable host, a
|
|
65
|
+
* `5xx`, or any other unexpected `upload()` failure. It carries no `status` field
|
|
66
|
+
* of its own: when a `5xx` produced it, the response and its status are reachable
|
|
67
|
+
* on the wrapped `ApiResponseError` via `cause`.
|
|
68
|
+
*/
|
|
69
|
+
export declare class UploadTransportError extends InputPreparationError {
|
|
70
|
+
constructor(message: string, options?: {
|
|
71
|
+
cause?: unknown;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
12
74
|
/**
|
|
13
75
|
* Thrown when the Pipelex API host cannot be reached at all (DNS failure,
|
|
14
76
|
* connection refused, TLS handshake failure, request timeout). The HTTP
|
package/dist/errors.js
CHANGED
|
@@ -11,6 +11,78 @@ export class ClientAuthenticationError extends Error {
|
|
|
11
11
|
this.name = "ClientAuthenticationError";
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Base class for every failure raised by input preparation (`uploadFile` /
|
|
16
|
+
* `prepareInputs`). Catch this to handle any preparation failure; catch a
|
|
17
|
+
* subclass to branch on the semantic category. All preparation failures are
|
|
18
|
+
* raised BEFORE any run is created — a run never triggers a hidden upload.
|
|
19
|
+
*/
|
|
20
|
+
export class InputPreparationError extends PipelineRequestError {
|
|
21
|
+
constructor(message, options) {
|
|
22
|
+
super(message, options);
|
|
23
|
+
this.name = "InputPreparationError";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A local asset could not be turned into bytes: a missing or unreadable path, or
|
|
28
|
+
* a path string in a non-Node runtime (path strings are Node-only). `source` is
|
|
29
|
+
* the offending path.
|
|
30
|
+
*/
|
|
31
|
+
export class InvalidLocalSourceError extends InputPreparationError {
|
|
32
|
+
source;
|
|
33
|
+
constructor(message, source, options) {
|
|
34
|
+
super(message, options);
|
|
35
|
+
this.name = "InvalidLocalSourceError";
|
|
36
|
+
this.source = source;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The server refused the asset — most commonly a `413` past the service-defined
|
|
41
|
+
* size cap. The SDK does not impose a client-side cap; it surfaces the server's
|
|
42
|
+
* rejection. `filename` and `status` locate it.
|
|
43
|
+
*/
|
|
44
|
+
export class RejectedAssetError extends InputPreparationError {
|
|
45
|
+
filename;
|
|
46
|
+
status;
|
|
47
|
+
constructor(message, filename, status, options) {
|
|
48
|
+
super(message, options);
|
|
49
|
+
this.name = "RejectedAssetError";
|
|
50
|
+
this.filename = filename;
|
|
51
|
+
this.status = status;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The configured deployment does not support upload (no `/v1/upload` route, seen
|
|
56
|
+
* as a `404`). Upload is a hosted Pipelex-product capability even though the SDK
|
|
57
|
+
* can be pointed at other base URLs.
|
|
58
|
+
*/
|
|
59
|
+
export class UnsupportedUploadCapabilityError extends InputPreparationError {
|
|
60
|
+
constructor(message, options) {
|
|
61
|
+
super(message, options);
|
|
62
|
+
this.name = "UnsupportedUploadCapabilityError";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Upload was not authorized — a `401`/`403` from the upload route. */
|
|
66
|
+
export class UploadAuthenticationError extends InputPreparationError {
|
|
67
|
+
status;
|
|
68
|
+
constructor(message, status, options) {
|
|
69
|
+
super(message, options);
|
|
70
|
+
this.name = "UploadAuthenticationError";
|
|
71
|
+
this.status = status;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* A network or server fault reaching the upload route — an unreachable host, a
|
|
76
|
+
* `5xx`, or any other unexpected `upload()` failure. It carries no `status` field
|
|
77
|
+
* of its own: when a `5xx` produced it, the response and its status are reachable
|
|
78
|
+
* on the wrapped `ApiResponseError` via `cause`.
|
|
79
|
+
*/
|
|
80
|
+
export class UploadTransportError extends InputPreparationError {
|
|
81
|
+
constructor(message, options) {
|
|
82
|
+
super(message, options);
|
|
83
|
+
this.name = "UploadTransportError";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
14
86
|
/**
|
|
15
87
|
* Thrown when the Pipelex API host cannot be reached at all (DNS failure,
|
|
16
88
|
* connection refused, TLS handshake failure, request timeout). The HTTP
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle gathering for the validate stage: the multi-file set sent to
|
|
3
|
+
* `POST /v1/validate` around an edited `.mthds` file.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors what the plxt-era hook's `-L "$PARENT_DIR/"` did through the Python
|
|
6
|
+
* runtime (`pipelex/libraries/library_utils.py`): a recursive `.mthds` scan of
|
|
7
|
+
* the edited file's parent directory, skipping the runtime's excluded dirs.
|
|
8
|
+
* Capped, because an under-supplied bundle can produce a FALSE invalid verdict
|
|
9
|
+
* (missing cross-file refs) — on overflow the caller must treat validate as
|
|
10
|
+
* unavailable rather than risk a wrong block.
|
|
11
|
+
*/
|
|
12
|
+
import type { MthdsFile } from "../client.js";
|
|
13
|
+
export interface GatherCaps {
|
|
14
|
+
maxFiles: number;
|
|
15
|
+
maxTotalBytes: number;
|
|
16
|
+
}
|
|
17
|
+
export declare const DEFAULT_GATHER_CAPS: GatherCaps;
|
|
18
|
+
export type GatherResult = {
|
|
19
|
+
ok: true;
|
|
20
|
+
files: MthdsFile[];
|
|
21
|
+
} | {
|
|
22
|
+
ok: false;
|
|
23
|
+
reason: "overflow" | "unreadable";
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Gather the `.mthds` files under the edited file's parent directory, the
|
|
27
|
+
* edited file first (absent any `main_pipe`, the server's primary blueprint is
|
|
28
|
+
* the first content — make that the file being edited). Contents are read
|
|
29
|
+
* fresh from disk, so a format write-back is already reflected.
|
|
30
|
+
*/
|
|
31
|
+
export declare function gatherBundle(editedFilePath: string, caps?: GatherCaps): GatherResult;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle gathering for the validate stage: the multi-file set sent to
|
|
3
|
+
* `POST /v1/validate` around an edited `.mthds` file.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors what the plxt-era hook's `-L "$PARENT_DIR/"` did through the Python
|
|
6
|
+
* runtime (`pipelex/libraries/library_utils.py`): a recursive `.mthds` scan of
|
|
7
|
+
* the edited file's parent directory, skipping the runtime's excluded dirs.
|
|
8
|
+
* Capped, because an under-supplied bundle can produce a FALSE invalid verdict
|
|
9
|
+
* (missing cross-file refs) — on overflow the caller must treat validate as
|
|
10
|
+
* unavailable rather than risk a wrong block.
|
|
11
|
+
*/
|
|
12
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
13
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
14
|
+
/** Mirror of pipelex's `scan_config.excluded_dirs` (dot-dirs are skipped wholesale). */
|
|
15
|
+
const EXCLUDED_DIRS = new Set([
|
|
16
|
+
"venv",
|
|
17
|
+
"env",
|
|
18
|
+
"virtualenv",
|
|
19
|
+
"__pycache__",
|
|
20
|
+
"node_modules",
|
|
21
|
+
"results",
|
|
22
|
+
]);
|
|
23
|
+
export const DEFAULT_GATHER_CAPS = {
|
|
24
|
+
maxFiles: 50,
|
|
25
|
+
maxTotalBytes: 2 * 1024 * 1024,
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Recursively collect `.mthds` paths under `dir`. Throws if any directory in
|
|
29
|
+
* the tree can't be read: a silently-skipped subtree would drop cross-file
|
|
30
|
+
* refs and risk a FALSE invalid verdict, so the caller must treat an
|
|
31
|
+
* unreadable scan as `unreadable` (validate unavailable), not as a smaller
|
|
32
|
+
* bundle. The caps guard the opposite failure (over-supply), never this one.
|
|
33
|
+
*/
|
|
34
|
+
function walkMthdsFiles(dir, collected) {
|
|
35
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
36
|
+
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
37
|
+
if (entry.name.startsWith(".") || EXCLUDED_DIRS.has(entry.name)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const full = join(dir, entry.name);
|
|
41
|
+
if (entry.isDirectory()) {
|
|
42
|
+
walkMthdsFiles(full, collected);
|
|
43
|
+
}
|
|
44
|
+
else if (entry.isFile() && entry.name.endsWith(".mthds")) {
|
|
45
|
+
collected.push(full);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Gather the `.mthds` files under the edited file's parent directory, the
|
|
51
|
+
* edited file first (absent any `main_pipe`, the server's primary blueprint is
|
|
52
|
+
* the first content — make that the file being edited). Contents are read
|
|
53
|
+
* fresh from disk, so a format write-back is already reflected.
|
|
54
|
+
*/
|
|
55
|
+
export function gatherBundle(editedFilePath, caps = DEFAULT_GATHER_CAPS) {
|
|
56
|
+
const editedAbs = resolve(editedFilePath);
|
|
57
|
+
const parentDir = dirname(editedAbs);
|
|
58
|
+
const paths = [];
|
|
59
|
+
try {
|
|
60
|
+
walkMthdsFiles(parentDir, paths);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return { ok: false, reason: "unreadable" };
|
|
64
|
+
}
|
|
65
|
+
const ordered = [editedAbs, ...paths.filter((path) => resolve(path) !== editedAbs)];
|
|
66
|
+
if (ordered.length > caps.maxFiles) {
|
|
67
|
+
return { ok: false, reason: "overflow" };
|
|
68
|
+
}
|
|
69
|
+
let totalBytes = 0;
|
|
70
|
+
for (const path of ordered) {
|
|
71
|
+
try {
|
|
72
|
+
totalBytes += statSync(path).size;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return { ok: false, reason: "unreadable" };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (totalBytes > caps.maxTotalBytes) {
|
|
79
|
+
return { ok: false, reason: "overflow" };
|
|
80
|
+
}
|
|
81
|
+
const files = [];
|
|
82
|
+
for (const path of ordered) {
|
|
83
|
+
try {
|
|
84
|
+
files.push({ content: readFileSync(path, "utf-8"), uri: relative(parentDir, path) });
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return { ok: false, reason: "unreadable" };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { ok: true, files };
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=bundle-gather.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle-gather.js","sourceRoot":"","sources":["../../src/hooks/bundle-gather.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine-agnostic core of the `.mthds` PostToolUse hook: the per-stage verdict
|
|
3
|
+
* shapes and the mapping from verdicts to the hook's decision output.
|
|
4
|
+
*
|
|
5
|
+
* The three stages (lint, format, validate) are swappable engines — local WASM
|
|
6
|
+
* today, `client.lint`/`client.format` as the documented fallback, MCP calls
|
|
7
|
+
* later. Nothing in this module knows which engine produced a verdict; it only
|
|
8
|
+
* maps verdict → decision, mirroring the Stage-3 model of the plxt-era hook:
|
|
9
|
+
*
|
|
10
|
+
* - lint diagnostics → BLOCK (agent fixes the file)
|
|
11
|
+
* - validate `is_valid: false` → BLOCK (input-domain by construction: over the
|
|
12
|
+
* API a produced verdict is always a 200; server/config faults are non-2xx =
|
|
13
|
+
* no verdict = unavailable)
|
|
14
|
+
* - validate valid + pending `PipeSignature`s → non-blocking additionalContext
|
|
15
|
+
* - any stage unavailable → fail-open (the other stages' verdicts stand)
|
|
16
|
+
*/
|
|
17
|
+
import type { Diagnostic, ValidationErrorItem } from "../models.js";
|
|
18
|
+
/** Verdict of the local lint stage. `unavailable` = engine failed to load. */
|
|
19
|
+
export type LintStage = {
|
|
20
|
+
status: "clean";
|
|
21
|
+
} | {
|
|
22
|
+
status: "diagnostics";
|
|
23
|
+
diagnostics: Diagnostic[];
|
|
24
|
+
} | {
|
|
25
|
+
status: "unavailable";
|
|
26
|
+
};
|
|
27
|
+
/** Verdict of the networked validate stage. `unavailable` = no verdict could be produced. */
|
|
28
|
+
export type ValidateStage = {
|
|
29
|
+
status: "valid";
|
|
30
|
+
pendingSignatures: string[];
|
|
31
|
+
} | {
|
|
32
|
+
status: "invalid";
|
|
33
|
+
message?: string;
|
|
34
|
+
validationErrors: ValidationErrorItem[];
|
|
35
|
+
renderedMarkdown?: string;
|
|
36
|
+
} | {
|
|
37
|
+
status: "unavailable";
|
|
38
|
+
};
|
|
39
|
+
/** The hook's decision, prior to JSON encoding. */
|
|
40
|
+
export type HookOutcome = {
|
|
41
|
+
kind: "pass";
|
|
42
|
+
} | {
|
|
43
|
+
kind: "block";
|
|
44
|
+
reason: string;
|
|
45
|
+
} | {
|
|
46
|
+
kind: "context";
|
|
47
|
+
context: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Which harness invoked the hook. Claude and Codex share the block /
|
|
51
|
+
* `hookSpecificOutput` stdout protocol; Mistral Vibe speaks
|
|
52
|
+
* deny / `hook_specific_output.additional_context`.
|
|
53
|
+
*/
|
|
54
|
+
export type HookPlatform = "claude" | "codex" | "vibe";
|
|
55
|
+
/**
|
|
56
|
+
* Extract the edited `.mthds` path from the Claude PostToolUse stdin payload;
|
|
57
|
+
* null = not this hook's business (fail open, mirroring the plxt-era hook,
|
|
58
|
+
* which also passed silently on unparseable input).
|
|
59
|
+
*/
|
|
60
|
+
export declare function extractMthdsFilePath(stdinJson: string): string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Extract every distinct `.mthds` path from a Codex PostToolUse(apply_patch)
|
|
63
|
+
* payload. `apply_patch` is Codex's freeform multi-file write tool: the patch
|
|
64
|
+
* envelope rides verbatim in `tool_input.command`, and the touched files are
|
|
65
|
+
* its `*** Update File: / *** Add File: / *** Move to:` headers (`Delete
|
|
66
|
+
* File:` and `Move from:` are skipped — the file no longer exists post-patch).
|
|
67
|
+
* Mirrors `mthds-agent codex hook`'s parser. Paths come back as written in
|
|
68
|
+
* the envelope (usually cwd-relative); the caller resolves and existence-checks.
|
|
69
|
+
*/
|
|
70
|
+
export declare function extractCodexMthdsFiles(stdinJson: string): string[];
|
|
71
|
+
/**
|
|
72
|
+
* Extract the edited `.mthds` path from a Mistral Vibe stable `post_tool`
|
|
73
|
+
* payload, plus the cwd to resolve it against. Only successful tool calls
|
|
74
|
+
* count (`tool_status: "success"`); the path rides in `tool_output.file` /
|
|
75
|
+
* `tool_output.path` / `tool_input.file_path` / `tool_input.path` — the same
|
|
76
|
+
* fallback chain as the plxt-era Vibe hook.
|
|
77
|
+
*/
|
|
78
|
+
export declare function extractVibeMthdsFilePath(stdinJson: string): {
|
|
79
|
+
filePath: string;
|
|
80
|
+
cwd?: string;
|
|
81
|
+
} | null;
|
|
82
|
+
/**
|
|
83
|
+
* Merge per-file outcomes (Codex's `apply_patch` can touch several `.mthds`
|
|
84
|
+
* files in one call) into the single decision the hook emits: any block wins
|
|
85
|
+
* (reasons joined), else contexts are joined, else pass.
|
|
86
|
+
*/
|
|
87
|
+
export declare function mergeOutcomes(outcomes: HookOutcome[]): HookOutcome;
|
|
88
|
+
export declare function truncate(text: string): string;
|
|
89
|
+
/**
|
|
90
|
+
* Map the lint verdict to a decision. Every engine diagnostic is an error by
|
|
91
|
+
* construction (the shared Rust engine emits `severity: "error"` only), so any
|
|
92
|
+
* diagnostic blocks — the same bar as `plxt lint`'s non-zero exit.
|
|
93
|
+
*/
|
|
94
|
+
export declare function decideAfterLint(filePath: string, lint: LintStage): HookOutcome;
|
|
95
|
+
/**
|
|
96
|
+
* Map the validate verdict to a decision.
|
|
97
|
+
*
|
|
98
|
+
* Invalid blocks with the server-rendered Markdown verbatim when present (the
|
|
99
|
+
* workspace's "surface output conventions": the wire is JSON, the agent reads
|
|
100
|
+
* Markdown), falling back to a client-side rendering of `validation_errors[]`.
|
|
101
|
+
* Valid passes, with a non-blocking nudge listing still-unimplemented
|
|
102
|
+
* `PipeSignature`s. Unavailable passes silently — the local lint/format
|
|
103
|
+
* verdicts already applied.
|
|
104
|
+
*/
|
|
105
|
+
export declare function decideAfterValidate(filePath: string, validate: ValidateStage): HookOutcome;
|
|
106
|
+
/**
|
|
107
|
+
* Encode an outcome as the harness's stdout payload. `pass` is empty output;
|
|
108
|
+
* the hook always exits 0. Claude and Codex share the block /
|
|
109
|
+
* `hookSpecificOutput` protocol; Vibe speaks deny / `hook_specific_output`.
|
|
110
|
+
*/
|
|
111
|
+
export declare function encodeOutcome(outcome: HookOutcome, platform?: HookPlatform): string;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine-agnostic core of the `.mthds` PostToolUse hook: the per-stage verdict
|
|
3
|
+
* shapes and the mapping from verdicts to the hook's decision output.
|
|
4
|
+
*
|
|
5
|
+
* The three stages (lint, format, validate) are swappable engines — local WASM
|
|
6
|
+
* today, `client.lint`/`client.format` as the documented fallback, MCP calls
|
|
7
|
+
* later. Nothing in this module knows which engine produced a verdict; it only
|
|
8
|
+
* maps verdict → decision, mirroring the Stage-3 model of the plxt-era hook:
|
|
9
|
+
*
|
|
10
|
+
* - lint diagnostics → BLOCK (agent fixes the file)
|
|
11
|
+
* - validate `is_valid: false` → BLOCK (input-domain by construction: over the
|
|
12
|
+
* API a produced verdict is always a 200; server/config faults are non-2xx =
|
|
13
|
+
* no verdict = unavailable)
|
|
14
|
+
* - validate valid + pending `PipeSignature`s → non-blocking additionalContext
|
|
15
|
+
* - any stage unavailable → fail-open (the other stages' verdicts stand)
|
|
16
|
+
*/
|
|
17
|
+
function parseJsonOrNull(stdinJson) {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(stdinJson);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null; // fail open on unparseable input, mirroring the plxt-era hooks
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Extract the edited `.mthds` path from the Claude PostToolUse stdin payload;
|
|
27
|
+
* null = not this hook's business (fail open, mirroring the plxt-era hook,
|
|
28
|
+
* which also passed silently on unparseable input).
|
|
29
|
+
*/
|
|
30
|
+
export function extractMthdsFilePath(stdinJson) {
|
|
31
|
+
const parsed = parseJsonOrNull(stdinJson);
|
|
32
|
+
const filePath = parsed?.tool_input
|
|
33
|
+
?.file_path;
|
|
34
|
+
if (typeof filePath !== "string" || !filePath.endsWith(".mthds")) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return filePath;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Extract every distinct `.mthds` path from a Codex PostToolUse(apply_patch)
|
|
41
|
+
* payload. `apply_patch` is Codex's freeform multi-file write tool: the patch
|
|
42
|
+
* envelope rides verbatim in `tool_input.command`, and the touched files are
|
|
43
|
+
* its `*** Update File: / *** Add File: / *** Move to:` headers (`Delete
|
|
44
|
+
* File:` and `Move from:` are skipped — the file no longer exists post-patch).
|
|
45
|
+
* Mirrors `mthds-agent codex hook`'s parser. Paths come back as written in
|
|
46
|
+
* the envelope (usually cwd-relative); the caller resolves and existence-checks.
|
|
47
|
+
*/
|
|
48
|
+
export function extractCodexMthdsFiles(stdinJson) {
|
|
49
|
+
const parsed = parseJsonOrNull(stdinJson);
|
|
50
|
+
const command = parsed?.tool_input?.command;
|
|
51
|
+
if (typeof command !== "string") {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
const headerRe = /^\*\*\* (?:Update File|Add File|Move to):\s*(.+\.mthds)\s*$/gm;
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
let match;
|
|
57
|
+
while ((match = headerRe.exec(command)) !== null) {
|
|
58
|
+
seen.add(match[1].trim());
|
|
59
|
+
}
|
|
60
|
+
return Array.from(seen);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Extract the edited `.mthds` path from a Mistral Vibe stable `post_tool`
|
|
64
|
+
* payload, plus the cwd to resolve it against. Only successful tool calls
|
|
65
|
+
* count (`tool_status: "success"`); the path rides in `tool_output.file` /
|
|
66
|
+
* `tool_output.path` / `tool_input.file_path` / `tool_input.path` — the same
|
|
67
|
+
* fallback chain as the plxt-era Vibe hook.
|
|
68
|
+
*/
|
|
69
|
+
export function extractVibeMthdsFilePath(stdinJson) {
|
|
70
|
+
const parsed = parseJsonOrNull(stdinJson);
|
|
71
|
+
if (!parsed || parsed.tool_status !== "success") {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const candidates = [
|
|
75
|
+
parsed.tool_output?.file,
|
|
76
|
+
parsed.tool_output?.path,
|
|
77
|
+
parsed.tool_input?.file_path,
|
|
78
|
+
parsed.tool_input?.path,
|
|
79
|
+
];
|
|
80
|
+
const filePath = candidates.find((value) => typeof value === "string" && value.endsWith(".mthds"));
|
|
81
|
+
if (!filePath) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return { filePath, cwd: typeof parsed.cwd === "string" ? parsed.cwd : undefined };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Merge per-file outcomes (Codex's `apply_patch` can touch several `.mthds`
|
|
88
|
+
* files in one call) into the single decision the hook emits: any block wins
|
|
89
|
+
* (reasons joined), else contexts are joined, else pass.
|
|
90
|
+
*/
|
|
91
|
+
export function mergeOutcomes(outcomes) {
|
|
92
|
+
const blocks = outcomes.filter((outcome) => outcome.kind === "block");
|
|
93
|
+
if (blocks.length > 0) {
|
|
94
|
+
return { kind: "block", reason: truncate(blocks.map((block) => block.reason).join("\n\n")) };
|
|
95
|
+
}
|
|
96
|
+
const contexts = outcomes.filter((outcome) => outcome.kind === "context");
|
|
97
|
+
if (contexts.length > 0) {
|
|
98
|
+
return {
|
|
99
|
+
kind: "context",
|
|
100
|
+
context: truncate(contexts.map((context) => context.context).join("\n\n")),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return { kind: "pass" };
|
|
104
|
+
}
|
|
105
|
+
/** Cap on emitted reason/context bodies — same guard as the plxt-era hook. */
|
|
106
|
+
const MAX_OUTPUT_CHARS = 9500;
|
|
107
|
+
export function truncate(text) {
|
|
108
|
+
if (text.length <= MAX_OUTPUT_CHARS) {
|
|
109
|
+
return text;
|
|
110
|
+
}
|
|
111
|
+
const omitted = text.length - MAX_OUTPUT_CHARS;
|
|
112
|
+
return `${text.slice(0, MAX_OUTPUT_CHARS)}\n\n[truncated, ${omitted} chars omitted]`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* One diagnostic as an agent-actionable line: severity, locators, message.
|
|
116
|
+
* `location` and `range` are independent — a schema/semantic diagnostic can name
|
|
117
|
+
* its target (a pipe, a concept) without a byte span, so both render when present.
|
|
118
|
+
*/
|
|
119
|
+
function renderDiagnosticLine(diagnostic) {
|
|
120
|
+
const locators = [
|
|
121
|
+
diagnostic.location,
|
|
122
|
+
diagnostic.range && `line ${diagnostic.range.start_line}, col ${diagnostic.range.start_col}`,
|
|
123
|
+
].filter(Boolean);
|
|
124
|
+
const span = locators.length > 0 ? ` (${locators.join(", ")})` : "";
|
|
125
|
+
return `- [${diagnostic.kind}/${diagnostic.severity}] ${diagnostic.message}${span}`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Map the lint verdict to a decision. Every engine diagnostic is an error by
|
|
129
|
+
* construction (the shared Rust engine emits `severity: "error"` only), so any
|
|
130
|
+
* diagnostic blocks — the same bar as `plxt lint`'s non-zero exit.
|
|
131
|
+
*/
|
|
132
|
+
export function decideAfterLint(filePath, lint) {
|
|
133
|
+
if (lint.status !== "diagnostics" || lint.diagnostics.length === 0) {
|
|
134
|
+
return { kind: "pass" };
|
|
135
|
+
}
|
|
136
|
+
const lines = [
|
|
137
|
+
`MTHDS lint errors in ${filePath}:`,
|
|
138
|
+
"",
|
|
139
|
+
...lint.diagnostics.map(renderDiagnosticLine),
|
|
140
|
+
];
|
|
141
|
+
return { kind: "block", reason: truncate(lines.join("\n")) };
|
|
142
|
+
}
|
|
143
|
+
/** One validation error with its locators — mirror of the plxt-era rendering. */
|
|
144
|
+
function renderValidationErrorLine(item) {
|
|
145
|
+
const locators = [
|
|
146
|
+
item.pipe_code && `pipe ${item.pipe_code}`,
|
|
147
|
+
item.concept_code && `concept ${item.concept_code}`,
|
|
148
|
+
item.field_name && `field ${item.field_name}`,
|
|
149
|
+
item.source && `source ${item.source}`,
|
|
150
|
+
]
|
|
151
|
+
.filter(Boolean)
|
|
152
|
+
.join(", ");
|
|
153
|
+
return `- [${item.category ?? "error"}] ${item.message ?? ""}${locators ? ` (${locators})` : ""}`;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Map the validate verdict to a decision.
|
|
157
|
+
*
|
|
158
|
+
* Invalid blocks with the server-rendered Markdown verbatim when present (the
|
|
159
|
+
* workspace's "surface output conventions": the wire is JSON, the agent reads
|
|
160
|
+
* Markdown), falling back to a client-side rendering of `validation_errors[]`.
|
|
161
|
+
* Valid passes, with a non-blocking nudge listing still-unimplemented
|
|
162
|
+
* `PipeSignature`s. Unavailable passes silently — the local lint/format
|
|
163
|
+
* verdicts already applied.
|
|
164
|
+
*/
|
|
165
|
+
export function decideAfterValidate(filePath, validate) {
|
|
166
|
+
switch (validate.status) {
|
|
167
|
+
case "unavailable":
|
|
168
|
+
return { kind: "pass" };
|
|
169
|
+
case "valid": {
|
|
170
|
+
if (validate.pendingSignatures.length === 0) {
|
|
171
|
+
return { kind: "pass" };
|
|
172
|
+
}
|
|
173
|
+
const context = "Bundle is valid but not yet runnable. Signatures still unimplemented (PipeSignature placeholders): " +
|
|
174
|
+
validate.pendingSignatures.join(", ") +
|
|
175
|
+
". They mock their output on dry-run; implement them before running the method for real.";
|
|
176
|
+
return { kind: "context", context: truncate(context) };
|
|
177
|
+
}
|
|
178
|
+
case "invalid": {
|
|
179
|
+
if (validate.renderedMarkdown) {
|
|
180
|
+
return { kind: "block", reason: truncate(validate.renderedMarkdown) };
|
|
181
|
+
}
|
|
182
|
+
const lines = [
|
|
183
|
+
`Validation failed for ${filePath}:`,
|
|
184
|
+
"",
|
|
185
|
+
validate.message || "Bundle is invalid.",
|
|
186
|
+
];
|
|
187
|
+
if (validate.validationErrors.length > 0) {
|
|
188
|
+
lines.push("");
|
|
189
|
+
lines.push(...validate.validationErrors.map(renderValidationErrorLine));
|
|
190
|
+
}
|
|
191
|
+
return { kind: "block", reason: truncate(lines.join("\n")) };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Encode an outcome as the harness's stdout payload. `pass` is empty output;
|
|
197
|
+
* the hook always exits 0. Claude and Codex share the block /
|
|
198
|
+
* `hookSpecificOutput` protocol; Vibe speaks deny / `hook_specific_output`.
|
|
199
|
+
*/
|
|
200
|
+
export function encodeOutcome(outcome, platform = "claude") {
|
|
201
|
+
switch (outcome.kind) {
|
|
202
|
+
case "pass":
|
|
203
|
+
return "";
|
|
204
|
+
case "block":
|
|
205
|
+
if (platform === "vibe") {
|
|
206
|
+
return JSON.stringify({ decision: "deny", reason: outcome.reason }) + "\n";
|
|
207
|
+
}
|
|
208
|
+
return JSON.stringify({ decision: "block", reason: outcome.reason }) + "\n";
|
|
209
|
+
case "context":
|
|
210
|
+
if (platform === "vibe") {
|
|
211
|
+
return (JSON.stringify({
|
|
212
|
+
decision: "allow",
|
|
213
|
+
hook_specific_output: { additional_context: outcome.context },
|
|
214
|
+
}) + "\n");
|
|
215
|
+
}
|
|
216
|
+
return (JSON.stringify({
|
|
217
|
+
hookSpecificOutput: {
|
|
218
|
+
hookEventName: "PostToolUse",
|
|
219
|
+
additionalContext: outcome.context,
|
|
220
|
+
},
|
|
221
|
+
}) + "\n");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=check-core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-core.js","sourceRoot":"","sources":["../../src/hooks/check-core.ts"],"names":[],"mappings":"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"}
|