@indigoai-us/hq-cli 5.345.190 → 5.345.193
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/CHANGELOG.md +420 -0
- package/assets/bot-workers/setup/worker.yaml +91 -34
- package/dist/command-catalog.generated.d.ts +96 -19
- package/dist/command-catalog.generated.js +124 -21
- package/dist/commands/bot-jobs.d.ts +21 -18
- package/dist/commands/bot-jobs.js +127 -39
- package/dist/commands/bot.d.ts +7 -4
- package/dist/commands/bot.js +289 -140
- package/dist/commands/core-jobs-schedule.js +10 -0
- package/dist/commands/daemon.js +37 -0
- package/dist/commands/files.d.ts +41 -6
- package/dist/commands/files.js +108 -27
- package/dist/commands/pack-start-bot.d.ts +4 -6
- package/dist/commands/pack-start-bot.js +4 -8
- package/dist/commands/signals-run.d.ts +45 -0
- package/dist/commands/signals-run.js +175 -0
- package/dist/commands/signals.d.ts +1 -0
- package/dist/commands/signals.js +3 -0
- package/dist/commands/sources.d.ts +11 -0
- package/dist/commands/sources.js +137 -25
- package/dist/commands/staff/reset-test-account.d.ts +10 -0
- package/dist/commands/staff/reset-test-account.js +18 -2
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +31171 -52512
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/lib/bot/api.d.ts +3 -2
- package/dist/lib/bot/config.d.ts +2 -0
- package/dist/lib/bot/fleet-cron.d.ts +121 -0
- package/dist/lib/bot/fleet-cron.js +319 -0
- package/dist/lib/bot/fleet-local.d.ts +113 -2
- package/dist/lib/bot/fleet-local.js +597 -35
- package/dist/lib/bot/fleet-owner-companies.d.ts +12 -0
- package/dist/lib/bot/fleet-owner-companies.js +30 -0
- package/dist/lib/bot/fleet-watch.d.ts +25 -0
- package/dist/lib/bot/fleet-watch.js +51 -0
- package/dist/lib/bot/index.d.ts +1 -1
- package/dist/lib/bot/index.js +1 -1
- package/dist/lib/bot/job-run.d.ts +5 -4
- package/dist/lib/bot/job-run.js +5 -4
- package/dist/lib/bot/jobs/hot-signal-sync.d.ts +57 -3
- package/dist/lib/bot/jobs/hot-signal-sync.js +163 -4
- package/dist/lib/bot/local-jobs.d.ts +13 -2
- package/dist/lib/bot/local-jobs.js +17 -4
- package/dist/lib/bot/progress.d.ts +14 -0
- package/dist/lib/bot/progress.js +47 -1
- package/dist/lib/bot/run.d.ts +55 -2
- package/dist/lib/bot/run.js +192 -10
- package/dist/lib/bot/setup-tool-offer.d.ts +1 -0
- package/dist/lib/bot/setup-tool-offer.js +16 -0
- package/dist/lib/bot/signals-engine-flag.d.ts +18 -0
- package/dist/lib/bot/signals-engine-flag.js +30 -0
- package/dist/lib/daemon/catalog.d.ts +4 -0
- package/dist/lib/daemon/catalog.js +29 -9
- package/dist/lib/daemon/legacy.d.ts +6 -0
- package/dist/lib/daemon/legacy.js +16 -10
- package/dist/lib/daemon/run.d.ts +1 -0
- package/dist/lib/daemon/run.js +10 -0
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/lib/flag-registry.d.ts +13 -1
- package/dist/lib/flag-registry.js +46 -0
- package/dist/lib/hot-channels/adapters/attio.d.ts +75 -2
- package/dist/lib/hot-channels/adapters/attio.js +367 -29
- package/dist/lib/hot-channels/adapters/gmail.d.ts +14 -0
- package/dist/lib/hot-channels/adapters/gmail.js +59 -2
- package/dist/lib/hot-channels/adapters/linear.d.ts +24 -0
- package/dist/lib/hot-channels/adapters/linear.js +71 -1
- package/dist/lib/hot-channels/adapters/meetings.js +4 -1
- package/dist/lib/hot-channels/adapters/slack.js +7 -3
- package/dist/lib/hot-channels/alert.js +1 -1
- package/dist/lib/hot-channels/contract.d.ts +11 -0
- package/dist/lib/hot-channels/contract.js +1 -0
- package/dist/lib/hot-channels/cursors.js +1 -1
- package/dist/lib/hot-channels/landing.d.ts +6 -2
- package/dist/lib/hot-channels/landing.js +13 -6
- package/dist/lib/hot-channels/ledger.js +2 -0
- package/dist/lib/hot-channels/loop.js +18 -4
- package/dist/lib/hot-channels/registry.js +9 -1
- package/dist/lib/hot-channels/run.d.ts +18 -0
- package/dist/lib/hot-channels/run.js +15 -4
- package/dist/lib/hot-channels/signals-pass.d.ts +1 -0
- package/dist/lib/hot-channels/signals-pass.js +7 -5
- package/dist/lib/hot-channels/sync-lock.js +22 -6
- package/dist/lib/mesh/live/daemon/install.d.ts +22 -0
- package/dist/lib/mesh/live/daemon/install.js +117 -30
- package/dist/lib/signals/adapters-catalog.d.ts +77 -0
- package/dist/lib/signals/adapters-catalog.js +194 -0
- package/dist/lib/signals/engine.d.ts +196 -0
- package/dist/lib/signals/engine.js +495 -0
- package/dist/lib/signals/failure-alert.d.ts +89 -0
- package/dist/lib/signals/failure-alert.js +175 -0
- package/dist/lib/signals/local-date.d.ts +3 -0
- package/dist/lib/signals/local-date.js +6 -0
- package/dist/lib/signals/projection.d.ts +42 -0
- package/dist/lib/signals/projection.js +67 -0
- package/dist/lib/signals/reply.d.ts +112 -0
- package/dist/lib/signals/reply.js +368 -0
- package/dist/lib/signals/run-lock.d.ts +36 -0
- package/dist/lib/signals/run-lock.js +148 -0
- package/dist/lib/signals/run-record.d.ts +24 -0
- package/dist/lib/signals/run-record.js +82 -0
- package/dist/lib/signals/sanitize.d.ts +105 -0
- package/dist/lib/signals/sanitize.js +439 -0
- package/dist/lib/signals/settings.d.ts +10 -0
- package/dist/lib/signals/settings.js +48 -0
- package/dist/lib/signals/steps/adapters.d.ts +14 -0
- package/dist/lib/signals/steps/adapters.js +156 -0
- package/dist/lib/signals/steps/entity-similarity.d.ts +10 -0
- package/dist/lib/signals/steps/entity-similarity.js +47 -0
- package/dist/lib/signals/steps/extract.d.ts +113 -0
- package/dist/lib/signals/steps/extract.js +765 -0
- package/dist/lib/signals/steps/garden.d.ts +24 -0
- package/dist/lib/signals/steps/garden.js +250 -0
- package/dist/lib/signals/steps/types.d.ts +112 -0
- package/dist/lib/signals/steps/types.js +4 -0
- package/dist/lib/signals/steps/upload.d.ts +43 -0
- package/dist/lib/signals/steps/upload.js +324 -0
- package/dist/lib/signals/write-guard.d.ts +63 -0
- package/dist/lib/signals/write-guard.js +287 -0
- package/dist/utils/resident-package-preload.js +16 -0
- package/package.json +9 -9
- package/dist/lib/bot/fleet-default-flag.d.ts +0 -31
- package/dist/lib/bot/fleet-default-flag.js +0 -127
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* keep a short-lived, offline CLI alive until the client's network deadline.
|
|
7
7
|
*/
|
|
8
8
|
import { type WorkerOptions } from "node:worker_threads";
|
|
9
|
-
import { createFlagClient, type FlagClient, type FlagLookupOptions, type FlagSnapshot } from "@indigoai-us/hq-flags-client";
|
|
9
|
+
import { createFlagClient, type FlagClient, type FlagLookupOptions, type FlagResolution, type FlagSnapshot } from "@indigoai-us/hq-flags-client";
|
|
10
10
|
type FlagRegistrySentry = Pick<typeof import("@sentry/node"), "captureException" | "withScope">;
|
|
11
11
|
export { resolveProcessFlagCompanyContext } from "./process-flag-company-context.js";
|
|
12
12
|
export type { ProcessFlagCompanyContext } from "./process-flag-company-context.js";
|
|
@@ -66,6 +66,18 @@ export declare function refreshFlagRegistrySnapshot(timeoutMs?: number): Promise
|
|
|
66
66
|
export declare function resolveFlagGate(reader: FlagReader | null | undefined, flagKey: string, lookup: FlagLookupOptions, legacyFallback: () => boolean, env?: NodeJS.ProcessEnv): boolean;
|
|
67
67
|
/** Resolve one explicit company's flag without relying on process-wide binding. */
|
|
68
68
|
export declare function resolveCompanyFlagGate(companyUid: string, idToken: string, flagKey: string, lookup: FlagLookupOptions, legacyFallback: () => boolean, dependencies?: CompanyFlagGateDependencies): Promise<boolean>;
|
|
69
|
+
/**
|
|
70
|
+
* Read one explicit company's flag and say whether the registry answered.
|
|
71
|
+
*
|
|
72
|
+
* Returns the evaluator's resolution when the registry snapshot loaded (an
|
|
73
|
+
* absent row resolves to `lookup.fallback`, source "fallback"), a
|
|
74
|
+
* "local-override" resolution when the process sets one, and null when the
|
|
75
|
+
* registry could not be read: no company uid or token, a client error, a
|
|
76
|
+
* timeout, or a failed load. Callers that keep a last-known value (ingest
|
|
77
|
+
* kill switches) use the null to tell an unreadable registry from an answer.
|
|
78
|
+
* Bounded by the client's request timeout, like `resolveCompanyFlagGate`.
|
|
79
|
+
*/
|
|
80
|
+
export declare function readCompanyFlag(companyUid: string, idToken: string, flagKey: string, lookup: FlagLookupOptions, dependencies?: CompanyFlagGateDependencies): Promise<FlagResolution | null>;
|
|
69
81
|
/** Resolve a process gate against the shared snapshot reader, when configured. */
|
|
70
82
|
export declare function resolveProcessFlagGate(flagKey: string, lookup: FlagLookupOptions, legacyFallback: () => boolean, companyUid?: string, options?: {
|
|
71
83
|
acceptStaleSnapshot?: boolean;
|
|
@@ -354,6 +354,52 @@ export async function resolveCompanyFlagGate(companyUid, idToken, flagKey, looku
|
|
|
354
354
|
client?.close();
|
|
355
355
|
}
|
|
356
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* Read one explicit company's flag and say whether the registry answered.
|
|
359
|
+
*
|
|
360
|
+
* Returns the evaluator's resolution when the registry snapshot loaded (an
|
|
361
|
+
* absent row resolves to `lookup.fallback`, source "fallback"), a
|
|
362
|
+
* "local-override" resolution when the process sets one, and null when the
|
|
363
|
+
* registry could not be read: no company uid or token, a client error, a
|
|
364
|
+
* timeout, or a failed load. Callers that keep a last-known value (ingest
|
|
365
|
+
* kill switches) use the null to tell an unreadable registry from an answer.
|
|
366
|
+
* Bounded by the client's request timeout, like `resolveCompanyFlagGate`.
|
|
367
|
+
*/
|
|
368
|
+
export async function readCompanyFlag(companyUid, idToken, flagKey, lookup, dependencies = {}) {
|
|
369
|
+
const localOverride = processLocalOverride(flagKey);
|
|
370
|
+
if (localOverride !== null)
|
|
371
|
+
return { value: localOverride, source: "local-override" };
|
|
372
|
+
const targetCompanyUid = normalizedCompanyUid(companyUid);
|
|
373
|
+
if (!targetCompanyUid || idToken.trim() === "")
|
|
374
|
+
return null;
|
|
375
|
+
let client;
|
|
376
|
+
try {
|
|
377
|
+
client = (dependencies.createClient ?? createFlagClient)({
|
|
378
|
+
endpoint: resolveFlagRegistryEndpoint(dependencies.endpoint, process.env),
|
|
379
|
+
getToken: () => idToken,
|
|
380
|
+
companyUid: targetCompanyUid,
|
|
381
|
+
refreshIntervalMs: 0,
|
|
382
|
+
requestTimeoutMs: dependencies.requestTimeoutMs ?? 1_200,
|
|
383
|
+
onError: (error) => {
|
|
384
|
+
const errorClass = error instanceof Error ? error.name : "unknown";
|
|
385
|
+
console.error(`hq: Could not read a company flag (${errorClass}).`);
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
await client.ready();
|
|
389
|
+
// ready() resolves after a failed load too; no snapshot means no answer.
|
|
390
|
+
if (client.snapshot() === null)
|
|
391
|
+
return null;
|
|
392
|
+
return client.explain(flagKey, lookup);
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
const errorClass = error instanceof Error ? error.name : "unknown";
|
|
396
|
+
console.error(`hq: Could not read a company flag (${errorClass}).`);
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
finally {
|
|
400
|
+
client?.close();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
357
403
|
/** Resolve a process gate against the shared snapshot reader, when configured. */
|
|
358
404
|
export function resolveProcessFlagGate(flagKey, lookup, legacyFallback, companyUid, options = {}) {
|
|
359
405
|
const defaultOnKillSwitch = options.killSwitchWithoutCompany === true;
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* The Attio webhook receiver in hq-pro-agents
|
|
5
5
|
* (`src/sources/inbound/attio-events.ts`) is the push half: it lands one
|
|
6
6
|
* document per delivery in the company vault under `sources/attio/`, with
|
|
7
|
-
* `event_key: attio:{
|
|
8
|
-
*
|
|
7
|
+
* `event_key: attio:{deliveryHash}` in the frontmatter, where deliveryHash is
|
|
8
|
+
* `sha256hex(Idempotency-Key + "\n" + rawBody)` (the raw key is kept in a
|
|
9
|
+
* separate `idempotency_key` field), and the webhook payload in the
|
|
10
|
+
* `.raw.json` sidecar. This adapter is the drain half, a poll
|
|
9
11
|
* adapter over that folder, the same shape as Slack (US-006). The cursor is
|
|
10
12
|
* the newest `ingested_at` it has read.
|
|
11
13
|
*
|
|
@@ -31,6 +33,50 @@
|
|
|
31
33
|
* `payload_ref` names the landed source document. No payload is copied: the
|
|
32
34
|
* `.raw.json` sidecar holds the source frontmatter and why the delivery
|
|
33
35
|
* matched.
|
|
36
|
+
*
|
|
37
|
+
* US-010 adds a gateway pull as the catch-up path alongside the drain, for
|
|
38
|
+
* changes whose webhook never landed. Once the drain has no more pages, each
|
|
39
|
+
* fetch asks the gateway for records (`list-records`, one call per object in
|
|
40
|
+
* `pullObjects`, filtered `created_at > watermark`, sorted ascending, limit
|
|
41
|
+
* 50) and notes (`search-notes-by-metadata` with `created_at_gt`) newer than
|
|
42
|
+
* that source's watermark. A pulled item is kept on the same rule as a
|
|
43
|
+
* delivery: the person created it or owns its record. The Attio gateway has
|
|
44
|
+
* no updated-at filter on records, so record updates still come from the
|
|
45
|
+
* webhook drain; the pull catches records and notes that were created.
|
|
46
|
+
*
|
|
47
|
+
* Event keys follow the US-008 shape `attio:{recordId}:{eventId}`, built from
|
|
48
|
+
* Attio ids both paths have, so a create the webhook delivered and the pull
|
|
49
|
+
* found lands once:
|
|
50
|
+
* - a create (a delivery holding one `record.created` or `note.created`
|
|
51
|
+
* event, or a pulled record or note) is `attio:{record_id}:record.created`
|
|
52
|
+
* or `attio:{note_id}:note.created`;
|
|
53
|
+
* - every other delivery is `attio:{subjectId}:{deliveryHash}`, where the
|
|
54
|
+
* subject is the note, comment, record or entry the first event names, so
|
|
55
|
+
* two updates to one record stay two items.
|
|
56
|
+
*
|
|
57
|
+
* The cursor is JSON `{ drain, pull }`: `drain` is the newest `ingested_at`
|
|
58
|
+
* read, and `pull` maps `records:{object}` and `notes` to the newest
|
|
59
|
+
* `created_at` read. A plain ISO string from before US-010 reads as `drain`.
|
|
60
|
+
*
|
|
61
|
+
* Upgrading from the drain before US-010 (re-review C): that drain keyed every
|
|
62
|
+
* delivery `attio:{deliveryHash}:{event_type}`, and a plain ISO cursor gives
|
|
63
|
+
* the pull no watermark, so the first pull reads the whole catch-up window.
|
|
64
|
+
* Landing dedupes on the event key alone (the landed document's path), so
|
|
65
|
+
* nothing the old drain landed may come back under a new key:
|
|
66
|
+
* - the drain keeps the old key for a delivery whose document under the old
|
|
67
|
+
* key is already landed (the deliveries at the old cursor are re-read);
|
|
68
|
+
* - the pull gives a create the old key of the landed delivery that carried
|
|
69
|
+
* it, so landing reports a duplicate.
|
|
70
|
+
* A create the old drain never landed (its webhook was lost, or it is newer
|
|
71
|
+
* than the old cursor) has no document under an old key and lands under the
|
|
72
|
+
* new one. The pull watermark is not seeded from the old cursor, so those
|
|
73
|
+
* lost creates are not skipped.
|
|
74
|
+
*
|
|
75
|
+
* Rate limits: every gateway call retries a 429 with backoff (Retry-After
|
|
76
|
+
* when Attio sends it), at most ATTIO_MAX_RETRIES times, and one fetch makes
|
|
77
|
+
* at most ATTIO_MAX_REQUESTS_PER_FETCH calls. A persistent 429 or the cap
|
|
78
|
+
* throws AttioRateLimitedError before a cursor is returned, so the watermark
|
|
79
|
+
* stays where it was.
|
|
34
80
|
*/
|
|
35
81
|
import { type PollHotChannelAdapter } from "../contract.js";
|
|
36
82
|
export declare const ATTIO_ADAPTER_ID = "attio";
|
|
@@ -42,6 +88,15 @@ export declare const ATTIO_COMMENT_EVENT = "attio.comment";
|
|
|
42
88
|
export declare const ATTIO_NOTE_EVENT = "attio.note";
|
|
43
89
|
export declare const ATTIO_LIST_MEMBERS_TOOL = "list-workspace-members";
|
|
44
90
|
export declare const ATTIO_GET_RECORDS_TOOL = "get-records-by-ids";
|
|
91
|
+
export declare const ATTIO_LIST_RECORDS_TOOL = "list-records";
|
|
92
|
+
export declare const ATTIO_SEARCH_NOTES_TOOL = "search-notes-by-metadata";
|
|
93
|
+
/** Records per `list-records` call; the Attio policy caps it at 50. */
|
|
94
|
+
export declare const ATTIO_PULL_LIMIT = 50;
|
|
95
|
+
/** Objects the catch-up pull lists by default. */
|
|
96
|
+
export declare const ATTIO_DEFAULT_PULL_OBJECTS: readonly string[];
|
|
97
|
+
export declare const ATTIO_MAX_RETRIES = 3;
|
|
98
|
+
/** Gateway calls one fetch may make, retries included. */
|
|
99
|
+
export declare const ATTIO_MAX_REQUESTS_PER_FETCH = 200;
|
|
45
100
|
/**
|
|
46
101
|
* Suggestion rule data: Attio is suggested when the person owns a record with
|
|
47
102
|
* activity in the last 14 days. The contract's `owned-by-me` rule has no
|
|
@@ -62,6 +117,24 @@ export interface AttioAdapterOptions {
|
|
|
62
117
|
memberIds?: readonly string[];
|
|
63
118
|
/** Deliveries newer than the cursor per page. Default 100. */
|
|
64
119
|
pageSize?: number;
|
|
120
|
+
/** Objects the catch-up pull lists. Default companies, people, deals. Empty turns the record pull off. */
|
|
121
|
+
pullObjects?: readonly string[];
|
|
122
|
+
/** Waits between rate-limit retries. Tests pass a fake. */
|
|
123
|
+
sleep?: (ms: number) => Promise<void>;
|
|
124
|
+
}
|
|
125
|
+
/** Attio kept answering 429 after every retry, or the run hit its request cap; the cursor stays put. */
|
|
126
|
+
export declare class AttioRateLimitedError extends Error {
|
|
127
|
+
readonly retryAfterMs: number | null;
|
|
128
|
+
readonly code = "rate_limited";
|
|
129
|
+
readonly status = 429;
|
|
130
|
+
constructor(retryAfterMs: number | null);
|
|
131
|
+
}
|
|
132
|
+
/** The adapter's cursor: see the file comment. */
|
|
133
|
+
export interface AttioCursor {
|
|
134
|
+
drain: string | null;
|
|
135
|
+
pull: Record<string, string>;
|
|
65
136
|
}
|
|
137
|
+
/** Parse a stored cursor. A plain ISO string (before US-010) is the drain cursor. */
|
|
138
|
+
export declare function parseAttioCursor(raw: string | null): AttioCursor;
|
|
66
139
|
export declare function createAttioAdapter(options: AttioAdapterOptions): PollHotChannelAdapter;
|
|
67
140
|
//# sourceMappingURL=attio.d.ts.map
|