@integrity-labs/agt-cli 0.10.0 → 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.0",
3
+ "version": "0.10.2",
4
4
  "description": "Augmented CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/claude-scheduler.ts"],"sourcesContent":["/**\n * In-process scheduler for Claude Code agents.\n *\n * On each manager poll cycle, checks if any tasks are due and fires them\n * via `claude -p`. State persists to disk so nextFireAt/lastFireAt survive\n * manager restarts.\n */\n\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { Cron } from 'croner';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SchedulerTaskState {\n taskId: string;\n templateId: string;\n name: string;\n agentCodeName: string;\n agentId: string;\n scheduleKind: 'cron' | 'every' | 'at';\n scheduleExpr: string | null;\n scheduleEvery: string | null;\n scheduleAt: string | null;\n timezone: string;\n prompt: string;\n sessionTarget: string;\n deliveryMode: string;\n deliveryChannel: string | null;\n deliveryTo: string | null;\n enabled: boolean;\n triggeredAt: number | null; // epoch ms — manual trigger from webapp\n nextFireAt: number | null; // epoch ms, null = completed one-shot\n lastFireAt: number | null;\n lastStatus: 'ok' | 'error' | null;\n firedCount: number;\n}\n\nexport interface SchedulerState {\n version: 1;\n tasks: Record<string, SchedulerTaskState>;\n updatedAt: string;\n}\n\nexport interface SchedulerTaskInput {\n id: string;\n template_id: string;\n name: string;\n schedule_kind: 'cron' | 'every' | 'at';\n schedule_expr: string | null;\n schedule_every: string | null;\n schedule_at: string | null;\n timezone: string;\n prompt: string;\n session_target: string;\n delivery_mode: string;\n delivery_channel: string | null;\n delivery_to: string | null;\n enabled: boolean;\n triggered_at?: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Interval parsing (reused from Claude Code adapter)\n// ---------------------------------------------------------------------------\n\nfunction parseIntervalMs(scheduleEvery: string | null): number {\n if (!scheduleEvery) return 60 * 60_000; // 1hr default\n const match = scheduleEvery.match(/^(\\d+)\\s*(m|min|h|hr|d)$/i);\n if (!match) return 60 * 60_000;\n const value = parseInt(match[1]!, 10);\n const unit = match[2]!.toLowerCase();\n if (unit === 'h' || unit === 'hr') return value * 60 * 60_000;\n if (unit === 'd') return value * 24 * 60 * 60_000;\n return value * 60_000; // minutes\n}\n\n// ---------------------------------------------------------------------------\n// Next-fire computation\n// ---------------------------------------------------------------------------\n\nexport function computeNextFire(\n kind: 'cron' | 'every' | 'at',\n expr: string | null,\n every: string | null,\n at: string | null,\n timezone: string,\n afterMs?: number,\n): number | null {\n const now = afterMs ?? Date.now();\n\n if (kind === 'cron' && expr) {\n try {\n const cron = new Cron(expr, { timezone: timezone || undefined });\n const next = cron.nextRun(new Date(now));\n return next ? next.getTime() : null;\n } catch {\n return null;\n }\n }\n\n if (kind === 'every') {\n const intervalMs = parseIntervalMs(every);\n return now + intervalMs;\n }\n\n if (kind === 'at' && at) {\n const ts = new Date(at).getTime();\n return isNaN(ts) ? null : ts;\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// State persistence\n// ---------------------------------------------------------------------------\n\nfunction getStateDir(codeName: string): string {\n return join(homedir(), '.augmented', codeName, 'claudecode');\n}\n\nfunction getStatePath(codeName: string): string {\n return join(getStateDir(codeName), 'scheduler-state.json');\n}\n\nexport function loadSchedulerState(codeName: string): SchedulerState {\n const path = getStatePath(codeName);\n if (existsSync(path)) {\n try {\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch { /* corrupted — start fresh */ }\n }\n return { version: 1, tasks: {}, updatedAt: new Date().toISOString() };\n}\n\nexport function saveSchedulerState(codeName: string, state: SchedulerState): void {\n const dir = getStateDir(codeName);\n mkdirSync(dir, { recursive: true });\n state.updatedAt = new Date().toISOString();\n const path = getStatePath(codeName);\n const tmpPath = path + '.tmp';\n writeFileSync(tmpPath, JSON.stringify(state, null, 2));\n renameSync(tmpPath, path);\n}\n\n// ---------------------------------------------------------------------------\n// Sync API tasks → scheduler state\n// ---------------------------------------------------------------------------\n\nexport function syncTasksToScheduler(\n codeName: string,\n agentId: string,\n tasks: SchedulerTaskInput[],\n): SchedulerState {\n const state = loadSchedulerState(codeName);\n const desiredIds = new Set(tasks.map((t) => t.id));\n\n // Remove tasks no longer in API\n for (const id of Object.keys(state.tasks)) {\n if (!desiredIds.has(id)) {\n delete state.tasks[id];\n }\n }\n\n // Add or update tasks\n for (const t of tasks) {\n const existing = state.tasks[t.id];\n if (existing) {\n // Only recompute nextFireAt if the schedule definition actually changed.\n // Without this guard, every sync cycle resets nextFireAt from \"now\",\n // preventing past-due tasks from ever being detected as ready.\n const scheduleChanged =\n existing.scheduleKind !== t.schedule_kind ||\n existing.scheduleExpr !== t.schedule_expr ||\n existing.scheduleEvery !== t.schedule_every ||\n existing.scheduleAt !== t.schedule_at ||\n existing.timezone !== t.timezone;\n\n // Update mutable fields, preserve fire history\n existing.name = t.name;\n existing.templateId = t.template_id;\n existing.scheduleKind = t.schedule_kind;\n existing.scheduleExpr = t.schedule_expr;\n existing.scheduleEvery = t.schedule_every;\n existing.scheduleAt = t.schedule_at;\n existing.timezone = t.timezone;\n existing.prompt = t.prompt;\n existing.sessionTarget = t.session_target;\n existing.deliveryMode = t.delivery_mode;\n existing.deliveryChannel = t.delivery_channel;\n existing.deliveryTo = t.delivery_to;\n existing.enabled = t.enabled;\n if (t.triggered_at) existing.triggeredAt = new Date(t.triggered_at).getTime();\n if (scheduleChanged) {\n existing.nextFireAt = computeNextFire(\n t.schedule_kind, t.schedule_expr, t.schedule_every, t.schedule_at,\n t.timezone, existing.lastFireAt ?? undefined,\n );\n }\n } else {\n // New task\n state.tasks[t.id] = {\n taskId: t.id,\n templateId: t.template_id,\n name: t.name,\n agentCodeName: codeName,\n agentId,\n scheduleKind: t.schedule_kind,\n scheduleExpr: t.schedule_expr,\n scheduleEvery: t.schedule_every,\n scheduleAt: t.schedule_at,\n timezone: t.timezone,\n prompt: t.prompt,\n sessionTarget: t.session_target,\n deliveryMode: t.delivery_mode,\n deliveryChannel: t.delivery_channel,\n deliveryTo: t.delivery_to,\n enabled: t.enabled,\n triggeredAt: t.triggered_at ? new Date(t.triggered_at).getTime() : null,\n nextFireAt: computeNextFire(\n t.schedule_kind, t.schedule_expr, t.schedule_every, t.schedule_at, t.timezone,\n ),\n lastFireAt: null,\n lastStatus: null,\n firedCount: 0,\n };\n }\n }\n\n saveSchedulerState(codeName, state);\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Ready-task detection\n// ---------------------------------------------------------------------------\n\nexport function getReadyTasks(state: SchedulerState): SchedulerTaskState[] {\n const now = Date.now();\n const ready = Object.values(state.tasks).filter((t) => {\n if (!t.enabled) return false;\n // Manual trigger: triggered_at is set and hasn't been fired yet\n if (t.triggeredAt) {\n const triggerReady = !t.lastFireAt || t.triggeredAt > t.lastFireAt;\n if (!triggerReady) {\n // Debug: trigger was already consumed\n }\n if (triggerReady) return true;\n }\n // Normal schedule\n return t.nextFireAt !== null && t.nextFireAt <= now;\n });\n // Deduplicate by templateId — only fire one task per template per cycle\n const seen = new Set<string>();\n return ready.filter((t) => {\n if (seen.has(t.templateId)) return false;\n seen.add(t.templateId);\n return true;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Post-execution state update\n// ---------------------------------------------------------------------------\n\nexport function markTaskFired(\n codeName: string,\n taskId: string,\n status: 'ok' | 'error',\n): SchedulerState {\n const state = loadSchedulerState(codeName);\n const task = state.tasks[taskId];\n if (!task) return state;\n\n task.lastFireAt = Date.now();\n task.lastStatus = status;\n task.firedCount++;\n\n // Compute next fire\n if (task.scheduleKind === 'at') {\n // One-shot — mark as completed\n task.nextFireAt = null;\n } else {\n task.nextFireAt = computeNextFire(\n task.scheduleKind, task.scheduleExpr, task.scheduleEvery, task.scheduleAt,\n task.timezone, task.lastFireAt,\n );\n }\n\n saveSchedulerState(codeName, state);\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Find a task by template ID (for work triggers)\n// ---------------------------------------------------------------------------\n\nexport function findTaskByTemplate(state: SchedulerState, templateId: string): SchedulerTaskState | undefined {\n return Object.values(state.tasks).find(\n (t) => t.templateId === templateId && t.enabled,\n );\n}\n\nexport function getProjectDir(codeName: string): string {\n return join(homedir(), '.augmented', codeName, 'project');\n}\n"],"mappings":"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","names":[]}