agentfootprint 9.26.0 → 9.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/adapters/google/aiPlatform.js +438 -0
  2. package/dist/adapters/google/aiPlatform.js.map +1 -0
  3. package/dist/adapters/hosting/googleAgentEngine.js +372 -0
  4. package/dist/adapters/hosting/googleAgentEngine.js.map +1 -0
  5. package/dist/adapters/identity/google.js +275 -0
  6. package/dist/adapters/identity/google.js.map +1 -0
  7. package/dist/adapters/memory/agentcore.js +19 -0
  8. package/dist/adapters/memory/agentcore.js.map +1 -1
  9. package/dist/adapters/memory/memoryBank.js +823 -0
  10. package/dist/adapters/memory/memoryBank.js.map +1 -0
  11. package/dist/core/agent/stages/routeTurn.js +13 -1
  12. package/dist/core/agent/stages/routeTurn.js.map +1 -1
  13. package/dist/esm/adapters/google/aiPlatform.d.ts +453 -0
  14. package/dist/esm/adapters/google/aiPlatform.js +424 -0
  15. package/dist/esm/adapters/google/aiPlatform.js.map +1 -0
  16. package/dist/esm/adapters/hosting/googleAgentEngine.d.ts +156 -0
  17. package/dist/esm/adapters/hosting/googleAgentEngine.js +368 -0
  18. package/dist/esm/adapters/hosting/googleAgentEngine.js.map +1 -0
  19. package/dist/esm/adapters/identity/google.d.ts +179 -0
  20. package/dist/esm/adapters/identity/google.js +271 -0
  21. package/dist/esm/adapters/identity/google.js.map +1 -0
  22. package/dist/esm/adapters/memory/agentcore.d.ts +19 -0
  23. package/dist/esm/adapters/memory/agentcore.js +19 -0
  24. package/dist/esm/adapters/memory/agentcore.js.map +1 -1
  25. package/dist/esm/adapters/memory/memoryBank.d.ts +390 -0
  26. package/dist/esm/adapters/memory/memoryBank.js +817 -0
  27. package/dist/esm/adapters/memory/memoryBank.js.map +1 -0
  28. package/dist/esm/core/agent/stages/routeTurn.js +13 -1
  29. package/dist/esm/core/agent/stages/routeTurn.js.map +1 -1
  30. package/dist/esm/events/payloads.d.ts +23 -0
  31. package/dist/esm/hosting-providers.d.ts +7 -0
  32. package/dist/esm/hosting-providers.js +6 -0
  33. package/dist/esm/hosting-providers.js.map +1 -1
  34. package/dist/esm/identity.d.ts +1 -0
  35. package/dist/esm/identity.js +5 -0
  36. package/dist/esm/identity.js.map +1 -1
  37. package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js +9 -0
  38. package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
  39. package/dist/esm/lib/injection-engine/routingPolicy.d.ts +8 -0
  40. package/dist/esm/lib/injection-engine/routingPolicy.js.map +1 -1
  41. package/dist/esm/lib/injection-engine/skillGraph.d.ts +11 -2
  42. package/dist/esm/lib/injection-engine/skillGraph.js +25 -1
  43. package/dist/esm/lib/injection-engine/skillGraph.js.map +1 -1
  44. package/dist/esm/lib/injection-engine/skillIntent.d.ts +13 -5
  45. package/dist/esm/lib/injection-engine/skillIntent.js +12 -2
  46. package/dist/esm/lib/injection-engine/skillIntent.js.map +1 -1
  47. package/dist/esm/lib/injection-engine/skillMatch.d.ts +40 -0
  48. package/dist/esm/lib/injection-engine/skillMatch.js +60 -0
  49. package/dist/esm/lib/injection-engine/skillMatch.js.map +1 -1
  50. package/dist/esm/memory-providers.d.ts +1 -0
  51. package/dist/esm/memory-providers.js +7 -0
  52. package/dist/esm/memory-providers.js.map +1 -1
  53. package/dist/esm/recorders/observability/AgentThinkingTraceRecorder.d.ts +4 -0
  54. package/dist/esm/recorders/observability/AgentThinkingTraceRecorder.js +4 -1
  55. package/dist/esm/recorders/observability/AgentThinkingTraceRecorder.js.map +1 -1
  56. package/dist/esm/recorders/observability/commentary/artifactPhrases.d.ts +50 -0
  57. package/dist/esm/recorders/observability/commentary/artifactPhrases.js +88 -0
  58. package/dist/esm/recorders/observability/commentary/artifactPhrases.js.map +1 -0
  59. package/dist/esm/recorders/observability/commentary/commentaryTemplates.js +233 -9
  60. package/dist/esm/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
  61. package/dist/hosting-providers.js +10 -1
  62. package/dist/hosting-providers.js.map +1 -1
  63. package/dist/identity.js +8 -1
  64. package/dist/identity.js.map +1 -1
  65. package/dist/lib/injection-engine/buildInjectionEngineSubflow.js +9 -0
  66. package/dist/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
  67. package/dist/lib/injection-engine/routingPolicy.js.map +1 -1
  68. package/dist/lib/injection-engine/skillGraph.js +25 -1
  69. package/dist/lib/injection-engine/skillGraph.js.map +1 -1
  70. package/dist/lib/injection-engine/skillIntent.js +12 -2
  71. package/dist/lib/injection-engine/skillIntent.js.map +1 -1
  72. package/dist/lib/injection-engine/skillMatch.js +61 -1
  73. package/dist/lib/injection-engine/skillMatch.js.map +1 -1
  74. package/dist/memory-providers.js +12 -1
  75. package/dist/memory-providers.js.map +1 -1
  76. package/dist/recorders/observability/AgentThinkingTraceRecorder.js +4 -1
  77. package/dist/recorders/observability/AgentThinkingTraceRecorder.js.map +1 -1
  78. package/dist/recorders/observability/commentary/artifactPhrases.js +94 -0
  79. package/dist/recorders/observability/commentary/artifactPhrases.js.map +1 -0
  80. package/dist/recorders/observability/commentary/commentaryTemplates.js +233 -9
  81. package/dist/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
  82. package/dist/types/adapters/google/aiPlatform.d.ts +454 -0
  83. package/dist/types/adapters/google/aiPlatform.d.ts.map +1 -0
  84. package/dist/types/adapters/hosting/googleAgentEngine.d.ts +157 -0
  85. package/dist/types/adapters/hosting/googleAgentEngine.d.ts.map +1 -0
  86. package/dist/types/adapters/identity/google.d.ts +180 -0
  87. package/dist/types/adapters/identity/google.d.ts.map +1 -0
  88. package/dist/types/adapters/memory/agentcore.d.ts +19 -0
  89. package/dist/types/adapters/memory/agentcore.d.ts.map +1 -1
  90. package/dist/types/adapters/memory/memoryBank.d.ts +391 -0
  91. package/dist/types/adapters/memory/memoryBank.d.ts.map +1 -0
  92. package/dist/types/core/agent/stages/routeTurn.d.ts.map +1 -1
  93. package/dist/types/events/payloads.d.ts +23 -0
  94. package/dist/types/events/payloads.d.ts.map +1 -1
  95. package/dist/types/hosting-providers.d.ts +7 -0
  96. package/dist/types/hosting-providers.d.ts.map +1 -1
  97. package/dist/types/identity.d.ts +1 -0
  98. package/dist/types/identity.d.ts.map +1 -1
  99. package/dist/types/lib/injection-engine/buildInjectionEngineSubflow.d.ts.map +1 -1
  100. package/dist/types/lib/injection-engine/routingPolicy.d.ts +8 -0
  101. package/dist/types/lib/injection-engine/routingPolicy.d.ts.map +1 -1
  102. package/dist/types/lib/injection-engine/skillGraph.d.ts +11 -2
  103. package/dist/types/lib/injection-engine/skillGraph.d.ts.map +1 -1
  104. package/dist/types/lib/injection-engine/skillIntent.d.ts +13 -5
  105. package/dist/types/lib/injection-engine/skillIntent.d.ts.map +1 -1
  106. package/dist/types/lib/injection-engine/skillMatch.d.ts +40 -0
  107. package/dist/types/lib/injection-engine/skillMatch.d.ts.map +1 -1
  108. package/dist/types/memory-providers.d.ts +1 -0
  109. package/dist/types/memory-providers.d.ts.map +1 -1
  110. package/dist/types/recorders/observability/AgentThinkingTraceRecorder.d.ts +4 -0
  111. package/dist/types/recorders/observability/AgentThinkingTraceRecorder.d.ts.map +1 -1
  112. package/dist/types/recorders/observability/commentary/artifactPhrases.d.ts +51 -0
  113. package/dist/types/recorders/observability/commentary/artifactPhrases.d.ts.map +1 -0
  114. package/dist/types/recorders/observability/commentary/commentaryTemplates.d.ts.map +1 -1
  115. package/package.json +24 -15
