agy-worker-mcp 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +141 -0
- package/LICENSE +21 -0
- package/README.md +309 -0
- package/commands/agy-ceiling.md +31 -0
- package/dist/broker/blockers.d.ts +86 -0
- package/dist/broker/blockers.d.ts.map +1 -0
- package/dist/broker/blockers.js +390 -0
- package/dist/broker/blockers.js.map +1 -0
- package/dist/broker/outcome.d.ts +85 -0
- package/dist/broker/outcome.d.ts.map +1 -0
- package/dist/broker/outcome.js +147 -0
- package/dist/broker/outcome.js.map +1 -0
- package/dist/broker/reconcile.d.ts +74 -0
- package/dist/broker/reconcile.d.ts.map +1 -0
- package/dist/broker/reconcile.js +415 -0
- package/dist/broker/reconcile.js.map +1 -0
- package/dist/broker/result.d.ts +88 -0
- package/dist/broker/result.d.ts.map +1 -0
- package/dist/broker/result.js +234 -0
- package/dist/broker/result.js.map +1 -0
- package/dist/broker/verify.d.ts +52 -0
- package/dist/broker/verify.d.ts.map +1 -0
- package/dist/broker/verify.js +174 -0
- package/dist/broker/verify.js.map +1 -0
- package/dist/contract/errors.d.ts +119 -0
- package/dist/contract/errors.d.ts.map +1 -0
- package/dist/contract/errors.js +99 -0
- package/dist/contract/errors.js.map +1 -0
- package/dist/contract/index.d.ts +10 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +10 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/paths.d.ts +139 -0
- package/dist/contract/paths.d.ts.map +1 -0
- package/dist/contract/paths.js +359 -0
- package/dist/contract/paths.js.map +1 -0
- package/dist/contract/schema.sql +64 -0
- package/dist/contract/types.d.ts +1113 -0
- package/dist/contract/types.d.ts.map +1 -0
- package/dist/contract/types.js +114 -0
- package/dist/contract/types.js.map +1 -0
- package/dist/events/cursor.d.ts +65 -0
- package/dist/events/cursor.d.ts.map +1 -0
- package/dist/events/cursor.js +286 -0
- package/dist/events/cursor.js.map +1 -0
- package/dist/events/detect.d.ts +58 -0
- package/dist/events/detect.d.ts.map +1 -0
- package/dist/events/detect.js +183 -0
- package/dist/events/detect.js.map +1 -0
- package/dist/events/normalize.d.ts +30 -0
- package/dist/events/normalize.d.ts.map +1 -0
- package/dist/events/normalize.js +158 -0
- package/dist/events/normalize.js.map +1 -0
- package/dist/events/parse.d.ts +41 -0
- package/dist/events/parse.d.ts.map +1 -0
- package/dist/events/parse.js +89 -0
- package/dist/events/parse.js.map +1 -0
- package/dist/gate/bind.d.ts +28 -0
- package/dist/gate/bind.d.ts.map +1 -0
- package/dist/gate/bind.js +154 -0
- package/dist/gate/bind.js.map +1 -0
- package/dist/gate/gate.d.ts +139 -0
- package/dist/gate/gate.d.ts.map +1 -0
- package/dist/gate/gate.js +488 -0
- package/dist/gate/gate.js.map +1 -0
- package/dist/gate/hooks-file.d.ts +55 -0
- package/dist/gate/hooks-file.d.ts.map +1 -0
- package/dist/gate/hooks-file.js +104 -0
- package/dist/gate/hooks-file.js.map +1 -0
- package/dist/gate.d.ts +3 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +20 -0
- package/dist/gate.js.map +1 -0
- package/dist/policy/ceiling-review.d.ts +22 -0
- package/dist/policy/ceiling-review.d.ts.map +1 -0
- package/dist/policy/ceiling-review.js +170 -0
- package/dist/policy/ceiling-review.js.map +1 -0
- package/dist/policy/ceiling.d.ts +128 -0
- package/dist/policy/ceiling.d.ts.map +1 -0
- package/dist/policy/ceiling.js +273 -0
- package/dist/policy/ceiling.js.map +1 -0
- package/dist/policy/containment.d.ts +100 -0
- package/dist/policy/containment.d.ts.map +1 -0
- package/dist/policy/containment.js +1071 -0
- package/dist/policy/containment.js.map +1 -0
- package/dist/policy/hard-deny.d.ts +28 -0
- package/dist/policy/hard-deny.d.ts.map +1 -0
- package/dist/policy/hard-deny.js +78 -0
- package/dist/policy/hard-deny.js.map +1 -0
- package/dist/policy/profiles.d.ts +82 -0
- package/dist/policy/profiles.d.ts.map +1 -0
- package/dist/policy/profiles.js +317 -0
- package/dist/policy/profiles.js.map +1 -0
- package/dist/policy/rules.d.ts +138 -0
- package/dist/policy/rules.d.ts.map +1 -0
- package/dist/policy/rules.js +1180 -0
- package/dist/policy/rules.js.map +1 -0
- package/dist/policy/seatbelt.d.ts +32 -0
- package/dist/policy/seatbelt.d.ts.map +1 -0
- package/dist/policy/seatbelt.js +59 -0
- package/dist/policy/seatbelt.js.map +1 -0
- package/dist/policy/tools.d.ts +36 -0
- package/dist/policy/tools.d.ts.map +1 -0
- package/dist/policy/tools.js +94 -0
- package/dist/policy/tools.js.map +1 -0
- package/dist/runner/gate-watchdog.d.ts +93 -0
- package/dist/runner/gate-watchdog.d.ts.map +1 -0
- package/dist/runner/gate-watchdog.js +153 -0
- package/dist/runner/gate-watchdog.js.map +1 -0
- package/dist/runner/idle.d.ts +51 -0
- package/dist/runner/idle.d.ts.map +1 -0
- package/dist/runner/idle.js +81 -0
- package/dist/runner/idle.js.map +1 -0
- package/dist/runner/inbox.d.ts +56 -0
- package/dist/runner/inbox.d.ts.map +1 -0
- package/dist/runner/inbox.js +134 -0
- package/dist/runner/inbox.js.map +1 -0
- package/dist/runner/reap.d.ts +65 -0
- package/dist/runner/reap.d.ts.map +1 -0
- package/dist/runner/reap.js +168 -0
- package/dist/runner/reap.js.map +1 -0
- package/dist/runner/runner.d.ts +51 -0
- package/dist/runner/runner.d.ts.map +1 -0
- package/dist/runner/runner.js +289 -0
- package/dist/runner/runner.js.map +1 -0
- package/dist/runner/spawn.d.ts +98 -0
- package/dist/runner/spawn.d.ts.map +1 -0
- package/dist/runner/spawn.js +230 -0
- package/dist/runner/spawn.js.map +1 -0
- package/dist/runner/verify.d.ts +24 -0
- package/dist/runner/verify.d.ts.map +1 -0
- package/dist/runner/verify.js +108 -0
- package/dist/runner/verify.js.map +1 -0
- package/dist/runner.d.ts +3 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +15 -0
- package/dist/runner.js.map +1 -0
- package/dist/server/context.d.ts +41 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +59 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/instructions.d.ts +13 -0
- package/dist/server/instructions.d.ts.map +1 -0
- package/dist/server/instructions.js +121 -0
- package/dist/server/instructions.js.map +1 -0
- package/dist/server/server.d.ts +20 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +55 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/tools/cancel.d.ts +24 -0
- package/dist/server/tools/cancel.d.ts.map +1 -0
- package/dist/server/tools/cancel.js +59 -0
- package/dist/server/tools/cancel.js.map +1 -0
- package/dist/server/tools/capabilities.d.ts +36 -0
- package/dist/server/tools/capabilities.d.ts.map +1 -0
- package/dist/server/tools/capabilities.js +116 -0
- package/dist/server/tools/capabilities.js.map +1 -0
- package/dist/server/tools/ceiling.d.ts +31 -0
- package/dist/server/tools/ceiling.d.ts.map +1 -0
- package/dist/server/tools/ceiling.js +121 -0
- package/dist/server/tools/ceiling.js.map +1 -0
- package/dist/server/tools/index.d.ts +38 -0
- package/dist/server/tools/index.d.ts.map +1 -0
- package/dist/server/tools/index.js +115 -0
- package/dist/server/tools/index.js.map +1 -0
- package/dist/server/tools/listJobs.d.ts +30 -0
- package/dist/server/tools/listJobs.d.ts.map +1 -0
- package/dist/server/tools/listJobs.js +37 -0
- package/dist/server/tools/listJobs.js.map +1 -0
- package/dist/server/tools/logs.d.ts +31 -0
- package/dist/server/tools/logs.d.ts.map +1 -0
- package/dist/server/tools/logs.js +96 -0
- package/dist/server/tools/logs.js.map +1 -0
- package/dist/server/tools/result.d.ts +32 -0
- package/dist/server/tools/result.d.ts.map +1 -0
- package/dist/server/tools/result.js +95 -0
- package/dist/server/tools/result.js.map +1 -0
- package/dist/server/tools/send.d.ts +37 -0
- package/dist/server/tools/send.d.ts.map +1 -0
- package/dist/server/tools/send.js +71 -0
- package/dist/server/tools/send.js.map +1 -0
- package/dist/server/tools/sessions.d.ts +28 -0
- package/dist/server/tools/sessions.d.ts.map +1 -0
- package/dist/server/tools/sessions.js +54 -0
- package/dist/server/tools/sessions.js.map +1 -0
- package/dist/server/tools/start.d.ts +107 -0
- package/dist/server/tools/start.d.ts.map +1 -0
- package/dist/server/tools/start.js +482 -0
- package/dist/server/tools/start.js.map +1 -0
- package/dist/server/tools/wait.d.ts +29 -0
- package/dist/server/tools/wait.d.ts.map +1 -0
- package/dist/server/tools/wait.js +120 -0
- package/dist/server/tools/wait.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +17 -0
- package/dist/server.js.map +1 -0
- package/dist/setup/install.d.ts +52 -0
- package/dist/setup/install.d.ts.map +1 -0
- package/dist/setup/install.js +108 -0
- package/dist/setup/install.js.map +1 -0
- package/dist/setup.d.ts +3 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +24 -0
- package/dist/setup.js.map +1 -0
- package/dist/store/db.d.ts +49 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +101 -0
- package/dist/store/db.js.map +1 -0
- package/dist/store/jobs.d.ts +45 -0
- package/dist/store/jobs.d.ts.map +1 -0
- package/dist/store/jobs.js +150 -0
- package/dist/store/jobs.js.map +1 -0
- package/dist/store/locks.d.ts +60 -0
- package/dist/store/locks.d.ts.map +1 -0
- package/dist/store/locks.js +172 -0
- package/dist/store/locks.js.map +1 -0
- package/dist/store/sessions.d.ts +37 -0
- package/dist/store/sessions.d.ts.map +1 -0
- package/dist/store/sessions.js +117 -0
- package/dist/store/sessions.js.map +1 -0
- package/dist/trace/digest.d.ts +77 -0
- package/dist/trace/digest.d.ts.map +1 -0
- package/dist/trace/digest.js +481 -0
- package/dist/trace/digest.js.map +1 -0
- package/package.json +68 -0
- package/skills/agy-ceiling/SKILL.md +72 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { BROKER_RESULT_VERSION } from '../contract/types.js';
|
|
2
|
+
import { ValidationError } from '../contract/errors.js';
|
|
3
|
+
import { readJsonIfExists, writeJsonAtomic } from '../contract/paths.js';
|
|
4
|
+
import { normalizeEvent, tailSummary } from '../events/normalize.js';
|
|
5
|
+
import { lastResult } from '../events/parse.js';
|
|
6
|
+
import { blockerFromDenial, blockerFromEnvironmentBlock, blockerFromGateMissing, blockerFromMissingArtifact, countActionable, renderBlocker, } from './blockers.js';
|
|
7
|
+
import { decideOutcome } from './outcome.js';
|
|
8
|
+
import { verifyJob } from './verify.js';
|
|
9
|
+
const DEFAULT_LOG_TAIL_LINES = 40;
|
|
10
|
+
export function buildBrokerResult(store, input) {
|
|
11
|
+
const verification = verifyJob(store, {
|
|
12
|
+
job: input.job,
|
|
13
|
+
events: input.events,
|
|
14
|
+
expectedArtifacts: input.expectedArtifacts,
|
|
15
|
+
cwd: input.job.cwd,
|
|
16
|
+
// Where a captured --json-schema payload actually lands on the wire is
|
|
17
|
+
// unmeasured (see verify.ts checkContract) — nothing to pass through yet.
|
|
18
|
+
structuredOutput: undefined,
|
|
19
|
+
jsonSchemaPath: input.jsonSchemaPath,
|
|
20
|
+
});
|
|
21
|
+
if (input.idleClosedAfterMs !== null) {
|
|
22
|
+
verification.warnings.push(`session closed by idle_timeout_ms (${input.idleClosedAfterMs} ms) with no agy_send after the last turn — resume with agy_start({ session_id })`);
|
|
23
|
+
}
|
|
24
|
+
// I4: fold the gate watchdog's own verdict into the same `blockers` list
|
|
25
|
+
// everything else uses, so `agy_result`'s verification section carries this
|
|
26
|
+
// exactly like any other blocker instead of a special-cased field.
|
|
27
|
+
if (input.gateConfirmed === false) {
|
|
28
|
+
const gateBlocker = blockerFromGateMissing();
|
|
29
|
+
verification.blockers.push(gateBlocker);
|
|
30
|
+
verification.warnings.push(renderBlocker(gateBlocker));
|
|
31
|
+
}
|
|
32
|
+
const agentReport = buildAgentReport(input.events);
|
|
33
|
+
const hadExpectations = input.expectedArtifacts.length > 0 || input.jsonSchemaPath !== null;
|
|
34
|
+
const decision = decideOutcome({
|
|
35
|
+
lifecycle: input.job.lifecycle,
|
|
36
|
+
exitCode: input.exitCode,
|
|
37
|
+
agentStatus: agentReport.status,
|
|
38
|
+
verification,
|
|
39
|
+
timedOut: input.timedOut,
|
|
40
|
+
canceled: input.canceled,
|
|
41
|
+
gateMissing: input.gateConfirmed === false,
|
|
42
|
+
runnerLost: input.runnerLost,
|
|
43
|
+
pidReused: input.pidReused,
|
|
44
|
+
hadExpectations,
|
|
45
|
+
});
|
|
46
|
+
const counts = countEvents(input.events, input.malformedLines);
|
|
47
|
+
const normalized = input.events
|
|
48
|
+
.map((e) => normalizeEvent(e))
|
|
49
|
+
.filter((n) => n !== null);
|
|
50
|
+
const logTail = tailSummary(normalized, DEFAULT_LOG_TAIL_LINES);
|
|
51
|
+
const finishedAt = input.finishedAt ?? input.now;
|
|
52
|
+
const durationMs = input.job.started_at !== null ? Math.max(0, finishedAt - input.job.started_at) : null;
|
|
53
|
+
const brokerSummary = {
|
|
54
|
+
headline: decision.headline,
|
|
55
|
+
outcome: decision.outcome,
|
|
56
|
+
exit_code: input.exitCode,
|
|
57
|
+
duration_ms: durationMs,
|
|
58
|
+
counts,
|
|
59
|
+
log_tail: logTail,
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
schema_version: BROKER_RESULT_VERSION,
|
|
63
|
+
job_id: input.job.job_id,
|
|
64
|
+
session_id: input.job.session_id,
|
|
65
|
+
conversation_id: agentReport.conversation_id,
|
|
66
|
+
lifecycle: 'finished',
|
|
67
|
+
cwd: input.job.cwd,
|
|
68
|
+
profile: input.job.profile,
|
|
69
|
+
session_mode: input.job.session_mode,
|
|
70
|
+
created_at: input.job.created_at,
|
|
71
|
+
started_at: input.job.started_at,
|
|
72
|
+
finished_at: finishedAt,
|
|
73
|
+
agent_report: agentReport,
|
|
74
|
+
broker_summary: brokerSummary,
|
|
75
|
+
verification,
|
|
76
|
+
agent_status: agentReport.status,
|
|
77
|
+
contract_status: decision.contract_status,
|
|
78
|
+
structured_output: null,
|
|
79
|
+
finalized_at: input.now,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function countEvents(events, malformedLines) {
|
|
83
|
+
let steps = 0;
|
|
84
|
+
let toolCalls = 0;
|
|
85
|
+
let toolErrors = 0;
|
|
86
|
+
let turns = 0;
|
|
87
|
+
for (const e of events) {
|
|
88
|
+
if (e.event === 'result') {
|
|
89
|
+
turns++;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (e.event !== 'step_update')
|
|
93
|
+
continue;
|
|
94
|
+
steps++;
|
|
95
|
+
const su = e.step_update;
|
|
96
|
+
if (su.step_type !== 'tool')
|
|
97
|
+
continue;
|
|
98
|
+
if (su.state === 'DONE')
|
|
99
|
+
toolCalls++;
|
|
100
|
+
if (su.state === 'ERROR')
|
|
101
|
+
toolErrors++;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
events: events.length,
|
|
105
|
+
steps,
|
|
106
|
+
tool_calls: toolCalls,
|
|
107
|
+
tool_errors: toolErrors,
|
|
108
|
+
turns,
|
|
109
|
+
malformed_lines: malformedLines,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/** Extract agy's unverified self-report. Quarantined from `broker_summary` on purpose. */
|
|
113
|
+
export function buildAgentReport(events) {
|
|
114
|
+
const r = lastResult(events);
|
|
115
|
+
if (!r) {
|
|
116
|
+
return { status: 'unknown', response: null, error: null, num_turns: null, usage: null, conversation_id: null };
|
|
117
|
+
}
|
|
118
|
+
const status = r.result.status === 'SUCCESS' || r.result.status === 'ERROR' ? r.result.status : 'unknown';
|
|
119
|
+
return {
|
|
120
|
+
status,
|
|
121
|
+
response: r.result.response ?? null,
|
|
122
|
+
error: r.result.error ?? null,
|
|
123
|
+
num_turns: r.result.num_turns ?? null,
|
|
124
|
+
usage: r.result.usage ?? null,
|
|
125
|
+
conversation_id: r.result.conversation_id ?? null,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** Atomic write, so a concurrent reader never sees a half-written result. */
|
|
129
|
+
export function writeBrokerResult(paths, result) {
|
|
130
|
+
writeJsonAtomic(paths.brokerResult, result);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Null when the job has not been finalized yet.
|
|
134
|
+
*
|
|
135
|
+
* A `broker-result.json` written by an older server is migrated in memory
|
|
136
|
+
* (see {@link migrateBrokerResult}) rather than crashing a tool call — job
|
|
137
|
+
* directories outlive an upgrade, and `agy_result` on yesterday's job must keep
|
|
138
|
+
* working. A version we do not know how to read is refused loudly instead of
|
|
139
|
+
* being handed on half-typed.
|
|
140
|
+
*
|
|
141
|
+
* @throws {import('../contract/errors.js').ValidationError} on an unknown version.
|
|
142
|
+
*/
|
|
143
|
+
export function loadBrokerResult(paths) {
|
|
144
|
+
const raw = readJsonIfExists(paths.brokerResult);
|
|
145
|
+
if (raw === null)
|
|
146
|
+
return null;
|
|
147
|
+
return migrateBrokerResult(raw, paths.brokerResult);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Bring a stored result up to {@link BROKER_RESULT_VERSION}.
|
|
151
|
+
*
|
|
152
|
+
* Version 1 kept `verification.permission_denials` and
|
|
153
|
+
* `verification.environment_blocks`; version 2 collapsed those into the single
|
|
154
|
+
* `verification.blockers`; version 3 adds `verification.verify` (PR6,
|
|
155
|
+
* `verify_command`) — always `null` on a migrated file, since no job written
|
|
156
|
+
* before 0.2.0 ever ran a verify command. The version-1 migration runs the
|
|
157
|
+
* same constructors the live path uses, so an old job is judged by exactly
|
|
158
|
+
* today's rules — and nothing in the old records is dropped, since each one is
|
|
159
|
+
* carried in `Blocker.detail`.
|
|
160
|
+
*/
|
|
161
|
+
export function migrateBrokerResult(raw, path) {
|
|
162
|
+
const version = raw.schema_version;
|
|
163
|
+
if (version === BROKER_RESULT_VERSION)
|
|
164
|
+
return raw;
|
|
165
|
+
if (version !== 1 && version !== 2) {
|
|
166
|
+
throw new ValidationError({
|
|
167
|
+
field: `schema_version of ${path}`,
|
|
168
|
+
value: version,
|
|
169
|
+
expected: `a broker-result.json version this server can read (1, 2 or ${BROKER_RESULT_VERSION}) — this file was written by a newer server`,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
let verification;
|
|
173
|
+
if (version === 1) {
|
|
174
|
+
const legacy = raw.verification;
|
|
175
|
+
const artifacts = legacy.expected_artifacts ?? [];
|
|
176
|
+
const blockers = [
|
|
177
|
+
...(legacy.permission_denials ?? []).map(blockerFromDenial),
|
|
178
|
+
...(legacy.environment_blocks ?? []).map((b) => blockerFromEnvironmentBlock(b)),
|
|
179
|
+
...artifacts.filter((a) => !a.exists).map(blockerFromMissingArtifact),
|
|
180
|
+
];
|
|
181
|
+
verification = {
|
|
182
|
+
blockers,
|
|
183
|
+
expected_artifacts: artifacts,
|
|
184
|
+
changed_files: legacy.changed_files ?? [],
|
|
185
|
+
warnings: legacy.warnings ?? [],
|
|
186
|
+
contract_status: legacy.contract_status,
|
|
187
|
+
checked_at: legacy.checked_at,
|
|
188
|
+
verify: null,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// version === 2: everything but `verify` is already in today's shape.
|
|
193
|
+
verification = { ...raw.verification, verify: null };
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
...raw,
|
|
197
|
+
schema_version: BROKER_RESULT_VERSION,
|
|
198
|
+
verification,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Project the judgement packet `agy_wait` returns: counts, warnings, headline,
|
|
203
|
+
* and a short log tail. No lists, no raw response text — those live in
|
|
204
|
+
* `agy_result`.
|
|
205
|
+
*/
|
|
206
|
+
export function projectJudgementPacket(result, opts) {
|
|
207
|
+
const maxLines = opts?.maxLogTailLines;
|
|
208
|
+
const logTail = maxLines !== undefined && maxLines < result.broker_summary.log_tail.length
|
|
209
|
+
? result.broker_summary.log_tail.slice(-maxLines)
|
|
210
|
+
: result.broker_summary.log_tail;
|
|
211
|
+
return {
|
|
212
|
+
job_id: result.job_id,
|
|
213
|
+
lifecycle: result.lifecycle,
|
|
214
|
+
outcome: result.broker_summary.outcome,
|
|
215
|
+
headline: result.broker_summary.headline,
|
|
216
|
+
exit_code: result.broker_summary.exit_code,
|
|
217
|
+
duration_ms: result.broker_summary.duration_ms,
|
|
218
|
+
agent_status: result.agent_status,
|
|
219
|
+
contract_status: result.contract_status,
|
|
220
|
+
counts: {
|
|
221
|
+
// Two numbers instead of four differently-defined ones: how much stood in
|
|
222
|
+
// the way, and how much of it the caller can act on. `headline` names the
|
|
223
|
+
// sources; `agy_result`'s `verification.blockers` has each one in full.
|
|
224
|
+
blockers: result.verification.blockers.length,
|
|
225
|
+
actionable: countActionable(result.verification.blockers),
|
|
226
|
+
tool_errors: result.broker_summary.counts.tool_errors,
|
|
227
|
+
turns: result.broker_summary.counts.turns,
|
|
228
|
+
},
|
|
229
|
+
warnings: result.verification.warnings,
|
|
230
|
+
log_tail: logTail,
|
|
231
|
+
cursor: opts?.cursor ?? 0,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/broker/result.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { AgyEvent, ArtifactCheck, ContractStatus, EffectivePolicy, JobRow, Verification } from '../contract/types.js';
|
|
2
|
+
import type { Store } from '../store/db.js';
|
|
3
|
+
/**
|
|
4
|
+
* Independent checks the broker runs on its own, without asking agy anything.
|
|
5
|
+
*
|
|
6
|
+
* Verification scope: expected-artifact existence, `git status` changed files,
|
|
7
|
+
* and Class 1 / Class 2 denial aggregation. Running arbitrary commands here in
|
|
8
|
+
* the broker is deliberately out — that needs its own allowlist design; PR6's
|
|
9
|
+
* `verify_command` instead runs once, in the *runner*, before this ever sees
|
|
10
|
+
* the job. This module's only job re: that
|
|
11
|
+
* is `readVerifyResult` below, which reads back what the runner already wrote.
|
|
12
|
+
*/
|
|
13
|
+
export interface VerifyInput {
|
|
14
|
+
job: JobRow;
|
|
15
|
+
events: AgyEvent[];
|
|
16
|
+
expectedArtifacts: string[];
|
|
17
|
+
/** Canonical workspace. */
|
|
18
|
+
cwd: string;
|
|
19
|
+
/** Raw structured output, when `--json-schema` was requested. */
|
|
20
|
+
structuredOutput?: unknown;
|
|
21
|
+
jsonSchemaPath?: string | null;
|
|
22
|
+
policy?: EffectivePolicy | null;
|
|
23
|
+
}
|
|
24
|
+
export declare function verifyJob(store: Store, input: VerifyInput): Verification;
|
|
25
|
+
/**
|
|
26
|
+
* Existence and size of each expected artifact.
|
|
27
|
+
*
|
|
28
|
+
* Paths are workspace-relative and containment-checked before use, so a job
|
|
29
|
+
* cannot claim success by writing outside its workspace. A path that escapes the
|
|
30
|
+
* workspace is treated as missing, not as an error — the caller asked for a
|
|
31
|
+
* verifiable fact, and "escaped the sandbox" is not a fact in its favour.
|
|
32
|
+
*/
|
|
33
|
+
export declare function checkExpectedArtifacts(cwd: string, expected: string[]): ArtifactCheck[];
|
|
34
|
+
/**
|
|
35
|
+
* `git status --porcelain` inside the workspace, via an argv array (never a shell
|
|
36
|
+
* string). Empty when the workspace is not a git repo — that is not an error.
|
|
37
|
+
*/
|
|
38
|
+
export declare function changedFiles(cwd: string): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Whether the structured output honoured the requested schema. `not_required`
|
|
41
|
+
* when no schema was asked for; `violated` keeps the raw payload regardless, since
|
|
42
|
+
* a schema miss must never destroy the response.
|
|
43
|
+
*
|
|
44
|
+
* ⚠ agy's actual `--json-schema` failure signalling is unmeasured.
|
|
45
|
+
* This is a conservative, documented placeholder:
|
|
46
|
+
* presence of a non-null payload is treated as satisfying the schema; its
|
|
47
|
+
* absence when one was requested is `unknown` rather than a confident
|
|
48
|
+
* `violated`, since we have no measured evidence of what an actual schema
|
|
49
|
+
* failure looks like on the wire.
|
|
50
|
+
*/
|
|
51
|
+
export declare function checkContract(structuredOutput: unknown, jsonSchemaPath: string | null): ContractStatus;
|
|
52
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/broker/verify.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,QAAQ,EACR,aAAa,EAEb,cAAc,EAEd,eAAe,EACf,MAAM,EACN,YAAY,EAGb,MAAM,sBAAsB,CAAA;AAG7B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAW3C;;;;;;;;;GASG;AAEH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,QAAQ,EAAE,CAAA;IAClB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;CAChC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,GAAG,YAAY,CAmExE;AAgCD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAevF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAwBlD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,gBAAgB,EAAE,OAAO,EACzB,cAAc,EAAE,MAAM,GAAG,IAAI,GAC5B,cAAc,CAIhB"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
3
|
+
import { isAbsolute, join } from 'node:path';
|
|
4
|
+
import { canonicalize, containedOrNull, jobPaths, readJsonIfExists } from '../contract/paths.js';
|
|
5
|
+
import { scanDenials } from '../events/detect.js';
|
|
6
|
+
import { now } from '../store/db.js';
|
|
7
|
+
import { blockerFromDenial, blockerFromEnvironmentBlock, blockerFromMissingArtifact, blockersFromGateLog, ceilingAbsenceWarning, renderBlockers, } from './blockers.js';
|
|
8
|
+
export function verifyJob(store, input) {
|
|
9
|
+
const paths = jobPaths(store.paths, input.job.job_id);
|
|
10
|
+
const policy = input.policy ??
|
|
11
|
+
readJsonIfExists(paths.policy) ??
|
|
12
|
+
readJsonIfExists(paths.effectiveConfig)?.policy ??
|
|
13
|
+
null;
|
|
14
|
+
const denials = scanDenials(input.events);
|
|
15
|
+
const artifacts = checkExpectedArtifacts(input.cwd, input.expectedArtifacts);
|
|
16
|
+
const changed = changedFiles(input.cwd);
|
|
17
|
+
const contractStatus = checkContract(input.structuredOutput, input.jsonSchemaPath ?? null);
|
|
18
|
+
const verify = readVerifyResult(store, input.job.job_id);
|
|
19
|
+
// One list, one vocabulary. Which of these force `outcome: 'blocked'` and
|
|
20
|
+
// which are only reported is decided in `blockers.ts` and nowhere else.
|
|
21
|
+
// A Class 2 signature only means "the sandbox refused" when the job actually
|
|
22
|
+
// ran sandboxed. With `bypass_sandbox: true` there is no sandbox to refuse
|
|
23
|
+
// anything, so the same text is an ordinary command failure (a real EACCES,
|
|
24
|
+
// a network that is really down) — reported as a warning, never a blocker,
|
|
25
|
+
// and never a reason to call the job `blocked`.
|
|
26
|
+
let gateLogBlockers = [];
|
|
27
|
+
if (existsSync(paths.gateLog)) {
|
|
28
|
+
try {
|
|
29
|
+
gateLogBlockers = blockersFromGateLog(readFileSync(paths.gateLog, 'utf8'));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// tolerate missing or unreadable gate log
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// `sandbox` is the 0.3.0 field; a pre-0.3.0 policy file only has bypass_sandbox.
|
|
36
|
+
const ranUnsandboxed = policy ? (policy.sandbox ?? (policy.bypass_sandbox ? 'none' : 'agy')) === 'none' : false;
|
|
37
|
+
const blockers = [
|
|
38
|
+
...denials.permission_denials.map(blockerFromDenial),
|
|
39
|
+
...(ranUnsandboxed ? [] : denials.environment_blocks.map((b) => blockerFromEnvironmentBlock(b, policy))),
|
|
40
|
+
...artifacts.filter((a) => !a.exists).map(blockerFromMissingArtifact),
|
|
41
|
+
...gateLogBlockers,
|
|
42
|
+
];
|
|
43
|
+
const warnings = renderBlockers(blockers);
|
|
44
|
+
// A gate refusal whose remedy is a rule string is exactly what a ceiling
|
|
45
|
+
// would open. Without a ceiling file the agent has no `agy_capabilities`
|
|
46
|
+
// entry to point at, so say it here, once, next to the blocker.
|
|
47
|
+
const ceilingHint = ceilingAbsenceWarning(policy, blockers);
|
|
48
|
+
if (ceilingHint)
|
|
49
|
+
warnings.push(ceilingHint);
|
|
50
|
+
if (ranUnsandboxed) {
|
|
51
|
+
for (const b of denials.environment_blocks) {
|
|
52
|
+
warnings.push(`${b.tool}${b.command ? ` (${b.command})` : ''} printed sandbox signature "${b.signature}", but this job ran with no OS sandbox (sandbox: none), so it is the command's own failure, not a sandbox block: ${b.excerpt}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (contractStatus === 'violated') {
|
|
56
|
+
// Not a blocker: `checkContract` never returns 'violated' on measured
|
|
57
|
+
// evidence (see below), so there is nothing here we could claim to confirm.
|
|
58
|
+
warnings.push('structured output did not honour the requested --json-schema');
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
blockers,
|
|
62
|
+
expected_artifacts: artifacts,
|
|
63
|
+
changed_files: changed,
|
|
64
|
+
warnings,
|
|
65
|
+
contract_status: contractStatus,
|
|
66
|
+
checked_at: now(),
|
|
67
|
+
verify,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* `Verification.verify` (PR6 §6.3): `null` when `jobs/<id>/verify.json` was
|
|
72
|
+
* never written — no `verify_command` was requested, or the job's own
|
|
73
|
+
* deadline killed agy before the runner could get to it (`runner.ts` skips
|
|
74
|
+
* verify entirely when `timedOut === true`). Deliberately re-read from disk
|
|
75
|
+
* rather than threaded through as an extra `VerifyInput` field: `jobPaths` is
|
|
76
|
+
* already the one place that knows where the runner wrote it, and every
|
|
77
|
+
* caller of `verifyJob` already has a `Store` (and so a `ProjectPaths`) in
|
|
78
|
+
* hand.
|
|
79
|
+
*/
|
|
80
|
+
function readVerifyResult(store, jobId) {
|
|
81
|
+
const paths = jobPaths(store.paths, jobId);
|
|
82
|
+
const record = readJsonIfExists(paths.verifyJson);
|
|
83
|
+
if (!record)
|
|
84
|
+
return null;
|
|
85
|
+
return { ...record, output_tail: readOutputTail(paths.verifyLog) };
|
|
86
|
+
}
|
|
87
|
+
/** Last 2 KiB of `verify.log`, byte-accurate; `''` when the file is empty or missing. */
|
|
88
|
+
const OUTPUT_TAIL_BYTES = 2048;
|
|
89
|
+
function readOutputTail(logPath) {
|
|
90
|
+
try {
|
|
91
|
+
const buf = readFileSync(logPath);
|
|
92
|
+
if (buf.length <= OUTPUT_TAIL_BYTES)
|
|
93
|
+
return buf.toString('utf8');
|
|
94
|
+
return buf.subarray(buf.length - OUTPUT_TAIL_BYTES).toString('utf8');
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return '';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Existence and size of each expected artifact.
|
|
102
|
+
*
|
|
103
|
+
* Paths are workspace-relative and containment-checked before use, so a job
|
|
104
|
+
* cannot claim success by writing outside its workspace. A path that escapes the
|
|
105
|
+
* workspace is treated as missing, not as an error — the caller asked for a
|
|
106
|
+
* verifiable fact, and "escaped the sandbox" is not a fact in its favour.
|
|
107
|
+
*/
|
|
108
|
+
export function checkExpectedArtifacts(cwd, expected) {
|
|
109
|
+
const canonicalCwd = canonicalize(cwd);
|
|
110
|
+
return expected.map((rel) => {
|
|
111
|
+
const attempted = isAbsolute(rel) ? rel : join(canonicalCwd, rel);
|
|
112
|
+
const contained = containedOrNull(attempted, [canonicalCwd]);
|
|
113
|
+
if (contained === null) {
|
|
114
|
+
return { path: rel, absolute: canonicalize(attempted), exists: false, size: null };
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const st = statSync(contained);
|
|
118
|
+
return { path: rel, absolute: contained, exists: true, size: st.size };
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return { path: rel, absolute: contained, exists: false, size: null };
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* `git status --porcelain` inside the workspace, via an argv array (never a shell
|
|
127
|
+
* string). Empty when the workspace is not a git repo — that is not an error.
|
|
128
|
+
*/
|
|
129
|
+
export function changedFiles(cwd) {
|
|
130
|
+
try {
|
|
131
|
+
// This call runs inside `finalizeCore`'s `BEGIN IMMEDIATE` transaction,
|
|
132
|
+
// so an unbounded `git status` — blocked on a network
|
|
133
|
+
// FS or an `index.lock` — would hold the SQLite write lock for as long as
|
|
134
|
+
// git hangs. Bounding it here is a minimal mitigation for finding 7;
|
|
135
|
+
// moving this work outside the transaction entirely is the fuller fix and
|
|
136
|
+
// is not done here.
|
|
137
|
+
const out = execFileSync('git', ['status', '--porcelain'], {
|
|
138
|
+
cwd: canonicalize(cwd),
|
|
139
|
+
encoding: 'utf8',
|
|
140
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
141
|
+
timeout: 5000,
|
|
142
|
+
killSignal: 'SIGKILL',
|
|
143
|
+
});
|
|
144
|
+
return out
|
|
145
|
+
.split('\n')
|
|
146
|
+
.map((l) => l.trimEnd())
|
|
147
|
+
.filter((l) => l.length > 0);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Not a git repo, git not installed, or the command failed. None of these
|
|
151
|
+
// are fatal to the job — they just mean nothing to report here.
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Whether the structured output honoured the requested schema. `not_required`
|
|
157
|
+
* when no schema was asked for; `violated` keeps the raw payload regardless, since
|
|
158
|
+
* a schema miss must never destroy the response.
|
|
159
|
+
*
|
|
160
|
+
* ⚠ agy's actual `--json-schema` failure signalling is unmeasured.
|
|
161
|
+
* This is a conservative, documented placeholder:
|
|
162
|
+
* presence of a non-null payload is treated as satisfying the schema; its
|
|
163
|
+
* absence when one was requested is `unknown` rather than a confident
|
|
164
|
+
* `violated`, since we have no measured evidence of what an actual schema
|
|
165
|
+
* failure looks like on the wire.
|
|
166
|
+
*/
|
|
167
|
+
export function checkContract(structuredOutput, jsonSchemaPath) {
|
|
168
|
+
if (!jsonSchemaPath)
|
|
169
|
+
return 'not_required';
|
|
170
|
+
if (structuredOutput === undefined || structuredOutput === null)
|
|
171
|
+
return 'unknown';
|
|
172
|
+
return 'satisfied';
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/broker/verify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured errors. READ-ONLY after Stage 1.
|
|
3
|
+
*
|
|
4
|
+
* Every error carries a machine-readable `detail` so the *calling agent* can
|
|
5
|
+
* repair itself without another round trip: which job holds the lock, which rule
|
|
6
|
+
* string to add, which enum values exist.
|
|
7
|
+
*/
|
|
8
|
+
import type { LockRequestScope, OnDenial, RuleVerb } from './types.js';
|
|
9
|
+
export type ErrorCode = 'LOCK_CONFLICT' | 'POLICY_DENIED' | 'PATH_ESCAPE' | 'JOB_NOT_FOUND' | 'VALIDATION';
|
|
10
|
+
/** Wire shape of any error surfaced through MCP. */
|
|
11
|
+
export interface ErrorEnvelope<D = unknown> {
|
|
12
|
+
error: ErrorCode;
|
|
13
|
+
message: string;
|
|
14
|
+
detail: D;
|
|
15
|
+
/** Concrete next action for the caller. Always present. */
|
|
16
|
+
remedy: string;
|
|
17
|
+
}
|
|
18
|
+
/** Base for everything in this module. `instanceof` works across all subclasses. */
|
|
19
|
+
export declare abstract class AgyWorkerError<D = unknown> extends Error {
|
|
20
|
+
abstract readonly code: ErrorCode;
|
|
21
|
+
readonly detail: D;
|
|
22
|
+
readonly remedy: string;
|
|
23
|
+
protected constructor(message: string, detail: D, remedy: string);
|
|
24
|
+
toJSON(): ErrorEnvelope<D>;
|
|
25
|
+
}
|
|
26
|
+
export declare function isAgyWorkerError(e: unknown): e is AgyWorkerError;
|
|
27
|
+
/** Normalizes anything thrown into an envelope so a tool handler never leaks a stack. */
|
|
28
|
+
export declare function toErrorEnvelope(e: unknown): ErrorEnvelope;
|
|
29
|
+
export interface LockConflictDetail {
|
|
30
|
+
/** `running_limit` means the project-wide concurrency ceiling, not a row. */
|
|
31
|
+
scope: LockRequestScope;
|
|
32
|
+
/** Canonical cwd, session id, or `'*'` for the running limit. */
|
|
33
|
+
key: string;
|
|
34
|
+
/** Whether an existing holder blocked it, or the ceiling did. */
|
|
35
|
+
reason: 'held' | 'limit';
|
|
36
|
+
/** Job currently holding the lock. Null for `reason: 'limit'`. */
|
|
37
|
+
holder_job_id: string | null;
|
|
38
|
+
holder_pid: number | null;
|
|
39
|
+
holder_started_at: number | null;
|
|
40
|
+
acquired_at: number | null;
|
|
41
|
+
/** Every job counted against the ceiling, for `reason: 'limit'`. */
|
|
42
|
+
running_job_ids: string[];
|
|
43
|
+
limit: number | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Losing a lock race is an error, never a silent serialization.
|
|
47
|
+
* The caller decides whether to wait on the holder or pick a different cwd.
|
|
48
|
+
*/
|
|
49
|
+
export declare class LockConflictError extends AgyWorkerError<LockConflictDetail> {
|
|
50
|
+
readonly code: "LOCK_CONFLICT";
|
|
51
|
+
constructor(detail: LockConflictDetail, message?: string);
|
|
52
|
+
}
|
|
53
|
+
export interface PolicyDeniedDetail {
|
|
54
|
+
job_id: string | null;
|
|
55
|
+
profile: string;
|
|
56
|
+
tool: string;
|
|
57
|
+
command: string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Rule string that would have permitted this, e.g. `command(python -m pytest)`.
|
|
60
|
+
* Paste it into the next `agy_start`'s `permissions.allow`.
|
|
61
|
+
*/
|
|
62
|
+
required_rule: string | null;
|
|
63
|
+
/** The deny entry that matched, when the refusal came from a deny list. */
|
|
64
|
+
matched_rule: string | null;
|
|
65
|
+
/** Which stage of the decision order refused. */
|
|
66
|
+
policy: 'unsupported' | 'control' | 'containment' | 'deny_list' | 'profile_allowlist' | 'default';
|
|
67
|
+
/** True when no client request can lift it (hard deny / profile ceiling). */
|
|
68
|
+
immutable: boolean;
|
|
69
|
+
on_denial: OnDenial;
|
|
70
|
+
}
|
|
71
|
+
/** A policy refusal, whether reported by the gate or replayed by the broker. */
|
|
72
|
+
export declare class PolicyDeniedError extends AgyWorkerError<PolicyDeniedDetail> {
|
|
73
|
+
readonly code: "POLICY_DENIED";
|
|
74
|
+
constructor(detail: PolicyDeniedDetail, message?: string);
|
|
75
|
+
}
|
|
76
|
+
export interface PathEscapeDetail {
|
|
77
|
+
/** What the caller supplied. */
|
|
78
|
+
input_path: string;
|
|
79
|
+
/** After realpath + `..` resolution. This is what actually escaped. */
|
|
80
|
+
resolved_path: string;
|
|
81
|
+
/** Whether read or write containment was violated. */
|
|
82
|
+
kind: 'read' | 'write';
|
|
83
|
+
/** Canonical roots that were allowed. */
|
|
84
|
+
roots: string[];
|
|
85
|
+
/** True when a symlink was what carried the path outside. */
|
|
86
|
+
via_symlink: boolean;
|
|
87
|
+
}
|
|
88
|
+
/** Containment failure. Checked *after* realpath, never before (see docs/permissions.md). */
|
|
89
|
+
export declare class PathEscapeError extends AgyWorkerError<PathEscapeDetail> {
|
|
90
|
+
readonly code: "PATH_ESCAPE";
|
|
91
|
+
constructor(detail: PathEscapeDetail, message?: string);
|
|
92
|
+
}
|
|
93
|
+
export interface JobNotFoundDetail {
|
|
94
|
+
job_id: string;
|
|
95
|
+
/** A few recent job ids so the caller can spot a typo without another call. */
|
|
96
|
+
known_recent: string[];
|
|
97
|
+
project_root: string;
|
|
98
|
+
}
|
|
99
|
+
export declare class JobNotFoundError extends AgyWorkerError<JobNotFoundDetail> {
|
|
100
|
+
readonly code: "JOB_NOT_FOUND";
|
|
101
|
+
constructor(detail: JobNotFoundDetail, message?: string);
|
|
102
|
+
}
|
|
103
|
+
export interface ValidationDetail {
|
|
104
|
+
/** Dotted path of the offending input, e.g. `permissions.allow[0]`. */
|
|
105
|
+
field: string;
|
|
106
|
+
/** What arrived. Truncated by the thrower if large. */
|
|
107
|
+
value: unknown;
|
|
108
|
+
/** Human description of what was required. */
|
|
109
|
+
expected: string;
|
|
110
|
+
/** Complete enum when the field is an enum. Lets the caller self-correct. */
|
|
111
|
+
allowed?: string[];
|
|
112
|
+
/** Rule verbs, when the failure was an unparsable permission rule. */
|
|
113
|
+
allowed_verbs?: RuleVerb[];
|
|
114
|
+
}
|
|
115
|
+
export declare class ValidationError extends AgyWorkerError<ValidationDetail> {
|
|
116
|
+
readonly code: "VALIDATION";
|
|
117
|
+
constructor(detail: ValidationDetail, message?: string);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/contract/errors.ts"],"names":[],"mappings":"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"}
|