@integrity-labs/agt-cli 0.27.8-test.9 → 0.27.9-test.11

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/mcp/index.js CHANGED
@@ -21061,8 +21061,11 @@ var DeliveryTargetSchema = external_exports.union([
21061
21061
  channel_id: external_exports.string().optional(),
21062
21062
  chat_id: external_exports.string().optional(),
21063
21063
  conversation_id: external_exports.string().optional(),
21064
- service_url: external_exports.string().optional()
21065
- }).describe("Post to a Slack channel, Telegram chat, or Microsoft Teams conversation. Provide channel_id for Slack, chat_id for Telegram, or conversation_id + service_url for Teams."),
21064
+ service_url: external_exports.string().optional(),
21065
+ thread_ts: external_exports.string().nullable().optional().describe(
21066
+ `Slack only (ENG-6038). The originating thread's thread_ts when the user asked for the result back in the thread the request came from ("report back here" inside a thread) \u2014 take it from the inbound message's <channel> envelope. Pass null to mean 'top-level on purpose' (e.g. the user said "post it to the channel" \u2014 null also suppresses server-side thread auto-injection on one-time tasks). Omit only when the request didn't come from a thread.`
21067
+ )
21068
+ }).describe("Post to a Slack channel, Telegram chat, or Microsoft Teams conversation. Provide channel_id for Slack, chat_id for Telegram, or conversation_id + service_url for Teams. For Slack, thread_ts optionally threads the delivery under the originating conversation."),
21066
21069
  external_exports.object({
21067
21070
  kind: external_exports.literal("dm"),
21068
21071
  person_id: external_exports.string().uuid(),
@@ -21076,6 +21079,7 @@ var DeliveryTargetSchema = external_exports.union([
21076
21079
  ]);
21077
21080
  var AGT_HOST = process.env.AGT_HOST;
21078
21081
  var AGT_API_KEY = process.env.AGT_API_KEY;
21082
+ var AGT_AGENT_SESSION_TOKEN = process.env.AGT_AGENT_SESSION_TOKEN;
21079
21083
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
21080
21084
  var AGT_AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME;
21081
21085
  var AGT_APP_URL = (process.env.AGT_APP_URL?.trim() || "https://app.augmented.team").replace(/\/+$/, "");
@@ -21086,9 +21090,9 @@ function readRunId() {
21086
21090
  }
21087
21091
  var AGT_RUN_ID = readRunId();
21088
21092
  var AGT_TOKEN = process.env.AGT_TOKEN ?? "";
21089
- if (!AGT_HOST || !AGT_AGENT_ID || !AGT_TOKEN && !AGT_API_KEY) {
21093
+ if (!AGT_HOST || !AGT_AGENT_ID || !AGT_TOKEN && !AGT_API_KEY && !AGT_AGENT_SESSION_TOKEN) {
21090
21094
  console.error(
21091
- "augmented-mcp: Missing required env vars. Need AGT_HOST, AGT_AGENT_ID, and AGT_TOKEN or AGT_API_KEY"
21095
+ "augmented-mcp: Missing required env vars. Need AGT_HOST, AGT_AGENT_ID, and one of AGT_AGENT_SESSION_TOKEN, AGT_TOKEN, or AGT_API_KEY"
21092
21096
  );
21093
21097
  process.exit(1);
21094
21098
  }
@@ -21110,6 +21114,9 @@ async function refreshToken() {
21110
21114
  return AGT_TOKEN;
21111
21115
  }
21112
21116
  async function getToken() {
21117
+ if (AGT_AGENT_SESSION_TOKEN) {
21118
+ return AGT_AGENT_SESSION_TOKEN;
21119
+ }
21113
21120
  if (AGT_API_KEY && (!AGT_TOKEN || Date.now() > tokenExpiresAt - 5 * 6e4)) {
21114
21121
  if (!exchangeInFlight) {
21115
21122
  exchangeInFlight = refreshToken().finally(() => {
@@ -21141,13 +21148,18 @@ async function apiPost(path, body, retried = false, timeoutMs = 15e3) {
21141
21148
  body: JSON.stringify(body),
21142
21149
  signal: controller.signal
21143
21150
  });
21144
- if (res.status === 401 && AGT_API_KEY && !retried) {
21151
+ if (res.status === 401 && AGT_API_KEY && !AGT_AGENT_SESSION_TOKEN && !retried) {
21145
21152
  clearTimeout(timeout);
21146
21153
  tokenExpiresAt = 0;
21147
21154
  return apiPost(path, body, true, timeoutMs);
21148
21155
  }
21149
21156
  if (!res.ok) {
21150
21157
  const text = await res.text().catch(() => res.statusText);
21158
+ if (res.status === 401 && AGT_AGENT_SESSION_TOKEN) {
21159
+ throw new Error(
21160
+ `API ${path} returned 401: agent-session rejected (expired or revoked). Re-run \`agt impersonate connect\` to mint a fresh session. (${text})`
21161
+ );
21162
+ }
21151
21163
  throw new Error(`API ${path} returned ${res.status}: ${text}`);
21152
21164
  }
21153
21165
  return await res.json();
@@ -21177,7 +21189,7 @@ server.tool(
21177
21189
  }
21178
21190
  const grouped = groupByStatus(data.items);
21179
21191
  const lines = [];
21180
- for (const status of ["in_progress", "todo", "backlog", "done"]) {
21192
+ for (const status of ["in_progress", "todo", "backlog", "done", "failed"]) {
21181
21193
  const items = grouped[status];
21182
21194
  if (!items?.length) continue;
21183
21195
  lines.push(`
@@ -21236,11 +21248,11 @@ server.tool(
21236
21248
  );
21237
21249
  server.tool(
21238
21250
  "kanban_move",
21239
- "Move a kanban item to a different status column.",
21251
+ 'Move a kanban item to a different status column. Use status="failed" to mark a task that was attempted but could not complete (matches the hosted kanban_move enum).',
21240
21252
  {
21241
21253
  id: external_exports.string().optional().describe("Item UUID (preferred)"),
21242
21254
  title: external_exports.string().optional().describe("Item title for fuzzy match (if no id)"),
21243
- status: external_exports.enum(["backlog", "todo", "in_progress", "done"]).describe("Target status"),
21255
+ status: external_exports.enum(["backlog", "todo", "in_progress", "done", "failed"]).describe('Target status. "failed" closes the row as a failed attempt; there is no "cancelled" status \u2014 close no-longer-needed work via kanban_done with an explanatory result.'),
21244
21256
  notes: external_exports.string().optional().describe("Progress notes")
21245
21257
  },
21246
21258
  async (params) => {
@@ -21728,7 +21740,7 @@ server.tool(
21728
21740
  prompt: external_exports.string().describe("What to do when the task fires"),
21729
21741
  delivery_channel: external_exports.string().optional().describe('Channel platform to deliver results to (e.g. "slack", "telegram"). Default: "slack" if available.'),
21730
21742
  delivery_to: DeliveryTargetSchema.optional().describe(
21731
- "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."
21743
+ "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 'report back HERE' said inside a Slack thread, also pass thread_ts from the inbound envelope so the result lands in that thread; if the user wants the channel top-level despite asking from a thread, pass thread_ts: null. 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."
21732
21744
  ),
21733
21745
  delivery_mode: external_exports.enum(["announce", "none"]).optional().describe('Delivery mode: "announce" sends output to delivery_channel, "none" suppresses. Default: "announce".')
21734
21746
  },
@@ -21801,7 +21813,7 @@ server.tool(
21801
21813
  'Where results are delivered (e.g. "slack", "telegram", "email")'
21802
21814
  ),
21803
21815
  delivery_to: DeliveryTargetSchema.optional().describe(
21804
- "Structured delivery target (see schedule_create description for shape). Pass null-equivalent by omitting the field; pass a new structured target to change routing."
21816
+ "Structured delivery target (see schedule_create description for shape). Pass null-equivalent by omitting the field; pass a new structured target to change routing. delivery_to is replaced wholesale: to STOP a task threading into a Slack conversation ('post it to the channel instead'), pass the channel target again WITHOUT thread_ts; to start threading, include thread_ts."
21805
21817
  ),
21806
21818
  enabled: external_exports.boolean().optional().describe(
21807
21819
  "Set to false to pause the schedule without deleting it"
@@ -22243,7 +22255,8 @@ function statusLabel(status) {
22243
22255
  backlog: "Backlog",
22244
22256
  todo: "To Do",
22245
22257
  in_progress: "In Progress",
22246
- done: "Done"
22258
+ done: "Done",
22259
+ failed: "Failed"
22247
22260
  };
22248
22261
  return labels[status] ?? status;
22249
22262
  }
@@ -22317,9 +22330,13 @@ var LOCAL_TOOL_NAMES = /* @__PURE__ */ new Set([
22317
22330
  "dashboards_request_refresh",
22318
22331
  "dashboards_pending_refreshes",
22319
22332
  "dashboards_persist_widget",
22333
+ "artefacts_list",
22334
+ "artefacts_get",
22335
+ "artefacts_get_source_chunk",
22336
+ // ADR-0017 Projects container (the reclaimed projects_* namespace — read-only
22337
+ // in v1; no projects_get_source_chunk, a project is a container not a document).
22320
22338
  "projects_list",
22321
- "projects_get",
22322
- "projects_get_source_chunk"
22339
+ "projects_get"
22323
22340
  ]);
22324
22341
  async function registerForwardedApiTools() {
22325
22342
  const apiTools = await discoverApiTools();
@@ -22353,76 +22370,135 @@ async function registerForwardedApiTools() {
22353
22370
  }
22354
22371
  return { registered, skipped };
22355
22372
  }
22356
- server.tool(
22357
- "projects_list",
22358
- "List artefacts (websites, slide decks, mockups) this agent has previously published. Call this BEFORE re-publishing to find and modify existing work instead of creating duplicates.",
22359
- {
22360
- publisher: external_exports.string().optional().describe('Filter by publisher (e.g. "here-now")'),
22361
- kind: external_exports.enum(["mockup", "deck", "site", "app", "other"]).optional().describe("Filter by artefact kind"),
22362
- limit: external_exports.number().int().min(1).max(100).optional().describe("Maximum projects to return (default 50, max 100)")
22363
- },
22364
- async (params) => {
22365
- const data = await apiPost("/host/my-published-projects", {
22373
+ async function listPublishedArtefactsText(params) {
22374
+ const data = await apiPost(
22375
+ "/host/my-published-artefacts",
22376
+ {
22366
22377
  agent_id: AGT_AGENT_ID,
22367
22378
  publisher: params.publisher,
22368
22379
  kind: params.kind,
22369
22380
  limit: params.limit
22370
- });
22371
- if (!data.projects.length) {
22372
- return { content: [{ type: "text", text: "No published projects yet." }] };
22373
22381
  }
22374
- const lines = data.projects.map((p) => {
22375
- const title = p.title ?? "(untitled)";
22376
- const expires = p.expires_at ? ` expires ${p.expires_at}` : "";
22377
- return `- [${p.kind}] ${title} \u2014 ${p.live_url} (id: ${p.id}, ${p.mode}, published ${p.published_at}${expires})`;
22378
- });
22379
- return { content: [{ type: "text", text: lines.join("\n") }] };
22380
- }
22382
+ );
22383
+ if (!data.artefacts.length) {
22384
+ return "No published artefacts yet.";
22385
+ }
22386
+ return data.artefacts.map((p) => {
22387
+ const title = p.title ?? "(untitled)";
22388
+ const expires = p.expires_at ? ` expires ${p.expires_at}` : "";
22389
+ return `- [${p.kind}] ${title} \u2014 ${p.live_url} (id: ${p.id}, ${p.mode}, published ${p.published_at}${expires})`;
22390
+ }).join("\n");
22391
+ }
22392
+ async function getPublishedArtefactText(artefactId) {
22393
+ const data = await apiPost(`/host/published-artefact/${encodeURIComponent(artefactId)}`, {
22394
+ agent_id: AGT_AGENT_ID
22395
+ });
22396
+ const p = data.artefact;
22397
+ return [
22398
+ `Artefact: ${p.title ?? "(untitled)"} [${p.kind}]`,
22399
+ `Publisher: ${p.publisher} (${p.mode})`,
22400
+ `Live URL: ${p.live_url}`,
22401
+ p.claim_url ? `Claim URL: ${p.claim_url}` : null,
22402
+ `Published: ${p.published_at}`,
22403
+ p.expires_at ? `Expires: ${p.expires_at}` : null,
22404
+ `Last modified: ${p.last_modified_at}`,
22405
+ p.has_source_html ? `Source HTML: ${p.source_html_length} bytes (call artefacts_get_source_chunk to fetch)` : "(source HTML not preserved for this artefact)"
22406
+ ].filter((s) => s !== null).join("\n");
22407
+ }
22408
+ async function getPublishedArtefactSourceChunkText(artefactId, offset, limit) {
22409
+ const data = await apiPost(`/host/published-artefact/${encodeURIComponent(artefactId)}/source-chunk`, {
22410
+ agent_id: AGT_AGENT_ID,
22411
+ offset,
22412
+ limit
22413
+ });
22414
+ const trailer = data.end_of_content ? "\n\n---\n(end of source)" : `
22415
+
22416
+ ---
22417
+ (more \u2014 next offset: ${data.offset + data.length}, total: ${data.total_length} bytes)`;
22418
+ return data.chunk + trailer;
22419
+ }
22420
+ var artefactListSchema = {
22421
+ publisher: external_exports.string().optional().describe('Filter by publisher (e.g. "here-now")'),
22422
+ kind: external_exports.enum(["mockup", "deck", "site", "app", "other"]).optional().describe("Filter by artefact kind"),
22423
+ limit: external_exports.number().int().min(1).max(100).optional().describe("Maximum artefacts to return (default 50, max 100)")
22424
+ };
22425
+ server.tool(
22426
+ "artefacts_list",
22427
+ "List artefacts (websites, slide decks, mockups) this agent has previously published. Call this BEFORE re-publishing to find and modify existing work instead of creating duplicates.",
22428
+ artefactListSchema,
22429
+ async (params) => ({
22430
+ content: [{ type: "text", text: await listPublishedArtefactsText(params) }]
22431
+ })
22381
22432
  );
22382
22433
  server.tool(
22383
- "projects_get",
22384
- "Fetch metadata for a single published project. Returns the project record without the source HTML \u2014 call projects_get_source_chunk to retrieve the HTML in chunks when you need to modify it.",
22434
+ "artefacts_get",
22435
+ "Fetch metadata for a single published artefact. Returns the artefact record without the source HTML \u2014 call artefacts_get_source_chunk to retrieve the HTML in chunks when you need to modify it.",
22385
22436
  {
22386
- project_id: external_exports.string().uuid().describe("The project id returned by projects_list")
22437
+ artefact_id: external_exports.string().uuid().describe("The artefact id returned by artefacts_list")
22387
22438
  },
22388
- async (params) => {
22389
- const data = await apiPost(`/host/published-project/${encodeURIComponent(params.project_id)}`, {
22390
- agent_id: AGT_AGENT_ID
22391
- });
22392
- const p = data.project;
22393
- const header = [
22394
- `Project: ${p.title ?? "(untitled)"} [${p.kind}]`,
22395
- `Publisher: ${p.publisher} (${p.mode})`,
22396
- `Live URL: ${p.live_url}`,
22397
- p.claim_url ? `Claim URL: ${p.claim_url}` : null,
22398
- `Published: ${p.published_at}`,
22399
- p.expires_at ? `Expires: ${p.expires_at}` : null,
22400
- `Last modified: ${p.last_modified_at}`,
22401
- p.has_source_html ? `Source HTML: ${p.source_html_length} bytes (call projects_get_source_chunk to fetch)` : "(source HTML not preserved for this project)"
22402
- ].filter((s) => s !== null).join("\n");
22403
- return { content: [{ type: "text", text: header }] };
22404
- }
22439
+ async (params) => ({
22440
+ content: [{ type: "text", text: await getPublishedArtefactText(params.artefact_id) }]
22441
+ })
22405
22442
  );
22406
22443
  server.tool(
22407
- "projects_get_source_chunk",
22408
- "Fetch a chunk of source HTML for a published project. Use this to assemble the HTML for modification when projects_get reports a non-zero source_html_length.",
22444
+ "artefacts_get_source_chunk",
22445
+ "Fetch a chunk of source HTML for a published artefact. Use this to assemble the HTML for modification when artefacts_get reports a non-zero source_html_length.",
22409
22446
  {
22410
- project_id: external_exports.string().uuid().describe("The project id returned by projects_list"),
22447
+ artefact_id: external_exports.string().uuid().describe("The artefact id returned by artefacts_list"),
22411
22448
  offset: external_exports.number().int().min(0).describe("Byte offset into the source HTML to start from"),
22412
22449
  limit: external_exports.number().int().min(1).max(65536).optional().describe("Max bytes to return (default 32KB, max 64KB)")
22413
22450
  },
22414
- async (params) => {
22415
- const data = await apiPost(`/host/published-project/${encodeURIComponent(params.project_id)}/source-chunk`, {
22416
- agent_id: AGT_AGENT_ID,
22417
- offset: params.offset,
22418
- limit: params.limit
22419
- });
22420
- const trailer = data.end_of_content ? "\n\n---\n(end of source)" : `
22421
-
22422
- ---
22423
- (more \u2014 next offset: ${data.offset + data.length}, total: ${data.total_length} bytes)`;
22424
- return { content: [{ type: "text", text: data.chunk + trailer }] };
22451
+ async (params) => ({
22452
+ content: [
22453
+ { type: "text", text: await getPublishedArtefactSourceChunkText(params.artefact_id, params.offset, params.limit) }
22454
+ ]
22455
+ })
22456
+ );
22457
+ async function listProjectsText(params) {
22458
+ const data = await apiPost("/host/my-projects", {
22459
+ agent_id: AGT_AGENT_ID,
22460
+ status: params.status,
22461
+ limit: params.limit
22462
+ });
22463
+ if (!data.projects.length) {
22464
+ return "No projects yet. Projects are created by a human in the console; ask one to create a project to group your work under.";
22425
22465
  }
22466
+ return data.projects.map((p) => `- ${p.name} [${p.status}] (id: ${p.id}, created ${p.created_at})`).join("\n");
22467
+ }
22468
+ async function getProjectText(projectId) {
22469
+ const data = await apiPost(
22470
+ `/host/project/${encodeURIComponent(projectId)}`,
22471
+ { agent_id: AGT_AGENT_ID }
22472
+ );
22473
+ const p = data.project;
22474
+ return [
22475
+ `Project: ${p.name} [${p.status}]`,
22476
+ `Id: ${p.id}`,
22477
+ p.linear_project_id ? `Linear project: ${p.linear_project_id}` : null,
22478
+ `Created: ${p.created_at}`,
22479
+ `Last updated: ${p.updated_at}`
22480
+ ].filter((s) => s !== null).join("\n");
22481
+ }
22482
+ server.tool(
22483
+ "projects_list",
22484
+ "List the projects belonging to this agent's team. A project is a container that groups related tasks and published artefacts across agents under one unit of work. Read-only: projects are created by humans in the console.",
22485
+ {
22486
+ status: external_exports.enum(["active", "archived"]).optional().describe("Filter by project status"),
22487
+ limit: external_exports.number().int().min(1).max(100).optional().describe("Maximum projects to return (default 50, max 100)")
22488
+ },
22489
+ async (params) => ({
22490
+ content: [{ type: "text", text: await listProjectsText(params) }]
22491
+ })
22492
+ );
22493
+ server.tool(
22494
+ "projects_get",
22495
+ "Fetch a single project (a team-scoped container) by id, including its name, status, and optional Linear link.",
22496
+ {
22497
+ project_id: external_exports.string().uuid().describe("The project id returned by projects_list")
22498
+ },
22499
+ async (params) => ({
22500
+ content: [{ type: "text", text: await getProjectText(params.project_id) }]
22501
+ })
22426
22502
  );
22427
22503
  async function main() {
22428
22504
  try {