@integrity-labs/agt-cli 0.28.875 → 0.28.877

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.
@@ -16,7 +16,7 @@ import {
16
16
  parseEnvIntegrations,
17
17
  shellQuote,
18
18
  summarizeUnanswerablePane
19
- } from "./chunk-SQ7PB5A6.js";
19
+ } from "./chunk-CA46EUVN.js";
20
20
  import {
21
21
  BIND_FAILURE_QUARANTINE_THRESHOLD,
22
22
  INTEGRATIONS_SECTION_END,
@@ -76,7 +76,7 @@ import {
76
76
  sessionTranscriptDir,
77
77
  worseConnectivityOutcome,
78
78
  wrapScheduledTaskPrompt
79
- } from "./chunk-Q2OVEMUG.js";
79
+ } from "./chunk-EARM456T.js";
80
80
  import {
81
81
  parsePsRows
82
82
  } from "./chunk-XWVM4KPK.js";
@@ -6771,7 +6771,7 @@ function exchangeFailureKind(err) {
6771
6771
  }
6772
6772
 
6773
6773
  // src/lib/api-client.ts
6774
- var agtCliVersion = true ? "0.28.875" : "dev";
6774
+ var agtCliVersion = true ? "0.28.877" : "dev";
6775
6775
  var lastConfigHash = null;
6776
6776
  function setConfigHash(hash) {
6777
6777
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -11381,4 +11381,4 @@ export {
11381
11381
  managerInstallSystemUnitCommand,
11382
11382
  managerUninstallSystemUnitCommand
11383
11383
  };
11384
- //# sourceMappingURL=chunk-6MGKXGCE.js.map
11384
+ //# sourceMappingURL=chunk-GYCS2NTY.js.map
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
100
100
  return { ok: true };
101
101
  } catch {
102
102
  }
103
- const { resolveClaudeBinary } = await import("./persistent-session-MG6FEYRY.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-XQG5H4KI.js");
104
104
  const claudeBin = resolveClaudeBinary();
105
105
  const pairEnv = {
106
106
  ...process.env,
@@ -373,4 +373,4 @@ export {
373
373
  startClaudePair,
374
374
  submitClaudePairCode
375
375
  };
376
- //# sourceMappingURL=claude-pair-runtime-GRZ2EHHR.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-G3SEYGH6.js.map
@@ -63,7 +63,7 @@ import {
63
63
  safeWriteJsonAtomic,
64
64
  setConfigHash,
65
65
  tripClass
66
- } from "../chunk-6MGKXGCE.js";
66
+ } from "../chunk-GYCS2NTY.js";
67
67
  import {
68
68
  getProjectDir as getProjectDir2,
69
69
  getReadyTasks,
@@ -129,7 +129,7 @@ import {
129
129
  takeZombieDetection,
130
130
  toOpencodeModel,
131
131
  writeEgressAllowlist
132
- } from "../chunk-SQ7PB5A6.js";
132
+ } from "../chunk-CA46EUVN.js";
133
133
  import {
134
134
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
135
135
  AnchorSessionClient,
@@ -224,7 +224,7 @@ import {
224
224
  subagentActivityAgeSeconds,
225
225
  sumTranscriptUsageInWindow,
226
226
  transcriptActivityAgeSeconds
227
- } from "../chunk-Q2OVEMUG.js";
227
+ } from "../chunk-EARM456T.js";
228
228
  import {
229
229
  reapOrphanChannelMcps
230
230
  } from "../chunk-XWVM4KPK.js";
