@netnodeag/kraftwerk 0.73.0 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/routes.d.ts +1 -0
- package/dist/client/routes.js +1 -0
- package/dist/core/chat/sessions.d.ts +13 -0
- package/dist/core/chat/sessions.js +22 -0
- package/dist/server/api/chats.d.ts +4 -1
- package/dist/server/api/chats.js +29 -3
- package/dist/server/api/index.d.ts +4 -1
- package/package.json +1 -1
- package/web/dist/assets/{dist-LUiVqSl6.js → dist-BJQuUDA0.js} +1 -1
- package/web/dist/assets/{dist-Bu0rxkzF.js → dist-CESw77ha.js} +1 -1
- package/web/dist/assets/dist-CMMQorId.js +1 -0
- package/web/dist/assets/{dist-CYnXUgv0.js → dist-CRrnyH8Z.js} +1 -1
- package/web/dist/assets/{dist-BLd_aA1g.js → dist-CaGkA8bH.js} +1 -1
- package/web/dist/assets/{dist-C8xoYPYE.js → dist-Cnm1S16W.js} +1 -1
- package/web/dist/assets/{dist-CVuec2Mm.js → dist-D746Qhyu.js} +1 -1
- package/web/dist/assets/{dist-H3OFzCSU.js → dist-Df4EJMUZ.js} +1 -1
- package/web/dist/assets/{dist-GJo81x50.js → dist-INPpBMuI.js} +1 -1
- package/web/dist/assets/{dist-WCCGMh5F.js → dist-XZFWBcL9.js} +1 -1
- package/web/dist/assets/{dist-DFZgINkL.js → dist-r61B6qLC.js} +1 -1
- package/web/dist/assets/{editor-6D-WNjZY.js → editor-ByOSpxTX.js} +3 -3
- package/web/dist/assets/{index-D8-2MY0Q.js → index-CJTkdJMe.js} +3 -3
- package/web/dist/index.html +1 -1
- package/web/dist/assets/dist-D-uSPljm.js +0 -1
package/dist/client/routes.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export declare const ROUTES: {
|
|
|
40
40
|
readonly "chats.permission": readonly ["POST", "/api/chats/:id/permission"];
|
|
41
41
|
readonly "chats.rename": readonly ["PATCH", "/api/chats/:id"];
|
|
42
42
|
readonly "chats.resetSession": readonly ["POST", "/api/chats/:id/reset-session"];
|
|
43
|
+
readonly "chats.setProject": readonly ["POST", "/api/chats/:id/project"];
|
|
43
44
|
readonly "chats.setVibeable": readonly ["POST", "/api/chats/:id/vibeable"];
|
|
44
45
|
readonly "chats.steer": readonly ["POST", "/api/chats/:id/steer"];
|
|
45
46
|
readonly "chats.stopTask": readonly ["POST", "/api/chats/:id/task-stop"];
|
package/dist/client/routes.js
CHANGED
|
@@ -41,6 +41,7 @@ export const ROUTES = {
|
|
|
41
41
|
"chats.permission": ["POST", "/api/chats/:id/permission"],
|
|
42
42
|
"chats.rename": ["PATCH", "/api/chats/:id"],
|
|
43
43
|
"chats.resetSession": ["POST", "/api/chats/:id/reset-session"],
|
|
44
|
+
"chats.setProject": ["POST", "/api/chats/:id/project"],
|
|
44
45
|
"chats.setVibeable": ["POST", "/api/chats/:id/vibeable"],
|
|
45
46
|
"chats.steer": ["POST", "/api/chats/:id/steer"],
|
|
46
47
|
"chats.stopTask": ["POST", "/api/chats/:id/task-stop"],
|
|
@@ -16,6 +16,8 @@ export declare function createChat(opts: {
|
|
|
16
16
|
title?: string;
|
|
17
17
|
/** Continue one of the agent's own sessions (from listAgentSessionsFor) instead of starting fresh. */
|
|
18
18
|
resume?: string;
|
|
19
|
+
/** The project an agent's chat works in (meta.project); the caller checks that it exists. */
|
|
20
|
+
project?: string;
|
|
19
21
|
}): Promise<ChatMeta>;
|
|
20
22
|
/** A permission request is waiting for a human in this chat (live state only — a restart drops it with the backend). */
|
|
21
23
|
export declare function chatAwaitingApproval(id: string): boolean;
|
|
@@ -153,6 +155,17 @@ export declare function renameChat(id: string, title: unknown): Promise<{
|
|
|
153
155
|
meta?: ChatMeta;
|
|
154
156
|
error?: string;
|
|
155
157
|
}>;
|
|
158
|
+
/**
|
|
159
|
+
* File an agent's chat under a project, or under none (`null`). The chat is
|
|
160
|
+
* then listed with the project, and the agent reads the project's context
|
|
161
|
+
* with its next message. Project chats and channels belong where
|
|
162
|
+
* their scope says and cannot move; the caller checks that the project exists.
|
|
163
|
+
*/
|
|
164
|
+
export declare function setChatProject(id: string, project: string | null): Promise<{
|
|
165
|
+
meta?: ChatMeta;
|
|
166
|
+
error?: string;
|
|
167
|
+
status?: number;
|
|
168
|
+
}>;
|
|
156
169
|
export declare function deleteChat(id: string): Promise<{
|
|
157
170
|
error?: string;
|
|
158
171
|
}>;
|
|
@@ -43,6 +43,7 @@ export async function createChat(opts) {
|
|
|
43
43
|
title: opts.title ?? "",
|
|
44
44
|
cwd,
|
|
45
45
|
scope: opts.scope,
|
|
46
|
+
...(opts.project && opts.scope.kind === "agent" ? { project: opts.project } : {}),
|
|
46
47
|
...(opts.resume && opts.agent !== "pi" ? { sessions: { [MAIN]: opts.resume } } : {}),
|
|
47
48
|
createdAt: now,
|
|
48
49
|
updatedAt: now,
|
|
@@ -478,6 +479,27 @@ export async function renameChat(id, title) {
|
|
|
478
479
|
await writeMeta(state.meta);
|
|
479
480
|
return { meta: state.meta };
|
|
480
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* File an agent's chat under a project, or under none (`null`). The chat is
|
|
484
|
+
* then listed with the project, and the agent reads the project's context
|
|
485
|
+
* with its next message. Project chats and channels belong where
|
|
486
|
+
* their scope says and cannot move; the caller checks that the project exists.
|
|
487
|
+
*/
|
|
488
|
+
export async function setChatProject(id, project) {
|
|
489
|
+
const state = await loadState(id);
|
|
490
|
+
if (!state)
|
|
491
|
+
return { error: "not found", status: 404 };
|
|
492
|
+
if (state.meta.scope.kind !== "agent")
|
|
493
|
+
return { error: "only an agent's chat can be filed under a project", status: 409 };
|
|
494
|
+
if (project)
|
|
495
|
+
state.meta.project = project;
|
|
496
|
+
else
|
|
497
|
+
delete state.meta.project;
|
|
498
|
+
for (const seat of state.seats.values())
|
|
499
|
+
seat.needsContext = true;
|
|
500
|
+
await writeMeta(state.meta);
|
|
501
|
+
return { meta: state.meta };
|
|
502
|
+
}
|
|
481
503
|
export async function deleteChat(id) {
|
|
482
504
|
const state = await loadState(id);
|
|
483
505
|
if (!state)
|
|
@@ -33,6 +33,7 @@ export declare const chatRoutes: (import("./router.js").Route<"agents.sessions",
|
|
|
33
33
|
slug: z.ZodOptional<z.ZodString>;
|
|
34
34
|
}, z.core.$strip>>;
|
|
35
35
|
resume: z.ZodOptional<z.ZodString>;
|
|
36
|
+
project: z.ZodOptional<z.ZodString>;
|
|
36
37
|
}, z.core.$strip>> | import("./router.js").Route<"chats.delete", import("./router.js").Reply<{
|
|
37
38
|
error?: string;
|
|
38
39
|
}>, "/api/chats/:id", undefined> | import("./router.js").Route<"chats.elicitation", import("./router.js").Reply<{
|
|
@@ -80,7 +81,9 @@ export declare const chatRoutes: (import("./router.js").Route<"agents.sessions",
|
|
|
80
81
|
error?: string;
|
|
81
82
|
}>, "/api/chats/:id", z.ZodObject<{
|
|
82
83
|
title: z.ZodString;
|
|
83
|
-
}, z.core.$strip>> | import("./router.js").Route<"chats.resetSession", import("../../core/chat/types.js").ChatMeta, "/api/chats/:id/reset-session", undefined> | import("./router.js").Route<"chats.
|
|
84
|
+
}, z.core.$strip>> | import("./router.js").Route<"chats.resetSession", import("../../core/chat/types.js").ChatMeta, "/api/chats/:id/reset-session", undefined> | import("./router.js").Route<"chats.setProject", import("../../core/chat/types.js").ChatMeta, "/api/chats/:id/project", z.ZodObject<{
|
|
85
|
+
project: z.ZodNullable<z.ZodString>;
|
|
86
|
+
}, z.core.$strip>> | import("./router.js").Route<"chats.setVibeable", import("../../core/chat/types.js").ChatMeta, "/api/chats/:id/vibeable", z.ZodObject<{
|
|
84
87
|
slug: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
85
88
|
}, z.core.$strip>> | import("./router.js").Route<"chats.steer", import("./router.js").Reply<{
|
|
86
89
|
error: string;
|
package/dist/server/api/chats.js
CHANGED
|
@@ -2,7 +2,7 @@ import { promises as fs } from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { getAgent } from "../../core/agents.js";
|
|
5
|
-
import { answerElicitation, cancelChat, createChat, deleteChat, forkChat, getChat, listAgentSessionsFor, listChats, postMessage, renameChat, resetSession, resolvePermission, setChatConfig, setChatVibeable, steerChat, stopChatTask, subscribeChat, } from "../../core/chat/sessions.js";
|
|
5
|
+
import { answerElicitation, cancelChat, createChat, deleteChat, forkChat, getChat, listAgentSessionsFor, listChats, postMessage, renameChat, resetSession, resolvePermission, setChatConfig, setChatProject, setChatVibeable, steerChat, stopChatTask, subscribeChat, } from "../../core/chat/sessions.js";
|
|
6
6
|
import { attachmentPath, saveAttachment } from "../../core/chat/store.js";
|
|
7
7
|
import { getProject } from "../../core/projects.js";
|
|
8
8
|
import { MIME } from "./mime.js";
|
|
@@ -25,6 +25,8 @@ const NewChat = z.object({
|
|
|
25
25
|
agent: z.string().optional(),
|
|
26
26
|
scope: z.object({ kind: z.string(), runId: z.string().optional(), bundle: z.string().optional(), slug: z.string().optional() }).optional(),
|
|
27
27
|
resume: z.string().optional(),
|
|
28
|
+
/** An agent's chat started in a project: listed with the project (meta.project). */
|
|
29
|
+
project: z.string().optional(),
|
|
28
30
|
});
|
|
29
31
|
/** An action on a running chat: `{ok}` when it went through, 409 with the reason when the chat refused. */
|
|
30
32
|
const act = (name, path, summary, body, run) => route({ name, method: "POST", path, summary, errors: 400, body }, async (c) => {
|
|
@@ -64,17 +66,29 @@ async function scopeOf(body) {
|
|
|
64
66
|
return { agent, scope: { kind: "knowledge", ...(s.bundle ? { bundle: s.bundle } : {}) } };
|
|
65
67
|
return { agent, scope: { kind: "general" } };
|
|
66
68
|
}
|
|
69
|
+
/** The slug of an existing project, else a 404 (or the error reading it). */
|
|
70
|
+
async function projectSlug(slug) {
|
|
71
|
+
const found = await getProject(slug).catch((err) => {
|
|
72
|
+
throw new ApiError(projectErrors(err.message), err.message);
|
|
73
|
+
});
|
|
74
|
+
if (!found)
|
|
75
|
+
fail(404, "project not found");
|
|
76
|
+
return found.slug;
|
|
77
|
+
}
|
|
67
78
|
/** Chats: ACP sessions with a coding agent, their event stream, and what a person does in them. */
|
|
68
79
|
export const chatRoutes = [
|
|
69
80
|
route({ name: "chats.list", method: "GET", path: "/api/chats", summary: "every chat with its live state" }, async () => ({ chats: await listChats() })),
|
|
70
|
-
route({ name: "chats.create", method: "POST", path: "/api/chats", summary: "start a chat {agent, scope, resume?}", body: NewChat }, async (c) => {
|
|
81
|
+
route({ name: "chats.create", method: "POST", path: "/api/chats", summary: "start a chat {agent, scope, resume?, project?}", body: NewChat }, async (c) => {
|
|
71
82
|
// `resume` continues one of the agent's own sessions (see agents.sessions).
|
|
72
83
|
const body = await c.body();
|
|
73
84
|
const { agent, scope } = await scopeOf(body);
|
|
74
85
|
if (!AGENTS.includes(agent))
|
|
75
86
|
fail(400, "agent must be claude, codex, or pi");
|
|
87
|
+
if (body.project && scope.kind !== "agent")
|
|
88
|
+
fail(400, "only an agent's chat takes a project");
|
|
89
|
+
const project = body.project ? await projectSlug(body.project) : undefined;
|
|
76
90
|
try {
|
|
77
|
-
return await createChat({ agent: agent, scope, ...(body.resume ? { resume: body.resume } : {}) });
|
|
91
|
+
return await createChat({ agent: agent, scope, ...(project ? { project } : {}), ...(body.resume ? { resume: body.resume } : {}) });
|
|
78
92
|
}
|
|
79
93
|
catch (err) {
|
|
80
94
|
throw new ApiError(400, err.message);
|
|
@@ -96,6 +110,18 @@ export const chatRoutes = [
|
|
|
96
110
|
const result = await validChat(renameChat(c.params.id, title), "invalid chat id or body");
|
|
97
111
|
return reply(result.error ? (result.error === "not found" ? 404 : 400) : 200, result);
|
|
98
112
|
}),
|
|
113
|
+
route({
|
|
114
|
+
name: "chats.setProject",
|
|
115
|
+
method: "POST",
|
|
116
|
+
path: "/api/chats/:id/project",
|
|
117
|
+
summary: "file an agent's chat under a project {project}, or under none {project: null}",
|
|
118
|
+
errors: 400,
|
|
119
|
+
body: z.object({ project: z.string().nullable() }),
|
|
120
|
+
}, async (c) => {
|
|
121
|
+
const { project } = await c.body();
|
|
122
|
+
const slug = project ? await projectSlug(project) : null;
|
|
123
|
+
return metaOf(await validChat(setChatProject(c.params.id, slug)));
|
|
124
|
+
}),
|
|
99
125
|
// Replays from ?after=N, then streams new events as they happen.
|
|
100
126
|
route({ name: "chats.events", method: "GET", path: "/api/chats/:id/events", summary: "SSE: the chat's events from ?after=N", raw: true }, async ({ req, res, params, query }) => {
|
|
101
127
|
const afterSeq = Number(query.get("after") ?? "0") || 0;
|
|
@@ -218,6 +218,7 @@ export declare const routes: (Route<"agents.addJournal", {
|
|
|
218
218
|
slug: z.ZodOptional<z.ZodString>;
|
|
219
219
|
}, z.core.$strip>>;
|
|
220
220
|
resume: z.ZodOptional<z.ZodString>;
|
|
221
|
+
project: z.ZodOptional<z.ZodString>;
|
|
221
222
|
}, z.core.$strip>> | Route<"chats.delete", import("./router.js").Reply<{
|
|
222
223
|
error?: string;
|
|
223
224
|
}>, "/api/chats/:id", undefined> | Route<"chats.elicitation", import("./router.js").Reply<{
|
|
@@ -265,7 +266,9 @@ export declare const routes: (Route<"agents.addJournal", {
|
|
|
265
266
|
error?: string;
|
|
266
267
|
}>, "/api/chats/:id", z.ZodObject<{
|
|
267
268
|
title: z.ZodString;
|
|
268
|
-
}, z.core.$strip>> | Route<"chats.resetSession", import("../../core/chat/types.js").ChatMeta, "/api/chats/:id/reset-session", undefined> | Route<"chats.
|
|
269
|
+
}, z.core.$strip>> | Route<"chats.resetSession", import("../../core/chat/types.js").ChatMeta, "/api/chats/:id/reset-session", undefined> | Route<"chats.setProject", import("../../core/chat/types.js").ChatMeta, "/api/chats/:id/project", z.ZodObject<{
|
|
270
|
+
project: z.ZodNullable<z.ZodString>;
|
|
271
|
+
}, z.core.$strip>> | Route<"chats.setVibeable", import("../../core/chat/types.js").ChatMeta, "/api/chats/:id/vibeable", z.ZodObject<{
|
|
269
272
|
slug: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
270
273
|
}, z.core.$strip>> | Route<"chats.steer", import("./router.js").Reply<{
|
|
271
274
|
error: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netnodeag/kraftwerk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.74.0",
|
|
4
4
|
"description": "Open-source agentic workspace for teams — where people and AI agents get work done together: agents (Claude Code, Codex, Pi), skills, shared knowledge, repeatable workflows, and deterministic verification",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|