melchizedek-agents 1.11.0 → 1.12.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 +53 -10
- package/AGENT_SETUP.md +4 -1
- package/CHANGELOG.md +126 -0
- package/DOCUMENTATION.md +108 -7
- package/ONBOARDING.md +11 -5
- package/QUICKSTART.md +5 -3
- package/README.md +7 -4
- package/config/agents/examples/classifier.yaml +104 -0
- package/config/agents/examples/model_zoo.yaml +5 -0
- package/config/agents/syndicate.schema.json +59 -1
- package/config/agents/syndicateSchema.yaml +9 -1
- package/db/hardening.sql +5 -0
- package/db/migrations/0020_embedding_flash_grok_pricing.sql +38 -0
- package/db/migrations/0021_correct_gemini_flash_grok_rates.sql +46 -0
- package/db/migrations/0022_typesafe_jev_pricing.sql +36 -0
- package/db/migrations/0023_memory_embedder.sql +66 -0
- package/dist/lib/config.d.ts +6 -0
- package/dist/lib/config.js +6 -0
- package/dist/lib/doctor.d.ts +8 -0
- package/dist/lib/doctor.js +17 -0
- package/dist/lib/loadSyndicate.d.ts +1 -1
- package/dist/lib/memory/providers.d.ts +31 -0
- package/dist/lib/memory/providers.js +82 -2
- package/dist/lib/memory/reembed.d.ts +47 -0
- package/dist/lib/memory/reembed.js +71 -0
- package/dist/lib/memory/store.d.ts +22 -0
- package/dist/lib/memory/store.js +33 -0
- package/dist/lib/memory/supabaseMemoryService.d.ts +17 -0
- package/dist/lib/memory/supabaseMemoryService.js +55 -1
- package/dist/lib/model.d.ts +4 -0
- package/dist/lib/model.js +3 -0
- package/dist/lib/models/adapterResolver.js +5 -2
- package/dist/lib/models/capabilities.d.ts +2 -0
- package/dist/lib/models/capabilities.js +28 -6
- package/dist/lib/models/chatCompletionsAdapter.d.ts +6 -1
- package/dist/lib/models/chatCompletionsAdapter.js +35 -6
- package/dist/lib/models/contract.d.ts +7 -1
- package/dist/lib/models/endpoints.d.ts +3 -2
- package/dist/lib/models/endpoints.js +6 -2
- package/dist/lib/models/gateway.d.ts +123 -7
- package/dist/lib/models/gateway.js +204 -22
- package/dist/lib/models/gatewayAdapter.d.ts +17 -6
- package/dist/lib/models/gatewayAdapter.js +28 -10
- package/dist/lib/models/jev.d.ts +190 -0
- package/dist/lib/models/jev.js +316 -0
- package/dist/lib/models/jevAdapter.d.ts +79 -0
- package/dist/lib/models/jevAdapter.js +136 -0
- package/dist/lib/models/providerMap.d.ts +2 -1
- package/dist/lib/models/providerMap.js +4 -0
- package/dist/lib/models/registry.d.ts +3 -3
- package/dist/lib/models/registry.js +11 -4
- package/dist/lib/observability/tracer.d.ts +1 -1
- package/dist/lib/onboarding.js +9 -4
- package/dist/lib/storage/postgres/memoryStore.js +27 -0
- package/dist/lib/syndicateSchema.d.ts +16 -0
- package/dist/lib/syndicateSchema.js +2 -1
- package/dist/lib/tools/credentialEnv.js +1 -1
- package/package.json +2 -1
- package/skills/briefs/melchizedek-author.md +1 -1
- package/skills/briefs/melchizedek-models.md +6 -5
- package/skills/briefs/melchizedek.md +2 -2
- package/skills/melchizedek-onboard/SKILL.md +1 -1
- package/skills/melchizedek-onboard-keys/SKILL.md +2 -2
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# tier: typesafe — needs only TYPESAFE_API_KEY, or one MODEL_GATEWAY key (Vercel AI Gateway or OpenRouter); `npm run doctor` shows what each key unlocks.
|
|
2
|
+
# ============================================================
|
|
3
|
+
# CLASSIFIER — one decision model, typed answers, calibrated confidence.
|
|
4
|
+
# ============================================================
|
|
5
|
+
#
|
|
6
|
+
# JOB: read one inbound support message and decide three things about it:
|
|
7
|
+
# which team it belongs to, how urgent it is, and whether a person must
|
|
8
|
+
# look before anything is sent back. The reply is one JSON object the
|
|
9
|
+
# `output.schema` below describes, so the software that calls this agent
|
|
10
|
+
# acts on fields, never on prose.
|
|
11
|
+
#
|
|
12
|
+
# WHY A DECISION MODEL: `model: jev-latest` is TypeSafe's Jev, a System One
|
|
13
|
+
# model (https://typesafe.ai). It writes no sentences and calls no tool: it
|
|
14
|
+
# answers typed questions with a probability for every option, in about a
|
|
15
|
+
# tenth of a second, at $0.042 per million input tokens and nothing for
|
|
16
|
+
# output. The engine turns this file's schema into Jev's questions
|
|
17
|
+
# (lib/models/jev.ts): a boolean property is a yes/no question, a string
|
|
18
|
+
# whose `oneOf` describes each constant is a choice, an integer whose
|
|
19
|
+
# `oneOf` describes the levels 0, 1, 2 in order is a score. The property's
|
|
20
|
+
# `description` is the question. The instruction below and the message are
|
|
21
|
+
# the state Jev decides about.
|
|
22
|
+
#
|
|
23
|
+
# WHAT COMES BACK: the schema's object, plus a `jev` key holding the raw
|
|
24
|
+
# answers: each question's probabilities and confidence. Act when the
|
|
25
|
+
# confidence is high and route to a person when it is not: that threshold
|
|
26
|
+
# is yours to set in the code that calls this agent, which is the point.
|
|
27
|
+
#
|
|
28
|
+
# {"department":"technical","urgency":2,"needs_human":false,
|
|
29
|
+
# "jev":{"department":{"type":"choice","choice":"technical","confidence":0.91,
|
|
30
|
+
# "probabilities":{"billing":0.03,"technical":0.91,"sales":0.01,"other":0.05}},
|
|
31
|
+
# "urgency":{"type":"score","score":1.8,"confidence":0.8,...},
|
|
32
|
+
# "needs_human":{"type":"noul","noul":0.12}}}
|
|
33
|
+
#
|
|
34
|
+
# ONE FILE, ANY MODEL: change `model:` to gemini-3.5-flash-lite,
|
|
35
|
+
# claude-haiku-5-5 or ollama/qwen3.5:9b and the same schema is answered by a
|
|
36
|
+
# chat model's structured output (the matrix's `structured_output` cell);
|
|
37
|
+
# the `jev` key then does not appear, since a chat model states no
|
|
38
|
+
# probabilities. The doctor shows what each path keeps.
|
|
39
|
+
#
|
|
40
|
+
# NOT A CONVERSATION: memory_system internal-only and includeContents none
|
|
41
|
+
# make every message stand alone; nothing is kept between calls.
|
|
42
|
+
#
|
|
43
|
+
# MAKE IT YOURS: rename the departments and their descriptions, change the
|
|
44
|
+
# urgency levels (up to 10, each described), add a boolean per policy you
|
|
45
|
+
# enforce. Every property must be a decision: a free string, an array or a
|
|
46
|
+
# nested object is refused before any call (TYPESAFE_SCHEMA_UNSUPPORTED),
|
|
47
|
+
# with the shapes Jev takes named in the error.
|
|
48
|
+
# ============================================================
|
|
49
|
+
syndicate_name: "Classifier"
|
|
50
|
+
memory_system: internal-only
|
|
51
|
+
|
|
52
|
+
orchestrator:
|
|
53
|
+
name: "Triage"
|
|
54
|
+
description: "Decides a support message's department, its urgency and whether a person must look, as typed answers with probabilities."
|
|
55
|
+
model: "jev-latest"
|
|
56
|
+
includeContents: none
|
|
57
|
+
instruction: |
|
|
58
|
+
You triage inbound messages for a software company's support desk. Each message was sent by a customer or a prospect through the help form or by email. You decide where it goes and how fast; you do not answer it.
|
|
59
|
+
|
|
60
|
+
Departments:
|
|
61
|
+
- billing handles charges, refunds, invoices, subscriptions and payment methods.
|
|
62
|
+
- technical handles bugs, outages, errors, integrations and anything about how the product behaves.
|
|
63
|
+
- sales handles pricing questions, quotes, upgrades, trials and new accounts.
|
|
64
|
+
- other is anything else: partnerships, press, job applications, spam.
|
|
65
|
+
|
|
66
|
+
Urgency is about the customer's situation, not their tone: an outage or a blocked payment is urgent however calmly it is written; a question with no deadline is not, however angrily.
|
|
67
|
+
|
|
68
|
+
A person must look before any automated reply when the message mentions legal action, a safety or security concern, a complaint about staff, a request to delete an account or data, or when it is unclear which department it belongs to.
|
|
69
|
+
output:
|
|
70
|
+
schema:
|
|
71
|
+
type: object
|
|
72
|
+
properties:
|
|
73
|
+
department:
|
|
74
|
+
type: string
|
|
75
|
+
description: "Which team should handle this message."
|
|
76
|
+
oneOf:
|
|
77
|
+
- const: billing
|
|
78
|
+
description: "Charges, refunds, invoices, subscriptions, payment methods."
|
|
79
|
+
- const: technical
|
|
80
|
+
description: "Bugs, outages, errors, integrations, product behaviour."
|
|
81
|
+
- const: sales
|
|
82
|
+
description: "Pricing, quotes, upgrades, trials, new accounts."
|
|
83
|
+
- const: other
|
|
84
|
+
description: "Partnerships, press, job applications, spam, or nothing above."
|
|
85
|
+
urgency:
|
|
86
|
+
type: integer
|
|
87
|
+
description: "How soon the company must act on this message."
|
|
88
|
+
oneOf:
|
|
89
|
+
- const: 0
|
|
90
|
+
description: "No deadline and nothing blocked: a question or a request that can wait days."
|
|
91
|
+
- const: 1
|
|
92
|
+
description: "Something is inconvenient or a date is near: within a day."
|
|
93
|
+
- const: 2
|
|
94
|
+
description: "Service is down, money is stuck, or a deadline is today: now."
|
|
95
|
+
needs_human:
|
|
96
|
+
type: boolean
|
|
97
|
+
description: "A person must read this message before any automated reply is sent."
|
|
98
|
+
oneOf:
|
|
99
|
+
- const: true
|
|
100
|
+
description: "Legal action, a safety or security concern, a complaint about staff, a deletion request, or an unclear department."
|
|
101
|
+
- const: false
|
|
102
|
+
description: "A routine message a department can answer on its own."
|
|
103
|
+
required: [department, urgency, needs_human]
|
|
104
|
+
mime: "application/json"
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
# kimi-* → Moonshot (MOONSHOT_API_KEY)
|
|
15
15
|
# deepseek-* → DeepSeek (DEEPSEEK_API_KEY)
|
|
16
16
|
#
|
|
17
|
+
# (jev-* → TypeSafe Jev is the eighth provider, and not in this zoo: a
|
|
18
|
+
# decision model answers a schema, never a question in prose. Its proof
|
|
19
|
+
# is classifier.yaml.) With no direct key, one MODEL_GATEWAY key serves
|
|
20
|
+
# every cloud agent here.
|
|
21
|
+
#
|
|
17
22
|
# Run the proof: npm run demo:models (scripts/demo_model_optionality.ts
|
|
18
23
|
# sends "explain quantum mechanics" to every agent whose provider is
|
|
19
24
|
# available, and prints input, thinking, output, and a token/latency trace.
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"model": {
|
|
23
23
|
"type": "string",
|
|
24
24
|
"minLength": 1,
|
|
25
|
-
"description": "Model id; its prefix picks the provider (gemini-*, claude-*, gpt-*/o*, grok-*, ollama/*)."
|
|
25
|
+
"description": "Model id; its prefix picks the provider (gemini-*, claude-*, gpt-*/o*, grok-*, kimi-*, deepseek-*, jev-*, ollama/*)."
|
|
26
26
|
},
|
|
27
27
|
"fallback_model": {
|
|
28
28
|
"description": "A model on another provider that answers when this agent's model fails provider-side (5xx, 429, network) before producing anything, or while that provider's circuit is open (ADR 0044).",
|
|
@@ -448,6 +448,35 @@
|
|
|
448
448
|
}
|
|
449
449
|
]
|
|
450
450
|
},
|
|
451
|
+
"typesafe": {
|
|
452
|
+
"type": "object",
|
|
453
|
+
"properties": {
|
|
454
|
+
"instruction": {
|
|
455
|
+
"description": "Replaces the agent's instruction on this provider.",
|
|
456
|
+
"type": "string",
|
|
457
|
+
"minLength": 1
|
|
458
|
+
},
|
|
459
|
+
"instruction_append": {
|
|
460
|
+
"description": "Appended to the agent's instruction, after a blank line, on this provider.",
|
|
461
|
+
"type": "string",
|
|
462
|
+
"minLength": 1
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
"additionalProperties": false,
|
|
466
|
+
"description": "The instruction on one provider: exactly one of instruction or instruction_append.",
|
|
467
|
+
"oneOf": [
|
|
468
|
+
{
|
|
469
|
+
"required": [
|
|
470
|
+
"instruction"
|
|
471
|
+
]
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
"required": [
|
|
475
|
+
"instruction_append"
|
|
476
|
+
]
|
|
477
|
+
}
|
|
478
|
+
]
|
|
479
|
+
},
|
|
451
480
|
"ollama": {
|
|
452
481
|
"type": "object",
|
|
453
482
|
"properties": {
|
|
@@ -1535,6 +1564,35 @@
|
|
|
1535
1564
|
}
|
|
1536
1565
|
]
|
|
1537
1566
|
},
|
|
1567
|
+
"typesafe": {
|
|
1568
|
+
"type": "object",
|
|
1569
|
+
"properties": {
|
|
1570
|
+
"instruction": {
|
|
1571
|
+
"description": "Replaces the agent's instruction on this provider.",
|
|
1572
|
+
"type": "string",
|
|
1573
|
+
"minLength": 1
|
|
1574
|
+
},
|
|
1575
|
+
"instruction_append": {
|
|
1576
|
+
"description": "Appended to the agent's instruction, after a blank line, on this provider.",
|
|
1577
|
+
"type": "string",
|
|
1578
|
+
"minLength": 1
|
|
1579
|
+
}
|
|
1580
|
+
},
|
|
1581
|
+
"additionalProperties": false,
|
|
1582
|
+
"description": "The instruction on one provider: exactly one of instruction or instruction_append.",
|
|
1583
|
+
"oneOf": [
|
|
1584
|
+
{
|
|
1585
|
+
"required": [
|
|
1586
|
+
"instruction"
|
|
1587
|
+
]
|
|
1588
|
+
},
|
|
1589
|
+
{
|
|
1590
|
+
"required": [
|
|
1591
|
+
"instruction_append"
|
|
1592
|
+
]
|
|
1593
|
+
}
|
|
1594
|
+
]
|
|
1595
|
+
},
|
|
1538
1596
|
"ollama": {
|
|
1539
1597
|
"type": "object",
|
|
1540
1598
|
"properties": {
|
|
@@ -270,7 +270,14 @@ orchestrator:
|
|
|
270
270
|
# grok-* → xAI (XAI_API_KEY)
|
|
271
271
|
# kimi-* → Moonshot Kimi (MOONSHOT_API_KEY)
|
|
272
272
|
# deepseek-* → DeepSeek (DEEPSEEK_API_KEY)
|
|
273
|
+
# jev-* → TypeSafe Jev (TYPESAFE_API_KEY; a decision model: it answers
|
|
274
|
+
# this agent's output.schema, never prose, so it
|
|
275
|
+
# takes no tools and no subagents)
|
|
273
276
|
# ollama/* → local Ollama (keyless)
|
|
277
|
+
# With no direct key, MODEL_GATEWAY (vercel | openrouter) serves any cloud id;
|
|
278
|
+
# MODEL_GATEWAY_PREFER=gateway sends every cloud id through it even beside
|
|
279
|
+
# a direct key, and MODEL_GATEWAY_EXCEPT names the providers that do the
|
|
280
|
+
# opposite. Deployment config, never YAML: the file names models, not paths.
|
|
274
281
|
# Subagents inherit this if not set on their own config.
|
|
275
282
|
model: "gemini-3.5-flash-lite"
|
|
276
283
|
|
|
@@ -444,6 +451,7 @@ orchestrator:
|
|
|
444
451
|
# that effort; none is the model's off switch,
|
|
445
452
|
# or low effort on Opus 5 and 5.5, Fable and
|
|
446
453
|
# Mythos (ADR 0049)
|
|
454
|
+
# jev-* → nothing: Jev decides without reasoning
|
|
447
455
|
# gpt-*/o*, grok-*, kimi-*, deepseek-*, ollama/*, a gateway
|
|
448
456
|
# → reasoningEffort (an effort word; where the
|
|
449
457
|
# provider lacks one, its nearest setting above;
|
|
@@ -508,7 +516,7 @@ orchestrator:
|
|
|
508
516
|
# ── model_overrides ───────────────────────────────────────
|
|
509
517
|
# [optional] A prompt nuance for one provider (ADR 0115). Keys are the
|
|
510
518
|
# providers a model id routes to: gemini, anthropic, openai, xai,
|
|
511
|
-
# moonshot, deepseek, ollama. Each holds ONE of:
|
|
519
|
+
# moonshot, deepseek, typesafe, ollama. Each holds ONE of:
|
|
512
520
|
# instruction: replaces the instruction on that provider
|
|
513
521
|
# instruction_append: added after the instruction, after a blank line
|
|
514
522
|
# Applied for the provider of this agent's model, before the skills
|
package/db/hardening.sql
CHANGED
|
@@ -57,6 +57,8 @@ END $$;
|
|
|
57
57
|
-- deny-by-default. service_role is unaffected (it bypasses RLS).
|
|
58
58
|
ALTER TABLE adk_memory_facts ENABLE ROW LEVEL SECURITY;
|
|
59
59
|
ALTER TABLE adk_sessions ENABLE ROW LEVEL SECURITY;
|
|
60
|
+
-- The store's one embedder row (migration 0023) names a model, nothing personal; locked all the same.
|
|
61
|
+
ALTER TABLE IF EXISTS melchizedek_memory_embedder ENABLE ROW LEVEL SECURITY;
|
|
60
62
|
|
|
61
63
|
-- Belt and suspenders: also revoke the default table privileges from the
|
|
62
64
|
-- API roles, so even a future accidentally-created permissive policy
|
|
@@ -65,6 +67,9 @@ DO $$
|
|
|
65
67
|
BEGIN
|
|
66
68
|
PERFORM pg_temp.melchizedek_revoke_api('adk_memory_facts');
|
|
67
69
|
PERFORM pg_temp.melchizedek_revoke_api('adk_sessions');
|
|
70
|
+
IF to_regclass('melchizedek_memory_embedder') IS NOT NULL THEN
|
|
71
|
+
PERFORM pg_temp.melchizedek_revoke_api('melchizedek_memory_embedder');
|
|
72
|
+
END IF;
|
|
68
73
|
END $$;
|
|
69
74
|
|
|
70
75
|
-- Optional observability ledger (db/telemetry.sql). Guarded: the tables only
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- 0020_embedding_flash_grok_pricing — price rows for three models a ledger
|
|
3
|
+
-- already holds calls of (extends ADR 0136)
|
|
4
|
+
-- ============================================================================
|
|
5
|
+
-- Rows only, in 0017's column layout (USD per million tokens). A deployment's
|
|
6
|
+
-- ledger (penguin's, 2026-10-22) had calls of these three models priced NULL
|
|
7
|
+
-- because no row existed; scripts that re-price NULL rows can now fill them.
|
|
8
|
+
--
|
|
9
|
+
-- grok-4.3: xAI first-party, docs.x.ai/docs/models, checked 2026-10-22. The
|
|
10
|
+
-- row holds the rate under 200k prompt tokens ($1.25 in / $0.20 cached /
|
|
11
|
+
-- $2.50 out); a request of 200k or more is billed at double for all its
|
|
12
|
+
-- tokens ($2.50 / $0.40 / $5.00), which a flat row cannot say: such a call
|
|
13
|
+
-- is underestimated by half.
|
|
14
|
+
--
|
|
15
|
+
-- gemini-embedding-001: Google's GA announcement for the Gemini API
|
|
16
|
+
-- (developers.googleblog.com, "Gemini Embedding now generally available"):
|
|
17
|
+
-- $0.15 per 1M input tokens, no output tokens. Google's current pricing page
|
|
18
|
+
-- lists only its successor (gemini-embedding-2), so verified_at stays NULL.
|
|
19
|
+
--
|
|
20
|
+
-- gemini-3.5-flash: $1.50 in / $0.15 cached / $9.00 out, as two pricing
|
|
21
|
+
-- guides give it, one citing Google's Gemini API pricing documentation
|
|
22
|
+
-- (June 2026). Google's current page no longer lists the model (superseded
|
|
23
|
+
-- by 3.6 and 3.8 Flash), so this could not be checked against the vendor:
|
|
24
|
+
-- verified_at NULL, a steering estimate (0015's convention).
|
|
25
|
+
--
|
|
26
|
+
-- New rows never overwrite a row that exists: an operator's own rates
|
|
27
|
+
-- survive. Nothing secret, nothing personal. Idempotent; safe to re-run.
|
|
28
|
+
-- ============================================================================
|
|
29
|
+
|
|
30
|
+
INSERT INTO model_pricing (model, input_per_mtok, output_per_mtok, cache_read_per_mtok, cache_write_per_mtok, verified_at, source, note) VALUES
|
|
31
|
+
('grok-4.3', 1.25, 2.50, 0.20, NULL, '2026-10-22', 'docs.x.ai/docs/models', 'xAI first-party, checked 2026-10-22; rate under 200k prompt tokens (a request of 200k or more bills $2.50 / $0.40 / $5.00)'),
|
|
32
|
+
('gemini-embedding-001', 0.15, 0.00, NULL, NULL, NULL, 'developers.googleblog.com, Gemini Embedding now generally available in the Gemini API', 'Google first-party announcement; input only; no longer on the current pricing page (successor gemini-embedding-2), not re-checked'),
|
|
33
|
+
('gemini-3.5-flash', 1.50, 9.00, 0.15, NULL, NULL, 'eesel.ai Gemini 3 pricing guide (citing ai.google.dev pricing, June 2026), agreeing with other guides', 'unverified: off Google''s current pricing page (superseded by 3.6 and 3.8 Flash)')
|
|
34
|
+
ON CONFLICT (model) DO NOTHING;
|
|
35
|
+
|
|
36
|
+
INSERT INTO melchizedek_schema_version (version, name)
|
|
37
|
+
VALUES (20, '0020_embedding_flash_grok_pricing')
|
|
38
|
+
ON CONFLICT (version) DO NOTHING;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- 0021_correct_gemini_flash_grok_rates — two seed rows to their vendors'
|
|
3
|
+
-- current lists (extends ADR 0136)
|
|
4
|
+
-- ============================================================================
|
|
5
|
+
-- 0015 seeded gemini-3.8-flash and grok-4.7 from melch-obs's pricing.toml as
|
|
6
|
+
-- unverified estimates. Checked 2026-10-22 against the vendors' lists, both
|
|
7
|
+
-- were wrong:
|
|
8
|
+
--
|
|
9
|
+
-- gemini-3.8-flash ai.google.dev/gemini-api/docs/pricing (paid, standard):
|
|
10
|
+
-- $0.75 in / $0.075 cached / $3.75 out, thinking billed
|
|
11
|
+
-- as output, through 2026-12-31. Google has announced
|
|
12
|
+
-- $1.50 / $0.15 / $7.50 from 2027-01-01; a flat row cannot
|
|
13
|
+
-- say the date, so that needs its own row change then.
|
|
14
|
+
-- Seed: $0.30 / $2.50 (a placeholder at 3.7's rate).
|
|
15
|
+
-- grok-4.7 docs.x.ai/docs/models: $2.00 in / $0.50 cached / $6.00
|
|
16
|
+
-- out under 200k prompt tokens (a request of 200k or more
|
|
17
|
+
-- bills $4.00 / $1.00 / $12.00 for all its tokens, which a
|
|
18
|
+
-- flat row underestimates by half). Seed: $3.00 / $15.00.
|
|
19
|
+
--
|
|
20
|
+
-- A row changes only while it is still the seed: source melch-obs/pricing.toml,
|
|
21
|
+
-- verified_at NULL, and the seed's own rates. A rate an operator set is kept.
|
|
22
|
+
--
|
|
23
|
+
-- Rows already priced keep what they were priced at: the ledger records the
|
|
24
|
+
-- rate in force at write time (db/telemetry.sql). Re-pricing history is a
|
|
25
|
+
-- deliberate UPDATE, never a migration. Idempotent; safe to re-run.
|
|
26
|
+
-- ============================================================================
|
|
27
|
+
|
|
28
|
+
UPDATE model_pricing
|
|
29
|
+
SET input_per_mtok = 0.75, output_per_mtok = 3.75, cache_read_per_mtok = 0.075,
|
|
30
|
+
verified_at = '2026-10-22', source = 'ai.google.dev/gemini-api/docs/pricing',
|
|
31
|
+
note = 'Gemini API paid standard tier, checked 2026-10-22; rate through 2026-12-31 (Google lists $1.50 / $0.15 / $7.50 from 2027-01-01)',
|
|
32
|
+
updated_at = now()
|
|
33
|
+
WHERE model = 'gemini-3.8-flash' AND source = 'melch-obs/pricing.toml' AND verified_at IS NULL
|
|
34
|
+
AND input_per_mtok = 0.30 AND output_per_mtok = 2.50;
|
|
35
|
+
|
|
36
|
+
UPDATE model_pricing
|
|
37
|
+
SET input_per_mtok = 2.00, output_per_mtok = 6.00, cache_read_per_mtok = 0.50,
|
|
38
|
+
verified_at = '2026-10-22', source = 'docs.x.ai/docs/models',
|
|
39
|
+
note = 'xAI first-party, checked 2026-10-22; rate under 200k prompt tokens (a request of 200k or more bills $4.00 / $1.00 / $12.00)',
|
|
40
|
+
updated_at = now()
|
|
41
|
+
WHERE model = 'grok-4.7' AND source = 'melch-obs/pricing.toml' AND verified_at IS NULL
|
|
42
|
+
AND input_per_mtok = 3.00 AND output_per_mtok = 15.00;
|
|
43
|
+
|
|
44
|
+
INSERT INTO melchizedek_schema_version (version, name)
|
|
45
|
+
VALUES (21, '0021_correct_gemini_flash_grok_rates')
|
|
46
|
+
ON CONFLICT (version) DO NOTHING;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- 0022_typesafe_jev_pricing — price rows for TypeSafe Jev (extends ADR 0136;
|
|
3
|
+
-- the provider is ADR 0144)
|
|
4
|
+
-- ============================================================================
|
|
5
|
+
-- Rows only, in 0017's column layout (USD per million tokens):
|
|
6
|
+
-- input_per_mtok an input token
|
|
7
|
+
-- output_per_mtok 0: TypeSafe bills nothing for output today
|
|
8
|
+
-- (docs.typesafe.ai/models, "output tokens are free")
|
|
9
|
+
-- cache_read_per_mtok NULL: no cache on this API
|
|
10
|
+
-- cache_write_per_mtok NULL
|
|
11
|
+
--
|
|
12
|
+
-- TypeSafe Jev (lib/models/jevAdapter.ts): $42 per billion input tokens,
|
|
13
|
+
-- which is $0.042 per million, the same on jev-1.14.0 and jev-1.13.0.
|
|
14
|
+
-- `jev-latest` and `jev-preview` are TypeSafe's aliases (both jev-1.14.0 on
|
|
15
|
+
-- 2026-10-23); a call made under an alias is priced under the alias, so the
|
|
16
|
+
-- aliases get rows too. Checked 2026-10-23 against docs.typesafe.ai/models.
|
|
17
|
+
--
|
|
18
|
+
-- Through a gateway (Vercel AI Gateway lists $0.042 input, max output 0;
|
|
19
|
+
-- OpenRouter bills "the rate on the Jev model page") the rate is the same
|
|
20
|
+
-- at the time of writing; an operator whose gateway adds a margin edits the
|
|
21
|
+
-- row.
|
|
22
|
+
--
|
|
23
|
+
-- New rows never overwrite a row that exists: an operator's own rates
|
|
24
|
+
-- survive. Nothing secret, nothing personal. Idempotent; safe to re-run.
|
|
25
|
+
-- ============================================================================
|
|
26
|
+
|
|
27
|
+
INSERT INTO model_pricing (model, input_per_mtok, output_per_mtok, cache_read_per_mtok, cache_write_per_mtok, verified_at, source, note) VALUES
|
|
28
|
+
('jev-latest', 0.042, 0, NULL, NULL, '2026-10-23', 'docs.typesafe.ai/models', 'TypeSafe first-party, checked 2026-10-23; alias of jev-1.14.0; output is free'),
|
|
29
|
+
('jev-preview', 0.042, 0, NULL, NULL, '2026-10-23', 'docs.typesafe.ai/models', 'TypeSafe first-party, checked 2026-10-23; alias of the newest build (jev-1.14.0); output is free'),
|
|
30
|
+
('jev-1.14.0', 0.042, 0, NULL, NULL, '2026-10-23', 'docs.typesafe.ai/models', 'TypeSafe first-party, checked 2026-10-23; output is free'),
|
|
31
|
+
('jev-1.13.0', 0.042, 0, NULL, NULL, '2026-10-23', 'docs.typesafe.ai/models', 'TypeSafe first-party, checked 2026-10-23; output is free')
|
|
32
|
+
ON CONFLICT (model) DO NOTHING;
|
|
33
|
+
|
|
34
|
+
INSERT INTO melchizedek_schema_version (version, name)
|
|
35
|
+
VALUES (22, '0022_typesafe_jev_pricing')
|
|
36
|
+
ON CONFLICT (version) DO NOTHING;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- 0023_memory_embedder — the one embedding model a memory store's vectors
|
|
3
|
+
-- come from (ADR 0147)
|
|
4
|
+
-- ============================================================================
|
|
5
|
+
-- Every vector in adk_memory_facts must come from one model: a different
|
|
6
|
+
-- model at the same dimension passes the size check (0007's
|
|
7
|
+
-- melchizedek_memory_dimensions) and quietly degrades recall. This table
|
|
8
|
+
-- holds one row: the provider, model and dimension the store was first
|
|
9
|
+
-- written with. The memory service records it on its first successful
|
|
10
|
+
-- insert and refuses, at start, an embedder whose model differs
|
|
11
|
+
-- (lib/memory/supabaseMemoryService.ts); switching models means re-embedding
|
|
12
|
+
-- the stored facts, never a silent change.
|
|
13
|
+
--
|
|
14
|
+
-- A gateway's spelling of the same model (google/gemini-embedding-001 for
|
|
15
|
+
-- gemini-embedding-001) is the same model: the service compares the last
|
|
16
|
+
-- path segment. Two functions serve the Supabase REST path, which reaches
|
|
17
|
+
-- tables through RPC here (0007's convention):
|
|
18
|
+
-- melchizedek_memory_embedder() the row, or none
|
|
19
|
+
-- melchizedek_memory_record_embedder(p, m, d) record it once; a later
|
|
20
|
+
-- call changes nothing
|
|
21
|
+
-- melchizedek_memory_set_embedder(p, m, d) overwrite it: what a
|
|
22
|
+
-- completed re-embed writes
|
|
23
|
+
-- (lib/memory/reembed.ts)
|
|
24
|
+
-- Nothing secret, nothing personal. Idempotent; safe to re-run.
|
|
25
|
+
-- ============================================================================
|
|
26
|
+
|
|
27
|
+
CREATE TABLE IF NOT EXISTS melchizedek_memory_embedder (
|
|
28
|
+
one BOOLEAN PRIMARY KEY DEFAULT TRUE CHECK (one),
|
|
29
|
+
provider TEXT NOT NULL,
|
|
30
|
+
model TEXT NOT NULL,
|
|
31
|
+
dimensions INTEGER NOT NULL CHECK (dimensions > 0),
|
|
32
|
+
recorded_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
CREATE OR REPLACE FUNCTION melchizedek_memory_embedder()
|
|
36
|
+
RETURNS TABLE (provider text, model text, dimensions integer, recorded_at timestamptz)
|
|
37
|
+
LANGUAGE sql
|
|
38
|
+
STABLE
|
|
39
|
+
SET search_path = public
|
|
40
|
+
AS $$
|
|
41
|
+
SELECT provider, model, dimensions, recorded_at FROM melchizedek_memory_embedder WHERE one;
|
|
42
|
+
$$;
|
|
43
|
+
|
|
44
|
+
CREATE OR REPLACE FUNCTION melchizedek_memory_record_embedder(p_provider text, p_model text, p_dimensions integer)
|
|
45
|
+
RETURNS void
|
|
46
|
+
LANGUAGE sql
|
|
47
|
+
SET search_path = public
|
|
48
|
+
AS $$
|
|
49
|
+
INSERT INTO melchizedek_memory_embedder (one, provider, model, dimensions)
|
|
50
|
+
VALUES (TRUE, p_provider, p_model, p_dimensions)
|
|
51
|
+
ON CONFLICT (one) DO NOTHING;
|
|
52
|
+
$$;
|
|
53
|
+
|
|
54
|
+
CREATE OR REPLACE FUNCTION melchizedek_memory_set_embedder(p_provider text, p_model text, p_dimensions integer)
|
|
55
|
+
RETURNS void
|
|
56
|
+
LANGUAGE sql
|
|
57
|
+
SET search_path = public
|
|
58
|
+
AS $$
|
|
59
|
+
INSERT INTO melchizedek_memory_embedder (one, provider, model, dimensions, recorded_at)
|
|
60
|
+
VALUES (TRUE, p_provider, p_model, p_dimensions, now())
|
|
61
|
+
ON CONFLICT (one) DO UPDATE SET provider = EXCLUDED.provider, model = EXCLUDED.model, dimensions = EXCLUDED.dimensions, recorded_at = now();
|
|
62
|
+
$$;
|
|
63
|
+
|
|
64
|
+
INSERT INTO melchizedek_schema_version (version, name)
|
|
65
|
+
VALUES (23, '0023_memory_embedder')
|
|
66
|
+
ON CONFLICT (version) DO NOTHING;
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -100,6 +100,12 @@ export declare const DEFAULT_MAX_STEPS = 50;
|
|
|
100
100
|
* qwen3:8b is the smallest pulled model that supports tool calling — the
|
|
101
101
|
* floor capability for syndicate delegation. Vision work uses ollama/qwen3-vl:8b.
|
|
102
102
|
*/
|
|
103
|
+
/**
|
|
104
|
+
* TypeSafe Jev (lib/models/jevAdapter.ts): `jev-latest` is TypeSafe's alias
|
|
105
|
+
* for the newest stable release (jev-1.14.0 as of 2026-10-14). A decision
|
|
106
|
+
* model: it answers an agent's `output.schema`, never free text.
|
|
107
|
+
*/
|
|
108
|
+
export declare const DEFAULT_JEV_MODEL = "jev-latest";
|
|
103
109
|
export declare const DEFAULT_OLLAMA_MODEL = "ollama/qwen3:8b";
|
|
104
110
|
/**
|
|
105
111
|
* Model used by SupabaseVectorMemoryService to extract discrete facts
|
package/dist/lib/config.js
CHANGED
|
@@ -101,6 +101,12 @@ export const DEFAULT_MAX_STEPS = 50;
|
|
|
101
101
|
* qwen3:8b is the smallest pulled model that supports tool calling — the
|
|
102
102
|
* floor capability for syndicate delegation. Vision work uses ollama/qwen3-vl:8b.
|
|
103
103
|
*/
|
|
104
|
+
/**
|
|
105
|
+
* TypeSafe Jev (lib/models/jevAdapter.ts): `jev-latest` is TypeSafe's alias
|
|
106
|
+
* for the newest stable release (jev-1.14.0 as of 2026-10-14). A decision
|
|
107
|
+
* model: it answers an agent's `output.schema`, never free text.
|
|
108
|
+
*/
|
|
109
|
+
export const DEFAULT_JEV_MODEL = 'jev-latest';
|
|
104
110
|
export const DEFAULT_OLLAMA_MODEL = 'ollama/qwen3:8b';
|
|
105
111
|
/**
|
|
106
112
|
* Model used by SupabaseVectorMemoryService to extract discrete facts
|
package/dist/lib/doctor.d.ts
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
import type { Platform } from './models/endpoints.ts';
|
|
27
27
|
import type { CapabilityGap, CapabilityReport } from './models/capabilities.ts';
|
|
28
28
|
import type { ProviderId } from './models/providerMap.ts';
|
|
29
|
+
import type { EmbedderPlan } from './memory/providers.ts';
|
|
29
30
|
import type { RuntimeName, RuntimeSource } from './runtime/runtimeFlag.ts';
|
|
30
31
|
import { type ProjectCheck } from './project.ts';
|
|
31
32
|
/**
|
|
@@ -172,6 +173,13 @@ export interface DoctorResult {
|
|
|
172
173
|
chatgpt?: DoctorChatGpt;
|
|
173
174
|
/** The project manifest (ADR 0138) found from the working directory, when there is one. */
|
|
174
175
|
project?: DoctorProject;
|
|
176
|
+
/** Long-term memory's embedder (ADR 0147), when any syndicate here is long-term or MEMORY_EMBEDDING_PROVIDER is set. */
|
|
177
|
+
memory?: DoctorMemory;
|
|
178
|
+
}
|
|
179
|
+
/** What would embed long-term memory here: the plan, and how many of this directory's syndicates need it. */
|
|
180
|
+
export interface DoctorMemory {
|
|
181
|
+
longTerm: number;
|
|
182
|
+
embedder: EmbedderPlan;
|
|
175
183
|
}
|
|
176
184
|
/** A `melchizedek.json` at or above the working directory: its checks, or why it does not load. */
|
|
177
185
|
export type DoctorProject = ProjectCheck | {
|
package/dist/lib/doctor.js
CHANGED
|
@@ -33,6 +33,7 @@ import { CAPABILITY_LABELS, capabilityGaps, describeCapabilities } from './model
|
|
|
33
33
|
import { credentialSource, endpointFromEnv, endpointLabel, endpointProblems, PLATFORM_SDK, PLATFORMS_FOR } from './models/endpoints.js';
|
|
34
34
|
import { GATEWAY_ENV, GATEWAY_KEY_ENV, GATEWAYS, gatewayConfig, gatewayProblem, gatewayUsable, } from './models/gateway.js';
|
|
35
35
|
import { PROVIDERS } from './models/providerMap.js';
|
|
36
|
+
import { embedderPlan } from './memory/providers.js';
|
|
36
37
|
import { describeRuntime } from './runtime/runtimeFlag.js';
|
|
37
38
|
import { CHATGPT_SIGNIN_ENV, CHATGPT_SIGNIN_FILE_ENV, chatGptSignInRoutesOpenAi, chatGptSignInStatus } from './chatgpt/state.js';
|
|
38
39
|
import { agentOAuthGrants, oauthEnvNames } from './tools/oauthTools.js';
|
|
@@ -179,6 +180,7 @@ export const CONSOLE_URLS = {
|
|
|
179
180
|
xai: 'https://console.x.ai',
|
|
180
181
|
moonshot: 'https://platform.moonshot.ai',
|
|
181
182
|
deepseek: 'https://platform.deepseek.com/api_keys',
|
|
183
|
+
typesafe: 'https://console.typesafe.ai/keys',
|
|
182
184
|
ollama: 'https://ollama.com',
|
|
183
185
|
};
|
|
184
186
|
// ── Discovery ────────────────────────────────────────────────────────────────
|
|
@@ -506,6 +508,9 @@ export function runDoctor(options = {}) {
|
|
|
506
508
|
for (const s of syndicates)
|
|
507
509
|
counts[s.verdict.state]++;
|
|
508
510
|
flagMemoryNamespaces(syndicates);
|
|
511
|
+
// Long-term memory's embedder (ADR 0147): what would embed, or what to set, names only.
|
|
512
|
+
const longTerm = syndicates.filter((s) => s.memory).length;
|
|
513
|
+
const memory = longTerm || process.env.MEMORY_EMBEDDING_PROVIDER?.trim() ? { longTerm, embedder: embedderPlan() } : undefined;
|
|
509
514
|
// The server's OAuth setup (ADR 0114): the key, the redirect URI and the allowlist, names only.
|
|
510
515
|
const grants = syndicates.flatMap((s) => s.grants ?? []).map((g) => ({ agent: g.agent, tools: g.tools, oauth2: { provider: g.provider, grant: g.grant, token_url: '' } }));
|
|
511
516
|
const set = Object.fromEntries([CREDENTIAL_KEY_ENV, OAUTH_REDIRECT_URI_ENV, OAUTH_HOSTS_ENV].map((name) => [name, !!process.env[name]?.trim()]));
|
|
@@ -537,6 +542,7 @@ export function runDoctor(options = {}) {
|
|
|
537
542
|
syndicates,
|
|
538
543
|
unlocks,
|
|
539
544
|
gateway,
|
|
545
|
+
...(memory ? { memory } : {}),
|
|
540
546
|
endpoints: endpointRows(),
|
|
541
547
|
counts,
|
|
542
548
|
...(oauth ? { oauth } : {}),
|
|
@@ -605,6 +611,7 @@ const PROBE_ID = {
|
|
|
605
611
|
xai: 'grok-x',
|
|
606
612
|
moonshot: 'kimi-x',
|
|
607
613
|
deepseek: 'deepseek-x',
|
|
614
|
+
typesafe: 'jev-x',
|
|
608
615
|
ollama: 'ollama/x',
|
|
609
616
|
};
|
|
610
617
|
/**
|
|
@@ -695,6 +702,16 @@ export function renderDoctor(result, opts = {}) {
|
|
|
695
702
|
? `gateway ${c.red}✗${c.reset} ${result.gateway.problem}`
|
|
696
703
|
: `gateway ${c.yellow}◇${c.reset} ${result.gateway.label} fills in for any provider whose direct key is absent ${c.dim}(native search is lost on that path)${c.reset}`);
|
|
697
704
|
}
|
|
705
|
+
if (result.memory) {
|
|
706
|
+
// Long-term memory's embedder (ADR 0147): funded directly, through the gateway, or what to set. Names only.
|
|
707
|
+
const e = result.memory.embedder;
|
|
708
|
+
const n = result.memory.longTerm;
|
|
709
|
+
const who = n ? `${n} long-term syndicate${n === 1 ? '' : 's'}` : 'MEMORY_EMBEDDING_PROVIDER set';
|
|
710
|
+
const mark = !e.funded ? `${c.red}✗${c.reset}` : e.transport === 'gateway' ? `${c.yellow}◇${c.reset}` : `${c.green}✓${c.reset}`;
|
|
711
|
+
lines.push(e.funded
|
|
712
|
+
? `memory ${mark} embeddings ${e.provider}/${e.model} (${e.dimensions}d)${e.transport === 'gateway' ? ` via gateway:${e.gateway}` : ''} ${c.dim}· ${e.detail} · ${who}${c.reset}`
|
|
713
|
+
: `memory ${mark} ${c.red}${e.detail}${c.reset} ${c.dim}· ${who}${c.reset}`);
|
|
714
|
+
}
|
|
698
715
|
if (result.serving) {
|
|
699
716
|
// Names only: the A2A identity mode, who pays, and what the server would refuse.
|
|
700
717
|
const sv = result.serving;
|
|
@@ -149,7 +149,7 @@ export interface AgentYamlConfig {
|
|
|
149
149
|
* appended after a blank line, for the provider of the model the agent runs
|
|
150
150
|
* on. Applied at compile time, before the skills index; not for fallback_model.
|
|
151
151
|
*/
|
|
152
|
-
model_overrides?: Partial<Record<'gemini' | 'anthropic' | 'openai' | 'xai' | 'moonshot' | 'deepseek' | 'ollama', {
|
|
152
|
+
model_overrides?: Partial<Record<'gemini' | 'anthropic' | 'openai' | 'xai' | 'moonshot' | 'deepseek' | 'typesafe' | 'ollama', {
|
|
153
153
|
instruction?: string;
|
|
154
154
|
instruction_append?: string;
|
|
155
155
|
}>>;
|
|
@@ -27,6 +27,16 @@
|
|
|
27
27
|
* MEMORY_EMBEDDING_API_KEY openai-compatible key (else none)
|
|
28
28
|
* The vector column is fixed at creation (db/), so changing the model or the
|
|
29
29
|
* dimension needs a re-embed, not just a new variable.
|
|
30
|
+
*
|
|
31
|
+
* THE GATEWAY (ADR 0146): with no key for the embedding provider, or with
|
|
32
|
+
* MODEL_GATEWAY_PREFER=gateway, the embedder goes through the configured
|
|
33
|
+
* gateway's /embeddings when that gateway carries the SAME model (Vercel
|
|
34
|
+
* carries google/gemini-embedding-001 and openai/text-embedding-3-small
|
|
35
|
+
* and honours `dimensions`; OpenRouter carries OpenAI's). The vectors are
|
|
36
|
+
* the model's own, so a store embedded directly and one embedded through
|
|
37
|
+
* the gateway agree. A gateway that lacks the model changes nothing: the
|
|
38
|
+
* direct path stays, keyless and failing loudly, never a different model
|
|
39
|
+
* behind the store's back.
|
|
30
40
|
*/
|
|
31
41
|
import type { ProviderEndpoint } from '../models/endpoints.ts';
|
|
32
42
|
import type { ModelAdapter } from '../models/contract.ts';
|
|
@@ -90,6 +100,27 @@ export interface MemoryProviders {
|
|
|
90
100
|
extractor: MemoryExtractor;
|
|
91
101
|
embedder: Embedder;
|
|
92
102
|
}
|
|
103
|
+
/** What the environment's embedder would be, with no client built (the doctor's memory line, ADR 0147). */
|
|
104
|
+
export interface EmbedderPlan {
|
|
105
|
+
provider: string;
|
|
106
|
+
model: string;
|
|
107
|
+
dimensions: number;
|
|
108
|
+
/** `none` when nothing funds the embedder. */
|
|
109
|
+
transport: 'direct' | 'gateway' | 'none';
|
|
110
|
+
gateway?: string;
|
|
111
|
+
funded: boolean;
|
|
112
|
+
/** For a person: what funds it, or what to set. Never a key. */
|
|
113
|
+
detail: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The embedder `memoryProvidersFromEnv` would build, as a plan: provider,
|
|
117
|
+
* model, dimension, the path and whether it is funded, with the fix when it
|
|
118
|
+
* is not. The OpenRouter case gets its documented answer: OpenRouter carries
|
|
119
|
+
* no Gemini embedding model, so `MEMORY_EMBEDDING_PROVIDER=openai` embeds
|
|
120
|
+
* `text-embedding-3-small` through it, with the re-embed caveat for a store
|
|
121
|
+
* already embedded with Gemini (ADR 0147).
|
|
122
|
+
*/
|
|
123
|
+
export declare function embedderPlan(env?: NodeJS.ProcessEnv, geminiKey?: string): EmbedderPlan;
|
|
93
124
|
/**
|
|
94
125
|
* The deployment's extractor and embedder. `geminiKey` is the key the server
|
|
95
126
|
* already passes for memory; it is used only when the configured extraction
|