melchizedek-agents 1.7.0 → 1.10.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 (57) hide show
  1. package/CHANGELOG.md +161 -1
  2. package/DOCUMENTATION.md +77 -10
  3. package/README.md +2 -0
  4. package/config/agents/syndicate.schema.json +69 -0
  5. package/config/agents/syndicateSchema.yaml +17 -0
  6. package/db/hardening.sql +3 -1
  7. package/db/migrations/0016_span_tree.sql +52 -0
  8. package/db/migrations/0017_cache_pricing.sql +146 -0
  9. package/db/migrations/0018_queue_view.sql +82 -0
  10. package/db/telemetry.sql +36 -8
  11. package/dist/lib/a2a/app.d.ts +26 -4
  12. package/dist/lib/a2a/app.js +41 -6
  13. package/dist/lib/a2a/executor.d.ts +28 -1
  14. package/dist/lib/a2a/executor.js +65 -2
  15. package/dist/lib/a2a/feedback.d.ts +121 -0
  16. package/dist/lib/a2a/feedback.js +219 -0
  17. package/dist/lib/a2a/policy.d.ts +55 -5
  18. package/dist/lib/a2a/policy.js +56 -12
  19. package/dist/lib/compile.d.ts +2 -0
  20. package/dist/lib/compile.js +2 -0
  21. package/dist/lib/compileNative.js +2 -0
  22. package/dist/lib/doctor.d.ts +10 -0
  23. package/dist/lib/doctor.js +33 -4
  24. package/dist/lib/index.d.ts +6 -2
  25. package/dist/lib/index.js +3 -0
  26. package/dist/lib/loadSyndicate.d.ts +14 -0
  27. package/dist/lib/loadSyndicate.js +22 -5
  28. package/dist/lib/memory/providers.js +7 -3
  29. package/dist/lib/observability/lineage.d.ts +19 -0
  30. package/dist/lib/observability/lineage.js +31 -0
  31. package/dist/lib/observability/metadata.d.ts +69 -0
  32. package/dist/lib/observability/metadata.js +153 -0
  33. package/dist/lib/observability/otlpFilter.js +1 -0
  34. package/dist/lib/observability/supabaseSpanExporter.d.ts +31 -2
  35. package/dist/lib/observability/supabaseSpanExporter.js +45 -6
  36. package/dist/lib/observability/tracer.d.ts +17 -1
  37. package/dist/lib/observability/tracer.js +61 -3
  38. package/dist/lib/project.d.ts +116 -0
  39. package/dist/lib/project.js +274 -0
  40. package/dist/lib/runtime/native/compaction.js +7 -3
  41. package/dist/lib/runtime/native/request.d.ts +2 -0
  42. package/dist/lib/runtime/native/step.js +1 -1
  43. package/dist/lib/runtime/native/telemetry.d.ts +10 -3
  44. package/dist/lib/runtime/native/telemetry.js +49 -4
  45. package/dist/lib/runtime/syndicateTurn.js +5 -1
  46. package/dist/lib/storage/postgres/index.d.ts +10 -0
  47. package/dist/lib/storage/postgres/index.js +6 -1
  48. package/dist/lib/syndicateSchema.d.ts +5 -0
  49. package/dist/lib/syndicateSchema.js +13 -0
  50. package/dist/lib/tools/taskTools.d.ts +6 -0
  51. package/dist/lib/tools/taskTools.js +24 -5
  52. package/dist/lib/workflow/toolNode.d.ts +1 -0
  53. package/dist/lib/workflow/toolNode.js +1 -1
  54. package/dist/scripts/a2a_server.js +3 -3
  55. package/dist/scripts/doctor.js +2 -1
  56. package/dist/scripts/mcp_server.js +2 -1
  57. package/package.json +6 -4
@@ -282,6 +282,28 @@ export function applyFinish(store, id, outcome) {
282
282
  job.error = outcome.error.slice(0, 1_000);
283
283
  }
284
284
  }
285
+ /** A failed or cancelled job made new again: no attempts, no error, no finish time. */
286
+ function resetForRetry(t) {
287
+ t.attempts = 0;
288
+ delete t.error;
289
+ delete t.finished_at;
290
+ }
291
+ /**
292
+ * The retry rule (every backend; an operator's Retry and task_update's
293
+ * `queued` alike): a failed or cancelled background job goes back to the
294
+ * queue with its attempts reset. Anything else is left alone.
295
+ */
296
+ export function applyRetry(store, id) {
297
+ const job = store.tasks.find((t) => t.id === id);
298
+ if (!job)
299
+ return 'not-found';
300
+ if (job.kind !== 'background' || !['failed', 'cancelled'].includes(job.status))
301
+ return 'not-retryable';
302
+ resetForRetry(job);
303
+ job.status = 'queued';
304
+ job.updated_at = now();
305
+ return 'queued';
306
+ }
285
307
  /** The interrupted-job rule for one record: back to the queue, or failed. */
