@harny/sdk 0.0.1-alpha.1 → 0.1.1

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.
Files changed (84) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +56 -42
  3. package/dist/cjs/agent/adapters.d.ts +167 -0
  4. package/dist/cjs/agent/adapters.js +557 -0
  5. package/dist/cjs/agent/adapters.js.map +1 -0
  6. package/dist/cjs/agent/hooks.d.ts +52 -0
  7. package/dist/cjs/agent/hooks.js +41 -0
  8. package/dist/cjs/agent/hooks.js.map +1 -0
  9. package/dist/cjs/agent/index.d.ts +34 -0
  10. package/dist/cjs/agent/index.js +62 -0
  11. package/dist/cjs/agent/index.js.map +1 -0
  12. package/dist/cjs/agent/loop.d.ts +401 -0
  13. package/dist/cjs/agent/loop.js +1252 -0
  14. package/dist/cjs/agent/loop.js.map +1 -0
  15. package/dist/cjs/agent/roster.d.ts +62 -0
  16. package/dist/cjs/agent/roster.js +149 -0
  17. package/dist/cjs/agent/roster.js.map +1 -0
  18. package/dist/cjs/agent/session.d.ts +106 -0
  19. package/dist/cjs/agent/session.js +261 -0
  20. package/dist/cjs/agent/session.js.map +1 -0
  21. package/dist/cjs/agent/spend.d.ts +39 -0
  22. package/dist/cjs/agent/spend.js +70 -0
  23. package/dist/cjs/agent/spend.js.map +1 -0
  24. package/dist/cjs/agent/tools.d.ts +83 -0
  25. package/dist/cjs/agent/tools.js +212 -0
  26. package/dist/cjs/agent/tools.js.map +1 -0
  27. package/dist/cjs/agent/tracing.d.ts +72 -0
  28. package/dist/cjs/agent/tracing.js +128 -0
  29. package/dist/cjs/agent/tracing.js.map +1 -0
  30. package/dist/cjs/agent/util.d.ts +60 -0
  31. package/dist/cjs/agent/util.js +188 -0
  32. package/dist/cjs/agent/util.js.map +1 -0
  33. package/dist/cjs/conflictQuestion.d.ts +137 -0
  34. package/dist/cjs/conflictQuestion.js +356 -0
  35. package/dist/cjs/conflictQuestion.js.map +1 -0
  36. package/dist/cjs/index.d.ts +950 -0
  37. package/dist/cjs/index.js +1124 -0
  38. package/dist/cjs/index.js.map +1 -0
  39. package/dist/cjs/memoryV1.d.ts +121 -0
  40. package/dist/cjs/memoryV1.js +132 -0
  41. package/dist/cjs/memoryV1.js.map +1 -0
  42. package/dist/cjs/package.json +1 -0
  43. package/dist/esm/agent/adapters.d.ts +167 -0
  44. package/dist/esm/agent/adapters.js +543 -0
  45. package/dist/esm/agent/adapters.js.map +1 -0
  46. package/dist/esm/agent/hooks.d.ts +52 -0
  47. package/dist/esm/agent/hooks.js +36 -0
  48. package/dist/esm/agent/hooks.js.map +1 -0
  49. package/dist/esm/agent/index.d.ts +34 -0
  50. package/dist/esm/agent/index.js +28 -0
  51. package/dist/esm/agent/index.js.map +1 -0
  52. package/dist/esm/agent/loop.d.ts +401 -0
  53. package/dist/esm/agent/loop.js +1243 -0
  54. package/dist/esm/agent/loop.js.map +1 -0
  55. package/dist/esm/agent/roster.d.ts +62 -0
  56. package/dist/esm/agent/roster.js +143 -0
  57. package/dist/esm/agent/roster.js.map +1 -0
  58. package/dist/esm/agent/session.d.ts +106 -0
  59. package/dist/esm/agent/session.js +221 -0
  60. package/dist/esm/agent/session.js.map +1 -0
  61. package/dist/esm/agent/spend.d.ts +39 -0
  62. package/dist/esm/agent/spend.js +65 -0
  63. package/dist/esm/agent/spend.js.map +1 -0
  64. package/dist/esm/agent/tools.d.ts +83 -0
  65. package/dist/esm/agent/tools.js +205 -0
  66. package/dist/esm/agent/tools.js.map +1 -0
  67. package/dist/esm/agent/tracing.d.ts +72 -0
  68. package/dist/esm/agent/tracing.js +119 -0
  69. package/dist/esm/agent/tracing.js.map +1 -0
  70. package/dist/esm/agent/util.d.ts +60 -0
  71. package/dist/esm/agent/util.js +168 -0
  72. package/dist/esm/agent/util.js.map +1 -0
  73. package/dist/esm/conflictQuestion.d.ts +137 -0
  74. package/dist/esm/conflictQuestion.js +346 -0
  75. package/dist/esm/conflictQuestion.js.map +1 -0
  76. package/dist/esm/index.d.ts +950 -0
  77. package/dist/esm/index.js +1072 -0
  78. package/dist/esm/index.js.map +1 -0
  79. package/dist/esm/memoryV1.d.ts +121 -0
  80. package/dist/esm/memoryV1.js +124 -0
  81. package/dist/esm/memoryV1.js.map +1 -0
  82. package/dist/esm/package.json +1 -0
  83. package/package.json +41 -15
  84. package/index.js +0 -270
