@agentrific/server 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/cli.js +181 -67
- package/cli.js.map +4 -4
- package/index.js +156 -50
- package/index.js.map +4 -4
- package/package.json +2 -1
package/index.js
CHANGED
|
@@ -492,11 +492,18 @@ var CreateSessionSchema = z2.object({
|
|
|
492
492
|
var SendMessageSchema = z2.object({
|
|
493
493
|
message: z2.string().trim().max(2e4),
|
|
494
494
|
attachmentIds: AttachmentIdsSchema.optional(),
|
|
495
|
-
clientMessageId: z2.string().min(1).max(120).optional()
|
|
495
|
+
clientMessageId: z2.string().min(1).max(120).optional(),
|
|
496
|
+
mode: z2.enum(["followUp", "steer"]).optional()
|
|
496
497
|
}).refine(
|
|
497
498
|
(input) => input.message.length > 0 || (input.attachmentIds?.length ?? 0) > 0,
|
|
498
499
|
"Write a message or attach a file."
|
|
499
500
|
);
|
|
501
|
+
var FileChangeSchema = z2.object({
|
|
502
|
+
path: z2.string(),
|
|
503
|
+
patch: z2.string().optional(),
|
|
504
|
+
content: z2.string().optional(),
|
|
505
|
+
omitted: z2.boolean().optional()
|
|
506
|
+
});
|
|
500
507
|
var SessionEventSchema = z2.discriminatedUnion("type", [
|
|
501
508
|
z2.object({ type: z2.literal("session.updated"), session: SessionSchema }),
|
|
502
509
|
z2.object({
|
|
@@ -531,7 +538,8 @@ var SessionEventSchema = z2.discriminatedUnion("type", [
|
|
|
531
538
|
sessionId: z2.string(),
|
|
532
539
|
toolCallId: z2.string().optional(),
|
|
533
540
|
tool: z2.string(),
|
|
534
|
-
input: z2.string()
|
|
541
|
+
input: z2.string(),
|
|
542
|
+
filePath: z2.string().optional()
|
|
535
543
|
}),
|
|
536
544
|
z2.object({
|
|
537
545
|
type: z2.literal("tool.completed"),
|
|
@@ -539,6 +547,7 @@ var SessionEventSchema = z2.discriminatedUnion("type", [
|
|
|
539
547
|
toolCallId: z2.string().optional(),
|
|
540
548
|
tool: z2.string(),
|
|
541
549
|
output: z2.string(),
|
|
550
|
+
fileChange: FileChangeSchema.optional(),
|
|
542
551
|
isError: z2.boolean().default(false)
|
|
543
552
|
}),
|
|
544
553
|
z2.object({
|
|
@@ -1081,7 +1090,7 @@ async function startControl(directory, security2, status, maintenance2) {
|
|
|
1081
1090
|
// package.json
|
|
1082
1091
|
var package_default = {
|
|
1083
1092
|
name: "@agentrific/server",
|
|
1084
|
-
version: "0.
|
|
1093
|
+
version: "0.2.0",
|
|
1085
1094
|
description: "Self-hosted control plane for long-running coding agents",
|
|
1086
1095
|
keywords: [
|
|
1087
1096
|
"agentrific",
|
|
@@ -1118,6 +1127,7 @@ var package_default = {
|
|
|
1118
1127
|
"@fastify/cors": "^11.3.0",
|
|
1119
1128
|
"@fastify/multipart": "^10.1.2",
|
|
1120
1129
|
"@inquirer/select": "^5.2.5",
|
|
1130
|
+
diff: "^9.0.0",
|
|
1121
1131
|
effect: "4.0.0-rc.117",
|
|
1122
1132
|
fastify: "^5.6.2",
|
|
1123
1133
|
"pino-pretty": "^13.1.3",
|
|
@@ -1467,7 +1477,7 @@ var UpdateDiscovery = class {
|
|
|
1467
1477
|
|
|
1468
1478
|
// src/index.ts
|
|
1469
1479
|
import { Effect as Effect16, ManagedRuntime } from "effect";
|
|
1470
|
-
import { z as
|
|
1480
|
+
import { z as z17 } from "zod";
|
|
1471
1481
|
|
|
1472
1482
|
// src/automation.ts
|
|
1473
1483
|
import { Effect as Effect7 } from "effect";
|
|
@@ -1829,7 +1839,7 @@ var AgentController = class {
|
|
|
1829
1839
|
Effect8.ensuring(Effect8.sync(() => this.working.delete(entry.session.id)))
|
|
1830
1840
|
);
|
|
1831
1841
|
}
|
|
1832
|
-
send(session, message, attachments2 = [], messageId = randomUUID4()) {
|
|
1842
|
+
send(session, message, attachments2 = [], messageId = randomUUID4(), mode = "followUp") {
|
|
1833
1843
|
return this.lock(session.id).withPermit(
|
|
1834
1844
|
Effect8.gen({ self: this }, function* () {
|
|
1835
1845
|
if (this.closed)
|
|
@@ -1839,6 +1849,16 @@ var AgentController = class {
|
|
|
1839
1849
|
if (this.hasMessage(session.id, messageId)) return;
|
|
1840
1850
|
const entry = yield* this.open(session);
|
|
1841
1851
|
yield* this.operation(async () => entry.agent.validateAttachments?.(attachments2));
|
|
1852
|
+
const steering = entry.running && mode === "steer";
|
|
1853
|
+
if (steering) {
|
|
1854
|
+
if (!entry.agent.steer)
|
|
1855
|
+
return yield* Effect8.fail(
|
|
1856
|
+
new AgentError({ message: "This agent does not support steering." })
|
|
1857
|
+
);
|
|
1858
|
+
yield* this.operation(
|
|
1859
|
+
() => entry.agent.steer(gitFlowPrompt(entry.session, message), attachments2)
|
|
1860
|
+
);
|
|
1861
|
+
}
|
|
1842
1862
|
this.emit({
|
|
1843
1863
|
type: "message.user",
|
|
1844
1864
|
sessionId: session.id,
|
|
@@ -1846,6 +1866,7 @@ var AgentController = class {
|
|
|
1846
1866
|
text: message,
|
|
1847
1867
|
attachments: attachments2
|
|
1848
1868
|
});
|
|
1869
|
+
if (steering) return;
|
|
1849
1870
|
if (entry.running) {
|
|
1850
1871
|
entry.pending.push({ text: message, attachments: attachments2 });
|
|
1851
1872
|
return;
|
|
@@ -2749,7 +2770,7 @@ import {
|
|
|
2749
2770
|
createAgentSession as createAgentSession2,
|
|
2750
2771
|
SessionManager as SessionManager2
|
|
2751
2772
|
} from "@earendil-works/pi-coding-agent";
|
|
2752
|
-
import { z as
|
|
2773
|
+
import { z as z13 } from "zod";
|
|
2753
2774
|
|
|
2754
2775
|
// src/delivery-tool.ts
|
|
2755
2776
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
@@ -2783,9 +2804,70 @@ function deliveryTool(sessionId, delivery2) {
|
|
|
2783
2804
|
});
|
|
2784
2805
|
}
|
|
2785
2806
|
|
|
2807
|
+
// src/file-change.ts
|
|
2808
|
+
import { createWriteToolDefinition, defineTool as defineTool2 } from "@earendil-works/pi-coding-agent";
|
|
2809
|
+
import { createTwoFilesPatch } from "diff";
|
|
2810
|
+
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
|
|
2811
|
+
import { z as z12 } from "zod";
|
|
2812
|
+
var previewLimit = 256e3;
|
|
2813
|
+
function boundFileChange(change) {
|
|
2814
|
+
if ((change.patch?.length ?? 0) + (change.content?.length ?? 0) > previewLimit)
|
|
2815
|
+
return { path: change.path, omitted: true };
|
|
2816
|
+
return change;
|
|
2817
|
+
}
|
|
2818
|
+
var EditResultSchema = z12.object({
|
|
2819
|
+
details: z12.object({ patch: z12.string().optional(), fileChange: FileChangeSchema.optional() }).optional()
|
|
2820
|
+
});
|
|
2821
|
+
function completedFileChange(result, path10) {
|
|
2822
|
+
const parsed = EditResultSchema.safeParse(result);
|
|
2823
|
+
if (!parsed.success) return;
|
|
2824
|
+
const details = parsed.data.details;
|
|
2825
|
+
if (details?.fileChange) return boundFileChange(details.fileChange);
|
|
2826
|
+
if (path10 && details?.patch) return boundFileChange({ path: path10, patch: details.patch });
|
|
2827
|
+
}
|
|
2828
|
+
function fileWriteTool(cwd) {
|
|
2829
|
+
const base = createWriteToolDefinition(cwd);
|
|
2830
|
+
return defineTool2({
|
|
2831
|
+
name: base.name,
|
|
2832
|
+
label: base.label,
|
|
2833
|
+
description: base.description,
|
|
2834
|
+
promptSnippet: base.promptSnippet,
|
|
2835
|
+
promptGuidelines: base.promptGuidelines,
|
|
2836
|
+
parameters: base.parameters,
|
|
2837
|
+
constrainedSampling: base.constrainedSampling,
|
|
2838
|
+
async execute(toolCallId, args, signal, _onUpdate, ctx) {
|
|
2839
|
+
let fileChange;
|
|
2840
|
+
const tool = createWriteToolDefinition(cwd, {
|
|
2841
|
+
operations: {
|
|
2842
|
+
mkdir: async (dir) => {
|
|
2843
|
+
await mkdir4(dir, { recursive: true });
|
|
2844
|
+
},
|
|
2845
|
+
// Pi invokes this inside its per-file mutation queue, so the snapshot
|
|
2846
|
+
// and write cannot race another built-in edit/write on the same file.
|
|
2847
|
+
writeFile: async (path10, content) => {
|
|
2848
|
+
const previous = await readFile4(path10, "utf8").catch((error) => {
|
|
2849
|
+
if (error.code === "ENOENT") return void 0;
|
|
2850
|
+
throw error;
|
|
2851
|
+
});
|
|
2852
|
+
await writeFile2(path10, content, "utf8");
|
|
2853
|
+
fileChange = boundFileChange(
|
|
2854
|
+
previous === void 0 ? { path: args.path, content } : {
|
|
2855
|
+
path: args.path,
|
|
2856
|
+
patch: createTwoFilesPatch(args.path, args.path, previous, content)
|
|
2857
|
+
}
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
});
|
|
2862
|
+
const result = await tool.execute(toolCallId, args, signal, void 0, ctx);
|
|
2863
|
+
return { ...result, details: { fileChange } };
|
|
2864
|
+
}
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2786
2868
|
// src/pi.ts
|
|
2787
|
-
var ToolResultSchema =
|
|
2788
|
-
content:
|
|
2869
|
+
var ToolResultSchema = z13.object({
|
|
2870
|
+
content: z13.array(z13.object({ type: z13.string(), text: z13.string().optional() })).optional()
|
|
2789
2871
|
}).passthrough();
|
|
2790
2872
|
var boundedJson = (value, limit) => {
|
|
2791
2873
|
let text;
|
|
@@ -2810,7 +2892,10 @@ function createPiFactory(files, models2, delivery2, createSession = createAgentS
|
|
|
2810
2892
|
model,
|
|
2811
2893
|
modelRuntime: models2.runtime,
|
|
2812
2894
|
sessionManager: SessionManager2.continueRecent(cwd, sessionDirectory),
|
|
2813
|
-
customTools:
|
|
2895
|
+
customTools: [
|
|
2896
|
+
fileWriteTool(cwd),
|
|
2897
|
+
...run?.gitFlow && delivery2 ? [deliveryTool(sessionId, delivery2)] : []
|
|
2898
|
+
]
|
|
2814
2899
|
});
|
|
2815
2900
|
return {
|
|
2816
2901
|
get model() {
|
|
@@ -2834,6 +2919,12 @@ function createPiFactory(files, models2, delivery2, createSession = createAgentS
|
|
|
2834
2919
|
throw new Error(last.errorMessage ?? "The model request failed");
|
|
2835
2920
|
}
|
|
2836
2921
|
},
|
|
2922
|
+
async steer(message, attachments2 = []) {
|
|
2923
|
+
const context = await Effect12.runPromise(files.prepare(attachments2));
|
|
2924
|
+
if (!session.isStreaming)
|
|
2925
|
+
throw new Error("The response has finished. Send this message as a follow-up instead.");
|
|
2926
|
+
await session.steer(message + context.context, context.images);
|
|
2927
|
+
},
|
|
2837
2928
|
async abort() {
|
|
2838
2929
|
session.clearQueue();
|
|
2839
2930
|
await session.abort();
|
|
@@ -2898,16 +2989,23 @@ function createPiFactory(files, models2, delivery2, createSession = createAgentS
|
|
|
2898
2989
|
}
|
|
2899
2990
|
return false;
|
|
2900
2991
|
}
|
|
2992
|
+
const filePaths = /* @__PURE__ */ new Map();
|
|
2993
|
+
const FileArgsSchema = z13.object({ path: z13.string() });
|
|
2901
2994
|
function handleTool(event) {
|
|
2902
2995
|
if (event.type === "tool_execution_start") {
|
|
2903
2996
|
flushText();
|
|
2904
2997
|
setActivity("thinking");
|
|
2998
|
+
if (event.toolName === "edit" || event.toolName === "write") {
|
|
2999
|
+
const args = FileArgsSchema.safeParse(event.args);
|
|
3000
|
+
if (args.success) filePaths.set(event.toolCallId, args.data.path);
|
|
3001
|
+
}
|
|
2905
3002
|
emit({
|
|
2906
3003
|
type: "tool.started",
|
|
2907
3004
|
sessionId,
|
|
2908
3005
|
toolCallId: event.toolCallId,
|
|
2909
3006
|
tool: event.toolName,
|
|
2910
|
-
input: boundedJson(event.args, 1200)
|
|
3007
|
+
input: boundedJson(event.args, 1200),
|
|
3008
|
+
filePath: filePaths.get(event.toolCallId)
|
|
2911
3009
|
});
|
|
2912
3010
|
return true;
|
|
2913
3011
|
}
|
|
@@ -2919,8 +3017,10 @@ function createPiFactory(files, models2, delivery2, createSession = createAgentS
|
|
|
2919
3017
|
toolCallId: event.toolCallId,
|
|
2920
3018
|
tool: event.toolName,
|
|
2921
3019
|
output: toolOutput(event.result),
|
|
3020
|
+
fileChange: event.isError ? void 0 : completedFileChange(event.result, filePaths.get(event.toolCallId)),
|
|
2922
3021
|
isError: event.isError
|
|
2923
3022
|
});
|
|
3023
|
+
filePaths.delete(event.toolCallId);
|
|
2924
3024
|
setActivity("thinking");
|
|
2925
3025
|
return true;
|
|
2926
3026
|
}
|
|
@@ -2949,9 +3049,9 @@ function createPiFactory(files, models2, delivery2, createSession = createAgentS
|
|
|
2949
3049
|
}
|
|
2950
3050
|
|
|
2951
3051
|
// src/projects.ts
|
|
2952
|
-
import { access, readdir as readdir2, realpath, stat as stat2, readFile as
|
|
3052
|
+
import { access, readdir as readdir2, realpath, stat as stat2, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
|
|
2953
3053
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
2954
|
-
import { z as
|
|
3054
|
+
import { z as z14 } from "zod";
|
|
2955
3055
|
import { constants } from "node:fs";
|
|
2956
3056
|
import { homedir } from "node:os";
|
|
2957
3057
|
import path6 from "node:path";
|
|
@@ -2983,12 +3083,12 @@ function projectLock(store2) {
|
|
|
2983
3083
|
}
|
|
2984
3084
|
return lock;
|
|
2985
3085
|
}
|
|
2986
|
-
var ProjectId =
|
|
3086
|
+
var ProjectId = z14.string().trim().min(1).max(255);
|
|
2987
3087
|
async function gitDirectory(directory) {
|
|
2988
3088
|
const location = path6.join(directory, ".git");
|
|
2989
3089
|
const info = await stat2(location);
|
|
2990
3090
|
if (info.isDirectory()) return location;
|
|
2991
|
-
const contents = await
|
|
3091
|
+
const contents = await readFile5(location, "utf8");
|
|
2992
3092
|
const match = /^gitdir: (.+)\s*$/m.exec(contents);
|
|
2993
3093
|
if (!match) throw new Error("Invalid Git worktree metadata.");
|
|
2994
3094
|
const resolved = await realpath(path6.resolve(directory, match[1].trim()));
|
|
@@ -2998,21 +3098,21 @@ async function gitDirectory(directory) {
|
|
|
2998
3098
|
async function identity(directory, preferred) {
|
|
2999
3099
|
const filename = path6.join(await gitDirectory(directory), "agentrific-project-id");
|
|
3000
3100
|
try {
|
|
3001
|
-
return ProjectId.parse(await
|
|
3101
|
+
return ProjectId.parse(await readFile5(filename, "utf8"));
|
|
3002
3102
|
} catch (error) {
|
|
3003
|
-
if (!
|
|
3103
|
+
if (!z14.object({ code: z14.literal("ENOENT") }).safeParse(error).success) throw error;
|
|
3004
3104
|
const legacyFilename = path6.join(await gitDirectory(directory), "chatplans-project-id");
|
|
3005
|
-
const legacy = await
|
|
3006
|
-
if (!
|
|
3105
|
+
const legacy = await readFile5(legacyFilename, "utf8").catch((cause) => {
|
|
3106
|
+
if (!z14.object({ code: z14.literal("ENOENT") }).safeParse(cause).success) throw cause;
|
|
3007
3107
|
return null;
|
|
3008
3108
|
});
|
|
3009
3109
|
const id = legacy === null ? preferred ?? randomUUID6() : ProjectId.parse(legacy);
|
|
3010
3110
|
try {
|
|
3011
|
-
await
|
|
3111
|
+
await writeFile3(filename, id + "\n", { flag: "wx" });
|
|
3012
3112
|
return id;
|
|
3013
3113
|
} catch (writeError) {
|
|
3014
|
-
if (!
|
|
3015
|
-
return ProjectId.parse(await
|
|
3114
|
+
if (!z14.object({ code: z14.literal("EEXIST") }).safeParse(writeError).success) throw writeError;
|
|
3115
|
+
return ProjectId.parse(await readFile5(filename, "utf8"));
|
|
3016
3116
|
}
|
|
3017
3117
|
}
|
|
3018
3118
|
}
|
|
@@ -3032,7 +3132,7 @@ function scanProjects(root, store2) {
|
|
|
3032
3132
|
let existing = registered.find((project2) => project2.id === id);
|
|
3033
3133
|
if (found.some((project2) => project2.id === id) || existing && existing.path !== directory && await stat2(path6.join(existing.path, ".git")).catch(() => null)) {
|
|
3034
3134
|
id = randomUUID6();
|
|
3035
|
-
await
|
|
3135
|
+
await writeFile3(
|
|
3036
3136
|
path6.join(await gitDirectory(directory), "agentrific-project-id"),
|
|
3037
3137
|
id + "\n"
|
|
3038
3138
|
);
|
|
@@ -3071,11 +3171,11 @@ function reconnectProject(root, id, input, store2) {
|
|
|
3071
3171
|
const filename = path6.join(await gitDirectory(directory), "agentrific-project-id");
|
|
3072
3172
|
const replacedId = await identity(directory);
|
|
3073
3173
|
const project = { id, name: path6.basename(directory), path: directory, available: true };
|
|
3074
|
-
await
|
|
3174
|
+
await writeFile3(filename, id + "\n");
|
|
3075
3175
|
try {
|
|
3076
3176
|
await Effect13.runPromise(store2.relocateProject(project, previous.path, replacedId));
|
|
3077
3177
|
} catch (error) {
|
|
3078
|
-
await
|
|
3178
|
+
await writeFile3(filename, replacedId + "\n");
|
|
3079
3179
|
throw error;
|
|
3080
3180
|
}
|
|
3081
3181
|
return project;
|
|
@@ -3089,32 +3189,32 @@ import { chmodSync, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "n
|
|
|
3089
3189
|
import path7 from "node:path";
|
|
3090
3190
|
|
|
3091
3191
|
// src/push-schema.ts
|
|
3092
|
-
import { z as
|
|
3093
|
-
var PushBindingSchema =
|
|
3094
|
-
bindingId:
|
|
3095
|
-
installationId:
|
|
3096
|
-
deviceId:
|
|
3192
|
+
import { z as z15 } from "zod";
|
|
3193
|
+
var PushBindingSchema = z15.object({
|
|
3194
|
+
bindingId: z15.string().uuid(),
|
|
3195
|
+
installationId: z15.string().uuid(),
|
|
3196
|
+
deviceId: z15.string().uuid()
|
|
3097
3197
|
});
|
|
3098
|
-
var PushStateSchema =
|
|
3099
|
-
bindings:
|
|
3100
|
-
error:
|
|
3198
|
+
var PushStateSchema = z15.object({
|
|
3199
|
+
bindings: z15.array(PushBindingSchema).max(10),
|
|
3200
|
+
error: z15.string().nullable()
|
|
3101
3201
|
});
|
|
3102
3202
|
var PendingPushSchema = PushEventSchema.extend({
|
|
3103
|
-
remaining:
|
|
3104
|
-
createdAt:
|
|
3105
|
-
attempts:
|
|
3106
|
-
nextAt:
|
|
3203
|
+
remaining: z15.array(PushBindingSchema),
|
|
3204
|
+
createdAt: z15.number(),
|
|
3205
|
+
attempts: z15.number().int().nonnegative(),
|
|
3206
|
+
nextAt: z15.number()
|
|
3107
3207
|
});
|
|
3108
3208
|
|
|
3109
3209
|
// src/store.ts
|
|
3110
3210
|
import { DatabaseSync } from "node:sqlite";
|
|
3111
3211
|
import { Context as Context3, Data as Data3, Effect as Effect14, Layer as Layer3 } from "effect";
|
|
3112
|
-
import { z as
|
|
3212
|
+
import { z as z16 } from "zod";
|
|
3113
3213
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
3114
3214
|
var StorageError = class extends Data3.TaggedError("StorageError") {
|
|
3115
3215
|
};
|
|
3116
|
-
var PayloadRow =
|
|
3117
|
-
var EventRow =
|
|
3216
|
+
var PayloadRow = z16.object({ payload: z16.string() });
|
|
3217
|
+
var EventRow = z16.object({ sequence: z16.number(), recorded_at: z16.string(), payload: z16.string() });
|
|
3118
3218
|
var SqliteSessionStore = class {
|
|
3119
3219
|
constructor(db) {
|
|
3120
3220
|
this.db = db;
|
|
@@ -3165,7 +3265,7 @@ var SqliteSessionStore = class {
|
|
|
3165
3265
|
const row = PayloadRow.parse(
|
|
3166
3266
|
this.db.prepare("SELECT payload FROM settings WHERE id = 'server-id'").get()
|
|
3167
3267
|
);
|
|
3168
|
-
return
|
|
3268
|
+
return z16.string().uuid().parse(JSON.parse(row.payload));
|
|
3169
3269
|
});
|
|
3170
3270
|
}
|
|
3171
3271
|
saveDevice(device, tokenHash) {
|
|
@@ -3253,7 +3353,7 @@ var SqliteSessionStore = class {
|
|
|
3253
3353
|
`).all();
|
|
3254
3354
|
const insert = this.db.prepare("INSERT OR IGNORE INTO projects(id, payload) VALUES (?, ?)");
|
|
3255
3355
|
for (const row of legacy) {
|
|
3256
|
-
const id =
|
|
3356
|
+
const id = z16.object({ id: z16.string() }).parse(row).id;
|
|
3257
3357
|
insert.run(
|
|
3258
3358
|
id,
|
|
3259
3359
|
JSON.stringify({ id, name: id, path: path7.join(root, id), available: false })
|
|
@@ -3463,7 +3563,7 @@ var SqliteSessionStore = class {
|
|
|
3463
3563
|
if (event.type === "message.user") this.claimAttachments(event.attachments ?? []);
|
|
3464
3564
|
const result = this.db.prepare("INSERT INTO events(session_id, recorded_at, payload) VALUES (?, ?, ?)").run(sessionId, recordedAt, JSON.stringify(event));
|
|
3465
3565
|
if (notification) {
|
|
3466
|
-
const count =
|
|
3566
|
+
const count = z16.object({ total: z16.number() }).parse(this.db.prepare("SELECT COUNT(*) AS total FROM push_outbox").get());
|
|
3467
3567
|
if (count.total >= 1e3)
|
|
3468
3568
|
this.db.prepare(
|
|
3469
3569
|
"DELETE FROM push_outbox WHERE rowid IN (SELECT rowid FROM push_outbox ORDER BY rowid LIMIT 1)"
|
|
@@ -3515,7 +3615,7 @@ var SessionStore = class extends Context3.Service()(
|
|
|
3515
3615
|
for (const suffix of ["-wal", "-shm"])
|
|
3516
3616
|
if (existsSync2(filename + suffix)) chmodSync(filename + suffix, 384);
|
|
3517
3617
|
try {
|
|
3518
|
-
const schema =
|
|
3618
|
+
const schema = z16.object({ user_version: z16.number() }).parse(db.prepare("PRAGMA user_version").get());
|
|
3519
3619
|
if (schema.user_version > 1)
|
|
3520
3620
|
throw new Error("This database requires a newer Agentrific server.");
|
|
3521
3621
|
db.exec(`
|
|
@@ -3905,7 +4005,7 @@ app.get("/api/projects/:id", async (request, reply) => {
|
|
|
3905
4005
|
return project ?? reply.code(404).send({ error: "Project not found on this server." });
|
|
3906
4006
|
});
|
|
3907
4007
|
app.post("/api/projects/:id/reconnect", async (request, reply) => {
|
|
3908
|
-
const parsed =
|
|
4008
|
+
const parsed = z17.object({ path: z17.string().trim().min(1).max(4096) }).safeParse(request.body);
|
|
3909
4009
|
if (!parsed.success)
|
|
3910
4010
|
return reply.code(400).send({ error: "Enter the project's new folder path." });
|
|
3911
4011
|
const root = await Effect16.runPromise(store.projectsRoot(defaultProjectsRoot));
|
|
@@ -4037,9 +4137,9 @@ app.post(
|
|
|
4037
4137
|
}
|
|
4038
4138
|
})
|
|
4039
4139
|
);
|
|
4040
|
-
var HistoryQuery =
|
|
4041
|
-
after:
|
|
4042
|
-
limit:
|
|
4140
|
+
var HistoryQuery = z17.object({
|
|
4141
|
+
after: z17.coerce.number().int().nonnegative().default(0),
|
|
4142
|
+
limit: z17.coerce.number().int().min(1).max(1e3).default(500)
|
|
4043
4143
|
});
|
|
4044
4144
|
app.get("/api/sessions/:id/events", async (request, reply) => {
|
|
4045
4145
|
const query = HistoryQuery.safeParse(request.query);
|
|
@@ -4181,7 +4281,7 @@ app.post("/api/sessions", async (request, reply) => {
|
|
|
4181
4281
|
if (!result.session) return reply.code(result.status).send({ error: result.error });
|
|
4182
4282
|
return reply.code(201).send(result.session);
|
|
4183
4283
|
});
|
|
4184
|
-
var StartTaskBody =
|
|
4284
|
+
var StartTaskBody = z17.object({ prompt: z17.string().trim().max(2e4).optional() }).default({});
|
|
4185
4285
|
function startTask(id, instructionsOverride, automated = false) {
|
|
4186
4286
|
return withTaskLock(
|
|
4187
4287
|
"agent-dispatch",
|
|
@@ -4259,7 +4359,7 @@ app.patch("/api/automation", async (request, reply) => {
|
|
|
4259
4359
|
return automation.configure(parsed.data);
|
|
4260
4360
|
});
|
|
4261
4361
|
app.patch("/api/automation/queue", async (request, reply) => {
|
|
4262
|
-
const parsed =
|
|
4362
|
+
const parsed = z17.object({ taskId: z17.string().min(1), beforeId: z17.string().min(1).nullable() }).safeParse(request.body);
|
|
4263
4363
|
if (!parsed.success)
|
|
4264
4364
|
return reply.code(400).send({ error: "Choose a task and a queue position." });
|
|
4265
4365
|
try {
|
|
@@ -4289,7 +4389,13 @@ app.post(
|
|
|
4289
4389
|
attachments.resolve(session.projectId, parsed.data.attachmentIds ?? [])
|
|
4290
4390
|
);
|
|
4291
4391
|
await Effect16.runPromise(
|
|
4292
|
-
runtime.send(
|
|
4392
|
+
runtime.send(
|
|
4393
|
+
session,
|
|
4394
|
+
parsed.data.message,
|
|
4395
|
+
files,
|
|
4396
|
+
parsed.data.clientMessageId,
|
|
4397
|
+
parsed.data.mode
|
|
4398
|
+
)
|
|
4293
4399
|
);
|
|
4294
4400
|
return reply.code(202).send({ accepted: true });
|
|
4295
4401
|
} catch (error) {
|