@sulala/agent 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/README.md +120 -0
- package/bin/sulala.mjs +7 -0
- package/dist/agent/loop.d.ts +38 -0
- package/dist/agent/loop.d.ts.map +1 -0
- package/dist/agent/loop.js +384 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/session-queue.d.ts +2 -0
- package/dist/agent/session-queue.d.ts.map +1 -0
- package/dist/agent/session-queue.js +13 -0
- package/dist/agent/session-queue.js.map +1 -0
- package/dist/agent/skill-install.d.ts +41 -0
- package/dist/agent/skill-install.d.ts.map +1 -0
- package/dist/agent/skill-install.js +211 -0
- package/dist/agent/skill-install.js.map +1 -0
- package/dist/agent/skills-config.d.ts +24 -0
- package/dist/agent/skills-config.d.ts.map +1 -0
- package/dist/agent/skills-config.js +126 -0
- package/dist/agent/skills-config.js.map +1 -0
- package/dist/agent/skills-watcher.d.ts +7 -0
- package/dist/agent/skills-watcher.d.ts.map +1 -0
- package/dist/agent/skills-watcher.js +32 -0
- package/dist/agent/skills-watcher.js.map +1 -0
- package/dist/agent/skills.d.ts +32 -0
- package/dist/agent/skills.d.ts.map +1 -0
- package/dist/agent/skills.js +208 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/skills.test.d.ts +2 -0
- package/dist/agent/skills.test.d.ts.map +1 -0
- package/dist/agent/skills.test.js +59 -0
- package/dist/agent/skills.test.js.map +1 -0
- package/dist/agent/tools.d.ts +8 -0
- package/dist/agent/tools.d.ts.map +1 -0
- package/dist/agent/tools.js +147 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/ai/orchestrator.d.ts +38 -0
- package/dist/ai/orchestrator.d.ts.map +1 -0
- package/dist/ai/orchestrator.js +360 -0
- package/dist/ai/orchestrator.js.map +1 -0
- package/dist/ai/orchestrator.test.d.ts +2 -0
- package/dist/ai/orchestrator.test.d.ts.map +1 -0
- package/dist/ai/orchestrator.test.js +29 -0
- package/dist/ai/orchestrator.test.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +278 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +16 -0
- package/dist/config.test.js.map +1 -0
- package/dist/db/index.d.ts +42 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +121 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.sql +74 -0
- package/dist/gateway/server.d.ts +13 -0
- package/dist/gateway/server.d.ts.map +1 -0
- package/dist/gateway/server.js +566 -0
- package/dist/gateway/server.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/index.d.ts +52 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +176 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/scheduler/cron.d.ts +8 -0
- package/dist/scheduler/cron.d.ts.map +1 -0
- package/dist/scheduler/cron.js +31 -0
- package/dist/scheduler/cron.js.map +1 -0
- package/dist/scheduler/queue.d.ts +13 -0
- package/dist/scheduler/queue.d.ts.map +1 -0
- package/dist/scheduler/queue.js +75 -0
- package/dist/scheduler/queue.js.map +1 -0
- package/dist/scheduler/queue.test.d.ts +2 -0
- package/dist/scheduler/queue.test.d.ts.map +1 -0
- package/dist/scheduler/queue.test.js +41 -0
- package/dist/scheduler/queue.test.js.map +1 -0
- package/dist/types.d.ts +149 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/watcher/index.d.ts +15 -0
- package/dist/watcher/index.d.ts.map +1 -0
- package/dist/watcher/index.js +87 -0
- package/dist/watcher/index.js.map +1 -0
- package/dist/webhooks.d.ts +2 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +38 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +62 -0
- package/src/db/schema.sql +74 -0
- package/src/index.ts +83 -0
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Sulala Agent — Local AI Orchestration Platform
|
|
2
|
+
|
|
3
|
+
A local-first platform that combines **file monitoring**, **task scheduling**, **AI orchestration**, and a **plugin system**. Runs on `127.0.0.1` and stays on your machine.
|
|
4
|
+
|
|
5
|
+
## Architecture (high level)
|
|
6
|
+
|
|
7
|
+
| Layer | Role |
|
|
8
|
+
|-------|------|
|
|
9
|
+
| **Gateway** | REST + WebSocket API on `localhost:3000`; auth and request handling |
|
|
10
|
+
| **File watcher** | Real-time folder watch (add/change/delete) → event triggers |
|
|
11
|
+
| **Task scheduler** | Cron-like scheduling + queue with retries and failure handling |
|
|
12
|
+
| **AI orchestration** | Single interface to multiple providers (OpenAI, OpenRouter, Claude, Gemini, Ollama); routing and rate limits |
|
|
13
|
+
| **Plugins** | Scripts and integrations that hook into events, tasks, and AI |
|
|
14
|
+
| **Persistence** | SQLite for tasks, file state, logs, and AI results |
|
|
15
|
+
|
|
16
|
+
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) and the project diagram for full layout.
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Install dependencies
|
|
22
|
+
npm install
|
|
23
|
+
|
|
24
|
+
# Configure (copy and edit)
|
|
25
|
+
cp .env.example .env
|
|
26
|
+
|
|
27
|
+
# Run gateway + watcher + scheduler (TypeScript via tsx)
|
|
28
|
+
npm start
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Development:** `npm run dev` runs the app with `tsx watch` (restarts on file changes). For a production build: `npm run build` then `node dist/index.js` (or run the gateway with `node dist/gateway/server.js`). Run tests with `npm test` and lint with `npm run lint`.
|
|
32
|
+
|
|
33
|
+
**Dashboard (React + Vite + shadcn/ui):**
|
|
34
|
+
|
|
35
|
+
- **Dev:** run the UI on its own port (e.g. 5173) while the gateway runs on 3000:
|
|
36
|
+
```bash
|
|
37
|
+
npm run dashboard
|
|
38
|
+
```
|
|
39
|
+
Then open the URL Vite prints (e.g. http://localhost:5173). Set `VITE_GATEWAY_URL=http://127.0.0.1:3000` in `dashboard/.env` if the API is on another host.
|
|
40
|
+
- **Production:** build and serve from the gateway (one origin):
|
|
41
|
+
```bash
|
|
42
|
+
npm run dashboard:build
|
|
43
|
+
npm start
|
|
44
|
+
```
|
|
45
|
+
Then open http://127.0.0.1:3000 — the gateway serves the built dashboard and the API.
|
|
46
|
+
|
|
47
|
+
**CLI** (from project root):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Via npm script
|
|
51
|
+
npm run cli -- status
|
|
52
|
+
npm run cli -- tasks --limit=20
|
|
53
|
+
npm run cli -- logs --limit=50
|
|
54
|
+
npm run cli -- enqueue --type=heartbeat --payload='{"x":1}'
|
|
55
|
+
|
|
56
|
+
# Or install globally: npm link (from project root)
|
|
57
|
+
sulala status
|
|
58
|
+
sulala tasks --limit=20
|
|
59
|
+
sulala skill list
|
|
60
|
+
sulala skill install apple-notes [--global]
|
|
61
|
+
sulala skill update
|
|
62
|
+
sulala skill uninstall apple-notes [--global]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Skill commands:** `sulala skill list` lists registry skills. `sulala skill install <slug> [--global]` installs to workspace (default) or managed dir (`~/.sulala/skills`). `sulala skill update` refreshes installed skills from the registry. `sulala skill uninstall <slug> [--global]
|
|
66
|
+
sulala init [dir]` removes an installed skill.
|
|
67
|
+
|
|
68
|
+
Set `GATEWAY_URL` and optionally `GATEWAY_API_KEY` when using gateway commands. Set `SULALA_SKILLS_DIR` and `AGENT_CONTEXT_PATH` for skill paths.
|
|
69
|
+
|
|
70
|
+
**Agent runner:** Multi-turn sessions with optional tool use. Create a session, then send messages to run the agent loop (model can call tools; built-in `run_task` enqueues background tasks). See [docs/ROADMAP_AGENT_RUNNER.md](docs/ROADMAP_AGENT_RUNNER.md) and [docs/AGENT_API.md](docs/AGENT_API.md).
|
|
71
|
+
- `GET /api/agent/sessions` — list sessions (query: `limit`).
|
|
72
|
+
- `POST /api/agent/sessions` — create or get session (body: `{ "session_key": "my-chat", "meta": {} }`).
|
|
73
|
+
- `GET /api/agent/sessions/:id` — get session and message history.
|
|
74
|
+
- `POST /api/agent/sessions/:id/messages` — send a message and run the agent turn (body: `{ "message": "…", "system_prompt": "…", "provider": "openai", "timeout_ms": 300000 }`). Returns `{ finalContent, messages, turnCount }`. Runs are serialized per session; client disconnect or timeout aborts the run (`AGENT_TIMEOUT_MS` in env or `timeout_ms` in body).
|
|
75
|
+
|
|
76
|
+
**AI models:** Supported providers: OpenAI (e.g. gpt-5.2, gpt-5-mini, gpt-4o-mini), OpenRouter (one key for many models, e.g. openai/gpt-5.2, anthropic/claude-sonnet-4), Claude (Opus 4.6, Sonnet 4.6, Haiku 4.5), Gemini (2.5 Flash/Pro, 3.1 Pro), Ollama (local). See [docs/MODELS.md](docs/MODELS.md) for model IDs and env vars (`AI_*_DEFAULT_MODEL`, `OPENROUTER_API_KEY`, `GOOGLE_GEMINI_API_KEY`).
|
|
77
|
+
|
|
78
|
+
**Config:** Watched folders can be set in `.env` (`WATCH_FOLDERS`) or in `config/watched.json` (array `folders`); both are merged. Optional gateway auth via `GATEWAY_API_KEY`; webhooks via `WEBHOOK_URL` or `WEBHOOK_URLS` and optional `WEBHOOK_SECRET`. AI: set `OPENAI_API_KEY`, `OPENROUTER_API_KEY`, `ANTHROPIC_API_KEY`, and/or use Ollama (`OLLAMA_BASE_URL`, default `http://localhost:11434`). Optional rate limit: `RATE_LIMIT_MAX`, `RATE_LIMIT_WINDOW_MS`. See `.env.example`.
|
|
79
|
+
|
|
80
|
+
**Docker:** Build and run with dashboard served from the gateway:
|
|
81
|
+
```bash
|
|
82
|
+
docker compose up --build
|
|
83
|
+
```
|
|
84
|
+
Then open http://localhost:3000. Mount `./config` for watched folders; data is stored in a named volume.
|
|
85
|
+
|
|
86
|
+
## Requirements
|
|
87
|
+
|
|
88
|
+
- **Node.js** 18+
|
|
89
|
+
- **TypeScript** + **tsx** (dev; in package.json)
|
|
90
|
+
- **Python 3.10+** (optional, for AI/automation scripts)
|
|
91
|
+
- SQLite (included via `better-sqlite3`)
|
|
92
|
+
|
|
93
|
+
## Project layout
|
|
94
|
+
|
|
95
|
+
Backend is TypeScript (`src/**/*.ts`); runs with `tsx` or compile with `tsc` to `dist/`.
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
sulala_agent/
|
|
99
|
+
├── src/
|
|
100
|
+
│ ├── gateway/ # API server (REST/WS), auth
|
|
101
|
+
│ ├── watcher/ # File/folder watcher (chokidar)
|
|
102
|
+
│ ├── scheduler/ # Cron + task queue
|
|
103
|
+
│ ├── ai/ # AI orchestration (multi-provider)
|
|
104
|
+
│ ├── plugins/ # Plugin loader and hooks
|
|
105
|
+
│ └── db/ # SQLite schema and access
|
|
106
|
+
├── scripts/ # User and plugin automation (Python/Node/Bash)
|
|
107
|
+
├── config/ # Watched folders, cron rules, plugin config
|
|
108
|
+
├── docs/
|
|
109
|
+
└── dashboard/ # Web UI (React + Vite + Tailwind + shadcn/ui)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Security
|
|
113
|
+
|
|
114
|
+
- Services bind to `127.0.0.1` only (no internet exposure by default).
|
|
115
|
+
- Store API keys and secrets in `.env`; never commit them.
|
|
116
|
+
- Plugins and automation scripts can be sandboxed (e.g. run in subprocess with limited permissions).
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT
|
package/bin/sulala.mjs
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AgentTurnMessage } from '../types.js';
|
|
2
|
+
export type AgentStreamEvent = {
|
|
3
|
+
type: 'assistant';
|
|
4
|
+
delta: string;
|
|
5
|
+
} | {
|
|
6
|
+
type: 'tool_call';
|
|
7
|
+
name: string;
|
|
8
|
+
result?: unknown;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'done';
|
|
11
|
+
finalContent: string;
|
|
12
|
+
turnCount: number;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'error';
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
export interface RunTurnOptions {
|
|
18
|
+
sessionId: string;
|
|
19
|
+
userMessage?: string | null;
|
|
20
|
+
systemPrompt?: string | null;
|
|
21
|
+
provider?: string;
|
|
22
|
+
model?: string;
|
|
23
|
+
max_tokens?: number;
|
|
24
|
+
/** Max run time in ms; overrides config.agentTimeoutMs when set. */
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
/** When aborted, the run throws. Used for request disconnect or cancel. */
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
}
|
|
29
|
+
export interface RunTurnResult {
|
|
30
|
+
sessionId: string;
|
|
31
|
+
messages: AgentTurnMessage[];
|
|
32
|
+
finalContent: string;
|
|
33
|
+
turnCount: number;
|
|
34
|
+
}
|
|
35
|
+
export declare function runAgentTurn(options: RunTurnOptions): Promise<RunTurnResult>;
|
|
36
|
+
/** Run agent turn with streaming (OpenAI: deltas; others: single done). */
|
|
37
|
+
export declare function runAgentTurnStream(options: RunTurnOptions, onEvent: (ev: AgentStreamEvent) => void): Promise<RunTurnResult>;
|
|
38
|
+
//# sourceMappingURL=loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA6CvC,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AA4FD,wBAAsB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAmHlF;AAED,2EAA2E;AAC3E,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,CAAC,EAAE,EAAE,gBAAgB,KAAK,IAAI,GACtC,OAAO,CAAC,aAAa,CAAC,CAyJxB"}
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync, statSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { complete, completeStream } from '../ai/orchestrator.js';
|
|
4
|
+
import { getAgentMessages, appendAgentMessage } from '../db/index.js';
|
|
5
|
+
import { log } from '../db/index.js';
|
|
6
|
+
import { config } from '../config.js';
|
|
7
|
+
import { runAgentHooksSessionStart, runAgentHooksSessionEnd, runAgentHooksBeforePromptBuild, runAgentHooksBeforeToolCall, runAgentHooksAfterToolCall, runAgentHooksAgentEnd, } from '../plugins/index.js';
|
|
8
|
+
import { listTools, executeTool } from './tools.js';
|
|
9
|
+
import { getSkillPaths } from './skills.js';
|
|
10
|
+
import { isSkillEnabled } from './skills-config.js';
|
|
11
|
+
const DEFAULT_SYSTEM = 'You are a helpful assistant. You have access to tools; use them when appropriate.';
|
|
12
|
+
const MAX_TOOL_TURNS = 10;
|
|
13
|
+
function throwIfAborted(signal) {
|
|
14
|
+
if (signal?.aborted) {
|
|
15
|
+
const e = new Error('Agent run aborted');
|
|
16
|
+
e.name = 'AbortError';
|
|
17
|
+
throw e;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function buildEffectiveSignal(options) {
|
|
21
|
+
const timeoutMs = options.timeoutMs ?? config.agentTimeoutMs ?? 0;
|
|
22
|
+
if (timeoutMs <= 0 && !options.signal)
|
|
23
|
+
return { signal: undefined, cleanup: () => { } };
|
|
24
|
+
const controller = new AbortController();
|
|
25
|
+
let timer = null;
|
|
26
|
+
if (timeoutMs > 0)
|
|
27
|
+
timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
28
|
+
if (options.signal)
|
|
29
|
+
options.signal.addEventListener('abort', () => controller.abort());
|
|
30
|
+
return {
|
|
31
|
+
signal: controller.signal,
|
|
32
|
+
cleanup: () => {
|
|
33
|
+
if (timer != null)
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function rowsToMessages(rows) {
|
|
39
|
+
return rows.map((r) => {
|
|
40
|
+
const msg = { role: r.role };
|
|
41
|
+
if (r.content != null)
|
|
42
|
+
msg.content = r.content;
|
|
43
|
+
if (r.tool_calls) {
|
|
44
|
+
try {
|
|
45
|
+
msg.tool_calls = JSON.parse(r.tool_calls);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// ignore
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (r.tool_call_id)
|
|
52
|
+
msg.tool_call_id = r.tool_call_id;
|
|
53
|
+
if (r.name)
|
|
54
|
+
msg.name = r.name;
|
|
55
|
+
return msg;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/** Parse YAML-like frontmatter (--- ... ---) and return name, description, and body. */
|
|
59
|
+
function parseFrontmatter(content) {
|
|
60
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
61
|
+
if (!match)
|
|
62
|
+
return { body: content };
|
|
63
|
+
const block = match[1];
|
|
64
|
+
const body = match[2].trim();
|
|
65
|
+
let name;
|
|
66
|
+
let description;
|
|
67
|
+
for (const line of block.split(/\r?\n/)) {
|
|
68
|
+
const nameMatch = line.match(/^name:\s*(.+)$/);
|
|
69
|
+
if (nameMatch)
|
|
70
|
+
name = nameMatch[1].trim().replace(/^['"]|['"]$/g, '');
|
|
71
|
+
const descMatch = line.match(/^description:\s*(.+)$/);
|
|
72
|
+
if (descMatch)
|
|
73
|
+
description = descMatch[1].trim().replace(/^['"]|['"]$/g, '');
|
|
74
|
+
}
|
|
75
|
+
return { name, description, body };
|
|
76
|
+
}
|
|
77
|
+
function collectFiles(base) {
|
|
78
|
+
const files = [];
|
|
79
|
+
if (!existsSync(base))
|
|
80
|
+
return files;
|
|
81
|
+
try {
|
|
82
|
+
const stat = statSync(base);
|
|
83
|
+
if (stat.isFile() && (base.endsWith('.md') || base.endsWith('.txt'))) {
|
|
84
|
+
files.push({ path: base, name: base.split(/[/\\]/).pop() || '' });
|
|
85
|
+
}
|
|
86
|
+
else if (stat.isDirectory()) {
|
|
87
|
+
const names = readdirSync(base).sort();
|
|
88
|
+
for (const n of names) {
|
|
89
|
+
if (!n.endsWith('.md') && !n.endsWith('.txt'))
|
|
90
|
+
continue;
|
|
91
|
+
files.push({ path: join(base, n), name: n });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
log('agent', 'warn', `Skip skill path ${base}: ${e.message}`);
|
|
97
|
+
}
|
|
98
|
+
return files;
|
|
99
|
+
}
|
|
100
|
+
function loadContextFromPaths() {
|
|
101
|
+
const paths = getSkillPaths(config);
|
|
102
|
+
const bySkillName = new Map();
|
|
103
|
+
const nonSkillChunks = [];
|
|
104
|
+
for (const { path: base } of paths) {
|
|
105
|
+
for (const { path: full, name: fileName } of collectFiles(base)) {
|
|
106
|
+
try {
|
|
107
|
+
const raw = readFileSync(full, 'utf8');
|
|
108
|
+
if (!fileName.endsWith('.md')) {
|
|
109
|
+
nonSkillChunks.push(`--- ${fileName}\n${raw}`);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const parsed = parseFrontmatter(raw);
|
|
113
|
+
if (parsed.name && parsed.description && isSkillEnabled(parsed.name)) {
|
|
114
|
+
bySkillName.set(parsed.name, {
|
|
115
|
+
index: { name: parsed.name, description: parsed.description },
|
|
116
|
+
body: parsed.body,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
nonSkillChunks.push(`--- ${fileName}\n${raw}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
log('agent', 'warn', `Skip context file ${full}: ${e.message}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const skillIndex = Array.from(bySkillName.values()).map((v) => v.index);
|
|
129
|
+
const chunks = Array.from(bySkillName.values()).map((v) => `### Skill: ${v.index.name}\n\n${v.body}`);
|
|
130
|
+
chunks.push(...nonSkillChunks);
|
|
131
|
+
if (chunks.length === 0)
|
|
132
|
+
return '';
|
|
133
|
+
const indexSection = skillIndex.length > 0
|
|
134
|
+
? `### Available skills (use when the user's request matches)\n${skillIndex.map((s) => `- **${s.name}**: ${s.description}`).join('\n')}\n\n`
|
|
135
|
+
: '';
|
|
136
|
+
return `\n\n## Context\n\n${indexSection}${chunks.join('\n\n')}`;
|
|
137
|
+
}
|
|
138
|
+
async function resolveSystemPrompt(sessionId, basePrompt, messageCount) {
|
|
139
|
+
const context = loadContextFromPaths();
|
|
140
|
+
const withContext = basePrompt + context;
|
|
141
|
+
const overridden = await runAgentHooksBeforePromptBuild(sessionId, {
|
|
142
|
+
systemPrompt: withContext,
|
|
143
|
+
messageCount,
|
|
144
|
+
});
|
|
145
|
+
return overridden ?? withContext;
|
|
146
|
+
}
|
|
147
|
+
export async function runAgentTurn(options) {
|
|
148
|
+
const { sessionId, userMessage = null, systemPrompt: optionPrompt = null, provider, model, max_tokens = 1024, } = options;
|
|
149
|
+
const { signal, cleanup } = buildEffectiveSignal(options);
|
|
150
|
+
try {
|
|
151
|
+
throwIfAborted(signal);
|
|
152
|
+
await runAgentHooksSessionStart(sessionId);
|
|
153
|
+
const history = getAgentMessages(sessionId);
|
|
154
|
+
const messages = [];
|
|
155
|
+
const baseSystem = optionPrompt ?? config.agentSystemPrompt ?? DEFAULT_SYSTEM;
|
|
156
|
+
const systemPrompt = await resolveSystemPrompt(sessionId, baseSystem, history.length + 1);
|
|
157
|
+
if (systemPrompt) {
|
|
158
|
+
messages.push({ role: 'system', content: systemPrompt });
|
|
159
|
+
}
|
|
160
|
+
messages.push(...rowsToMessages(history));
|
|
161
|
+
if (userMessage) {
|
|
162
|
+
messages.push({ role: 'user', content: userMessage });
|
|
163
|
+
appendAgentMessage({ session_id: sessionId, role: 'user', content: userMessage });
|
|
164
|
+
}
|
|
165
|
+
const toolsForApi = listTools().map((t) => ({
|
|
166
|
+
name: t.name,
|
|
167
|
+
description: t.description,
|
|
168
|
+
parameters: t.parameters,
|
|
169
|
+
}));
|
|
170
|
+
let turnCount = 0;
|
|
171
|
+
let lastContent = '';
|
|
172
|
+
while (turnCount < MAX_TOOL_TURNS) {
|
|
173
|
+
throwIfAborted(signal);
|
|
174
|
+
turnCount++;
|
|
175
|
+
const result = await complete({
|
|
176
|
+
provider,
|
|
177
|
+
model,
|
|
178
|
+
messages,
|
|
179
|
+
max_tokens,
|
|
180
|
+
tools: toolsForApi.length ? toolsForApi : undefined,
|
|
181
|
+
signal,
|
|
182
|
+
});
|
|
183
|
+
lastContent = result.content ?? '';
|
|
184
|
+
const assistantContent = result.content ?? null;
|
|
185
|
+
const toolCalls = result.tool_calls;
|
|
186
|
+
appendAgentMessage({
|
|
187
|
+
session_id: sessionId,
|
|
188
|
+
role: 'assistant',
|
|
189
|
+
content: assistantContent,
|
|
190
|
+
tool_calls: toolCalls ? JSON.stringify(toolCalls) : null,
|
|
191
|
+
});
|
|
192
|
+
if (!toolCalls?.length) {
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
messages.push({
|
|
196
|
+
role: 'assistant',
|
|
197
|
+
content: assistantContent,
|
|
198
|
+
tool_calls: toolCalls,
|
|
199
|
+
});
|
|
200
|
+
for (const tc of toolCalls) {
|
|
201
|
+
throwIfAborted(signal);
|
|
202
|
+
let args = tc.arguments ? JSON.parse(tc.arguments) : {};
|
|
203
|
+
args = await runAgentHooksBeforeToolCall(sessionId, tc.name, args);
|
|
204
|
+
let toolResult;
|
|
205
|
+
try {
|
|
206
|
+
toolResult = await executeTool(tc.name, args);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
toolResult = { error: err instanceof Error ? err.message : String(err) };
|
|
210
|
+
log('agent', 'warn', `Tool ${tc.name} failed`, { error: err.message });
|
|
211
|
+
}
|
|
212
|
+
await runAgentHooksAfterToolCall(sessionId, tc.name, args, toolResult);
|
|
213
|
+
messages.push({
|
|
214
|
+
role: 'tool',
|
|
215
|
+
tool_call_id: tc.id,
|
|
216
|
+
name: tc.name,
|
|
217
|
+
content: typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult),
|
|
218
|
+
});
|
|
219
|
+
appendAgentMessage({
|
|
220
|
+
session_id: sessionId,
|
|
221
|
+
role: 'tool',
|
|
222
|
+
tool_call_id: tc.id,
|
|
223
|
+
name: tc.name,
|
|
224
|
+
content: typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const updatedHistory = getAgentMessages(sessionId);
|
|
229
|
+
const result = {
|
|
230
|
+
sessionId,
|
|
231
|
+
messages: rowsToMessages(updatedHistory),
|
|
232
|
+
finalContent: lastContent,
|
|
233
|
+
turnCount,
|
|
234
|
+
};
|
|
235
|
+
await runAgentHooksAgentEnd(sessionId, { finalContent: lastContent, turnCount });
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
cleanup();
|
|
240
|
+
await runAgentHooksSessionEnd(sessionId);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** Run agent turn with streaming (OpenAI: deltas; others: single done). */
|
|
244
|
+
export async function runAgentTurnStream(options, onEvent) {
|
|
245
|
+
const { sessionId, userMessage = null, systemPrompt: optionPrompt = null, provider, model, max_tokens = 1024, } = options;
|
|
246
|
+
const { signal, cleanup } = buildEffectiveSignal(options);
|
|
247
|
+
try {
|
|
248
|
+
throwIfAborted(signal);
|
|
249
|
+
await runAgentHooksSessionStart(sessionId);
|
|
250
|
+
const history = getAgentMessages(sessionId);
|
|
251
|
+
const messages = [];
|
|
252
|
+
const baseSystem = optionPrompt ?? config.agentSystemPrompt ?? DEFAULT_SYSTEM;
|
|
253
|
+
const systemPrompt = await resolveSystemPrompt(sessionId, baseSystem, history.length + 1);
|
|
254
|
+
if (systemPrompt)
|
|
255
|
+
messages.push({ role: 'system', content: systemPrompt });
|
|
256
|
+
messages.push(...rowsToMessages(history));
|
|
257
|
+
if (userMessage) {
|
|
258
|
+
messages.push({ role: 'user', content: userMessage });
|
|
259
|
+
appendAgentMessage({ session_id: sessionId, role: 'user', content: userMessage });
|
|
260
|
+
}
|
|
261
|
+
const toolsForApi = listTools().map((t) => ({
|
|
262
|
+
name: t.name,
|
|
263
|
+
description: t.description,
|
|
264
|
+
parameters: t.parameters,
|
|
265
|
+
}));
|
|
266
|
+
let turnCount = 0;
|
|
267
|
+
let lastContent = '';
|
|
268
|
+
const useStream = ['openai', 'openrouter'].includes(provider ?? process.env.AI_DEFAULT_PROVIDER ?? 'openai');
|
|
269
|
+
while (turnCount < MAX_TOOL_TURNS) {
|
|
270
|
+
throwIfAborted(signal);
|
|
271
|
+
turnCount++;
|
|
272
|
+
const isFirstTurn = turnCount === 1;
|
|
273
|
+
if (useStream && isFirstTurn) {
|
|
274
|
+
const result = await completeStream({ provider, model, messages, max_tokens, tools: toolsForApi.length ? toolsForApi : undefined, signal }, (ev) => {
|
|
275
|
+
if (ev.type === 'delta')
|
|
276
|
+
onEvent({ type: 'assistant', delta: ev.content });
|
|
277
|
+
});
|
|
278
|
+
lastContent = result.content ?? '';
|
|
279
|
+
appendAgentMessage({
|
|
280
|
+
session_id: sessionId,
|
|
281
|
+
role: 'assistant',
|
|
282
|
+
content: lastContent,
|
|
283
|
+
tool_calls: result.tool_calls ? JSON.stringify(result.tool_calls) : null,
|
|
284
|
+
});
|
|
285
|
+
if (result.tool_calls?.length) {
|
|
286
|
+
messages.push({ role: 'assistant', content: lastContent, tool_calls: result.tool_calls });
|
|
287
|
+
for (const tc of result.tool_calls) {
|
|
288
|
+
throwIfAborted(signal);
|
|
289
|
+
let args = tc.arguments ? JSON.parse(tc.arguments) : {};
|
|
290
|
+
args = await runAgentHooksBeforeToolCall(sessionId, tc.name, args);
|
|
291
|
+
let toolResult;
|
|
292
|
+
try {
|
|
293
|
+
toolResult = await executeTool(tc.name, args);
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
toolResult = { error: err instanceof Error ? err.message : String(err) };
|
|
297
|
+
log('agent', 'warn', `Tool ${tc.name} failed`, { error: err.message });
|
|
298
|
+
}
|
|
299
|
+
await runAgentHooksAfterToolCall(sessionId, tc.name, args, toolResult);
|
|
300
|
+
onEvent({ type: 'tool_call', name: tc.name, result: toolResult });
|
|
301
|
+
messages.push({
|
|
302
|
+
role: 'tool',
|
|
303
|
+
tool_call_id: tc.id,
|
|
304
|
+
name: tc.name,
|
|
305
|
+
content: typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult),
|
|
306
|
+
});
|
|
307
|
+
appendAgentMessage({
|
|
308
|
+
session_id: sessionId,
|
|
309
|
+
role: 'tool',
|
|
310
|
+
tool_call_id: tc.id,
|
|
311
|
+
name: tc.name,
|
|
312
|
+
content: typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult),
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
onEvent({ type: 'done', finalContent: lastContent, turnCount });
|
|
318
|
+
const updatedHistory = getAgentMessages(sessionId);
|
|
319
|
+
const runResult = { sessionId, messages: rowsToMessages(updatedHistory), finalContent: lastContent, turnCount };
|
|
320
|
+
await runAgentHooksAgentEnd(sessionId, { finalContent: lastContent, turnCount });
|
|
321
|
+
return runResult;
|
|
322
|
+
}
|
|
323
|
+
const result = await complete({
|
|
324
|
+
provider,
|
|
325
|
+
model,
|
|
326
|
+
messages,
|
|
327
|
+
max_tokens,
|
|
328
|
+
tools: toolsForApi.length ? toolsForApi : undefined,
|
|
329
|
+
signal,
|
|
330
|
+
});
|
|
331
|
+
lastContent = result.content ?? '';
|
|
332
|
+
const toolCalls = result.tool_calls;
|
|
333
|
+
appendAgentMessage({
|
|
334
|
+
session_id: sessionId,
|
|
335
|
+
role: 'assistant',
|
|
336
|
+
content: lastContent,
|
|
337
|
+
tool_calls: toolCalls ? JSON.stringify(toolCalls) : null,
|
|
338
|
+
});
|
|
339
|
+
if (!toolCalls?.length) {
|
|
340
|
+
onEvent({ type: 'done', finalContent: lastContent, turnCount });
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
messages.push({ role: 'assistant', content: lastContent, tool_calls: toolCalls });
|
|
344
|
+
for (const tc of toolCalls) {
|
|
345
|
+
throwIfAborted(signal);
|
|
346
|
+
let args = tc.arguments ? JSON.parse(tc.arguments) : {};
|
|
347
|
+
args = await runAgentHooksBeforeToolCall(sessionId, tc.name, args);
|
|
348
|
+
let toolResult;
|
|
349
|
+
try {
|
|
350
|
+
toolResult = await executeTool(tc.name, args);
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
toolResult = { error: err instanceof Error ? err.message : String(err) };
|
|
354
|
+
log('agent', 'warn', `Tool ${tc.name} failed`, { error: err.message });
|
|
355
|
+
}
|
|
356
|
+
await runAgentHooksAfterToolCall(sessionId, tc.name, args, toolResult);
|
|
357
|
+
onEvent({ type: 'tool_call', name: tc.name, result: toolResult });
|
|
358
|
+
messages.push({
|
|
359
|
+
role: 'tool',
|
|
360
|
+
tool_call_id: tc.id,
|
|
361
|
+
name: tc.name,
|
|
362
|
+
content: typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult),
|
|
363
|
+
});
|
|
364
|
+
appendAgentMessage({
|
|
365
|
+
session_id: sessionId,
|
|
366
|
+
role: 'tool',
|
|
367
|
+
tool_call_id: tc.id,
|
|
368
|
+
name: tc.name,
|
|
369
|
+
content: typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult),
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
const updatedHistory = getAgentMessages(sessionId);
|
|
374
|
+
const runResult = { sessionId, messages: rowsToMessages(updatedHistory), finalContent: lastContent, turnCount };
|
|
375
|
+
onEvent({ type: 'done', finalContent: lastContent, turnCount });
|
|
376
|
+
await runAgentHooksAgentEnd(sessionId, { finalContent: lastContent, turnCount });
|
|
377
|
+
return runResult;
|
|
378
|
+
}
|
|
379
|
+
finally {
|
|
380
|
+
cleanup();
|
|
381
|
+
await runAgentHooksSessionEnd(sessionId);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
//# sourceMappingURL=loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAyB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,8BAA8B,EAC9B,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AASpD,MAAM,cAAc,GAAG,mFAAmF,CAAC;AAC3G,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,SAAS,cAAc,CAAC,MAA+B;IACrD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACzC,CAAC,CAAC,IAAI,GAAG,YAAY,CAAC;QACtB,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAuB;IACnD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC;IAClE,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IACvF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,KAAK,GAAyC,IAAI,CAAC;IACvD,IAAI,SAAS,GAAG,CAAC;QAAE,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAC3E,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;IACvF,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO,EAAE,GAAG,EAAE;YACZ,IAAI,KAAK,IAAI,IAAI;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,IAA2C;IACjE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACpB,MAAM,GAAG,GAAqB,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/C,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI;YAAE,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;QAC/C,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAA2D,CAAC;YACtG,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;QACD,IAAI,CAAC,CAAC,YAAY;YAAE,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC;QACtD,IAAI,CAAC,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;AACL,CAAC;AAsBD,wFAAwF;AACxF,SAAS,gBAAgB,CAAC,OAAe;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC3E,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,IAAwB,CAAC;IAC7B,IAAI,WAA+B,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC/C,IAAI,SAAS;YAAE,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACtD,IAAI,SAAS;YAAE,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,KAAK,GAAqC,EAAE,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACrE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;aAAM,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YACvC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,SAAS;gBACxD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,mBAAmB,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB;IAC3B,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,WAAW,GAAG,IAAI,GAAG,EAA0E,CAAC;IACtG,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;QACnC,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YAChE,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACvC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC9B,cAAc,CAAC,IAAI,CAAC,OAAO,QAAQ,KAAK,GAAG,EAAE,CAAC,CAAC;oBAC/C,SAAS;gBACX,CAAC;gBACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;gBACrC,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,IAAI,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrE,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE;wBAC3B,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE;wBAC7D,IAAI,EAAE,MAAM,CAAC,IAAI;qBAClB,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,cAAc,CAAC,IAAI,CAAC,OAAO,QAAQ,KAAK,GAAG,EAAE,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,qBAAqB,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CACjD,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,EAAE,CACjD,CAAC;IACF,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC;IAC/B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,YAAY,GAChB,UAAU,CAAC,MAAM,GAAG,CAAC;QACnB,CAAC,CAAC,+DAA+D,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;QAC5I,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,qBAAqB,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,SAAiB,EACjB,UAAkB,EAClB,YAAoB;IAEpB,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;IACvC,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;IACzC,MAAM,UAAU,GAAG,MAAM,8BAA8B,CAAC,SAAS,EAAE;QACjE,YAAY,EAAE,WAAW;QACzB,YAAY;KACb,CAAC,CAAC;IACH,OAAO,UAAU,IAAI,WAAW,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAuB;IACxD,MAAM,EACJ,SAAS,EACT,WAAW,GAAG,IAAI,EAClB,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,QAAQ,EACR,KAAK,EACL,UAAU,GAAG,IAAI,GAClB,GAAG,OAAO,CAAC;IAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC;QACvB,MAAM,yBAAyB,CAAC,SAAS,CAAC,CAAC;QAE3C,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAuB,EAAE,CAAC;QAExC,MAAM,UAAU,GACd,YAAY,IAAI,MAAM,CAAC,iBAAiB,IAAI,cAAc,CAAC;QAC7D,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC1F,IAAI,YAAY,EAAE,CAAC;YACjB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;QAE1C,IAAI,WAAW,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YACtD,kBAAkB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,WAAW,GAAG,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC,CAAC,CAAC;QAEJ,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,WAAW,GAAG,EAAE,CAAC;QAErB,OAAO,SAAS,GAAG,cAAc,EAAE,CAAC;YAClC,cAAc,CAAC,MAAM,CAAC,CAAC;YACvB,SAAS,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC;gBAC5B,QAAQ;gBACR,KAAK;gBACL,QAAQ;gBACR,UAAU;gBACV,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;gBACnD,MAAM;aACP,CAAC,CAAC;YAEH,WAAW,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;YAEnC,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC;YAChD,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;YAEpC,kBAAkB,CAAC;gBACjB,UAAU,EAAE,SAAS;gBACrB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,gBAAgB;gBACzB,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI;aACzD,CAAC,CAAC;YAEH,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;gBACvB,MAAM;YACR,CAAC;YAED,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,gBAAgB;gBACzB,UAAU,EAAE,SAAS;aACtB,CAAC,CAAC;YAEH,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,IAAI,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAA4B,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnF,IAAI,GAAG,MAAM,2BAA2B,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACnE,IAAI,UAAmB,CAAC;gBACxB,IAAI,CAAC;oBACH,UAAU,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAChD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,UAAU,GAAG,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,SAAS,EAAE,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;gBACpF,CAAC;gBACD,MAAM,0BAA0B,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;gBACvE,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,MAAM;oBACZ,YAAY,EAAE,EAAE,CAAC,EAAE;oBACnB,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,OAAO,EAAE,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;iBAClF,CAAC,CAAC;gBACH,kBAAkB,CAAC;oBACjB,UAAU,EAAE,SAAS;oBACrB,IAAI,EAAE,MAAM;oBACZ,YAAY,EAAE,EAAE,CAAC,EAAE;oBACnB,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,OAAO,EAAE,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;iBAClF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,MAAM,cAAc,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,MAAM,GAAkB;YAC5B,SAAS;YACT,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC;YACxC,YAAY,EAAE,WAAW;YACzB,SAAS;SACV,CAAC;QACF,MAAM,qBAAqB,CAAC,SAAS,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QACjF,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,OAAO,EAAE,CAAC;QACV,MAAM,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAuB,EACvB,OAAuC;IAEvC,MAAM,EACJ,SAAS,EACT,WAAW,GAAG,IAAI,EAClB,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,QAAQ,EACR,KAAK,EACL,UAAU,GAAG,IAAI,GAClB,GAAG,OAAO,CAAC;IAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC;QACH,cAAc,CAAC,MAAM,CAAC,CAAC;QACvB,MAAM,yBAAyB,CAAC,SAAS,CAAC,CAAC;QAE3C,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAuB,EAAE,CAAC;QAExC,MAAM,UAAU,GAAG,YAAY,IAAI,MAAM,CAAC,iBAAiB,IAAI,cAAc,CAAC;QAC9E,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC1F,IAAI,YAAY;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;QAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1C,IAAI,WAAW,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YACtD,kBAAkB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,WAAW,GAAG,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC,CAAC,CAAC;QAEJ,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,QAAQ,CAAC,CAAC;QAE7G,OAAO,SAAS,GAAG,cAAc,EAAE,CAAC;YAClC,cAAc,CAAC,MAAM,CAAC,CAAC;YACvB,SAAS,EAAE,CAAC;YACZ,MAAM,WAAW,GAAG,SAAS,KAAK,CAAC,CAAC;YAEpC,IAAI,SAAS,IAAI,WAAW,EAAE,CAAC;gBAC7B,MAAM,MAAM,GAAG,MAAM,cAAc,CACjC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,EACtG,CAAC,EAAoB,EAAE,EAAE;oBACvB,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO;wBAAE,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC7E,CAAC,CACF,CAAC;gBACF,WAAW,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;gBACnC,kBAAkB,CAAC;oBACjB,UAAU,EAAE,SAAS;oBACrB,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,WAAW;oBACpB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI;iBACzE,CAAC,CAAC;gBACH,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;oBAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;oBAC1F,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;wBACnC,cAAc,CAAC,MAAM,CAAC,CAAC;wBACvB,IAAI,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAA4B,CAAC,CAAC,CAAC,EAAE,CAAC;wBACnF,IAAI,GAAG,MAAM,2BAA2B,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;wBACnE,IAAI,UAAmB,CAAC;wBACxB,IAAI,CAAC;4BACH,UAAU,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;wBAChD,CAAC;wBAAC,OAAO,GAAG,EAAE,CAAC;4BACb,UAAU,GAAG,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;4BACzE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,SAAS,EAAE,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;wBACpF,CAAC;wBACD,MAAM,0BAA0B,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;wBACvE,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;wBAClE,QAAQ,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,MAAM;4BACZ,YAAY,EAAE,EAAE,CAAC,EAAE;4BACnB,IAAI,EAAE,EAAE,CAAC,IAAI;4BACb,OAAO,EAAE,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;yBAClF,CAAC,CAAC;wBACH,kBAAkB,CAAC;4BACjB,UAAU,EAAE,SAAS;4BACrB,IAAI,EAAE,MAAM;4BACZ,YAAY,EAAE,EAAE,CAAC,EAAE;4BACnB,IAAI,EAAE,EAAE,CAAC,IAAI;4BACb,OAAO,EAAE,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;yBAClF,CAAC,CAAC;oBACL,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;gBAChE,MAAM,cAAc,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;gBACnD,MAAM,SAAS,GAAkB,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;gBAC/H,MAAM,qBAAqB,CAAC,SAAS,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;gBACjF,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC;gBAC5B,QAAQ;gBACR,KAAK;gBACL,QAAQ;gBACR,UAAU;gBACV,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;gBACnD,MAAM;aACP,CAAC,CAAC;YACH,WAAW,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;YACnC,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;YACpC,kBAAkB,CAAC;gBACjB,UAAU,EAAE,SAAS;gBACrB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,WAAW;gBACpB,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI;aACzD,CAAC,CAAC;YACH,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;gBACvB,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;gBAChE,MAAM;YACR,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;YAClF,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,IAAI,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAA4B,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnF,IAAI,GAAG,MAAM,2BAA2B,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACnE,IAAI,UAAmB,CAAC;gBACxB,IAAI,CAAC;oBACH,UAAU,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAChD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,UAAU,GAAG,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,SAAS,EAAE,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;gBACpF,CAAC;gBACD,MAAM,0BAA0B,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;gBACvE,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;gBAClE,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,MAAM;oBACZ,YAAY,EAAE,EAAE,CAAC,EAAE;oBACnB,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,OAAO,EAAE,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;iBAClF,CAAC,CAAC;gBACH,kBAAkB,CAAC;oBACjB,UAAU,EAAE,SAAS;oBACrB,IAAI,EAAE,MAAM;oBACZ,YAAY,EAAE,EAAE,CAAC,EAAE;oBACnB,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,OAAO,EAAE,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;iBAClF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,MAAM,cAAc,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,SAAS,GAAkB,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;QAC/H,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QAChE,MAAM,qBAAqB,CAAC,SAAS,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QACjF,OAAO,SAAS,CAAC;IACnB,CAAC;YAAS,CAAC;QACT,OAAO,EAAE,CAAC;QACV,MAAM,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-queue.d.ts","sourceRoot":"","sources":["../../src/agent/session-queue.ts"],"names":[],"mappings":"AAMA,wBAAsB,eAAe,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAY5F"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-session lock: only one agent run per session at a time.
|
|
3
|
+
* Concurrent requests for the same session are serialized.
|
|
4
|
+
*/
|
|
5
|
+
const sessionTails = new Map();
|
|
6
|
+
export async function withSessionLock(sessionId, fn) {
|
|
7
|
+
const prev = sessionTails.get(sessionId) ?? Promise.resolve();
|
|
8
|
+
const myRun = prev.then(() => fn(), () => fn());
|
|
9
|
+
const tail = myRun.then(() => { }, () => { });
|
|
10
|
+
sessionTails.set(sessionId, tail);
|
|
11
|
+
return myRun;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=session-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-queue.js","sourceRoot":"","sources":["../../src/agent/session-queue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAI,SAAiB,EAAE,EAAoB;IAC9E,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CACrB,GAAG,EAAE,CAAC,EAAE,EAAE,EACV,GAAG,EAAE,CAAC,EAAE,EAAE,CACX,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CACrB,GAAG,EAAE,GAAE,CAAC,EACR,GAAG,EAAE,GAAE,CAAC,CACT,CAAC;IACF,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type RegistrySkill = {
|
|
2
|
+
slug: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
version?: string;
|
|
7
|
+
};
|
|
8
|
+
export type RegistryIndex = {
|
|
9
|
+
skills: RegistrySkill[];
|
|
10
|
+
};
|
|
11
|
+
export declare function getRegistrySkills(overrideUrl?: string): Promise<RegistrySkill[]>;
|
|
12
|
+
export declare function getRegistrySkillsLocal(): RegistrySkill[];
|
|
13
|
+
export type InstallTarget = 'managed' | 'workspace';
|
|
14
|
+
export type InstallSkillOptions = {
|
|
15
|
+
registryUrl?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function installSkill(slug: string, target: InstallTarget, opts?: InstallSkillOptions): Promise<{
|
|
18
|
+
success: boolean;
|
|
19
|
+
path: string;
|
|
20
|
+
error?: string;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function uninstallSkill(slug: string, target: InstallTarget): {
|
|
23
|
+
success: boolean;
|
|
24
|
+
path: string;
|
|
25
|
+
error?: string;
|
|
26
|
+
};
|
|
27
|
+
export declare function updateSkillsAll(): Promise<{
|
|
28
|
+
updated: string[];
|
|
29
|
+
failed: {
|
|
30
|
+
slug: string;
|
|
31
|
+
error: string;
|
|
32
|
+
}[];
|
|
33
|
+
}>;
|
|
34
|
+
export type SkillUpdateInfo = {
|
|
35
|
+
slug: string;
|
|
36
|
+
installedVersion?: string;
|
|
37
|
+
registryVersion?: string;
|
|
38
|
+
updateAvailable: boolean;
|
|
39
|
+
};
|
|
40
|
+
export declare function getAvailableUpdates(): Promise<SkillUpdateInfo[]>;
|
|
41
|
+
//# sourceMappingURL=skill-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-install.d.ts","sourceRoot":"","sources":["../../src/agent/skill-install.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC;AAEF,wBAAsB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAatF;AAED,wBAAgB,sBAAsB,IAAI,aAAa,EAAE,CAQxD;AAoDD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsC7D;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,GACpB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAmBpD;AA6BD,wBAAsB,eAAe,IAAI,OAAO,CAC9C;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CACjE,CAaA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAqBtE"}
|