@integrity-labs/agt-cli 0.28.423 → 0.28.425

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.
@@ -18867,7 +18867,7 @@ var require_filters = __commonJS({
18867
18867
  return r.copySafeness(str, res);
18868
18868
  }
18869
18869
  _exports.indent = indent;
18870
- function join11(arr, del, attr) {
18870
+ function join12(arr, del, attr) {
18871
18871
  del = del || "";
18872
18872
  if (attr) {
18873
18873
  arr = lib.map(arr, function(v) {
@@ -18876,7 +18876,7 @@ var require_filters = __commonJS({
18876
18876
  }
18877
18877
  return arr.join(del);
18878
18878
  }
18879
- _exports.join = join11;
18879
+ _exports.join = join12;
18880
18880
  function last(arr) {
18881
18881
  return arr[arr.length - 1];
18882
18882
  }
@@ -29827,17 +29827,30 @@ function writeTurnInitiatorMarker(input) {
29827
29827
  }
29828
29828
  }
29829
29829
 
29830
+ // src/scheduled-turn-marker.ts
29831
+ import { readFileSync as readFileSync3, unlinkSync } from "fs";
29832
+ import { join as join3 } from "path";
29833
+ var SCHEDULED_TURN_MARKER_FILENAME = ".current-scheduled-turn.json";
29834
+ var SCHEDULED_TURN_MAX_AGE_MS = 15 * 60 * 1e3;
29835
+ function clearScheduledTurnMarker(agentDir) {
29836
+ if (!agentDir) return;
29837
+ try {
29838
+ unlinkSync(join3(agentDir, SCHEDULED_TURN_MARKER_FILENAME));
29839
+ } catch {
29840
+ }
29841
+ }
29842
+
29830
29843
  // src/direct-chat-pending-inbound.ts
29831
29844
  import {
29832
29845
  existsSync as existsSync2,
29833
29846
  mkdirSync as mkdirSync2,
29834
29847
  readdirSync,
29835
- readFileSync as readFileSync3,
29848
+ readFileSync as readFileSync4,
29836
29849
  renameSync as renameSync2,
29837
- unlinkSync,
29850
+ unlinkSync as unlinkSync2,
29838
29851
  writeFileSync as writeFileSync2
29839
29852
  } from "fs";
29840
- import { join as join3 } from "path";
29853
+ import { join as join4 } from "path";
29841
29854
  function hexEncodeSegment(value) {
29842
29855
  return Buffer.from(value, "utf8").toString("hex");
29843
29856
  }
@@ -29846,7 +29859,7 @@ function directChatMarkerName(sessionId, messageId) {
29846
29859
  }
29847
29860
  var defaultClearMarkerFile = (fullPath) => {
29848
29861
  try {
29849
- if (existsSync2(fullPath)) unlinkSync(fullPath);
29862
+ if (existsSync2(fullPath)) unlinkSync2(fullPath);
29850
29863
  } catch {
29851
29864
  }
29852
29865
  };
@@ -29864,7 +29877,7 @@ function writeDirectChatPendingInboundMarker(dir, sessionId, messageId) {
29864
29877
  received_at: (/* @__PURE__ */ new Date()).toISOString(),
29865
29878
  inbound_id: directChatInboundId(sessionId, messageId)
29866
29879
  };
29867
- const final = join3(dir, directChatMarkerName(sessionId, messageId));
29880
+ const final = join4(dir, directChatMarkerName(sessionId, messageId));
29868
29881
  const tmp = `${final}.tmp`;
29869
29882
  writeFileSync2(tmp, JSON.stringify(marker), "utf8");
29870
29883
  renameSync2(tmp, final);
@@ -29883,15 +29896,15 @@ function clearDirectChatPendingMarkersForSession(dir, sessionId, op = defaultCle
29883
29896
  }
29884
29897
  for (const name of names) {
29885
29898
  if (!name.startsWith(prefix) || !name.endsWith(".json")) continue;
29886
- op(join3(dir, name));
29899
+ op(join4(dir, name));
29887
29900
  cleared += 1;
29888
29901
  }
29889
29902
  return cleared;
29890
29903
  }
29891
- function readDirectChatPendingInboundMarker(dir, sessionId, messageId, readFileImpl = (path) => readFileSync3(path, "utf8")) {
29904
+ function readDirectChatPendingInboundMarker(dir, sessionId, messageId, readFileImpl = (path) => readFileSync4(path, "utf8")) {
29892
29905
  if (!dir || !sessionId || !messageId) return null;
29893
29906
  try {
29894
- const raw = readFileImpl(join3(dir, directChatMarkerName(sessionId, messageId)));
29907
+ const raw = readFileImpl(join4(dir, directChatMarkerName(sessionId, messageId)));
29895
29908
  return JSON.parse(raw);
29896
29909
  } catch {
29897
29910
  return null;
@@ -29908,7 +29921,7 @@ function sweepAgedDirectChatMarkers(dir, deps) {
29908
29921
  }
29909
29922
  for (const name of names) {
29910
29923
  if (!name.endsWith(".json") || name.startsWith(".")) continue;
29911
- const full = join3(dir, name);
29924
+ const full = join4(dir, name);
29912
29925
  let marker;
29913
29926
  try {
29914
29927
  marker = JSON.parse(deps.readFile(full));
@@ -29997,8 +30010,8 @@ async function consumeDirectChatRecoveryFile(fullPath, filename, deps) {
29997
30010
  }
29998
30011
 
29999
30012
  // src/inbound-delivery-ledger.ts
30000
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, renameSync as renameSync3, writeFileSync as writeFileSync3 } from "fs";
30001
- import { join as join4 } from "path";
30013
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, renameSync as renameSync3, writeFileSync as writeFileSync3 } from "fs";
30014
+ import { join as join5 } from "path";
30002
30015
  function safeInboundId(inboundId) {
30003
30016
  return inboundId.replace(/[^A-Za-z0-9_-]/g, "_");
30004
30017
  }
@@ -30007,7 +30020,7 @@ var defaultDeps = {
30007
30020
  writeFile: (path, data) => writeFileSync3(path, data, "utf8"),
30008
30021
  rename: (from, to) => renameSync3(from, to),
30009
30022
  readdir: (dir) => readdirSync2(dir),
30010
- readFile: (path) => readFileSync4(path, "utf8"),
30023
+ readFile: (path) => readFileSync5(path, "utf8"),
30011
30024
  exists: (path) => existsSync3(path)
30012
30025
  };
30013
30026
  function writeInboundDeliveryLedgerEntry(dir, record2, deps = defaultDeps) {
@@ -30016,7 +30029,7 @@ function writeInboundDeliveryLedgerEntry(dir, record2, deps = defaultDeps) {
30016
30029
  if (!safe || safe.includes("/") || safe.includes("\\") || safe.includes("..")) return;
30017
30030
  try {
30018
30031
  deps.mkdir(dir);
30019
- const final = join4(dir, `${safe}.json`);
30032
+ const final = join5(dir, `${safe}.json`);
30020
30033
  const tmp = `${final}.tmp`;
30021
30034
  deps.writeFile(tmp, JSON.stringify(record2));
30022
30035
  deps.rename(tmp, final);
@@ -30028,22 +30041,22 @@ function inboundDeliveryLedgerHas(dir, inboundId, deps = defaultDeps) {
30028
30041
  const safe = safeInboundId(inboundId);
30029
30042
  if (!safe || safe.includes("/") || safe.includes("\\") || safe.includes("..")) return false;
30030
30043
  try {
30031
- return deps.exists(join4(dir, `${safe}.json`));
30044
+ return deps.exists(join5(dir, `${safe}.json`));
30032
30045
  } catch {
30033
30046
  return false;
30034
30047
  }
30035
30048
  }
30036
30049
 
30037
30050
  // src/ack-reaction.ts
30038
- import { readdirSync as readdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
30039
- import { join as join6 } from "path";
30051
+ import { readdirSync as readdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
30052
+ import { join as join7 } from "path";
30040
30053
 
30041
30054
  // src/flags-cache-read.ts
30042
- import { existsSync as existsSync4, readFileSync as readFileSync5 } from "fs";
30055
+ import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
30043
30056
  import { homedir } from "os";
30044
- import { join as join5 } from "path";
30057
+ import { join as join6 } from "path";
30045
30058
  function defaultFlagsCachePath() {
30046
- return join5(homedir(), ".augmented", "flags-cache.json");
30059
+ return join6(homedir(), ".augmented", "flags-cache.json");
30047
30060
  }
30048
30061
  function envBoolean(raw) {
30049
30062
  if (raw === void 0) return void 0;
@@ -30056,7 +30069,7 @@ function envBoolean(raw) {
30056
30069
  function cachedBoolean(key, path) {
30057
30070
  try {
30058
30071
  if (!existsSync4(path)) return void 0;
30059
- const parsed = JSON.parse(readFileSync5(path, "utf8"));
30072
+ const parsed = JSON.parse(readFileSync6(path, "utf8"));
30060
30073
  if (!parsed || typeof parsed !== "object") return void 0;
30061
30074
  const flags = parsed.flags;
30062
30075
  if (!flags || typeof flags !== "object") return void 0;
@@ -30142,7 +30155,7 @@ function oldestPendingMarkerAgeMs(dir, now = Date.now(), opts) {
30142
30155
  if (!name.endsWith(".json")) continue;
30143
30156
  let receivedAt;
30144
30157
  try {
30145
- const raw = JSON.parse(readFileSync6(join6(dir, name), "utf-8"));
30158
+ const raw = JSON.parse(readFileSync7(join7(dir, name), "utf-8"));
30146
30159
  if (raw.discretionary === true) continue;
30147
30160
  if (!opts?.includeSeen && typeof raw.seen_at === "string" && raw.seen_at) continue;
30148
30161
  receivedAt = raw.received_at;
@@ -30183,14 +30196,14 @@ function isMarkerGenuinelyAged(receivedAt, nowMs, thresholdMs) {
30183
30196
  }
30184
30197
  var DEFLECTION_COUNTER_SUFFIX = "-deflections.json";
30185
30198
  function deflectionCounterPath(agentDir, channel) {
30186
- return join6(agentDir, `${channel}${DEFLECTION_COUNTER_SUFFIX}`);
30199
+ return join7(agentDir, `${channel}${DEFLECTION_COUNTER_SUFFIX}`);
30187
30200
  }
30188
30201
  function recordChannelDeflection(agentDir, channel, cause) {
30189
30202
  if (!agentDir) return;
30190
30203
  const path = deflectionCounterPath(agentDir, channel);
30191
30204
  let counts = {};
30192
30205
  try {
30193
- const parsed = JSON.parse(readFileSync6(path, "utf-8"));
30206
+ const parsed = JSON.parse(readFileSync7(path, "utf-8"));
30194
30207
  if (parsed && typeof parsed === "object") counts = parsed;
30195
30208
  } catch {
30196
30209
  }
@@ -30277,14 +30290,14 @@ async function fetchWithTimeout(input, init, timeoutMs, fetchImpl = fetch) {
30277
30290
  import {
30278
30291
  existsSync as existsSync5,
30279
30292
  mkdirSync as mkdirSync4,
30280
- readFileSync as readFileSync7,
30293
+ readFileSync as readFileSync8,
30281
30294
  renameSync as renameSync4,
30282
30295
  statSync,
30283
- unlinkSync as unlinkSync2,
30296
+ unlinkSync as unlinkSync3,
30284
30297
  utimesSync,
30285
30298
  writeFileSync as writeFileSync5
30286
30299
  } from "fs";
30287
- import { join as join7 } from "path";
30300
+ import { join as join8 } from "path";
30288
30301
  var STALE_LOCK_MS = 9e4;
30289
30302
  var HEARTBEAT_INTERVAL_MS = 3e4;
30290
30303
  function defaultIsPidAlive(pid) {
@@ -30307,7 +30320,7 @@ function acquireMcpSpawnLock(args) {
30307
30320
  const nowMs = options.nowMs ?? (() => Date.now());
30308
30321
  const lockMtimeMs = options.lockMtimeMs ?? defaultLockMtimeMs;
30309
30322
  const staleMs = options.staleMs ?? STALE_LOCK_MS;
30310
- const path = join7(agentDir, basename);
30323
+ const path = join8(agentDir, basename);
30311
30324
  const existing = readLockHolder(path);
30312
30325
  if (existing) {
30313
30326
  if (existing.pid === selfPid) {
@@ -30335,7 +30348,7 @@ function releaseMcpSpawnLock(lockPath, opts = {}) {
30335
30348
  if (!existing) return;
30336
30349
  if (existing.pid !== selfPid) return;
30337
30350
  try {
30338
- unlinkSync2(lockPath);
30351
+ unlinkSync3(lockPath);
30339
30352
  } catch {
30340
30353
  }
30341
30354
  }
@@ -30374,7 +30387,7 @@ function defaultLockMtimeMs(path) {
30374
30387
  function readLockHolder(path) {
30375
30388
  if (!existsSync5(path)) return null;
30376
30389
  try {
30377
- const raw = readFileSync7(path, "utf8");
30390
+ const raw = readFileSync8(path, "utf8");
30378
30391
  const parsed = JSON.parse(raw);
30379
30392
  const pid = typeof parsed.pid === "number" ? parsed.pid : Number(parsed.pid);
30380
30393
  if (!Number.isFinite(pid) || pid <= 0) return null;
@@ -30387,38 +30400,38 @@ function readLockHolder(path) {
30387
30400
 
30388
30401
  // src/direct-chat-channel.ts
30389
30402
  import { homedir as homedir3 } from "os";
30390
- import { join as join10 } from "path";
30403
+ import { join as join11 } from "path";
30391
30404
  import { randomUUID } from "crypto";
30392
30405
  import {
30393
30406
  watch,
30394
30407
  mkdirSync as mkdirSync5,
30395
30408
  writeFileSync as writeFileSync6,
30396
- readFileSync as readFileSync9,
30409
+ readFileSync as readFileSync10,
30397
30410
  readdirSync as readdirSync4,
30398
30411
  existsSync as existsSync6,
30399
30412
  renameSync as renameSync5,
30400
- unlinkSync as unlinkSync3,
30413
+ unlinkSync as unlinkSync4,
30401
30414
  statSync as statSync2,
30402
30415
  createWriteStream
30403
30416
  } from "fs";
30404
30417
 
30405
30418
  // src/direct-chat-inbound-attachments.ts
30406
- import { dirname as dirname2, join as join8 } from "path";
30419
+ import { dirname as dirname2, join as join9 } from "path";
30407
30420
  var MAX_INBOUND_ATTACHMENT_BYTES = 10 * 1024 * 1024;
30408
30421
  var INBOUND_ATTACHMENTS_SUBDIR = "direct-chat-inbound";
30409
30422
  function resolveInboundAttachmentsDir(input) {
30410
30423
  const { codeName, turnInitiatorFile, agentId, homeDir } = input;
30411
30424
  const codeNameTrimmed = typeof codeName === "string" ? codeName.trim() : "";
30412
30425
  if (codeNameTrimmed) {
30413
- return join8(homeDir, ".augmented", codeNameTrimmed, INBOUND_ATTACHMENTS_SUBDIR);
30426
+ return join9(homeDir, ".augmented", codeNameTrimmed, INBOUND_ATTACHMENTS_SUBDIR);
30414
30427
  }
30415
30428
  const initiator = typeof turnInitiatorFile === "string" ? turnInitiatorFile.trim() : "";
30416
30429
  if (initiator) {
30417
- return join8(dirname2(initiator), INBOUND_ATTACHMENTS_SUBDIR);
30430
+ return join9(dirname2(initiator), INBOUND_ATTACHMENTS_SUBDIR);
30418
30431
  }
30419
30432
  const agentIdTrimmed = typeof agentId === "string" ? agentId.trim() : "";
30420
30433
  if (agentIdTrimmed) {
30421
- return join8(homeDir, ".augmented", agentIdTrimmed, INBOUND_ATTACHMENTS_SUBDIR);
30434
+ return join9(homeDir, ".augmented", agentIdTrimmed, INBOUND_ATTACHMENTS_SUBDIR);
30422
30435
  }
30423
30436
  return null;
30424
30437
  }
@@ -30825,9 +30838,9 @@ function isMaintenanceModeActive(opts) {
30825
30838
  }
30826
30839
 
30827
30840
  // src/usage-limit-notice.ts
30828
- import { readFileSync as readFileSync8 } from "fs";
30841
+ import { readFileSync as readFileSync9 } from "fs";
30829
30842
  import { homedir as homedir2 } from "os";
30830
- import { join as join9 } from "path";
30843
+ import { join as join10 } from "path";
30831
30844
 
30832
30845
  // ../core/dist/types/integration.js
30833
30846
  var HITL_TIER_ORDER = [
@@ -33886,6 +33899,86 @@ var INTEGRATION_REGISTRY = [
33886
33899
  ]
33887
33900
  }
33888
33901
  },
33902
+ {
33903
+ // Social Scraping: a PREMIUM, platform-managed integration on the Deck /
33904
+ // Firecrawl / X-Search model (ADR-0031, epic ENG-6920; ADR-0053). Backed by
33905
+ // Apify, but deliberately NOT surfaced as an "Apify" integration - the
33906
+ // integration is what a customer picks, and Apify is a vendor, not a job.
33907
+ // Splitting by job also means opt-in, rate card and monthly budget are keyed
33908
+ // per definition, so an org can take Local Business Data without taking the
33909
+ // pricier, more ToS-sensitive social scraping.
33910
+ //
33911
+ // Augmented holds ONE Apify account whose token (APIFY_API_TOKEN, read
33912
+ // from SSM - the API Lambda env is at the 4KB cap) every customer run bills
33913
+ // back to, so the key is a single platform-held secret, NOT a per-agent
33914
+ // credential. Auth type is `none` - customers never enter a key. Tools run on
33915
+ // a brokered-REST lane (apify-brokers.ts) so each run is metered at one
33916
+ // chokepoint and gated on a per-org monthly USD cap + the per-org premium
33917
+ // opt-in.
33918
+ //
33919
+ // "PPE-only" is guaranteed by a curated allowlist: the broker only ever runs
33920
+ // Actors on it, so a rental / pay-per-usage Actor can never surprise-bill the
33921
+ // shared account. (Apify's x402 rail enforces PPE-only at the payment layer;
33922
+ // we are on the account-key rail - Option A in the spike.) See
33923
+ // docs/design/apify-premium-option-a-ppe-allowlist.md.
33924
+ //
33925
+ // No `installable` here on purpose: this is a seed integration
33926
+ // (integration-definitions.json), so the seed catalog already makes it
33927
+ // picker-visible. This registry entry exists ONLY to carry the `premium`
33928
+ // descriptor that `isPremiumDefinition` reads - which arms the per-org opt-in
33929
+ // gate, the priced acknowledgement modal, and the admin pricing tab.
33930
+ id: "social-scraping",
33931
+ name: "Social Scraping",
33932
+ category: "social",
33933
+ description: "Pull public posts and videos from TikTok, Instagram and YouTube - captions, media, engagement counts and URLs - for brand, competitor and campaign research. Augmented Team manages the scraping account for you; there is no key to enter.",
33934
+ supported_auth_types: ["none"],
33935
+ capabilities: [
33936
+ { id: "social-scraping:scrape", name: "Scrape Social Posts", description: "Scrape public TikTok, Instagram and YouTube content (social_scrape_tiktok, social_scrape_instagram, social_scrape_youtube).", access: "write" },
33937
+ { id: "social-scraping:status", name: "Check Scrape Runs", description: "Poll a running scrape for status + results (social_scrape_status).", access: "read" }
33938
+ ],
33939
+ docs_url: "https://docs.apify.com/api/v2",
33940
+ beta: true,
33941
+ // Premium (billable). The upstream pay-per-event cost is per-Actor and
33942
+ // VARIABLE (each Actor's creator sets its own event prices), unlike X-Search's
33943
+ // fixed per-post price. So we meter the ACTUAL cost charged to us for each
33944
+ // run, as a pass-through: `units` = the run's `usageTotalUsd` in whole US
33945
+ // cents (the physical unit `usd_cent`), and the rate card prices each cent at
33946
+ // a managed markup (1.5x USD). This keeps margin safe across cheap and
33947
+ // expensive scrapes alike. `event_type` must match what the broker writes to
33948
+ // integration_usage_events. Until the rate row is seeded a run prices at 0
33949
+ // (budget gate inert) - the rate-card migration ships in the same PR.
33950
+ premium: {
33951
+ pricing: "usage",
33952
+ note: "Billed per result on the upstream pay-per-event cost of each scrape, at a managed markup.",
33953
+ meters: [{ event_type: "actor_run", unit: "usd_cent" }]
33954
+ }
33955
+ },
33956
+ {
33957
+ // Local Business Data: the second Apify-backed premium integration (ADR-0053).
33958
+ // Same platform-held account, same pass-through metering model, but a separate
33959
+ // definition so its opt-in, rate card and monthly budget are independent of
33960
+ // Social Scraping's - see the note on that entry for why the split exists.
33961
+ //
33962
+ // Distinct from Firecrawl on purpose: Firecrawl covers generic web
33963
+ // scrape/crawl/search, and we deliberately do NOT ship an Apify-backed
33964
+ // duplicate of that. This is the local-places job Firecrawl does not do.
33965
+ id: "local-business-data",
33966
+ name: "Local Business Data",
33967
+ category: "knowledge",
33968
+ description: "Find local businesses on Google Maps and pull their public listing details - name, address, phone, website, category, rating and review count - for local market research, competitor lists and lead research. Augmented Team manages the data account for you; there is no key to enter.",
33969
+ supported_auth_types: ["none"],
33970
+ capabilities: [
33971
+ { id: "local-business-data:search", name: "Search Local Businesses", description: "Search Google Maps for businesses and return their public listing details (local_business_search).", access: "write" },
33972
+ { id: "local-business-data:status", name: "Check Searches", description: "Poll a running search for status + results (local_business_search_status).", access: "read" }
33973
+ ],
33974
+ docs_url: "https://docs.apify.com/api/v2",
33975
+ beta: true,
33976
+ premium: {
33977
+ pricing: "usage",
33978
+ note: "Billed per place returned on the upstream pay-per-event cost of each search, at a managed markup.",
33979
+ meters: [{ event_type: "actor_run", unit: "usd_cent" }]
33980
+ }
33981
+ },
33889
33982
  {
33890
33983
  // Seed-catalog toolkit (composed by the ultimate-app-coder bundle). Registered
33891
33984
  // here only so the manager's ensureToolkitCli installs the binary via the
@@ -35346,14 +35439,14 @@ var FLAGS_SCHEMA_VERSION = computeFlagsSchemaVersion();
35346
35439
  // src/usage-limit-notice.ts
35347
35440
  function usageLimitMarkerPath(codeName) {
35348
35441
  if (!codeName) return null;
35349
- return join9(homedir2(), ".augmented", codeName, USAGE_LIMIT_MARKER_FILENAME);
35442
+ return join10(homedir2(), ".augmented", codeName, USAGE_LIMIT_MARKER_FILENAME);
35350
35443
  }
35351
35444
  function readUsageLimitUntil(opts) {
35352
35445
  const path = opts.filePath ?? usageLimitMarkerPath(opts.codeName);
35353
35446
  if (!path) return null;
35354
35447
  let raw;
35355
35448
  try {
35356
- raw = readFileSync8(path, "utf-8");
35449
+ raw = readFileSync9(path, "utf-8");
35357
35450
  } catch {
35358
35451
  return null;
35359
35452
  }
@@ -35384,7 +35477,7 @@ var DIRECT_CHAT_USAGE_LIMIT_CACHE = /* @__PURE__ */ new Map();
35384
35477
  var AGT_HOST = process.env.AGT_HOST;
35385
35478
  var AGT_API_KEY = process.env.AGT_API_KEY;
35386
35479
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
35387
- var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join10(homedir3(), ".augmented", AGT_AGENT_ID) : null;
35480
+ var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join11(homedir3(), ".augmented", AGT_AGENT_ID) : null;
35388
35481
  var INBOUND_ATTACHMENTS_DIR = resolveInboundAttachmentsDir({
35389
35482
  codeName: process.env.AGT_AGENT_CODE_NAME,
35390
35483
  turnInitiatorFile: process.env.AGT_TURN_INITIATOR_FILE,
@@ -35395,10 +35488,10 @@ var AGT_AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME;
35395
35488
  var directChatStderrLogStream = null;
35396
35489
  if (AGT_AGENT_CODE_NAME) {
35397
35490
  try {
35398
- const logDir = join10(homedir3(), ".augmented", AGT_AGENT_CODE_NAME);
35491
+ const logDir = join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME);
35399
35492
  mkdirSync5(logDir, { recursive: true });
35400
35493
  directChatStderrLogStream = createWriteStream(
35401
- join10(logDir, "direct-chat-channel-stderr.log"),
35494
+ join11(logDir, "direct-chat-channel-stderr.log"),
35402
35495
  { flags: "a", mode: 384 }
35403
35496
  );
35404
35497
  directChatStderrLogStream.on("error", () => {
@@ -35417,10 +35510,10 @@ if (AGT_AGENT_CODE_NAME) {
35417
35510
  } catch {
35418
35511
  }
35419
35512
  }
35420
- var PROGRESS_HEARTBEAT_PATH = AGT_AGENT_CODE_NAME ? join10(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, "channel-progress-heartbeat.json") : null;
35421
- var DIRECT_CHAT_PENDING_INBOUND_DIR = AGT_AGENT_CODE_NAME ? join10(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-pending-inbound") : null;
35422
- var DIRECT_CHAT_DELIVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join10(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-inbound-delivery-ledger") : null;
35423
- var DIRECT_CHAT_CODE_NAME_AGENT_DIR = AGT_AGENT_CODE_NAME ? join10(homedir3(), ".augmented", AGT_AGENT_CODE_NAME) : null;
35513
+ var PROGRESS_HEARTBEAT_PATH = AGT_AGENT_CODE_NAME ? join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, "channel-progress-heartbeat.json") : null;
35514
+ var DIRECT_CHAT_PENDING_INBOUND_DIR = AGT_AGENT_CODE_NAME ? join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-pending-inbound") : null;
35515
+ var DIRECT_CHAT_DELIVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-inbound-delivery-ledger") : null;
35516
+ var DIRECT_CHAT_CODE_NAME_AGENT_DIR = AGT_AGENT_CODE_NAME ? join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME) : null;
35424
35517
  var DIRECT_CHAT_STALE_MARKER_MS = 24 * 60 * 60 * 1e3;
35425
35518
  function recordDirectChatDelivery(sessionId, messageIds) {
35426
35519
  if (!sessionId) return;
@@ -35431,8 +35524,8 @@ function recordDirectChatDelivery(sessionId, messageIds) {
35431
35524
  delivered_at: (/* @__PURE__ */ new Date()).toISOString()
35432
35525
  });
35433
35526
  }
35434
- var DIRECT_CHAT_RECOVERY_OUTBOX_DIR = AGT_AGENT_CODE_NAME ? join10(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-recovery-outbox") : null;
35435
- var DIRECT_CHAT_RECOVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join10(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-direct-chat-recovery-ledger") : null;
35527
+ var DIRECT_CHAT_RECOVERY_OUTBOX_DIR = AGT_AGENT_CODE_NAME ? join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-recovery-outbox") : null;
35528
+ var DIRECT_CHAT_RECOVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-direct-chat-recovery-ledger") : null;
35436
35529
  var progressReceivedAt = /* @__PURE__ */ new Map();
35437
35530
  var directChatProgressState = { tracked: null };
35438
35531
  var directChatProgressTickRunning = false;
@@ -35451,7 +35544,7 @@ var directChatKanbanCardClient = createKanbanCardActiveClient({
35451
35544
  function readProgressHeartbeat() {
35452
35545
  if (!PROGRESS_HEARTBEAT_PATH || !existsSync6(PROGRESS_HEARTBEAT_PATH)) return null;
35453
35546
  try {
35454
- return parseProgressHeartbeat(readFileSync9(PROGRESS_HEARTBEAT_PATH, "utf-8"));
35547
+ return parseProgressHeartbeat(readFileSync10(PROGRESS_HEARTBEAT_PATH, "utf-8"));
35455
35548
  } catch {
35456
35549
  return null;
35457
35550
  }
@@ -35460,12 +35553,12 @@ function seedProgressHeartbeat() {
35460
35553
  if (!PROGRESS_HEARTBEAT_PATH) return;
35461
35554
  const tmp = `${PROGRESS_HEARTBEAT_PATH}.${process.pid}.tmp`;
35462
35555
  try {
35463
- mkdirSync5(join10(homedir3(), ".augmented", AGT_AGENT_CODE_NAME), { recursive: true });
35556
+ mkdirSync5(join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME), { recursive: true });
35464
35557
  writeFileSync6(tmp, serializeProgressHeartbeat(SEED_PROGRESS_STEP, Date.now()), { mode: 384 });
35465
35558
  renameSync5(tmp, PROGRESS_HEARTBEAT_PATH);
35466
35559
  } catch {
35467
35560
  try {
35468
- unlinkSync3(tmp);
35561
+ unlinkSync4(tmp);
35469
35562
  } catch {
35470
35563
  }
35471
35564
  }
@@ -35620,7 +35713,7 @@ var inboundAttachmentDeps = {
35620
35713
  },
35621
35714
  ensureDir: (dir) => mkdirSync5(dir, { recursive: true }),
35622
35715
  writeFile: (path, bytes) => writeFileSync6(path, bytes, { mode: 384 }),
35623
- joinPath: (...parts) => join10(...parts),
35716
+ joinPath: (...parts) => join11(...parts),
35624
35717
  warn: (msg) => process.stderr.write(`${msg}
35625
35718
  `)
35626
35719
  };
@@ -35944,7 +36037,7 @@ function scheduleDirectChatBusyAck(sessionId, messageId, arrivedWhileBusy) {
35944
36037
  let paneLogFreshAgeMs = null;
35945
36038
  if (DIRECT_CHAT_CODE_NAME_AGENT_DIR) {
35946
36039
  try {
35947
- const paneMtimeMs = statSync2(join10(DIRECT_CHAT_CODE_NAME_AGENT_DIR, "pane.log")).mtimeMs;
36040
+ const paneMtimeMs = statSync2(join11(DIRECT_CHAT_CODE_NAME_AGENT_DIR, "pane.log")).mtimeMs;
35948
36041
  paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
35949
36042
  } catch {
35950
36043
  }
@@ -36101,6 +36194,9 @@ async function pollForMessages(sinceMs) {
36101
36194
  if (annotation) injectContent = `${msg.content}${annotation}`;
36102
36195
  attachmentMeta = buildAttachmentMeta(processed);
36103
36196
  }
36197
+ if (!isNotice && msg.sender_id) {
36198
+ clearScheduledTurnMarker(DIRECT_CHAT_CODE_NAME_AGENT_DIR);
36199
+ }
36104
36200
  await mcp.notification({
36105
36201
  method: "notifications/claude/channel",
36106
36202
  params: {
@@ -36267,9 +36363,9 @@ function sweepAgedDirectChatMarkersNow(thresholdMs) {
36267
36363
  const now = Date.now();
36268
36364
  const res = sweepAgedDirectChatMarkers(DIRECT_CHAT_PENDING_INBOUND_DIR, {
36269
36365
  readdir: (dir) => readdirSync4(dir),
36270
- readFile: (p2) => readFileSync9(p2, "utf8"),
36366
+ readFile: (p2) => readFileSync10(p2, "utf8"),
36271
36367
  unlink: (p2) => {
36272
- if (existsSync6(p2)) unlinkSync3(p2);
36368
+ if (existsSync6(p2)) unlinkSync4(p2);
36273
36369
  },
36274
36370
  isAged: (receivedAt) => isMarkerGenuinelyAged(receivedAt, now, thresholdMs),
36275
36371
  hasDelivery: (inboundId) => inboundDeliveryLedgerHas(DIRECT_CHAT_DELIVERY_LEDGER_DIR, inboundId),
@@ -36303,10 +36399,10 @@ function sanitizeRecoveryText(text) {
36303
36399
  }
36304
36400
  function directChatRecoveryDeps() {
36305
36401
  return {
36306
- readFile: (p2) => readFileSync9(p2, "utf-8"),
36402
+ readFile: (p2) => readFileSync10(p2, "utf-8"),
36307
36403
  renameFile: (from, to) => renameSync5(from, to),
36308
36404
  unlinkFile: (p2) => {
36309
- if (existsSync6(p2)) unlinkSync3(p2);
36405
+ if (existsSync6(p2)) unlinkSync4(p2);
36310
36406
  },
36311
36407
  sanitize: sanitizeRecoveryText,
36312
36408
  peekClaims: (sessionId) => claimTracker.peek(sessionId),
@@ -36316,8 +36412,8 @@ function directChatRecoveryDeps() {
36316
36412
  if (!DIRECT_CHAT_RECOVERY_LEDGER_DIR) return;
36317
36413
  if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return;
36318
36414
  try {
36319
- const p2 = join10(DIRECT_CHAT_RECOVERY_LEDGER_DIR, markerName);
36320
- if (existsSync6(p2)) unlinkSync3(p2);
36415
+ const p2 = join11(DIRECT_CHAT_RECOVERY_LEDGER_DIR, markerName);
36416
+ if (existsSync6(p2)) unlinkSync4(p2);
36321
36417
  } catch {
36322
36418
  }
36323
36419
  },
@@ -36352,7 +36448,7 @@ async function processDirectChatRecoveryOutboxFile(filename) {
36352
36448
  if (!enabled) return;
36353
36449
  directChatRecoveryInFlight.add(filename);
36354
36450
  try {
36355
- const fullPath = join10(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, filename);
36451
+ const fullPath = join11(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, filename);
36356
36452
  await consumeDirectChatRecoveryFile(fullPath, filename, directChatRecoveryDeps());
36357
36453
  } catch (err) {
36358
36454
  process.stderr.write(
@@ -36380,7 +36476,7 @@ if (DIRECT_CHAT_RECOVERY_OUTBOX_DIR) {
36380
36476
  if (!filename) return;
36381
36477
  const name = filename.toString();
36382
36478
  if (!name.endsWith(".json")) return;
36383
- if (existsSync6(join10(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, name))) {
36479
+ if (existsSync6(join11(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, name))) {
36384
36480
  void processDirectChatRecoveryOutboxFile(name);
36385
36481
  }
36386
36482
  });
@@ -39538,6 +39538,86 @@ var INTEGRATION_REGISTRY = [
39538
39538
  ]
39539
39539
  }
39540
39540
  },
39541
+ {
39542
+ // Social Scraping: a PREMIUM, platform-managed integration on the Deck /
39543
+ // Firecrawl / X-Search model (ADR-0031, epic ENG-6920; ADR-0053). Backed by
39544
+ // Apify, but deliberately NOT surfaced as an "Apify" integration - the
39545
+ // integration is what a customer picks, and Apify is a vendor, not a job.
39546
+ // Splitting by job also means opt-in, rate card and monthly budget are keyed
39547
+ // per definition, so an org can take Local Business Data without taking the
39548
+ // pricier, more ToS-sensitive social scraping.
39549
+ //
39550
+ // Augmented holds ONE Apify account whose token (APIFY_API_TOKEN, read
39551
+ // from SSM - the API Lambda env is at the 4KB cap) every customer run bills
39552
+ // back to, so the key is a single platform-held secret, NOT a per-agent
39553
+ // credential. Auth type is `none` - customers never enter a key. Tools run on
39554
+ // a brokered-REST lane (apify-brokers.ts) so each run is metered at one
39555
+ // chokepoint and gated on a per-org monthly USD cap + the per-org premium
39556
+ // opt-in.
39557
+ //
39558
+ // "PPE-only" is guaranteed by a curated allowlist: the broker only ever runs
39559
+ // Actors on it, so a rental / pay-per-usage Actor can never surprise-bill the
39560
+ // shared account. (Apify's x402 rail enforces PPE-only at the payment layer;
39561
+ // we are on the account-key rail - Option A in the spike.) See
39562
+ // docs/design/apify-premium-option-a-ppe-allowlist.md.
39563
+ //
39564
+ // No `installable` here on purpose: this is a seed integration
39565
+ // (integration-definitions.json), so the seed catalog already makes it
39566
+ // picker-visible. This registry entry exists ONLY to carry the `premium`
39567
+ // descriptor that `isPremiumDefinition` reads - which arms the per-org opt-in
39568
+ // gate, the priced acknowledgement modal, and the admin pricing tab.
39569
+ id: "social-scraping",
39570
+ name: "Social Scraping",
39571
+ category: "social",
39572
+ description: "Pull public posts and videos from TikTok, Instagram and YouTube - captions, media, engagement counts and URLs - for brand, competitor and campaign research. Augmented Team manages the scraping account for you; there is no key to enter.",
39573
+ supported_auth_types: ["none"],
39574
+ capabilities: [
39575
+ { id: "social-scraping:scrape", name: "Scrape Social Posts", description: "Scrape public TikTok, Instagram and YouTube content (social_scrape_tiktok, social_scrape_instagram, social_scrape_youtube).", access: "write" },
39576
+ { id: "social-scraping:status", name: "Check Scrape Runs", description: "Poll a running scrape for status + results (social_scrape_status).", access: "read" }
39577
+ ],
39578
+ docs_url: "https://docs.apify.com/api/v2",
39579
+ beta: true,
39580
+ // Premium (billable). The upstream pay-per-event cost is per-Actor and
39581
+ // VARIABLE (each Actor's creator sets its own event prices), unlike X-Search's
39582
+ // fixed per-post price. So we meter the ACTUAL cost charged to us for each
39583
+ // run, as a pass-through: `units` = the run's `usageTotalUsd` in whole US
39584
+ // cents (the physical unit `usd_cent`), and the rate card prices each cent at
39585
+ // a managed markup (1.5x USD). This keeps margin safe across cheap and
39586
+ // expensive scrapes alike. `event_type` must match what the broker writes to
39587
+ // integration_usage_events. Until the rate row is seeded a run prices at 0
39588
+ // (budget gate inert) - the rate-card migration ships in the same PR.
39589
+ premium: {
39590
+ pricing: "usage",
39591
+ note: "Billed per result on the upstream pay-per-event cost of each scrape, at a managed markup.",
39592
+ meters: [{ event_type: "actor_run", unit: "usd_cent" }]
39593
+ }
39594
+ },
39595
+ {
39596
+ // Local Business Data: the second Apify-backed premium integration (ADR-0053).
39597
+ // Same platform-held account, same pass-through metering model, but a separate
39598
+ // definition so its opt-in, rate card and monthly budget are independent of
39599
+ // Social Scraping's - see the note on that entry for why the split exists.
39600
+ //
39601
+ // Distinct from Firecrawl on purpose: Firecrawl covers generic web
39602
+ // scrape/crawl/search, and we deliberately do NOT ship an Apify-backed
39603
+ // duplicate of that. This is the local-places job Firecrawl does not do.
39604
+ id: "local-business-data",
39605
+ name: "Local Business Data",
39606
+ category: "knowledge",
39607
+ description: "Find local businesses on Google Maps and pull their public listing details - name, address, phone, website, category, rating and review count - for local market research, competitor lists and lead research. Augmented Team manages the data account for you; there is no key to enter.",
39608
+ supported_auth_types: ["none"],
39609
+ capabilities: [
39610
+ { id: "local-business-data:search", name: "Search Local Businesses", description: "Search Google Maps for businesses and return their public listing details (local_business_search).", access: "write" },
39611
+ { id: "local-business-data:status", name: "Check Searches", description: "Poll a running search for status + results (local_business_search_status).", access: "read" }
39612
+ ],
39613
+ docs_url: "https://docs.apify.com/api/v2",
39614
+ beta: true,
39615
+ premium: {
39616
+ pricing: "usage",
39617
+ note: "Billed per place returned on the upstream pay-per-event cost of each search, at a managed markup.",
39618
+ meters: [{ event_type: "actor_run", unit: "usd_cent" }]
39619
+ }
39620
+ },
39541
39621
  {
39542
39622
  // Seed-catalog toolkit (composed by the ultimate-app-coder bundle). Registered
39543
39623
  // here only so the manager's ensureToolkitCli installs the binary via the