@netnodeag/kraftwerk 0.25.0 → 0.26.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.
@@ -8,7 +8,7 @@ import { listWorkflows, getWorkflow } from "./workflows.js";
8
8
  import { dockerStatus, triggerRun, stopRun } from "./runner.js";
9
9
  import { cancelChat, createChat, deleteChat, disposeAllBackends, getChat, listChats, postMessage, resolvePermission, subscribeChat, } from "./chat/sessions.js";
10
10
  import { bundleDetail, conceptDetail, createBundle, knowledgeIndex, putConcept, verifyFromUi, } from "./knowledge.js";
11
- import { deleteMember, getMember, listMembers, saveMember, teamRoot, } from "./team.js";
11
+ import { deleteMember, getMember, listMembers, saveMember, setMemberArchived, teamRoot, } from "./team.js";
12
12
  import { deleteAgentSkill, getSkill, listAgentSkills, listSkills, readSkill, saveAgentSkill, skillsRoot, } from "./skills.js";
13
13
  import { discoverInstances, registerInstance, unregisterInstance } from "./instances.js";
14
14
  import { getSettings, saveSettings } from "./settings.js";
@@ -358,6 +358,16 @@ async function handleApi(req, res, url) {
358
358
  }
359
359
  }
360
360
  }
361
+ // POST /api/team/:slug/archive — archive/unarchive a member ({ archived: boolean })
362
+ if (seg.length === 4 && seg[1] === "team" && seg[3] === "archive" && method === "POST") {
363
+ try {
364
+ const body = JSON.parse(await readBody(req));
365
+ return json(res, await setMemberArchived(decodeURIComponent(seg[2]), body.archived === true));
366
+ }
367
+ catch (err) {
368
+ return json(res, { error: err.message }, 400);
369
+ }
370
+ }
361
371
  // GET/POST /api/team/:slug/skills — the agent's own skills / create or update one
362
372
  if (seg.length === 4 && seg[1] === "team" && seg[3] === "skills") {
363
373
  const slug = decodeURIComponent(seg[2]);
@@ -30,6 +30,8 @@ export interface TeamMember {
30
30
  * Absent = all discovered skills; empty list = no skills.
31
31
  */
32
32
  skills?: string[];
33
+ /** Archived: hidden from the active roster, restorable any time. */
34
+ archived?: boolean;
33
35
  }
34
36
  export interface TeamMemberDetail extends TeamMember {
35
37
  /** Contents of system.md — the member's system prompt. */
@@ -58,4 +60,6 @@ export interface SaveMemberInput {
58
60
  system?: string;
59
61
  }
60
62
  export declare function saveMember(input: SaveMemberInput): Promise<TeamMemberDetail>;
63
+ /** Archive/unarchive a member: toggles `archived:` in agent.yml, nothing else. */
64
+ export declare function setMemberArchived(slug: string, archived: boolean): Promise<TeamMemberDetail>;
61
65
  export declare function deleteMember(slug: string): Promise<void>;
@@ -52,6 +52,7 @@ function normalize(slug, raw) {
52
52
  workflows: Array.isArray(raw.workflows) ? raw.workflows.map(String) : [],
53
53
  knowledge: Array.isArray(raw.knowledge) ? raw.knowledge.map(String) : [],
54
54
  ...(Array.isArray(raw.skills) ? { skills: raw.skills.map(String) } : {}),
55
+ ...(raw.archived === true ? { archived: true } : {}),
55
56
  };
56
57
  }
57
58
  export async function listMembers() {
@@ -101,6 +102,11 @@ export async function saveMember(input) {
101
102
  const slug = input.slug ? safeMemberSlug(input.slug) : slugFromName(name);
102
103
  const dir = path.join(await teamRoot(), slug);
103
104
  await fs.mkdir(dir, { recursive: true });
105
+ // Profile edits must not silently unarchive: carry the flag over.
106
+ const existing = await fs
107
+ .readFile(path.join(dir, "agent.yml"), "utf8")
108
+ .then((raw) => (parse(raw) ?? {}))
109
+ .catch(() => null);
104
110
  const yml = {
105
111
  name,
106
112
  emoji: input.emoji?.trim() || "🤖",
@@ -112,11 +118,30 @@ export async function saveMember(input) {
112
118
  workflows: (input.workflows ?? []).map(String),
113
119
  knowledge: (input.knowledge ?? []).map(String),
114
120
  ...(input.skills ? { skills: input.skills.map(String) } : {}),
121
+ ...(existing?.archived === true ? { archived: true } : {}),
115
122
  };
116
123
  await fs.writeFile(path.join(dir, "agent.yml"), stringify(yml));
117
124
  await fs.writeFile(path.join(dir, "system.md"), (input.system ?? "").trim() + "\n");
118
125
  return (await getMember(slug));
119
126
  }
127
+ /** Archive/unarchive a member: toggles `archived:` in agent.yml, nothing else. */
128
+ export async function setMemberArchived(slug, archived) {
129
+ const dir = path.join(await teamRoot(), safeMemberSlug(slug));
130
+ let raw;
131
+ try {
132
+ raw = (parse(await fs.readFile(path.join(dir, "agent.yml"), "utf8")) ?? {});
133
+ }
134
+ catch {
135
+ throw new Error("agent not found");
136
+ }
137
+ const yml = { ...raw };
138
+ if (archived)
139
+ yml.archived = true;
140
+ else
141
+ delete yml.archived;
142
+ await fs.writeFile(path.join(dir, "agent.yml"), stringify(yml));
143
+ return (await getMember(slug));
144
+ }
120
145
  export async function deleteMember(slug) {
121
146
  const dir = path.join(await teamRoot(), safeMemberSlug(slug));
122
147
  await fs.rm(dir, { recursive: true, force: true });