@@ -0,0 +1,424 @@
1
+ /**
2
+ * adapters/google/aiPlatform — the one place this package builds a Vertex AI
3
+ * REST client, names a Vertex resource, waits on a Vertex operation, or
4
+ * describes a Vertex failure.
5
+ *
6
+ * Three adapters sit on top of it — `agentEngineSessions`, `memoryBankStore`
7
+ * and (for its auth half only) `googleIdentity` — and none of them repeats any
8
+ * of the four things above. That is the whole reason this file exists: the AWS
9
+ * column learned, expensively, that a shim duplicated across three adapters is
10
+ * three places for the same wire fact to go stale, and only one of them gets
11
+ * fixed.
12
+ *
13
+ * ── Which client, and why THIS one ──────────────────────────────────────────
14
+ * `@googleapis/aiplatform` — the **split, per-API** discovery package (31.0.0,
15
+ * 27 MB) rather than the `googleapis` mega-package (174.0.1, 209 MB) that
16
+ * carries every Google API at once for the same generated code. Both were
17
+ * installed and measured before this was written.
18
+ *
19
+ * The gax/proto client (`@google-cloud/aiplatform`, 78 MB) was rejected on a
20
+ * fact rather than on size: its Memory Bank surface is **v1beta1 only**, while
21
+ * the REST **v1** surface is complete — `memories.purge` and `memories.rollback`
22
+ * exist at v1 and do not exist at v1beta1. One client, at the version that has
23
+ * everything, beats two clients at two versions.
24
+ *
25
+ * `@google-cloud/vertexai` is past its own announced removal date and is not
26
+ * loaded anywhere in this package, ever.
27
+ *
28
+ * ── The endpoint fact that is not in anybody's design doc ───────────────────
29
+ * The generated client defaults to `https://aiplatform.googleapis.com/` — the
30
+ * GLOBAL host. Reasoning engines, their sessions and their memories are
31
+ * **regional** resources. An adapter that accepts the default calls the wrong
32
+ * host and gets a 404 that reads exactly like "your resource does not exist".
33
+ * So {@link buildAiPlatformClient} always sets a regional `rootUrl`, derived
34
+ * from the same `location` that composes the resource name, and the surface pin
35
+ * asserts the default really is the global one so this comment cannot go stale
36
+ * quietly.
37
+ *
38
+ * ── Secrets ─────────────────────────────────────────────────────────────────
39
+ * {@link googleSdkFailure} is the `sdkFailure` law from the AWS identity
40
+ * adapter, re-aimed at a Gaxios error: the SDK's own message never comes
41
+ * through. It is not that a Vertex error always contains a secret — it is that
42
+ * a REST client echoes the request into failure text, our requests carry
43
+ * conversation state and access tokens, and an error message here reaches the
44
+ * model as a tool result AND rides the event stream to every sink attached.
45
+ * One echo publishes it to both at once.
46
+ */
47
+ import { lazyRequire } from '../../lib/lazyRequire.js';
48
+ // ─── Connection ──────────────────────────────────────────────────────
49
+ /**
50
+ * The API version every adapter in this column dials, **stated rather than
51
+ * defaulted**.
52
+ *
53
+ * v1, not v1beta1, and that is a decision with evidence behind it: at v1 the
54
+ * memories collection carries `purge` and `rollback`; at v1beta1 it does not.
55
+ * The Google column's pin asserts this against the installed package on every
56
+ * test run, because "which version does this really call" is the question that
57
+ * made the pin exist.
58
+ */
59
+ export const AI_PLATFORM_API_VERSION = 'v1';
60
+ /** The OAuth scope every Vertex data-plane call needs. */
61
+ export const CLOUD_PLATFORM_SCOPE = 'https://www.googleapis.com/auth/cloud-platform';
62
+ const ENGINE_NAME = /^projects\/([^/]+)\/locations\/([^/]+)\/reasoningEngines\/([^/]+)$/;
63
+ /**
64
+ * Work out which reasoning engine this adapter talks to, from either spelling
65
+ * of `reasoningEngine`.
66
+ *
67
+ * A full resource name wins over `project` / `location` and is CHECKED against
68
+ * them rather than silently overriding: two spellings of one fact that could
69
+ * disagree is the same law the builder refuses `agent` beside `agentFactory`
70
+ * under, and a name that says `us-central1` under a config that says
71
+ * `europe-west4` is a bug somebody should be told about, not arbitrated.
72
+ */
73
+ export function resolveEngine(adapter, connection) {
74
+ const { reasoningEngine, location } = connection;
75
+ if (typeof reasoningEngine !== 'string' || reasoningEngine.trim() === '') {
76
+ throw new TypeError(`${adapter} requires 'reasoningEngine' — the id of the Agent Runtime resource these ` +
77
+ `live under, or its full resource name.\n` +
78
+ ` Sessions and memories are CHILDREN of a reasoning engine; there is nowhere else ` +
79
+ `to put them, so one has to exist even if you deploy no code to it.\n` +
80
+ ` Creating it is a control-plane job (gcloud / Terraform / the console) that this ` +
81
+ `library deliberately does not do.`);
82
+ }
83
+ const match = ENGINE_NAME.exec(reasoningEngine.trim());
84
+ if (match) {
85
+ const [, project, engineLocation, engineId] = match;
86
+ if (connection.project !== undefined && connection.project !== project) {
87
+ throw new TypeError(`${adapter}: 'reasoningEngine' names project '${project}' but 'project' says ` +
88
+ `'${connection.project}'. Two spellings of one fact that disagree are refused rather ` +
89
+ `than arbitrated — drop one of them.`);
90
+ }
91
+ if (location !== undefined && location !== engineLocation) {
92
+ throw new TypeError(`${adapter}: 'reasoningEngine' names location '${engineLocation}' but 'location' says ` +
93
+ `'${location}'. The location picks the regional host as well as the resource name, ` +
94
+ `so a mismatch would call one region for a resource that lives in another. Drop one.`);
95
+ }
96
+ return { project, location: engineLocation, engineId, parent: reasoningEngine.trim() };
97
+ }
98
+ const project = connection.project ?? readEnv('GOOGLE_CLOUD_PROJECT');
99
+ if (project === undefined || project === '') {
100
+ throw new TypeError(`${adapter} requires 'project' — no project was configured and GOOGLE_CLOUD_PROJECT is ` +
101
+ `not set.\n` +
102
+ ` Pass it, set the environment variable, or give 'reasoningEngine' as a full resource ` +
103
+ `name ('projects/…/locations/…/reasoningEngines/…'), which carries the project with it.`);
104
+ }
105
+ if (typeof location !== 'string' || location.trim() === '') {
106
+ throw new TypeError(`${adapter} requires 'location' (e.g. 'us-central1'). There is no default, on purpose: ` +
107
+ `it selects the REGIONAL API host as well as composing the resource name, so a guess ` +
108
+ `does not fail — it calls a different region and answers "not found".`);
109
+ }
110
+ const engineId = reasoningEngine.trim();
111
+ return {
112
+ project,
113
+ location: location.trim(),
114
+ engineId,
115
+ parent: `projects/${project}/locations/${location.trim()}/reasoningEngines/${engineId}`,
116
+ };
117
+ }
118
+ /** `process.env` without assuming `process` exists (browser bundles do not have one). */
119
+ function readEnv(name) {
120
+ return typeof process !== 'undefined' && process.env ? process.env[name] : undefined;
121
+ }
122
+ /**
123
+ * The regional host for a location.
124
+ *
125
+ * See the module header: the client's own default is the global host, and
126
+ * these resources are regional. This is the fix, in one line, applied at every
127
+ * construction.
128
+ */
129
+ export function regionalRootUrl(location) {
130
+ return `https://${location}-aiplatform.googleapis.com/`;
131
+ }
132
+ /**
133
+ * Build the REST client, or refuse by name.
134
+ *
135
+ * An injected `_client` short-circuits everything below it, which is how every
136
+ * test in this column runs with no package installed and no credential.
137
+ */
138
+ export function buildAiPlatformClient(adapter, connection, scope) {
139
+ if (connection._client)
140
+ return connection._client;
141
+ let mod;
142
+ if (connection._sdk) {
143
+ mod = connection._sdk;
144
+ }
145
+ else {
146
+ try {
147
+ mod = lazyRequire('@googleapis/aiplatform');
148
+ }
149
+ catch {
150
+ throw new Error(`${adapter} requires the \`@googleapis/aiplatform\` peer dependency.\n` +
151
+ ` Install: npm install @googleapis/aiplatform\n` +
152
+ ` It is the SPLIT per-API package (~27 MB), not the \`googleapis\` mega-package ` +
153
+ `(~209 MB) that carries every Google API for the same generated code.\n` +
154
+ ` It is optional and loaded only when you construct this adapter, so nothing else ` +
155
+ `in this library pays for it.`);
156
+ }
157
+ }
158
+ if (typeof mod.aiplatform !== 'function') {
159
+ throw new Error(`${adapter}: \`@googleapis/aiplatform\` is installed but exports no \`aiplatform\` ` +
160
+ `factory. This adapter is built against the 31.x package — update it, or pass a ` +
161
+ `pre-built client.`);
162
+ }
163
+ const auth = connection.auth ?? defaultAuth(adapter, mod);
164
+ return mod.aiplatform({
165
+ version: AI_PLATFORM_API_VERSION,
166
+ // Never the client's global default — see the module header.
167
+ rootUrl: regionalRootUrl(scope.location),
168
+ auth,
169
+ });
170
+ }
171
+ /**
172
+ * Application Default Credentials, from the SDK's own re-exported auth surface.
173
+ *
174
+ * Taken from `@googleapis/aiplatform` rather than by loading
175
+ * `google-auth-library` separately: the package already carries it, and one
176
+ * load is one version to reason about instead of two that can drift apart.
177
+ */
178
+ function defaultAuth(adapter, mod) {
179
+ const GoogleAuth = mod.auth?.GoogleAuth;
180
+ if (typeof GoogleAuth !== 'function') {
181
+ throw new Error(`${adapter}: \`@googleapis/aiplatform\` exposes no \`auth.GoogleAuth\`, so Application ` +
182
+ `Default Credentials cannot be resolved.\n` +
183
+ ` Pass 'auth' with your own GoogleAuth / OAuth2Client, or update the package.`);
184
+ }
185
+ return new GoogleAuth({ scopes: [CLOUD_PLATFORM_SCOPE] });
186
+ }
187
+ // ─── Long-running operations ─────────────────────────────────────────
188
+ /** How long {@link awaitOperation} keeps waiting before it refuses, by default. */
189
+ export const DEFAULT_OPERATION_TIMEOUT_MS = 30_000;
190
+ /** One server-side wait, in the duration spelling the API takes. */
191
+ const WAIT_SLICE = '10s';
192
+ /**
193
+ * Wait for a long-running operation to finish, or refuse by name.
194
+ *
195
+ * ── Why any of this exists ──────────────────────────────────────────────────
196
+ * `sessions.create`, `sessions.delete`, `memories.create`, `memories.patch`
197
+ * and `memories.delete` **all answer with an Operation, not with the resource**
198
+ * — verified against the installed package's own return types before a line of
199
+ * either adapter was written. `get`, `list`, `patch`-on-a-session and
200
+ * `retrieve` are the synchronous ones.
201
+ *
202
+ * That asymmetry is the trap: a `put` that returns as soon as the service
203
+ * accepts the request, followed by a `get`, is a race that passes on a warm
204
+ * day and fails under load — and fails by answering "no data", which is
205
+ * indistinguishable from the truth. So every write in this column goes through
206
+ * here and does not return until the service says `done`.
207
+ *
208
+ * An operation that finished with an error is raised as one. The operation's
209
+ * own message is a Google-side description of OUR request, so it is subject to
210
+ * the same secrecy law as everything else here: the code comes through, the
211
+ * text does not.
212
+ */
213
+ export async function awaitOperation(adapter, operations, operation, what, timeoutMs = DEFAULT_OPERATION_TIMEOUT_MS) {
214
+ if (operation === undefined)
215
+ return;
216
+ // Some services answer an already-finished operation on the first call. That
217
+ // is the common case for a small write, and it costs no round trip.
218
+ if (operation.done === true) {
219
+ throwIfOperationFailed(adapter, operation, what);
220
+ return;
221
+ }
222
+ const name = operation.name;
223
+ if (typeof name !== 'string' || name === '') {
224
+ // Nothing to wait ON. Answering as though the write had landed would be
225
+ // exactly the silent success this whole function exists to prevent.
226
+ throw operationError(`${adapter}: ${what} was accepted but the service returned an operation with no name, ` +
227
+ `so there is nothing to wait on and no way to confirm the write landed.\n` +
228
+ ` Refusing rather than reporting a success this adapter cannot verify.`);
229
+ }
230
+ const deadline = Date.now() + Math.max(0, timeoutMs);
231
+ let current = operation;
232
+ while (current.done !== true) {
233
+ if (Date.now() >= deadline) {
234
+ throw operationError(`${adapter}: ${what} did not finish within ${timeoutMs}ms.\n` +
235
+ ` The operation is still running on Google's side — it may yet succeed — but this ` +
236
+ `call will not report a write it has not seen land.\n` +
237
+ ` Raise the adapter's 'operationTimeoutMs' if your engine is routinely slower.`);
238
+ }
239
+ const answer = await operations.wait({ name, timeout: WAIT_SLICE });
240
+ current = answer?.data ?? {};
241
+ }
242
+ throwIfOperationFailed(adapter, current, what);
243
+ }
244
+ function throwIfOperationFailed(adapter, operation, what) {
245
+ const error = operation.error;
246
+ if (error === null || error === undefined)
247
+ return;
248
+ const code = typeof error.code === 'number' ? ` (code ${error.code})` : '';
249
+ throw operationError(`${adapter}: ${what} failed${code}.\n` +
250
+ ` The operation's own message is withheld: it is Google's description of OUR request, ` +
251
+ `and this request carried conversation state. Check Cloud Logging for the full text.`);
252
+ }
253
+ /**
254
+ * The name every refusal from this function carries.
255
+ *
256
+ * It exists so a caller's `catch` can tell "the operation went wrong" — which
257
+ * is already sanitized and already says what to do — apart from "the transport
258
+ * went wrong", which still needs {@link googleSdkFailure} run over it. Without
259
+ * the distinction an adapter re-wraps its own refusal and replaces a precise
260
+ * diagnosis ("did not finish within 30000ms") with a generic one.
261
+ */
262
+ export const OPERATION_ERROR_NAME = 'GoogleOperationError';
263
+ function operationError(message) {
264
+ const err = new Error(message);
265
+ err.name = OPERATION_ERROR_NAME;
266
+ return err;
267
+ }
268
+ /**
269
+ * Has this error already been sanitized by this module? Used by every adapter's
270
+ * `catch` so a refusal is reported once rather than wrapped twice.
271
+ */
272
+ export function isSanitizedGoogleError(err) {
273
+ return (err instanceof Error && (err.name === OPERATION_ERROR_NAME || err.name === 'GoogleApiError'));
274
+ }
275
+ // ─── Failures ────────────────────────────────────────────────────────
276
+ /**
277
+ * Re-raise a failed REST call **without its text** — the `sdkFailure` law from
278
+ * the AWS identity adapter, re-aimed at a Gaxios error.
279
+ *
280
+ * What comes through is the part that is both safe and actionable: which
281
+ * operation failed and the HTTP status. What does not is the message, because
282
+ * a REST client echoes the request into its failure text and these requests
283
+ * carry a whole conversation's state, a user id, and an access token in the
284
+ * headers. A thrown message here reaches the LLM as a tool result AND rides the
285
+ * event stream to every sink attached to the agent.
286
+ *
287
+ * **The original is deliberately not attached as `cause`** — a cause travels
288
+ * with the error into every serializer that walks own properties, which would
289
+ * undo all of this in one `JSON.stringify`.
290
+ */
291
+ export function googleSdkFailure(adapter, operation, err) {
292
+ const status = httpStatusOf(err);
293
+ const failure = new Error(`${adapter}: ${operation} failed` +
294
+ (status === undefined ? '' : ` (HTTP ${status})`) +
295
+ `.\n The SDK's own message is withheld: this request carried session state and an ` +
296
+ `access token, and REST clients echo request detail into failure text. Check Cloud ` +
297
+ `Logging for the full error.`);
298
+ failure.name = 'GoogleApiError';
299
+ return failure;
300
+ }
301
+ /**
302
+ * The HTTP status of a failed call, wherever this client happened to put it.
303
+ *
304
+ * Three places rather than one because the client reports a transport failure,
305
+ * an API error and a thrown `GaxiosError` slightly differently, and a
306
+ * classification that only reads one of them silently stops classifying the
307
+ * day the client is upgraded.
308
+ */
309
+ export function httpStatusOf(err) {
310
+ const e = err;
311
+ if (e === null || typeof e !== 'object')
312
+ return undefined;
313
+ for (const candidate of [e.status, e.code, e.response?.status]) {
314
+ if (typeof candidate === 'number' && Number.isFinite(candidate))
315
+ return candidate;
316
+ // Gaxios sometimes reports the status as a numeric STRING.
317
+ if (typeof candidate === 'string' && /^\d{3}$/.test(candidate))
318
+ return Number(candidate);
319
+ }
320
+ return undefined;
321
+ }
322
+ /** Is this the service's "no such resource"? */
323
+ export function isNotFound(err) {
324
+ return httpStatusOf(err) === 404;
325
+ }
326
+ /** Is this "a resource by that name already exists"? */
327
+ export function isAlreadyExists(err) {
328
+ return httpStatusOf(err) === 409;
329
+ }
330
+ // ─── Ids ─────────────────────────────────────────────────────────────
331
+ /** The longest a resource id may be in both collections this column writes to. */
332
+ export const MAX_RESOURCE_ID_LENGTH = 63;
333
+ /**
334
+ * The id grammar this column really has to satisfy — the INTERSECTION of the
335
+ * two documented rules, so one function is right for both callers and neither
336
+ * has to remember which is stricter: `[a-z0-9-]`, first character a letter,
337
+ * last character a letter or a digit.
338
+ *
339
+ * Exported so the surface pin can hold it against the installed package's own
340
+ * words rather than against this file's memory of them.
341
+ */
342
+ export const LEGAL_RESOURCE_ID = /^[a-z]$|^[a-z][a-z0-9-]*[a-z0-9]$/;
343
+ /**
344
+ * Turn caller data into a resource id the service will accept — and never into
345
+ * a DIFFERENT caller's id.
346
+ *
347
+ * ── The grammar, quoted rather than guessed ─────────────────────────────────
348
+ * This function used to state that "Vertex resource ids accept `[A-Za-z0-9_-]`".
349
+ * That is a Google-wide habit and it is not what either collection this column
350
+ * writes to documents. From the installed package (`@googleapis/aiplatform`
351
+ * 31.0.0, `build/v1.d.ts`), verbatim:
352
+ *
353
+ * `memoryId` — "This value may be up to 63 characters, and valid characters
354
+ * are `[a-z0-9-]`. The first character must be a letter, and
355
+ * the last character must be a letter or number."
356
+ * `sessionId` — "This value may be up to 63 characters, and valid characters
357
+ * are `[a-z0-9-]`. The first and last characters must be a
358
+ * letter or number."
359
+ *
360
+ * So UPPERCASE and `_` are illegal in both, and a leading digit is illegal for
361
+ * a memory. Under the old grammar a UUID entry id (leading digit) and a ULID
362
+ * session id (uppercase Crockford base32) — two of the most ordinary id shapes
363
+ * there are — went to the wire unchanged, to be refused by Google with a 400
364
+ * whose text {@link googleSdkFailure} then withholds. A grammar error the
365
+ * adapter could have caught locally, delivered as a censored 400, is the one
366
+ * place the secrecy law and the teaching-refusal law collide; the fix is to not
367
+ * send it. The surface pin reads those two sentences out of the installed
368
+ * `.d.ts` and checks them against {@link LEGAL_RESOURCE_ID}, so this cannot
369
+ * drift back to a guess.
370
+ *
371
+ * ── Why a hash and not just a fold ──────────────────────────────────────────
372
+ * Lowercasing and substituting are LOSSY: `Alice` folds onto `alice`, `a_b`
373
+ * onto `a-b`. Two ids that folded together would be ONE row, which is the same
374
+ * silent overwrite this column's addressing law exists to prevent. So the
375
+ * readable fast path is taken only when the caller's id already is a legal id
376
+ * byte for byte; anything the fold touched — or that overruns 63 characters —
377
+ * is carried by a {@link fingerprint} of the ORIGINAL, which keeps distinct
378
+ * inputs distinct.
379
+ */
380
+ export function safeResourceId(raw, max = MAX_RESOURCE_ID_LENGTH) {
381
+ const slug = raw.toLowerCase().replace(/[^a-z0-9-]/g, '-');
382
+ if (slug === raw && slug.length <= max && LEGAL_RESOURCE_ID.test(slug))
383
+ return slug;
384
+ const suffix = fingerprint(raw);
385
+ const room = max - suffix.length - 1;
386
+ if (room < 2) {
387
+ // Returning something longer than `max` would be a silently invalid id —
388
+ // refused rather than sent, since only a caller of this function can fix it.
389
+ throw new RangeError(`safeResourceId: max of ${max} leaves no room for the fingerprint that keeps two ` +
390
+ `folded ids apart. The smallest workable bound is ${suffix.length + 3}.`);
391
+ }
392
+ // `id-` rather than the bare slug: the first character must be a LETTER, and
393
+ // the fold cannot promise one. The fingerprint is base36, so the last
394
+ // character is a letter or a digit by construction — which also makes this
395
+ // function IDEMPOTENT: its own output is a legal id and comes back unchanged.
396
+ // `agentEngineSessions.listByUser` relies on that, since it hands composed
397
+ // resource ids back to callers who feed them to `hydrate`.
398
+ const head = `id-${slug}`.slice(0, room).replace(/-+$/, '');
399
+ return `${head}-${suffix}`;
400
+ }
401
+ /**
402
+ * A stable fingerprint of a string, in `[0-9a-z-]`.
403
+ *
404
+ * TWO FNV-1a lanes rather than one, because of what this hash is now asked to
405
+ * carry: it is the only thing keeping two ids apart once the fold has run them
406
+ * together, and it is half of how `memoryBankStore` addresses one identity's
407
+ * memories apart from another's. A single 32-bit lane collides at around one
408
+ * chance in a hundred across ten thousand ids, which is too often for either
409
+ * job; two lanes cost one more multiply per character and make it negligible.
410
+ *
411
+ * It is a fingerprint, not a security boundary — a colliding address is still
412
+ * refused by the scope check that runs before every read and every overwrite.
413
+ */
414
+ export function fingerprint(value) {
415
+ let a = 0x811c9dc5;
416
+ let b = 0x01000193;
417
+ for (let i = 0; i < value.length; i++) {
418
+ const code = value.charCodeAt(i);
419
+ a = Math.imul(a ^ code, 0x01000193);
420
+ b = Math.imul(b ^ code, 0x85ebca6b);
421
+ }
422
+ return `${(a >>> 0).toString(36)}-${(b >>> 0).toString(36)}`;
423
+ }
424
+ //# sourceMappingURL=aiPlatform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aiPlatform.js","sourceRoot":"","sources":["../../../../src/adapters/google/aiPlatform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * agentEngineSessions — conversations in Vertex AI's own session service, so a
3
+ * fleet shares them.
4
+ *
5
+ * `memorySessions()` loses everything on restart and says so. `sqliteSessions()`
6
+ * survives a restart on ONE machine and says so. The row above both — *many
7
+ * containers, one conversation* — is where a managed session service belongs,
8
+ * and on this column that service is the `sessions` collection under a
9
+ * reasoning engine.
10
+ *
11
+ * ── The name, said once ─────────────────────────────────────────────────────
12
+ * The product was **Agent Engine**, is now **Agent Runtime**, and the API
13
+ * resource is still spelled `reasoningEngines`. This factory keeps the name it
14
+ * was designed under; where the product name and the API disagree, the API is
15
+ * the one that has not moved.
16
+ *
17
+ * ── The fit, and it is a good one ───────────────────────────────────────────
18
+ * `Session.sessionState` is an arbitrary JSON `Struct`. A `CheckpointEnvelope`
19
+ * is arbitrary JSON. So the envelope goes in whole, under one key, and comes
20
+ * back whole — no event log to fold, no blob encoding to get wrong, no
21
+ * per-turn append. That is a materially better fit than the other column's
22
+ * session store, which had to learn the hard way that an object handed to an
23
+ * event blob comes back as somebody else's `toString()`.
24
+ *
25
+ * ── The four facts that shaped the code, all read off the installed SDK ─────
26
+ * 1. **`sessions.create` takes a caller-supplied `sessionId`.** So our session
27
+ * id IS the resource id and `hydrate` is one `get` by name. No mapping
28
+ * table, no listing to find a conversation.
29
+ * 2. **`create` and `delete` answer a long-running Operation; `get` and
30
+ * `patch` answer the Session.** Every write here therefore waits for the
31
+ * operation to report `done` before it returns — a `persist` that returned
32
+ * early would make the very next `hydrate` a race whose failure mode is
33
+ * "no conversation", which nobody can tell from a new user.
34
+ * 3. **`Session.userId` is required and immutable.** Our port's
35
+ * `persist(sessionId, envelope)` carries no user, so one has to be
36
+ * resolved — see {@link AgentEngineSessionsOptions.userId}. Immutable
37
+ * means the first write decides forever, which is exactly the ownership
38
+ * rule this library already enforces in its own stores; here the service
39
+ * enforces it for us.
40
+ * 4. **`ttl` is input-only with a 24-hour floor**, and `expireTime` always
41
+ * comes back. Sliding expiry is free; an hour-long TTL is not available at
42
+ * any price.
43
+ *
44
+ * ── The laws it inherits rather than re-implements ──────────────────────────
45
+ * `checkEnvelope` runs on the way OUT and on the way IN, so an envelope whose
46
+ * `format` this runtime does not know is refused by name, and a session that
47
+ * is PRESENT but unreadable is refused by name too. Only a session that was
48
+ * never written hydrates as `undefined`. A conversation that exists and cannot
49
+ * be read must never be answered with a fresh start — that failure is
50
+ * indistinguishable, from the outside, from a brand-new user.
51
+ */
52
+ import type { CheckpointEnvelope, SessionLifecycle } from '../../hosting/types.js';
53
+ import { type AiPlatformConnection } from '../google/aiPlatform.js';
54
+ /**
55
+ * The `sessionState` key the envelope lives under.
56
+ *
57
+ * One key, namespaced, rather than spreading the envelope's own fields across
58
+ * `sessionState`: the struct belongs to whoever owns the reasoning engine, an
59
+ * agent framework is a guest in it, and a guest that scatters `format` and
60
+ * `data` at the top level collides with the next guest. Namespacing also makes
61
+ * the console readable — one entry that says whose it is.
62
+ */
63
+ export declare const SESSION_STATE_KEY = "agentfootprint.envelope";
64
+ /** Options for {@link agentEngineSessions}. */
65
+ export interface AgentEngineSessionsOptions extends AiPlatformConnection {
66
+ /**
67
+ * WHO a session belongs to — required by the service on create, and
68
+ * **immutable** once written.
69
+ *
70
+ * The port hands `persist` a session id and an envelope, never a user, so
71
+ * this is where the missing half comes from. Two spellings:
72
+ *
73
+ * - a **function**, called with the session id and the envelope about to be
74
+ * stored. The recommended shape: return `envelopeOwner(envelope)` — the
75
+ * principal the conversation itself was signed with — so the service's
76
+ * idea of the owner and this library's own ownership index agree by
77
+ * construction rather than by coincidence. That is what the default does.
78
+ * - a **string**, when every conversation in this engine belongs to one
79
+ * service identity. Honest for a single-tenant deployment and wrong the
80
+ * moment it is not, which is why it is not the default.
81
+ *
82
+ * The default resolver reads the envelope's own principal and falls back to
83
+ * {@link DEFAULT_USER_ID} for a conversation that ran anonymously. It never
84
+ * invents a per-session user id: the service treats `userId` as the thing
85
+ * you filter a listing by, and minting a unique one per session would make
86
+ * every listing return exactly one row and look like it worked.
87
+ */
88
+ readonly userId?: string | ((sessionId: string, envelope: CheckpointEnvelope) => string);
89
+ /**
90
+ * How long a session lives after its last write, as a duration string the
91
+ * API accepts (`'86400s'`). **The service's own floor is 24 hours** and it
92
+ * rejects anything shorter, so this is a knob for keeping conversations
93
+ * LONGER, never for expiring them sooner.
94
+ *
95
+ * Omit and no `ttl` is sent, which leaves the service's own default
96
+ * expiry in charge.
97
+ */
98
+ readonly ttl?: string;
99
+ /**
100
+ * How long a write waits for its long-running operation before refusing.
101
+ * Default {@link DEFAULT_OPERATION_TIMEOUT_MS} (30s).
102
+ *
103
+ * It refuses rather than returning: a `persist` that reported success on an
104
+ * operation it never saw finish is a conversation that may or may not be
105
+ * there next turn.
106
+ */
107
+ readonly operationTimeoutMs?: number;
108
+ }
109
+ /** What a conversation that named nobody is stored under. */
110
+ export declare const DEFAULT_USER_ID = "agentfootprint-anonymous";
111
+ /**
112
+ * A session store in Vertex AI's session service.
113
+ *
114
+ * It is a {@link SessionLifecycle} plus the two things a real store owns beyond
115
+ * the port — forgetting, and closing — because the port deliberately asks for
116
+ * two methods and leaves the rest to whoever implements it.
117
+ */
118
+ export interface AgentEngineSessions extends SessionLifecycle {
119
+ /** The resource these sessions live under. Useful in an incident. */
120
+ readonly parent: string;
121
+ /** Forget one session. A session that was never there is not an error. */
122
+ forget(sessionId: string): Promise<void>;
123
+ /**
124
+ * Stop using this store. Idempotent, and **final** — reading or writing
125
+ * afterwards refuses by name rather than quietly reconnecting, because a
126
+ * store that reopened behind you would hide a shutdown-ordering bug instead
127
+ * of surfacing it.
128
+ *
129
+ * Nothing is torn down on Google's side: the sessions outlive this process,
130
+ * which is the entire reason to use a managed store.
131
+ */
132
+ close(): void;
133
+ }
134
+ /**
135
+ * Conversations in Vertex AI's session service — the store that survives a
136
+ * fleet, not just a restart.
137
+ *
138
+ * **Status: contract-shaped and tested; awaiting field use.** Every call is
139
+ * exercised through an injected client and pinned against the really-installed
140
+ * SDK. None of it has yet answered a request from Google in a real project.
141
+ *
142
+ * @example A standing agent whose conversations are shared across instances
143
+ * import { standingAgent, nodeHost } from 'agentfootprint/hosting';
144
+ * import { agentEngineSessions } from 'agentfootprint/hosting';
145
+ *
146
+ * const handle = await standingAgent({
147
+ * agentFactory: () => buildAgent(),
148
+ * host: nodeHost({ port: 8080 }),
149
+ * sessions: agentEngineSessions({
150
+ * project: 'my-project',
151
+ * location: 'us-central1',
152
+ * reasoningEngine: '1234567890',
153
+ * }),
154
+ * });
155
+ */
156
+ export declare function agentEngineSessions(options: AgentEngineSessionsOptions): AgentEngineSessions;