@inbrowser/agent 0.0.0-placeholder → 0.1.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/AGENTS.md +270 -0
- package/README.md +117 -2
- package/bin/agent.ts +10 -0
- package/dist/cli/commands/describe.d.ts +14 -0
- package/dist/cli/commands/describe.d.ts.map +1 -0
- package/dist/cli/commands/describe.js +179 -0
- package/dist/cli/commands/describe.js.map +1 -0
- package/dist/cli/commands/events.d.ts +21 -0
- package/dist/cli/commands/events.d.ts.map +1 -0
- package/dist/cli/commands/events.js +59 -0
- package/dist/cli/commands/events.js.map +1 -0
- package/dist/cli/commands/fleet.d.ts +15 -0
- package/dist/cli/commands/fleet.d.ts.map +1 -0
- package/dist/cli/commands/fleet.js +149 -0
- package/dist/cli/commands/fleet.js.map +1 -0
- package/dist/cli/commands/help.d.ts +15 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/help.js +93 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +27 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +109 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/run.d.ts +38 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +535 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/schema.d.ts +8 -0
- package/dist/cli/commands/schema.d.ts.map +1 -0
- package/dist/cli/commands/schema.js +12 -0
- package/dist/cli/commands/schema.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +39 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +65 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/undo.d.ts +36 -0
- package/dist/cli/commands/undo.d.ts.map +1 -0
- package/dist/cli/commands/undo.js +132 -0
- package/dist/cli/commands/undo.js.map +1 -0
- package/dist/cli/fixtures.d.ts +17 -0
- package/dist/cli/fixtures.d.ts.map +1 -0
- package/dist/cli/fixtures.js +107 -0
- package/dist/cli/fixtures.js.map +1 -0
- package/dist/cli/hardening.d.ts +39 -0
- package/dist/cli/hardening.d.ts.map +1 -0
- package/dist/cli/hardening.js +68 -0
- package/dist/cli/hardening.js.map +1 -0
- package/dist/cli/index.d.ts +28 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/llm/openrouter.d.ts +33 -0
- package/dist/cli/llm/openrouter.d.ts.map +1 -0
- package/dist/cli/llm/openrouter.js +285 -0
- package/dist/cli/llm/openrouter.js.map +1 -0
- package/dist/cli/main.d.ts +32 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +106 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/output.d.ts +36 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +95 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/parse.d.ts +26 -0
- package/dist/cli/parse.d.ts.map +1 -0
- package/dist/cli/parse.js +160 -0
- package/dist/cli/parse.js.map +1 -0
- package/dist/cli/session-log.d.ts +34 -0
- package/dist/cli/session-log.d.ts.map +1 -0
- package/dist/cli/session-log.js +52 -0
- package/dist/cli/session-log.js.map +1 -0
- package/dist/cli/spec.d.ts +62 -0
- package/dist/cli/spec.d.ts.map +1 -0
- package/dist/cli/spec.js +510 -0
- package/dist/cli/spec.js.map +1 -0
- package/dist/cli/ui/RunView.d.ts +134 -0
- package/dist/cli/ui/RunView.d.ts.map +1 -0
- package/dist/cli/ui/RunView.js +341 -0
- package/dist/cli/ui/RunView.js.map +1 -0
- package/dist/events/codec.d.ts +79 -0
- package/dist/events/codec.d.ts.map +1 -0
- package/dist/events/codec.js +142 -0
- package/dist/events/codec.js.map +1 -0
- package/dist/events/log-core.d.ts +76 -0
- package/dist/events/log-core.d.ts.map +1 -0
- package/dist/events/log-core.js +73 -0
- package/dist/events/log-core.js.map +1 -0
- package/dist/events/log.d.ts +60 -0
- package/dist/events/log.d.ts.map +1 -0
- package/dist/events/log.js +193 -0
- package/dist/events/log.js.map +1 -0
- package/dist/events/replay.d.ts +106 -0
- package/dist/events/replay.d.ts.map +1 -0
- package/dist/events/replay.js +137 -0
- package/dist/events/replay.js.map +1 -0
- package/dist/events/wrap.d.ts +100 -0
- package/dist/events/wrap.d.ts.map +1 -0
- package/dist/events/wrap.js +141 -0
- package/dist/events/wrap.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-adapter.d.ts +96 -0
- package/dist/llm-adapter.d.ts.map +1 -0
- package/dist/llm-adapter.js +132 -0
- package/dist/llm-adapter.js.map +1 -0
- package/dist/mcp/serve.d.ts +70 -0
- package/dist/mcp/serve.d.ts.map +1 -0
- package/dist/mcp/serve.js +154 -0
- package/dist/mcp/serve.js.map +1 -0
- package/dist/metrics/runs.d.ts +58 -0
- package/dist/metrics/runs.d.ts.map +1 -0
- package/dist/metrics/runs.js +99 -0
- package/dist/metrics/runs.js.map +1 -0
- package/dist/metrics.d.ts +38 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +123 -0
- package/dist/metrics.js.map +1 -0
- package/dist/node.d.ts +22 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +22 -0
- package/dist/node.js.map +1 -0
- package/dist/session.d.ts +10 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +179 -0
- package/dist/session.js.map +1 -0
- package/dist/storage.d.ts +14 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +58 -0
- package/dist/storage.js.map +1 -0
- package/dist/strategy.d.ts +26 -0
- package/dist/strategy.d.ts.map +1 -0
- package/dist/strategy.js +200 -0
- package/dist/strategy.js.map +1 -0
- package/dist/tools.d.ts +26 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +129 -0
- package/dist/tools.js.map +1 -0
- package/dist/types/agent.d.ts +94 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +17 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/capabilities.d.ts +17 -0
- package/dist/types/capabilities.d.ts.map +1 -0
- package/dist/types/capabilities.js +13 -0
- package/dist/types/capabilities.js.map +1 -0
- package/dist/types/chat.d.ts +74 -0
- package/dist/types/chat.d.ts.map +1 -0
- package/dist/types/chat.js +10 -0
- package/dist/types/chat.js.map +1 -0
- package/dist/types/events.d.ts +115 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +30 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/llm.d.ts +89 -0
- package/dist/types/llm.d.ts.map +1 -0
- package/dist/types/llm.js +12 -0
- package/dist/types/llm.js.map +1 -0
- package/dist/types/metrics.d.ts +34 -0
- package/dist/types/metrics.d.ts.map +1 -0
- package/dist/types/metrics.js +10 -0
- package/dist/types/metrics.js.map +1 -0
- package/dist/types/observer.d.ts +41 -0
- package/dist/types/observer.d.ts.map +1 -0
- package/dist/types/observer.js +41 -0
- package/dist/types/observer.js.map +1 -0
- package/dist/types/project-context.d.ts +18 -0
- package/dist/types/project-context.d.ts.map +1 -0
- package/dist/types/project-context.js +11 -0
- package/dist/types/project-context.js.map +1 -0
- package/dist/types/runtime.d.ts +71 -0
- package/dist/types/runtime.d.ts.map +1 -0
- package/dist/types/runtime.js +21 -0
- package/dist/types/runtime.js.map +1 -0
- package/dist/types/session.d.ts +103 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +11 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/storage.d.ts +20 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/storage.js +41 -0
- package/dist/types/storage.js.map +1 -0
- package/dist/types/strategy.d.ts +76 -0
- package/dist/types/strategy.d.ts.map +1 -0
- package/dist/types/strategy.js +10 -0
- package/dist/types/strategy.js.map +1 -0
- package/dist/types/tools.d.ts +136 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +11 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/types/trace.d.ts +125 -0
- package/dist/types/trace.d.ts.map +1 -0
- package/dist/types/trace.js +24 -0
- package/dist/types/trace.js.map +1 -0
- package/dist/types/workspace.d.ts +29 -0
- package/dist/types/workspace.d.ts.map +1 -0
- package/dist/types/workspace.js +18 -0
- package/dist/types/workspace.js.map +1 -0
- package/package.json +45 -14
- package/skills/agent-cli.md +218 -0
- package/index.js +0 -2
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter from the playground's existing `LlmProvider` shape to the
|
|
3
|
+
* core `LlmClient` interface. Lets new core code (AgentSession,
|
|
4
|
+
* AgentStrategy) consume providers via the narrow event-stream
|
|
5
|
+
* surface without each provider needing a refactor.
|
|
6
|
+
*
|
|
7
|
+
* The existing `LlmProvider` is callback-based (`onText`,
|
|
8
|
+
* `onToolCall`, etc.) and lives in the React host alongside its
|
|
9
|
+
* BYOK forms + localStorage wiring. This file flips it into the
|
|
10
|
+
* `AsyncIterable<ChatEvent>` shape the core wants.
|
|
11
|
+
*
|
|
12
|
+
* Each provider can later migrate to natively implement `LlmClient`
|
|
13
|
+
* to drop this adapter. The plan calls this "slice 4 — one
|
|
14
|
+
* provider at a time"; the adapter exists so slice 4 doesn't have
|
|
15
|
+
* to land atomically.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Wrap a legacy `LlmProvider` instance in the `LlmClient` shape.
|
|
19
|
+
* The adapter:
|
|
20
|
+
*
|
|
21
|
+
* - Translates `ChatRequest` → legacy `chatWithTools` / `ask`
|
|
22
|
+
* call.
|
|
23
|
+
* - Buffers callback events into an async queue and replays them
|
|
24
|
+
* as a `ChatEvent` `AsyncIterable`.
|
|
25
|
+
* - Forwards the final usage + details as a `turn_complete`
|
|
26
|
+
* event before closing the stream.
|
|
27
|
+
*/
|
|
28
|
+
export function legacyProviderAsLlmClient(legacy, id) {
|
|
29
|
+
return {
|
|
30
|
+
id,
|
|
31
|
+
supportsTools: legacy.supportsTools ?? typeof legacy.chatWithTools === 'function',
|
|
32
|
+
chat(req, signal) {
|
|
33
|
+
return drive(legacy, req, signal);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async function* drive(legacy, req, signal) {
|
|
38
|
+
const queue = [];
|
|
39
|
+
let resolver = null;
|
|
40
|
+
let done = false;
|
|
41
|
+
function push(ev) {
|
|
42
|
+
queue.push(ev);
|
|
43
|
+
resolver?.();
|
|
44
|
+
resolver = null;
|
|
45
|
+
}
|
|
46
|
+
function finish() {
|
|
47
|
+
done = true;
|
|
48
|
+
resolver?.();
|
|
49
|
+
resolver = null;
|
|
50
|
+
}
|
|
51
|
+
const callbacks = {
|
|
52
|
+
onText: (chunk) => push({ kind: 'text', chunk }),
|
|
53
|
+
onThinking: (chunk) => push({ kind: 'thinking', chunk }),
|
|
54
|
+
onToolCall: (call) => push({
|
|
55
|
+
kind: 'tool_call',
|
|
56
|
+
id: call.callId,
|
|
57
|
+
name: call.name,
|
|
58
|
+
args: call.args,
|
|
59
|
+
signature: call.signature,
|
|
60
|
+
}),
|
|
61
|
+
signal,
|
|
62
|
+
};
|
|
63
|
+
const messagesLegacy = req.messages.map((m) => ({
|
|
64
|
+
role: m.role,
|
|
65
|
+
text: m.text,
|
|
66
|
+
...(m.toolCalls ? { toolCalls: m.toolCalls } : {}),
|
|
67
|
+
...(m.callId ? { callId: m.callId } : {}),
|
|
68
|
+
...(m.name ? { name: m.name } : {}),
|
|
69
|
+
...(m.resultJson !== undefined ? { resultJson: m.resultJson } : {}),
|
|
70
|
+
}));
|
|
71
|
+
const toolsLegacy = req.tools.map((t) => ({
|
|
72
|
+
name: t.name,
|
|
73
|
+
description: t.description,
|
|
74
|
+
parameters: t.parameters,
|
|
75
|
+
}));
|
|
76
|
+
let result;
|
|
77
|
+
let error;
|
|
78
|
+
const driver = (async () => {
|
|
79
|
+
try {
|
|
80
|
+
if (req.toolUseEnabled && legacy.chatWithTools) {
|
|
81
|
+
result = await legacy.chatWithTools(messagesLegacy, toolsLegacy, callbacks);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// Plain-chat path — flatten messages into a single prompt.
|
|
85
|
+
const prompt = messagesLegacy
|
|
86
|
+
.filter((m) => m.role === 'user' || m.role === 'system')
|
|
87
|
+
.map((m) => m.text ?? '')
|
|
88
|
+
.filter(Boolean)
|
|
89
|
+
.join('\n\n');
|
|
90
|
+
result = await legacy.ask(prompt, callbacks.onText, { signal });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
error = e;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
finish();
|
|
98
|
+
}
|
|
99
|
+
})();
|
|
100
|
+
while (!done || queue.length > 0) {
|
|
101
|
+
if (queue.length === 0) {
|
|
102
|
+
await new Promise((r) => {
|
|
103
|
+
resolver = r;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const next = queue.shift();
|
|
107
|
+
if (next)
|
|
108
|
+
yield next;
|
|
109
|
+
}
|
|
110
|
+
await driver;
|
|
111
|
+
if (error) {
|
|
112
|
+
yield { kind: 'error', message: error instanceof Error ? error.message : String(error) };
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (result) {
|
|
116
|
+
const rawUsage = {
|
|
117
|
+
promptTokens: result.usage?.promptTokens ?? 0,
|
|
118
|
+
completionTokens: result.usage?.outputTokens ?? 0,
|
|
119
|
+
cachedTokens: result.usage?.cachedTokens,
|
|
120
|
+
reasoningTokens: result.usage?.reasoningTokens,
|
|
121
|
+
...(typeof result.usage?.costUsd === 'number' ? { costUsd: result.usage.costUsd } : {}),
|
|
122
|
+
};
|
|
123
|
+
const details = {
|
|
124
|
+
requestedModel: result.details?.requestedModel ?? '',
|
|
125
|
+
...(result.details?.servedModel ? { servedModel: result.details.servedModel } : {}),
|
|
126
|
+
...(result.details?.fingerprint ? { fingerprint: result.details.fingerprint } : {}),
|
|
127
|
+
...(result.details?.routing ? { routing: result.details.routing } : {}),
|
|
128
|
+
};
|
|
129
|
+
yield { kind: 'turn_complete', usage: rawUsage, details };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=llm-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-adapter.js","sourceRoot":"","sources":["../src/llm-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverse-mode MCP serve adapter — exposes a set of `AgentDefinition`s
|
|
3
|
+
* as stdio MCP tools an external host (Claude Code, Claude Desktop,
|
|
4
|
+
* Cursor, ...) can call.
|
|
5
|
+
*
|
|
6
|
+
* Wire model: each `AgentDefinition.tools[i]` becomes one MCP tool
|
|
7
|
+
* registered under its own behavior-name verbatim. The host LLM matches
|
|
8
|
+
* user intent against `description`; nothing about the `AgentDefinition`
|
|
9
|
+
* itself surfaces. (Developers see definitions; LLMs see tools.)
|
|
10
|
+
*
|
|
11
|
+
* The transport is stdio. This module deliberately writes nothing to
|
|
12
|
+
* stdout — the MCP transport owns that file descriptor. Startup logs
|
|
13
|
+
* and per-call traces go to stderr.
|
|
14
|
+
*/
|
|
15
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
16
|
+
import type { EventLog } from '../events/log-core.js';
|
|
17
|
+
import { type RunLog } from '../metrics/runs.js';
|
|
18
|
+
import type { AgentDefinition, AgentTool } from '../types/agent.js';
|
|
19
|
+
import type { ProjectContext } from '../types/project-context.js';
|
|
20
|
+
export interface ServeAgentsOptions {
|
|
21
|
+
agents: AgentDefinition[];
|
|
22
|
+
/** Firebase project id — routes event log + runs log paths. */
|
|
23
|
+
projectId: string;
|
|
24
|
+
/** Override `~/.pyric/projects` for tests. */
|
|
25
|
+
eventsDir?: string;
|
|
26
|
+
/** Override the runs log directory. Defaults to `eventsDir`. */
|
|
27
|
+
runsDir?: string;
|
|
28
|
+
/** Server identity advertised in the MCP handshake. */
|
|
29
|
+
serverName?: string;
|
|
30
|
+
serverVersion?: string;
|
|
31
|
+
/** Injectable clock. */
|
|
32
|
+
now?: () => number;
|
|
33
|
+
/** Stream for diagnostic messages. Defaults to process.stderr. */
|
|
34
|
+
stderr?: NodeJS.WriteStream;
|
|
35
|
+
/**
|
|
36
|
+
* Initialized `ProjectContext`. Pass through to every
|
|
37
|
+
* `AgentContext` so tools that need live project access (e.g.
|
|
38
|
+
* `audit_firestore_backend` in `projectId` mode) can use it.
|
|
39
|
+
* The caller is responsible for initialization — usually via
|
|
40
|
+
* `toProjectContext(await initializeAgentApp())` after reading
|
|
41
|
+
* FIREBASE_SA_BASE64.
|
|
42
|
+
*/
|
|
43
|
+
agentApp?: ProjectContext;
|
|
44
|
+
}
|
|
45
|
+
export interface ServeAgentsHandle {
|
|
46
|
+
/** Close the event/run logs and the MCP server. */
|
|
47
|
+
close(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build a stdio MCP server exposing the given agents' tools. Connects
|
|
51
|
+
* immediately and resolves once the transport is wired. The returned
|
|
52
|
+
* handle lets tests shut down cleanly; in production the process
|
|
53
|
+
* terminates with the parent (Claude Code, etc.).
|
|
54
|
+
*/
|
|
55
|
+
export declare function serveAgentsOverStdio(opts: ServeAgentsOptions): Promise<ServeAgentsHandle>;
|
|
56
|
+
/**
|
|
57
|
+
* Lower-level entrypoint — builds the MCP server + logs without
|
|
58
|
+
* connecting to a transport. Used by tests to drive request handlers
|
|
59
|
+
* directly without spawning a stdio transport.
|
|
60
|
+
*/
|
|
61
|
+
export declare function buildServer(opts: ServeAgentsOptions): {
|
|
62
|
+
server: Server;
|
|
63
|
+
eventLog: EventLog;
|
|
64
|
+
runLog: RunLog;
|
|
65
|
+
toolsByName: Map<string, {
|
|
66
|
+
agent: AgentDefinition;
|
|
67
|
+
tool: AgentTool;
|
|
68
|
+
}>;
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/mcp/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,KAAK,MAAM,EAA6C,MAAM,oBAAoB,CAAC;AAC5F,OAAO,KAAK,EAAgB,eAAe,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;IAC5B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAiB/F;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,eAAe,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;CACvE,CAwHA"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverse-mode MCP serve adapter — exposes a set of `AgentDefinition`s
|
|
3
|
+
* as stdio MCP tools an external host (Claude Code, Claude Desktop,
|
|
4
|
+
* Cursor, ...) can call.
|
|
5
|
+
*
|
|
6
|
+
* Wire model: each `AgentDefinition.tools[i]` becomes one MCP tool
|
|
7
|
+
* registered under its own behavior-name verbatim. The host LLM matches
|
|
8
|
+
* user intent against `description`; nothing about the `AgentDefinition`
|
|
9
|
+
* itself surfaces. (Developers see definitions; LLMs see tools.)
|
|
10
|
+
*
|
|
11
|
+
* The transport is stdio. This module deliberately writes nothing to
|
|
12
|
+
* stdout — the MCP transport owns that file descriptor. Startup logs
|
|
13
|
+
* and per-call traces go to stderr.
|
|
14
|
+
*/
|
|
15
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
16
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
17
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
18
|
+
import { openEventLog } from '../events/log.js';
|
|
19
|
+
import { generateRunId, openRunLog } from '../metrics/runs.js';
|
|
20
|
+
/**
|
|
21
|
+
* Build a stdio MCP server exposing the given agents' tools. Connects
|
|
22
|
+
* immediately and resolves once the transport is wired. The returned
|
|
23
|
+
* handle lets tests shut down cleanly; in production the process
|
|
24
|
+
* terminates with the parent (Claude Code, etc.).
|
|
25
|
+
*/
|
|
26
|
+
export async function serveAgentsOverStdio(opts) {
|
|
27
|
+
const { server, eventLog, runLog } = buildServer(opts);
|
|
28
|
+
const transport = new StdioServerTransport();
|
|
29
|
+
await server.connect(transport);
|
|
30
|
+
writeStderr(opts.stderr, `[pyric/agents] mcp server up · project=${opts.projectId} · agents=${opts.agents
|
|
31
|
+
.map((a) => a.name)
|
|
32
|
+
.join(',')}\n`);
|
|
33
|
+
return {
|
|
34
|
+
async close() {
|
|
35
|
+
await server.close();
|
|
36
|
+
runLog.close();
|
|
37
|
+
eventLog.close();
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Lower-level entrypoint — builds the MCP server + logs without
|
|
43
|
+
* connecting to a transport. Used by tests to drive request handlers
|
|
44
|
+
* directly without spawning a stdio transport.
|
|
45
|
+
*/
|
|
46
|
+
export function buildServer(opts) {
|
|
47
|
+
if (opts.agents.length === 0) {
|
|
48
|
+
throw new Error('serveAgentsOverStdio: at least one AgentDefinition is required');
|
|
49
|
+
}
|
|
50
|
+
const eventLog = openEventLog({
|
|
51
|
+
projectId: opts.projectId,
|
|
52
|
+
logDir: opts.eventsDir,
|
|
53
|
+
now: opts.now,
|
|
54
|
+
});
|
|
55
|
+
const runLog = openRunLog({
|
|
56
|
+
projectId: opts.projectId,
|
|
57
|
+
logDir: opts.runsDir ?? opts.eventsDir,
|
|
58
|
+
now: opts.now,
|
|
59
|
+
});
|
|
60
|
+
const toolsByName = new Map();
|
|
61
|
+
for (const agent of opts.agents) {
|
|
62
|
+
for (const tool of agent.tools) {
|
|
63
|
+
if (toolsByName.has(tool.name)) {
|
|
64
|
+
throw new Error(`serveAgentsOverStdio: duplicate tool name "${tool.name}" across agents (registered by ${toolsByName.get(tool.name).agent.name} and ${agent.name})`);
|
|
65
|
+
}
|
|
66
|
+
toolsByName.set(tool.name, { agent, tool });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const server = new Server({
|
|
70
|
+
name: opts.serverName ?? 'pyric-agents',
|
|
71
|
+
version: opts.serverVersion ?? '0.0.0',
|
|
72
|
+
}, { capabilities: { tools: {} } });
|
|
73
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
74
|
+
return {
|
|
75
|
+
tools: Array.from(toolsByName.values()).map(({ tool }) => ({
|
|
76
|
+
name: tool.name,
|
|
77
|
+
description: tool.description,
|
|
78
|
+
inputSchema: tool.inputSchema,
|
|
79
|
+
})),
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
83
|
+
const { name, arguments: args } = req.params;
|
|
84
|
+
const entry = toolsByName.get(name);
|
|
85
|
+
if (!entry) {
|
|
86
|
+
return {
|
|
87
|
+
content: [
|
|
88
|
+
{
|
|
89
|
+
type: 'text',
|
|
90
|
+
text: JSON.stringify({ ok: false, summary: `unknown tool: ${name}` }),
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
isError: true,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const runId = generateRunId(opts.now);
|
|
97
|
+
const ts = new Date((opts.now ?? Date.now)()).toISOString();
|
|
98
|
+
const startedAt = (opts.now ?? Date.now)();
|
|
99
|
+
const ctx = {
|
|
100
|
+
runId,
|
|
101
|
+
projectId: opts.projectId,
|
|
102
|
+
events: eventLog,
|
|
103
|
+
signal: new AbortController().signal,
|
|
104
|
+
now: opts.now,
|
|
105
|
+
...(opts.agentApp ? { agentApp: opts.agentApp } : {}),
|
|
106
|
+
};
|
|
107
|
+
let outcome = 'ok';
|
|
108
|
+
let errorSummary;
|
|
109
|
+
let planHash;
|
|
110
|
+
let eventIds = [];
|
|
111
|
+
let payload;
|
|
112
|
+
try {
|
|
113
|
+
const result = await entry.tool.execute(args ?? {}, ctx);
|
|
114
|
+
outcome = result.ok ? 'ok' : 'failed';
|
|
115
|
+
planHash = result.planHash;
|
|
116
|
+
eventIds = result.eventIds ?? [];
|
|
117
|
+
payload = result;
|
|
118
|
+
if (!result.ok)
|
|
119
|
+
errorSummary = result.summary;
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
outcome = 'failed';
|
|
123
|
+
errorSummary = err instanceof Error ? err.message : String(err);
|
|
124
|
+
payload = { ok: false, summary: errorSummary, eventIds: [] };
|
|
125
|
+
}
|
|
126
|
+
const record = {
|
|
127
|
+
runId,
|
|
128
|
+
ts,
|
|
129
|
+
agent: entry.agent.name,
|
|
130
|
+
tool: entry.tool.name,
|
|
131
|
+
mode: 'inverse',
|
|
132
|
+
outcome,
|
|
133
|
+
durationMs: Math.max(0, (opts.now ?? Date.now)() - startedAt),
|
|
134
|
+
...(planHash ? { planHash } : {}),
|
|
135
|
+
eventIds,
|
|
136
|
+
...(errorSummary ? { errorSummary } : {}),
|
|
137
|
+
};
|
|
138
|
+
runLog.append(record);
|
|
139
|
+
return {
|
|
140
|
+
content: [
|
|
141
|
+
{
|
|
142
|
+
type: 'text',
|
|
143
|
+
text: JSON.stringify(payload),
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
...(outcome === 'failed' ? { isError: true } : {}),
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
return { server, eventLog, runLog, toolsByName };
|
|
150
|
+
}
|
|
151
|
+
function writeStderr(stream, msg) {
|
|
152
|
+
(stream ?? process.stderr).write(msg);
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/mcp/serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-call run record — `~/.pyric/projects/<projectId>/runs.ndjson`.
|
|
3
|
+
*
|
|
4
|
+
* Distinct from `events.ndjson` (mutation audit) and
|
|
5
|
+
* `<sessionId>.ndjson` (per-session event stream). Runs is a single,
|
|
6
|
+
* project-scoped, append-only NDJSON file that captures one record per
|
|
7
|
+
* agent tool invocation. The schema carries a `mode` discriminator so
|
|
8
|
+
* inference-mode and inverse-mode runs land in the same file for easy
|
|
9
|
+
* A/B comparison.
|
|
10
|
+
*
|
|
11
|
+
* Why a separate file rather than reusing the session log: a session
|
|
12
|
+
* log scopes to one conversation; a run record scopes to one *call*
|
|
13
|
+
* across modes. The host-driven (inverse) flow has no session id —
|
|
14
|
+
* each MCP tool call is its own run.
|
|
15
|
+
*/
|
|
16
|
+
import type { EventLogIO } from '../events/log.js';
|
|
17
|
+
export interface RunRecord {
|
|
18
|
+
/** Time-prefixed base36; sortable by emission order. */
|
|
19
|
+
runId: string;
|
|
20
|
+
/** ISO-8601 timestamp. */
|
|
21
|
+
ts: string;
|
|
22
|
+
/** AgentDefinition.name, e.g. 'hello-firestore'. */
|
|
23
|
+
agent: string;
|
|
24
|
+
/** AgentTool.name, e.g. 'design_firestore_hello_schema'. */
|
|
25
|
+
tool: string;
|
|
26
|
+
/** Discriminator across the dual-mode story. */
|
|
27
|
+
mode: 'inference' | 'inverse';
|
|
28
|
+
outcome: 'ok' | 'failed';
|
|
29
|
+
durationMs: number;
|
|
30
|
+
/** Hash a preview tool returned; consumed by the commit tool. */
|
|
31
|
+
planHash?: string;
|
|
32
|
+
/** Event log ids written this call. */
|
|
33
|
+
eventIds: string[];
|
|
34
|
+
/** Truncated error message when outcome !== 'ok'. */
|
|
35
|
+
errorSummary?: string;
|
|
36
|
+
}
|
|
37
|
+
export type RunRecordFilter = Partial<Pick<RunRecord, 'agent' | 'tool' | 'mode' | 'outcome'>>;
|
|
38
|
+
export interface RunLog {
|
|
39
|
+
readonly path: string;
|
|
40
|
+
readonly projectId: string;
|
|
41
|
+
append(record: RunRecord): void;
|
|
42
|
+
read(filter?: RunRecordFilter): RunRecord[];
|
|
43
|
+
close(): void;
|
|
44
|
+
}
|
|
45
|
+
export interface OpenRunLogOptions {
|
|
46
|
+
projectId: string;
|
|
47
|
+
/** Defaults to `~/.pyric/projects`. */
|
|
48
|
+
logDir?: string;
|
|
49
|
+
/** Injectable IO for tests. Same shape as `events/log.ts`. */
|
|
50
|
+
io?: EventLogIO;
|
|
51
|
+
/** Injectable clock. */
|
|
52
|
+
now?: () => number;
|
|
53
|
+
}
|
|
54
|
+
export declare function defaultRunsLogDir(): string;
|
|
55
|
+
/** Time-prefixed base36 id; matches generateEventId's shape. */
|
|
56
|
+
export declare function generateRunId(now?: () => number): string;
|
|
57
|
+
export declare function openRunLog(opts: OpenRunLogOptions): RunLog;
|
|
58
|
+
//# sourceMappingURL=runs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/metrics/runs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,IAAI,GAAG,QAAQ,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAE9F,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,EAAE,CAAC;IAC5C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AASD,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAM,MAAiB,GAAG,MAAM,CAIlE;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CA4D1D"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-call run record — `~/.pyric/projects/<projectId>/runs.ndjson`.
|
|
3
|
+
*
|
|
4
|
+
* Distinct from `events.ndjson` (mutation audit) and
|
|
5
|
+
* `<sessionId>.ndjson` (per-session event stream). Runs is a single,
|
|
6
|
+
* project-scoped, append-only NDJSON file that captures one record per
|
|
7
|
+
* agent tool invocation. The schema carries a `mode` discriminator so
|
|
8
|
+
* inference-mode and inverse-mode runs land in the same file for easy
|
|
9
|
+
* A/B comparison.
|
|
10
|
+
*
|
|
11
|
+
* Why a separate file rather than reusing the session log: a session
|
|
12
|
+
* log scopes to one conversation; a run record scopes to one *call*
|
|
13
|
+
* across modes. The host-driven (inverse) flow has no session id —
|
|
14
|
+
* each MCP tool call is its own run.
|
|
15
|
+
*/
|
|
16
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
17
|
+
import { homedir } from 'node:os';
|
|
18
|
+
const DEFAULT_IO = {
|
|
19
|
+
existsSync,
|
|
20
|
+
mkdirSync,
|
|
21
|
+
appendFileSync,
|
|
22
|
+
readFileSync,
|
|
23
|
+
};
|
|
24
|
+
export function defaultRunsLogDir() {
|
|
25
|
+
return `${homedir()}/.pyric/projects`;
|
|
26
|
+
}
|
|
27
|
+
/** Time-prefixed base36 id; matches generateEventId's shape. */
|
|
28
|
+
export function generateRunId(now = Date.now) {
|
|
29
|
+
const ts = now().toString(36).padStart(9, '0');
|
|
30
|
+
const rand = Math.random().toString(36).slice(2, 8);
|
|
31
|
+
return `run-${ts}-${rand}`;
|
|
32
|
+
}
|
|
33
|
+
export function openRunLog(opts) {
|
|
34
|
+
if (!/^[a-zA-Z0-9_.-]+$/.test(opts.projectId)) {
|
|
35
|
+
throw new Error(`openRunLog: projectId ${JSON.stringify(opts.projectId)} contains disallowed characters; use [a-zA-Z0-9_.-]+`);
|
|
36
|
+
}
|
|
37
|
+
const io = opts.io ?? DEFAULT_IO;
|
|
38
|
+
const baseDir = opts.logDir ?? defaultRunsLogDir();
|
|
39
|
+
const projectDir = `${baseDir.replace(/\/$/, '')}/${opts.projectId}`;
|
|
40
|
+
const path = `${projectDir}/runs.ndjson`;
|
|
41
|
+
if (!io.existsSync(projectDir))
|
|
42
|
+
io.mkdirSync(projectDir, { recursive: true });
|
|
43
|
+
let closed = false;
|
|
44
|
+
function ensureOpen() {
|
|
45
|
+
if (closed)
|
|
46
|
+
throw new Error(`run log ${path} is closed`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
path,
|
|
50
|
+
projectId: opts.projectId,
|
|
51
|
+
append(record) {
|
|
52
|
+
ensureOpen();
|
|
53
|
+
// appendFileSync mirrors the events-log atomicity story: one
|
|
54
|
+
// syscall per record so concurrent writers can't interleave
|
|
55
|
+
// mid-line on Linux + macOS.
|
|
56
|
+
io.appendFileSync(path, JSON.stringify(record) + '\n');
|
|
57
|
+
},
|
|
58
|
+
read(filter) {
|
|
59
|
+
ensureOpen();
|
|
60
|
+
if (!io.existsSync(path))
|
|
61
|
+
return [];
|
|
62
|
+
const raw = io.readFileSync(path, 'utf8');
|
|
63
|
+
if (!raw)
|
|
64
|
+
return [];
|
|
65
|
+
const out = [];
|
|
66
|
+
for (const line of raw.split('\n')) {
|
|
67
|
+
if (!line)
|
|
68
|
+
continue;
|
|
69
|
+
let parsed;
|
|
70
|
+
try {
|
|
71
|
+
parsed = JSON.parse(line);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (filter) {
|
|
77
|
+
if (filter.agent && parsed.agent !== filter.agent)
|
|
78
|
+
continue;
|
|
79
|
+
if (filter.tool && parsed.tool !== filter.tool)
|
|
80
|
+
continue;
|
|
81
|
+
if (filter.mode && parsed.mode !== filter.mode)
|
|
82
|
+
continue;
|
|
83
|
+
if (filter.outcome && parsed.outcome !== filter.outcome)
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
out.push(parsed);
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
},
|
|
90
|
+
close() {
|
|
91
|
+
if (closed)
|
|
92
|
+
return;
|
|
93
|
+
closed = true;
|
|
94
|
+
// No file descriptor to release; close is a logical marker so
|
|
95
|
+
// subsequent reads/appends throw a clean error.
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/metrics/runs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `MetricsCollector` implementation — pricing tables + cost
|
|
3
|
+
* derivation in one place. Pure functions; no I/O.
|
|
4
|
+
*
|
|
5
|
+
* Pricing is per-million-token USD figures. When the provider
|
|
6
|
+
* reports a cost (OpenRouter's `x-cost` header), the collector
|
|
7
|
+
* skips estimation and marks `costEstimated: false`. When the
|
|
8
|
+
* model isn't in the pricing table, cost is set to 0 with
|
|
9
|
+
* `costEstimated: true`.
|
|
10
|
+
*
|
|
11
|
+
* Update pricing rows below when providers revise rates — there's
|
|
12
|
+
* no API to introspect them.
|
|
13
|
+
*/
|
|
14
|
+
import type { TurnMetrics } from './types/llm.js';
|
|
15
|
+
import type { MetricsCollector, RecordTurnInput } from './types/metrics.js';
|
|
16
|
+
interface PricingRow {
|
|
17
|
+
/** USD per million input tokens. */
|
|
18
|
+
input: number;
|
|
19
|
+
/** USD per million output tokens. */
|
|
20
|
+
output: number;
|
|
21
|
+
/** USD per million cached input tokens (when cache-hit). */
|
|
22
|
+
cacheRead: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Look up a pricing row. Returns undefined when the model isn't
|
|
26
|
+
* priced — caller skips the cost field rather than fabricating one.
|
|
27
|
+
*/
|
|
28
|
+
export declare function findPricing(llmId: string, model: string): PricingRow | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Derive a `TurnMetrics` value from one turn's raw usage. Pure
|
|
31
|
+
* function — used by both the collector below and direct callers
|
|
32
|
+
* that don't need session-level aggregation.
|
|
33
|
+
*/
|
|
34
|
+
export declare function computeTurnMetrics(input: RecordTurnInput): TurnMetrics;
|
|
35
|
+
/** Build a stateful `MetricsCollector` for one session. */
|
|
36
|
+
export declare function createMetricsCollector(): MetricsCollector;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAiB,MAAM,oBAAoB,CAAC;AAE3F,UAAU,UAAU;IAClB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;CACnB;AAeD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,WAAW,CA8CtE;AAED,2DAA2D;AAC3D,wBAAgB,sBAAsB,IAAI,gBAAgB,CAqCzD"}
|