@harny/sdk 0.1.2 → 0.1.3
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/cjs/agent/adapters.d.ts +167 -0
- package/dist/cjs/agent/adapters.js +557 -0
- package/dist/cjs/agent/adapters.js.map +1 -0
- package/dist/cjs/agent/hooks.d.ts +52 -0
- package/dist/cjs/agent/hooks.js +41 -0
- package/dist/cjs/agent/hooks.js.map +1 -0
- package/dist/cjs/agent/index.d.ts +34 -0
- package/dist/cjs/agent/index.js +62 -0
- package/dist/cjs/agent/index.js.map +1 -0
- package/dist/cjs/agent/loop.d.ts +401 -0
- package/dist/cjs/agent/loop.js +1252 -0
- package/dist/cjs/agent/loop.js.map +1 -0
- package/dist/cjs/agent/roster.d.ts +62 -0
- package/dist/cjs/agent/roster.js +149 -0
- package/dist/cjs/agent/roster.js.map +1 -0
- package/dist/cjs/agent/session.d.ts +106 -0
- package/dist/cjs/agent/session.js +261 -0
- package/dist/cjs/agent/session.js.map +1 -0
- package/dist/cjs/agent/spend.d.ts +39 -0
- package/dist/cjs/agent/spend.js +70 -0
- package/dist/cjs/agent/spend.js.map +1 -0
- package/dist/cjs/agent/tools.d.ts +83 -0
- package/dist/cjs/agent/tools.js +212 -0
- package/dist/cjs/agent/tools.js.map +1 -0
- package/dist/cjs/agent/tracing.d.ts +72 -0
- package/dist/cjs/agent/tracing.js +128 -0
- package/dist/cjs/agent/tracing.js.map +1 -0
- package/dist/cjs/agent/util.d.ts +60 -0
- package/dist/cjs/agent/util.js +188 -0
- package/dist/cjs/agent/util.js.map +1 -0
- package/dist/cjs/conflictQuestion.d.ts +137 -0
- package/dist/cjs/conflictQuestion.js +356 -0
- package/dist/cjs/conflictQuestion.js.map +1 -0
- package/dist/cjs/index.d.ts +950 -0
- package/dist/cjs/index.js +1124 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/memoryV1.d.ts +121 -0
- package/dist/cjs/memoryV1.js +132 -0
- package/dist/cjs/memoryV1.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/agent/adapters.d.ts +167 -0
- package/dist/esm/agent/adapters.js +543 -0
- package/dist/esm/agent/adapters.js.map +1 -0
- package/dist/esm/agent/hooks.d.ts +52 -0
- package/dist/esm/agent/hooks.js +36 -0
- package/dist/esm/agent/hooks.js.map +1 -0
- package/dist/esm/agent/index.d.ts +34 -0
- package/dist/esm/agent/index.js +28 -0
- package/dist/esm/agent/index.js.map +1 -0
- package/dist/esm/agent/loop.d.ts +401 -0
- package/dist/esm/agent/loop.js +1243 -0
- package/dist/esm/agent/loop.js.map +1 -0
- package/dist/esm/agent/roster.d.ts +62 -0
- package/dist/esm/agent/roster.js +143 -0
- package/dist/esm/agent/roster.js.map +1 -0
- package/dist/esm/agent/session.d.ts +106 -0
- package/dist/esm/agent/session.js +221 -0
- package/dist/esm/agent/session.js.map +1 -0
- package/dist/esm/agent/spend.d.ts +39 -0
- package/dist/esm/agent/spend.js +65 -0
- package/dist/esm/agent/spend.js.map +1 -0
- package/dist/esm/agent/tools.d.ts +83 -0
- package/dist/esm/agent/tools.js +205 -0
- package/dist/esm/agent/tools.js.map +1 -0
- package/dist/esm/agent/tracing.d.ts +72 -0
- package/dist/esm/agent/tracing.js +119 -0
- package/dist/esm/agent/tracing.js.map +1 -0
- package/dist/esm/agent/util.d.ts +60 -0
- package/dist/esm/agent/util.js +168 -0
- package/dist/esm/agent/util.js.map +1 -0
- package/dist/esm/conflictQuestion.d.ts +137 -0
- package/dist/esm/conflictQuestion.js +346 -0
- package/dist/esm/conflictQuestion.js.map +1 -0
- package/dist/esm/index.d.ts +950 -0
- package/dist/esm/index.js +1072 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/memoryV1.d.ts +121 -0
- package/dist/esm/memoryV1.js +124 -0
- package/dist/esm/memoryV1.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/package.json +2 -3
|
@@ -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";
|