melchizedek-agents 1.3.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +15 -0
- package/CHANGELOG.md +134 -0
- package/DOCUMENTATION.md +61 -5
- package/ONBOARDING.md +3 -3
- package/README.md +1 -0
- package/config/agents/examples/connectors.yaml +4 -1
- package/config/agents/examples/event_assistant.yaml +82 -0
- package/config/agents/syndicate.schema.json +80 -6
- package/db/hardening.sql +38 -12
- package/dist/lib/a2a/app.js +2 -1
- package/dist/lib/chatgpt/state.js +4 -4
- package/dist/lib/compile.js +15 -2
- package/dist/lib/compileNative.js +1 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/loadSyndicate.js +4 -0
- package/dist/lib/memory/providers.js +2 -1
- package/dist/lib/models/claudeAdapter.js +2 -1
- package/dist/lib/models/credentialSource.d.ts +28 -0
- package/dist/lib/models/credentialSource.js +49 -0
- package/dist/lib/models/endpoints.js +2 -1
- package/dist/lib/models/gateway.js +2 -1
- package/dist/lib/models/gatewayAdapter.js +2 -1
- package/dist/lib/models/geminiAdapter.js +2 -1
- package/dist/lib/models/gptAdapter.js +2 -1
- package/dist/lib/models/grokAdapter.js +2 -1
- package/dist/lib/models/kimiAdapter.js +2 -1
- package/dist/lib/models/providerMap.js +3 -2
- package/dist/lib/observability/embeddings.js +2 -1
- package/dist/lib/observability/lineage.js +11 -3
- package/dist/lib/observability/supabaseSpanExporter.d.ts +19 -1
- package/dist/lib/observability/supabaseSpanExporter.js +37 -1
- package/dist/lib/observability/tracer.d.ts +9 -0
- package/dist/lib/observability/tracer.js +45 -0
- package/dist/lib/paths.d.ts +31 -0
- package/dist/lib/paths.js +76 -0
- package/dist/lib/runtime/credentials.d.ts +21 -0
- package/dist/lib/runtime/credentials.js +32 -0
- package/dist/lib/runtime/native/delegate.d.ts +2 -0
- package/dist/lib/runtime/native/delegate.js +9 -2
- package/dist/lib/runtime/native/interrupts.d.ts +33 -3
- package/dist/lib/runtime/native/interrupts.js +99 -9
- package/dist/lib/runtime/syndicateTurn.js +41 -11
- package/dist/lib/storage/postgres/index.d.ts +25 -0
- package/dist/lib/storage/postgres/index.js +10 -1
- package/dist/lib/syndicateSchema.d.ts +26 -4
- package/dist/lib/syndicateSchema.js +63 -1
- package/dist/lib/tools/generateImageTool.js +6 -6
- package/dist/lib/tools/inspectImageTool.d.ts +2 -0
- package/dist/lib/tools/inspectImageTool.js +17 -10
- package/dist/lib/tools/mcpToolFactory.d.ts +34 -1
- package/dist/lib/tools/mcpToolFactory.js +200 -27
- package/dist/lib/tools/mcpTransports.d.ts +4 -2
- package/dist/lib/tools/mcpTransports.js +4 -2
- package/dist/lib/tools/taskTools.js +3 -3
- package/dist/lib/tools/xApiSearchTool.js +2 -1
- package/dist/lib/workflow/agentNode.d.ts +19 -3
- package/dist/lib/workflow/agentNode.js +106 -13
- package/dist/lib/workflow/resume.d.ts +8 -7
- package/dist/lib/workflow/resume.js +17 -10
- package/dist/lib/workflow/turn.d.ts +12 -2
- package/dist/lib/workflow/turn.js +22 -12
- package/dist/scripts/a2a_server.js +5 -0
- package/package.json +11 -4
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
*/
|
|
43
43
|
import { z } from 'zod';
|
|
44
44
|
import { APPROVAL_REQUEST } from '../runtime/approvals.js';
|
|
45
|
-
import { CREDENTIAL_REQUEST } from '../runtime/credentials.js';
|
|
45
|
+
import { CREDENTIAL_REQUEST, consentFrom } from '../runtime/credentials.js';
|
|
46
46
|
import { INPUT_REQUEST } from '../workflowConfig.js';
|
|
47
47
|
import { RESPONSE_SCHEMA_ARG } from './pause.js';
|
|
48
48
|
/** The key ADK unwraps a bare reply from: `{ result: <value> }`. */
|
|
@@ -385,18 +385,18 @@ export function resumeInputsFromPlainText(content, events, invocationId) {
|
|
|
385
385
|
// ── What the native walk cannot resume yet ───────────────────────────────────
|
|
386
386
|
/**
|
|
387
387
|
* A pause the native walk cannot resume: one raised inside an agent node
|
|
388
|
-
* other than an approval (an `ask_user` tool
|
|
389
|
-
* inside a map item. ADK resumes those inside the node (the
|
|
390
|
-
* history, the ParallelWorker's item); the native agent node
|
|
391
|
-
* an approval (lib/workflow/agentNode.ts, ADR 0098)
|
|
392
|
-
* others up. Resuming the walk anyway would run the node again from its
|
|
388
|
+
* other than an approval or an OAuth consent request (an `ask_user` tool
|
|
389
|
+
* call) or inside a map item. ADK resumes those inside the node (the
|
|
390
|
+
* agent's own history, the ParallelWorker's item); the native agent node
|
|
391
|
+
* pauses only on an approval (lib/workflow/agentNode.ts, ADR 0098) or a
|
|
392
|
+
* consent request (ADR 0128), so it cannot pick the others up. Resuming the walk anyway would run the node again from its
|
|
393
393
|
* input and ask again, so the resume refuses by name instead.
|
|
394
394
|
*/
|
|
395
395
|
export class UnsupportedWorkflowResumeError extends Error {
|
|
396
396
|
/** The node path the pause was raised at. */
|
|
397
397
|
nodePath;
|
|
398
398
|
constructor(nodePath, why) {
|
|
399
|
-
super(`Cannot resume the workflow on the native runtime: the pause at '${nodePath}' was raised ${why}, which only an ask_user node's pause or an agent node's approval supports here.`);
|
|
399
|
+
super(`Cannot resume the workflow on the native runtime: the pause at '${nodePath}' was raised ${why}, which only an ask_user node's pause or an agent node's approval or consent request supports here.`);
|
|
400
400
|
this.name = 'UnsupportedWorkflowResumeError';
|
|
401
401
|
this.nodePath = nodePath;
|
|
402
402
|
}
|
|
@@ -404,8 +404,9 @@ export class UnsupportedWorkflowResumeError extends Error {
|
|
|
404
404
|
/**
|
|
405
405
|
* Throws UnsupportedWorkflowResumeError for the first interrupt in the run's
|
|
406
406
|
* events that is neither an ask_user node's input request nor an agent
|
|
407
|
-
* node's approval request at a direct child of the workflow
|
|
408
|
-
* own record aside).
|
|
407
|
+
* node's approval or credential request at a direct child of the workflow
|
|
408
|
+
* (the workflow's own record aside). A credential request it cannot read
|
|
409
|
+
* (no paused call's id, no auth config) does not resume.
|
|
409
410
|
*/
|
|
410
411
|
export function assertResumable(runEvents, workflowPath) {
|
|
411
412
|
for (const event of runEvents) {
|
|
@@ -416,7 +417,13 @@ export function assertResumable(runEvents, workflowPath) {
|
|
|
416
417
|
continue;
|
|
417
418
|
if (directChildName(path, workflowPath) === undefined)
|
|
418
419
|
throw new UnsupportedWorkflowResumeError(path || String(event.author ?? ''), 'inside a nested node (a map item)');
|
|
419
|
-
|
|
420
|
+
// A credential request resumes when this engine can read it (consentFrom: the paused call's id and the auth config, ADR 0128).
|
|
421
|
+
const resumable = partsOf(event).some((p) => {
|
|
422
|
+
const call = p.functionCall;
|
|
423
|
+
if (call?.name === INPUT_REQUEST || call?.name === APPROVAL_REQUEST)
|
|
424
|
+
return true;
|
|
425
|
+
return call?.name === CREDENTIAL_REQUEST && consentFrom(event.author, call) !== undefined;
|
|
426
|
+
});
|
|
420
427
|
if (!resumable)
|
|
421
428
|
throw new UnsupportedWorkflowResumeError(path, 'inside an agent node');
|
|
422
429
|
}
|
|
@@ -53,8 +53,10 @@
|
|
|
53
53
|
* WHAT IT REFUSES before any model call: refuseUnrunnableNodes throws, for
|
|
54
54
|
* a tool node, ADK's compile-time refusals (an unregistered tool, a
|
|
55
55
|
* long-running one), and an ADK tool (anything with runAsync), which 1.0.0
|
|
56
|
-
* no longer runs. A pause raised inside an agent node
|
|
57
|
-
* runAgentNode by name.
|
|
56
|
+
* no longer runs. A pause raised inside an agent node other than an
|
|
57
|
+
* approval or an OAuth consent request is refused by runAgentNode by name.
|
|
58
|
+
* The consent step (`consent`) reaches every agent node's loop but a map
|
|
59
|
+
* item's, so a node's tool that needs a grant pauses the walk (ADR 0128).
|
|
58
60
|
*
|
|
59
61
|
* It imports nothing from ADK: the caller passes the tool lookup (the
|
|
60
62
|
* registry's own Tools) and the store as the engine's interface.
|
|
@@ -65,6 +67,7 @@ import type { ModelAdapter } from '../models/contract.ts';
|
|
|
65
67
|
import type { TurnEvent } from '../runtime/events.ts';
|
|
66
68
|
import type { WorkflowSubagentEnd } from '../runtime/native/delegate.ts';
|
|
67
69
|
import type { MemoryService } from '../runtime/memoryService.ts';
|
|
70
|
+
import type { AgentLoopContext } from '../runtime/native/agentLoop.ts';
|
|
68
71
|
import type { NativeAgent } from '../runtime/native/request.ts';
|
|
69
72
|
import type { SelfCorrection } from '../runtime/native/selfCorrection.ts';
|
|
70
73
|
import type { SessionService } from '../runtime/sessions.ts';
|
|
@@ -94,6 +97,13 @@ export interface NativeWorkflowParams {
|
|
|
94
97
|
selfCorrection?: SelfCorrection;
|
|
95
98
|
/** The run's tool credentials, pinned to its app (ADR 0072). */
|
|
96
99
|
credentials?: Pick<CredentialStore, 'get'>;
|
|
100
|
+
/**
|
|
101
|
+
* The consent step for the agent nodes' tools (ADR 0085, ADR 0128), its
|
|
102
|
+
* flows bound to the turn's app (consentPinnedTo): a call whose grant is
|
|
103
|
+
* missing pauses its node, and the walk with it. A nested walk gets it
|
|
104
|
+
* pinned to the app of the walk that runs it. Map items never get it.
|
|
105
|
+
*/
|
|
106
|
+
consent?: AgentLoopContext['consent'];
|
|
97
107
|
/** The agent nodes that are a nested workflow syndicate (ADR 0106) or a nested dispatch syndicate (ADR 0120), by YAML name. */
|
|
98
108
|
workflows?: ReadonlyMap<string, NestedWorkflow | NestedRun>;
|
|
99
109
|
}
|
|
@@ -53,8 +53,10 @@
|
|
|
53
53
|
* WHAT IT REFUSES before any model call: refuseUnrunnableNodes throws, for
|
|
54
54
|
* a tool node, ADK's compile-time refusals (an unregistered tool, a
|
|
55
55
|
* long-running one), and an ADK tool (anything with runAsync), which 1.0.0
|
|
56
|
-
* no longer runs. A pause raised inside an agent node
|
|
57
|
-
* runAgentNode by name.
|
|
56
|
+
* no longer runs. A pause raised inside an agent node other than an
|
|
57
|
+
* approval or an OAuth consent request is refused by runAgentNode by name.
|
|
58
|
+
* The consent step (`consent`) reaches every agent node's loop but a map
|
|
59
|
+
* item's, so a node's tool that needs a grant pauses the walk (ADR 0128).
|
|
58
60
|
*
|
|
59
61
|
* It imports nothing from ADK: the caller passes the tool lookup (the
|
|
60
62
|
* registry's own Tools) and the store as the engine's interface.
|
|
@@ -63,8 +65,9 @@
|
|
|
63
65
|
*/
|
|
64
66
|
import { randomUUID } from 'node:crypto';
|
|
65
67
|
import { APPROVAL_REQUEST } from '../runtime/approvals.js';
|
|
68
|
+
import { CREDENTIAL_REQUEST, isGrantAnswer } from '../runtime/credentials.js';
|
|
66
69
|
import { createTurnEvent, getFunctionCalls } from '../runtime/events.js';
|
|
67
|
-
import { entrySession } from '../runtime/native/delegate.js';
|
|
70
|
+
import { consentPinnedTo, entrySession } from '../runtime/native/delegate.js';
|
|
68
71
|
import { INPUT_REQUEST } from '../workflowConfig.js';
|
|
69
72
|
import { traceNodeExecution, traceToolNodeCall, traceWorkflowInvocation } from '../runtime/native/telemetry.js';
|
|
70
73
|
import { TEMP_STATE_PREFIX } from '../runtime/sessions.js';
|
|
@@ -81,8 +84,8 @@ function lastText(event) {
|
|
|
81
84
|
.filter((t) => t)
|
|
82
85
|
.join('\n');
|
|
83
86
|
}
|
|
84
|
-
/** The requests a walk's interrupts are, as a node raises them: an approval request or an
|
|
85
|
-
const RAISED = new Set([APPROVAL_REQUEST, INPUT_REQUEST]);
|
|
87
|
+
/** The requests a walk's interrupts are, as a node raises them: an approval request, an input request, or an OAuth consent request (ADR 0128). */
|
|
88
|
+
const RAISED = new Set([APPROVAL_REQUEST, INPUT_REQUEST, CREDENTIAL_REQUEST]);
|
|
86
89
|
/** The latest request call, by id, among `ids` that `events` hold (an agent's or a node's, never the user's). */
|
|
87
90
|
function requestCalls(events, ids, author) {
|
|
88
91
|
const wanted = new Set(ids);
|
|
@@ -101,12 +104,15 @@ function requestCalls(events, ids, author) {
|
|
|
101
104
|
/**
|
|
102
105
|
* Whether a resumed walk's answer to `call` answers it: a decision for an
|
|
103
106
|
* approval request (a ToolConfirmation, or ADK's `{ response: <json> }`
|
|
104
|
-
* form, as lib/workflow/agentNode.ts reads one),
|
|
105
|
-
* request.
|
|
107
|
+
* form, as lib/workflow/agentNode.ts reads one), a grant's answer for a
|
|
108
|
+
* credential request, any answer for an input request.
|
|
106
109
|
*/
|
|
107
110
|
function answers(call, value) {
|
|
108
111
|
if (value === undefined || !call)
|
|
109
112
|
return false;
|
|
113
|
+
// A credential request is answered by the grant's answer only (ADR 0128): the turn sends it once the grant is stored.
|
|
114
|
+
if (call.name === CREDENTIAL_REQUEST)
|
|
115
|
+
return isGrantAnswer(value);
|
|
110
116
|
if (call.name !== APPROVAL_REQUEST)
|
|
111
117
|
return true;
|
|
112
118
|
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
@@ -116,7 +122,7 @@ function answers(call, value) {
|
|
|
116
122
|
}
|
|
117
123
|
/** The part that carries `value` down to the nested walk, as the answer to `call`: its explicit reply, under the request's name. */
|
|
118
124
|
function answerPart(call, value) {
|
|
119
|
-
const response = call.name === APPROVAL_REQUEST ? value : { result: value };
|
|
125
|
+
const response = call.name === APPROVAL_REQUEST || call.name === CREDENTIAL_REQUEST ? value : { result: value };
|
|
120
126
|
return { functionResponse: { id: call.id, name: call.name, response } };
|
|
121
127
|
}
|
|
122
128
|
/**
|
|
@@ -172,12 +178,13 @@ function raiseAgain(name, run, invocationId, calls, stateDelta) {
|
|
|
172
178
|
* node, carrying that output and the walk's state writes, so a resumed
|
|
173
179
|
* walk completes the node from it.
|
|
174
180
|
*
|
|
175
|
-
* A walk that ends paused (an ask_user node, a gated agent node, a node
|
|
176
|
-
*
|
|
181
|
+
* A walk that ends paused (an ask_user node, a gated agent node, a node
|
|
182
|
+
* waiting for an OAuth grant (ADR 0128), a node of its own that is a nested
|
|
183
|
+
* workflow) pauses the node on the same ids
|
|
177
184
|
* (raiseAgain), and the caller's walk with it. Rerun on the resume, the
|
|
178
185
|
* node walks its graph again on the answers among its ids, each as its
|
|
179
186
|
* explicit reply (an approval decision as it came, an input request's
|
|
180
|
-
* answer as `{ result }
|
|
187
|
+
* answer as `{ result }`, a grant's answer as it came), which the nested walk's resume reads as a
|
|
181
188
|
* top-level one's; with none of them answered it waits again without
|
|
182
189
|
* walking; once an earlier resume finished it, its stored output is the
|
|
183
190
|
* node's.
|
|
@@ -224,6 +231,8 @@ async function runWorkflowNode(name, workflow, run, params, parent) {
|
|
|
224
231
|
...(params.log ? { log: params.log } : {}),
|
|
225
232
|
...(params.selfCorrection ? { selfCorrection: params.selfCorrection } : {}),
|
|
226
233
|
...(params.credentials ? { credentials: params.credentials } : {}),
|
|
234
|
+
// Its flows bound to the walk's app (already the turn's): the callback stores the grant where the pinned credentials read it (ADR 0128).
|
|
235
|
+
...(params.consent ? { consent: consentPinnedTo(params.consent, parent.session.appName) } : {}),
|
|
227
236
|
});
|
|
228
237
|
let last;
|
|
229
238
|
const stateDelta = {};
|
|
@@ -251,7 +260,7 @@ async function runWorkflowNode(name, workflow, run, params, parent) {
|
|
|
251
260
|
const raised = named ?? requestCalls(walked, paused);
|
|
252
261
|
const missing = paused.filter((id) => !raised.has(id));
|
|
253
262
|
if (missing.length > 0)
|
|
254
|
-
throw new Error(`Node '${name}': the ${'walk' in workflow ? 'syndicate' : 'workflow'} it runs paused on ${missing.join(', ')}, which is not an approval request or a
|
|
263
|
+
throw new Error(`Node '${name}': the ${'walk' in workflow ? 'syndicate' : 'workflow'} it runs paused on ${missing.join(', ')}, which is not an approval request, a question or a consent request.`);
|
|
255
264
|
parent.store(raiseAgain(name, run, parent.invocationId, paused.map((id) => raised.get(id)), stateDelta));
|
|
256
265
|
return { interruptIds: [...paused] };
|
|
257
266
|
}
|
|
@@ -320,6 +329,7 @@ export async function* runNativeWorkflow(params) {
|
|
|
320
329
|
...(params.log ? { log: params.log } : {}),
|
|
321
330
|
...(params.selfCorrection ? { selfCorrection: params.selfCorrection } : {}),
|
|
322
331
|
...(params.credentials ? { credentials: params.credentials } : {}),
|
|
332
|
+
...(params.consent ? { consent: params.consent } : {}),
|
|
323
333
|
},
|
|
324
334
|
onEvent: (event) => {
|
|
325
335
|
// A node's input turn is appended straight to the session, as ADK's runLlmAgentAsNode appends it: stored, never yielded.
|
|
@@ -373,8 +373,13 @@ export async function startServer(syndicateName = 'syndicate.yaml', extensions =
|
|
|
373
373
|
...(positiveInt('DATABASE_POOL_MAX') ? { poolConfig: { max: positiveInt('DATABASE_POOL_MAX') } } : {}),
|
|
374
374
|
...(positiveInt('A2A_TURN_LOCK_POOL_MAX') ? { lockPoolMax: positiveInt('A2A_TURN_LOCK_POOL_MAX') } : {}),
|
|
375
375
|
memory: { apiKey: process.env.GOOGLE_GENAI_API_KEY || process.env.GEMINI_API_KEY || '' },
|
|
376
|
+
// The ledger in this database (ADR 0131): TELEMETRY_POSTGRES=true.
|
|
377
|
+
...(process.env.TELEMETRY_POSTGRES === 'true' ? { ledger: true } : {}),
|
|
376
378
|
})
|
|
377
379
|
: undefined;
|
|
380
|
+
if (process.env.TELEMETRY_POSTGRES === 'true' && !pgStorage) {
|
|
381
|
+
console.warn('[TELEMETRY] TELEMETRY_POSTGRES=true needs DATABASE_URL; no ledger is written.');
|
|
382
|
+
}
|
|
378
383
|
if (!pgStorage && dbSchema() !== 'public') {
|
|
379
384
|
console.error(`[A2A] ✗ MELCHIZEDEK_DB_SCHEMA=${dbSchema()} needs DATABASE_URL: a private schema is not reachable over the Supabase REST API.`);
|
|
380
385
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "melchizedek-agents",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A multi-model, multi-agent orchestration framework — YAML-defined syndicates on the engine's own agent loop, Supabase or Postgres session persistence, pgvector long-term memory. Companion repo to the lyceumagents.com curriculum.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -107,6 +107,10 @@
|
|
|
107
107
|
"syndicate:pipeline": "node --disable-warning=DEP0040 --experimental-strip-types scripts/syndicate_chat.ts --syndicate pipeline",
|
|
108
108
|
"syndicate:weather": "node --disable-warning=DEP0040 --experimental-strip-types scripts/syndicate_chat.ts --syndicate weather",
|
|
109
109
|
"syndicate:conversational": "node --disable-warning=DEP0040 --experimental-strip-types scripts/syndicate_chat.ts --syndicate conversational",
|
|
110
|
+
"syndicate:event": "node --disable-warning=DEP0040 --experimental-strip-types scripts/syndicate_chat.ts --syndicate event_assistant",
|
|
111
|
+
"capstone": "node --disable-warning=DEP0040 --experimental-strip-types examples/capstone/server.ts",
|
|
112
|
+
"capstone:agent": "node --disable-warning=DEP0040 --experimental-strip-types examples/capstone/serve-agent.ts",
|
|
113
|
+
"capstone:eval": "node --disable-warning=DEP0040 --experimental-strip-types examples/capstone/eval/run.ts",
|
|
110
114
|
"assistant:worker": "node --disable-warning=DEP0040 --experimental-strip-types scripts/assistant_worker.ts",
|
|
111
115
|
"demo:models": "node --disable-warning=DEP0040 --experimental-strip-types scripts/demo_model_optionality.ts",
|
|
112
116
|
"demo:direct": "node --disable-warning=DEP0040 --experimental-strip-types scripts/direct_call.ts",
|
|
@@ -152,18 +156,21 @@
|
|
|
152
156
|
"@opentelemetry/sdk-trace-base": "^2.7.1",
|
|
153
157
|
"@opentelemetry/sdk-trace-node": "^2.7.1",
|
|
154
158
|
"@supabase/supabase-js": "^2.43.0",
|
|
155
|
-
"jose": "^6.2.12",
|
|
156
159
|
"express": "^5.2.1",
|
|
157
160
|
"express-rate-limit": "^8.5.2",
|
|
158
|
-
"
|
|
161
|
+
"jose": "^6.2.12",
|
|
159
162
|
"openai": "^7.28.0",
|
|
163
|
+
"pg": "^8.23.1",
|
|
160
164
|
"yaml": "^2.9.0",
|
|
161
165
|
"zod": "4.6.5"
|
|
162
166
|
},
|
|
163
167
|
"devDependencies": {
|
|
164
|
-
"@
|
|
168
|
+
"@electric-sql/pglite": "^0.5.10",
|
|
169
|
+
"@electric-sql/pglite-pgvector": "^0.0.11",
|
|
170
|
+
"@electric-sql/pglite-socket": "^0.2.13",
|
|
165
171
|
"@types/express": "^5.0.6",
|
|
166
172
|
"@types/node": "^25",
|
|
173
|
+
"@types/pg": "^8.23.1",
|
|
167
174
|
"typescript": "^7.0.2"
|
|
168
175
|
},
|
|
169
176
|
"overrides": {
|