@@ -13016,7 +13016,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
13016
13016
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
13017
13017
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
13018
13018
  async function channelInboundActivityAgeSecondsFor(codeName) {
13019
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-2OGWHDXE.js");
13019
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-LA4VGH5W.js");
13020
13020
  const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
13021
13021
  if (newest === null) return null;
13022
13022
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -13684,7 +13684,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
13684
13684
  var lastVersionCheckAt = 0;
13685
13685
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
13686
13686
  var lastResponsivenessProbeAt = 0;
13687
- var agtCliVersion = true ? "0.28.875" : "dev";
13687
+ var agtCliVersion = true ? "0.28.877" : "dev";
13688
13688
  function resolveBrewPath(execFileSync2) {
13689
13689
  try {
13690
13690
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -15274,7 +15274,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
15274
15274
  if (codeNames.length === 0) return;
15275
15275
  void (async () => {
15276
15276
  try {
15277
- const { collectDiagnostics } = await import("../persistent-session-MG6FEYRY.js");
15277
+ const { collectDiagnostics } = await import("../persistent-session-XQG5H4KI.js");
15278
15278
  await api.post("/host/heartbeat", {
15279
15279
  host_id: hostId,
15280
15280
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -15416,7 +15416,7 @@ async function pollCycleInner() {
15416
15416
  }
15417
15417
  try {
15418
15418
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
15419
- const { collectDiagnostics } = await import("../persistent-session-MG6FEYRY.js");
15419
+ const { collectDiagnostics } = await import("../persistent-session-XQG5H4KI.js");
15420
15420
  const diagCodeNames = [...agentState.persistentSessionAgents];
15421
15421
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
15422
15422
  let tailscaleHostname;
@@ -15585,7 +15585,7 @@ async function pollCycleInner() {
15585
15585
  collectPanelessActivityProbes,
15586
15586
  getResponsivenessIntervalMs,
15587
15587
  occupancyQualificationClassifications
15588
- } = await import("../responsiveness-probe-2OGWHDXE.js");
15588
+ } = await import("../responsiveness-probe-LA4VGH5W.js");
15589
15589
  const probeIntervalMs = getResponsivenessIntervalMs();
15590
15590
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
15591
15591
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -15702,7 +15702,7 @@ async function pollCycleInner() {
15702
15702
  collectResponsivenessProbes,
15703
15703
  livePendingInboundOldestAgeSeconds,
15704
15704
  parkPendingInbound
15705
- } = await import("../responsiveness-probe-2OGWHDXE.js");
15705
+ } = await import("../responsiveness-probe-LA4VGH5W.js");
15706
15706
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
15707
15707
  const wedgeNow = /* @__PURE__ */ new Date();
15708
15708
  const liveAgents = agentState.persistentSessionAgents;
@@ -15858,7 +15858,7 @@ async function pollCycleInner() {
15858
15858
  }
15859
15859
  try {
15860
15860
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
15861
- const { probeSessionAuth } = await import("../session-auth-dead-AHL6D3CM.js");
15861
+ const { probeSessionAuth } = await import("../session-auth-dead-DFLSWVAQ.js");
15862
15862
  const observations = [];
15863
15863
  const pendingCacheCommits = [];
15864
15864
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -20103,7 +20103,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
20103
20103
  try {
20104
20104
  const freshId = rotateSessionForWedge(codeName);
20105
20105
  consecutiveWedgeCycles.delete(codeName);
20106
- const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-2OGWHDXE.js");
20106
+ const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-LA4VGH5W.js");
20107
20107
  const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
20108
20108
  const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
20109
20109
  const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
@@ -20141,7 +20141,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
20141
20141
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
20142
20142
  void (async () => {
20143
20143
  try {
20144
- const { collectDiagnostics } = await import("../persistent-session-MG6FEYRY.js");
20144
+ const { collectDiagnostics } = await import("../persistent-session-XQG5H4KI.js");
20145
20145
  await api.post("/host/heartbeat", {
20146
20146
  host_id: hostId,
20147
20147
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -20187,7 +20187,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
20187
20187
  }
20188
20188
  try {
20189
20189
  const hostId = await getHostId();
20190
- const { collectDiagnostics } = await import("../persistent-session-MG6FEYRY.js");
20190
+ const { collectDiagnostics } = await import("../persistent-session-XQG5H4KI.js");
20191
20191
  await api.post("/host/heartbeat", {
20192
20192
  host_id: hostId,
20193
20193
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -20823,7 +20823,7 @@ async function processClaudePairSessions(agents) {
20823
20823
  killPairSession,
20824
20824
  pairTmuxSession,
20825
20825
  finalizeClaudePairOnboarding
20826
- } = await import("../claude-pair-runtime-GRZ2EHHR.js");
20826
+ } = await import("../claude-pair-runtime-G3SEYGH6.js");
20827
20827
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
20828
20828
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
20829
20829
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -34161,6 +34161,97 @@ var INTEGRATION_REGISTRY = [
34161
34161
  ]
34162
34162
  }
34163
34163
  },
34164
+ {
34165
+ id: "origami",
34166
+ name: "origami.chat",
34167
+ category: "crm",
34168
+ description: "Lead data + outbound: build and enrich lead lists, drive origami's AI worker from a natural-language brief, and read the tables it builds. Available on the platform-managed account, or with your own origami key.",
34169
+ // ENG-7423: origami migrates from a customer-key-only integration to a
34170
+ // PREMIUM one that ALSO keeps BYO — the Firecrawl / ADR-0055 model, with one
34171
+ // structural difference that drives most of the design.
34172
+ //
34173
+ // Firecrawl's premium tier is a single platform account key that every
34174
+ // customer's calls bill back to, and isolation is not a concern because a
34175
+ // scrape has no tenancy. origami is the opposite: it stores the customer's
34176
+ // LEAD LISTS, tables, chats and campaigns. Putting every customer on one
34177
+ // parent org would make every customer's data mutually readable, so the
34178
+ // managed tier gives each ORGANIZATION its own origami project (child org)
34179
+ // and mints a key BOUND to that project (`POST /account/keys` with
34180
+ // `project_id`, v3). See `packages/core/src/origami/provision.ts` for why a
34181
+ // bound key rather than the `x-origami-project` header — in short, the
34182
+ // header is a per-call assertion and the tool argument is deliberately
34183
+ // nullable, so under a shared parent an ordinary tool call could reach it.
34184
+ //
34185
+ // ── auth types, and the ENG-9235 trap this deliberately re-enters ─────────
34186
+ // Both are offered, unlike Firecrawl, which PARKED `api_key` down to
34187
+ // `['none']` because a 2+-auth-type wizard renders a picker that is not
34188
+ // entitlement-aware: a customer picks BYO, goes and fetches a vendor key,
34189
+ // and is then rejected with `byo_not_entitled_by_plan` (BYO on a premium def
34190
+ // needs `plans.byo_credentials`, enterprise-only today).
34191
+ //
34192
+ // origami cannot take that exit. BYO is the INCUMBENT here — every existing
34193
+ // install is a customer's own key — so dropping `api_key` would remove the
34194
+ // only mode its current customers use. The known gap is therefore accepted
34195
+ // and pointed at its owner: the picker will still let a non-entitled org
34196
+ // choose BYO and reject it afterwards. ENG-9236 (entitlement-aware wizard)
34197
+ // is the fix; until it lands the rejection is at least loud, specific, and
34198
+ // ahead of any charge.
34199
+ //
34200
+ // EXISTING installs are unaffected by that gate: the premium migration
34201
+ // backfills them to `credential_source='byo'` AND stamps
34202
+ // `config.byo_grandfathered_at`, which the call-time resolver honours in
34203
+ // place of the plan check. Grandfathering is per-install and set only by
34204
+ // that one migration — a NEW BYO install still needs the entitlement.
34205
+ //
34206
+ // KEEP IN LOCKSTEP with the `origami` rows in
34207
+ // packages/supabase/seeds/integration-definitions.json and
34208
+ // toolkit-definitions.json: those seeds carry their own auth types and are
34209
+ // what `db:catalog:seed` upserts on every prod deploy, so editing this array
34210
+ // alone changes nothing a customer can see.
34211
+ supported_auth_types: ["none", "api_key"],
34212
+ capabilities: [
34213
+ { id: "origami:read", name: "Read Lists & Runs", description: "Discover projects and tables, read built tables and rows, poll runs/batches, and check credit balance. Credit-free.", access: "read" },
34214
+ { id: "origami:write", name: "Enrich Leads", description: "Insert raw rows into an enrichment table (submit_enrichment). Consumes credits.", access: "write" },
34215
+ { id: "origami:agent", name: "Drive the AI Worker", description: "Create an origami agent, send follow-up runs, cancel a run, archive an agent. Consumes credits.", access: "write" }
34216
+ ],
34217
+ docs_url: "https://docs.origami.chat/v3/overview",
34218
+ // ENG-7423: premium (billable). origami bills internally in CREDITS, so the
34219
+ // integration is usage-priced on one meter whose unit is the vendor's own
34220
+ // billing unit. Priced at 2.0 c USD / 3.5 c AUD per credit by
34221
+ // `20260907000050_origami_credits_rate_card.sql`, against a retail cost of
34222
+ // 1.29-1.43 c/credit depending on which origami tier we hold.
34223
+ //
34224
+ // The note deliberately does NOT say "at cost". origami sells a
34225
+ // SUBSCRIPTION WITH AN INCLUDED BUNDLE while this meters PER CREDIT
34226
+ // CONSUMED, so a per-credit price recovers the subscription only at full
34227
+ // utilisation — around 72% of the bundle at this rate. Calling that "at
34228
+ // cost" in a customer-facing pricing string would be a claim about our
34229
+ // margin that is only true at one utilisation level we do not control.
34230
+ //
34231
+ // ONE meter, not one per tool, because of where the number comes from. Every
34232
+ // other premium integration meters at a server-side broker chokepoint, which
34233
+ // sees each call and can attribute it. origami's agent surface is a
34234
+ // host-resident stdio MCP server (ADR-0040) that calls origami.chat DIRECTLY
34235
+ // — the control plane never sees the tool call, so there is no per-operation
34236
+ // quantity to meter. What the control plane CAN see is the project's own
34237
+ // spend (`GET /account/projects/{id}` → `usage.spent`), which the credit
34238
+ // reconciler polls and meters as a delta. That is a per-project total, so it
34239
+ // can only ever be one meter; splitting it per tool would require the vendor
34240
+ // to break spend down by operation, which v3 does not expose.
34241
+ //
34242
+ // `unit_label` is set because the machine unit is the vendor's internal
34243
+ // billing unit rather than a thing the customer asked for — "(per credit)"
34244
+ // is the honest rendering, in the ADR-0053 cost-pass-through spirit.
34245
+ //
34246
+ // Only a MANAGED install is metered. A BYO install spends the customer's own
34247
+ // origami credits on their own bill (`isBilledInstall` → false), which is why
34248
+ // the reconciler polls only projects it provisioned.
34249
+ premium: {
34250
+ pricing: "usage",
34251
+ note: "Billed per origami credit the agent consumes. Bring your own origami key instead and usage is billed to you by origami directly.",
34252
+ meters: [{ event_type: "credits", unit: "credit", label: "origami credits", unit_label: "credit" }]
34253
+ }
34254
+ },
34164
34255
  {
34165
34256
  id: "ayrshare",
34166
34257
  name: "Ayrshare",
package/dist/mcp/index.js CHANGED
@@ -26735,6 +26735,97 @@ var INTEGRATION_REGISTRY = [
26735
26735
  ]
26736
26736
  }
26737
26737
  },
26738
+ {
26739
+ id: "origami",
26740
+ name: "origami.chat",
26741
+ category: "crm",
26742
+ description: "Lead data + outbound: build and enrich lead lists, drive origami's AI worker from a natural-language brief, and read the tables it builds. Available on the platform-managed account, or with your own origami key.",
26743
+ // ENG-7423: origami migrates from a customer-key-only integration to a
26744
+ // PREMIUM one that ALSO keeps BYO — the Firecrawl / ADR-0055 model, with one
26745
+ // structural difference that drives most of the design.
26746
+ //
26747
+ // Firecrawl's premium tier is a single platform account key that every
26748
+ // customer's calls bill back to, and isolation is not a concern because a
26749
+ // scrape has no tenancy. origami is the opposite: it stores the customer's
26750
+ // LEAD LISTS, tables, chats and campaigns. Putting every customer on one
26751
+ // parent org would make every customer's data mutually readable, so the
26752
+ // managed tier gives each ORGANIZATION its own origami project (child org)
26753
+ // and mints a key BOUND to that project (`POST /account/keys` with
26754
+ // `project_id`, v3). See `packages/core/src/origami/provision.ts` for why a
26755
+ // bound key rather than the `x-origami-project` header — in short, the
26756
+ // header is a per-call assertion and the tool argument is deliberately
26757
+ // nullable, so under a shared parent an ordinary tool call could reach it.
26758
+ //
26759
+ // ── auth types, and the ENG-9235 trap this deliberately re-enters ─────────
26760
+ // Both are offered, unlike Firecrawl, which PARKED `api_key` down to
26761
+ // `['none']` because a 2+-auth-type wizard renders a picker that is not
26762
+ // entitlement-aware: a customer picks BYO, goes and fetches a vendor key,
26763
+ // and is then rejected with `byo_not_entitled_by_plan` (BYO on a premium def
26764
+ // needs `plans.byo_credentials`, enterprise-only today).
26765
+ //
26766
+ // origami cannot take that exit. BYO is the INCUMBENT here — every existing
26767
+ // install is a customer's own key — so dropping `api_key` would remove the
26768
+ // only mode its current customers use. The known gap is therefore accepted
26769
+ // and pointed at its owner: the picker will still let a non-entitled org
26770
+ // choose BYO and reject it afterwards. ENG-9236 (entitlement-aware wizard)
26771
+ // is the fix; until it lands the rejection is at least loud, specific, and
26772
+ // ahead of any charge.
26773
+ //
26774
+ // EXISTING installs are unaffected by that gate: the premium migration
26775
+ // backfills them to `credential_source='byo'` AND stamps
26776
+ // `config.byo_grandfathered_at`, which the call-time resolver honours in
26777
+ // place of the plan check. Grandfathering is per-install and set only by
26778
+ // that one migration — a NEW BYO install still needs the entitlement.
26779
+ //
26780
+ // KEEP IN LOCKSTEP with the `origami` rows in
26781
+ // packages/supabase/seeds/integration-definitions.json and
26782
+ // toolkit-definitions.json: those seeds carry their own auth types and are
26783
+ // what `db:catalog:seed` upserts on every prod deploy, so editing this array
26784
+ // alone changes nothing a customer can see.
26785
+ supported_auth_types: ["none", "api_key"],
26786
+ capabilities: [
26787
+ { id: "origami:read", name: "Read Lists & Runs", description: "Discover projects and tables, read built tables and rows, poll runs/batches, and check credit balance. Credit-free.", access: "read" },
26788
+ { id: "origami:write", name: "Enrich Leads", description: "Insert raw rows into an enrichment table (submit_enrichment). Consumes credits.", access: "write" },
26789
+ { id: "origami:agent", name: "Drive the AI Worker", description: "Create an origami agent, send follow-up runs, cancel a run, archive an agent. Consumes credits.", access: "write" }
26790
+ ],
26791
+ docs_url: "https://docs.origami.chat/v3/overview",
26792
+ // ENG-7423: premium (billable). origami bills internally in CREDITS, so the
26793
+ // integration is usage-priced on one meter whose unit is the vendor's own
26794
+ // billing unit. Priced at 2.0 c USD / 3.5 c AUD per credit by
26795
+ // `20260907000050_origami_credits_rate_card.sql`, against a retail cost of
26796
+ // 1.29-1.43 c/credit depending on which origami tier we hold.
26797
+ //
26798
+ // The note deliberately does NOT say "at cost". origami sells a
26799
+ // SUBSCRIPTION WITH AN INCLUDED BUNDLE while this meters PER CREDIT
26800
+ // CONSUMED, so a per-credit price recovers the subscription only at full
26801
+ // utilisation — around 72% of the bundle at this rate. Calling that "at
26802
+ // cost" in a customer-facing pricing string would be a claim about our
26803
+ // margin that is only true at one utilisation level we do not control.
26804
+ //
26805
+ // ONE meter, not one per tool, because of where the number comes from. Every
26806
+ // other premium integration meters at a server-side broker chokepoint, which
26807
+ // sees each call and can attribute it. origami's agent surface is a
26808
+ // host-resident stdio MCP server (ADR-0040) that calls origami.chat DIRECTLY
26809
+ // — the control plane never sees the tool call, so there is no per-operation
26810
+ // quantity to meter. What the control plane CAN see is the project's own
26811
+ // spend (`GET /account/projects/{id}` → `usage.spent`), which the credit
26812
+ // reconciler polls and meters as a delta. That is a per-project total, so it
26813
+ // can only ever be one meter; splitting it per tool would require the vendor
26814
+ // to break spend down by operation, which v3 does not expose.
26815
+ //
26816
+ // `unit_label` is set because the machine unit is the vendor's internal
26817
+ // billing unit rather than a thing the customer asked for — "(per credit)"
26818
+ // is the honest rendering, in the ADR-0053 cost-pass-through spirit.
26819
+ //
26820
+ // Only a MANAGED install is metered. A BYO install spends the customer's own
26821
+ // origami credits on their own bill (`isBilledInstall` → false), which is why
26822
+ // the reconciler polls only projects it provisioned.
26823
+ premium: {
26824
+ pricing: "usage",
26825
+ note: "Billed per origami credit the agent consumes. Bring your own origami key instead and usage is billed to you by origami directly.",
26826
+ meters: [{ event_type: "credits", unit: "credit", label: "origami credits", unit_label: "credit" }]
26827
+ }
26828
+ },
26738
26829
  {
26739
26830
  id: "ayrshare",
26740
26831
  name: "Ayrshare",
@@ -40866,6 +40866,97 @@ var INTEGRATION_REGISTRY = [
40866
40866
  ]
40867
40867
  }
40868
40868
  },
40869
+ {
40870
+ id: "origami",
40871
+ name: "origami.chat",
40872
+ category: "crm",
40873
+ description: "Lead data + outbound: build and enrich lead lists, drive origami's AI worker from a natural-language brief, and read the tables it builds. Available on the platform-managed account, or with your own origami key.",
40874
+ // ENG-7423: origami migrates from a customer-key-only integration to a
40875
+ // PREMIUM one that ALSO keeps BYO — the Firecrawl / ADR-0055 model, with one
40876
+ // structural difference that drives most of the design.
40877
+ //
40878
+ // Firecrawl's premium tier is a single platform account key that every
40879
+ // customer's calls bill back to, and isolation is not a concern because a
40880
+ // scrape has no tenancy. origami is the opposite: it stores the customer's
40881
+ // LEAD LISTS, tables, chats and campaigns. Putting every customer on one
40882
+ // parent org would make every customer's data mutually readable, so the
40883
+ // managed tier gives each ORGANIZATION its own origami project (child org)
40884
+ // and mints a key BOUND to that project (`POST /account/keys` with
40885
+ // `project_id`, v3). See `packages/core/src/origami/provision.ts` for why a
40886
+ // bound key rather than the `x-origami-project` header — in short, the
40887
+ // header is a per-call assertion and the tool argument is deliberately
40888
+ // nullable, so under a shared parent an ordinary tool call could reach it.
40889
+ //
40890
+ // ── auth types, and the ENG-9235 trap this deliberately re-enters ─────────
40891
+ // Both are offered, unlike Firecrawl, which PARKED `api_key` down to
40892
+ // `['none']` because a 2+-auth-type wizard renders a picker that is not
40893
+ // entitlement-aware: a customer picks BYO, goes and fetches a vendor key,
40894
+ // and is then rejected with `byo_not_entitled_by_plan` (BYO on a premium def
40895
+ // needs `plans.byo_credentials`, enterprise-only today).
40896
+ //
40897
+ // origami cannot take that exit. BYO is the INCUMBENT here — every existing
40898
+ // install is a customer's own key — so dropping `api_key` would remove the
40899
+ // only mode its current customers use. The known gap is therefore accepted
40900
+ // and pointed at its owner: the picker will still let a non-entitled org
40901
+ // choose BYO and reject it afterwards. ENG-9236 (entitlement-aware wizard)
40902
+ // is the fix; until it lands the rejection is at least loud, specific, and
40903
+ // ahead of any charge.
40904
+ //
40905
+ // EXISTING installs are unaffected by that gate: the premium migration
40906
+ // backfills them to `credential_source='byo'` AND stamps
40907
+ // `config.byo_grandfathered_at`, which the call-time resolver honours in
40908
+ // place of the plan check. Grandfathering is per-install and set only by
40909
+ // that one migration — a NEW BYO install still needs the entitlement.
40910
+ //
40911
+ // KEEP IN LOCKSTEP with the `origami` rows in
40912
+ // packages/supabase/seeds/integration-definitions.json and
40913
+ // toolkit-definitions.json: those seeds carry their own auth types and are
40914
+ // what `db:catalog:seed` upserts on every prod deploy, so editing this array
40915
+ // alone changes nothing a customer can see.
40916
+ supported_auth_types: ["none", "api_key"],
40917
+ capabilities: [
40918
+ { id: "origami:read", name: "Read Lists & Runs", description: "Discover projects and tables, read built tables and rows, poll runs/batches, and check credit balance. Credit-free.", access: "read" },
40919
+ { id: "origami:write", name: "Enrich Leads", description: "Insert raw rows into an enrichment table (submit_enrichment). Consumes credits.", access: "write" },
40920
+ { id: "origami:agent", name: "Drive the AI Worker", description: "Create an origami agent, send follow-up runs, cancel a run, archive an agent. Consumes credits.", access: "write" }
40921
+ ],
40922
+ docs_url: "https://docs.origami.chat/v3/overview",
40923
+ // ENG-7423: premium (billable). origami bills internally in CREDITS, so the
40924
+ // integration is usage-priced on one meter whose unit is the vendor's own
40925
+ // billing unit. Priced at 2.0 c USD / 3.5 c AUD per credit by
40926
+ // `20260907000050_origami_credits_rate_card.sql`, against a retail cost of
40927
+ // 1.29-1.43 c/credit depending on which origami tier we hold.
40928
+ //
40929
+ // The note deliberately does NOT say "at cost". origami sells a
40930
+ // SUBSCRIPTION WITH AN INCLUDED BUNDLE while this meters PER CREDIT
40931
+ // CONSUMED, so a per-credit price recovers the subscription only at full
40932
+ // utilisation — around 72% of the bundle at this rate. Calling that "at
40933
+ // cost" in a customer-facing pricing string would be a claim about our
40934
+ // margin that is only true at one utilisation level we do not control.
40935
+ //
40936
+ // ONE meter, not one per tool, because of where the number comes from. Every
40937
+ // other premium integration meters at a server-side broker chokepoint, which
40938
+ // sees each call and can attribute it. origami's agent surface is a
40939
+ // host-resident stdio MCP server (ADR-0040) that calls origami.chat DIRECTLY
40940
+ // — the control plane never sees the tool call, so there is no per-operation
40941
+ // quantity to meter. What the control plane CAN see is the project's own
40942
+ // spend (`GET /account/projects/{id}` → `usage.spent`), which the credit
40943
+ // reconciler polls and meters as a delta. That is a per-project total, so it
40944
+ // can only ever be one meter; splitting it per tool would require the vendor
40945
+ // to break spend down by operation, which v3 does not expose.
40946
+ //
40947
+ // `unit_label` is set because the machine unit is the vendor's internal
40948
+ // billing unit rather than a thing the customer asked for — "(per credit)"
40949
+ // is the honest rendering, in the ADR-0053 cost-pass-through spirit.
40950
+ //
40951
+ // Only a MANAGED install is metered. A BYO install spends the customer's own
40952
+ // origami credits on their own bill (`isBilledInstall` → false), which is why
40953
+ // the reconciler polls only projects it provisioned.
40954
+ premium: {
40955
+ pricing: "usage",
40956
+ note: "Billed per origami credit the agent consumes. Bring your own origami key instead and usage is billed to you by origami directly.",
40957
+ meters: [{ event_type: "credits", unit: "credit", label: "origami credits", unit_label: "credit" }]
40958
+ }
40959
+ },
40869
40960
  {
40870
40961
  id: "ayrshare",
40871
40962
  name: "Ayrshare",
@@ -35096,6 +35096,97 @@ var INTEGRATION_REGISTRY = [
35096
35096
  ]
35097
35097
  }
35098
35098
  },
35099
+ {
35100
+ id: "origami",
35101
+ name: "origami.chat",
35102
+ category: "crm",
35103
+ description: "Lead data + outbound: build and enrich lead lists, drive origami's AI worker from a natural-language brief, and read the tables it builds. Available on the platform-managed account, or with your own origami key.",
35104
+ // ENG-7423: origami migrates from a customer-key-only integration to a
35105
+ // PREMIUM one that ALSO keeps BYO — the Firecrawl / ADR-0055 model, with one
35106
+ // structural difference that drives most of the design.
35107
+ //
35108
+ // Firecrawl's premium tier is a single platform account key that every
35109
+ // customer's calls bill back to, and isolation is not a concern because a
35110
+ // scrape has no tenancy. origami is the opposite: it stores the customer's
35111
+ // LEAD LISTS, tables, chats and campaigns. Putting every customer on one
35112
+ // parent org would make every customer's data mutually readable, so the
35113
+ // managed tier gives each ORGANIZATION its own origami project (child org)
35114
+ // and mints a key BOUND to that project (`POST /account/keys` with
35115
+ // `project_id`, v3). See `packages/core/src/origami/provision.ts` for why a
35116
+ // bound key rather than the `x-origami-project` header — in short, the
35117
+ // header is a per-call assertion and the tool argument is deliberately
35118
+ // nullable, so under a shared parent an ordinary tool call could reach it.
35119
+ //
35120
+ // ── auth types, and the ENG-9235 trap this deliberately re-enters ─────────
35121
+ // Both are offered, unlike Firecrawl, which PARKED `api_key` down to
35122
+ // `['none']` because a 2+-auth-type wizard renders a picker that is not
35123
+ // entitlement-aware: a customer picks BYO, goes and fetches a vendor key,
35124
+ // and is then rejected with `byo_not_entitled_by_plan` (BYO on a premium def
35125
+ // needs `plans.byo_credentials`, enterprise-only today).
35126
+ //
35127
+ // origami cannot take that exit. BYO is the INCUMBENT here — every existing
35128
+ // install is a customer's own key — so dropping `api_key` would remove the
35129
+ // only mode its current customers use. The known gap is therefore accepted
35130
+ // and pointed at its owner: the picker will still let a non-entitled org
35131
+ // choose BYO and reject it afterwards. ENG-9236 (entitlement-aware wizard)
35132
+ // is the fix; until it lands the rejection is at least loud, specific, and
35133
+ // ahead of any charge.
35134
+ //
35135
+ // EXISTING installs are unaffected by that gate: the premium migration
35136
+ // backfills them to `credential_source='byo'` AND stamps
35137
+ // `config.byo_grandfathered_at`, which the call-time resolver honours in
35138
+ // place of the plan check. Grandfathering is per-install and set only by
35139
+ // that one migration — a NEW BYO install still needs the entitlement.
35140
+ //
35141
+ // KEEP IN LOCKSTEP with the `origami` rows in
35142
+ // packages/supabase/seeds/integration-definitions.json and
35143
+ // toolkit-definitions.json: those seeds carry their own auth types and are
35144
+ // what `db:catalog:seed` upserts on every prod deploy, so editing this array
35145
+ // alone changes nothing a customer can see.
35146
+ supported_auth_types: ["none", "api_key"],
35147
+ capabilities: [
35148
+ { id: "origami:read", name: "Read Lists & Runs", description: "Discover projects and tables, read built tables and rows, poll runs/batches, and check credit balance. Credit-free.", access: "read" },
35149
+ { id: "origami:write", name: "Enrich Leads", description: "Insert raw rows into an enrichment table (submit_enrichment). Consumes credits.", access: "write" },
35150
+ { id: "origami:agent", name: "Drive the AI Worker", description: "Create an origami agent, send follow-up runs, cancel a run, archive an agent. Consumes credits.", access: "write" }
35151
+ ],
35152
+ docs_url: "https://docs.origami.chat/v3/overview",
35153
+ // ENG-7423: premium (billable). origami bills internally in CREDITS, so the
35154
+ // integration is usage-priced on one meter whose unit is the vendor's own
35155
+ // billing unit. Priced at 2.0 c USD / 3.5 c AUD per credit by
35156
+ // `20260907000050_origami_credits_rate_card.sql`, against a retail cost of
35157
+ // 1.29-1.43 c/credit depending on which origami tier we hold.
35158
+ //
35159
+ // The note deliberately does NOT say "at cost". origami sells a
35160
+ // SUBSCRIPTION WITH AN INCLUDED BUNDLE while this meters PER CREDIT
35161
+ // CONSUMED, so a per-credit price recovers the subscription only at full
35162
+ // utilisation — around 72% of the bundle at this rate. Calling that "at
35163
+ // cost" in a customer-facing pricing string would be a claim about our
35164
+ // margin that is only true at one utilisation level we do not control.
35165
+ //
35166
+ // ONE meter, not one per tool, because of where the number comes from. Every
35167
+ // other premium integration meters at a server-side broker chokepoint, which
35168
+ // sees each call and can attribute it. origami's agent surface is a
35169
+ // host-resident stdio MCP server (ADR-0040) that calls origami.chat DIRECTLY
35170
+ // — the control plane never sees the tool call, so there is no per-operation
35171
+ // quantity to meter. What the control plane CAN see is the project's own
35172
+ // spend (`GET /account/projects/{id}` → `usage.spent`), which the credit
35173
+ // reconciler polls and meters as a delta. That is a per-project total, so it
35174
+ // can only ever be one meter; splitting it per tool would require the vendor
35175
+ // to break spend down by operation, which v3 does not expose.
35176
+ //
35177
+ // `unit_label` is set because the machine unit is the vendor's internal
35178
+ // billing unit rather than a thing the customer asked for — "(per credit)"
35179
+ // is the honest rendering, in the ADR-0053 cost-pass-through spirit.
35180
+ //
35181
+ // Only a MANAGED install is metered. A BYO install spends the customer's own
35182
+ // origami credits on their own bill (`isBilledInstall` → false), which is why
35183
+ // the reconciler polls only projects it provisioned.
35184
+ premium: {
35185
+ pricing: "usage",
35186
+ note: "Billed per origami credit the agent consumes. Bring your own origami key instead and usage is billed to you by origami directly.",
35187
+ meters: [{ event_type: "credits", unit: "credit", label: "origami credits", unit_label: "credit" }]
35188
+ }
35189
+ },
35099
35190
  {
35100
35191
  id: "ayrshare",
35101
35192
  name: "Ayrshare",