@integrity-labs/agt-cli 0.11.0 → 0.12.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/dist/bin/agt.js +6 -4
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-QU7FBXH3.js → chunk-M6FSTVGG.js} +2 -2
- package/dist/chunk-M6FSTVGG.js.map +1 -0
- package/dist/{chunk-WTMVQND4.js → chunk-S5VHDDAJ.js} +576 -232
- package/dist/chunk-S5VHDDAJ.js.map +1 -0
- package/dist/{claude-scheduler-7PVWQHWU.js → claude-scheduler-CLSMSF5W.js} +2 -2
- package/dist/lib/manager-worker.js +340 -23
- package/dist/lib/manager-worker.js.map +1 -1
- package/mcp/index.js +23 -3
- package/mcp/slack-channel.js +59 -4
- package/package.json +1 -1
- package/dist/chunk-QU7FBXH3.js.map +0 -1
- package/dist/chunk-WTMVQND4.js.map +0 -1
- /package/dist/{claude-scheduler-7PVWQHWU.js.map → claude-scheduler-CLSMSF5W.js.map} +0 -0
package/mcp/index.js
CHANGED
|
@@ -20987,6 +20987,24 @@ var StdioServerTransport = class {
|
|
|
20987
20987
|
|
|
20988
20988
|
// src/index.ts
|
|
20989
20989
|
import { spawn } from "child_process";
|
|
20990
|
+
var DeliveryTargetSchema = external_exports.union([
|
|
20991
|
+
external_exports.object({
|
|
20992
|
+
kind: external_exports.literal("channel"),
|
|
20993
|
+
provider: external_exports.enum(["slack", "telegram"]),
|
|
20994
|
+
channel_id: external_exports.string().optional(),
|
|
20995
|
+
chat_id: external_exports.string().optional()
|
|
20996
|
+
}).describe("Post to a Slack channel or Telegram chat. Provide channel_id for Slack or chat_id for Telegram."),
|
|
20997
|
+
external_exports.object({
|
|
20998
|
+
kind: external_exports.literal("dm"),
|
|
20999
|
+
person_id: external_exports.string().uuid(),
|
|
21000
|
+
follow_reports_to: external_exports.boolean(),
|
|
21001
|
+
medium: external_exports.enum(["auto", "slack", "telegram"]).describe(
|
|
21002
|
+
"'auto' picks Slack \u2192 Telegram based on the person's linked IDs and the agent's configured channels"
|
|
21003
|
+
)
|
|
21004
|
+
}).describe(
|
|
21005
|
+
"DM a specific person. When follow_reports_to=true, person_id must equal the agent's current reports_to person_id; at fire time the runtime re-resolves to whoever the agent's reports_to points at, so role changes are auto-followed."
|
|
21006
|
+
)
|
|
21007
|
+
]);
|
|
20990
21008
|
var AGT_HOST = process.env.AGT_HOST;
|
|
20991
21009
|
var AGT_API_KEY = process.env.AGT_API_KEY;
|
|
20992
21010
|
var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
|
|
@@ -21586,7 +21604,9 @@ server.tool(
|
|
|
21586
21604
|
timezone: external_exports.string().optional().describe('Timezone (default: UTC, e.g. "Australia/Sydney")'),
|
|
21587
21605
|
prompt: external_exports.string().describe("What to do when the task fires"),
|
|
21588
21606
|
delivery_channel: external_exports.string().optional().describe('Channel platform to deliver results to (e.g. "slack", "telegram"). Default: "slack" if available.'),
|
|
21589
|
-
delivery_to:
|
|
21607
|
+
delivery_to: DeliveryTargetSchema.optional().describe(
|
|
21608
|
+
"Where the task output should be delivered. Structured object: either { kind: 'channel', provider, channel_id? | chat_id? } to post to a Slack channel / Telegram chat, or { kind: 'dm', person_id, follow_reports_to, medium } to DM a person. For 'reply to the channel this request came from', pass the incoming message's channel_id. For 'DM my manager', use follow_reports_to=true with the agent's current reports_to person_id. Legacy string forms ('channel:<id>', 'chat:<id>', 'slack_user:<id>') are rejected server-side \u2014 use the structured form."
|
|
21609
|
+
),
|
|
21590
21610
|
delivery_mode: external_exports.enum(["announce", "none"]).optional().describe('Delivery mode: "announce" sends output to delivery_channel, "none" suppresses. Default: "announce".')
|
|
21591
21611
|
},
|
|
21592
21612
|
async (params) => {
|
|
@@ -21652,8 +21672,8 @@ server.tool(
|
|
|
21652
21672
|
delivery_channel: external_exports.string().optional().describe(
|
|
21653
21673
|
'Where results are delivered (e.g. "slack", "telegram", "email")'
|
|
21654
21674
|
),
|
|
21655
|
-
delivery_to:
|
|
21656
|
-
"
|
|
21675
|
+
delivery_to: DeliveryTargetSchema.optional().describe(
|
|
21676
|
+
"Structured delivery target (see schedule.create description for shape). Pass null-equivalent by omitting the field; pass a new structured target to change routing."
|
|
21657
21677
|
),
|
|
21658
21678
|
enabled: external_exports.boolean().optional().describe(
|
|
21659
21679
|
"Set to false to pause the schedule without deleting it"
|
package/mcp/slack-channel.js
CHANGED
|
@@ -13922,7 +13922,9 @@ var mcp = new Server(
|
|
|
13922
13922
|
tools: {}
|
|
13923
13923
|
},
|
|
13924
13924
|
instructions: [
|
|
13925
|
-
'Messages from Slack arrive as <channel source="slack" user="
|
|
13925
|
+
'Messages from Slack arrive as <channel source="slack" user="<slack-id>" user_name="<display-name>" channel="..." thread_ts="...">.',
|
|
13926
|
+
"Address users by their user_name (display name), NEVER by the raw user ID.",
|
|
13927
|
+
"In threads with multiple participants, the CURRENT speaker is always the one in the <channel> tag on the latest message \u2014 do not conflate them with other participants who spoke earlier.",
|
|
13926
13928
|
"Reply using the slack.reply tool, passing channel and thread_ts from the tag.",
|
|
13927
13929
|
"For threaded replies, always include thread_ts so the response appears in the same thread.",
|
|
13928
13930
|
"When someone @mentions you in a channel, respond helpfully in that thread.",
|
|
@@ -14129,7 +14131,10 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
14129
14131
|
}
|
|
14130
14132
|
cursor = data.response_metadata?.next_cursor || void 0;
|
|
14131
14133
|
} while (cursor && allMessages.length < limit);
|
|
14132
|
-
const
|
|
14134
|
+
const uniqueUserIds = [...new Set(allMessages.map((m) => m.user))];
|
|
14135
|
+
const resolved = await Promise.all(uniqueUserIds.map(async (id) => [id, await resolveUserName(id)]));
|
|
14136
|
+
const nameById = new Map(resolved);
|
|
14137
|
+
const formatted = allMessages.map((m) => `[${m.ts}] ${nameById.get(m.user) ?? m.user} (<@${m.user}>): ${m.text}`).join("\n");
|
|
14133
14138
|
return {
|
|
14134
14139
|
content: [{
|
|
14135
14140
|
type: "text",
|
|
@@ -14212,7 +14217,7 @@ ${formatted}` : "Thread is empty or not found."
|
|
|
14212
14217
|
});
|
|
14213
14218
|
if (!step2.ok) {
|
|
14214
14219
|
return {
|
|
14215
|
-
content: [{ type: "text", text: `Slack upload
|
|
14220
|
+
content: [{ type: "text", text: `Slack upload POST failed: ${step2.status} ${step2.statusText}` }],
|
|
14216
14221
|
isError: true
|
|
14217
14222
|
};
|
|
14218
14223
|
}
|
|
@@ -14269,19 +14274,50 @@ async function getBotUserId() {
|
|
|
14269
14274
|
return null;
|
|
14270
14275
|
}
|
|
14271
14276
|
}
|
|
14277
|
+
var userNameCache = /* @__PURE__ */ new Map();
|
|
14278
|
+
async function resolveUserName(userId) {
|
|
14279
|
+
if (!userId || userId === "unknown") return userId ?? "unknown";
|
|
14280
|
+
const cached2 = userNameCache.get(userId);
|
|
14281
|
+
if (cached2 !== void 0) return cached2;
|
|
14282
|
+
try {
|
|
14283
|
+
const res = await fetch(
|
|
14284
|
+
`https://slack.com/api/users.info?user=${encodeURIComponent(userId)}`,
|
|
14285
|
+
{ headers: { Authorization: `Bearer ${BOT_TOKEN}` } }
|
|
14286
|
+
);
|
|
14287
|
+
const data = await res.json();
|
|
14288
|
+
const name = data.user?.profile?.display_name || data.user?.profile?.real_name || userId;
|
|
14289
|
+
userNameCache.set(userId, name);
|
|
14290
|
+
return name;
|
|
14291
|
+
} catch {
|
|
14292
|
+
userNameCache.set(userId, userId);
|
|
14293
|
+
return userId;
|
|
14294
|
+
}
|
|
14295
|
+
}
|
|
14296
|
+
var currentWs = null;
|
|
14297
|
+
var isShuttingDown = false;
|
|
14272
14298
|
async function connectSocketMode() {
|
|
14299
|
+
if (isShuttingDown) return;
|
|
14273
14300
|
const res = await fetch("https://slack.com/api/apps.connections.open", {
|
|
14274
14301
|
method: "POST",
|
|
14275
14302
|
headers: { Authorization: `Bearer ${APP_TOKEN}` }
|
|
14276
14303
|
});
|
|
14277
14304
|
const data = await res.json();
|
|
14305
|
+
if (isShuttingDown) return;
|
|
14278
14306
|
if (!data.ok || !data.url) {
|
|
14279
14307
|
process.stderr.write(`slack-channel: Socket Mode connection failed: ${data.error}
|
|
14280
14308
|
`);
|
|
14281
|
-
setTimeout(connectSocketMode, 1e4);
|
|
14309
|
+
if (!isShuttingDown) setTimeout(connectSocketMode, 1e4);
|
|
14282
14310
|
return;
|
|
14283
14311
|
}
|
|
14284
14312
|
const ws = new WebSocket(data.url);
|
|
14313
|
+
if (isShuttingDown) {
|
|
14314
|
+
try {
|
|
14315
|
+
ws.close();
|
|
14316
|
+
} catch {
|
|
14317
|
+
}
|
|
14318
|
+
return;
|
|
14319
|
+
}
|
|
14320
|
+
currentWs = ws;
|
|
14285
14321
|
ws.onopen = () => {
|
|
14286
14322
|
process.stderr.write("slack-channel: Socket Mode connected\n");
|
|
14287
14323
|
};
|
|
@@ -14329,12 +14365,14 @@ async function connectSocketMode() {
|
|
|
14329
14365
|
if (channel && ts) {
|
|
14330
14366
|
trackPendingMessage(channel, threadTs, ts);
|
|
14331
14367
|
}
|
|
14368
|
+
const userName = await resolveUserName(user);
|
|
14332
14369
|
await mcp.notification({
|
|
14333
14370
|
method: "notifications/claude/channel",
|
|
14334
14371
|
params: {
|
|
14335
14372
|
content: text,
|
|
14336
14373
|
meta: {
|
|
14337
14374
|
user,
|
|
14375
|
+
user_name: userName,
|
|
14338
14376
|
channel,
|
|
14339
14377
|
thread_ts: threadTs,
|
|
14340
14378
|
event_type: evt.type,
|
|
@@ -14348,6 +14386,8 @@ async function connectSocketMode() {
|
|
|
14348
14386
|
}
|
|
14349
14387
|
};
|
|
14350
14388
|
ws.onclose = () => {
|
|
14389
|
+
if (currentWs === ws) currentWs = null;
|
|
14390
|
+
if (isShuttingDown) return;
|
|
14351
14391
|
process.stderr.write("slack-channel: Socket Mode disconnected, reconnecting...\n");
|
|
14352
14392
|
setTimeout(connectSocketMode, 5e3);
|
|
14353
14393
|
};
|
|
@@ -14356,6 +14396,21 @@ async function connectSocketMode() {
|
|
|
14356
14396
|
`);
|
|
14357
14397
|
};
|
|
14358
14398
|
}
|
|
14399
|
+
function shutdown(reason, exitCode = 0) {
|
|
14400
|
+
if (isShuttingDown) return;
|
|
14401
|
+
isShuttingDown = true;
|
|
14402
|
+
process.stderr.write(`slack-channel: ${reason} \u2014 closing Socket Mode and exiting
|
|
14403
|
+
`);
|
|
14404
|
+
try {
|
|
14405
|
+
currentWs?.close();
|
|
14406
|
+
} catch {
|
|
14407
|
+
}
|
|
14408
|
+
setTimeout(() => process.exit(exitCode), 500).unref();
|
|
14409
|
+
}
|
|
14410
|
+
process.stdin.on("close", () => shutdown("stdin closed"));
|
|
14411
|
+
process.stdin.on("end", () => shutdown("stdin ended"));
|
|
14412
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
14413
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
14359
14414
|
botUserId = await getBotUserId();
|
|
14360
14415
|
process.stderr.write(`slack-channel: Bot user ID: ${botUserId}
|
|
14361
14416
|
`);
|
package/package.json
CHANGED
|
@@ -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 if (isNaN(ts)) return null;\n // If the 'at' timestamp is in the past and afterMs is set (meaning we already\n // fired), return null to prevent re-firing on state rebuild.\n if (afterMs && ts <= afterMs) return null;\n return 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":[]}
|