melchizedek-agents 1.0.3 → 1.2.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 +29 -2
- package/AGENT_SETUP.md +3 -1
- package/CHANGELOG.md +524 -0
- package/DOCUMENTATION.md +178 -43
- package/ONBOARDING.md +339 -0
- package/QUICKSTART.md +15 -2
- package/README.md +6 -2
- package/config/agents/README.md +2 -2
- package/config/agents/examples/ares.yaml +6 -10
- package/config/agents/examples/assistant.yaml +6 -6
- package/config/agents/examples/augustin.yaml +9 -15
- package/config/agents/examples/cartographers.yaml +6 -6
- package/config/agents/examples/council.yaml +7 -7
- package/config/agents/examples/critic.yaml +24 -24
- package/config/agents/examples/harness.yaml +4 -4
- package/config/agents/examples/image_production.yaml +37 -35
- package/config/agents/examples/librarian.yaml +4 -4
- package/config/agents/examples/patient_advocate.yaml +6 -10
- package/config/agents/examples/pipeline.yaml +20 -19
- package/config/agents/examples/research.yaml +36 -43
- package/config/agents/examples/scribe.yaml +31 -32
- package/config/agents/examples/scriptorium.yaml +6 -6
- package/config/agents/examples/structured_critic.yaml +82 -0
- package/config/agents/examples/style_council.yaml +9 -11
- package/config/agents/examples/syndicate.yaml +3 -5
- package/config/agents/examples/tutor.yaml +2 -2
- package/config/agents/examples/weather.yaml +2 -2
- package/config/agents/syndicate.schema.json +859 -13
- package/config/agents/syndicateSchema.yaml +122 -73
- package/config/agents/templates/README.md +1 -1
- package/config/agents/templates/account_memory.yaml +4 -4
- package/config/agents/templates/case_desk.yaml +6 -6
- package/config/agents/templates/conversational.yaml +2 -2
- package/config/agents/templates/draft_review.yaml +6 -6
- package/config/agents/templates/intake_extractor.yaml +64 -62
- package/config/agents/templates/research_brief.yaml +6 -6
- package/config/agents/templates/research_desk.yaml +6 -6
- package/config/agents/templates/review_panel.yaml +8 -8
- package/config/agents/templates/support_triage.yaml +30 -29
- package/config/agents/templates/systems_operator.yaml +24 -5
- package/db/migrations/0014_durable_runs.sql +31 -0
- package/dist/lib/a2a/app.d.ts +27 -0
- package/dist/lib/a2a/app.js +64 -5
- package/dist/lib/a2a/executor.d.ts +7 -1
- package/dist/lib/a2a/executor.js +43 -5
- package/dist/lib/a2a/oauthSetup.d.ts +106 -0
- package/dist/lib/a2a/oauthSetup.js +259 -0
- package/dist/lib/agentDialect.d.ts +76 -0
- package/dist/lib/agentDialect.js +151 -0
- package/dist/lib/compile.d.ts +42 -6
- package/dist/lib/compile.js +97 -45
- package/dist/lib/compileNative.d.ts +11 -3
- package/dist/lib/compileNative.js +20 -1
- package/dist/lib/dispatch.d.ts +10 -5
- package/dist/lib/dispatch.js +10 -5
- package/dist/lib/doctor.d.ts +110 -1
- package/dist/lib/doctor.js +205 -9
- package/dist/lib/loadSyndicate.d.ts +54 -2
- package/dist/lib/loadSyndicate.js +22 -2
- package/dist/lib/memory/namespace.d.ts +6 -5
- package/dist/lib/memory/namespace.js +6 -5
- package/dist/lib/memory/providers.js +3 -4
- package/dist/lib/models/capabilities.d.ts +25 -1
- package/dist/lib/models/capabilities.js +79 -1
- package/dist/lib/models/chatCompletionsAdapter.d.ts +11 -3
- package/dist/lib/models/chatCompletionsAdapter.js +19 -5
- package/dist/lib/models/claudeAdapter.js +4 -0
- package/dist/lib/models/contract.d.ts +5 -2
- package/dist/lib/models/gateway.d.ts +2 -1
- package/dist/lib/models/gateway.js +4 -2
- package/dist/lib/models/gatewayAdapter.d.ts +7 -1
- package/dist/lib/models/gatewayAdapter.js +8 -0
- package/dist/lib/models/geminiAdapter.js +8 -2
- package/dist/lib/models/genaiMapping.d.ts +8 -4
- package/dist/lib/models/genaiMapping.js +23 -9
- package/dist/lib/models/gptAdapter.d.ts +4 -2
- package/dist/lib/models/gptAdapter.js +11 -4
- package/dist/lib/models/grokAdapter.d.ts +3 -1
- package/dist/lib/models/grokAdapter.js +11 -3
- package/dist/lib/models/kimiAdapter.d.ts +2 -1
- package/dist/lib/models/kimiAdapter.js +3 -3
- package/dist/lib/models/reasoning.d.ts +30 -2
- package/dist/lib/models/reasoning.js +56 -5
- package/dist/lib/observability/tracer.d.ts +8 -1
- package/dist/lib/observability/tracer.js +33 -5
- package/dist/lib/onboarding.d.ts +134 -0
- package/dist/lib/onboarding.js +539 -0
- package/dist/lib/runtime/approvals.d.ts +8 -0
- package/dist/lib/runtime/approvals.js +4 -3
- package/dist/lib/runtime/credentials.d.ts +6 -0
- package/dist/lib/runtime/native/agentLoop.d.ts +23 -3
- package/dist/lib/runtime/native/agentLoop.js +107 -11
- package/dist/lib/runtime/native/checkpoint.d.ts +171 -0
- package/dist/lib/runtime/native/checkpoint.js +359 -0
- package/dist/lib/runtime/native/delegate.d.ts +222 -18
- package/dist/lib/runtime/native/delegate.js +390 -39
- package/dist/lib/runtime/native/interrupts.d.ts +184 -2
- package/dist/lib/runtime/native/interrupts.js +391 -1
- package/dist/lib/runtime/native/request.d.ts +13 -3
- package/dist/lib/runtime/native/request.js +28 -4
- package/dist/lib/runtime/native/telemetry.js +10 -15
- package/dist/lib/runtime/questions.d.ts +7 -4
- package/dist/lib/runtime/sessions.d.ts +1 -1
- package/dist/lib/runtime/syndicateTurn.d.ts +11 -3
- package/dist/lib/runtime/syndicateTurn.js +353 -68
- package/dist/lib/runtime/turnControl.d.ts +56 -0
- package/dist/lib/runtime/turnControl.js +10 -0
- package/dist/lib/session/transcript.d.ts +9 -0
- package/dist/lib/session/transcript.js +20 -1
- package/dist/lib/skills.d.ts +18 -0
- package/dist/lib/skills.js +73 -1
- package/dist/lib/storage/postgres/index.d.ts +12 -2
- package/dist/lib/storage/postgres/index.js +8 -3
- package/dist/lib/storage/postgres/taskQueue.d.ts +20 -4
- package/dist/lib/storage/postgres/taskQueue.js +29 -5
- package/dist/lib/storage/postgres/taskStore.d.ts +26 -2
- package/dist/lib/storage/postgres/taskStore.js +74 -8
- package/dist/lib/syndicateSchema.d.ts +316 -1
- package/dist/lib/syndicateSchema.js +203 -29
- package/dist/lib/tools/auth.d.ts +20 -6
- package/dist/lib/tools/auth.js +21 -5
- package/dist/lib/tools/credentialEnv.d.ts +28 -0
- package/dist/lib/tools/credentialEnv.js +52 -0
- package/dist/lib/tools/credentialHosts.d.ts +88 -0
- package/dist/lib/tools/credentialHosts.js +165 -0
- package/dist/lib/tools/credentialStore.js +9 -2
- package/dist/lib/tools/credentialUses.d.ts +92 -0
- package/dist/lib/tools/credentialUses.js +112 -0
- package/dist/lib/tools/mcpToolFactory.d.ts +25 -2
- package/dist/lib/tools/mcpToolFactory.js +179 -21
- package/dist/lib/tools/oauthConsent.js +8 -1
- package/dist/lib/tools/oauthHosts.d.ts +73 -0
- package/dist/lib/tools/oauthHosts.js +154 -0
- package/dist/lib/tools/oauthTools.d.ts +242 -0
- package/dist/lib/tools/oauthTools.js +447 -0
- package/dist/lib/tools/openapiTools.d.ts +11 -6
- package/dist/lib/tools/openapiTools.js +88 -38
- package/dist/lib/tools/taskTools.d.ts +61 -6
- package/dist/lib/tools/taskTools.js +145 -21
- package/dist/lib/workflow/turn.d.ts +22 -3
- package/dist/lib/workflow/turn.js +151 -31
- package/dist/lib/workflow.d.ts +14 -7
- package/dist/lib/workflow.js +14 -7
- package/dist/lib/workflowConfig.d.ts +6 -0
- package/dist/scripts/a2a_server.d.ts +36 -0
- package/dist/scripts/a2a_server.js +131 -1
- package/dist/scripts/assistant_worker.d.ts +12 -0
- package/dist/scripts/assistant_worker.js +81 -22
- package/dist/scripts/doctor.d.ts +7 -2
- package/dist/scripts/doctor.js +9 -4
- package/dist/scripts/setup.d.ts +23 -0
- package/dist/scripts/setup.js +154 -0
- package/dist/scripts/skills_install.d.ts +3 -1
- package/dist/scripts/skills_install.js +17 -2
- package/dist/scripts/yaml_codemod.d.ts +62 -0
- package/dist/scripts/yaml_codemod.js +652 -0
- package/package.json +8 -2
- package/skills/README.md +11 -2
- package/skills/briefs/_shared.md +1 -1
- package/skills/briefs/melchizedek-author.md +7 -5
- package/skills/briefs/melchizedek-models.md +7 -4
- package/skills/briefs/melchizedek.md +1 -0
- package/skills/briefs/skills-readme.md +3 -1
- package/skills/melchizedek/SKILL.md +1 -0
- package/skills/melchizedek-author/SKILL.md +7 -4
- package/skills/melchizedek-author/assets/minimal.yaml +13 -13
- package/skills/melchizedek-models/SKILL.md +11 -4
- package/skills/melchizedek-onboard/SKILL.md +49 -0
- package/skills/melchizedek-onboard-cloud/SKILL.md +38 -0
- package/skills/melchizedek-onboard-keys/SKILL.md +35 -0
- package/skills/melchizedek-onboard-local/SKILL.md +41 -0
- package/skills/melchizedek-onboard-serve/SKILL.md +43 -0
|
@@ -12,15 +12,43 @@ import type { ReasoningLevel, ReasoningSetting } from './contract.ts';
|
|
|
12
12
|
/**
|
|
13
13
|
* Thinking tokens per level, for the providers that take a budget (Claude,
|
|
14
14
|
* Gemini 2.x). The same table rounds a `budget_tokens` value up to a level
|
|
15
|
-
* for the providers that take only a level or an effort word.
|
|
15
|
+
* for the providers that take only a level or an effort word. `xhigh` and
|
|
16
|
+
* `max` take `high`'s budget (ADR 0117): above it a non-streaming Claude
|
|
17
|
+
* request passes the Anthropic SDK's ceiling (ADR 0047), so a budget path
|
|
18
|
+
* sends them as `high`, and a budget never rounds up to either.
|
|
16
19
|
*/
|
|
17
20
|
export declare const REASONING_BUDGETS: Readonly<Record<ReasoningLevel, number>>;
|
|
21
|
+
/** The levels in order of how hard they ask the model to think. */
|
|
22
|
+
export declare const REASONING_ORDER: readonly ReasoningLevel[];
|
|
23
|
+
/** The levels above `high`, which only some models take (ADR 0117). */
|
|
24
|
+
export declare const isAboveHigh: (setting: ReasoningSetting | undefined) => setting is 'xhigh' | 'max';
|
|
25
|
+
/**
|
|
26
|
+
* The highest level the direct adapter for `model` sends as asked (ADR
|
|
27
|
+
* 0117); a level above it goes as this one. `max` where every level
|
|
28
|
+
* passes: Claude's adaptive generations (the Claude adapter sends its budget
|
|
29
|
+
* generations `high`'s budget) and Kimi K3. OpenAI's GPT-5.2 and later and
|
|
30
|
+
* grok-4.7 stop at `xhigh`; other OpenAI and Grok ids, Gemini and Ollama at
|
|
31
|
+
* `high`. A gateway stops at `high` whatever the id (gatewayAdapter.ts).
|
|
32
|
+
*/
|
|
33
|
+
export declare function effortCeiling(model: string): ReasoningLevel;
|
|
34
|
+
/**
|
|
35
|
+
* The effort word an adapter sends for one setting: ADR 0047's word for the
|
|
36
|
+
* model, held at `ceiling` (default effortCeiling(model)). `weakened` is the
|
|
37
|
+
* level asked for when the word sent is below it; the adapter marks the span
|
|
38
|
+
* `llm.reasoning.weakened` with it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function effortWord(model: string, setting: ReasoningSetting, ceiling?: ReasoningLevel): {
|
|
41
|
+
word: string;
|
|
42
|
+
weakened?: ReasoningLevel;
|
|
43
|
+
};
|
|
18
44
|
/**
|
|
19
45
|
* The generateContentConfig fields a `reasoning:` setting becomes for one
|
|
20
46
|
* model (ADR 0047). `reasoningEffort` is always set, so the gateway (which
|
|
21
47
|
* may serve any id) carries the level too; the Claude adapter reads it first
|
|
22
48
|
* on the adaptive generations (ADR 0049), and the genai SDK drops it from a
|
|
23
49
|
* Gemini request. Claude and Gemini also get the `thinkingConfig` their
|
|
24
|
-
* adapters read.
|
|
50
|
+
* adapters read. `xhigh` and `max` are written as asked (Kimi's `xhigh` as
|
|
51
|
+
* `max`), beside `high`'s thinkingConfig: the adapter holds the word at its
|
|
52
|
+
* model's ceiling (effortWord), so the setting reaches it intact (ADR 0117).
|
|
25
53
|
*/
|
|
26
54
|
export declare function reasoningConfig(model: string, setting: ReasoningSetting): Record<string, unknown>;
|
|
@@ -2,10 +2,25 @@ import { providerForModel } from './providerMap.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Thinking tokens per level, for the providers that take a budget (Claude,
|
|
4
4
|
* Gemini 2.x). The same table rounds a `budget_tokens` value up to a level
|
|
5
|
-
* for the providers that take only a level or an effort word.
|
|
5
|
+
* for the providers that take only a level or an effort word. `xhigh` and
|
|
6
|
+
* `max` take `high`'s budget (ADR 0117): above it a non-streaming Claude
|
|
7
|
+
* request passes the Anthropic SDK's ceiling (ADR 0047), so a budget path
|
|
8
|
+
* sends them as `high`, and a budget never rounds up to either.
|
|
6
9
|
*/
|
|
7
|
-
export const REASONING_BUDGETS = { none: 0, low: 2048, medium: 8192, high: 16384 };
|
|
8
|
-
const GEMINI_THINKING_LEVEL = { none: 'MINIMAL', low: 'LOW', medium: 'MEDIUM', high: 'HIGH' };
|
|
10
|
+
export const REASONING_BUDGETS = { none: 0, low: 2048, medium: 8192, high: 16384, xhigh: 16384, max: 16384 };
|
|
11
|
+
const GEMINI_THINKING_LEVEL = { none: 'MINIMAL', low: 'LOW', medium: 'MEDIUM', high: 'HIGH', xhigh: 'HIGH', max: 'HIGH' };
|
|
12
|
+
/** The levels in order of how hard they ask the model to think. */
|
|
13
|
+
export const REASONING_ORDER = ['none', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
14
|
+
/** The levels above `high`, which only some models take (ADR 0117). */
|
|
15
|
+
export const isAboveHigh = (setting) => setting === 'xhigh' || setting === 'max';
|
|
16
|
+
/** An OpenAI id that takes `xhigh`: GPT-5.2 and later (the o-series and GPT-5 and 5.1 stop at `high`). */
|
|
17
|
+
function openAiTakesXhigh(model) {
|
|
18
|
+
const m = /^gpt-(\d{1,3})(?:\.(\d{1,3}))?/.exec(model);
|
|
19
|
+
if (!m)
|
|
20
|
+
return false;
|
|
21
|
+
const major = Number(m[1]);
|
|
22
|
+
return major > 5 || (major === 5 && Number(m[2] ?? 0) >= 2);
|
|
23
|
+
}
|
|
9
24
|
/** The smallest level whose budget covers the setting: never less thought than asked. */
|
|
10
25
|
function reasoningLevel(setting) {
|
|
11
26
|
if (typeof setting === 'string')
|
|
@@ -29,18 +44,54 @@ function reasoningEffort(model, level) {
|
|
|
29
44
|
case 'xai':
|
|
30
45
|
return level === 'none' ? 'low' : level; // Grok 4.5/4.7 cannot stop reasoning
|
|
31
46
|
case 'moonshot':
|
|
32
|
-
|
|
47
|
+
// K3 has low | high | max: a missing word rounds up.
|
|
48
|
+
return level === 'medium' ? 'high' : level === 'xhigh' ? 'max' : level;
|
|
33
49
|
default:
|
|
34
50
|
return level;
|
|
35
51
|
}
|
|
36
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* The highest level the direct adapter for `model` sends as asked (ADR
|
|
55
|
+
* 0117); a level above it goes as this one. `max` where every level
|
|
56
|
+
* passes: Claude's adaptive generations (the Claude adapter sends its budget
|
|
57
|
+
* generations `high`'s budget) and Kimi K3. OpenAI's GPT-5.2 and later and
|
|
58
|
+
* grok-4.7 stop at `xhigh`; other OpenAI and Grok ids, Gemini and Ollama at
|
|
59
|
+
* `high`. A gateway stops at `high` whatever the id (gatewayAdapter.ts).
|
|
60
|
+
*/
|
|
61
|
+
export function effortCeiling(model) {
|
|
62
|
+
switch (providerForModel(model)) {
|
|
63
|
+
case 'anthropic':
|
|
64
|
+
case 'moonshot':
|
|
65
|
+
return 'max';
|
|
66
|
+
case 'openai':
|
|
67
|
+
return openAiTakesXhigh(model) ? 'xhigh' : 'high';
|
|
68
|
+
case 'xai':
|
|
69
|
+
return /^grok-4\.7(?!\d)/.test(model) ? 'xhigh' : 'high';
|
|
70
|
+
default:
|
|
71
|
+
return 'high';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The effort word an adapter sends for one setting: ADR 0047's word for the
|
|
76
|
+
* model, held at `ceiling` (default effortCeiling(model)). `weakened` is the
|
|
77
|
+
* level asked for when the word sent is below it; the adapter marks the span
|
|
78
|
+
* `llm.reasoning.weakened` with it.
|
|
79
|
+
*/
|
|
80
|
+
export function effortWord(model, setting, ceiling = effortCeiling(model)) {
|
|
81
|
+
const word = reasoningConfig(model, setting).reasoningEffort;
|
|
82
|
+
if (!isAboveHigh(setting) || REASONING_ORDER.indexOf(word) <= REASONING_ORDER.indexOf(ceiling))
|
|
83
|
+
return { word };
|
|
84
|
+
return { word: ceiling, weakened: setting };
|
|
85
|
+
}
|
|
37
86
|
/**
|
|
38
87
|
* The generateContentConfig fields a `reasoning:` setting becomes for one
|
|
39
88
|
* model (ADR 0047). `reasoningEffort` is always set, so the gateway (which
|
|
40
89
|
* may serve any id) carries the level too; the Claude adapter reads it first
|
|
41
90
|
* on the adaptive generations (ADR 0049), and the genai SDK drops it from a
|
|
42
91
|
* Gemini request. Claude and Gemini also get the `thinkingConfig` their
|
|
43
|
-
* adapters read.
|
|
92
|
+
* adapters read. `xhigh` and `max` are written as asked (Kimi's `xhigh` as
|
|
93
|
+
* `max`), beside `high`'s thinkingConfig: the adapter holds the word at its
|
|
94
|
+
* model's ceiling (effortWord), so the setting reaches it intact (ADR 0117).
|
|
44
95
|
*/
|
|
45
96
|
export function reasoningConfig(model, setting) {
|
|
46
97
|
const level = reasoningLevel(setting);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SpanContext } from '@opentelemetry/api';
|
|
1
|
+
import type { Span, SpanContext, SpanOptions } from '@opentelemetry/api';
|
|
2
2
|
import type { ReadableSpan } from '@opentelemetry/sdk-trace-base';
|
|
3
3
|
import type { LlmResponse } from '../models/genaiMapping.ts';
|
|
4
4
|
import type { TurnEvent as Event } from '../runtime/events.ts';
|
|
@@ -43,6 +43,13 @@ export declare function takeTraceStats(traceId: string): TraceStats | undefined;
|
|
|
43
43
|
/** Name of the agent of the nearest enclosing agent span (ADK's `invoke_agent`, the loop's `agent.invoke`), or null. */
|
|
44
44
|
export declare function agentForSpan(spanId: string | undefined): string | null;
|
|
45
45
|
export declare function initializeTracing(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Starts a span on the named tracer, starting the tracer first; in a turn
|
|
48
|
+
* that opted out of tracing, a non-recording span and no tracer. Every span
|
|
49
|
+
* the engine opens inside a turn goes through here or checks turnUntraced
|
|
50
|
+
* itself.
|
|
51
|
+
*/
|
|
52
|
+
export declare function startEngineSpan(tracerName: string, name: string, options?: SpanOptions): Span;
|
|
46
53
|
export interface TraceMetadata {
|
|
47
54
|
syndicateName: string;
|
|
48
55
|
bindings?: Record<string, any>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { trace, context, defaultTextMapGetter, ROOT_CONTEXT } from '@opentelemetry/api';
|
|
1
|
+
import { trace, context, defaultTextMapGetter, ROOT_CONTEXT, INVALID_SPAN_CONTEXT } from '@opentelemetry/api';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { ADK_SPAN_SCOPE, RUNTIME_SPAN_SCOPE, TELEMETRY_SCHEMA_VERSION, agentOfSpanName, engineVersion, isModelCallSpan, isToolSpanName } from './lineage.js';
|
|
4
4
|
import { FilteringSpanExporter, otlpContentMode } from './otlpFilter.js';
|
|
5
5
|
import { telemetryRedactor } from './redact.js';
|
|
6
|
-
import { chargeLlmCall, chargeTokens } from '../runtime/turnControl.js';
|
|
6
|
+
import { chargeLlmCall, chargeTokens, turnUntraced } from '../runtime/turnControl.js';
|
|
7
7
|
import sdkNode from '@opentelemetry/sdk-trace-node';
|
|
8
8
|
const { NodeTracerProvider } = sdkNode;
|
|
9
9
|
import sdkBase from '@opentelemetry/sdk-trace-base';
|
|
@@ -275,6 +275,26 @@ export function initializeTracing() {
|
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
const tracer = trace.getTracer('melchizedek-tracer');
|
|
278
|
+
/**
|
|
279
|
+
* A span that records nothing, for code running in a turn that opted out of
|
|
280
|
+
* tracing (`runSyndicateTurn({ trace: false })`, turnUntraced): its
|
|
281
|
+
* attributes, events and end go nowhere, and no tracer is started for it.
|
|
282
|
+
*/
|
|
283
|
+
function nonRecordingSpan() {
|
|
284
|
+
return trace.wrapSpanContext(INVALID_SPAN_CONTEXT);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Starts a span on the named tracer, starting the tracer first; in a turn
|
|
288
|
+
* that opted out of tracing, a non-recording span and no tracer. Every span
|
|
289
|
+
* the engine opens inside a turn goes through here or checks turnUntraced
|
|
290
|
+
* itself.
|
|
291
|
+
*/
|
|
292
|
+
export function startEngineSpan(tracerName, name, options) {
|
|
293
|
+
if (turnUntraced())
|
|
294
|
+
return nonRecordingSpan();
|
|
295
|
+
initializeTracing();
|
|
296
|
+
return trace.getTracer(tracerName).startSpan(name, options);
|
|
297
|
+
}
|
|
278
298
|
/** Turn identity by trace id, so llm.request children can carry it too. */
|
|
279
299
|
const turnContexts = new Map();
|
|
280
300
|
/**
|
|
@@ -328,6 +348,11 @@ export function callerSpanContext(traceparent) {
|
|
|
328
348
|
return trace.getSpanContext(ctx);
|
|
329
349
|
}
|
|
330
350
|
export async function* traceAgentRun(stream, metadata) {
|
|
351
|
+
// A turn that opted out of tracing gets its events untouched and no span.
|
|
352
|
+
if (turnUntraced()) {
|
|
353
|
+
yield* stream;
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
331
356
|
initializeTracing();
|
|
332
357
|
const caller = callerSpanContext(metadata.traceparent);
|
|
333
358
|
const span = tracer.startSpan(`Syndicate Execution: ${metadata.syndicateName}`, caller ? { links: [{ context: caller }], attributes: { 'caller.trace_id': caller.traceId } } : undefined);
|
|
@@ -551,7 +576,10 @@ function refineErrorCode(code, message) {
|
|
|
551
576
|
* (e.g. llm.web_search.native) via setLlmSpanAttribute below.
|
|
552
577
|
*/
|
|
553
578
|
export async function* traceLlmGeneration(meta, inner) {
|
|
554
|
-
|
|
579
|
+
// An untraced turn still charges the call and its tokens; it opens no span.
|
|
580
|
+
const untraced = turnUntraced();
|
|
581
|
+
if (!untraced)
|
|
582
|
+
initializeTracing();
|
|
555
583
|
// Every model call on every provider passes here, so this is where the
|
|
556
584
|
// turn's step budget and cancellation are enforced (lib/runtime/
|
|
557
585
|
// turnControl.ts). A refused call never reaches the provider.
|
|
@@ -561,7 +589,7 @@ export async function* traceLlmGeneration(meta, inner) {
|
|
|
561
589
|
yield { errorCode: charge.code, errorMessage: charge.message };
|
|
562
590
|
return;
|
|
563
591
|
}
|
|
564
|
-
const span = tracer.startSpan('llm.request');
|
|
592
|
+
const span = untraced ? nonRecordingSpan() : tracer.startSpan('llm.request');
|
|
565
593
|
span.setAttribute('llm.provider', meta.provider);
|
|
566
594
|
span.setAttribute('llm.model', meta.model);
|
|
567
595
|
// OpenTelemetry GenAI semantic conventions alongside the llm.* names, so
|
|
@@ -633,7 +661,7 @@ export async function* traceLlmGeneration(meta, inner) {
|
|
|
633
661
|
if (thinkingPreview) {
|
|
634
662
|
span.addEvent('llm.thinking', { 'thinking.preview': thinkingPreview });
|
|
635
663
|
}
|
|
636
|
-
if (errorCode) {
|
|
664
|
+
if (errorCode && span.isRecording()) {
|
|
637
665
|
span.setAttribute('llm.error_code', errorCode);
|
|
638
666
|
span.setAttribute('llm.error_message', errorMessage.slice(0, ERROR_MESSAGE_MAX_CHARS));
|
|
639
667
|
// Make this span a payload candidate (see supabaseSpanExporter's
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/onboarding.ts — the authentication levels and their startup guides.
|
|
3
|
+
*
|
|
4
|
+
* WHY this file exists:
|
|
5
|
+
* A newcomer arrives with something: no key, one provider's key, several, a
|
|
6
|
+
* gateway key, a cloud account, a server to put in front of other people,
|
|
7
|
+
* or a ChatGPT / Claude.ai / Gemini CLI sign-in. Each of those is a
|
|
8
|
+
* different first ten minutes. This module names those levels once, from
|
|
9
|
+
* what the engine actually supports (lib/models/providerMap.ts,
|
|
10
|
+
* endpoints.ts, gateway.ts, the A2A server's identity modes and the OAuth
|
|
11
|
+
* grant setup), and renders one startup guide per level. The
|
|
12
|
+
* `melchizedek-setup` menu prints these guides and ONBOARDING.md is
|
|
13
|
+
* generated from the same function, so the two cannot drift
|
|
14
|
+
* (tests/onboarding.test.ts holds them equal).
|
|
15
|
+
*
|
|
16
|
+
* DETECTION IS THE DOCTOR'S:
|
|
17
|
+
* `detectLevels` reads a DoctorResult (lib/doctor.ts: the providers line,
|
|
18
|
+
* the gateway, the cloud endpoints, the serving and OAuth lines). It never
|
|
19
|
+
* reads a key itself, so `--auto` cannot disagree with the doctor.
|
|
20
|
+
*
|
|
21
|
+
* WHAT IT NEVER DOES:
|
|
22
|
+
* print a value. Guides carry variable NAMES and SHAPES; detection carries
|
|
23
|
+
* names and set/unset. Writing `.env` (writeEnvForLevel) copies
|
|
24
|
+
* `.env.example`, leaves every chosen name blank, refuses to overwrite an
|
|
25
|
+
* existing file, and refuses unless `git check-ignore` says `.env` is
|
|
26
|
+
* ignored (secrets-hygiene).
|
|
27
|
+
*/
|
|
28
|
+
import type { DoctorResult, Tier } from './doctor.ts';
|
|
29
|
+
export type LevelId = 'local' | 'one-provider' | 'several-providers' | 'gateway' | 'cloud-platform' | 'byok' | 'caller-tokens' | 'oauth-grants' | 'subscription-signin';
|
|
30
|
+
/** How a command is spelled: in a project that installed the package, or in a clone of the repository. */
|
|
31
|
+
export type CommandForm = 'package' | 'clone';
|
|
32
|
+
export interface EnvLine {
|
|
33
|
+
name: string;
|
|
34
|
+
/** The shape of the value, never a value. */
|
|
35
|
+
shape: string;
|
|
36
|
+
/** What setting it does. */
|
|
37
|
+
purpose: string;
|
|
38
|
+
}
|
|
39
|
+
export interface Level {
|
|
40
|
+
id: LevelId;
|
|
41
|
+
/** The menu line: what the user has. */
|
|
42
|
+
menu: string;
|
|
43
|
+
title: string;
|
|
44
|
+
summary: string;
|
|
45
|
+
env: EnvLine[];
|
|
46
|
+
/** What the doctor shows when this level is set up. */
|
|
47
|
+
confirm: string;
|
|
48
|
+
/** Shipped syndicates that run at this level, rendered by `shippedFor`. */
|
|
49
|
+
runs: (shipped: ShippedIndex) => string[];
|
|
50
|
+
first: Record<CommandForm, string[]>;
|
|
51
|
+
notes: string[];
|
|
52
|
+
/** The onboarding skill a coding agent follows for this level. */
|
|
53
|
+
skill: string;
|
|
54
|
+
/** False for an entry that is not a way to run the engine (subscription sign-ins). */
|
|
55
|
+
detectable: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** Shipped templates and examples by the tier their models imply, and which declare an OAuth grant. */
|
|
58
|
+
export interface ShippedIndex {
|
|
59
|
+
byTier: Partial<Record<Tier, string[]>>;
|
|
60
|
+
withGrants: string[];
|
|
61
|
+
/** Files that carry a commented-out `oauth2:` grant to start from. */
|
|
62
|
+
grantExamples: string[];
|
|
63
|
+
templates: string[];
|
|
64
|
+
}
|
|
65
|
+
/** The package (or clone) root: the directory holding config/agents/syndicate.schema.json. */
|
|
66
|
+
export declare function packageRoot(from?: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Index the shipped templates and examples by tier, using the doctor's own
|
|
69
|
+
* diagnosis (lib/doctor.ts `diagnoseSyndicate`: the tier the models imply,
|
|
70
|
+
* and the OAuth grants the tools declare). The tier does not depend on the
|
|
71
|
+
* environment, so the index is the same wherever it is computed.
|
|
72
|
+
*/
|
|
73
|
+
export declare function shippedIndex(root?: string): ShippedIndex;
|
|
74
|
+
export declare const LEVELS: readonly Level[];
|
|
75
|
+
export declare function levelById(id: string): Level | undefined;
|
|
76
|
+
/** Every variable name the guides mention. */
|
|
77
|
+
export declare function guideEnvNames(): string[];
|
|
78
|
+
/** One level's startup guide, as Markdown (the terminal prints the same text). */
|
|
79
|
+
export declare function renderGuide(level: Level, form: CommandForm, shipped?: ShippedIndex): string;
|
|
80
|
+
/** The menu: one numbered line per level. */
|
|
81
|
+
export declare function renderMenu(): string;
|
|
82
|
+
/** ONBOARDING.md, generated in full from the levels (package spelling). */
|
|
83
|
+
export declare function renderOnboardingDoc(shipped?: ShippedIndex): string;
|
|
84
|
+
export interface LevelDetection {
|
|
85
|
+
id: LevelId;
|
|
86
|
+
detected: boolean;
|
|
87
|
+
/** Names and set/unset only. */
|
|
88
|
+
evidence: string;
|
|
89
|
+
/** The doctor's problems for this level, by variable name. */
|
|
90
|
+
problems: string[];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Which levels the environment is set up for, read from the doctor's result.
|
|
94
|
+
* Local is always available (whether Ollama is running is not checked).
|
|
95
|
+
*/
|
|
96
|
+
export declare function detectLevels(result: DoctorResult): LevelDetection[];
|
|
97
|
+
/** The highest detected level (the last in menu order). */
|
|
98
|
+
export declare function highestLevel(detections: LevelDetection[]): Level;
|
|
99
|
+
/** `--auto`: what the environment has (names only), then the guide for the highest level. */
|
|
100
|
+
export declare function renderAuto(result: DoctorResult, form: CommandForm, shipped?: ShippedIndex): string;
|
|
101
|
+
export type EnvWriteResult = {
|
|
102
|
+
status: 'written';
|
|
103
|
+
path: string;
|
|
104
|
+
added: string[];
|
|
105
|
+
} | {
|
|
106
|
+
status: 'exists';
|
|
107
|
+
path: string;
|
|
108
|
+
} | {
|
|
109
|
+
status: 'not-ignored';
|
|
110
|
+
path: string;
|
|
111
|
+
reason: string;
|
|
112
|
+
} | {
|
|
113
|
+
status: 'no-template';
|
|
114
|
+
path: string;
|
|
115
|
+
};
|
|
116
|
+
/** True when git confirms `.env` in `cwd` is ignored (exit 0 from `git check-ignore`). */
|
|
117
|
+
export declare function gitIgnoresEnv(cwd: string): {
|
|
118
|
+
ignored: boolean;
|
|
119
|
+
reason: string;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Create `.env` from `.env.example` for a level: the template verbatim, then
|
|
123
|
+
* every name the level lists that the template does not already assign, left
|
|
124
|
+
* blank. Never overwrites, never writes a value, and refuses unless git
|
|
125
|
+
* confirms `.env` is ignored. The file is created mode 600.
|
|
126
|
+
*/
|
|
127
|
+
export declare function writeEnvForLevel(level: Level, opts?: {
|
|
128
|
+
cwd?: string;
|
|
129
|
+
root?: string;
|
|
130
|
+
checkIgnored?: (cwd: string) => {
|
|
131
|
+
ignored: boolean;
|
|
132
|
+
reason: string;
|
|
133
|
+
};
|
|
134
|
+
}): EnvWriteResult;
|