@integrity-labs/agt-cli 0.10.1 → 0.10.2

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/mcp/index.js CHANGED
@@ -21624,6 +21624,187 @@ server.tool(
21624
21624
  };
21625
21625
  }
21626
21626
  );
21627
+ server.tool(
21628
+ "schedule.update",
21629
+ // Lead with user phrasings the agent should match against, then explain
21630
+ // the two modes. Order matters for tool selection.
21631
+ 'Update an existing scheduled task. USE THIS TOOL when the user says: "change the schedule for X", "run the daily report at 10am instead of 9am", "pause the standup schedule", "move the weekly digest to Mondays", "make this report more concise", "add a section about X to the daily summary", "tell the Y schedule to also cover Z". Two modes: (1) DIRECT FIELD UPDATES \u2014 set cron_expression/interval/timezone/channel/enabled/name/prompt to change those values directly. (2) LLM DESCRIPTION REWRITE \u2014 pass description_feedback to have the platform rewrite the task prompt based on natural-language feedback (e.g. "make this more concise" or "add a section about the team backlog"). Default for LLM rewrites is preview-then-apply: call once to get the proposed rewrite, show the diff to the user, call again with auto_apply=true on confirmation. Direct field updates apply immediately. The two modes are mutually exclusive \u2014 one request is EITHER a field update OR a description rewrite.',
21632
+ {
21633
+ task_id: external_exports.string().describe("The task ID to update (from schedule.list)"),
21634
+ // Direct-field mode
21635
+ name: external_exports.string().optional().describe("New task display name"),
21636
+ schedule_kind: external_exports.enum(["cron", "every", "at"]).optional().describe(
21637
+ "Schedule type. If changing, must also provide the matching expression field."
21638
+ ),
21639
+ schedule_expr: external_exports.string().optional().describe(
21640
+ 'Cron expression (e.g. "0 9 * * 1-5") when schedule_kind is cron'
21641
+ ),
21642
+ schedule_every: external_exports.string().optional().describe(
21643
+ 'Interval string (e.g. "30m", "2h") when schedule_kind is every'
21644
+ ),
21645
+ schedule_at: external_exports.string().optional().describe(
21646
+ "ISO 8601 timestamp when schedule_kind is at (one-off task)"
21647
+ ),
21648
+ timezone: external_exports.string().optional().describe('IANA timezone (e.g. "America/Los_Angeles")'),
21649
+ prompt: external_exports.string().optional().describe(
21650
+ "Raw new prompt text. Use description_feedback instead for LLM-assisted rewrites."
21651
+ ),
21652
+ delivery_channel: external_exports.string().optional().describe(
21653
+ 'Where results are delivered (e.g. "slack", "telegram", "email")'
21654
+ ),
21655
+ delivery_to: external_exports.string().optional().describe(
21656
+ "Channel/chat/email identifier for delivery"
21657
+ ),
21658
+ enabled: external_exports.boolean().optional().describe(
21659
+ "Set to false to pause the schedule without deleting it"
21660
+ ),
21661
+ // LLM rewrite mode
21662
+ description_feedback: external_exports.string().optional().describe(
21663
+ 'Natural-language feedback about how to rewrite the task prompt. Examples: "make this more concise", "add a section covering the team backlog", "focus on blockers instead of progress". Triggers an LLM rewrite \u2014 mutually exclusive with direct prompt updates.'
21664
+ ),
21665
+ auto_apply: external_exports.boolean().optional().describe(
21666
+ "For description_feedback only. Default false (preview the rewrite, then call again with auto_apply: true to commit)."
21667
+ )
21668
+ },
21669
+ async (params) => {
21670
+ const data = await apiPost("/host/schedules/update", {
21671
+ agent_id: AGT_AGENT_ID,
21672
+ ...params
21673
+ });
21674
+ if (params.description_feedback) {
21675
+ const lines = [];
21676
+ lines.push(data.applied ? "\u2705 Applied schedule prompt rewrite" : "\u{1F4CB} Proposed schedule prompt rewrite (preview)");
21677
+ lines.push("");
21678
+ if (data.proposed) {
21679
+ lines.push(`Rationale: ${data.proposed.rationale}`);
21680
+ lines.push("");
21681
+ lines.push("## Before");
21682
+ lines.push("```");
21683
+ lines.push(data.current?.prompt ?? "(empty)");
21684
+ lines.push("```");
21685
+ lines.push("## After");
21686
+ lines.push("```");
21687
+ lines.push(data.proposed.new_prompt);
21688
+ lines.push("```");
21689
+ }
21690
+ if (!data.applied) {
21691
+ lines.push("");
21692
+ lines.push("---");
21693
+ lines.push("Show this diff to the user. If they confirm, call `schedule.update` again with the same `task_id` and `description_feedback` plus `auto_apply: true` to commit the change.");
21694
+ }
21695
+ return { content: [{ type: "text", text: lines.join("\n") }] };
21696
+ }
21697
+ const updatedFields = [];
21698
+ for (const key of ["name", "schedule_kind", "schedule_expr", "schedule_every", "schedule_at", "timezone", "prompt", "delivery_channel", "delivery_to", "enabled"]) {
21699
+ if (params[key] !== void 0) updatedFields.push(key);
21700
+ }
21701
+ const summary = `Updated scheduled task ${params.task_id} (${updatedFields.join(", ") || "no changes"})`;
21702
+ return { content: [{ type: "text", text: summary }] };
21703
+ }
21704
+ );
21705
+ server.tool(
21706
+ "plugin.list",
21707
+ `List the plugins currently installed on this agent, with their current typed context values and a preview of any freeform overrides. Use this when the user asks "what plugins do I have?", "show me the plugins", "what is the Coding plugin configured with?", or before calling plugin.improve to see what fields exist and what they're set to.`,
21708
+ {},
21709
+ async () => {
21710
+ const data = await apiPost("/host/list-plugins", {
21711
+ agent_id: AGT_AGENT_ID
21712
+ });
21713
+ if (!data.plugins.length) {
21714
+ return { content: [{ type: "text", text: "No plugins installed on this agent." }] };
21715
+ }
21716
+ const lines = [];
21717
+ lines.push(`## Installed Plugins (${data.plugins.length})
21718
+ `);
21719
+ for (const p of data.plugins) {
21720
+ lines.push(`### ${p.plugin_name} \`${p.plugin_slug}\` (v${p.version})`);
21721
+ if (p.description) lines.push(p.description);
21722
+ lines.push(`- Skills: ${p.skill_count}`);
21723
+ if (p.has_schema && p.context_field_count > 0) {
21724
+ lines.push(`- Context values:`);
21725
+ for (const [key, val] of Object.entries(p.current_values)) {
21726
+ lines.push(` - \`${key}\`: ${JSON.stringify(val)}`);
21727
+ }
21728
+ } else if (p.has_schema) {
21729
+ lines.push(`- Context: schema declared but no values set (all defaults)`);
21730
+ } else {
21731
+ lines.push(`- Context: no typed schema (freeform overrides only)`);
21732
+ }
21733
+ if (p.has_overrides) {
21734
+ lines.push(`- Freeform overrides (preview):`);
21735
+ lines.push(` > ${p.overrides_preview.replace(/\n/g, "\n > ")}`);
21736
+ }
21737
+ lines.push("");
21738
+ }
21739
+ lines.push("To update any plugin's behavior, use the `plugin.improve` tool with the user's feedback.");
21740
+ return { content: [{ type: "text", text: lines.join("\n") }] };
21741
+ }
21742
+ );
21743
+ server.tool(
21744
+ "plugin.improve",
21745
+ // Description leads with the user phrasings the agent should match against,
21746
+ // then explains the safety rule. Order matters — Claude\'s tool selection
21747
+ // weights the first line of a description heavily.
21748
+ `Update, edit, or add a rule to an installed plugin (e.g. the Coding plugin, the Knowledge Base plugin, the Slack plugin). USE THIS TOOL when the user says any of: "update the X plugin", "add a rule to plugin Y", "tell the X plugin not to do Z", "change the X plugin so it does Y", "the Coding plugin should always/never...", "remember this for the X plugin". This is the ONLY correct way to modify a plugin's behavior. NEVER edit SKILL.md files under .claude/skills/plugin-* directly \u2014 those files are derived from the platform database and your edits will be silently overwritten on the next manager refresh. The platform calls an LLM to translate the user's request into a structured update of the plugin's typed context fields and/or freeform overrides text, then returns a diff for you to show the user. Default flow is preview-then-apply: call once to get the proposed diff, show it to the user, then call again with auto_apply=true if they confirm. Only works for plugins that are actually installed on this agent.`,
21749
+ {
21750
+ plugin_slug: external_exports.string().optional().describe('Plugin slug to improve (e.g. "claude-code-github"). Either this or plugin_id is required.'),
21751
+ plugin_id: external_exports.string().optional().describe("Plugin UUID. Either this or plugin_slug is required."),
21752
+ feedback: external_exports.string().min(1).describe("The user's feedback in natural language. What should the plugin do differently?"),
21753
+ transcript_snippet: external_exports.string().optional().describe("Optional short transcript snippet showing the behavior the user flagged. Helps the LLM understand context. Max 2000 chars."),
21754
+ auto_apply: external_exports.boolean().optional().describe("If true, apply the proposed update immediately without preview. Default false (preview-then-apply). Only set to true after the user has confirmed the proposed diff.")
21755
+ },
21756
+ async (params) => {
21757
+ if (!params.plugin_slug && !params.plugin_id) {
21758
+ return {
21759
+ content: [{ type: "text", text: "Error: either plugin_slug or plugin_id is required." }]
21760
+ };
21761
+ }
21762
+ const data = await apiPost("/host/improve-plugin", {
21763
+ agent_id: AGT_AGENT_ID,
21764
+ plugin_slug: params.plugin_slug,
21765
+ plugin_id: params.plugin_id,
21766
+ feedback: params.feedback,
21767
+ transcript_snippet: params.transcript_snippet,
21768
+ auto_apply: params.auto_apply ?? false
21769
+ });
21770
+ const lines = [];
21771
+ lines.push(data.applied ? "\u2705 Applied plugin context update" : "\u{1F4CB} Proposed plugin context update (preview)");
21772
+ lines.push("");
21773
+ lines.push(`Rationale: ${data.proposed.rationale}`);
21774
+ if (data.proposed.changed_fields.length > 0) {
21775
+ lines.push("");
21776
+ lines.push("## Typed field changes");
21777
+ for (const field of data.proposed.changed_fields) {
21778
+ const before = JSON.stringify(data.current.values[field] ?? null);
21779
+ const after = JSON.stringify(data.proposed.values[field] ?? null);
21780
+ lines.push(`- \`${field}\`: ${before} \u2192 ${after}`);
21781
+ }
21782
+ }
21783
+ if (data.proposed.appended_to_overrides) {
21784
+ lines.push("");
21785
+ lines.push("## Overrides change");
21786
+ const before = data.current.overrides || "(empty)";
21787
+ const after = data.proposed.overrides || "(empty)";
21788
+ lines.push("Before:");
21789
+ lines.push("```");
21790
+ lines.push(before);
21791
+ lines.push("```");
21792
+ lines.push("After:");
21793
+ lines.push("```");
21794
+ lines.push(after);
21795
+ lines.push("```");
21796
+ }
21797
+ if (!data.applied) {
21798
+ lines.push("");
21799
+ lines.push("---");
21800
+ lines.push("Show this diff to the user. If they confirm, call `plugin.improve` again with `auto_apply: true` and the same arguments to apply.");
21801
+ } else {
21802
+ lines.push("");
21803
+ lines.push("Update applied. The manager will re-render the plugin's SKILL.md files on the next refresh cycle.");
21804
+ }
21805
+ return { content: [{ type: "text", text: lines.join("\n") }] };
21806
+ }
21807
+ );
21627
21808
  function groupByStatus(items) {
21628
21809
  const groups = {};
21629
21810
  for (const item of items) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Augmented CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "bin": {