@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.
- package/dist/bin/agt.js +4 -4
- package/dist/{chunk-4SEBGBAO.js → chunk-M3L6HOYG.js} +3 -3
- package/dist/{chunk-XFC7YVGS.js → chunk-PR3IJAMV.js} +81 -1
- package/dist/chunk-PR3IJAMV.js.map +1 -0
- package/dist/{claude-pair-runtime-3JHCWZZD.js → claude-pair-runtime-XN4JLRAB.js} +2 -2
- package/dist/lib/manager-worker.js +63 -42
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +160 -64
- package/dist/mcp/origami.js +80 -0
- package/dist/mcp/slack-channel.js +81 -1
- package/dist/mcp/telegram-channel.js +193 -97
- package/dist/{persistent-session-HWCKGPYF.js → persistent-session-37WNPBRA.js} +2 -2
- package/dist/{responsiveness-probe-4CGMUXOH.js → responsiveness-probe-GMIXR3TR.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-XFC7YVGS.js.map +0 -1
- /package/dist/{chunk-4SEBGBAO.js.map → chunk-M3L6HOYG.js.map} +0 -0
- /package/dist/{claude-pair-runtime-3JHCWZZD.js.map → claude-pair-runtime-XN4JLRAB.js.map} +0 -0
- /package/dist/{persistent-session-HWCKGPYF.js.map → persistent-session-37WNPBRA.js.map} +0 -0
- /package/dist/{responsiveness-probe-4CGMUXOH.js.map → responsiveness-probe-GMIXR3TR.js.map} +0 -0
|
@@ -18867,7 +18867,7 @@ var require_filters = __commonJS({
|
|
|
18867
18867
|
return r.copySafeness(str, res);
|
|
18868
18868
|
}
|
|
18869
18869
|
_exports.indent = indent;
|
|
18870
|
-
function
|
|
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 =
|
|
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
|
|
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
|
|
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))
|
|
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 =
|
|
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(
|
|
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) =>
|
|
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(
|
|
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 =
|
|
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
|
|
30001
|
-
import { join as
|
|
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) =>
|
|
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 =
|
|
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(
|
|
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
|
|
30039
|
-
import { join as
|
|
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
|
|
30055
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
|
|
30043
30056
|
import { homedir } from "os";
|
|
30044
|
-
import { join as
|
|
30057
|
+
import { join as join6 } from "path";
|
|
30045
30058
|
function defaultFlagsCachePath() {
|
|
30046
|
-
return
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
30293
|
+
readFileSync as readFileSync8,
|
|
30281
30294
|
renameSync as renameSync4,
|
|
30282
30295
|
statSync,
|
|
30283
|
-
unlinkSync as
|
|
30296
|
+
unlinkSync as unlinkSync3,
|
|
30284
30297
|
utimesSync,
|
|
30285
30298
|
writeFileSync as writeFileSync5
|
|
30286
30299
|
} from "fs";
|
|
30287
|
-
import { join as
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
|
30409
|
+
readFileSync as readFileSync10,
|
|
30397
30410
|
readdirSync as readdirSync4,
|
|
30398
30411
|
existsSync as existsSync6,
|
|
30399
30412
|
renameSync as renameSync5,
|
|
30400
|
-
unlinkSync as
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
30841
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
30829
30842
|
import { homedir as homedir2 } from "os";
|
|
30830
|
-
import { join as
|
|
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
|
|
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 =
|
|
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 ?
|
|
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 =
|
|
35491
|
+
const logDir = join11(homedir3(), ".augmented", AGT_AGENT_CODE_NAME);
|
|
35399
35492
|
mkdirSync5(logDir, { recursive: true });
|
|
35400
35493
|
directChatStderrLogStream = createWriteStream(
|
|
35401
|
-
|
|
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 ?
|
|
35421
|
-
var DIRECT_CHAT_PENDING_INBOUND_DIR = AGT_AGENT_CODE_NAME ?
|
|
35422
|
-
var DIRECT_CHAT_DELIVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ?
|
|
35423
|
-
var DIRECT_CHAT_CODE_NAME_AGENT_DIR = AGT_AGENT_CODE_NAME ?
|
|
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 ?
|
|
35435
|
-
var DIRECT_CHAT_RECOVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ?
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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) =>
|
|
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(
|
|
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) =>
|
|
36366
|
+
readFile: (p2) => readFileSync10(p2, "utf8"),
|
|
36271
36367
|
unlink: (p2) => {
|
|
36272
|
-
if (existsSync6(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) =>
|
|
36402
|
+
readFile: (p2) => readFileSync10(p2, "utf-8"),
|
|
36307
36403
|
renameFile: (from, to) => renameSync5(from, to),
|
|
36308
36404
|
unlinkFile: (p2) => {
|
|
36309
|
-
if (existsSync6(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 =
|
|
36320
|
-
if (existsSync6(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 =
|
|
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(
|
|
36479
|
+
if (existsSync6(join11(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, name))) {
|
|
36384
36480
|
void processDirectChatRecoveryOutboxFile(name);
|
|
36385
36481
|
}
|
|
36386
36482
|
});
|
package/dist/mcp/origami.js
CHANGED
|
@@ -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
|