286
308
  export function applyInterrupted(t) {
287
309
  t.updated_at = now();
@@ -470,11 +492,8 @@ export const taskUpdateContract = defineTool({
470
492
  if (status === 'queued' && !['failed', 'cancelled'].includes(task.status)) {
471
493
  return `Error: only a failed or cancelled job can be queued again; ${id} is ${task.status}.`;
472
494
  }
473
- if (status === 'queued') {
474
- task.attempts = 0;
475
- delete task.error;
476
- delete task.finished_at;
477
- }
495
+ if (status === 'queued')
496
+ resetForRetry(task);
478
497
  }
479
498
  task.status = status;
480
499
  }
@@ -76,6 +76,7 @@ export interface ToolNodeContext extends Pick<ToolContextInit, 'appName' | 'user
76
76
  traceCall?: (call: {
77
77
  id: string;
78
78
  name: string;
79
+ args?: unknown;
79
80
  }, tool: unknown, run: () => Promise<unknown>) => Promise<unknown>;
80
81
  }
81
82
  /**
@@ -161,7 +161,7 @@ export async function runToolNode(node, run, context) {
161
161
  let error;
162
162
  const invoke = () => runOwnTool(resolved.own, args, call);
163
163
  try {
164
- response = await (context.traceCall ? context.traceCall({ id: functionCallId, name: resolved.name }, resolved.own, invoke) : invoke());
164
+ response = await (context.traceCall ? context.traceCall({ id: functionCallId, name: resolved.name, args }, resolved.own, invoke) : invoke());
165
165
  }
166
166
  catch (e) {
167
167
  // handleFunctionCallList: an Error's message, any other throw as it is.
@@ -97,7 +97,6 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
97
97
  */
98
98
  import { randomBytes } from 'node:crypto';
99
99
  import { readdirSync, realpathSync, writeFileSync } from 'node:fs';
100
- import path from 'node:path';
101
100
  import { pathToFileURL } from 'node:url';
102
101
  import { createA2AApp } from '../lib/a2a/app.js';
103
102
  import { callerTokens, firstOf, hashCallerToken, jwtIdentity, parseCallers, sharedSecret, trustedHeader, } from '../lib/a2a/identity.js';
@@ -116,6 +115,7 @@ import { callbackIdentity, callbackIdentityProblem, oauthServerSetup } from '../
116
115
  import { postgresCredentialRows } from '../lib/storage/postgres/credentialStore.js';
117
116
  import { setOAuthHosts } from '../lib/tools/oauthHosts.js';
118
117
  import { setCredentialHosts } from '../lib/tools/credentialHosts.js';
118
+ import { resolveAgentsDir } from '../lib/project.js';
119
119
  // Re-exported for existing importers (tests/failNarration.test.ts).
120
120
  export { describeTurnError } from '../lib/a2a/executor.js';
121
121
  /** Minimum bearer-secret length below which the server warns. */
@@ -181,7 +181,7 @@ export function servedFileSyndicates(syndicateName, servedAgents, registryAgents
181
181
  add(id);
182
182
  }
