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,96 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ValidationError } from '../../contract/errors.js';
|
|
3
|
+
import { jobPaths } from '../../contract/paths.js';
|
|
4
|
+
import { reconcile } from '../../broker/reconcile.js';
|
|
5
|
+
import { readLinesFrom, tailLines } from '../../events/cursor.js';
|
|
6
|
+
import { parseEventLines } from '../../events/parse.js';
|
|
7
|
+
import { formatNormalized, normalizeParsed } from '../../events/normalize.js';
|
|
8
|
+
import { getJob } from '../../store/jobs.js';
|
|
9
|
+
import { loadJobDigest, renderDigest } from '../../trace/digest.js';
|
|
10
|
+
import { errorReply, reply } from '../context.js';
|
|
11
|
+
/**
|
|
12
|
+
* `agy_logs` — read events, normalized lines, or stderr by cursor or tail.
|
|
13
|
+
*
|
|
14
|
+
* MVP-essential rather than a later nicety: with jobs owned by no client, this is
|
|
15
|
+
* the only way a client that did not start a job can see what it is doing
|
|
16
|
+
* (see docs/tools.md).
|
|
17
|
+
*/
|
|
18
|
+
export const logsInput = z.object({
|
|
19
|
+
job_id: z.string(),
|
|
20
|
+
stream: z
|
|
21
|
+
.enum(['events', 'normalized', 'stderr', 'digest'])
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('events = raw NDJSON, normalized = one readable line per meaningful step, digest = execution trace summary, stderr = raw stderr. Defaults to normalized.'),
|
|
24
|
+
after_cursor: z
|
|
25
|
+
.number()
|
|
26
|
+
.int()
|
|
27
|
+
.min(0)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe('Byte offset from a previous call. Mutually exclusive with tail_lines.'),
|
|
30
|
+
tail_lines: z
|
|
31
|
+
.number()
|
|
32
|
+
.int()
|
|
33
|
+
.positive()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('Last N lines. Mutually exclusive with after_cursor.'),
|
|
36
|
+
max_bytes: z.number().int().positive().optional(),
|
|
37
|
+
});
|
|
38
|
+
export async function handleLogs(ctx, input) {
|
|
39
|
+
try {
|
|
40
|
+
await reconcile(ctx.store);
|
|
41
|
+
if (input.stream === 'digest') {
|
|
42
|
+
if (input.after_cursor !== undefined || input.tail_lines !== undefined) {
|
|
43
|
+
throw new ValidationError({
|
|
44
|
+
field: 'stream',
|
|
45
|
+
value: { stream: input.stream, after_cursor: input.after_cursor, tail_lines: input.tail_lines },
|
|
46
|
+
expected: 'stream=digest cannot be used with after_cursor or tail_lines',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const job = getJob(ctx.store, input.job_id);
|
|
50
|
+
const paths = jobPaths(ctx.paths, job.job_id);
|
|
51
|
+
const digest = loadJobDigest(paths.dir, job.cwd);
|
|
52
|
+
return reply({
|
|
53
|
+
job_id: job.job_id,
|
|
54
|
+
stream: 'digest',
|
|
55
|
+
digest,
|
|
56
|
+
text: renderDigest(digest),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (input.after_cursor !== undefined && input.tail_lines !== undefined) {
|
|
60
|
+
throw new ValidationError({
|
|
61
|
+
field: 'after_cursor/tail_lines',
|
|
62
|
+
value: { after_cursor: input.after_cursor, tail_lines: input.tail_lines },
|
|
63
|
+
expected: 'only one of after_cursor or tail_lines, not both',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const job = getJob(ctx.store, input.job_id);
|
|
67
|
+
const paths = jobPaths(ctx.paths, job.job_id);
|
|
68
|
+
const stream = input.stream ?? 'normalized';
|
|
69
|
+
const maxBytes = input.max_bytes ?? ctx.limits.max_response_bytes;
|
|
70
|
+
const sourcePath = stream === 'stderr' ? paths.stderr : paths.events;
|
|
71
|
+
if (input.tail_lines !== undefined) {
|
|
72
|
+
const rawLines = tailLines(sourcePath, input.tail_lines, maxBytes);
|
|
73
|
+
const lines = stream === 'normalized'
|
|
74
|
+
? normalizeParsed(parseEventLines(rawLines)).map(formatNormalized)
|
|
75
|
+
: rawLines;
|
|
76
|
+
return reply({ job_id: job.job_id, stream, lines });
|
|
77
|
+
}
|
|
78
|
+
const cursor = input.after_cursor ?? 0;
|
|
79
|
+
const read = readLinesFrom(sourcePath, cursor, { maxBytes });
|
|
80
|
+
const lines = stream === 'normalized'
|
|
81
|
+
? normalizeParsed(parseEventLines(read.lines, cursor)).map(formatNormalized)
|
|
82
|
+
: read.lines;
|
|
83
|
+
return reply({
|
|
84
|
+
job_id: job.job_id,
|
|
85
|
+
stream,
|
|
86
|
+
lines,
|
|
87
|
+
cursor: read.nextCursor,
|
|
88
|
+
eof: read.eof,
|
|
89
|
+
truncated: read.truncated,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
return errorReply(e);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/server/tools/logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type ToolContext, type ToolReply } from '../context.js';
|
|
3
|
+
/**
|
|
4
|
+
* `agy_result` — the full, paged result of a finished job.
|
|
5
|
+
*
|
|
6
|
+
* This is where the recovery loop lives: `verification.blockers[]` carries one
|
|
7
|
+
* entry per thing that stood in the way, each with `actionable` (can a
|
|
8
|
+
* different `agy_start` lift it) and `remedy` (what to change) — a gate
|
|
9
|
+
* denial's `required_rule` for `permissions.allow`, or the project ceiling's
|
|
10
|
+
* `sandboxed`/`read_roots` for a silent sandbox block that agy reported
|
|
11
|
+
* as SUCCESS. The original record behind each entry is kept verbatim in
|
|
12
|
+
* `detail`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const resultInput: z.ZodObject<{
|
|
15
|
+
job_id: z.ZodString;
|
|
16
|
+
section: z.ZodOptional<z.ZodEnum<["summary", "agent_report", "verification", "response", "all"]>>;
|
|
17
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
job_id: string;
|
|
21
|
+
limit?: number | undefined;
|
|
22
|
+
offset?: number | undefined;
|
|
23
|
+
section?: "summary" | "agent_report" | "verification" | "response" | "all" | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
job_id: string;
|
|
26
|
+
limit?: number | undefined;
|
|
27
|
+
offset?: number | undefined;
|
|
28
|
+
section?: "summary" | "agent_report" | "verification" | "response" | "all" | undefined;
|
|
29
|
+
}>;
|
|
30
|
+
export type ResultInput = z.infer<typeof resultInput>;
|
|
31
|
+
export declare function handleResult(ctx: ToolContext, input: ResultInput): Promise<ToolReply>;
|
|
32
|
+
//# sourceMappingURL=result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../../src/server/tools/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAA;AAEnF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;EAatB,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAerD,wBAAsB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAuD3F"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { jobPaths } from '../../contract/paths.js';
|
|
3
|
+
import { reconcile } from '../../broker/reconcile.js';
|
|
4
|
+
import { loadBrokerResult } from '../../broker/result.js';
|
|
5
|
+
import { getJob } from '../../store/jobs.js';
|
|
6
|
+
import { errorReply, reply } from '../context.js';
|
|
7
|
+
/**
|
|
8
|
+
* `agy_result` — the full, paged result of a finished job.
|
|
9
|
+
*
|
|
10
|
+
* This is where the recovery loop lives: `verification.blockers[]` carries one
|
|
11
|
+
* entry per thing that stood in the way, each with `actionable` (can a
|
|
12
|
+
* different `agy_start` lift it) and `remedy` (what to change) — a gate
|
|
13
|
+
* denial's `required_rule` for `permissions.allow`, or the project ceiling's
|
|
14
|
+
* `sandboxed`/`read_roots` for a silent sandbox block that agy reported
|
|
15
|
+
* as SUCCESS. The original record behind each entry is kept verbatim in
|
|
16
|
+
* `detail`.
|
|
17
|
+
*/
|
|
18
|
+
export const resultInput = z.object({
|
|
19
|
+
job_id: z.string(),
|
|
20
|
+
section: z
|
|
21
|
+
.enum(['summary', 'agent_report', 'verification', 'response', 'all'])
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('Which part to return. Defaults to summary.'),
|
|
24
|
+
offset: z
|
|
25
|
+
.number()
|
|
26
|
+
.int()
|
|
27
|
+
.min(0)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe('Character offset into the "response" section, for paging a long agent response.'),
|
|
30
|
+
limit: z.number().int().positive().optional().describe('Character count for the "response" section.'),
|
|
31
|
+
});
|
|
32
|
+
const DEFAULT_RESPONSE_LIMIT = 8000;
|
|
33
|
+
function pageResponse(text, offset, limit) {
|
|
34
|
+
const full = text ?? '';
|
|
35
|
+
const slice = full.slice(offset, offset + limit);
|
|
36
|
+
return {
|
|
37
|
+
text: slice,
|
|
38
|
+
offset,
|
|
39
|
+
next_offset: offset + slice.length < full.length ? offset + slice.length : null,
|
|
40
|
+
total_length: full.length,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export async function handleResult(ctx, input) {
|
|
44
|
+
try {
|
|
45
|
+
await reconcile(ctx.store);
|
|
46
|
+
const job = getJob(ctx.store, input.job_id);
|
|
47
|
+
if (job.lifecycle !== 'finished') {
|
|
48
|
+
return reply({
|
|
49
|
+
job_id: job.job_id,
|
|
50
|
+
lifecycle: job.lifecycle,
|
|
51
|
+
message: 'job has not finished yet; call agy_wait or retry agy_result later',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const paths = jobPaths(ctx.paths, job.job_id);
|
|
55
|
+
const result = loadBrokerResult(paths);
|
|
56
|
+
if (!result) {
|
|
57
|
+
return reply({
|
|
58
|
+
job_id: job.job_id,
|
|
59
|
+
lifecycle: job.lifecycle,
|
|
60
|
+
message: 'job is finished but broker-result.json is not available yet; retry shortly',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const section = input.section ?? 'summary';
|
|
64
|
+
const offset = input.offset ?? 0;
|
|
65
|
+
const limit = input.limit ?? DEFAULT_RESPONSE_LIMIT;
|
|
66
|
+
if (section === 'summary') {
|
|
67
|
+
return reply({
|
|
68
|
+
job_id: result.job_id,
|
|
69
|
+
session_id: result.session_id,
|
|
70
|
+
lifecycle: result.lifecycle,
|
|
71
|
+
broker_summary: result.broker_summary,
|
|
72
|
+
agent_status: result.agent_status,
|
|
73
|
+
contract_status: result.contract_status,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (section === 'agent_report') {
|
|
77
|
+
return reply({ job_id: result.job_id, agent_report: result.agent_report });
|
|
78
|
+
}
|
|
79
|
+
if (section === 'verification') {
|
|
80
|
+
return reply({ job_id: result.job_id, verification: result.verification });
|
|
81
|
+
}
|
|
82
|
+
if (section === 'response') {
|
|
83
|
+
return reply({ job_id: result.job_id, response: pageResponse(result.agent_report.response, offset, limit) });
|
|
84
|
+
}
|
|
85
|
+
// section === 'all'
|
|
86
|
+
return reply({
|
|
87
|
+
...result,
|
|
88
|
+
agent_report: { ...result.agent_report, response: pageResponse(result.agent_report.response, offset, limit) },
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
return errorReply(e);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../../src/server/tools/result.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type ToolContext, type ToolReply } from '../context.js';
|
|
3
|
+
/**
|
|
4
|
+
* `agy_send` — queue a follow-up turn.
|
|
5
|
+
*
|
|
6
|
+
* Appends one line to `jobs/<id>/inbox.jsonl` and returns. It does not touch the
|
|
7
|
+
* process; the runner relays the line to agy's stdin.
|
|
8
|
+
*
|
|
9
|
+
* ⚠ Queued turns only queue. agy finishes the in-flight turn first and there is no
|
|
10
|
+
* way to interrupt or redirect it in print mode.
|
|
11
|
+
*
|
|
12
|
+
* ⚠ Does **not** touch `deadline_at`. The job's
|
|
13
|
+
* hard deadline is fixed once at `agy_start` from `timeout_ms` and this handler
|
|
14
|
+
* never patches it — see the comment on `EffectiveConfig.deadline_at` for why
|
|
15
|
+
* (short version: an ever-pushed-out deadline lets an actively-fed session hold
|
|
16
|
+
* its locks indefinitely, and nothing else would notice since `reconcile` only
|
|
17
|
+
* runs from a tool entry point). Use `idle_timeout_ms` (`agy_start`) if the goal
|
|
18
|
+
* is "end this session promptly once nobody is sending more turns" — that is a
|
|
19
|
+
* different axis (idle vs. total wall-clock) and is enforced by the runner
|
|
20
|
+
* itself, not by anything `agy_send` does here.
|
|
21
|
+
*/
|
|
22
|
+
export declare const sendInput: z.ZodObject<{
|
|
23
|
+
job_id: z.ZodString;
|
|
24
|
+
text: z.ZodOptional<z.ZodString>;
|
|
25
|
+
close: z.ZodOptional<z.ZodBoolean>;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
job_id: string;
|
|
28
|
+
text?: string | undefined;
|
|
29
|
+
close?: boolean | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
job_id: string;
|
|
32
|
+
text?: string | undefined;
|
|
33
|
+
close?: boolean | undefined;
|
|
34
|
+
}>;
|
|
35
|
+
export type SendInput = z.infer<typeof sendInput>;
|
|
36
|
+
export declare function handleSend(ctx: ToolContext, input: SendInput): Promise<ToolReply>;
|
|
37
|
+
//# sourceMappingURL=send.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../../src/server/tools/send.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAA;AAEnF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;EAOpB,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA;AAEjD,wBAAsB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAmCvF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ValidationError } from '../../contract/errors.js';
|
|
3
|
+
import { jobPaths } from '../../contract/paths.js';
|
|
4
|
+
import { reconcile } from '../../broker/reconcile.js';
|
|
5
|
+
import { appendClose, appendUserTurn } from '../../runner/inbox.js';
|
|
6
|
+
import { getJob } from '../../store/jobs.js';
|
|
7
|
+
import { errorReply, reply } from '../context.js';
|
|
8
|
+
/**
|
|
9
|
+
* `agy_send` — queue a follow-up turn.
|
|
10
|
+
*
|
|
11
|
+
* Appends one line to `jobs/<id>/inbox.jsonl` and returns. It does not touch the
|
|
12
|
+
* process; the runner relays the line to agy's stdin.
|
|
13
|
+
*
|
|
14
|
+
* ⚠ Queued turns only queue. agy finishes the in-flight turn first and there is no
|
|
15
|
+
* way to interrupt or redirect it in print mode.
|
|
16
|
+
*
|
|
17
|
+
* ⚠ Does **not** touch `deadline_at`. The job's
|
|
18
|
+
* hard deadline is fixed once at `agy_start` from `timeout_ms` and this handler
|
|
19
|
+
* never patches it — see the comment on `EffectiveConfig.deadline_at` for why
|
|
20
|
+
* (short version: an ever-pushed-out deadline lets an actively-fed session hold
|
|
21
|
+
* its locks indefinitely, and nothing else would notice since `reconcile` only
|
|
22
|
+
* runs from a tool entry point). Use `idle_timeout_ms` (`agy_start`) if the goal
|
|
23
|
+
* is "end this session promptly once nobody is sending more turns" — that is a
|
|
24
|
+
* different axis (idle vs. total wall-clock) and is enforced by the runner
|
|
25
|
+
* itself, not by anything `agy_send` does here.
|
|
26
|
+
*/
|
|
27
|
+
export const sendInput = z.object({
|
|
28
|
+
job_id: z.string(),
|
|
29
|
+
text: z.string().optional().describe('The follow-up turn. Omit when only closing.'),
|
|
30
|
+
close: z
|
|
31
|
+
.boolean()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe('Close stdin after this turn, ending the agy process at EOF.'),
|
|
34
|
+
});
|
|
35
|
+
export async function handleSend(ctx, input) {
|
|
36
|
+
try {
|
|
37
|
+
await reconcile(ctx.store);
|
|
38
|
+
const job = getJob(ctx.store, input.job_id);
|
|
39
|
+
if (!input.text && !input.close) {
|
|
40
|
+
throw new ValidationError({
|
|
41
|
+
field: 'text/close',
|
|
42
|
+
value: input,
|
|
43
|
+
expected: 'at least one of "text" or "close: true"',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (job.session_mode !== 'session') {
|
|
47
|
+
throw new ValidationError({
|
|
48
|
+
field: 'job_id',
|
|
49
|
+
value: input.job_id,
|
|
50
|
+
expected: 'a job started with session_mode "session" — a "oneshot" job closes stdin after its one turn and cannot accept follow-ups',
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (job.lifecycle === 'finished' || job.lifecycle === 'canceling') {
|
|
54
|
+
throw new ValidationError({
|
|
55
|
+
field: 'job_id',
|
|
56
|
+
value: input.job_id,
|
|
57
|
+
expected: `a job that is still live — job ${job.job_id} is already "${job.lifecycle}"`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
const paths = jobPaths(ctx.paths, job.job_id);
|
|
61
|
+
if (input.text)
|
|
62
|
+
appendUserTurn(paths.inbox, input.text);
|
|
63
|
+
if (input.close)
|
|
64
|
+
appendClose(paths.inbox);
|
|
65
|
+
return reply({ job_id: job.job_id, queued: true, closed: Boolean(input.close) });
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
return errorReply(e);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=send.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.js","sourceRoot":"","sources":["../../../src/server/tools/send.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,KAAK,EAAoC,MAAM,eAAe,CAAA;AAEnF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IACnF,KAAK,EAAE,CAAC;SACL,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CAAC,6DAA6D,CAAC;CAC3E,CAAC,CAAA;AAIF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAgB,EAAE,KAAgB;IACjE,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;QAE3C,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAChC,MAAM,IAAI,eAAe,CAAC;gBACxB,KAAK,EAAE,YAAY;gBACnB,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,yCAAyC;aACpD,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,IAAI,eAAe,CAAC;gBACxB,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,KAAK,CAAC,MAAM;gBACnB,QAAQ,EAAE,0HAA0H;aACrI,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,SAAS,KAAK,UAAU,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAClE,MAAM,IAAI,eAAe,CAAC;gBACxB,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,KAAK,CAAC,MAAM;gBACnB,QAAQ,EAAE,kCAAkC,GAAG,CAAC,MAAM,gBAAgB,GAAG,CAAC,SAAS,GAAG;aACvF,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QAC7C,IAAI,KAAK,CAAC,IAAI;YAAE,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACvD,IAAI,KAAK,CAAC,KAAK;YAAE,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAEzC,OAAO,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IAClF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,UAAU,CAAC,CAAC,CAAC,CAAA;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type ToolContext, type ToolReply } from '../context.js';
|
|
3
|
+
/**
|
|
4
|
+
* `agy_sessions` — list, inspect, or close agy conversations.
|
|
5
|
+
*
|
|
6
|
+
* A session is one agy conversation; a job is one turn. Resume is lossless
|
|
7
|
+
* (`--conversation`), so a finished oneshot job can always be continued later by
|
|
8
|
+
* passing its `session_id` to `agy_start`.
|
|
9
|
+
*/
|
|
10
|
+
export declare const sessionsInput: z.ZodObject<{
|
|
11
|
+
action: z.ZodOptional<z.ZodEnum<["list", "get", "close"]>>;
|
|
12
|
+
session_id: z.ZodOptional<z.ZodString>;
|
|
13
|
+
state: z.ZodOptional<z.ZodEnum<["active", "closed"]>>;
|
|
14
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
state?: "active" | "closed" | undefined;
|
|
17
|
+
limit?: number | undefined;
|
|
18
|
+
session_id?: string | undefined;
|
|
19
|
+
action?: "close" | "list" | "get" | undefined;
|
|
20
|
+
}, {
|
|
21
|
+
state?: "active" | "closed" | undefined;
|
|
22
|
+
limit?: number | undefined;
|
|
23
|
+
session_id?: string | undefined;
|
|
24
|
+
action?: "close" | "list" | "get" | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
export type SessionsInput = z.infer<typeof sessionsInput>;
|
|
27
|
+
export declare function handleSessions(ctx: ToolContext, input: SessionsInput): Promise<ToolReply>;
|
|
28
|
+
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/server/tools/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAA;AAEnF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;EAKxB,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAazD,wBAAsB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CA0B/F"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ValidationError } from '../../contract/errors.js';
|
|
3
|
+
import { reconcile } from '../../broker/reconcile.js';
|
|
4
|
+
import { closeSession, getSession, listSessions } from '../../store/sessions.js';
|
|
5
|
+
import { errorReply, reply } from '../context.js';
|
|
6
|
+
/**
|
|
7
|
+
* `agy_sessions` — list, inspect, or close agy conversations.
|
|
8
|
+
*
|
|
9
|
+
* A session is one agy conversation; a job is one turn. Resume is lossless
|
|
10
|
+
* (`--conversation`), so a finished oneshot job can always be continued later by
|
|
11
|
+
* passing its `session_id` to `agy_start`.
|
|
12
|
+
*/
|
|
13
|
+
export const sessionsInput = z.object({
|
|
14
|
+
action: z.enum(['list', 'get', 'close']).optional().describe('Defaults to list.'),
|
|
15
|
+
session_id: z.string().optional().describe('Required for get and close.'),
|
|
16
|
+
state: z.enum(['active', 'closed']).optional(),
|
|
17
|
+
limit: z.number().int().positive().optional(),
|
|
18
|
+
});
|
|
19
|
+
function requireSessionId(input) {
|
|
20
|
+
if (!input.session_id) {
|
|
21
|
+
throw new ValidationError({
|
|
22
|
+
field: 'session_id',
|
|
23
|
+
value: input.session_id,
|
|
24
|
+
expected: 'a session_id, required for action "get" and "close"',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return input.session_id;
|
|
28
|
+
}
|
|
29
|
+
export async function handleSessions(ctx, input) {
|
|
30
|
+
try {
|
|
31
|
+
await reconcile(ctx.store);
|
|
32
|
+
const action = input.action ?? 'list';
|
|
33
|
+
if (action === 'list') {
|
|
34
|
+
const rows = listSessions(ctx.store, { state: input.state, limit: input.limit });
|
|
35
|
+
return reply({ sessions: rows, count: rows.length });
|
|
36
|
+
}
|
|
37
|
+
if (action === 'get') {
|
|
38
|
+
const sessionId = requireSessionId(input);
|
|
39
|
+
const row = getSession(ctx.store, sessionId);
|
|
40
|
+
if (!row) {
|
|
41
|
+
return errorReply(new Error(`no session "${sessionId}" in project ${ctx.paths.root}`));
|
|
42
|
+
}
|
|
43
|
+
return reply({ session: row });
|
|
44
|
+
}
|
|
45
|
+
// action === 'close'
|
|
46
|
+
const sessionId = requireSessionId(input);
|
|
47
|
+
const row = closeSession(ctx.store, sessionId);
|
|
48
|
+
return reply({ session: row });
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
return errorReply(e);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/server/tools/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAChF,OAAO,EAAE,UAAU,EAAE,KAAK,EAAoC,MAAM,eAAe,CAAA;AAEnF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IACjF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IACzE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC9C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC9C,CAAC,CAAA;AAIF,SAAS,gBAAgB,CAAC,KAAoB;IAC5C,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,IAAI,eAAe,CAAC;YACxB,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,KAAK,CAAC,UAAU;YACvB,QAAQ,EAAE,qDAAqD;SAChE,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,UAAU,CAAA;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAgB,EAAE,KAAoB;IACzE,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,MAAM,CAAA;QAErC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;YAChF,OAAO,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QACtD,CAAC;QAED,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;YACzC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;YAC5C,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAO,UAAU,CAAC,IAAI,KAAK,CAAC,eAAe,SAAS,gBAAgB,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YACxF,CAAC;YACD,OAAO,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAA;QAChC,CAAC;QAED,qBAAqB;QACrB,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;QACzC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QAC9C,OAAO,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAA;IAChC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,UAAU,CAAC,CAAC,CAAC,CAAA;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type ToolContext, type ToolReply } from '../context.js';
|
|
3
|
+
/**
|
|
4
|
+
* `agy_start` — begin a new job and return its `job_id` immediately.
|
|
5
|
+
*
|
|
6
|
+
* Never blocks. The job outlives this server process, so any client connected to
|
|
7
|
+
* the same project can pick it up with `agy_wait` / `agy_logs`.
|
|
8
|
+
*
|
|
9
|
+
* `dry_run: true` resolves everything — argv, policy, locks that *would* be
|
|
10
|
+
* taken — and returns the `EffectiveConfig` without spawning. Settling
|
|
11
|
+
* configuration this way costs no agy quota.
|
|
12
|
+
*/
|
|
13
|
+
export declare const startInput: z.ZodObject<{
|
|
14
|
+
prompt: z.ZodString;
|
|
15
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
16
|
+
profile: z.ZodOptional<z.ZodEnum<["research_readonly", "general_worker"]>>;
|
|
17
|
+
model: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
18
|
+
effort: z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>;
|
|
19
|
+
mode: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
20
|
+
session_id: z.ZodOptional<z.ZodString>;
|
|
21
|
+
session_mode: z.ZodOptional<z.ZodEnum<["oneshot", "session"]>>;
|
|
22
|
+
permissions: z.ZodOptional<z.ZodObject<{
|
|
23
|
+
allow: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
24
|
+
deny: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
25
|
+
sandboxed: z.ZodOptional<z.ZodBoolean>;
|
|
26
|
+
read_roots: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
27
|
+
}, "strip", z.ZodTypeAny, {
|
|
28
|
+
deny?: string[] | undefined;
|
|
29
|
+
allow?: string[] | undefined;
|
|
30
|
+
read_roots?: string[] | undefined;
|
|
31
|
+
sandboxed?: boolean | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
deny?: string[] | undefined;
|
|
34
|
+
allow?: string[] | undefined;
|
|
35
|
+
read_roots?: string[] | undefined;
|
|
36
|
+
sandboxed?: boolean | undefined;
|
|
37
|
+
}>>;
|
|
38
|
+
on_denial: z.ZodOptional<z.ZodEnum<["abort", "continue", "guide"]>>;
|
|
39
|
+
max_denials: z.ZodOptional<z.ZodNumber>;
|
|
40
|
+
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
idle_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
42
|
+
expected_artifacts: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
43
|
+
json_schema: z.ZodOptional<z.ZodString>;
|
|
44
|
+
verify_command: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
45
|
+
verify_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
46
|
+
requested_by: z.ZodOptional<z.ZodString>;
|
|
47
|
+
parent_task_id: z.ZodOptional<z.ZodString>;
|
|
48
|
+
dry_run: z.ZodOptional<z.ZodBoolean>;
|
|
49
|
+
expected_commands: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
50
|
+
}, "strip", z.ZodTypeAny, {
|
|
51
|
+
prompt: string;
|
|
52
|
+
cwd?: string | undefined;
|
|
53
|
+
profile?: "research_readonly" | "general_worker" | undefined;
|
|
54
|
+
on_denial?: "abort" | "continue" | "guide" | undefined;
|
|
55
|
+
max_denials?: number | undefined;
|
|
56
|
+
mode?: string | undefined;
|
|
57
|
+
session_id?: string | undefined;
|
|
58
|
+
session_mode?: "oneshot" | "session" | undefined;
|
|
59
|
+
requested_by?: string | undefined;
|
|
60
|
+
parent_task_id?: string | undefined;
|
|
61
|
+
model?: string | undefined;
|
|
62
|
+
effort?: "high" | "medium" | "low" | undefined;
|
|
63
|
+
idle_timeout_ms?: number | undefined;
|
|
64
|
+
permissions?: {
|
|
65
|
+
deny?: string[] | undefined;
|
|
66
|
+
allow?: string[] | undefined;
|
|
67
|
+
read_roots?: string[] | undefined;
|
|
68
|
+
sandboxed?: boolean | undefined;
|
|
69
|
+
} | undefined;
|
|
70
|
+
timeout_ms?: number | undefined;
|
|
71
|
+
expected_artifacts?: string[] | undefined;
|
|
72
|
+
json_schema?: string | undefined;
|
|
73
|
+
verify_command?: string | undefined;
|
|
74
|
+
verify_timeout_ms?: number | undefined;
|
|
75
|
+
dry_run?: boolean | undefined;
|
|
76
|
+
expected_commands?: string[] | undefined;
|
|
77
|
+
}, {
|
|
78
|
+
prompt: string;
|
|
79
|
+
cwd?: string | undefined;
|
|
80
|
+
profile?: "research_readonly" | "general_worker" | undefined;
|
|
81
|
+
on_denial?: "abort" | "continue" | "guide" | undefined;
|
|
82
|
+
max_denials?: number | undefined;
|
|
83
|
+
mode?: string | undefined;
|
|
84
|
+
session_id?: string | undefined;
|
|
85
|
+
session_mode?: "oneshot" | "session" | undefined;
|
|
86
|
+
requested_by?: string | undefined;
|
|
87
|
+
parent_task_id?: string | undefined;
|
|
88
|
+
model?: string | undefined;
|
|
89
|
+
effort?: "high" | "medium" | "low" | undefined;
|
|
90
|
+
idle_timeout_ms?: number | undefined;
|
|
91
|
+
permissions?: {
|
|
92
|
+
deny?: string[] | undefined;
|
|
93
|
+
allow?: string[] | undefined;
|
|
94
|
+
read_roots?: string[] | undefined;
|
|
95
|
+
sandboxed?: boolean | undefined;
|
|
96
|
+
} | undefined;
|
|
97
|
+
timeout_ms?: number | undefined;
|
|
98
|
+
expected_artifacts?: string[] | undefined;
|
|
99
|
+
json_schema?: string | undefined;
|
|
100
|
+
verify_command?: string | undefined;
|
|
101
|
+
verify_timeout_ms?: number | undefined;
|
|
102
|
+
dry_run?: boolean | undefined;
|
|
103
|
+
expected_commands?: string[] | undefined;
|
|
104
|
+
}>;
|
|
105
|
+
export type StartInput = z.infer<typeof startInput>;
|
|
106
|
+
export declare function handleStart(ctx: ToolContext, input: StartInput): Promise<ToolReply>;
|
|
107
|
+
//# sourceMappingURL=start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/server/tools/start.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA8BvB,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAA;AAGnF;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0GrB,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA;AASnD,wBAAsB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAoZzF"}
|