@femtomc/mu-agent 26.2.53 → 26.2.55

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.
@@ -1 +1 @@
1
- {"version":3,"file":"messaging-setup.d.ts","sourceRoot":"","sources":["../../src/extensions/messaging-setup.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,YAAY,EAA6C,MAAM,+BAA+B,CAAC;AAwiC7G,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,YAAY,QA0PvD;AAED,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"messaging-setup.d.ts","sourceRoot":"","sources":["../../src/extensions/messaging-setup.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,YAAY,EAA6C,MAAM,+BAA+B,CAAC;AAyiC7G,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,YAAY,QA0PvD;AAED,eAAe,uBAAuB,CAAC"}
@@ -77,6 +77,7 @@ const ADAPTERS = [
77
77
  "Create bot with @BotFather and place token in control_plane.adapters.telegram.bot_token.",
78
78
  "Set control_plane.adapters.telegram.webhook_secret to a random secret string.",
79
79
  "Call Telegram setWebhook using URL <public-base-url>/webhooks/telegram and matching secret_token.",
80
+ "Link your Telegram identity to control-plane policy (mu control link --channel telegram --actor-id <telegram-user-id> --tenant-id telegram-bot --role <viewer|contributor|operator>).",
80
81
  "Optionally set control_plane.adapters.telegram.bot_username.",
81
82
  "Send /mu in Telegram chat, then /mu-setup verify telegram.",
82
83
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"server-tools.d.ts","sourceRoot":"","sources":["../../src/extensions/server-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAgElE,MAAM,MAAM,wBAAwB,GAAG;IACtC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC,CAAC;AA4SF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,GAAE,wBAA6B,QAQzF;AAED,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,YAAY,QAS5D;AAED,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"server-tools.d.ts","sourceRoot":"","sources":["../../src/extensions/server-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAgElE,MAAM,MAAM,wBAAwB,GAAG;IACtC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC,CAAC;AAoXF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,GAAE,wBAA6B,QAQzF;AAED,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,YAAY,QAS5D;AAED,eAAe,oBAAoB,CAAC"}
@@ -283,6 +283,83 @@ function registerServerTools(pi, opts) {
283
283
  }
284
284
  },
285
285
  });
286
+ const IdentityParams = Type.Object({
287
+ action: StringEnum(["list", "link", "unlink"]),
288
+ channel: Type.Optional(Type.String({ description: "Channel: slack, discord, telegram (for link)" })),
289
+ actor_id: Type.Optional(Type.String({ description: "Channel actor ID (for link)" })),
290
+ tenant_id: Type.Optional(Type.String({ description: "Channel tenant ID (for link)" })),
291
+ role: Type.Optional(Type.String({ description: "Role: operator, contributor, viewer (for link, default operator)" })),
292
+ binding_id: Type.Optional(Type.String({ description: "Binding ID (for link/unlink)" })),
293
+ actor_binding_id: Type.Optional(Type.String({ description: "Actor binding ID (for unlink, usually same as binding_id)" })),
294
+ reason: Type.Optional(Type.String({ description: "Unlink reason (for unlink)" })),
295
+ include_inactive: Type.Optional(Type.Boolean({ description: "Include inactive bindings (for list)" })),
296
+ });
297
+ pi.registerTool({
298
+ name: "mu_identity",
299
+ label: "Identity",
300
+ description: "Manage identity bindings. Actions: list (enumerate bindings), link (create binding), unlink (self-unlink).",
301
+ parameters: IdentityParams,
302
+ async execute(_toolCallId, params) {
303
+ switch (params.action) {
304
+ case "list": {
305
+ const query = new URLSearchParams();
306
+ if (params.include_inactive)
307
+ query.set("include_inactive", "true");
308
+ const data = await fetchMuJson(`/api/identities${query.size > 0 ? `?${query.toString()}` : ""}`);
309
+ return textResult(toJsonText(data), { count: data.count });
310
+ }
311
+ case "link": {
312
+ const channel = trimOrNull(params.channel);
313
+ const actorId = trimOrNull(params.actor_id);
314
+ const tenantId = trimOrNull(params.tenant_id);
315
+ if (!channel)
316
+ return textResult("Error: channel required for link");
317
+ if (!actorId)
318
+ return textResult("Error: actor_id required for link");
319
+ if (!tenantId)
320
+ return textResult("Error: tenant_id required for link");
321
+ const body = {
322
+ channel,
323
+ actor_id: actorId,
324
+ tenant_id: tenantId,
325
+ };
326
+ const role = trimOrNull(params.role);
327
+ if (role)
328
+ body.role = role;
329
+ const bindingId = trimOrNull(params.binding_id);
330
+ if (bindingId)
331
+ body.binding_id = bindingId;
332
+ const result = await fetchMuJson("/api/identities/link", {
333
+ method: "POST",
334
+ body,
335
+ });
336
+ return textResult(toJsonText(result), result);
337
+ }
338
+ case "unlink": {
339
+ const bindingId = trimOrNull(params.binding_id);
340
+ const actorBindingId = trimOrNull(params.actor_binding_id);
341
+ if (!bindingId)
342
+ return textResult("Error: binding_id required for unlink");
343
+ if (!actorBindingId)
344
+ return textResult("Error: actor_binding_id required for unlink");
345
+ const body = {
346
+ binding_id: bindingId,
347
+ actor_binding_id: actorBindingId,
348
+ };
349
+ const reason = trimOrNull(params.reason);
350
+ if (reason)
351
+ body.reason = reason;
352
+ const result = await fetchMuJson("/api/identities/unlink", {
353
+ method: "POST",
354
+ body,
355
+ });
356
+ return textResult(toJsonText(result), result);
357
+ }
358
+ default:
359
+ return textResult(`Unknown action: ${params.action}`);
360
+ }
361
+ },
362
+ });
286
363
  pi.registerCommand("mu-status", {
287
364
  description: "Show concise mu server status",
288
365
  handler: async (_args, ctx) => {
@@ -323,16 +400,16 @@ export function serverToolsExtension(pi, opts = {}) {
323
400
  registerServerTools(pi, {
324
401
  allowForumPost: opts.allowForumPost ?? true,
325
402
  toolIntroLine: opts.toolIntroLine ??
326
- "Tools: mu_status, mu_control_plane, mu_issues, mu_forum, mu_events, mu_runs, mu_activities, mu_heartbeats.",
403
+ "Tools: mu_status, mu_control_plane, mu_issues, mu_forum, mu_events, mu_runs, mu_activities, mu_heartbeats, mu_identity.",
327
404
  extraSystemPromptLines: opts.extraSystemPromptLines ?? [],
328
405
  });
329
406
  }
330
407
  export function serverToolsReadOnlyExtension(pi) {
331
408
  registerServerTools(pi, {
332
409
  allowForumPost: false,
333
- toolIntroLine: "Tools: mu_status, mu_control_plane, mu_issues, mu_forum(read/topics), mu_events, mu_runs(read), mu_messaging_setup(read).",
410
+ toolIntroLine: "Tools: mu_status, mu_control_plane, mu_issues, mu_forum(read/topics), mu_events, mu_runs(read), mu_messaging_setup, mu_identity.",
334
411
  extraSystemPromptLines: [
335
- "Mutating tool actions are disabled in operator mode; propose mutations via approved /mu commands.",
412
+ "You have Bash, Read, Write, and Edit tools. Use them to run mu CLI commands, edit config files, and complete tasks directly.",
336
413
  ],
337
414
  });
338
415
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@femtomc/mu-agent",
3
- "version": "26.2.53",
3
+ "version": "26.2.55",
4
4
  "description": "Shared agent runtime for mu chat, orchestration roles, and serve extensions.",
5
5
  "keywords": [
6
6
  "mu",
@@ -23,7 +23,7 @@
23
23
  "prompts/**"
24
24
  ],
25
25
  "dependencies": {
26
- "@femtomc/mu-core": "26.2.53",
26
+ "@femtomc/mu-core": "26.2.54",
27
27
  "@mariozechner/pi-agent-core": "^0.52.12",
28
28
  "@mariozechner/pi-ai": "^0.52.12",
29
29
  "@mariozechner/pi-coding-agent": "^0.52.12",
@@ -18,6 +18,8 @@ missing fields: {{missing_fields}}
18
18
  2) Generate values you CAN create yourself (e.g. webhook_secret — run `openssl rand -hex 32` via Bash).
19
19
  3) Write config via mu_messaging_setup tool: call mu_messaging_setup(action="apply", adapter="{{adapter_id}}", fields={...}) with ALL missing field values. This writes config and reloads the control plane in one step.
20
20
  4) After config is applied, call provider APIs (e.g. Telegram setWebhook) via Bash/curl.
21
- 5) Run {{verify_command}} to confirm everything works.
21
+ 5) Link an identity binding via mu_identity tool: call mu_identity(action="link", channel="{{adapter_id}}", actor_id="<actor>", tenant_id="<tenant>") do NOT use `mu control link` CLI.
22
+ 6) Run {{verify_command}} to confirm everything works.
22
23
 
23
24
  Do NOT give the user copy-paste commands or tutorials. Do the work yourself.
25
+ For identity operations, always use the mu_identity tool (not `mu control link` or direct .mu file access).