@integrity-labs/agt-cli 0.17.2 → 0.18.0

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 CHANGED
@@ -48,7 +48,7 @@ import {
48
48
  success,
49
49
  table,
50
50
  warn
51
- } from "../chunk-RGJV3MV3.js";
51
+ } from "../chunk-W6ADLCZD.js";
52
52
 
53
53
  // src/bin/agt.ts
54
54
  import { join as join10 } from "path";
@@ -3732,7 +3732,7 @@ import { execFileSync, execSync } from "child_process";
3732
3732
  import { existsSync as existsSync5, realpathSync } from "fs";
3733
3733
  import chalk17 from "chalk";
3734
3734
  import ora15 from "ora";
3735
- var cliVersion = true ? "0.17.2" : "dev";
3735
+ var cliVersion = true ? "0.18.0" : "dev";
3736
3736
  async function fetchLatestVersion() {
3737
3737
  const host2 = getHost();
3738
3738
  if (!host2) return null;
@@ -4190,7 +4190,7 @@ function handleError(err) {
4190
4190
  }
4191
4191
 
4192
4192
  // src/bin/agt.ts
4193
- var cliVersion2 = true ? "0.17.2" : "dev";
4193
+ var cliVersion2 = true ? "0.18.0" : "dev";
4194
4194
  var program = new Command();
4195
4195
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
4196
4196
  program.hook("preAction", (thisCommand) => {
@@ -429,6 +429,27 @@ var INTEGRATION_REGISTRY = [
429
429
  { id: "xero:manage-settings", name: "Manage Settings", description: "Manage org settings and chart of accounts", access: "admin" }
430
430
  ]
431
431
  },
432
+ {
433
+ id: "granola",
434
+ name: "Granola",
435
+ category: "knowledge",
436
+ description: "Meeting notes search \u2014 query transcripts, summaries, and folders from Granola",
437
+ // Granola uses a remote streamable-HTTP MCP with PKCE + Dynamic Client
438
+ // Registration. End-user OAuth is brokered by the webapp (ENG-4693)
439
+ // through the shared /integrations/oauth/authorize → /callback path
440
+ // (ENG-4694), and the access_token is injected into .mcp.json via the
441
+ // generic bearer-header path. No host-side action required from the
442
+ // operator beyond running the one-time DCR registration script at
443
+ // deploy time.
444
+ supported_auth_types: ["oauth2"],
445
+ capabilities: [
446
+ { id: "granola:search-meetings", name: "Search Meetings", description: "Browse meetings, search content, and chat with notes (query_granola_meetings, list_meetings, get_meetings)", access: "read" },
447
+ { id: "granola:read-transcripts", name: "Read Transcripts", description: "Access raw meeting transcripts (paid plans only \u2014 get_meeting_transcript)", access: "read" },
448
+ { id: "granola:list-folders", name: "List Folders", description: "View accessible meeting folders (paid plans only \u2014 list_meeting_folders)", access: "read" }
449
+ ],
450
+ docs_url: "https://docs.granola.ai/docs/api/mcp",
451
+ beta: true
452
+ },
432
453
  {
433
454
  id: "qmd",
434
455
  name: "QMD Memory Search",
@@ -2802,6 +2823,50 @@ You are **${frontmatter.display_name}**, **${roleDisplay}**${team ? ` at **${tea
2802
2823
  ${desc ? `
2803
2824
  ${desc}
2804
2825
  ` : ""}
2826
+
2827
+ ## \u26A0\uFE0F FIRST ACTION on every channel message: triage
2828
+
2829
+ This is the highest-priority instruction in this document. Before anything
2830
+ else when you receive an inbound \`<channel>\` tag (Slack/Telegram/Direct
2831
+ Chat), decide:
2832
+
2833
+ **Will completing this request take longer than ~60 seconds of tool work?**
2834
+ Treat as SLOW if it involves any of: Xero data pulls, multi-step Composio
2835
+ chains, web research, reading/writing >5 files, image generation, dashboard
2836
+ refreshes, multi-skill activations, or anything you'd reasonably want to
2837
+ acknowledge before you start.
2838
+
2839
+ - **FAST (< 60s):** handle inline. Reply via the channel tool
2840
+ (slack.reply / telegram.reply / directchat.reply) and end your turn.
2841
+
2842
+ - **SLOW (\u2265 60s):** dispatch.
2843
+ 1. Send a one-line acknowledgement via the channel tool \u2014 short, warm,
2844
+ and tell the user you'll come back. Example shape (don't copy verbatim,
2845
+ match your voice): "On it \u2014 this'll take a minute or two, I'll ping
2846
+ when it's done."
2847
+ 2. Invoke the \`channel-message-handler\` subagent (Task tool, with
2848
+ \`subagent_type: channel-message-handler\`) with the full original
2849
+ message text plus the **channel-specific routing keys** the reply
2850
+ tool needs: Slack threads \u2192 \`{ channel_id, thread_ts }\`; Slack
2851
+ non-thread DMs \u2192 \`{ channel_id }\`; Telegram \u2192 \`{ chat_id, message_id }\`;
2852
+ Direct Chat \u2192 \`{ conversation_id }\`. Pass these verbatim from the
2853
+ inbound \`<channel>\` tag \u2014 don't substitute a generic \`message_ts\`,
2854
+ since only Slack threads use it. The subagent will do the actual
2855
+ work and post the real reply itself.
2856
+ 3. End your turn. **Do NOT call slack.reply / telegram.reply with the
2857
+ full result yourself** \u2014 that's the subagent's job.
2858
+
2859
+ **Why this matters more than any other instruction below:** if you handle
2860
+ slow requests inline, you go silent for 60+ seconds while operators send
2861
+ follow-up messages that queue behind you. Dispatching keeps you free to
2862
+ acknowledge new pings. The kanban-tracking-link convention, work-management
2863
+ "create a task" guidance, and Slack reply patterns ALL apply to fast
2864
+ inline replies \u2014 they do NOT replace this dispatch decision.
2865
+
2866
+ If the work turns out to be unexpectedly slow after you started inline,
2867
+ finish the current sub-step, then dispatch the rest. Don't apologise for
2868
+ mid-task switching \u2014 operators care about responsiveness, not consistency.
2869
+
2805
2870
  ${personalitySection}## Identity
2806
2871
 
2807
2872
  - Code Name: ${frontmatter.code_name}
@@ -2813,8 +2878,13 @@ ${personalitySection}## Identity
2813
2878
  ${resolvedChannels?.includes("slack") ? `
2814
2879
  ## Slack
2815
2880
 
2816
- You have a Slack MCP server connected. When Slack messages arrive via the channel
2817
- protocol, respond directly in the conversation. You can also proactively use:
2881
+ You have a Slack MCP server connected. **First, see \xA7 FIRST ACTION on
2882
+ every channel message: triage** at the top of this document \u2014 decide
2883
+ fast vs slow before anything else, and dispatch slow work via
2884
+ \`channel-message-handler\` rather than handling it inline.
2885
+
2886
+ For fast requests, respond directly in the conversation. You can also
2887
+ proactively use:
2818
2888
 
2819
2889
  - **slack.reply** \u2014 reply to a message in a channel/thread
2820
2890
  - **slack.react** \u2014 add an emoji reaction to a message (use sparingly \u2014 see taxonomy below)
@@ -2998,21 +3068,6 @@ The marginal cost of completeness is near zero. Do the whole thing.
2998
3068
  - **Search before building. Test before shipping.**
2999
3069
  - **No excuses.** Time, fatigue, and complexity are not reasons to deliver less than complete.
3000
3070
 
3001
- ## Channel message triage (ENG-4684)
3002
-
3003
- Every inbound \`<channel>\` tag (Slack/Telegram/Direct Chat) is a fresh request. Triage it BEFORE doing the work:
3004
-
3005
- - **Will this reply take longer than ~60 seconds?** Treat as slow if it involves: Xero pulls (any), multi-step Composio chains, web research, reading/writing >5 files, image generation, or a multi-skill activation.
3006
-
3007
- - **FAST (< 60s):** handle inline. Reply via the channel tool (slack.reply / telegram.reply / directchat.reply) and end your turn.
3008
-
3009
- - **SLOW (\u2265 60s):**
3010
- 1. Send this exact acknowledgement via the channel tool: *"This will take a while, I'll ping you when it's done."* Use the verbatim copy \u2014 don't paraphrase or add detail.
3011
- 2. Invoke the \`channel-message-handler\` subagent (background) with the full message + channel/thread/message_ts metadata as the task.
3012
- 3. End your turn. The subagent posts the actual reply itself when it's done.
3013
-
3014
- Why: dispatching short replies wastes ~20s of subagent overhead. Dispatching slow ones keeps you free to acknowledge new inbound messages immediately instead of going silent for 60s+. Get the routing decision right; the rest follows.
3015
-
3016
3071
  ## Rules
3017
3072
 
3018
3073
  - Never expose secrets or API keys in output.
@@ -3022,6 +3077,124 @@ Why: dispatching short replies wastes ~20s of subagent overhead. Dispatching slo
3022
3077
  ${frontmatter.environment === "prod" ? "- Production environment: exercise extra caution with all operations.\n" : ""}`;
3023
3078
  }
3024
3079
 
3080
+ // ../../packages/core/dist/integrations/oauth-providers.js
3081
+ var OAUTH_PROVIDERS = {
3082
+ "google-workspace": {
3083
+ definitionId: "google-workspace",
3084
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
3085
+ tokenUrl: "https://oauth2.googleapis.com/token",
3086
+ revokeUrl: "https://oauth2.googleapis.com/revoke",
3087
+ defaultScopes: [
3088
+ "https://www.googleapis.com/auth/gmail.modify",
3089
+ "https://www.googleapis.com/auth/calendar",
3090
+ "https://www.googleapis.com/auth/drive",
3091
+ "https://www.googleapis.com/auth/spreadsheets",
3092
+ "https://www.googleapis.com/auth/documents",
3093
+ "https://www.googleapis.com/auth/chat.messages",
3094
+ "https://www.googleapis.com/auth/chat.spaces.readonly"
3095
+ ],
3096
+ supportsRefresh: true,
3097
+ extraAuthorizeParams: {
3098
+ access_type: "offline",
3099
+ prompt: "consent"
3100
+ },
3101
+ clientAuthMethod: "body",
3102
+ userInfoUrl: "https://www.googleapis.com/oauth2/v2/userinfo"
3103
+ },
3104
+ "github": {
3105
+ definitionId: "github",
3106
+ authorizeUrl: "https://github.com/login/oauth/authorize",
3107
+ tokenUrl: "https://github.com/login/oauth/access_token",
3108
+ defaultScopes: ["repo", "read:org", "gist", "workflow"],
3109
+ supportsRefresh: true,
3110
+ extraAuthorizeParams: {},
3111
+ clientAuthMethod: "body",
3112
+ userInfoUrl: "https://api.github.com/user"
3113
+ },
3114
+ "granola": {
3115
+ // Granola MCP — remote streamable-HTTP at https://mcp.granola.ai/mcp.
3116
+ // The AS is at mcp-auth.granola.ai and exposes RFC 8414 metadata at
3117
+ // /.well-known/oauth-authorization-server. Auth is OAuth 2.0 with
3118
+ // mandatory PKCE (S256) and a public client (no client_secret) issued
3119
+ // via Dynamic Client Registration (RFC 7591). The bootstrap script
3120
+ // (`packages/api/scripts/dcr-register.ts`) registers a client once at
3121
+ // deploy time; OAUTH_GRANOLA_CLIENT_ID is set from its output.
3122
+ definitionId: "granola",
3123
+ authorizeUrl: "https://mcp-auth.granola.ai/oauth2/authorize",
3124
+ tokenUrl: "https://mcp-auth.granola.ai/oauth2/token",
3125
+ // openid+profile+email give us the user identity for status_message;
3126
+ // offline_access is the one that earns us a refresh_token so the
3127
+ // refresh cron can rotate the bearer without operator action.
3128
+ defaultScopes: ["openid", "profile", "email", "offline_access"],
3129
+ supportsRefresh: true,
3130
+ extraAuthorizeParams: {},
3131
+ clientAuthMethod: "body",
3132
+ pkce: "S256",
3133
+ publicClient: true,
3134
+ mcpUrl: "https://mcp.granola.ai/mcp"
3135
+ },
3136
+ "xero": {
3137
+ definitionId: "xero",
3138
+ authorizeUrl: "https://login.xero.com/identity/connect/authorize",
3139
+ tokenUrl: "https://identity.xero.com/connect/token",
3140
+ revokeUrl: "https://identity.xero.com/connect/revocation",
3141
+ defaultScopes: [
3142
+ "openid",
3143
+ "profile",
3144
+ "email",
3145
+ "offline_access",
3146
+ // Granular scopes (required for apps created after March 2, 2026 —
3147
+ // do NOT revert to the broad `accounting.transactions` /
3148
+ // `accounting.contacts` scopes, Xero rejects the manifest).
3149
+ // The variant *without* `.read` is the read+write granular scope.
3150
+ "accounting.settings.read",
3151
+ // contacts: write enables agent-driven supplier/customer creation
3152
+ // (required for bill creation since a bill must reference a contact).
3153
+ "accounting.contacts",
3154
+ // invoices: write enables bill creation (Type=ACCPAY invoices) and
3155
+ // updates to sales invoices alongside the existing read access.
3156
+ "accounting.invoices",
3157
+ // attachments: write enables agents to attach the source PDF to a
3158
+ // bill at creation time. Read-only would force a follow-up manual
3159
+ // upload in Xero; write closes the loop.
3160
+ "accounting.attachments",
3161
+ // accounting.transactions.read → granular read-only replacements
3162
+ // for the surfaces we don't yet need write access on.
3163
+ "accounting.payments.read",
3164
+ "accounting.banktransactions.read",
3165
+ "accounting.manualjournals.read",
3166
+ // accounting.reports.read → granular read-only replacements
3167
+ "accounting.reports.balancesheet.read",
3168
+ "accounting.reports.profitandloss.read",
3169
+ "accounting.reports.trialbalance.read",
3170
+ "accounting.reports.budgetsummary.read",
3171
+ "accounting.reports.banksummary.read",
3172
+ "accounting.reports.executivesummary.read",
3173
+ "accounting.reports.aged.read"
3174
+ ],
3175
+ supportsRefresh: true,
3176
+ extraAuthorizeParams: {},
3177
+ clientAuthMethod: "basic",
3178
+ userInfoUrl: "https://api.xero.com/connections"
3179
+ }
3180
+ };
3181
+
3182
+ // ../../packages/core/dist/provisioning/remote-mcp.js
3183
+ function envVarForToken(definitionId) {
3184
+ return `${definitionId.replace(/-/g, "_").toUpperCase()}_ACCESS_TOKEN`;
3185
+ }
3186
+ function buildRemoteMcpEntry(definitionId) {
3187
+ const provider = OAUTH_PROVIDERS[definitionId];
3188
+ if (!provider?.mcpUrl)
3189
+ return null;
3190
+ return {
3191
+ url: provider.mcpUrl,
3192
+ headers: {
3193
+ Authorization: `Bearer \${${envVarForToken(definitionId)}}`
3194
+ }
3195
+ };
3196
+ }
3197
+
3025
3198
  // ../../packages/core/dist/provisioning/frameworks/claudecode/index.js
3026
3199
  var VALID_CODE_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
3027
3200
  var SECRET_FILE_MODE = 384;
@@ -3179,9 +3352,20 @@ function deployArtifactsToProject(codeName, provisionDir) {
3179
3352
  const destAgentsDir = join4(projectDir, ".claude", "agents");
3180
3353
  try {
3181
3354
  if (existsSync4(agentsDir)) {
3182
- for (const agentFile of readdirSync(agentsDir)) {
3183
- if (!agentFile.endsWith(".md"))
3184
- continue;
3355
+ const sourceAgentFiles = new Set(readdirSync(agentsDir).filter((f) => f.endsWith(".md")));
3356
+ if (existsSync4(destAgentsDir)) {
3357
+ for (const destFile of readdirSync(destAgentsDir)) {
3358
+ if (!destFile.endsWith(".md"))
3359
+ continue;
3360
+ if (sourceAgentFiles.has(destFile))
3361
+ continue;
3362
+ try {
3363
+ rmSync(join4(destAgentsDir, destFile));
3364
+ } catch {
3365
+ }
3366
+ }
3367
+ }
3368
+ for (const agentFile of sourceAgentFiles) {
3185
3369
  const srcPath = join4(agentsDir, agentFile);
3186
3370
  const destPath = join4(destAgentsDir, agentFile);
3187
3371
  const srcContent = readFileSync4(srcPath, "utf-8");
@@ -3622,7 +3806,7 @@ function buildChannelMessageHandlerAgent() {
3622
3806
  name: channel-message-handler
3623
3807
  description: Handles a single inbound Slack/Telegram/Direct-Chat message end to end. Posts the reply itself via the matching channel tool. The parent agent dispatches to this subagent only for slow requests (\u2265 ~60s) so the parent's listener turn stays free for new inbound work.
3624
3808
  background: true
3625
- tools: Bash, Read, Write, Edit, Grep, Glob, Skill, Agent, mcp__augmented__*, mcp__slack__*, mcp__telegram__*, mcp__direct_chat__*, mcp__xero__*, mcp__composio_attio__*, mcp__composio_canva__*, mcp__composio_gmail__*, mcp__composio_googlecalendar__*, mcp__composio_googledocs__*, mcp__composio_googledrive__*, mcp__composio_googlesheets__*
3809
+ tools: Bash, Read, Write, Edit, Grep, Glob, Skill, Agent, mcp__augmented__*, mcp__slack__*, mcp__telegram__*, mcp__direct_chat__*, mcp__xero__*, mcp__granola__*, mcp__composio_attio__*, mcp__composio_canva__*, mcp__composio_gmail__*, mcp__composio_googlecalendar__*, mcp__composio_googledocs__*, mcp__composio_googledrive__*, mcp__composio_googlesheets__*
3626
3810
  ---
3627
3811
 
3628
3812
  You are dispatched by the parent agent to handle one channel message.
@@ -3687,6 +3871,12 @@ function buildMcpJson(input) {
3687
3871
  }
3688
3872
  };
3689
3873
  }
3874
+ for (const integration of input.integrations ?? []) {
3875
+ const entry = buildRemoteMcpEntry(integration.definition_id);
3876
+ if (entry) {
3877
+ mcpServers[integration.definition_id] = entry;
3878
+ }
3879
+ }
3690
3880
  return { mcpServers };
3691
3881
  }
3692
3882
  function parseIntervalMinutes(scheduleEvery) {
@@ -4184,6 +4374,12 @@ ${sections}`
4184
4374
  }
4185
4375
  });
4186
4376
  }
4377
+ for (const integration of integrations) {
4378
+ const entry = buildRemoteMcpEntry(integration.definition_id);
4379
+ if (entry) {
4380
+ this.writeMcpServer(codeName, integration.definition_id, entry);
4381
+ }
4382
+ }
4187
4383
  const projectDir = getProjectDir(codeName);
4188
4384
  const claudeMdPath = join4(projectDir, "CLAUDE.md");
4189
4385
  try {
@@ -4254,6 +4450,11 @@ ${sections}`
4254
4450
  PIPEDREAM_PROJECT_ENVIRONMENT: headers["x-pd-environment"] ?? process.env["PIPEDREAM_ENVIRONMENT"] ?? "development"
4255
4451
  }
4256
4452
  };
4453
+ } else if (config.headers && Object.keys(config.headers).length > 0) {
4454
+ serverEntry = {
4455
+ url: config.url,
4456
+ headers: config.headers
4457
+ };
4257
4458
  } else {
4258
4459
  serverEntry = {
4259
4460
  command: "npx",
@@ -7766,4 +7967,4 @@ export {
7766
7967
  managerInstallCommand,
7767
7968
  managerUninstallCommand
7768
7969
  };
7769
- //# sourceMappingURL=chunk-RGJV3MV3.js.map
7970
+ //# sourceMappingURL=chunk-W6ADLCZD.js.map