@integrity-labs/agt-cli 0.28.1054 → 0.28.1056

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.
Files changed (24) hide show
  1. package/dist/bin/agt.js +5 -5
  2. package/dist/{chunk-AT7E625H.js → chunk-A7HDJW23.js} +2 -2
  3. package/dist/{chunk-M4ADTK6F.js → chunk-M5P24M2Z.js} +11 -5
  4. package/dist/{chunk-M4ADTK6F.js.map → chunk-M5P24M2Z.js.map} +1 -1
  5. package/dist/{chunk-2SGXGNDW.js → chunk-P544KDE3.js} +129 -36
  6. package/dist/chunk-P544KDE3.js.map +1 -0
  7. package/dist/{claude-pair-runtime-GO3C7KT6.js → claude-pair-runtime-TSRRFBNJ.js} +2 -2
  8. package/dist/lib/manager-worker.js +17 -14
  9. package/dist/lib/manager-worker.js.map +1 -1
  10. package/dist/mcp/direct-chat-channel.js +31 -33
  11. package/dist/mcp/index.js +31 -33
  12. package/dist/mcp/origami.js +31 -33
  13. package/dist/mcp/slack-channel.js +31 -33
  14. package/dist/mcp/telegram-channel.js +31 -33
  15. package/dist/{persistent-session-3WRSJIDM.js → persistent-session-WSJVCGEO.js} +3 -3
  16. package/dist/{responsiveness-probe-2DF6VH7Q.js → responsiveness-probe-7MQI6SUF.js} +3 -3
  17. package/dist/{session-auth-dead-GRTHA2Z5.js → session-auth-dead-NFVTUFPI.js} +2 -2
  18. package/package.json +1 -1
  19. package/dist/chunk-2SGXGNDW.js.map +0 -1
  20. /package/dist/{chunk-AT7E625H.js.map → chunk-A7HDJW23.js.map} +0 -0
  21. /package/dist/{claude-pair-runtime-GO3C7KT6.js.map → claude-pair-runtime-TSRRFBNJ.js.map} +0 -0
  22. /package/dist/{persistent-session-3WRSJIDM.js.map → persistent-session-WSJVCGEO.js.map} +0 -0
  23. /package/dist/{responsiveness-probe-2DF6VH7Q.js.map → responsiveness-probe-7MQI6SUF.js.map} +0 -0
  24. /package/dist/{session-auth-dead-GRTHA2Z5.js.map → session-auth-dead-NFVTUFPI.js.map} +0 -0
@@ -6920,7 +6920,7 @@ var FLAG_REGISTRY = [
6920
6920
  },