183
183
  else {
184
- const agentsDir = path.resolve(process.env.MELCHIZEDEK_AGENTS_DIR ?? path.join(process.cwd(), 'config', 'agents'));
184
+ const agentsDir = resolveAgentsDir();
185
185
  let names = [];
186
186
  try {
187
187
  names = readdirSync(agentsDir);
@@ -633,7 +633,7 @@ if (invokedAsMain) {
633
633
  if (error?.code === 'ENOENT') {
634
634
  console.error(`[A2A] Syndicate not found: ${arg || 'syndicate.yaml'}.\n`
635
635
  + ' Pass your syndicate: melchizedek-serve <name>.yaml\n'
636
- + ' (agents directory: MELCHIZEDEK_AGENTS_DIR, or <cwd>/config/agents)');
636
+ + ' (agents directory: MELCHIZEDEK_AGENTS_DIR, else the agents folder in melchizedek.json, else <cwd>/config/agents)');
637
637
  process.exit(1);
638
638
  }
639
639
  console.error(error);
@@ -33,6 +33,7 @@ import { loadEnv } from '../lib/loadEnv.js';
33
33
  import { checkProblems, renderDoctor, runDoctor } from '../lib/doctor.js';
34
34
  import { renderCapabilityMatrix } from '../lib/models/capabilities.js';
35
35
  import { assignMemoryNamespace, LEGACY_MEMORY_APP_NAME } from '../lib/memory/namespace.js';
36
+ import { resolveAgentsDir } from '../lib/project.js';
36
37
  loadEnv();
37
38
  const args = process.argv.slice(2);
38
39
  const json = args.includes('--json');
@@ -52,7 +53,7 @@ function packageScripts() {
52
53
  if (fixAt !== -1) {
53
54
  // ADR 0020: give each named long-term syndicate its own memory namespace.
54
55
  // Only the files named are touched; with none named, list the candidates.
55
- const agentsDir = path.resolve(process.env.MELCHIZEDEK_AGENTS_DIR ?? path.join(process.cwd(), 'config', 'agents'));
56
+ const agentsDir = resolveAgentsDir();
56
57
  const files = args.slice(fixAt + 1).filter((a) => !a.startsWith('--'));
57
58
  if (files.length === 0) {
58
59
  const pending = runDoctor({ agentsDir }).syndicates.filter((s) => s.memory && !s.memory.declared && !s.file.includes('/'));
@@ -38,6 +38,7 @@
38
38
  import { readdirSync, realpathSync } from 'node:fs';
39
39
  import path from 'node:path';
40
40
  import { pathToFileURL } from 'node:url';
41
+ import { resolveAgentsDir } from '../lib/project.js';
41
42
  /** The bin's flags. Throws, naming the flag, on one it does not know. */
42
43
  export function parseMcpArgs(argv) {
43
44
  const out = { syndicates: [], http: false, help: false };
@@ -160,7 +161,7 @@ export async function startMcpServer(argv = process.argv.slice(2)) {
160
161
  const bindings = () => ({
161
162
  current_date: new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }),
162
163
  });
163
- const agentsDir = path.resolve(process.env.MELCHIZEDEK_AGENTS_DIR ?? path.join(process.cwd(), 'config', 'agents'));
164
+ const agentsDir = resolveAgentsDir();
164
165
  let files = args.syndicates.map((id) => (id.endsWith('.yaml') || id.endsWith('.yml') ? id : `${id}.yaml`));
165
166
  const named = files.length > 0;
166
167
  if (!named) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "melchizedek-agents",
3
- "version": "1.7.0",
3
+ "version": "1.10.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",
@@ -30,9 +30,11 @@
30
30
  "./a2a/remote": "./dist/lib/a2a/remoteAgent.js",
31
31
  "./a2a/identity": "./dist/lib/a2a/identity.js",
32
32
  "./a2a/policy": "./dist/lib/a2a/policy.js",
33
+ "./a2a/feedback": "./dist/lib/a2a/feedback.js",
33
34
  "./a2a/limits": "./dist/lib/a2a/redisLimits.js",
34
35
  "./mcp": "./dist/lib/mcp/server.js",
35
36
  "./registry": "./dist/lib/registry.js",
37
+ "./project": "./dist/lib/project.js",
36
38
  "./server": "./dist/scripts/a2a_server.js",
37
39
  "./guards": "./dist/lib/guards/index.js",
38
40
  "./storage/postgres": "./dist/lib/storage/postgres/index.js",
@@ -148,13 +150,13 @@
148
150
  },
149
151
  "dependencies": {
150
152
  "@a2a-js/sdk": "^1.3.0",
151
- "@anthropic-ai/sdk": "^0.131.0",
153
+ "@anthropic-ai/sdk": "^0.135.0",
152
154
  "@google/genai": "2.27.0",
153
155
  "@jitl/quickjs-wasmfile-release-sync": "0.32.0",
154
156
  "@modelcontextprotocol/sdk": "^1.32.1",
155
157
  "@opentelemetry/api": "^1.9.1",
156
158
  "@opentelemetry/core": "^2.8.0",
157
- "@opentelemetry/exporter-trace-otlp-http": "^0.222.0",
159
+ "@opentelemetry/exporter-trace-otlp-http": "^0.223.0",
158
160
  "@opentelemetry/resources": "^2.7.1",
159
161
  "@opentelemetry/sdk-trace-base": "^2.7.1",
160
162
  "@opentelemetry/sdk-trace-node": "^2.7.1",
@@ -166,7 +168,7 @@
166
168
  "pg": "^8.23.1",
167
169
  "quickjs-emscripten-core": "0.32.0",
168
170
  "yaml": "^2.9.0",
169
- "zod": "4.6.5"
171
+ "zod": "^4.6.7"
170
172
  },
171
173
  "devDependencies": {
172
174
  "@electric-sql/pglite": "^0.5.10",