@graph8/sdk 0.13.1 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -846,6 +846,8 @@ var KNOWN_WEBHOOK_EVENTS = [
846
846
  "engagement.email_bounced",
847
847
  "engagement.email_skipped",
848
848
  "engagement.call_dispatched",
849
+ "engagement.call_connected",
850
+ "engagement.call_graded",
849
851
  "engagement.sms_sent",
850
852
  "engagement.sms_replied",
851
853
  "engagement.whatsapp_sent",
@@ -856,7 +858,12 @@ var KNOWN_WEBHOOK_EVENTS = [
856
858
  "engagement.linkedin_connection_accepted",
857
859
  "meeting.booked",
858
860
  "meeting.cancelled",
859
- "meeting.rescheduled"
861
+ "meeting.rescheduled",
862
+ "deal.won",
863
+ "crm.record.created",
864
+ "crm.record.updated",
865
+ "crm.record.archived",
866
+ "crm.record.restored"
860
867
  ];
861
868
  var WebhookSignatureError = class extends Error {
862
869
  constructor(message) {
@@ -1216,10 +1223,284 @@ var createAppsClient = (apiKey, apiUrl) => {
1216
1223
  };
1217
1224
  };
1218
1225
 
1219
- // src/fields.ts
1226
+ // src/appPlatform.ts
1220
1227
  var DEFAULT_API18 = "https://be.graph8.com";
1221
- var createFieldsClient = (apiKey, apiUrl) => {
1228
+ var MIN_TAIL_LINES = 1;
1229
+ var MAX_TAIL_LINES = 2e3;
1230
+ var createAppPlatformClient = (apiKey, apiUrl) => {
1222
1231
  const baseUrl = apiUrl || DEFAULT_API18;
1232
+ const unwrap = (resp) => resp.data ?? resp;
1233
+ return {
1234
+ // ---- source binding -------------------------------------------------
1235
+ /**
1236
+ * Bind the repository an app builds from.
1237
+ *
1238
+ * `repo_url` must be fetchable -- `https://`, `ssh://` or `git@`, with no
1239
+ * whitespace. A `file://` or bare path is refused with 422, because a build
1240
+ * that can read the builder's filesystem is a build that can read ours.
1241
+ *
1242
+ * `credential_ref` is a POINTER into your secret manager, not a token.
1243
+ */
1244
+ async setSource(appId, params) {
1245
+ const resp = await request(
1246
+ baseUrl,
1247
+ `/api/v1/apps/${appId}/source`,
1248
+ apiKey,
1249
+ {
1250
+ method: "PUT",
1251
+ body: {
1252
+ repo_url: params.repo_url,
1253
+ provider: params.provider,
1254
+ default_branch: params.default_branch ?? null,
1255
+ credential_ref: params.credential_ref ?? null
1256
+ }
1257
+ }
1258
+ );
1259
+ return unwrap(resp);
1260
+ },
1261
+ /** Unbind the source. Returns the full app with every source field null. */
1262
+ async clearSource(appId) {
1263
+ const resp = await request(
1264
+ baseUrl,
1265
+ `/api/v1/apps/${appId}/source`,
1266
+ apiKey,
1267
+ { method: "DELETE" }
1268
+ );
1269
+ return unwrap(resp);
1270
+ },
1271
+ // ---- deployments ----------------------------------------------------
1272
+ /** Every deployment for this app, newest first. Never 404s for an app with none. */
1273
+ async listDeployments(appId) {
1274
+ return request(baseUrl, `/api/v1/apps/${appId}/deployments`, apiKey);
1275
+ },
1276
+ /**
1277
+ * Queue a deployment. Returns `201` with `status: "queued"` -- nothing builds
1278
+ * as a side effect of this call; the build controller picks it up.
1279
+ *
1280
+ * NOT idempotent: two identical calls create two deployments.
1281
+ */
1282
+ async deploy(appId, params) {
1283
+ const body = { source_ref: params.source_ref };
1284
+ if (params.schema_version_id) body.schema_version_id = params.schema_version_id;
1285
+ const resp = await request(
1286
+ baseUrl,
1287
+ `/api/v1/apps/${appId}/deployments`,
1288
+ apiKey,
1289
+ { method: "POST", body }
1290
+ );
1291
+ return unwrap(resp);
1292
+ },
1293
+ /** Fetch one deployment. The polling endpoint for a build loop. */
1294
+ async getDeployment(appId, deploymentId) {
1295
+ const resp = await request(
1296
+ baseUrl,
1297
+ `/api/v1/apps/${appId}/deployments/${deploymentId}`,
1298
+ apiKey
1299
+ );
1300
+ return unwrap(resp);
1301
+ },
1302
+ /**
1303
+ * The deployment currently serving traffic, or `null`.
1304
+ *
1305
+ * `null` is a real answer with a 200, not a 404: "this app has never shipped"
1306
+ * is information, while a 404 would read as "no such app".
1307
+ */
1308
+ async activeDeployment(appId) {
1309
+ const resp = await request(
1310
+ baseUrl,
1311
+ `/api/v1/apps/${appId}/deployments/active`,
1312
+ apiKey
1313
+ );
1314
+ return resp.data ?? null;
1315
+ },
1316
+ /**
1317
+ * Promote a built deployment to serve traffic. Anything it displaces moves to
1318
+ * `rolled_back` in the same transaction, so there is never a moment with two
1319
+ * live deployments.
1320
+ *
1321
+ * `409` when the state machine forbids it -- a deployment cannot become
1322
+ * `deployed` without having been built, and a `failed` one cannot be revived.
1323
+ * A retry is a new deployment, not a resurrection.
1324
+ */
1325
+ async promote(appId, deploymentId, imageDigest) {
1326
+ const resp = await request(
1327
+ baseUrl,
1328
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/promote`,
1329
+ apiKey,
1330
+ { method: "POST", body: { image_digest: imageDigest } }
1331
+ );
1332
+ return unwrap(resp);
1333
+ },
1334
+ /** Roll back a deployment that is currently serving. Only a `deployed` one may be. */
1335
+ async rollback(appId, deploymentId) {
1336
+ const resp = await request(
1337
+ baseUrl,
1338
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/rollback`,
1339
+ apiKey,
1340
+ { method: "POST", body: {} }
1341
+ );
1342
+ return unwrap(resp);
1343
+ },
1344
+ // ---- logs -----------------------------------------------------------
1345
+ /**
1346
+ * Why a build failed. Returns every step of the build pod in the order
1347
+ * Kubernetes runs them; a step that has not started yet is omitted rather
1348
+ * than returned empty.
1349
+ *
1350
+ * An empty `containers` list is not an error -- build pods are reaped an hour
1351
+ * after they finish, so logs for an older deployment are genuinely gone.
1352
+ * `last_error_sanitized` on the deployment is what survives.
1353
+ *
1354
+ * `503` means graph8 could not reach the cluster, which is deliberately
1355
+ * different from an empty `200`: one means we could not look, the other means
1356
+ * your build produced no output.
1357
+ */
1358
+ async deploymentLogs(appId, deploymentId, tailLines) {
1359
+ const resp = await request(
1360
+ baseUrl,
1361
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/logs`,
1362
+ apiKey,
1363
+ { query: tailLines === void 0 ? void 0 : { tail_lines: tailLines } }
1364
+ );
1365
+ return unwrap(resp);
1366
+ },
1367
+ /**
1368
+ * What the running app is printing. The app's own pods only -- the per-app
1369
+ * egress proxy shares the namespace and is deliberately excluded.
1370
+ *
1371
+ * Empty until a deployment reaches `deployed`.
1372
+ */
1373
+ async logs(appId, tailLines) {
1374
+ const resp = await request(
1375
+ baseUrl,
1376
+ `/api/v1/apps/${appId}/logs`,
1377
+ apiKey,
1378
+ { query: tailLines === void 0 ? void 0 : { tail_lines: tailLines } }
1379
+ );
1380
+ return unwrap(resp);
1381
+ },
1382
+ // ---- domains --------------------------------------------------------
1383
+ /** Every hostname claimed for this app, whatever its verification state. */
1384
+ async listDomains(appId) {
1385
+ return request(baseUrl, `/api/v1/apps/${appId}/domains`, apiKey);
1386
+ },
1387
+ /**
1388
+ * Claim a hostname and get the TXT record that proves you own it.
1389
+ *
1390
+ * Returns `201`, and the domain is NESTED at `data.domain` -- this is the one
1391
+ * route on the surface whose payload is not the record itself. Hostnames are
1392
+ * globally unique, so a host another app holds is refused.
1393
+ */
1394
+ async claimDomain(appId, hostname) {
1395
+ const resp = await request(
1396
+ baseUrl,
1397
+ `/api/v1/apps/${appId}/domains`,
1398
+ apiKey,
1399
+ { method: "POST", body: { hostname } }
1400
+ );
1401
+ return unwrap(resp);
1402
+ },
1403
+ /**
1404
+ * Check DNS for the TXT record and advance the domain to `verified`.
1405
+ *
1406
+ * Idempotent: verifying an already-verified domain re-checks and stays
1407
+ * verified, so it is safe to re-run after a DNS change. Send no body -- the
1408
+ * record in DNS is the payload.
1409
+ */
1410
+ async verifyDomain(appId, hostname) {
1411
+ const resp = await request(
1412
+ baseUrl,
1413
+ `/api/v1/apps/${appId}/domains/${encodeURIComponent(hostname)}/verify`,
1414
+ apiKey,
1415
+ { method: "POST", body: {} }
1416
+ );
1417
+ return unwrap(resp);
1418
+ },
1419
+ /**
1420
+ * Release a claimed hostname.
1421
+ *
1422
+ * A HARD delete. Hostnames are globally unique, so a row left behind in any
1423
+ * status keeps the host burned for every other builder. Releasing one you
1424
+ * already released is a `404`, because after the first call the claim
1425
+ * genuinely does not exist.
1426
+ *
1427
+ * Returns the NORMALIZED hostname, which may differ from what you passed.
1428
+ */
1429
+ async releaseDomain(appId, hostname) {
1430
+ const resp = await request(
1431
+ baseUrl,
1432
+ `/api/v1/apps/${appId}/domains/${encodeURIComponent(hostname)}`,
1433
+ apiKey,
1434
+ { method: "DELETE" }
1435
+ );
1436
+ return unwrap(resp);
1437
+ },
1438
+ // ---- secrets --------------------------------------------------------
1439
+ /**
1440
+ * Which secrets this app declares, and when each was last rotated.
1441
+ *
1442
+ * NEVER returns a value. graph8 stores a POINTER into your secret manager and
1443
+ * has no column for the secret itself.
1444
+ */
1445
+ async listSecrets(appId) {
1446
+ return request(baseUrl, `/api/v1/apps/${appId}/secrets`, apiKey);
1447
+ },
1448
+ /**
1449
+ * Declare a secret, or rotate the pointer to it.
1450
+ *
1451
+ * `providerRef` is a REFERENCE, and the server rejects anything that looks
1452
+ * like a credential -- a value starting `bearer `, `sk-`, `ghp_`, `xox` and
1453
+ * friends is a 422. That refusal is the feature: it catches the mistake of
1454
+ * pasting the secret where its address belongs.
1455
+ */
1456
+ async putSecret(appId, secretKey, providerRef) {
1457
+ const resp = await request(
1458
+ baseUrl,
1459
+ `/api/v1/apps/${appId}/secrets/${encodeURIComponent(secretKey)}`,
1460
+ apiKey,
1461
+ { method: "PUT", body: { provider_ref: providerRef ?? null } }
1462
+ );
1463
+ return unwrap(resp);
1464
+ },
1465
+ /** Undeclare a secret. A key the app never declared is a 404, so a typo is
1466
+ * never reported as a successful removal. */
1467
+ async deleteSecret(appId, secretKey) {
1468
+ const resp = await request(
1469
+ baseUrl,
1470
+ `/api/v1/apps/${appId}/secrets/${encodeURIComponent(secretKey)}`,
1471
+ apiKey,
1472
+ { method: "DELETE" }
1473
+ );
1474
+ return unwrap(resp);
1475
+ },
1476
+ // ---- schema versions ------------------------------------------------
1477
+ /**
1478
+ * Publish a custom-object schema version. Returns `201`.
1479
+ *
1480
+ * Takes only the `objects` list, not a whole `graph8.app.yaml`: the rest of
1481
+ * that file is app metadata the control plane already holds, and accepting it
1482
+ * here would create a second place for it to disagree.
1483
+ */
1484
+ async publishSchemaVersion(appId, objects) {
1485
+ const resp = await request(
1486
+ baseUrl,
1487
+ `/api/v1/apps/${appId}/schema-versions`,
1488
+ apiKey,
1489
+ { method: "POST", body: { objects } }
1490
+ );
1491
+ return unwrap(resp);
1492
+ },
1493
+ /** Every schema version this app has published. Empty array, never 404. */
1494
+ async listSchemaVersions(appId) {
1495
+ return request(baseUrl, `/api/v1/apps/${appId}/schema-versions`, apiKey);
1496
+ }
1497
+ };
1498
+ };
1499
+
1500
+ // src/fields.ts
1501
+ var DEFAULT_API19 = "https://be.graph8.com";
1502
+ var createFieldsClient = (apiKey, apiUrl) => {
1503
+ const baseUrl = apiUrl || DEFAULT_API19;
1223
1504
  return {
1224
1505
  /** List contact fields (base + custom). Pass listId to include list-specific custom fields. */
1225
1506
  async listContactFields(listId) {
@@ -1261,14 +1542,38 @@ var createFieldsClient = (apiKey, apiUrl) => {
1261
1542
  };
1262
1543
 
1263
1544
  // src/objects.ts
1264
- var DEFAULT_API19 = "https://be.graph8.com";
1545
+ var DEFAULT_API20 = "https://be.graph8.com";
1265
1546
  var createObjectsClient = (apiKey, apiUrl) => {
1266
- const baseUrl = apiUrl || DEFAULT_API19;
1547
+ const baseUrl = apiUrl || DEFAULT_API20;
1267
1548
  const encode = (value) => encodeURIComponent(value);
1268
1549
  return {
1269
1550
  /** List the custom object types in your workspace. */
1270
- async list() {
1271
- return request(baseUrl, "/api/v1/objects", apiKey);
1551
+ async list(params = {}) {
1552
+ const query = params.include_archived ? "?include_archived=true" : "";
1553
+ return request(baseUrl, `/api/v1/objects${query}`, apiKey);
1554
+ },
1555
+ /** Create a native custom object. Requires objects:manage and Admin access. */
1556
+ async create(input) {
1557
+ const resp = await request(baseUrl, "/api/v1/objects", apiKey, {
1558
+ method: "POST",
1559
+ body: input
1560
+ });
1561
+ return resp.data;
1562
+ },
1563
+ /** Rename, archive or restore an object while preserving its slug and data. */
1564
+ async update(objectSlug, input) {
1565
+ const resp = await request(baseUrl, `/api/v1/objects/${encode(objectSlug)}`, apiKey, {
1566
+ method: "PATCH",
1567
+ body: input
1568
+ });
1569
+ return resp.data;
1570
+ },
1571
+ /** Archive the object without deleting records; restore with update({ is_archived: false }). */
1572
+ async archive(objectSlug) {
1573
+ const resp = await request(baseUrl, `/api/v1/objects/${encode(objectSlug)}`, apiKey, {
1574
+ method: "DELETE"
1575
+ });
1576
+ return resp.data;
1272
1577
  },
1273
1578
  /** Fetch one object type by slug. */
1274
1579
  async get(objectSlug) {
@@ -1280,10 +1585,35 @@ var createObjectsClient = (apiKey, apiUrl) => {
1280
1585
  return resp.data ?? resp;
1281
1586
  },
1282
1587
  /** The object's attributes — the schema its records must satisfy. */
1283
- async listAttributes(objectSlug) {
1284
- return request(baseUrl, `/api/v1/objects/${encode(objectSlug)}/attributes`, apiKey);
1588
+ async listAttributes(objectSlug, params = {}) {
1589
+ const query = params.include_archived ? "?include_archived=true" : "";
1590
+ return request(baseUrl, `/api/v1/objects/${encode(objectSlug)}/attributes${query}`, apiKey);
1591
+ },
1592
+ /** Create a field using the same schema rules as the customer UI. */
1593
+ async createAttribute(objectSlug, input) {
1594
+ const resp = await request(baseUrl, `/api/v1/objects/${encode(objectSlug)}/attributes`, apiKey, {
1595
+ method: "POST",
1596
+ body: input
1597
+ });
1598
+ return resp.data;
1285
1599
  },
1286
- /** Paginated records with their current values. Archived records are excluded. */
1600
+ /** Edit or restore a field; its type and slug are immutable. */
1601
+ async updateAttribute(objectSlug, attributeSlug, input) {
1602
+ const resp = await request(baseUrl, `/api/v1/objects/${encode(objectSlug)}/attributes/${encode(attributeSlug)}`, apiKey, {
1603
+ method: "PATCH",
1604
+ body: input
1605
+ });
1606
+ return resp.data;
1607
+ },
1608
+ /** Archive without deleting values; restore with updateAttribute({ is_archived: false }). */
1609
+ async archiveAttribute(objectSlug, attributeSlug) {
1610
+ const resp = await request(baseUrl, `/api/v1/objects/${encode(objectSlug)}/attributes/${encode(attributeSlug)}`, apiKey, {
1611
+ method: "DELETE"
1612
+ });
1613
+ return resp.data;
1614
+ },
1615
+ /** Paginated custom records or canonical deals with current values and revisions.
1616
+ * Deal totals and related references respect current record access. */
1287
1617
  async listRecords(objectSlug, params = {}) {
1288
1618
  const query = {};
1289
1619
  if (params.page != null) query.page = params.page;
@@ -1307,7 +1637,24 @@ var createObjectsClient = (apiKey, apiUrl) => {
1307
1637
  );
1308
1638
  return resp.data ?? resp;
1309
1639
  },
1310
- /** Fetch one record with its currently active values. */
1640
+ /** Match a unique single-value key, creating or updating while preserving omitted fields. */
1641
+ async upsertRecord(objectSlug, matchingAttribute, values, options = {}) {
1642
+ const resp = await request(
1643
+ baseUrl,
1644
+ `/api/v1/objects/${encode(objectSlug)}/records/upsert`,
1645
+ apiKey,
1646
+ { method: "POST", body: {
1647
+ matching_attribute: matchingAttribute,
1648
+ values,
1649
+ ...options.expectedRevision !== void 0 ? { expected_revision: options.expectedRevision } : {}
1650
+ } }
1651
+ );
1652
+ return resp.data;
1653
+ },
1654
+ /** Fetch one custom record, canonical contact/company, or deal by its stable graph8 ID.
1655
+ * Deals retain their UUIDs and expose company, primary-contact and contact_ids references only
1656
+ * when permitted. Generic deal mutations are not yet supported.
1657
+ */
1311
1658
  async getRecord(objectSlug, recordId) {
1312
1659
  const resp = await request(
1313
1660
  baseUrl,
@@ -1321,15 +1668,24 @@ var createObjectsClient = (apiKey, apiUrl) => {
1321
1668
  * required attributes you omit are left alone rather than reported missing.
1322
1669
  * Sending an explicit `null` CLEARS that attribute.
1323
1670
  *
1324
- * Values are versioned rather than overwritten, so the previous value stays
1325
- * readable through `history`.
1671
+ * Custom values retain generations through `history`. Canonical contacts and
1672
+ * companies require expectedRevision from a fresh read and expose recorded
1673
+ * mutations through `changes`. They do not yet support appendValues/removeValues.
1326
1674
  */
1327
1675
  async updateRecord(objectSlug, recordId, values, options) {
1328
1676
  const resp = await request(
1329
1677
  baseUrl,
1330
1678
  `/api/v1/objects/${encode(objectSlug)}/records/${encode(recordId)}`,
1331
1679
  apiKey,
1332
- { method: "PATCH", body: { values, ...options?.expectedRevision === void 0 ? {} : { expected_revision: options.expectedRevision } } }
1680
+ {
1681
+ method: "PATCH",
1682
+ body: {
1683
+ values,
1684
+ ...options?.expectedRevision === void 0 ? {} : { expected_revision: options.expectedRevision },
1685
+ ...options?.appendValues === void 0 ? {} : { append_values: options.appendValues },
1686
+ ...options?.removeValues === void 0 ? {} : { remove_values: options.removeValues }
1687
+ }
1688
+ }
1333
1689
  );
1334
1690
  return resp.data ?? resp;
1335
1691
  },
@@ -1368,14 +1724,27 @@ var createObjectsClient = (apiKey, apiUrl) => {
1368
1724
  { query: limit != null ? { limit } : void 0 }
1369
1725
  );
1370
1726
  return resp.data ?? resp;
1727
+ },
1728
+ /** Recorded custom-record or canonical contact/company mutations. Pass next_cursor to continue.
1729
+ * Canonical history respects current access/privacy; archived records and older
1730
+ * unrecorded writes are not reconstructed. Store unavailability returns 503.
1731
+ */
1732
+ async changes(objectSlug, recordId, options = {}) {
1733
+ const resp = await request(
1734
+ baseUrl,
1735
+ `/api/v1/objects/${encode(objectSlug)}/records/${encode(recordId)}/changes`,
1736
+ apiKey,
1737
+ { query: options }
1738
+ );
1739
+ return resp.data ?? resp;
1371
1740
  }
1372
1741
  };
1373
1742
  };
1374
1743
 
1375
1744
  // src/deals.ts
1376
- var DEFAULT_API20 = "https://be.graph8.com";
1745
+ var DEFAULT_API21 = "https://be.graph8.com";
1377
1746
  var createDealsClient = (apiKey, apiUrl) => {
1378
- const baseUrl = apiUrl || DEFAULT_API20;
1747
+ const baseUrl = apiUrl || DEFAULT_API21;
1379
1748
  return {
1380
1749
  /** List all deal pipelines and their stages. */
1381
1750
  async pipelines() {
@@ -1419,9 +1788,9 @@ var createDealsClient = (apiKey, apiUrl) => {
1419
1788
  };
1420
1789
 
1421
1790
  // src/inbox.ts
1422
- var DEFAULT_API21 = "https://be.graph8.com";
1791
+ var DEFAULT_API22 = "https://be.graph8.com";
1423
1792
  var createInboxClient = (apiKey, apiUrl) => {
1424
- const baseUrl = apiUrl || DEFAULT_API21;
1793
+ const baseUrl = apiUrl || DEFAULT_API22;
1425
1794
  return {
1426
1795
  /** List inbox threads across email, SMS, and LinkedIn. */
1427
1796
  async list(params = {}) {
@@ -1474,9 +1843,9 @@ var createInboxClient = (apiKey, apiUrl) => {
1474
1843
  };
1475
1844
 
1476
1845
  // src/quotes.ts
1477
- var DEFAULT_API22 = "https://be.graph8.com";
1846
+ var DEFAULT_API23 = "https://be.graph8.com";
1478
1847
  var createQuotesClient = (apiKey, apiUrl) => {
1479
- const baseUrl = apiUrl || DEFAULT_API22;
1848
+ const baseUrl = apiUrl || DEFAULT_API23;
1480
1849
  return {
1481
1850
  /** List quotes org-wide with optional filters and pagination. */
1482
1851
  async list(params = {}) {
@@ -1548,9 +1917,9 @@ var createQuotesClient = (apiKey, apiUrl) => {
1548
1917
  };
1549
1918
 
1550
1919
  // src/pipelines.ts
1551
- var DEFAULT_API23 = "https://be.graph8.com";
1920
+ var DEFAULT_API24 = "https://be.graph8.com";
1552
1921
  var createPipelinesClient = (apiKey, apiUrl) => {
1553
- const baseUrl = apiUrl || DEFAULT_API23;
1922
+ const baseUrl = apiUrl || DEFAULT_API24;
1554
1923
  return {
1555
1924
  /** List all stage-checklist pipelines with stages, evidence, scripts. */
1556
1925
  async list() {
@@ -1632,9 +2001,9 @@ var createPipelinesClient = (apiKey, apiUrl) => {
1632
2001
  };
1633
2002
 
1634
2003
  // src/workflows.ts
1635
- var DEFAULT_API24 = "https://be.graph8.com";
2004
+ var DEFAULT_API25 = "https://be.graph8.com";
1636
2005
  var createWorkflowsClient = (apiKey, apiUrl) => {
1637
- const baseUrl = apiUrl || DEFAULT_API24;
2006
+ const baseUrl = apiUrl || DEFAULT_API25;
1638
2007
  return {
1639
2008
  /** List workflows org-wide. */
1640
2009
  async list(params = {}) {
@@ -1750,9 +2119,9 @@ var createWorkflowsClient = (apiKey, apiUrl) => {
1750
2119
  };
1751
2120
 
1752
2121
  // src/skills.ts
1753
- var DEFAULT_API25 = "https://be.graph8.com";
2122
+ var DEFAULT_API26 = "https://be.graph8.com";
1754
2123
  var createSkillsClient = (apiKey, apiUrl) => {
1755
- const baseUrl = apiUrl || DEFAULT_API25;
2124
+ const baseUrl = apiUrl || DEFAULT_API26;
1756
2125
  return {
1757
2126
  /** List skills. */
1758
2127
  async list(params = {}) {
@@ -1839,9 +2208,9 @@ var createSkillsClient = (apiKey, apiUrl) => {
1839
2208
  };
1840
2209
 
1841
2210
  // src/intent.ts
1842
- var DEFAULT_API26 = "https://be.graph8.com";
2211
+ var DEFAULT_API27 = "https://be.graph8.com";
1843
2212
  var createIntentClient = (apiKey, apiUrl) => {
1844
- const baseUrl = apiUrl || DEFAULT_API26;
2213
+ const baseUrl = apiUrl || DEFAULT_API27;
1845
2214
  const get = (path) => request(baseUrl, `/api/v1${path}`, apiKey);
1846
2215
  const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
1847
2216
  const del = (path) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "DELETE" });
@@ -1916,9 +2285,9 @@ var createIntentClient = (apiKey, apiUrl) => {
1916
2285
  };
1917
2286
 
1918
2287
  // src/studio.ts
1919
- var DEFAULT_API27 = "https://be.graph8.com";
2288
+ var DEFAULT_API28 = "https://be.graph8.com";
1920
2289
  var createStudioClient = (apiKey, apiUrl) => {
1921
- const baseUrl = apiUrl || DEFAULT_API27;
2290
+ const baseUrl = apiUrl || DEFAULT_API28;
1922
2291
  const get = (path, params = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { query: params });
1923
2292
  const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
1924
2293
  const patch = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "PATCH", body });
@@ -1973,9 +2342,9 @@ var createStudioClient = (apiKey, apiUrl) => {
1973
2342
  };
1974
2343
 
1975
2344
  // src/meetings.ts
1976
- var DEFAULT_API28 = "https://be.graph8.com";
2345
+ var DEFAULT_API29 = "https://be.graph8.com";
1977
2346
  var createMeetingsClient = (apiKey, apiUrl) => {
1978
- const baseUrl = apiUrl || DEFAULT_API28;
2347
+ const baseUrl = apiUrl || DEFAULT_API29;
1979
2348
  return {
1980
2349
  /** List meetings with optional filters. Returns summary rows without transcript / analysis. */
1981
2350
  async list(params = {}) {
@@ -1990,9 +2359,9 @@ var createMeetingsClient = (apiKey, apiUrl) => {
1990
2359
  };
1991
2360
 
1992
2361
  // src/audiences.ts
1993
- var DEFAULT_API29 = "https://be.graph8.com";
2362
+ var DEFAULT_API30 = "https://be.graph8.com";
1994
2363
  var createAudiencesClient = (apiKey, apiUrl) => {
1995
- const baseUrl = apiUrl || DEFAULT_API29;
2364
+ const baseUrl = apiUrl || DEFAULT_API30;
1996
2365
  const base = "/api/v1/audience-syncs";
1997
2366
  return {
1998
2367
  /** List all audience syncs for the organization. */
@@ -2040,9 +2409,9 @@ var createAudiencesClient = (apiKey, apiUrl) => {
2040
2409
  };
2041
2410
 
2042
2411
  // src/search.ts
2043
- var DEFAULT_API30 = "https://be.graph8.com";
2412
+ var DEFAULT_API31 = "https://be.graph8.com";
2044
2413
  var createSearchClient = (apiKey, apiUrl) => {
2045
- const baseUrl = apiUrl || DEFAULT_API30;
2414
+ const baseUrl = apiUrl || DEFAULT_API31;
2046
2415
  const body = (p) => ({ filters: [], page: 1, limit: 25, ...p });
2047
2416
  return {
2048
2417
  /** Search open-data contacts by filter. */
@@ -2073,9 +2442,9 @@ var createSearchClient = (apiKey, apiUrl) => {
2073
2442
  };
2074
2443
 
2075
2444
  // src/agency.ts
2076
- var DEFAULT_API31 = "https://be.graph8.com";
2445
+ var DEFAULT_API32 = "https://be.graph8.com";
2077
2446
  var createAgencyClient = (apiKey, apiUrl) => {
2078
- const baseUrl = apiUrl || DEFAULT_API31;
2447
+ const baseUrl = apiUrl || DEFAULT_API32;
2079
2448
  return {
2080
2449
  /** Describe the agency credential: agency org + authorized client count. */
2081
2450
  async me() {
@@ -2090,9 +2459,9 @@ var createAgencyClient = (apiKey, apiUrl) => {
2090
2459
  };
2091
2460
 
2092
2461
  // src/marketplace.ts
2093
- var DEFAULT_API32 = "https://be.graph8.com";
2462
+ var DEFAULT_API33 = "https://be.graph8.com";
2094
2463
  var createMarketplaceClient = (apiKey, apiUrl) => {
2095
- const baseUrl = apiUrl || DEFAULT_API32;
2464
+ const baseUrl = apiUrl || DEFAULT_API33;
2096
2465
  const base = "/api/v1/marketplace";
2097
2466
  return {
2098
2467
  /** Your own marketplace SDR profile. */
@@ -2142,9 +2511,9 @@ var createMarketplaceClient = (apiKey, apiUrl) => {
2142
2511
  };
2143
2512
 
2144
2513
  // src/snippet.ts
2145
- var DEFAULT_API33 = "https://be.graph8.com";
2514
+ var DEFAULT_API34 = "https://be.graph8.com";
2146
2515
  var createSnippetClient = (apiKey, apiUrl) => {
2147
- const baseUrl = apiUrl || DEFAULT_API33;
2516
+ const baseUrl = apiUrl || DEFAULT_API34;
2148
2517
  return {
2149
2518
  /** Get your org's tracking snippet (write key + React/script-tag embeds + config). */
2150
2519
  async get() {
@@ -2156,7 +2525,7 @@ var createSnippetClient = (apiKey, apiUrl) => {
2156
2525
 
2157
2526
  // src/core.ts
2158
2527
  var DEFAULT_HOST = "https://t.graph8.com";
2159
- var DEFAULT_API34 = "https://be.graph8.com";
2528
+ var DEFAULT_API35 = "https://be.graph8.com";
2160
2529
  var G8 = class {
2161
2530
  constructor() {
2162
2531
  /** @internal */
@@ -2200,6 +2569,8 @@ var G8 = class {
2200
2569
  /** @internal */
2201
2570
  this._apps = null;
2202
2571
  /** @internal */
2572
+ this._appPlatform = null;
2573
+ /** @internal */
2203
2574
  this._objects = null;
2204
2575
  /** @internal */
2205
2576
  this._deals = null;
@@ -2243,7 +2614,7 @@ var G8 = class {
2243
2614
  debug: config.debug
2244
2615
  });
2245
2616
  }
2246
- const apiUrl = config.apiUrl || DEFAULT_API34;
2617
+ const apiUrl = config.apiUrl || DEFAULT_API35;
2247
2618
  const writeKey = config.writeKey || "";
2248
2619
  const apiKey = config.apiKey || "";
2249
2620
  if (writeKey) {
@@ -2267,6 +2638,7 @@ var G8 = class {
2267
2638
  this._tasks = createTasksClient(apiKey, apiUrl);
2268
2639
  this._fields = createFieldsClient(apiKey, apiUrl);
2269
2640
  this._apps = createAppsClient(apiKey, apiUrl);
2641
+ this._appPlatform = createAppPlatformClient(apiKey, apiUrl);
2270
2642
  this._objects = createObjectsClient(apiKey, apiUrl);
2271
2643
  this._deals = createDealsClient(apiKey, apiUrl);
2272
2644
  this._inbox = createInboxClient(apiKey, apiUrl);
@@ -2393,6 +2765,18 @@ var G8 = class {
2393
2765
  this._assertKey("apps");
2394
2766
  return this._apps;
2395
2767
  }
2768
+ /**
2769
+ * Ship a hosted app: bind a source, deploy, promote, attach a hostname, read
2770
+ * build logs (requires API key). PREVIEW.
2771
+ *
2772
+ * Separate from `apps` on purpose. `apps` is the app's IDENTITY -- create it,
2773
+ * see who installed it, what it cost. This is its LIFECYCLE, and the two have
2774
+ * different blast radii: a mistake here takes a customer's app down.
2775
+ */
2776
+ get appPlatform() {
2777
+ this._assertKey("appPlatform");
2778
+ return this._appPlatform;
2779
+ }
2396
2780
  /** Custom object types, their schema, and their records (requires API key). PREVIEW. */
2397
2781
  get objects() {
2398
2782
  this._assertKey("objects");
@@ -2649,9 +3033,12 @@ export {
2649
3033
  DEFAULT_APP_API,
2650
3034
  G8Error,
2651
3035
  KNOWN_WEBHOOK_EVENTS,
3036
+ MAX_TAIL_LINES,
3037
+ MIN_TAIL_LINES,
2652
3038
  WebhookSignatureError,
2653
3039
  backoffDelayMs,
2654
3040
  constructEvent,
3041
+ createAppPlatformClient,
2655
3042
  createAppRequester,
2656
3043
  createGraph8AppClient,
2657
3044
  createGraph8ServiceClient,