@@ -0,0 +1,950 @@
1
+ import type { ConflictLike, ConflictQuestion } from "./conflictQuestion.js";
2
+ import type { DataPoint, IngestDataPointOptions, MemoryDeletion, MemoryIngestionStatus, MemoryIngestReceipt, MemoryRecall, MemoryUsage, RecallOptions, WaitOptions } from "./memoryV1.js";
3
+ export declare class HarnyError extends Error {
4
+ readonly statusCode: number;
5
+ readonly errorCode: string;
6
+ readonly recoveryHint: string;
7
+ readonly docsUrl: string;
8
+ readonly retryAfterS: number | null;
9
+ /** Field-level reasons when the API rejected the request's fields: where, why, and the kind. */
10
+ readonly detail?: ReadonlyArray<{
11
+ loc: string[];
12
+ msg: string;
13
+ type?: string;
14
+ }> | undefined;
15
+ constructor(statusCode: number, errorCode: string, message: string, recoveryHint: string, docsUrl: string, retryAfterS: number | null,
16
+ /** Field-level reasons when the API rejected the request's fields: where, why, and the kind. */
17
+ detail?: ReadonlyArray<{
18
+ loc: string[];
19
+ msg: string;
20
+ type?: string;
21
+ }> | undefined);
22
+ }
23
+ /**
24
+ * Thrown for local state problems that never reach the network — calling a
25
+ * user-scoped method before `provisionUser`, or provisioning twice on one
26
+ * client. Mirrors the Python SDK's `HarnyStateError`.
27
+ */
28
+ export declare class HarnyStateError extends Error {
29
+ constructor(message: string);
30
+ }
31
+ /** A key was given that is not text (a number, an object, ...). */
32
+ export declare class HarnyInvalidKeyError extends HarnyStateError {
33
+ constructor(message: string);
34
+ }
35
+ /** No API key was given and none was found in `HARNY_API_KEY` (or its alias `HARNY_APP_KEY`). */
36
+ export declare class HarnyMissingKeyError extends HarnyStateError {
37
+ constructor(message: string);
38
+ }
39
+ /** Providers the platform can connect. Mirrors the API's ContextSourceProvider. */
40
+ export type ContextSourceProvider = "gmail" | "calendar" | "drive" | "notion" | "slack" | "email_bridge";
41
+ export type SubsystemStatus = "ready" | "degraded" | "failing";
42
+ export interface ContextSourceFreshness {
43
+ provider: string;
44
+ last_refreshed_at?: string | null;
45
+ auth_state: "ok" | "expired" | "error" | "disconnected";
46
+ last_sync_status?: string | null;
47
+ last_error?: string | null;
48
+ }
49
+ export interface DiagnoseResponse {
50
+ oauth_status: SubsystemStatus;
51
+ vault_status: SubsystemStatus;
52
+ assembly_status: SubsystemStatus;
53
+ overall: SubsystemStatus;
54
+ /** Empty when the request carried no user context. */
55
+ context_sources: ContextSourceFreshness[];
56
+ }
57
+ export type IdentifierType = "email" | "app_id" | "device_id";
58
+ /**
59
+ * Trust levels the API accepts when CREATING a user. Narrower than the trust
60
+ * levels it returns: `platform_verified` is server-assigned only and is
61
+ * rejected on the request.
62
+ */
63
+ export type IngressEmailTrustLevel = "unverified" | "app_asserted";
64
+ /** Trust levels the API may report back on a user record. */
65
+ export type EmailTrustLevel = IngressEmailTrustLevel | "platform_verified";
66
+ export interface User {
67
+ id: string;
68
+ app_id: string;
69
+ identifier: string;
70
+ identifier_type: IdentifierType;
71
+ email: string | null;
72
+ email_trust_level: EmailTrustLevel;
73
+ identity_provider: string | null;
74
+ created_at: string;
75
+ vault_initialized: boolean;
76
+ }
77
+ /** The mark a host may put on a person at registration. */
78
+ export type UserRole = "staff" | "test";
79
+ /** How a host says a card was answered when it confirms. */
80
+ export type ConfirmAnsweredBy = "tap" | "timeout" | "dismissed" | "server";
81
+ /**
82
+ * What a person may correct on the card before approving: the content of the action. `attendees` is the guest list of the same guests or fewer; the API refuses a guest who
83
+ * was not on the card.
84
+ */
85
+ export interface ConfirmEdit {
86
+ title?: string;
87
+ start?: string;
88
+ end?: string;
89
+ duration_minutes?: number;
90
+ time_zone?: string;
91
+ description?: string;
92
+ location?: string;
93
+ attendees?: string[];
94
+ }
95
+ export interface ProvisionUserOptions {
96
+ identifier_type?: IdentifierType;
97
+ email_trust_level?: IngressEmailTrustLevel;
98
+ /**
99
+ * Mark the person: `staff` (works for the business) or `test` (an account made to try the app). Leave it out for an
100
+ * ordinary customer. A `test` account is not counted as a customer when Harny reads how your users answer. Sent again
101
+ * for a person who already exists it updates the mark; leaving it out never removes one; `null` removes it.
102
+ */
103
+ role?: UserRole | null;
104
+ }
105
+ export interface ProvisionUserResponse {
106
+ user: User;
107
+ /**
108
+ * Always present on the wire, but `null` for a returning user the API
109
+ * did not mint a fresh key for. Reuse the key you stored the first time.
110
+ */
111
+ api_key_id: string | null;
112
+ api_key: string | null;
113
+ api_key_display: string | null;
114
+ trust_upgraded: boolean;
115
+ message: string;
116
+ delivery_ack_token?: string | null;
117
+ delivery_reread_expires_at?: string | null;
118
+ }
119
+ export type IngestStatus = "ingested" | "deduped" | "queued";
120
+ export type IngestQueuedReason = "extraction_unavailable" | "memory_service_degraded" | "circuit_open" | "empty_extraction_suspected";
121
+ export interface IngestResponse {
122
+ status: IngestStatus;
123
+ message: string;
124
+ resource_uri: string;
125
+ /** Present only when `status` is `queued`: why the content was accepted for retry. */
126
+ queued_reason?: IngestQueuedReason | null;
127
+ /** Present only when `status` is `deduped`. */
128
+ existing_memory_ids?: string[] | null;
129
+ }
130
+ export interface ContextBlockPolicy {
131
+ cross_app: boolean;
132
+ sharing_tier: "open" | "sensitive" | "restricted";
133
+ consent_basis: "self_app_scope" | "vault_link_category_policy";
134
+ origin_app_id?: string | null;
135
+ }
136
+ export interface TemporalAnchor {
137
+ event_time?: string | null;
138
+ /** Tolerant string: the server may add categories without an SDK bump. */
139
+ recency?: string | null;
140
+ temporal_relevance?: string | null;
141
+ }
142
+ export type ContextBlockSourceType = "vault" | "context_source" | "linked" | "tool" | "memory";
143
+ export interface ContextBlock {
144
+ source_type: ContextBlockSourceType;
145
+ score: number;
146
+ content: string;
147
+ token_count: number;
148
+ policy: ContextBlockPolicy;
149
+ metadata: Record<string, unknown>;
150
+ last_refreshed_at?: string | null;
151
+ temporal?: TemporalAnchor | null;
152
+ /** Tolerant strings — the API's registries may gain values mid-deploy. */
153
+ basis?: string | null;
154
+ freshness?: string | null;
155
+ provenance_type?: string | null;
156
+ occurred_at?: string | null;
157
+ last_retrieved_at?: string | null;
158
+ /** Present only on deployments with graduated confidence enabled. */
159
+ confidence_tier?: string | null;
160
+ uncertainty_note?: string | null;
161
+ }
162
+ export interface TemporalScope {
163
+ start?: string | null;
164
+ end?: string | null;
165
+ label: string;
166
+ }
167
+ export interface QueryInterpretation {
168
+ intent: string;
169
+ temporal_scope?: TemporalScope | null;
170
+ entities: Array<Record<string, string>>;
171
+ source_hints: string[];
172
+ reformulated_query?: string | null;
173
+ }
174
+ /**
175
+ * The one mechanically-earned issue attached to a thin or empty result.
176
+ * `null` on a healthy response.
177
+ */
178
+ export interface Issue {
179
+ reason: string;
180
+ scope?: string | null;
181
+ plain: string;
182
+ next: string;
183
+ fix_url: string;
184
+ }
185
+ export interface EmailCaptureHealth {
186
+ state: string;
187
+ status_message: string;
188
+ last_updated_at?: string | null;
189
+ action?: string | null;
190
+ }
191
+ export type ContextAssemblySource = "vault" | "context_source" | "memory" | "linked" | "tool";
192
+ /**
193
+ * Two things one user said that cannot both be true. Neither statement replaces
194
+ * the other: nothing here says which one is right.
195
+ */
196
+ export interface ContextConflict {
197
+ statement_1: string;
198
+ said_1: string;
199
+ event_date_1?: string | null;
200
+ statement_2: string;
201
+ said_2: string;
202
+ record_id_1: string;
203
+ record_id_2: string;
204
+ /** True when the user said both in one conversation: do not ask about it there. */
205
+ same_conversation: boolean;
206
+ speaker: string;
207
+ /** Names this conflict: the same in every response, whichever statement is listed first. Absent from older servers. */
208
+ conflict_key?: string | null;
209
+ /** True when your app has already reported asking the user about this conflict (`markConflictAsked`). */
210
+ asked?: boolean;
211
+ }
212
+ /** Harny's answer to `markConflictAsked`. */
213
+ export interface ConflictAsked {
214
+ conflict_key: string;
215
+ /** True the first time you report this conflict as asked, false on every repeat. */
216
+ first_time: boolean;
217
+ }
218
+ /** Harny's answer to `answerConflict`. */
219
+ export interface ConflictAnswered {
220
+ conflict_key: string;
221
+ /** True once the answer is saved; the conflict is no longer returned. */
222
+ answered: boolean;
223
+ /** How the saving went: `ingested`, `deduped` or `queued`. */
224
+ status: string;
225
+ message: string;
226
+ /** Identifies the saved answer. */
227
+ resource_uri: string;
228
+ }
229
+ export interface ContextResult {
230
+ blocks: ContextBlock[];
231
+ total_tokens: number;
232
+ budget_used: number;
233
+ budget_remaining: number;
234
+ query: string;
235
+ assembly_profile: string;
236
+ sources_queried: ContextAssemblySource[];
237
+ /** A source here FAILED. Never read an empty result as "the user has no data". */
238
+ degraded_sources: ContextAssemblySource[];
239
+ source_failures?: Record<string, string> | null;
240
+ thread_id?: string | null;
241
+ query_interpretation?: QueryInterpretation | null;
242
+ /** Matches the `X-Request-Id` response header. Quote it in support requests. */
243
+ request_id: string;
244
+ issue?: Issue | null;
245
+ capture_health?: EmailCaptureHealth | null;
246
+ /**
247
+ * Two things the user said that cannot both be true, for your own interface
248
+ * to show. Absent unless there is at least one.
249
+ */
250
+ conflicts?: ContextConflict[] | null;
251
+ /**
252
+ * How to word the question when you ask about a conflict: your app's "When notes conflict" setting (simple,
253
+ * precise or handoff). Absent with no conflict, and absent while Harny has the question switched off, so no
254
+ * mode with a conflict in hand means do not ask. Pass it to `decideConflictQuestion({ mode })`.
255
+ */
256
+ conflict_question_mode?: string | null;
257
+ }
258
+ export type AssemblySourceFilter = "vault" | "context_source" | "memory" | "linked" | "tool" | "permission";
259
+ export interface AssembleOptions {
260
+ token_budget?: number;
261
+ assembly_profile?: string;
262
+ thread_id?: string | null;
263
+ include_tools?: boolean;
264
+ source_filter?: AssemblySourceFilter[] | null;
265
+ min_relevance_score?: number | null;
266
+ /** Last N conversation turns (max 5) for context-adaptive retrieval. */
267
+ conversation_context?: string[] | null;
268
+ }
269
+ /**
270
+ * Who the assembly is for, sent as a header (never in the request body):
271
+ * `user` assembles for that end user with the app key (Harny id or your
272
+ * identifier) — for a backend agent woken by a webhook. Omit it on a client
273
+ * that provisioned a user.
274
+ */
275
+ export interface AssembleTarget {
276
+ user?: string;
277
+ /** W3C trace context header, so Harny's work joins your trace. */
278
+ traceparent?: string;
279
+ }
280
+ /** List price per million tokens, from a versioned rate table. */
281
+ export interface RosterPrice {
282
+ priced: boolean;
283
+ input_per_mtok?: number | null;
284
+ output_per_mtok?: number | null;
285
+ cached_input_per_mtok?: number | null;
286
+ has_peak_window?: boolean;
287
+ rate_version: string;
288
+ }
289
+ export interface RosterApi {
290
+ style: "chat_completions" | "messages" | "generate_content";
291
+ base_url: string;
292
+ auth: "bearer" | "x-api-key" | "x-goog-api-key";
293
+ headers?: Record<string, string>;
294
+ max_tokens_param: string;
295
+ /** Added to every request body (for example a pin to one host); never replaces a field the agent sets. */
296
+ extra_body?: Record<string, unknown>;
297
+ }
298
+ /** The one host that serves an entry on a provider that routes to many hosts. */
299
+ export interface RosterHost {
300
+ id: string;
301
+ label: string;
302
+ headquarters?: string | null;
303
+ }
304
+ export interface RosterCapabilities {
305
+ tool_calls?: boolean;
306
+ mcp_supported?: boolean;
307
+ /** The model thinks before it answers (never switched off); the thinking counts against the answer limit. */
308
+ thinking_always_on?: boolean;
309
+ /** Set with `thinking_always_on`: the answer limit (max output tokens) to give the model at least. */
310
+ answer_room_tokens?: number | null;
311
+ }
312
+ export interface RosterEntry {
313
+ id: string;
314
+ provider: string;
315
+ provider_label: string;
316
+ model: string;
317
+ api: RosterApi;
318
+ capabilities: RosterCapabilities;
319
+ key_env: string[];
320
+ region: string;
321
+ price: RosterPrice;
322
+ notes?: string | null;
323
+ host?: RosterHost | null;
324
+ /** Informational only: never used to pick or refuse an entry. */
325
+ data_terms?: string | null;
326
+ }
327
+ export interface RosterPreset {
328
+ name: "cost_first" | "quality_first" | "regulated";
329
+ description: string;
330
+ entries: RosterEntry[];
331
+ }
332
+ /**
333
+ * The platform model roster: for each preset, provider/model entries an agent
334
+ * resolves with the business's own key (first entry whose provider it holds a
335
+ * key for). Reading it runs no model.
336
+ */
337
+ export interface ModelRoster {
338
+ roster_version: string;
339
+ updated_at: string;
340
+ rate_version: string;
341
+ presets: Record<string, RosterPreset>;
342
+ }
343
+ export interface SetupBundleOptions {
344
+ /** `common:<path id>` or `developer`. */
345
+ shape: string;
346
+ preset?: "cost_first" | "quality_first" | "regulated";
347
+ deployTarget?: "cloud_run" | "render" | "docker" | "unspecified";
348
+ surface?: "chat_page" | "email" | "webhook_only";
349
+ sources?: string[];
350
+ actions?: string[];
351
+ emailArrivalTrigger?: boolean;
352
+ description?: string;
353
+ }
354
+ /** What names a conflict: a `ContextConflict`, an object with both note ids, or the decision `decideConflictQuestion` returned. */
355
+ export type ConflictRefInput = ConflictLike | ConflictQuestion;
356
+ export interface ConnectResponse {
357
+ provider: ContextSourceProvider;
358
+ authorization_url: string;
359
+ state: string;
360
+ expires_in_seconds: number;
361
+ }
362
+ export interface SourceConnection {
363
+ connection_id: string;
364
+ provider: ContextSourceProvider;
365
+ status: "connected" | "disconnected" | "error";
366
+ connected_at: string;
367
+ last_synced_at?: string | null;
368
+ last_sync_status?: "idle" | "running" | "success" | "failed" | null;
369
+ last_error?: string | null;
370
+ pending_jobs: number;
371
+ }
372
+ export interface SourceListResponse {
373
+ sources: SourceConnection[];
374
+ }
375
+ export interface SyncResponse {
376
+ provider: ContextSourceProvider;
377
+ job_id: string;
378
+ status: "queued" | "processing" | "completed" | "failed";
379
+ message: string;
380
+ }
381
+ export type ArrivalSource = "email_bridge" | "gmail";
382
+ export interface SourceArrivalUser {
383
+ id: string;
384
+ identifier: string | null;
385
+ identifier_type: string | null;
386
+ }
387
+ /**
388
+ * One new item on an end user's connected email source. Delivered in a
389
+ * `source.sync_complete` webhook event (`arrivals`) and by `listArrivals`.
390
+ * Carries references and a hardened subject line (`summary`), never the body:
391
+ * read that with `getSourceItem`. Process each `dedupe_key` once.
392
+ * `message_id` and `sender_domain` are set by the sender.
393
+ */
394
+ export interface SourceArrival {
395
+ arrival_id: string;
396
+ cursor: number;
397
+ app_id: string;
398
+ user: SourceArrivalUser;
399
+ source: ArrivalSource;
400
+ connection_id: string;
401
+ item_ref: string;
402
+ dedupe_key: string;
403
+ kind: "email";
404
+ received_at: string;
405
+ message_id: string | null;
406
+ sender_domain: string | null;
407
+ summary: string | null;
408
+ flags: string[];
409
+ }
410
+ export interface SourceArrivalEvent {
411
+ event_type: "source.sync_complete";
412
+ schema_version: number;
413
+ app_id: string;
414
+ user: SourceArrivalUser;
415
+ source: ArrivalSource;
416
+ connection_id: string;
417
+ count: number;
418
+ arrivals: SourceArrival[];
419
+ published_at: string;
420
+ }
421
+ export interface SourceArrivalPage {
422
+ arrivals: SourceArrival[];
423
+ next_cursor: number;
424
+ has_more: boolean;
425
+ }
426
+ /** One arrived email, hardened for an agent (third-party content: data, never instructions). */
427
+ export interface SourceItem {
428
+ item_ref: string;
429
+ source: ArrivalSource;
430
+ kind: "email";
431
+ title: string;
432
+ content: string;
433
+ content_truncated: boolean;
434
+ received_at: string | null;
435
+ message_id: string | null;
436
+ sender_domain: string | null;
437
+ flags: string[];
438
+ untrusted: true;
439
+ handling: string;
440
+ }
441
+ export interface HarnyClientOptions {
442
+ /** App-scoped key (`fsa_`). Required to call `provisionUser`. With no key given, Node reads `HARNY_API_KEY` (`HARNY_APP_KEY` is accepted as an alias). */
443
+ apiKey?: string;
444
+ /** User-scoped key (`fsk_`). Set directly to restore an existing session. */
445
+ userApiKey?: string;
446
+ baseUrl?: string;
447
+ timeoutMs?: number;
448
+ }
449
+ /** What caused an action. Read it from your runtime, never from model output. */
450
+ export type ActionInitiator = "user_request" | "schedule" | "agent_plan" | "system_event" | "unknown";
451
+ export type ActingMode = "act" | "ask_first" | "off";
452
+ /**
453
+ * The four kinds of action a business sets its acting policy for, named by
454
+ * what the action touches:
455
+ * - `nobody_else`: changes only the end user's own account;
456
+ * - `others_affected`: reaches other people (a calendar invite sent to guests);
457
+ * - `money`: any charge, payment, refund, discount or credit;
458
+ * - `irreversible`: can't be undone once done.
459
+ *
460
+ * An action can be more than one kind; the agent follows the most careful of
461
+ * the business's settings for the kinds it is.
462
+ */
463
+ export type ActionKind = "nobody_else" | "others_affected" | "money" | "irreversible";
464
+ /** The four kinds of action, in the order Harny lists them everywhere. */
465
+ export declare const ACTION_KINDS: readonly ActionKind[];
466
+ export interface ActionRefusal {
467
+ code: string;
468
+ message: string;
469
+ retry_after_seconds?: number | null;
470
+ expansion_hint?: Record<string, unknown> | null;
471
+ }
472
+ /**
473
+ * What happened to one catalog action. Give a model `forModel()` only.
474
+ * `confirmRef` (ask-first) is non-enumerable: `JSON.stringify(outcome)` never
475
+ * includes it, because nothing a model reads may approve an action on the
476
+ * person's behalf. Read it explicitly in your confirm UI handler.
477
+ */
478
+ export interface ActionOutcome {
479
+ executionId: string;
480
+ action: string;
481
+ outcome: "completed" | "awaiting_end_user" | "refused" | "declined" | "expired" | "failed" | "processing";
482
+ /** The kinds of action this is, in Harny's order (e.g. `["others_affected"]`). */
483
+ kinds: ActionKind[];
484
+ /** Why the action is those kinds (e.g. `guests_receive_invitations`). */
485
+ kindReasons: string[];
486
+ /** The kind whose setting decided the outcome: the most careful of the business's settings for the kinds read. */
487
+ decidedBy: ActionKind | null;
488
+ recordId: string | null;
489
+ refusal: ActionRefusal | null;
490
+ result: Record<string, unknown> | null;
491
+ alreadyDecided: boolean;
492
+ replayed: boolean;
493
+ confirmExpiresAt: string | null;
494
+ readonly confirmRef?: string;
495
+ forModel(): {
496
+ status: string;
497
+ message: string;
498
+ };
499
+ }
500
+ /** The business's setting for one kind of action, and who set it when. */
501
+ export interface ActingKindSetting {
502
+ mode: ActingMode | null;
503
+ version: number | null;
504
+ set_by: string | null;
505
+ set_via: string | null;
506
+ set_at: string | null;
507
+ }
508
+ export interface ActingPolicyResponse {
509
+ app_id: string;
510
+ version: number;
511
+ nobody_else: ActingKindSetting;
512
+ others_affected: ActingKindSetting;
513
+ money: ActingKindSetting;
514
+ irreversible: ActingKindSetting;
515
+ unset_means: string;
516
+ /**
517
+ * True while a proposal stored before the owner decided is in force: while
518
+ * the app is in test, Harny applies every proposed kind as proposed. Absent
519
+ * from older servers.
520
+ */
521
+ proposal_in_effect?: boolean;
522
+ /**
523
+ * The app's stage: "test" (the default) or "production". The owner moves the
524
+ * app to production by confirming the four settings. Absent from older servers.
525
+ */
526
+ stage?: "test" | "production";
527
+ }
528
+ /**
529
+ * A short-lived token for ONE end user, for a hosted agent runtime's MCP
530
+ * connection. Give `access_token` only to that connection
531
+ * (`Authorization: Bearer`) at `mcp_url`; never the app key. Rotating the
532
+ * app key ends every token it minted.
533
+ */
534
+ export interface RuntimeToken {
535
+ access_token: string;
536
+ token_type?: "Bearer";
537
+ expires_in: number;
538
+ expires_at: string;
539
+ scope: string;
540
+ token_id: string;
541
+ user_id: string;
542
+ mcp_url: string;
543
+ message: string;
544
+ user_driven_only?: boolean;
545
+ }
546
+ export interface RuntimeTokenRevoked {
547
+ token_id: string;
548
+ revoked_at: string;
549
+ already_revoked?: boolean;
550
+ }
551
+ export interface MintRuntimeTokenOptions {
552
+ /** Seconds the token works; the deployment's default (15 minutes) when omitted. */
553
+ ttlSeconds?: number;
554
+ /** Read the end user's context only; perform no action. */
555
+ readOnly?: boolean;
556
+ /** Catalog actions it may perform, e.g. ["calendar.create_event"]; all when omitted. Undo needs "calendar.delete_event". */
557
+ actions?: string[];
558
+ /** What started the runtime session, from your backend (never a model). */
559
+ initiatedBy?: ActionInitiator;
560
+ /** Your note for the audit trail, e.g. the runtime session id. */
561
+ label?: string;
562
+ /** Your own https page where the end user grants write access. Required unless readOnly. */
563
+ connectUrl?: string;
564
+ /**
565
+ * A hosted runtime can read content Harny never sees, so by default, where
566
+ * a setting is act, an invitation or message from the session to an
567
+ * address the person never gave waits for their yes. True (only when every
568
+ * action in the session is the end user's own request) removes that
569
+ * assumption and nothing else: the same wait still applies when
570
+ * initiatedBy is "system_event" or when something read for this person
571
+ * through Harny recently (15 minutes by default) included someone else's
572
+ * content, such as an email. Actions on the person's own account never
573
+ * wait for this.
574
+ */
575
+ userDrivenOnly?: boolean;
576
+ /**
577
+ * The end user's own words that start this session (their chat message),
578
+ * from your backend, never a model. An email address in them counts as one
579
+ * the person gave for the session's actions, so an invitation or message
580
+ * to it follows your settings instead of waiting for their yes. Only the
581
+ * addresses are kept, never the words.
582
+ */
583
+ endUserMessage?: string;
584
+ /**
585
+ * The token reads this person's action history (read-only) by default;
586
+ * false leaves it out.
587
+ */
588
+ actionHistory?: boolean;
589
+ }
590
+ /**
591
+ * An ask-first action a hosted runtime asked for over MCP. The runtime never
592
+ * receives `confirm_ref`; your backend reads it here and shows your confirm
593
+ * card. Never pass `confirm_ref` to a model.
594
+ */
595
+ export interface PendingConfirmation {
596
+ execution_id: string;
597
+ confirm_ref: string;
598
+ expires_at: string;
599
+ action: string;
600
+ arguments: Record<string, unknown>;
601
+ summary?: Record<string, unknown>;
602
+ kinds?: ActionKind[];
603
+ kind_reasons?: string[];
604
+ decided_by?: ActionKind | null;
605
+ /**
606
+ * The addresses the person never gave, when that is why it waits although
607
+ * your setting said act: show them on your confirm card.
608
+ */
609
+ held_for_recipients?: string[];
610
+ /**
611
+ * True when Harny could not finish checking those addresses (a look-up
612
+ * failed), so it asked instead; they may well be ones the person gave.
613
+ */
614
+ recipient_lookup_failed?: boolean;
615
+ }
616
+ /**
617
+ * The longest end-user message Harny reads for the addresses it names; a
618
+ * longer one is sent cut to this length (addresses past it are not read).
619
+ */
620
+ export declare const END_USER_MESSAGE_MAX_CHARS = 100000;
621
+ export declare class HarnyClient {
622
+ private readonly apiKey;
623
+ private userApiKeyValue;
624
+ /** A user key given to the constructor (possibly the app owner's), not one cached by provisionUser. */
625
+ private readonly userKeyGiven;
626
+ private readonly baseUrl;
627
+ private readonly timeoutMs;
628
+ /** The id of the user provisionUser made: the recall identity of a client that acts as that user. */
629
+ private provisionedUserId;
630
+ constructor({ apiKey, userApiKey, baseUrl, timeoutMs }?: HarnyClientOptions);
631
+ /** A key-free view: `JSON.stringify(client)` never carries a key. */
632
+ toJSON(): Record<string, unknown>;
633
+ /**
634
+ * The current user-scoped key, or `undefined` before `provisionUser`.
635
+ * Persist it to restore this user's session on a later run instead of
636
+ * provisioning again (provisioning is rate-limited).
637
+ */
638
+ get userApiKey(): string | undefined;
639
+ private resolveBaseUrl;
640
+ private bearer;
641
+ private request;
642
+ /**
643
+ * Per-subsystem health snapshot. Needs no user session; with one, the
644
+ * response also carries per-source freshness.
645
+ */
646
+ diagnose(): Promise<DiagnoseResponse>;
647
+ /**
648
+ * Create or retrieve one app-scoped end user and switch this client to
649
+ * that user's key. Call it again for the next person: the client then
650
+ * acts for that person.
651
+ *
652
+ * Requires an `fsa_` app key. Provisioning is rate-limited: persist
653
+ * `client.userApiKey` and reuse it instead of re-provisioning per run.
654
+ * For a person who already exists, the call returns that user and no new
655
+ * key: nothing new is cached (name the person with `user`).
656
+ */
657
+ provisionUser(identifier: string, email: string, options?: ProvisionUserOptions): Promise<User>;
658
+ /**
659
+ * Persist a plain-text document to the user's vault (the provisioned
660
+ * user's, or `options.user` with an app key). `options.writtenByPerson`:
661
+ * set only when the text is the person's own typed words, never pasted,
662
+ * received or model-written content, and only with `options.user` (your
663
+ * app key for that person); it is ignored with the person's own key. An
664
+ * email address in such text then counts as one the person gave: after
665
+ * your agent read someone else's content, an invitation or message to it
666
+ * follows your settings instead of waiting for their yes.
667
+ */
668
+ ingestText(content: string, title?: string, options?: {
669
+ user?: string;
670
+ writtenByPerson?: boolean;
671
+ idempotencyKey?: string;
672
+ }): Promise<IngestResponse>;
673
+ /** Run an idempotent request; if the answer never arrived (timeout or dropped connection), send it once more with the same key. */
674
+ private retryOnceWhenLost;
675
+ /** Upload a binary file to the provisioned user's vault. */
676
+ ingestFile(file: File | Blob | Uint8Array, filename?: string): Promise<IngestResponse>;
677
+ /**
678
+ * Retrieve assembled context for a query.
679
+ *
680
+ * Check `result.degraded_sources` before treating an empty `blocks` array
681
+ * as "this user has no data" — a non-empty array means retrieval FAILED
682
+ * for those sources.
683
+ */
684
+ assembleContext(query: string, options?: AssembleOptions, target?: AssembleTarget): Promise<ContextResult>;
685
+ /**
686
+ * Tell Harny you asked the user about a conflict, so the question is not put twice. Call it BEFORE you show the
687
+ * question `decideConflictQuestion` returned, and show it only when the result's `first_time` is true: the first
688
+ * report wins, so a second action in the same turn, a retry or a second process cannot put the question twice. The
689
+ * next context response marks that conflict `asked`. `conflict` is a `ContextConflict`, an object with its
690
+ * `record_id_1` and `record_id_2`, or the decision itself (a decision that says not to ask is refused). Safe to repeat. `options.user`: the end user (needs an app key); omit it
691
+ * on a client that provisioned a user. Never expose this to a model as a tool: asking is your confirm step's.
692
+ * Throws `HarnyError` (404, `conflict_not_found`) for a conflict that was not in this user's context response.
693
+ */
694
+ markConflictAsked(conflict: ConflictRefInput, options?: {
695
+ user?: string;
696
+ traceparent?: string;
697
+ }): Promise<ConflictAsked>;
698
+ /**
699
+ * Send the user's answer to a conflict. It is saved as something the user said, and the conflict is no
700
+ * longer returned. `answer` is the user's answer as a statement that stands on its own, in their words (for
701
+ * example "Maya prefers email"); it is saved the way `ingestText` saves text and goes through the
702
+ * same limits. Throws `HarnyError` as `ingestText` does (for example when the memory service is unavailable;
703
+ * nothing is marked answered then), and 404 `conflict_not_found` for a conflict that was not in this user's
704
+ * context response (nothing is saved then). `conflict` and `options` are as for `markConflictAsked`.
705
+ */
706
+ answerConflict(conflict: ConflictRefInput, answer: string, options?: {
707
+ user?: string;
708
+ traceparent?: string;
709
+ }): Promise<ConflictAnswered>;
710
+ /**
711
+ * Read one arrived email (an arrival's `item_ref`) for its end user. The
712
+ * text comes back hardened — secrets redacted, instruction-like lines
713
+ * removed — and is third-party content: pass it to a model as data only.
714
+ */
715
+ getSourceItem(itemRef: string, options?: {
716
+ user?: string;
717
+ traceparent?: string;
718
+ }): Promise<SourceItem>;
719
+ /**
720
+ * Poll new items that arrived on your end users' email sources (app key),
721
+ * oldest first — the same arrivals the `source.sync_complete` webhook
722
+ * delivers. Pass the last `next_cursor` as `after`; process each
723
+ * `dedupe_key` once. `user` narrows to one end user.
724
+ */
725
+ listArrivals(options?: {
726
+ after?: number;
727
+ limit?: number;
728
+ user?: string;
729
+ traceparent?: string;
730
+ }): Promise<SourceArrivalPage>;
731
+ /**
732
+ * Start an OAuth flow for one external source. Send the end user to the
733
+ * returned `authorization_url`.
734
+ *
735
+ * Which providers a deployment can connect varies, and Gmail / Calendar /
736
+ * Drive sit behind Early Access approval — do not hardcode a provider
737
+ * name without checking the account's access first.
738
+ *
739
+ * `sharedFactsOptIn` passes the person's own answer to Harny's sharing
740
+ * question, the one Harny's connect widget shows (unticked). Send `true`
741
+ * only when the person themselves ticked it: Harny keeps the answer with
742
+ * this connect and saves it, as the person's own choice, when the
743
+ * connection completes. `false` and leaving it out record nothing and never
744
+ * withdraw an earlier yes. A person flagged as a child is never opted in.
745
+ * Anything but `true` or `false` throws.
746
+ */
747
+ connectSource(provider: ContextSourceProvider | string, returnUrl?: string, options?: {
748
+ capabilities?: string[];
749
+ user?: string;
750
+ sharedFactsOptIn?: boolean;
751
+ }): Promise<ConnectResponse>;
752
+ /** The end user an action is for: app key + named user, or the user's own key. */
753
+ private actingAuth;
754
+ /**
755
+ * Perform one catalog action (for example `calendar.create_event`) for one
756
+ * end user. Harny works out which kinds of action it is from what it does,
757
+ * follows the most careful of your business's settings for those kinds,
758
+ * checks the user's write consent, performs the action and records the
759
+ * outcome. No model is called. Tell a model only `outcome.forModel()`.
760
+ * After your agent read someone else's content (an email, a calendar
761
+ * entry, a shared document), where your setting is act, an invitation or
762
+ * message to an address the person never gave waits for their yes; with
763
+ * `initiatedBy: "system_event"` it always does. `endUserMessage`: the
764
+ * person's own words for this request (their chat message), from your
765
+ * backend, never a model; an email address in them counts as given. Only
766
+ * the addresses are kept, never the words; with `initiatedBy:
767
+ * "system_event"` they are not counted.
768
+ */
769
+ act(action: string, args: Record<string, unknown>, options?: {
770
+ user?: string;
771
+ initiatedBy?: ActionInitiator;
772
+ idempotencyKey?: string;
773
+ correlationId?: string;
774
+ traceparent?: string;
775
+ endUserMessage?: string;
776
+ }): Promise<ActionOutcome>;
777
+ /**
778
+ * Send the end user's decision on an ask-first action, from your UI
779
+ * handler. Never expose this to a model as a tool.
780
+ *
781
+ * `answeredBy` says how the card was answered, as your app knows it: `tap` (the person pressed the button),
782
+ * `timeout` (the card ran out of time), `dismissed` (the person closed it without choosing) or `server` (your backend
783
+ * answered without showing a card). Leave it out when you do not know; an answer marked `timeout`, `dismissed` or
784
+ * `server` is not counted as a person's choice when Harny reads how your users answer.
785
+ *
786
+ * `edit` is what the person corrected on the card before approving it (only with `approve: true`, for a calendar
787
+ * event): `title`, `start`, `end`, `duration_minutes`, `time_zone`, `description`, `location`, or a shorter guest list in
788
+ * `attendees` (the same guests or fewer). The corrected action is the one that runs, and the record shows what changed.
789
+ * An edit never adds a guest: one who was not on the card is refused (`confirm_edit_not_allowed`) and the card stays
790
+ * open; the agent proposes that as a new request. Any other field throws before a call is made.
791
+ */
792
+ confirm(executionId: string, confirmRef: string, approve: boolean, options?: {
793
+ user?: string;
794
+ traceparent?: string;
795
+ answeredBy?: ConfirmAnsweredBy;
796
+ edit?: ConfirmEdit;
797
+ }): Promise<ActionOutcome>;
798
+ /**
799
+ * Mint a short-lived token for ONE end user (app key), for a hosted agent
800
+ * runtime's MCP connection. The runtime reads that person's context and
801
+ * performs catalog actions for that person only, through your acting
802
+ * policy, until the token expires. It also reads that person's action
803
+ * history by default (`actionHistory: false` leaves it out).
804
+ */
805
+ mintRuntimeToken(user: string, options?: MintRuntimeTokenOptions): Promise<RuntimeToken>;
806
+ /** Revoke one runtime token now (app key). Rotating the app key revokes them all. */
807
+ revokeRuntimeToken(tokenId: string): Promise<RuntimeTokenRevoked>;
808
+ /**
809
+ * The confirm reference of an ask-first action a hosted runtime asked for
810
+ * over MCP (app key). Call it when the approval-needed webhook names the
811
+ * execution, show your confirm card, then `confirm(...)`.
812
+ */
813
+ getPendingConfirmation(executionId: string, options: {
814
+ user: string;
815
+ }): Promise<PendingConfirmation>;
816
+ /**
817
+ * Set up the person's Google bridge: a small script they copy into their own Google account.
818
+ *
819
+ * Call it first without `acceptedTextSha256`: it returns `{ registered: false, consent, next_step }`. Show the
820
+ * person `consent.text` and ask which of `gmail`, `calendar` and `drive` to include. After their yes, call it
821
+ * again with `acceptedTextSha256: consent.text_sha256` (and `sources`): it registers and returns the setup
822
+ * answer once (`setup_code`, `script_properties`, `agent_instructions`). Needs the bridge to be switched on for
823
+ * your deployment (otherwise a 404 `google_bridge_off`). `user`: as in `act`.
824
+ */
825
+ googleBridgeSetup(sources?: string[], options?: {
826
+ acceptedTextSha256?: string;
827
+ label?: string;
828
+ user?: string;
829
+ }): Promise<Record<string, any>>;
830
+ /**
831
+ * Ask the person's Google bridge to do one thing in their own Google account.
832
+ *
833
+ * `kind`: `gmail.send`, `gmail.draft`, `gmail.search`, `gmail.read`, `calendar.list`, `calendar.create`,
834
+ * `calendar.delete`, `drive.search`, `drive.read` or `drive.create`; `params` holds that kind's fields. With
835
+ * `wait` (the default) it polls until the action is `done`, `failed` or `expired`, or `timeoutMs` pass, and
836
+ * returns the last view: check `status`. A send, draft or create whose delivery is unconfirmed is not repeated:
837
+ * read `status` before asking again. `user`: as in `act`.
838
+ */
839
+ googleBridgeAct(kind: string, params?: Record<string, unknown>, options?: {
840
+ wait?: boolean;
841
+ timeoutMs?: number;
842
+ pollIntervalMs?: number;
843
+ user?: string;
844
+ }): Promise<Record<string, any>>;
845
+ /** Undo an action your agent performed, by its action-record id. */
846
+ undo(recordId: string, options?: {
847
+ user?: string;
848
+ initiatedBy?: ActionInitiator;
849
+ idempotencyKey?: string;
850
+ traceparent?: string;
851
+ }): Promise<ActionOutcome>;
852
+ /**
853
+ * Read the platform model roster (app key): presets over provider/model
854
+ * entries with capability flags, region hints and list prices. Your agent
855
+ * runs on your own model key.
856
+ */
857
+ getModelRoster(): Promise<ModelRoster>;
858
+ /**
859
+ * The setup bundle a coding assistant stands your agent up from (app key).
860
+ * It names key variables and never carries a key.
861
+ */
862
+ getSetupBundle(appId: string, options: SetupBundleOptions): Promise<Record<string, unknown>>;
863
+ /** Read your app's acting policy (app key). */
864
+ getActingPolicy(appId: string): Promise<ActingPolicyResponse>;
865
+ /**
866
+ * Set what your agent may do for each kind of action: "act", "ask_first",
867
+ * "off", or null (unset — the agent does not act on that kind). Kinds you
868
+ * omit are unchanged. The kinds: `nobody_else` (only the customer's own
869
+ * account), `others_affected` (reaches other people),
870
+ * `money` (any charge, payment, refund, discount or credit) and
871
+ * `irreversible` (can't be undone once done). An action can be more than
872
+ * one kind; your agent follows the most careful of your settings for the
873
+ * kinds it is. Where that is act and your agent has read someone else's
874
+ * content, an invitation or message to an address the person never gave
875
+ * waits for their yes.
876
+ *
877
+ * Needs the APP OWNER's user key (`userApiKey: 'fsk_...'`), never the
878
+ * `fsa_` app key your agent runs with: Harny refuses that key here (403
879
+ * owner_credential_required) so an agent can never turn acting on for
880
+ * itself. Keep the owner key out of the agent's deployment, or set the
881
+ * policy in the console.
882
+ */
883
+ setActingPolicy(appId: string, policy: {
884
+ nobody_else?: ActingMode | null;
885
+ others_affected?: ActingMode | null;
886
+ money?: ActingMode | null;
887
+ irreversible?: ActingMode | null;
888
+ setVia?: "console" | "api" | "bundle" | "assistant";
889
+ /** Needed only while the app is live (in production): `true` confirms the change and it applies at once. */
890
+ confirm?: boolean;
891
+ }): Promise<ActingPolicyResponse>;
892
+ /** List the provisioned user's connected sources and their freshness. */
893
+ listSources(): Promise<SourceListResponse>;
894
+ /** Trigger a sync job for one connected source. */
895
+ syncSource(provider: ContextSourceProvider | string, options?: {
896
+ fullResync?: boolean;
897
+ }): Promise<SyncResponse>;
898
+ /**
899
+ * Send one data point: text plus the time it happened. Answers 202 with an `ingestionId` to poll with
900
+ * `getIngestion`. Send the same `id` again with changed content and the new text replaces the old; the same
901
+ * content again answers `unchanged: true` and costs nothing. `options.user` names the person (needs an app key).
902
+ */
903
+ ingestDataPoint(point: DataPoint, options?: IngestDataPointOptions): Promise<MemoryIngestReceipt>;
904
+ /** Send 1 to 1,000 data points at once. Send the same `idempotencyKey` and body again after a failure to resume. */
905
+ ingestBatch(items: DataPoint[], options?: IngestDataPointOptions): Promise<MemoryIngestReceipt>;
906
+ /** Where one send is: `processing`, `completed` or `failed`. */
907
+ getIngestion(ingestionId: string, options?: {
908
+ user?: string;
909
+ }): Promise<MemoryIngestionStatus>;
910
+ /** Poll `getIngestion` until the send is `completed` or `failed`; throws after `timeoutMs` (default 300000). A timeout does not mean the save failed. */
911
+ waitForIngestion(ingestionId: string, options?: WaitOptions): Promise<MemoryIngestionStatus>;
912
+ /** Forget one send: its data points and every memory that rests only on them. Free; a repeat succeeds. */
913
+ deleteIngestion(ingestionId: string, options?: {
914
+ user?: string;
915
+ }): Promise<void>;
916
+ /** Delete one data point by its `sourceId`, and the memory built on it. */
917
+ deleteDataPoint(sourceId: string, options?: {
918
+ user?: string;
919
+ }): Promise<MemoryDeletion>;
920
+ /** Delete 1 to 1,000 data points by `sourceId`. If one id is unknown, none is deleted and the error names it. */
921
+ deleteDataPoints(ids: string[], options?: {
922
+ user?: string;
923
+ }): Promise<MemoryDeletion>;
924
+ /** Ranked, dated evidence for a question, as the person asking (`options.identity`, default `options.user`). */
925
+ recall(query: string, options?: RecallOptions): Promise<MemoryRecall>;
926
+ /** This month's usage for the app. Needs the app key. */
927
+ getUsage(): Promise<MemoryUsage>;
928
+ /** The recall identity when none is named: only a client that provisioned a user knows it. */
929
+ private userApiKeyIdentity;
930
+ }
931
+ /** The `X-Harny-Signature` value Harny sends for `body` under `secret`. */
932
+ export declare function computeWebhookSignature(secret: string, body: string | Uint8Array): Promise<string>;
933
+ /**
934
+ * Constant-time check of `X-Harny-Signature` against one or more secrets
935
+ * (pass the current and the previous one during a rotation). Verify the RAW
936
+ * body bytes before parsing. Accepts the header with or without `sha256=`.
937
+ */
938
+ export declare function verifyWebhookSignature(body: string | Uint8Array, signature: string | null | undefined, secrets: string | string[]): Promise<boolean>;
939
+ /**
940
+ * Verify, then parse a `source.sync_complete` delivery. Throws when the
941
+ * signature does not verify (answer 401 and do nothing) or the body is not a
942
+ * `source.sync_complete` event.
943
+ */
944
+ export declare function parseSourceArrivalEvent(body: string | Uint8Array, signature: string | null | undefined, secrets: string | string[]): Promise<SourceArrivalEvent>;
945
+ export { ActDecision, ActionNote, ActionTrace, Agent, AgentConfig, AgentPendingConfirmation, ChatCompletionsAdapter, FileSessionStore, GenerateContentAdapter, HARNY_CALLS, HarnyTools, HookBlocked, MODEL_REACHABLE_CALLS, MemorySessionStore, Message, MessagesAdapter, ModelProviderError, ModelTurn, PRESET_NAMES, PresetResolutionError, ResolvedModel, RunResult, SpendCap, SpendMeter, Tracer, Turn, Usage, buildAdapter, parseTraceparent, resolvePreset, } from "./agent/index.js";
946
+ export type { AdapterOptions, AgentConfigOptions, AgentHooks, AgentOptions, CompleteRequest, ContextStatus, CreateAgentOptions, HarnyClientLike, HookContext, MessageRole, ModelAdapter, OtelApiLike, OtelSpanContextLike, OtelSpanLike, OtelTracerLike, PresetName, ResolvePresetOptions, RunOptions, SessionStore, SpanAttributeValue, StopReason, ToolCall, ToolResult, ToolSpec, ToolTransport, TurnRole, } from "./agent/index.js";
947
+ export { ASKING_KINDS, CONFLICT_QUESTION_MODES, DEFAULT_CONFLICT_QUESTION_MODE, InMemoryConflictAskLedger, QuestionPhrases, conflictKey, decideConflictQuestion, formatDay, normaliseMode, questionText, } from "./conflictQuestion.js";
948
+ export type { ConflictAskLedger, ConflictLike, ConflictQuestion, ConflictQuestionMode, DecideConflictQuestionOptions, PhrasesSource, QuestionPhrasesInit, } from "./conflictQuestion.js";
949
+ export { RECALL_LEVELS } from "./memoryV1.js";
950
+ export type { DataPoint, IngestDataPointOptions, MemoryDeletion, MemoryIngestionStatus, MemoryIngestReceipt, MemoryItemReceipt, MemoryReadiness, MemoryRecall, MemoryResult, MemorySource, MemoryUsage, RecallLevel, RecallOptions, RecallSort, WaitOptions, } from "./memoryV1.js";