agim-cli 1.1.2 → 1.1.4
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 +104 -0
- package/README.md +2 -1
- package/README.zh-CN.md +2 -1
- package/dist/core/a2a.d.ts +19 -0
- package/dist/core/a2a.d.ts.map +1 -1
- package/dist/core/a2a.js +55 -4
- package/dist/core/a2a.js.map +1 -1
- package/dist/core/approval-bus.d.ts.map +1 -1
- package/dist/core/approval-bus.js +19 -0
- package/dist/core/approval-bus.js.map +1 -1
- package/dist/core/artifacts.d.ts +86 -0
- package/dist/core/artifacts.d.ts.map +1 -0
- package/dist/core/artifacts.js +306 -0
- package/dist/core/artifacts.js.map +1 -0
- package/dist/core/commands/a2a.d.ts.map +1 -1
- package/dist/core/commands/a2a.js +19 -5
- package/dist/core/commands/a2a.js.map +1 -1
- package/dist/core/job-board.d.ts +5 -0
- package/dist/core/job-board.d.ts.map +1 -1
- package/dist/core/job-board.js +32 -0
- package/dist/core/job-board.js.map +1 -1
- package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts +27 -2
- package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts.map +1 -1
- package/dist/plugins/agents/claude-code/mcp-approval-server.js +58 -6
- package/dist/plugins/agents/claude-code/mcp-approval-server.js.map +1 -1
- package/dist/web/public/memos.html +71 -15
- package/dist/web/public/reminders.html +89 -15
- package/dist/web/public/tasks.html +555 -8
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +275 -4
- package/dist/web/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
declare function resolveMaxFileBytes(): number;
|
|
2
|
+
declare function resolveMaxJobBytes(): number;
|
|
3
|
+
declare function resolveMaxFiles(): number;
|
|
4
|
+
export interface JobArtifactDirs {
|
|
5
|
+
jobDir: string;
|
|
6
|
+
inputDir: string;
|
|
7
|
+
outputDir: string;
|
|
8
|
+
}
|
|
9
|
+
export type InputSource = {
|
|
10
|
+
name: string;
|
|
11
|
+
fromCallerOutput: string;
|
|
12
|
+
} | {
|
|
13
|
+
name: string;
|
|
14
|
+
fromAbsolutePath: string;
|
|
15
|
+
} | {
|
|
16
|
+
name: string;
|
|
17
|
+
content: string;
|
|
18
|
+
};
|
|
19
|
+
export interface OutputFile {
|
|
20
|
+
name: string;
|
|
21
|
+
bytes: number;
|
|
22
|
+
mtime: string;
|
|
23
|
+
}
|
|
24
|
+
/** Resolve the on-disk dirs for a job. Does NOT create them. Pure path math. */
|
|
25
|
+
export declare function getArtifactsDir(jobId: number): JobArtifactDirs;
|
|
26
|
+
/** Make sure all three dirs exist; idempotent. */
|
|
27
|
+
export declare function ensureArtifactsDir(jobId: number): Promise<JobArtifactDirs>;
|
|
28
|
+
/** Copy the caller-supplied inputs into the callee's _agim-input/.
|
|
29
|
+
* Resolution rules:
|
|
30
|
+
* - `fromAbsolutePath` — copyFile from disk; absolute paths only (reject
|
|
31
|
+
* anything with a relative segment to avoid CWD-dependent surprises).
|
|
32
|
+
* - `fromCallerOutput` — pull from <ROOT>/<callerJobId>/_agim-output/<name>.
|
|
33
|
+
* - `content` — write the string verbatim (UTF-8).
|
|
34
|
+
* All three honor the per-file size cap. After every write the running
|
|
35
|
+
* per-job byte+count totals are re-checked; on overflow we throw + leave
|
|
36
|
+
* the partial state for the caller to inspect on failure.
|
|
37
|
+
* Uses hard links when source/destination share a device — near-zero
|
|
38
|
+
* cost for read-only inputs. Falls back to copy on EXDEV. */
|
|
39
|
+
export declare function copyInputs(jobId: number, inputs: InputSource[], callerJobId?: number): Promise<Array<{
|
|
40
|
+
name: string;
|
|
41
|
+
bytes: number;
|
|
42
|
+
}>>;
|
|
43
|
+
/** List everything the callee left under _agim-output/. */
|
|
44
|
+
export declare function listOutputs(jobId: number): Promise<OutputFile[]>;
|
|
45
|
+
/** Read a single output file (for /a2a tree or future Web UI download). */
|
|
46
|
+
export declare function readOutput(jobId: number, name: string): Promise<Buffer | null>;
|
|
47
|
+
/** Drop the whole <jobId>/ tree. Safe on missing dirs. */
|
|
48
|
+
export declare function pruneArtifacts(jobId: number): Promise<void>;
|
|
49
|
+
/** Drop dirs for every jobId in the given list. Called by job-board's
|
|
50
|
+
* retention sweep with rows it just deleted. */
|
|
51
|
+
export declare function pruneArtifactsBatch(jobIds: number[]): Promise<number>;
|
|
52
|
+
/** Compute per-job totals (used by tests + future /a2a stats extension). */
|
|
53
|
+
export declare function statJob(jobId: number): Promise<{
|
|
54
|
+
files: number;
|
|
55
|
+
bytes: number;
|
|
56
|
+
outputs: OutputFile[];
|
|
57
|
+
inputs: Array<{
|
|
58
|
+
name: string;
|
|
59
|
+
bytes: number;
|
|
60
|
+
}>;
|
|
61
|
+
}>;
|
|
62
|
+
export interface EnvelopeOpts {
|
|
63
|
+
jobId: number;
|
|
64
|
+
inputs: Array<{
|
|
65
|
+
name: string;
|
|
66
|
+
bytes: number;
|
|
67
|
+
}>;
|
|
68
|
+
expectOutputs?: string[];
|
|
69
|
+
}
|
|
70
|
+
/** Build the [A2A workspace] preamble the callee sees prefixed to its
|
|
71
|
+
* prompt. We use a clearly-tagged block so the model treats it as
|
|
72
|
+
* agim metadata and doesn't blur it with the user's intent. */
|
|
73
|
+
export declare function buildEnvelope(opts: EnvelopeOpts): string;
|
|
74
|
+
declare function formatBytes(n: number): string;
|
|
75
|
+
/** Test hook: wipe ALL artifacts. Production code must never call this. */
|
|
76
|
+
export declare function _wipeAllForTests(): Promise<void>;
|
|
77
|
+
/** Internal exports for tests. */
|
|
78
|
+
export declare const _internal: {
|
|
79
|
+
ROOT: string;
|
|
80
|
+
formatBytes: typeof formatBytes;
|
|
81
|
+
resolveMaxFileBytes: typeof resolveMaxFileBytes;
|
|
82
|
+
resolveMaxJobBytes: typeof resolveMaxJobBytes;
|
|
83
|
+
resolveMaxFiles: typeof resolveMaxFiles;
|
|
84
|
+
};
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=artifacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../../src/core/artifacts.ts"],"names":[],"mappings":"AAwCA,iBAAS,mBAAmB,IAAI,MAAM,CAIrC;AACD,iBAAS,kBAAkB,IAAI,MAAM,CAIpC;AACD,iBAAS,eAAe,IAAI,MAAM,CAIjC;AAID,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAErC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAO9D;AAED,kDAAkD;AAClD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAKhF;AAED;;;;;;;;;;8DAU8D;AAC9D,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAiEjD;AAED,2DAA2D;AAC3D,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAgBtE;AAED,2EAA2E;AAC3E,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMpF;AAED,0DAA0D;AAC1D,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjE;AAED;iDACiD;AACjD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ3E;AAED,4EAA4E;AAC5E,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAc7J;AAID,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC9C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CACzB;AAED;;gEAEgE;AAChE,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA0BxD;AAED,iBAAS,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKtC;AAID,2EAA2E;AAC3E,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAEtD;AAED,kCAAkC;AAClC,eAAO,MAAM,SAAS;;;;;;CAMrB,CAAA"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// A2A Layer 2 — shared artifact pool.
|
|
2
|
+
//
|
|
3
|
+
// Each A2A inline job gets a dedicated directory under
|
|
4
|
+
// `~/.agim/artifacts/<jobId>/`, split into:
|
|
5
|
+
//
|
|
6
|
+
// _agim-input/ — files copied here by callAgentByName before the callee
|
|
7
|
+
// runs. Read-only by convention (we don't enforce mode).
|
|
8
|
+
// _agim-output/ — files the callee writes here become visible to the
|
|
9
|
+
// caller in callAgentByName's return value.
|
|
10
|
+
//
|
|
11
|
+
// Lifecycle is bound to the inline-job row: when job-board's retention
|
|
12
|
+
// sweep prunes a row, pruneArtifacts() removes its directory too.
|
|
13
|
+
//
|
|
14
|
+
// Trust model is single-host: every agent runs as the same user, so we
|
|
15
|
+
// don't sandbox file access. We do enforce size + count caps so a runaway
|
|
16
|
+
// callee can't blow up the disk.
|
|
17
|
+
//
|
|
18
|
+
// Why one central tree (~/.agim/artifacts/) instead of per-agent cwd:
|
|
19
|
+
// - callers and callees can use absolute paths consistently
|
|
20
|
+
// - retention sits next to jobs.db and audit.db, easy to back up / wipe
|
|
21
|
+
// - doesn't pollute ~/.agim-workspaces/<agent>/ which is long-term memory
|
|
22
|
+
// - mirrors the file/jobs.db split — workspace cwds are conceptual
|
|
23
|
+
// home directories, artifacts/ is per-call scratch.
|
|
24
|
+
import { mkdir, copyFile, link, readFile, writeFile, readdir, stat, rm } from 'node:fs/promises';
|
|
25
|
+
import { existsSync } from 'node:fs';
|
|
26
|
+
import { join, isAbsolute, dirname, basename } from 'node:path';
|
|
27
|
+
import { logger as rootLogger } from './logger.js';
|
|
28
|
+
import { AGIM_HOME } from './agim-paths.js';
|
|
29
|
+
const log = rootLogger.child({ component: 'a2a.artifacts' });
|
|
30
|
+
const ROOT = join(AGIM_HOME, 'artifacts');
|
|
31
|
+
// ─── env-tunable caps ───────────────────────────────────────────────
|
|
32
|
+
const DEFAULT_MAX_FILE_BYTES = 50 * 1024 * 1024; // 50 MB
|
|
33
|
+
const DEFAULT_MAX_JOB_BYTES = 200 * 1024 * 1024; // 200 MB
|
|
34
|
+
const DEFAULT_MAX_FILES = 200;
|
|
35
|
+
function resolveMaxFileBytes() {
|
|
36
|
+
const raw = process.env.IMHUB_A2A_ARTIFACT_MAX_BYTES_PER_FILE;
|
|
37
|
+
if (raw) {
|
|
38
|
+
const n = parseInt(raw, 10);
|
|
39
|
+
if (Number.isFinite(n) && n > 0)
|
|
40
|
+
return n;
|
|
41
|
+
}
|
|
42
|
+
return DEFAULT_MAX_FILE_BYTES;
|
|
43
|
+
}
|
|
44
|
+
function resolveMaxJobBytes() {
|
|
45
|
+
const raw = process.env.IMHUB_A2A_ARTIFACT_MAX_BYTES_PER_JOB;
|
|
46
|
+
if (raw) {
|
|
47
|
+
const n = parseInt(raw, 10);
|
|
48
|
+
if (Number.isFinite(n) && n > 0)
|
|
49
|
+
return n;
|
|
50
|
+
}
|
|
51
|
+
return DEFAULT_MAX_JOB_BYTES;
|
|
52
|
+
}
|
|
53
|
+
function resolveMaxFiles() {
|
|
54
|
+
const raw = process.env.IMHUB_A2A_ARTIFACT_MAX_FILES_PER_JOB;
|
|
55
|
+
if (raw) {
|
|
56
|
+
const n = parseInt(raw, 10);
|
|
57
|
+
if (Number.isFinite(n) && n > 0)
|
|
58
|
+
return n;
|
|
59
|
+
}
|
|
60
|
+
return DEFAULT_MAX_FILES;
|
|
61
|
+
}
|
|
62
|
+
/** Resolve the on-disk dirs for a job. Does NOT create them. Pure path math. */
|
|
63
|
+
export function getArtifactsDir(jobId) {
|
|
64
|
+
const jobDir = join(ROOT, String(jobId));
|
|
65
|
+
return {
|
|
66
|
+
jobDir,
|
|
67
|
+
inputDir: join(jobDir, '_agim-input'),
|
|
68
|
+
outputDir: join(jobDir, '_agim-output'),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Make sure all three dirs exist; idempotent. */
|
|
72
|
+
export async function ensureArtifactsDir(jobId) {
|
|
73
|
+
const dirs = getArtifactsDir(jobId);
|
|
74
|
+
await mkdir(dirs.inputDir, { recursive: true });
|
|
75
|
+
await mkdir(dirs.outputDir, { recursive: true });
|
|
76
|
+
return dirs;
|
|
77
|
+
}
|
|
78
|
+
/** Copy the caller-supplied inputs into the callee's _agim-input/.
|
|
79
|
+
* Resolution rules:
|
|
80
|
+
* - `fromAbsolutePath` — copyFile from disk; absolute paths only (reject
|
|
81
|
+
* anything with a relative segment to avoid CWD-dependent surprises).
|
|
82
|
+
* - `fromCallerOutput` — pull from <ROOT>/<callerJobId>/_agim-output/<name>.
|
|
83
|
+
* - `content` — write the string verbatim (UTF-8).
|
|
84
|
+
* All three honor the per-file size cap. After every write the running
|
|
85
|
+
* per-job byte+count totals are re-checked; on overflow we throw + leave
|
|
86
|
+
* the partial state for the caller to inspect on failure.
|
|
87
|
+
* Uses hard links when source/destination share a device — near-zero
|
|
88
|
+
* cost for read-only inputs. Falls back to copy on EXDEV. */
|
|
89
|
+
export async function copyInputs(jobId, inputs, callerJobId) {
|
|
90
|
+
if (!inputs.length)
|
|
91
|
+
return [];
|
|
92
|
+
const dirs = await ensureArtifactsDir(jobId);
|
|
93
|
+
const maxFile = resolveMaxFileBytes();
|
|
94
|
+
const maxJob = resolveMaxJobBytes();
|
|
95
|
+
const maxFiles = resolveMaxFiles();
|
|
96
|
+
const written = [];
|
|
97
|
+
let totalBytes = 0;
|
|
98
|
+
for (const inp of inputs) {
|
|
99
|
+
if (written.length >= maxFiles) {
|
|
100
|
+
throw new Error(`artifacts: too many input files (max ${maxFiles})`);
|
|
101
|
+
}
|
|
102
|
+
const inputName = inp.name; // capture for the final 'never' branch
|
|
103
|
+
if (!inputName || inputName.includes('/') || inputName.includes('\\') || inputName === '..') {
|
|
104
|
+
throw new Error(`artifacts: input filename invalid (no slashes / no '..'): ${JSON.stringify(inputName)}`);
|
|
105
|
+
}
|
|
106
|
+
const dest = join(dirs.inputDir, inputName);
|
|
107
|
+
let bytes = 0;
|
|
108
|
+
if ('fromAbsolutePath' in inp) {
|
|
109
|
+
if (!isAbsolute(inp.fromAbsolutePath)) {
|
|
110
|
+
throw new Error(`artifacts: fromAbsolutePath must be absolute: ${inp.fromAbsolutePath}`);
|
|
111
|
+
}
|
|
112
|
+
const st = await stat(inp.fromAbsolutePath);
|
|
113
|
+
if (!st.isFile())
|
|
114
|
+
throw new Error(`artifacts: source not a regular file: ${inp.fromAbsolutePath}`);
|
|
115
|
+
if (st.size > maxFile)
|
|
116
|
+
throw new Error(`artifacts: ${inp.name} exceeds per-file cap (${st.size} > ${maxFile})`);
|
|
117
|
+
bytes = st.size;
|
|
118
|
+
try {
|
|
119
|
+
await link(inp.fromAbsolutePath, dest);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
// EEXIST (file already there from a prior copyInputs of same name)
|
|
123
|
+
// and EXDEV (cross-device) both fall back to plain copy.
|
|
124
|
+
await copyFile(inp.fromAbsolutePath, dest);
|
|
125
|
+
void err;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if ('fromCallerOutput' in inp) {
|
|
129
|
+
if (typeof callerJobId !== 'number' || callerJobId <= 0) {
|
|
130
|
+
throw new Error(`artifacts: fromCallerOutput requires a callerJobId`);
|
|
131
|
+
}
|
|
132
|
+
const callerDirs = getArtifactsDir(callerJobId);
|
|
133
|
+
const src = join(callerDirs.outputDir, inp.fromCallerOutput);
|
|
134
|
+
if (!existsSync(src)) {
|
|
135
|
+
throw new Error(`artifacts: caller output '${inp.fromCallerOutput}' not found (job ${callerJobId})`);
|
|
136
|
+
}
|
|
137
|
+
const st = await stat(src);
|
|
138
|
+
if (st.size > maxFile)
|
|
139
|
+
throw new Error(`artifacts: ${inp.name} exceeds per-file cap (${st.size} > ${maxFile})`);
|
|
140
|
+
bytes = st.size;
|
|
141
|
+
try {
|
|
142
|
+
await link(src, dest);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
await copyFile(src, dest);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else if ('content' in inp) {
|
|
149
|
+
const buf = Buffer.from(inp.content, 'utf-8');
|
|
150
|
+
if (buf.length > maxFile) {
|
|
151
|
+
throw new Error(`artifacts: ${inp.name} content exceeds per-file cap (${buf.length} > ${maxFile})`);
|
|
152
|
+
}
|
|
153
|
+
bytes = buf.length;
|
|
154
|
+
await writeFile(dest, buf);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
throw new Error(`artifacts: input '${inputName}' missing fromAbsolutePath / fromCallerOutput / content`);
|
|
158
|
+
}
|
|
159
|
+
totalBytes += bytes;
|
|
160
|
+
if (totalBytes > maxJob) {
|
|
161
|
+
throw new Error(`artifacts: per-job byte cap exceeded (${totalBytes} > ${maxJob})`);
|
|
162
|
+
}
|
|
163
|
+
written.push({ name: inputName, bytes });
|
|
164
|
+
}
|
|
165
|
+
return written;
|
|
166
|
+
}
|
|
167
|
+
/** List everything the callee left under _agim-output/. */
|
|
168
|
+
export async function listOutputs(jobId) {
|
|
169
|
+
const { outputDir } = getArtifactsDir(jobId);
|
|
170
|
+
if (!existsSync(outputDir))
|
|
171
|
+
return [];
|
|
172
|
+
let names;
|
|
173
|
+
try {
|
|
174
|
+
names = await readdir(outputDir);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
const out = [];
|
|
180
|
+
for (const name of names) {
|
|
181
|
+
try {
|
|
182
|
+
const st = await stat(join(outputDir, name));
|
|
183
|
+
if (st.isFile()) {
|
|
184
|
+
out.push({ name, bytes: st.size, mtime: st.mtime.toISOString() });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch { /* skip transient errors */ }
|
|
188
|
+
}
|
|
189
|
+
out.sort((a, b) => a.name.localeCompare(b.name));
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
/** Read a single output file (for /a2a tree or future Web UI download). */
|
|
193
|
+
export async function readOutput(jobId, name) {
|
|
194
|
+
if (name.includes('/') || name === '..')
|
|
195
|
+
return null;
|
|
196
|
+
const { outputDir } = getArtifactsDir(jobId);
|
|
197
|
+
const p = join(outputDir, name);
|
|
198
|
+
if (!existsSync(p))
|
|
199
|
+
return null;
|
|
200
|
+
try {
|
|
201
|
+
return await readFile(p);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/** Drop the whole <jobId>/ tree. Safe on missing dirs. */
|
|
208
|
+
export async function pruneArtifacts(jobId) {
|
|
209
|
+
const { jobDir } = getArtifactsDir(jobId);
|
|
210
|
+
try {
|
|
211
|
+
await rm(jobDir, { recursive: true, force: true });
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
log.warn({ event: 'artifacts.prune_failed', jobId, err: err instanceof Error ? err.message : String(err) }, `pruneArtifacts(${jobId}) failed`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/** Drop dirs for every jobId in the given list. Called by job-board's
|
|
218
|
+
* retention sweep with rows it just deleted. */
|
|
219
|
+
export async function pruneArtifactsBatch(jobIds) {
|
|
220
|
+
if (!jobIds.length)
|
|
221
|
+
return 0;
|
|
222
|
+
let n = 0;
|
|
223
|
+
for (const id of jobIds) {
|
|
224
|
+
await pruneArtifacts(id);
|
|
225
|
+
n++;
|
|
226
|
+
}
|
|
227
|
+
return n;
|
|
228
|
+
}
|
|
229
|
+
/** Compute per-job totals (used by tests + future /a2a stats extension). */
|
|
230
|
+
export async function statJob(jobId) {
|
|
231
|
+
const dirs = getArtifactsDir(jobId);
|
|
232
|
+
const inputs = [];
|
|
233
|
+
const outputs = await listOutputs(jobId);
|
|
234
|
+
if (existsSync(dirs.inputDir)) {
|
|
235
|
+
for (const name of await readdir(dirs.inputDir)) {
|
|
236
|
+
try {
|
|
237
|
+
const st = await stat(join(dirs.inputDir, name));
|
|
238
|
+
if (st.isFile())
|
|
239
|
+
inputs.push({ name, bytes: st.size });
|
|
240
|
+
}
|
|
241
|
+
catch { /* ignore */ }
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const bytes = inputs.reduce((s, f) => s + f.bytes, 0) + outputs.reduce((s, f) => s + f.bytes, 0);
|
|
245
|
+
return { files: inputs.length + outputs.length, bytes, outputs, inputs };
|
|
246
|
+
}
|
|
247
|
+
/** Build the [A2A workspace] preamble the callee sees prefixed to its
|
|
248
|
+
* prompt. We use a clearly-tagged block so the model treats it as
|
|
249
|
+
* agim metadata and doesn't blur it with the user's intent. */
|
|
250
|
+
export function buildEnvelope(opts) {
|
|
251
|
+
const dirs = getArtifactsDir(opts.jobId);
|
|
252
|
+
const lines = [
|
|
253
|
+
'[A2A workspace]',
|
|
254
|
+
`Your dedicated artifacts directory for this run:`,
|
|
255
|
+
` ${dirs.outputDir}/`,
|
|
256
|
+
'',
|
|
257
|
+
];
|
|
258
|
+
if (opts.inputs.length > 0) {
|
|
259
|
+
lines.push(`Input files placed by the caller (under ${dirs.inputDir}/):`);
|
|
260
|
+
for (const f of opts.inputs) {
|
|
261
|
+
lines.push(` - ${f.name}\t(${formatBytes(f.bytes)})`);
|
|
262
|
+
}
|
|
263
|
+
lines.push(`Read with absolute paths.`);
|
|
264
|
+
lines.push('');
|
|
265
|
+
}
|
|
266
|
+
if (opts.expectOutputs && opts.expectOutputs.length > 0) {
|
|
267
|
+
lines.push(`Expected outputs (place in ${dirs.outputDir}/):`);
|
|
268
|
+
for (const name of opts.expectOutputs)
|
|
269
|
+
lines.push(` - ${name}`);
|
|
270
|
+
lines.push('');
|
|
271
|
+
}
|
|
272
|
+
lines.push(`Anything you write under ${dirs.outputDir}/ will be visible`);
|
|
273
|
+
lines.push(`to the caller after you return.`);
|
|
274
|
+
lines.push('');
|
|
275
|
+
lines.push('---');
|
|
276
|
+
return lines.join('\n');
|
|
277
|
+
}
|
|
278
|
+
function formatBytes(n) {
|
|
279
|
+
if (n < 1024)
|
|
280
|
+
return `${n} B`;
|
|
281
|
+
if (n < 1024 * 1024)
|
|
282
|
+
return `${(n / 1024).toFixed(1)} KB`;
|
|
283
|
+
if (n < 1024 * 1024 * 1024)
|
|
284
|
+
return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
285
|
+
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
286
|
+
}
|
|
287
|
+
// ─── test-only ──────────────────────────────────────────────────────
|
|
288
|
+
/** Test hook: wipe ALL artifacts. Production code must never call this. */
|
|
289
|
+
export async function _wipeAllForTests() {
|
|
290
|
+
try {
|
|
291
|
+
await rm(ROOT, { recursive: true, force: true });
|
|
292
|
+
}
|
|
293
|
+
catch { /* ignore */ }
|
|
294
|
+
}
|
|
295
|
+
/** Internal exports for tests. */
|
|
296
|
+
export const _internal = {
|
|
297
|
+
ROOT,
|
|
298
|
+
formatBytes,
|
|
299
|
+
resolveMaxFileBytes,
|
|
300
|
+
resolveMaxJobBytes,
|
|
301
|
+
resolveMaxFiles,
|
|
302
|
+
};
|
|
303
|
+
// Reference unused-by-design helpers so eslint / tsc-noUnused don't whine.
|
|
304
|
+
void dirname;
|
|
305
|
+
void basename;
|
|
306
|
+
//# sourceMappingURL=artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../src/core/artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a2a.d.ts","sourceRoot":"","sources":["../../../src/core/commands/a2a.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"a2a.d.ts","sourceRoot":"","sources":["../../../src/core/commands/a2a.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAkJhD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,MAAM,CAAC,CAmCjB"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { join } from 'node:path';
|
|
12
12
|
import { logger as rootLogger } from '../logger.js';
|
|
13
13
|
import { AGIM_HOME } from '../agim-paths.js';
|
|
14
|
+
import { listOutputs } from '../artifacts.js';
|
|
14
15
|
const log = rootLogger.child({ component: 'cmd.a2a' });
|
|
15
16
|
/** Open a read-only handle. /a2a is a viewer — we don't want to take the
|
|
16
17
|
* same connection job-board.ts uses for writes. better-sqlite3 supports
|
|
@@ -78,14 +79,14 @@ function fmtRecent(d, n) {
|
|
|
78
79
|
}
|
|
79
80
|
return lines.join('\n');
|
|
80
81
|
}
|
|
81
|
-
function fmtTree(d, rootId) {
|
|
82
|
+
async function fmtTree(d, rootId) {
|
|
82
83
|
const root = d.prepare(`SELECT * FROM jobs WHERE id = ?`).get(rootId);
|
|
83
84
|
if (!root)
|
|
84
85
|
return `❌ 未找到 jobs #${rootId}。`;
|
|
85
86
|
// Walk down (children of rootId, grandchildren, ...).
|
|
86
87
|
const lines = [];
|
|
87
88
|
const visited = new Set();
|
|
88
|
-
function walk(id, depth) {
|
|
89
|
+
async function walk(id, depth) {
|
|
89
90
|
if (visited.has(id) || depth > 10)
|
|
90
91
|
return;
|
|
91
92
|
visited.add(id);
|
|
@@ -98,13 +99,26 @@ function fmtTree(d, rootId) {
|
|
|
98
99
|
row.status === 'running' ? '🔄' : '⏳';
|
|
99
100
|
const preview = row.prompt.replace(/\n/g, ' ').slice(0, 60);
|
|
100
101
|
lines.push(`${indent}${icon} #${row.id} ${row.agent} [${row.status}] ${preview}${row.prompt.length > 60 ? '…' : ''}`);
|
|
102
|
+
// L2 — show output files alongside the row. Cheap fs hit; tree is a
|
|
103
|
+
// diagnostic command, not on the hot path.
|
|
104
|
+
const outs = await listOutputs(row.id);
|
|
105
|
+
for (const f of outs) {
|
|
106
|
+
lines.push(`${indent} 📎 ${f.name} (${fmtBytes(f.bytes)})`);
|
|
107
|
+
}
|
|
101
108
|
const children = d.prepare(`SELECT id FROM jobs WHERE parent_id = ? ORDER BY id`).all(id);
|
|
102
109
|
for (const c of children)
|
|
103
|
-
walk(c.id, depth + 1);
|
|
110
|
+
await walk(c.id, depth + 1);
|
|
104
111
|
}
|
|
105
|
-
walk(rootId, 0);
|
|
112
|
+
await walk(rootId, 0);
|
|
106
113
|
return [`🌳 A2A 调用树 (root #${rootId}):`, '', ...lines].join('\n');
|
|
107
114
|
}
|
|
115
|
+
function fmtBytes(n) {
|
|
116
|
+
if (n < 1024)
|
|
117
|
+
return `${n} B`;
|
|
118
|
+
if (n < 1024 * 1024)
|
|
119
|
+
return `${(n / 1024).toFixed(1)} KB`;
|
|
120
|
+
return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
121
|
+
}
|
|
108
122
|
export async function handleA2ACommand(args, _ctx) {
|
|
109
123
|
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
110
124
|
const sub = parts[0] || 'stats';
|
|
@@ -128,7 +142,7 @@ export async function handleA2ACommand(args, _ctx) {
|
|
|
128
142
|
const id = parseInt(parts[1] || '', 10);
|
|
129
143
|
if (!Number.isFinite(id) || id <= 0)
|
|
130
144
|
return '用法: /a2a tree <id>';
|
|
131
|
-
return fmtTree(d, id);
|
|
145
|
+
return await fmtTree(d, id);
|
|
132
146
|
}
|
|
133
147
|
default:
|
|
134
148
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a2a.js","sourceRoot":"","sources":["../../../src/core/commands/a2a.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,eAAe;AACf,sCAAsC;AACtC,0DAA0D;AAC1D,sCAAsC;AACtC,iFAAiF;AACjF,EAAE;AACF,uEAAuE;AACvE,gCAAgC;AAIhC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"a2a.js","sourceRoot":"","sources":["../../../src/core/commands/a2a.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,eAAe;AACf,sCAAsC;AACtC,0DAA0D;AAC1D,sCAAsC;AACtC,iFAAiF;AACjF,EAAE;AACF,uEAAuE;AACvE,gCAAgC;AAIhC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAA;AAetD;;uDAEuD;AACvD,SAAS,YAAY;IACnB,IAAI,CAAC;QACH,iEAAiE;QACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAoC,CAAA;QAC7E,MAAM,CAAC,GAAG,IAAK,QAAgG,CAC7G,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAC1B,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CACxC,CAAA;QACD,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA;QAC9B,OAAO,CAAC,CAAA;IACV,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,2BAA2B,CAAC,CAAA;QACjG,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,CAAoB;IACpC,2BAA2B;IAC3B,iEAAiE;IACjE,gCAAgC;IAChC,MAAM,KAAK,GAAI,CAAC,CAAC,OAAO,CACtB,8EAA8E,CAC/E,CAAC,GAAG,EAAoB,CAAC,CAAC,CAAA;IAC3B,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,cAAc,CAAA;IACvB,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,CACxB,sGAAsG,CACvG,CAAC,GAAG,EAA0C,CAAA;IAC/C,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CACvB,4HAA4H,CAC7H,CAAC,GAAG,EAAyC,CAAA;IAC9C,MAAM,QAAQ,GAAI,CAAC,CAAC,OAAO,CACzB,qFAAqF,CACtF,CAAC,GAAG,EAA2B,CAAC,CAAC,IAAI,CAAC,CAAA;IACvC,MAAM,SAAS,GAAI,CAAC,CAAC,OAAO,CAC1B,yHAAyH,CAC1H,CAAC,GAAG,EAAoB,CAAC,CAAC,CAAA;IAE3B,MAAM,KAAK,GAAa;QACtB,cAAc,KAAK,gBAAgB,SAAS,WAAW,QAAQ,IAAI;QACnE,EAAE;QACF,MAAM;QACN,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,EAAE;QACF,yBAAyB;QACzB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,EAAE;QACF,gCAAgC;QAChC,yBAAyB;KAC1B,CAAA;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,SAAS,CAAC,CAAoB,EAAE,CAAS;IAChD,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CACpB;;;;;;cAMU,CACX,CAAC,GAAG,CAAC,CAAC,CAA2H,CAAA;IAClI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,cAAc,CAAA;IAC5C,MAAM,KAAK,GAAa,CAAC,aAAa,IAAI,CAAC,MAAM,KAAK,CAAC,CAAA;IACvD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,GACR,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC5D,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC7B,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/B,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAA;QACvC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,YAAY;YACxC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG;YAC9G,CAAC,CAAC,GAAG,CAAA;QACP,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,EAAE,IAAI,KAAK,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,CAAC,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACpJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,CAAoB,EAAE,MAAc;IACzD,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAuB,CAAA;IAC3F,IAAI,CAAC,IAAI;QAAE,OAAO,eAAe,MAAM,GAAG,CAAA;IAE1C,sDAAsD;IACtD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;IACjC,KAAK,UAAU,IAAI,CAAC,EAAU,EAAE,KAAa;QAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,GAAG,EAAE;YAAE,OAAM;QACzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACf,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAuB,CAAA;QACtF,IAAI,CAAC,GAAG;YAAE,OAAM;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACjC,MAAM,IAAI,GACR,GAAG,CAAC,MAAM,KAAK,WAAW,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAChE,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC/B,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAA;QACvC,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC3D,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,KAAK,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,MAAM,KAAK,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QACrH,oEAAoE;QACpE,2CAA2C;QAC3C,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACtC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,QAAQ,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9D,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,CACxB,qDAAqD,CACtD,CAAC,GAAG,CAAC,EAAE,CAA0B,CAAA;QAClC,KAAK,MAAM,CAAC,IAAI,QAAQ;YAAE,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;IACvD,CAAC;IACD,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACrB,OAAO,CAAC,qBAAqB,MAAM,IAAI,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACnE,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACzB,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,IAAI,CAAA;IAC7B,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;IACzD,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAY,EACZ,IAAkB;IAElB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACtD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAA;IAE/B,MAAM,CAAC,GAAG,YAAY,EAAE,CAAA;IACxB,IAAI,CAAC,CAAC;QAAE,OAAO,gCAAgC,CAAA;IAE/C,IAAI,CAAC;QACH,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,OAAO,CAAC;YACb,KAAK,GAAG;gBACN,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAA;YACpB,KAAK,QAAQ,CAAC;YACd,KAAK,GAAG,CAAC;YACT,KAAK,MAAM,CAAC;YACZ,KAAK,IAAI,CAAC,CAAC,CAAC;gBACV,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;gBACvE,OAAO,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACxB,CAAC;YACD,KAAK,MAAM,CAAC;YACZ,KAAK,GAAG,CAAC,CAAC,CAAC;gBACT,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;gBACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;oBAAE,OAAO,oBAAoB,CAAA;gBAChE,OAAO,MAAM,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YAC7B,CAAC;YACD;gBACE,OAAO;oBACL,YAAY,GAAG,EAAE;oBACjB,EAAE;oBACF,6CAA6C;iBAC9C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YAAC,CAAC,CAAC,KAAK,EAAE,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC"}
|
package/dist/core/job-board.d.ts
CHANGED
|
@@ -108,6 +108,11 @@ export interface OwnerOpts {
|
|
|
108
108
|
* (claude-code / opencode / codex tabs); IM commands generally don't
|
|
109
109
|
* pass it (they want the user's full job history). */
|
|
110
110
|
agent?: string;
|
|
111
|
+
/** Optional kind filter. 'job' = explicit /job rows; 'inline' = the
|
|
112
|
+
* per-message rows auto-created by the cli main loop (Phase 2).
|
|
113
|
+
* Web /tasks Jobs tab uses this to give the operator a clean
|
|
114
|
+
* explicit-only vs inline-only view. */
|
|
115
|
+
kind?: JobKind;
|
|
111
116
|
}
|
|
112
117
|
export interface CreateJobOpts {
|
|
113
118
|
creatorId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-board.d.ts","sourceRoot":"","sources":["../../src/core/job-board.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"job-board.d.ts","sourceRoot":"","sources":["../../src/core/job-board.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAE1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AA+DlC,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAA;AAEtC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,SAAS,GACT,WAAW,GACX,WAAW,GACX,QAAQ,GACR,WAAW,GACX,aAAa,GACb,UAAU,GACV,WAAW,CAAA;AAEf,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,SAAS,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAA;IAClB;6DACyD;IACzD,IAAI,EAAE,OAAO,CAAA;IACb,gFAAgF;IAChF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,sEAAsE;IACtE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,qEAAqE;IACrE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B;mCAC+B;IAC/B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B;iEAC6D;IAC7D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;+BAE2B;IAC3B,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,KAAK,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,cAAc,CAAC,MAAM,CAAC,CAAA;AA6J1F;;0DAE0D;AAC1D,wBAAgB,gCAAgC,CAAC,MAAM,GAAE,MAAwB,GAAG,MAAM,CA0BzF;AAED;;;;;;yEAMyE;AACzE,wBAAgB,0BAA0B,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE,CAqBnE;AAED;;wCAEwC;AACxC,wBAAgB,yBAAyB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CA2BnE;AAED;;;qBAGqB;AACrB,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAcpE;AAED,iFAAiF;AACjF,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAazD;AAaD;qCACqC;AACrC,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;;yBAGyB;AACzB,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAWpE;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAED;4DAC4D;AAC5D,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAMD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;2DAGuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;6CAGyC;IACzC,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yEAAyE;IACzE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd;;4EAEwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;gCAC4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,MAAM,CAgBzF;AAED;;;;;;;;8CAQ8C;AAC9C,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,MAAM,CAkBT;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,SAAc,GAAG,GAAG,GAAG,IAAI,CAQnE;AAED,wBAAgB,QAAQ,CAAC,KAAK,SAAK,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,GAAE,SAAc,GAAG,GAAG,EAAE,CAgBpF;AAmBD;;;kDAGkD;AAClD,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAS9D;AAED;qCACqC;AACrC,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAc/C;AAED;;+EAE+E;AAC/E,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAejE;AAED;;wEAEwE;AACxE,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAShE;AAED;kFACkF;AAClF,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAcjD;AAED;;2CAE2C;AAC3C,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAe7D;AAED;;;GAGG;AACH,iBAAe,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ1C;AAED,iBAAS,WAAW,IAAI,IAAI,CAI3B;AAED,wBAAsB,MAAM,CAC1B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CA6Df;AAED,qFAAqF;AACrF,wBAAgB,eAAe,IAAI,MAAM,CAAsB;AAC/D,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,MAAM,CAA4B;AACrE,wEAAwE;AACxE,eAAO,MAAM,SAAS;;;CAAiD,CAAA;AAEvE,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,SAAc,GAAG,OAAO,CAWnE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAE,QAAQ,CAAC,QAAmB,EAAE,aAAa,GAAE,MAA+B,GAAG,MAAM,CAyEpH;AAED,wBAAgB,WAAW,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAqBpH"}
|
package/dist/core/job-board.js
CHANGED
|
@@ -451,6 +451,10 @@ export function listJobs(limit = 20, status, opts = {}) {
|
|
|
451
451
|
conditions.push('agent = ?');
|
|
452
452
|
params.push(opts.agent);
|
|
453
453
|
}
|
|
454
|
+
if (opts.kind) {
|
|
455
|
+
conditions.push('kind = ?');
|
|
456
|
+
params.push(opts.kind);
|
|
457
|
+
}
|
|
454
458
|
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
455
459
|
return d.prepare(`SELECT * FROM jobs ${where} ORDER BY created_at DESC LIMIT ?`)
|
|
456
460
|
.all(...params, safeLimit);
|
|
@@ -706,6 +710,24 @@ export function pruneOldJobs(d = getDb(), daysRetention = resolveRetentionDays()
|
|
|
706
710
|
// Two passes — different retention by kind. SQLite can't do this in one
|
|
707
711
|
// statement without a CASE-on-window-or-something gnarly; two prepares
|
|
708
712
|
// keeps it readable and the row counts attributable.
|
|
713
|
+
//
|
|
714
|
+
// L2 — collect ids BEFORE delete so we can hand them to artifacts.ts
|
|
715
|
+
// for matching-dir cleanup. Two-step is unavoidable because SQLite
|
|
716
|
+
// doesn't have DELETE … RETURNING. The window is tiny and the side
|
|
717
|
+
// effect (orphaned dirs) is small, so we don't bother with a Tx.
|
|
718
|
+
const jobIdsToDel = d.prepare(`
|
|
719
|
+
SELECT id FROM jobs
|
|
720
|
+
WHERE kind = 'job'
|
|
721
|
+
AND status IN (${TERMINAL})
|
|
722
|
+
AND completed_at IS NOT NULL
|
|
723
|
+
AND completed_at < datetime('now', ?)
|
|
724
|
+
`).all(`-${daysRetention} days`);
|
|
725
|
+
const inlineIdsToDel = d.prepare(`
|
|
726
|
+
SELECT id FROM jobs
|
|
727
|
+
WHERE kind = 'inline'
|
|
728
|
+
AND status IN (${TERMINAL})
|
|
729
|
+
AND COALESCE(completed_at, created_at) < datetime('now', ?)
|
|
730
|
+
`).all(`-${inlineHours} hours`);
|
|
709
731
|
const jobInfo = d.prepare(`
|
|
710
732
|
DELETE FROM jobs
|
|
711
733
|
WHERE kind = 'job'
|
|
@@ -720,6 +742,16 @@ export function pruneOldJobs(d = getDb(), daysRetention = resolveRetentionDays()
|
|
|
720
742
|
AND COALESCE(completed_at, created_at) < datetime('now', ?)
|
|
721
743
|
`).run(`-${inlineHours} hours`);
|
|
722
744
|
const total = jobInfo.changes + inlineInfo.changes;
|
|
745
|
+
// L2 — drop artifacts dirs for everything we just deleted. inline jobs
|
|
746
|
+
// are where the artifacts live, but kind='job' rows might also have
|
|
747
|
+
// them in the future, so we feed both. Fire-and-forget; failures only
|
|
748
|
+
// leave an orphaned dir, not a broken DB.
|
|
749
|
+
const allIds = [...jobIdsToDel, ...inlineIdsToDel].map((r) => r.id);
|
|
750
|
+
if (allIds.length > 0) {
|
|
751
|
+
void import('./artifacts.js')
|
|
752
|
+
.then(({ pruneArtifactsBatch }) => pruneArtifactsBatch(allIds))
|
|
753
|
+
.catch((err) => rootLogger.warn({ component: 'job-board', event: 'job-board.prune.artifacts_failed', err: err instanceof Error ? err.message : String(err) }, 'pruneArtifactsBatch failed (orphaned dirs may remain)'));
|
|
754
|
+
}
|
|
723
755
|
if (total > 0) {
|
|
724
756
|
rootLogger.info({
|
|
725
757
|
component: 'job-board', event: 'job-board.pruned',
|