6921
6921
  {
6922
6922
  key: "email-require-approval-enforcement",
6923
- description: 'Enforcement gate for the `email.require_approval` guardrail (ENG-9611). That guardrail has been `default_for_new_orgs` since ~2026-05-03 and its display text promises "Require human approval before sending any email", but nothing ever read it: its only runtime path was toGuardrailForPrompt, i.e. a line in the agent CLAUDE.md. When ON for an org, a DISPATCHING email send (never a draft-create, ENG-7980) is held and routed to Human Approval regardless of recipient domain \u2014 which is what "any email" means, and is what distinguishes it from email-guard-require-approval-enabled, whose require_approval stage only intercepts a would-be DOMAIN block. Deliberately separate from the guardrail row: roughly four months of orgs already carry an inert `enforce`-level row, so reading the row alone would arm a blocking control across all of them on deploy. New orgs are armed by an org-scoped override written at org creation; existing orgs stay off until an operator flips them. Evaluated per-org. Ships dark.',
6923
+ description: 'Enforcement gate for the `email.require_approval` guardrail (ENG-9611). That guardrail has been `default_for_new_orgs` since ~2026-05-03 and its display text promises "Require human approval before sending any email", but nothing ever read it: its only runtime path was toGuardrailForPrompt, i.e. a line in the agent CLAUDE.md. When ON for an org, a DISPATCHING email send (never a draft-create, ENG-7980) is held and routed to Human Approval regardless of recipient domain \u2014 which is what "any email" means, and is what distinguishes it from email-guard-require-approval-enabled, whose require_approval stage only intercepts a would-be DOMAIN block. Deliberately separate from the guardrail row: roughly four months of orgs already carry an inert `enforce`-level row, so reading the row alone would arm a blocking control across all of them on deploy. New orgs are no longer armed (ENG-11234). Orgs created while the ENG-9629/9675 new-org arm was live keep their org-scoped ON override until an operator flips them per org. Evaluated per-org. Ships dark.',
6924
6924
  flagType: "boolean",
6925
6925
  // Declared safe value is `false` (no hold). A flag-DB read error degrades here, so a flags
6926
6926
  // outage can never silently start holding real customer email — the same fail-OPEN posture
@@ -6930,36 +6930,15 @@ var FLAG_REGISTRY = [
6930
6930
  defaultValue: false,
6931
6931
  // Turning it on holds real customer email pending a human tap, so it is a deliberate,
6932
6932
  // audited per-org flip (ADR-0022 §4).
6933
- sensitive: true,
6934
- // ENG-9629: NEW orgs are armed on. Declared here rather than hardcoded in the
6935
- // seeding code, so `listNewOrgFlagOverrides()` is the one answer to "which flags
6936
- // does a new org get". `defaultValue` stays false so the ~4 months of orgs already
6937
- // carrying an inert enforce-level email.require_approval row are NOT armed on deploy.
6938
- // ENG-9675: EVERY creation path, self-serve included.
6939
- //
6940
- // ENG-9630 had restricted this to API-created orgs on the grounds that a
6941
- // self-serve org has no way of being TOLD about a held send — no Slack
6942
- // alert channel is wired at signup. That reasoning was wrong, and the check
6943
- // behind it was incomplete: it confirmed an in-console page exists at
6944
- // /organization/approvals and stopped, without looking at the dispatch path.
6945
- //
6946
- // `routeBlockedCallToApproval` has three dispatchers, and the Direct Chat
6947
- // one (lib/integration-broker-approval-direct-chat.ts, ENG-7680) is the
6948
- // universal fallback — "every managed agent always has a Direct Chat session
6949
- // its operator/manager watches in the Console ... usable out of the box with
6950
- // no per-org approval-route setup and no Slack dependency". It posts into a
6951
- // thread keyed on the approval_requests.id and correlates the manager's
6952
- // reply back through tryCaptureDirectChatApproval, so a self-serve org has
6953
- // both a zero-config delivery channel AND a reply path.
6954
- //
6955
- // With the stated blocker gone, the guardrail's own promise — "before
6956
- // sending any email" — applies to the organizations with the LEAST operator
6957
- // oversight exactly as it does to the rest.
6958
- //
6959
- // Existing self-serve orgs are deliberately NOT armed by this: newOrgOverride
6960
- // is applied at creation, and nothing backfills. Extending it to them is a
6961
- // separate decision with a comms obligation.
6962
- newOrgOverride: true
6933
+ sensitive: true
6934
+ // No newOrgOverride (ENG-11234). ENG-9629/ENG-9675 armed this on EVERY new org at
6935
+ // creation, so every org created since then held each dispatching send, internal
6936
+ // recipients included, behind a human tap. In practice that stalled real work: Pedders
6937
+ // (CS-1904/1908/1910) had an agent's emails to its own principal expire unapproved,
6938
+ // because "any email" includes the person the agent works for. New orgs now start at
6939
+ // `defaultValue` (off) like every other org; turning it on is the deliberate, audited
6940
+ // per-org flip `sensitive: true` already describes. Orgs armed by the old override keep
6941
+ // their override row; nothing here disarms them (that is an operator decision per org).
6963
6942
  },
6964
6943
  {
6965
6944
  key: "mail-rule-control-enforcement",
@@ -8614,7 +8593,7 @@ var integration_metadata_v1_default = {
8614
8593
  type: "string",
8615
8594
  format: "uri",
8616
8595
  pattern: "^https://",
8617
- description: "Absolute HTTPS URL the broker uses as the vendor API root. Required when any tool descriptor relies on http_templater (i.e. whenever `tools[]` is non-empty)."
8596
+ description: "Absolute HTTPS URL the broker uses as the vendor API root. Required when any tool descriptor relies on http_templater (i.e. whenever `tools[]` is non-empty), unless the definition declares a per-install `base_url_template` instead (CS-1863)."
8618
8597
  },
8619
8598
  auth_scheme: {
8620
8599
  type: "string",
@@ -8648,6 +8627,22 @@ var integration_metadata_v1_default = {
8648
8627
  }
8649
8628
  }
8650
8629
  },
8630
+ base_url_template: {
8631
+ type: "object",
8632
+ description: "A PER-INSTALL API host (CS-1863), for vendors with one host per customer (Storrito: https://<ORG_UUID>.storrito.com/api/v1). Used when base_url is absent. `template` holds exactly one `{value}` placeholder in its host; the value is read from the install's config[config_key], must match value_pattern in full, and the built host must be exactly <value>.<host_suffix> over https. Resolved and re-validated at call time by resolveIntegrationBaseUrl.",
8633
+ additionalProperties: false,
8634
+ required: ["template", "config_key", "value_pattern", "host_suffix"],
8635
+ properties: {
8636
+ template: { type: "string", pattern: "^https://\\{value\\}\\.[^{}]+$" },
8637
+ config_key: { type: "string", pattern: "^[a-z][a-z0-9_]*$" },
8638
+ value_pattern: { type: "string", minLength: 1 },
8639
+ host_suffix: { type: "string", pattern: "^[a-z0-9.-]+\\.[a-z]{2,}$" }
8640
+ }
8641
+ },
8642
+ redirect_means_auth_failure: {
8643
+ type: "boolean",
8644
+ description: "The vendor answers a rejected credential with a REDIRECT (Storrito: a 302 to its login page) rather than a 401. A redirected non-GET call is never followed (vendor-fetch.ts) and always fails; with this set, it is also treated like a 401 and the install is flagged for re-auth."
8645
+ },
8651
8646
  tools: {
8652
8647
  type: "array",
8653
8648
  description: "Auto-loaded MCP tool descriptors. Each entry produces one MCP tool entry per supported runtime scope.",
@@ -8659,7 +8654,10 @@ var integration_metadata_v1_default = {
8659
8654
  properties: { tools: { type: "array", minItems: 1 } },
8660
8655
  required: ["tools"]
8661
8656
  },
8662
- then: { required: ["base_url"] },
8657
+ then: {
8658
+ description: "A tool needs an API root: a fixed base_url, or a per-install base_url_template (CS-1863).",
8659
+ anyOf: [{ required: ["base_url"] }, { required: ["base_url_template"] }]
8660
+ },
8663
8661
  not: {
8664
8662
  description: "auth_scheme and auth_encoding are mutually exclusive (ENG-10524). The templater refuses the combination on every call, so catalog validation refuses it first.",
8665
8663
  required: ["auth_scheme", "auth_encoding"]
@@ -11589,7 +11587,11 @@ var HTTP_PROBE_PROVIDERS = /* @__PURE__ */ new Set([
11589
11587
  // admin revokes it, and the integration is read-only, so a dead token would
11590
11588
  // otherwise surface as empty compliance reports rather than a failed write.
11591
11589
  // Routes to `probeMitti` against `GET /scheduling/v1/feed/schedules?limit=1`.
11592
- "mitti"
11590
+ "mitti",
11591
+ // CS-1863: Storrito, added with the integration. A deleted API credential
11592
+ // answers with a redirect to the login page rather than a 401, so without a
11593
+ // probe a dead token would surface only as failed story posts.
11594
+ "storrito"
11593
11595
  // ENG-6100: GitHub is deliberately NOT here. This set drives the ASYNC
11594
11596
  // connectivity monitor's routing, where github (source_type='native')
11595
11597
  // stays host-side (cli_command — `gh`, the credential the agent actually
@@ -11753,6 +11755,46 @@ function resolveConnectivityProbe(input) {
11753
11755
  }
11754
11756
  }
11755
11757
 
11758
+ // ../../packages/core/dist/integrations/integration-broker/base-url.js
11759
+ var FORBIDDEN_IN_VALUE = /[./@:?#\\\s]/;
11760
+ function resolveTemplatedBaseUrl(spec, config) {
11761
+ const raw = config?.[spec.config_key];
11762
+ if (typeof raw !== "string")
11763
+ return null;
11764
+ const value = raw.trim().toLowerCase();
11765
+ if (value === "" || FORBIDDEN_IN_VALUE.test(value))
11766
+ return null;
11767
+ let pattern;
11768
+ try {
11769
+ pattern = new RegExp(`^(?:${spec.value_pattern})$`, "i");
11770
+ } catch {
11771
+ return null;
11772
+ }
11773
+ if (!pattern.test(value))
11774
+ return null;
11775
+ const built = spec.template.replace("{value}", value);
11776
+ let url;
11777
+ try {
11778
+ url = new URL(built);
11779
+ } catch {
11780
+ return null;
11781
+ }
11782
+ const suffix = spec.host_suffix.toLowerCase().replace(/^\.+/, "");
11783
+ if (url.protocol !== "https:")
11784
+ return null;
11785
+ if (url.username !== "" || url.password !== "" || url.port !== "")
11786
+ return null;
11787
+ if (url.hostname !== `${value}.${suffix}`)
11788
+ return null;
11789
+ return built.replace(/\/+$/, "");
11790
+ }
11791
+ var STORRITO_BASE_URL_SPEC = {
11792
+ template: "https://{value}.storrito.com/api/v1",
11793
+ config_key: "org_id",
11794
+ value_pattern: "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
11795
+ host_suffix: "storrito.com"
11796
+ };
11797
+
11756
11798
  // ../../packages/core/dist/integrations/connectivity-http-probes.js
11757
11799
  var PROBE_TIMEOUT_MS = 1e4;
11758
11800
  var NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 204, 205, 304]);
@@ -12074,8 +12116,59 @@ async function probeMitti(creds, fetchImpl) {
12074
12116
  return networkOutcome(err, String(token));
12075
12117
  }
12076
12118
  }
12077
- async function probeHttpProvider(definitionId, credentials, fetchImpl = fetch) {
12119
+ async function probeStorrito(creds, fetchImpl, config) {
12120
+ const token = creds.api_key ?? creds.access_token;
12121
+ if (!token)
12122
+ return { status: "down", message: "No credential present" };
12123
+ const base = resolveTemplatedBaseUrl(STORRITO_BASE_URL_SPEC, config);
12124
+ if (!base) {
12125
+ return {
12126
+ status: "down",
12127
+ message: "Storrito organisation ID is missing or not a valid UUID - set it on the install (Storrito API settings)"
12128
+ };
12129
+ }
12130
+ try {
12131
+ const res = await timedFetch(fetchImpl, `${base}/list-instagram-users`, {
12132
+ method: "POST",
12133
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
12134
+ body: "{}",
12135
+ redirect: "manual"
12136
+ });
12137
+ if (res.status >= 300 && res.status < 400) {
12138
+ return {
12139
+ status: "down",
12140
+ cause: "auth_rejected",
12141
+ message: "Storrito rejected the token (redirected to its login page) - the API credential was deleted, mistyped or belongs to another organisation"
12142
+ };
12143
+ }
12144
+ if (!res.ok) {
12145
+ const message = res.status === 401 || res.status === 403 ? `Storrito rejected the token (${res.status})` : res.status === 429 ? rateLimitMessage("Storrito", res.status) : `Storrito API returned ${res.status}`;
12146
+ return { status: statusForHttp(res.status), cause: causeForHttp(res.status), message };
12147
+ }
12148
+ let body = null;
12149
+ try {
12150
+ body = await res.json();
12151
+ } catch {
12152
+ body = null;
12153
+ }
12154
+ if (!Array.isArray(body?.instagramUsers)) {
12155
+ return { status: "down", message: "Storrito returned 200 without an Instagram account list - not a Storrito API response" };
12156
+ }
12157
+ if (body.instagramUsers.length === 0) {
12158
+ return {
12159
+ status: "degraded",
12160
+ message: "Connected to Storrito, but no Instagram account is connected in Storrito yet - stories have nowhere to post"
12161
+ };
12162
+ }
12163
+ return { status: "ok", message: `Connected to Storrito (${body.instagramUsers.length} Instagram account(s))` };
12164
+ } catch (err) {
12165
+ return networkOutcome(err, String(token));
12166
+ }
12167
+ }
12168
+ async function probeHttpProvider(definitionId, credentials, fetchImpl = fetch, config) {
12078
12169
  switch (definitionId) {
12170
+ case "storrito":
12171
+ return probeStorrito(credentials, fetchImpl, config);
12079
12172
  case "linear":
12080
12173
  return probeLinear(credentials, fetchImpl);
12081
12174
  case "buffer":
@@ -15901,4 +15994,4 @@ export {
15901
15994
  peekCurrentSession,
15902
15995
  readDailySessionPin
15903
15996
  };
15904
- //# sourceMappingURL=chunk-2SGXGNDW.js.map
15997
+ //# sourceMappingURL=chunk-P544KDE3.js.map