@keystrokehq/cli 0.1.5 → 0.1.9
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 +8 -9
- package/dist/dist-BPdyQaUt.mjs +19268 -0
- package/dist/dist-BPdyQaUt.mjs.map +1 -0
- package/dist/dist-Dz6iW5q5.mjs +3 -0
- package/dist/{dist-B9XaHV_2.mjs → dist-IOphuHYN.mjs} +57 -20
- package/dist/dist-IOphuHYN.mjs.map +1 -0
- package/dist/{dist-C3YClLXV.mjs → dist-YV-kApfg.mjs} +790 -73
- package/dist/dist-YV-kApfg.mjs.map +1 -0
- package/dist/index.mjs +559 -225
- package/dist/index.mjs.map +1 -1
- package/dist/{maybe-auto-update-DHt-mVf1.mjs → maybe-auto-update-BiR_kXZX.mjs} +2 -2
- package/dist/{maybe-auto-update-DHt-mVf1.mjs.map → maybe-auto-update-BiR_kXZX.mjs.map} +1 -1
- package/dist/pack-artifact-DVnIKrsg-BtNTTQcz.mjs +112 -0
- package/dist/pack-artifact-DVnIKrsg-BtNTTQcz.mjs.map +1 -0
- package/dist/skills-bundle/_AGENTS.md +7 -7
- package/dist/skills-bundle/skills/keystroke-actions/SKILL.md +39 -7
- package/dist/skills-bundle/skills/keystroke-actions/references/catalog-and-imports.md +25 -19
- package/dist/skills-bundle/skills/keystroke-agents/SKILL.md +7 -5
- package/dist/skills-bundle/skills/keystroke-apps/SKILL.md +133 -0
- package/dist/skills-bundle/skills/keystroke-apps/references/cli-and-catalog.md +66 -0
- package/dist/skills-bundle/skills/keystroke-cli/SKILL.md +3 -3
- package/dist/skills-bundle/skills/keystroke-cli/references/api-targets.md +6 -5
- package/dist/skills-bundle/skills/keystroke-deploy/SKILL.md +2 -2
- package/dist/skills-bundle/skills/keystroke-files/SKILL.md +6 -5
- package/dist/skills-bundle/skills/keystroke-gateways/SKILL.md +2 -2
- package/dist/skills-bundle/skills/keystroke-gateways/references/slack-setup.md +1 -1
- package/dist/skills-bundle/skills/keystroke-skills/SKILL.md +1 -1
- package/dist/skills-bundle/skills/keystroke-workflows/SKILL.md +1 -1
- package/dist/skills-bundle/skills/keystroke-workflows/references/authoring.md +2 -2
- package/dist/templates/hello-world/.env.example +1 -15
- package/dist/templates/hello-world/README.md +1 -1
- package/dist/templates/hello-world/package.json +1 -1
- package/dist/{version-BOm_5ar9.mjs → version-BGuC7Cpu.mjs} +10 -14
- package/dist/version-BGuC7Cpu.mjs.map +1 -0
- package/package.json +8 -2
- package/dist/dist-B9XaHV_2.mjs.map +0 -1
- package/dist/dist-C3YClLXV.mjs.map +0 -1
- package/dist/dist-D_-88U7y.mjs +0 -1887
- package/dist/dist-D_-88U7y.mjs.map +0 -1
- package/dist/dist-iKd6nzBK.mjs +0 -3
- package/dist/skills-bundle/skills/keystroke-credentials/SKILL.md +0 -108
- package/dist/skills-bundle/skills/keystroke-credentials/references/cli-and-oauth.md +0 -51
- package/dist/version-BOm_5ar9.mjs.map +0 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# CLI, catalog, connect
|
|
2
|
+
|
|
3
|
+
## Log in once
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
keystroke auth login
|
|
7
|
+
keystroke auth status
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Token is stored in the OS keychain and reused for **cloud** CLI commands. Switching local ↔ cloud does not require re-auth. See [cli skill](.agents/skills/keystroke-cli/SKILL.md).
|
|
11
|
+
|
|
12
|
+
## keystroke app commands
|
|
13
|
+
|
|
14
|
+
All org-scoped; output is JSON.
|
|
15
|
+
|
|
16
|
+
| Command | Purpose |
|
|
17
|
+
| ------- | ------- |
|
|
18
|
+
| `app list` | Apps registered/connectable in your org |
|
|
19
|
+
| `app search <query>` | Search live Composio catalog (`--category`, `--limit`, `--cursor`) |
|
|
20
|
+
| `app show <slug>` | Single catalog app details |
|
|
21
|
+
| `app actions [slug]` | List actions for an app, or global search with `--search` (no slug) |
|
|
22
|
+
| `app action <tool-slug>` | Full input/output JSON schema for one action |
|
|
23
|
+
| `app create` | Create custom org `api_key` app (`--name`, `--slug`, `--description`, `--field`) |
|
|
24
|
+
| `app sync <slug>` | Write `src/apps/<name>/app.ts` from platform template (`--dir`) |
|
|
25
|
+
|
|
26
|
+
`--field` syntax: `key`, `key:secret`, `key:optional`, or `key:secret:optional` (repeatable).
|
|
27
|
+
|
|
28
|
+
## Connect an app
|
|
29
|
+
|
|
30
|
+
`keystroke connect <slug>` attaches secrets to an app via the dashboard connect flow:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
keystroke connect google # official OAuth
|
|
34
|
+
keystroke connect slack
|
|
35
|
+
keystroke connect exa # official API key
|
|
36
|
+
keystroke connect acme/internal-api # custom app (sync first)
|
|
37
|
+
keystroke connect <slug> --print-url # deeplink without opening browser
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- **Official integrations** — always prefer `keystroke connect <slug>`
|
|
41
|
+
- **Custom apps** — `keystroke app sync <slug>` first, then `keystroke connect <slug>`
|
|
42
|
+
- Slug must exist in your org registry (`app list`)
|
|
43
|
+
- Connect once per **target** (local dev server vs cloud deployed project)
|
|
44
|
+
- Dashboard at `:3000` → **Apps** offers the same flow
|
|
45
|
+
|
|
46
|
+
## Scopes
|
|
47
|
+
|
|
48
|
+
When you connect an app, the connection is stored at one scope:
|
|
49
|
+
|
|
50
|
+
| Scope | When |
|
|
51
|
+
| ----- | ---- |
|
|
52
|
+
| `project` (default) | Tie to one project — use unless told otherwise |
|
|
53
|
+
| `org` | Share with every user and project — only on explicit request |
|
|
54
|
+
| `user` | Single user's personal connection |
|
|
55
|
+
|
|
56
|
+
At runtime resolution is **org first, then project**. Get the active project id from `keystroke config show`.
|
|
57
|
+
|
|
58
|
+
## `.env` vs connected apps
|
|
59
|
+
|
|
60
|
+
| Holds | `.env` | Connected apps (via connect) |
|
|
61
|
+
| ----- | ------ | ------------------------------ |
|
|
62
|
+
| Model keys (`ANTHROPIC_API_KEY`), DB URL, OAuth **provider** config (`SLACK_CLIENT_ID`, `GOOGLE_*`) | yes — local boot only | — |
|
|
63
|
+
| Integration secrets resolved at runtime | — | yes |
|
|
64
|
+
| Reaches the cloud? | no | yes, when connected on cloud target |
|
|
65
|
+
|
|
66
|
+
App secrets are **not** read from `.env` — connect the app with `keystroke connect`. Connections follow the active target (local while `keystroke dev` runs; cloud after deploy). Re-connect on the cloud target after deploy.
|
|
@@ -13,7 +13,7 @@ The CLI is the primary interface for keystroke projects. Most commands hit an **
|
|
|
13
13
|
|
|
14
14
|
| Target | Use for | Default URL |
|
|
15
15
|
| --------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------- |
|
|
16
|
-
| **Local** | Development and testing — iterate on `src/`, run workflows/agents against your machine, debug sessions | `
|
|
16
|
+
| **Local** | Development and testing — iterate on `src/`, run workflows/agents against your machine, debug sessions | `PUBLIC_PLATFORM_URL` in project `.env` (dev session when `keystroke dev` is running) |
|
|
17
17
|
| **Cloud** | Invoking, listing, and operating a **deployed** project — production runs, trigger URLs, remote audit | `{platformUrl}/api/projects/{id}` |
|
|
18
18
|
|
|
19
19
|
**Rule of thumb:** while you are building or validating changes, use **local**. After deploy, use **cloud** to invoke and inspect what is live.
|
|
@@ -111,7 +111,7 @@ Full detail: [api-targets.md](references/api-targets.md).
|
|
|
111
111
|
| `dev`, `start`, `build` | Local project only |
|
|
112
112
|
| `project list`, `project create` | Platform control plane (org-scoped) |
|
|
113
113
|
| `deploy` | Platform (sets `activeProjectId` + `apiTarget=platform`) |
|
|
114
|
-
| `workflow`, `agent`, `trigger`, `
|
|
114
|
+
| `workflow`, `agent`, `trigger`, `app`, `connect`, `health` | Follows resolved target |
|
|
115
115
|
| `auth login` | Web dashboard (`webUrl`); token reused for cloud API calls |
|
|
116
116
|
|
|
117
117
|
## Audit & debug
|
|
@@ -129,4 +129,4 @@ keystroke trigger list --endpoint shared-hub
|
|
|
129
129
|
keystroke trigger url incoming-message
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
Related: [deploy](.agents/skills/keystroke-deploy/SKILL.md), [
|
|
132
|
+
Related: [deploy](.agents/skills/keystroke-deploy/SKILL.md), [apps](.agents/skills/keystroke-apps/SKILL.md), [workflows](.agents/skills/keystroke-workflows/SKILL.md), [agents](.agents/skills/keystroke-agents/SKILL.md), [triggers](.agents/skills/keystroke-triggers/SKILL.md).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# API target routing
|
|
2
2
|
|
|
3
|
-
The CLI resolves a `baseUrl` before runtime commands (`workflow`, `agent`, `trigger`, `
|
|
3
|
+
The CLI resolves a `baseUrl` before runtime commands (`workflow`, `agent`, `trigger`, `app`, `connect`, `health`). Implementation: `apps/cli/src/resolve-api-target.ts`.
|
|
4
4
|
|
|
5
5
|
## Mental model
|
|
6
6
|
|
|
@@ -13,12 +13,13 @@ Auth is independent of target. `keystroke auth login` stores a bearer token in t
|
|
|
13
13
|
|
|
14
14
|
| Key | Default | Role |
|
|
15
15
|
| ----------------- | -------------------------- | -------------------------------- |
|
|
16
|
-
| `serverUrl` | `http://localhost:3001` | Local keystroke server API |
|
|
17
16
|
| `platformUrl` | `https://api.keystroke.ai` | Keystroke platform control plane |
|
|
18
|
-
| `webUrl` | `https://
|
|
17
|
+
| `webUrl` | `https://keystroke.ai` | Dashboard + device login |
|
|
19
18
|
| `activeProjectId` | unset | Deployed project id (persistent) |
|
|
20
19
|
| `apiTarget` | inferred | `local` or `platform` |
|
|
21
20
|
|
|
21
|
+
Local commands use `PUBLIC_PLATFORM_URL` from the project `.env` (dev default `http://localhost:3002` when unset). They do not read `platformUrl` when `apiTarget=local`, so cloud login does not redirect local workflow runs to production.
|
|
22
|
+
|
|
22
23
|
If `apiTarget` is unset and `activeProjectId` exists, effective target is **platform** (backward compatible). Explicit `apiTarget=local` overrides that without clearing `activeProjectId`.
|
|
23
24
|
|
|
24
25
|
`keystroke config show` prints effective `apiTarget` and any active dev session.
|
|
@@ -28,7 +29,7 @@ If `apiTarget` is unset and `activeProjectId` exists, effective target is **plat
|
|
|
28
29
|
```bash
|
|
29
30
|
keystroke deploy --project proj_abc # activeProjectId=proj_abc, apiTarget=platform
|
|
30
31
|
keystroke config use local # apiTarget=local; proj_abc unchanged
|
|
31
|
-
keystroke workflow run foo --input '{}' # → localhost:
|
|
32
|
+
keystroke workflow run foo --input '{}' # → localhost:3002
|
|
32
33
|
keystroke config use cloud # apiTarget=platform; same proj_abc
|
|
33
34
|
keystroke trigger list # → platform runtime
|
|
34
35
|
```
|
|
@@ -55,7 +56,7 @@ keystroke --project proj_xyz workflow runs list my-workflow
|
|
|
55
56
|
|
|
56
57
|
| Flag | Effect |
|
|
57
58
|
| ---------------- | -------------------------------------------------------------------------- |
|
|
58
|
-
| `--local` | Force local `
|
|
59
|
+
| `--local` | Force local API (`PUBLIC_PLATFORM_URL` / project `.env`) for this command |
|
|
59
60
|
| `--project <id>` | Force platform runtime for that project; does not update `activeProjectId` |
|
|
60
61
|
|
|
61
62
|
## Platform projects
|
|
@@ -78,7 +78,7 @@ Detail: [build-and-full-deploy.md](references/build-and-full-deploy.md).
|
|
|
78
78
|
- **First deploy with `--filter`** — fails; run full deploy once.
|
|
79
79
|
- **Wrong `--dir`** — builds a different tree than you edited.
|
|
80
80
|
- **Expecting full refresh with `--filter`** — only matched modules rebuild; rest comes from active prod.
|
|
81
|
-
- **
|
|
81
|
+
- **Connected apps aren't in `.env`** — deploy never uploads `.env`; connect apps on the cloud target. See [apps skill](../keystroke-apps/SKILL.md).
|
|
82
82
|
|
|
83
83
|
## Audit deployed runtime
|
|
84
84
|
|
|
@@ -89,4 +89,4 @@ keystroke workflow run morning-check --input '{}'
|
|
|
89
89
|
keystroke trigger list
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
Related: [cli skill](../keystroke-cli/SKILL.md), [
|
|
92
|
+
Related: [cli skill](../keystroke-cli/SKILL.md), [apps skill](../keystroke-apps/SKILL.md).
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: keystroke-files
|
|
3
|
-
description: Add static files to agent workspaces from src/files/ — product docs, instructions, context. Use with
|
|
3
|
+
description: Add static files to agent workspaces from src/files/ — product docs, instructions, context. Use with defineSandbox on defineAgent.
|
|
4
4
|
metadata:
|
|
5
5
|
keystroke-domain: files
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Files
|
|
9
9
|
|
|
10
|
-
Files under `src/files/` mount into the agent sandbox at `/workspace/`.
|
|
10
|
+
Files under `src/files/` mount into the agent sandbox at `/workspace/agent/`.
|
|
11
11
|
|
|
12
12
|
## Layout
|
|
13
13
|
|
|
@@ -19,15 +19,16 @@ src/files/support/
|
|
|
19
19
|
|
|
20
20
|
```ts
|
|
21
21
|
import { defineAgent } from "@keystrokehq/agent";
|
|
22
|
+
import { defineSandbox } from "@keystrokehq/sandbox";
|
|
22
23
|
|
|
23
24
|
export default defineAgent({
|
|
24
25
|
slug: "support",
|
|
25
|
-
systemPrompt: "Read /workspace/product-guide.md before answering.",
|
|
26
|
-
files: true, // uses agent
|
|
26
|
+
systemPrompt: "Read /workspace/agent/product-guide.md before answering.",
|
|
27
|
+
sandbox: defineSandbox({ files: true }), // uses agent slug → src/files/support/
|
|
27
28
|
});
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
Use `files: "shared"` to mount `src/files/shared/` instead.
|
|
31
|
+
Use `defineSandbox({ files: "shared" })` to mount `src/files/shared/` instead.
|
|
31
32
|
|
|
32
33
|
Point the agent at paths in `systemPrompt`. After `keystroke start`, verify behavior with `keystroke agent prompt support --message "…"`.
|
|
33
34
|
|
|
@@ -11,7 +11,7 @@ Gateways route **Slack (and similar) messages** to an agent — users chat in-ch
|
|
|
11
11
|
|
|
12
12
|
## Setup (Slack)
|
|
13
13
|
|
|
14
|
-
1. Set Slack app env vars in `.env` (see
|
|
14
|
+
1. Set Slack app env vars in `.env` (see apps skill)
|
|
15
15
|
2. `keystroke start` — open dashboard at `:3000`
|
|
16
16
|
3. Complete Slack OAuth install
|
|
17
17
|
4. **Gateways → Slack → Attach** — pick an agent key + channel
|
|
@@ -40,4 +40,4 @@ keystroke agent sessions get <agent-key> <session-id> --include messages,trace
|
|
|
40
40
|
|
|
41
41
|
- [slack-setup.md](references/slack-setup.md) — env vars, attach flow
|
|
42
42
|
|
|
43
|
-
Related: [agents](.agents/skills/keystroke-agents/SKILL.md), [
|
|
43
|
+
Related: [agents](.agents/skills/keystroke-agents/SKILL.md), [apps](.agents/skills/keystroke-apps/SKILL.md).
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## .env
|
|
4
4
|
|
|
5
|
-
Set Slack
|
|
5
|
+
Set Slack OAuth provider env vars in `.env` (client id, secret, signing secret) — then connect the Slack app with `keystroke connect slack`.
|
|
6
6
|
|
|
7
7
|
## Install & bind
|
|
8
8
|
|
|
@@ -56,7 +56,7 @@ Unit-test through `executeWorkflow` from `@keystrokehq/workflow` — never call
|
|
|
56
56
|
|
|
57
57
|
## Next references
|
|
58
58
|
|
|
59
|
-
- [authoring.md](references/authoring.md) — agents in actions,
|
|
59
|
+
- [authoring.md](references/authoring.md) — agents in actions, app connections, composition
|
|
60
60
|
- [testing.md](references/testing.md) — unit tests, stubbing actions, run/trace debugging
|
|
61
61
|
|
|
62
62
|
Related: [actions](.agents/skills/keystroke-actions/SKILL.md), [triggers](.agents/skills/keystroke-triggers/SKILL.md), [agents](.agents/skills/keystroke-agents/SKILL.md).
|
|
@@ -32,9 +32,9 @@ Use a wrapper action only when the agent call should also be an agent tool, or w
|
|
|
32
32
|
|
|
33
33
|
When an action must call an agent (e.g. the action is reused as an agent tool), call `.prompt()` inside the action's `run`. That prompt is not a separate workflow step — the action is.
|
|
34
34
|
|
|
35
|
-
##
|
|
35
|
+
## Connecting apps
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Sync the app into `src/apps/`, author with `app.action()`, then `keystroke connect <slug>` before testing. Catalog integration actions from npm packages work once the app is connected.
|
|
38
38
|
|
|
39
39
|
## Keys
|
|
40
40
|
|
|
@@ -1,18 +1,4 @@
|
|
|
1
|
-
PUBLIC_SERVER_URL=http://localhost:3001
|
|
2
|
-
|
|
3
|
-
# Required for agent prompts
|
|
4
1
|
ANTHROPIC_API_KEY=
|
|
5
|
-
|
|
6
|
-
# Better Auth (required for /api/auth/* and web login)
|
|
7
2
|
BETTER_AUTH_SECRET=dev-better-auth-secret-min-32-chars!!
|
|
8
3
|
PUBLIC_WEB_URL=http://localhost:3000
|
|
9
|
-
|
|
10
|
-
# Optional — defaults to sqlite at ./data/dev.db
|
|
11
|
-
# DATABASE_URL=file:./data/dev.db
|
|
12
|
-
#
|
|
13
|
-
# Postgres:
|
|
14
|
-
# POSTGRES_HOST=localhost
|
|
15
|
-
# POSTGRES_PORT=5432
|
|
16
|
-
# POSTGRES_DB=keystroke
|
|
17
|
-
# POSTGRES_USER=keystroke
|
|
18
|
-
# POSTGRES_PASSWORD=keystroke
|
|
4
|
+
PUBLIC_PLATFORM_URL=http://localhost:3002
|
|
@@ -7,7 +7,7 @@ Keystroke project — agents, workflows, actions, and triggers under `src/`. See
|
|
|
7
7
|
```bash
|
|
8
8
|
pnpm install # @keystrokehq/* from GitHub Packages (see .npmrc)
|
|
9
9
|
# .env is created from .env.example on init — set ANTHROPIC_API_KEY and integration keys
|
|
10
|
-
keystroke start # API :
|
|
10
|
+
keystroke start # API :3002, dashboard :3000
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
Login at `http://localhost:3000` (`admin@example.com` / `adminadmin` by default).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { Nn as originFromPublicUrl, ot as LOCAL_PLATFORM_ORIGIN } from "./dist-YV-kApfg.mjs";
|
|
3
3
|
import Conf from "conf";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
@@ -7,17 +7,16 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
7
7
|
import { spawnSync } from "node:child_process";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
//#region src/resolve-platform-url.ts
|
|
10
|
-
const DEFAULT_WEB_URL = "https://
|
|
10
|
+
const DEFAULT_WEB_URL = "https://keystroke.ai";
|
|
11
11
|
const DEFAULT_PLATFORM_URL = "https://api.keystroke.ai";
|
|
12
|
-
const LOCAL_PLATFORM_URL = "http://localhost:3002";
|
|
13
12
|
function webOriginFromUrl(webUrl) {
|
|
14
13
|
return originFromPublicUrl(webUrl, webUrl.replace(/\/+$/, ""));
|
|
15
14
|
}
|
|
16
15
|
/** Known web origins with a fixed platform API — undefined for custom/staging URLs. */
|
|
17
16
|
function knownPlatformUrlForWebUrl(webUrl) {
|
|
18
17
|
const webOrigin = webOriginFromUrl(webUrl);
|
|
19
|
-
if (webOrigin === "http://localhost:3000" || webOrigin === "http://127.0.0.1:3000") return
|
|
20
|
-
if (webOrigin === "https://
|
|
18
|
+
if (webOrigin === "http://localhost:3000" || webOrigin === "http://127.0.0.1:3000") return LOCAL_PLATFORM_ORIGIN;
|
|
19
|
+
if (webOrigin === "https://keystroke.ai") return DEFAULT_PLATFORM_URL;
|
|
21
20
|
}
|
|
22
21
|
function resolvePlatformUrlForWebUrl(webUrl, options = {}) {
|
|
23
22
|
const explicit = options.platformUrl?.trim();
|
|
@@ -37,6 +36,7 @@ function getConfigDir(config) {
|
|
|
37
36
|
function getEffectiveApiTarget(config) {
|
|
38
37
|
const explicit = config.get("apiTarget");
|
|
39
38
|
if (explicit === "local" || explicit === "platform") return explicit;
|
|
39
|
+
if (process.env.KEYSTROKE_API_KEY?.trim()) return "platform";
|
|
40
40
|
return "local";
|
|
41
41
|
}
|
|
42
42
|
function syncPlatformUrlWithWebUrl(config) {
|
|
@@ -49,10 +49,6 @@ function createCliConfig(cwd = getCliConfigDir()) {
|
|
|
49
49
|
projectName: "keystroke",
|
|
50
50
|
cwd,
|
|
51
51
|
schema: {
|
|
52
|
-
serverUrl: {
|
|
53
|
-
type: "string",
|
|
54
|
-
default: "http://localhost:3001"
|
|
55
|
-
},
|
|
56
52
|
webUrl: {
|
|
57
53
|
type: "string",
|
|
58
54
|
default: DEFAULT_WEB_URL
|
|
@@ -72,13 +68,13 @@ function createCliConfig(cwd = getCliConfigDir()) {
|
|
|
72
68
|
syncPlatformUrlWithWebUrl(config);
|
|
73
69
|
return config;
|
|
74
70
|
}
|
|
75
|
-
function getServerUrl(config) {
|
|
76
|
-
return config.get("serverUrl");
|
|
77
|
-
}
|
|
78
71
|
function getWebUrl(config) {
|
|
79
72
|
return config.get("webUrl");
|
|
80
73
|
}
|
|
81
74
|
function getPlatformUrl(config) {
|
|
75
|
+
const apiKey = process.env.KEYSTROKE_API_KEY?.trim();
|
|
76
|
+
const fromEnv = process.env.KEYSTROKE_PLATFORM_URL?.trim();
|
|
77
|
+
if (apiKey && fromEnv) return fromEnv.replace(/\/+$/, "");
|
|
82
78
|
return resolvePlatformUrlForWebUrl(getWebUrl(config), { fallback: config.get("platformUrl") });
|
|
83
79
|
}
|
|
84
80
|
//#endregion
|
|
@@ -168,6 +164,6 @@ function readCliVersion() {
|
|
|
168
164
|
return JSON.parse(readFileSync(packageJsonPath, "utf8")).version ?? "0.0.0";
|
|
169
165
|
}
|
|
170
166
|
//#endregion
|
|
171
|
-
export {
|
|
167
|
+
export { installPlaygroundDependencies as a, createCliConfig as c, getEffectiveApiTarget as d, getPlatformUrl as f, resolvePlatformUrlForWebUrl as g, DEFAULT_WEB_URL as h, installDependencies as i, getCliConfigDir as l, DEFAULT_PLATFORM_URL as m, buildPlaygroundWorkspace as n, resolvePackageManager as o, getWebUrl as p, detectPackageManager as r, resolveCliRoot as s, readCliVersion as t, getConfigDir as u };
|
|
172
168
|
|
|
173
|
-
//# sourceMappingURL=version-
|
|
169
|
+
//# sourceMappingURL=version-BGuC7Cpu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-BGuC7Cpu.mjs","names":[],"sources":["../src/resolve-platform-url.ts","../src/config.ts","../src/project/resolve-cli-root.ts","../src/init/package-manager.ts","../src/version.ts"],"sourcesContent":["import { LOCAL_PLATFORM_ORIGIN, originFromPublicUrl } from \"@keystrokehq/shared\";\n\nexport const DEFAULT_WEB_URL = \"https://keystroke.ai\";\nexport const DEFAULT_PLATFORM_URL = \"https://api.keystroke.ai\";\nexport const LOCAL_WEB_URL = \"http://localhost:3000\";\n\nexport type ResolvePlatformUrlOptions = {\n platformUrl?: string;\n /** Used when webUrl does not match a known deployment. */\n fallback?: string;\n};\n\nfunction webOriginFromUrl(webUrl: string): string {\n return originFromPublicUrl(webUrl, webUrl.replace(/\\/+$/, \"\"));\n}\n\n/** Known web origins with a fixed platform API — undefined for custom/staging URLs. */\nexport function knownPlatformUrlForWebUrl(webUrl: string): string | undefined {\n const webOrigin = webOriginFromUrl(webUrl);\n\n if (webOrigin === LOCAL_WEB_URL || webOrigin === \"http://127.0.0.1:3000\") {\n return LOCAL_PLATFORM_ORIGIN;\n }\n\n if (webOrigin === DEFAULT_WEB_URL) {\n return DEFAULT_PLATFORM_URL;\n }\n\n return undefined;\n}\n\nexport function resolvePlatformUrlForWebUrl(\n webUrl: string,\n options: ResolvePlatformUrlOptions = {},\n): string {\n const explicit = options.platformUrl?.trim();\n if (explicit) {\n return explicit.replace(/\\/+$/, \"\");\n }\n\n const known = knownPlatformUrlForWebUrl(webUrl);\n if (known) {\n return known;\n }\n\n const fallback = options.fallback?.trim() || DEFAULT_PLATFORM_URL;\n return fallback.replace(/\\/+$/, \"\");\n}\n","import Conf from \"conf\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n DEFAULT_PLATFORM_URL,\n DEFAULT_WEB_URL,\n knownPlatformUrlForWebUrl,\n resolvePlatformUrlForWebUrl,\n} from \"./resolve-platform-url\";\n\nexport type ApiTargetMode = \"local\" | \"platform\";\n\nexport type CliConfig = {\n webUrl: string;\n platformUrl: string;\n activeOrganizationId?: string;\n activeProjectId?: string;\n apiTarget?: ApiTargetMode;\n};\n\nexport function getCliConfigDir(cwd = join(homedir(), \".keystroke\")): string {\n return cwd;\n}\n\nexport function getConfigDir(config: Conf<CliConfig>): string {\n return dirname(config.path);\n}\n\nexport function getEffectiveApiTarget(config: Conf<CliConfig>): ApiTargetMode {\n const explicit = config.get(\"apiTarget\");\n if (explicit === \"local\" || explicit === \"platform\") {\n return explicit;\n }\n\n if (process.env.KEYSTROKE_API_KEY?.trim()) {\n return \"platform\";\n }\n\n return \"local\";\n}\n\nfunction syncPlatformUrlWithWebUrl(config: Conf<CliConfig>): void {\n const webUrl = config.get(\"webUrl\");\n const known = knownPlatformUrlForWebUrl(webUrl);\n if (!known) {\n return;\n }\n\n const stored = config.get(\"platformUrl\");\n if (stored !== known) {\n config.set(\"platformUrl\", known);\n }\n}\n\nexport function createCliConfig(cwd = getCliConfigDir()): Conf<CliConfig> {\n const config = new Conf<CliConfig>({\n projectName: \"keystroke\",\n cwd,\n schema: {\n webUrl: {\n type: \"string\",\n default: DEFAULT_WEB_URL,\n },\n platformUrl: {\n type: \"string\",\n default: DEFAULT_PLATFORM_URL,\n },\n activeOrganizationId: {\n type: \"string\",\n },\n activeProjectId: {\n type: \"string\",\n },\n apiTarget: {\n type: \"string\",\n enum: [\"local\", \"platform\"],\n },\n },\n });\n\n syncPlatformUrlWithWebUrl(config);\n return config;\n}\n\nexport function getWebUrl(config: Conf<CliConfig>): string {\n return config.get(\"webUrl\");\n}\n\nexport function getPlatformUrl(config: Conf<CliConfig>): string {\n const apiKey = process.env.KEYSTROKE_API_KEY?.trim();\n const fromEnv = process.env.KEYSTROKE_PLATFORM_URL?.trim();\n if (apiKey && fromEnv) {\n return fromEnv.replace(/\\/+$/, \"\");\n }\n return resolvePlatformUrlForWebUrl(getWebUrl(config), {\n fallback: config.get(\"platformUrl\"),\n });\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction isCliPackage(dir: string): boolean {\n const packageJsonPath = join(dir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return false;\n }\n\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { name?: string };\n return pkg.name === \"@keystrokehq/cli\";\n}\n\nexport function resolveCliRoot(fromModuleUrl: string): string {\n let dir = dirname(fileURLToPath(fromModuleUrl));\n\n while (dir !== dirname(dir)) {\n if (isCliPackage(dir)) {\n return dir;\n }\n\n dir = dirname(dir);\n }\n\n throw new Error(\"Could not resolve keystroke CLI package root\");\n}\n","import { spawnSync } from \"node:child_process\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nconst MANAGERS: PackageManager[] = [\"pnpm\", \"npm\", \"yarn\", \"bun\"];\n\nexport function detectPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent ?? \"\";\n\n for (const manager of MANAGERS) {\n if (userAgent.startsWith(manager)) {\n return manager;\n }\n }\n\n if (process.env.PNPM_HOME) {\n return \"pnpm\";\n }\n\n return \"npm\";\n}\n\nexport function resolvePackageManager(explicit?: string): PackageManager {\n if (!explicit) {\n return detectPackageManager();\n }\n\n const normalized = explicit.trim().toLowerCase();\n if (!MANAGERS.includes(normalized as PackageManager)) {\n throw new Error(`Unsupported package manager \"${explicit}\". Use npm, pnpm, yarn, or bun.`);\n }\n\n return normalized as PackageManager;\n}\n\n/** Resolve GitHub Packages auth for @keystrokehq/* when NODE_AUTH_TOKEN is unset. */\nexport function resolveGithubPackagesToken(): string | undefined {\n if (process.env.NODE_AUTH_TOKEN) {\n return process.env.NODE_AUTH_TOKEN;\n }\n\n for (const key of [\"GITHUB_TOKEN\", \"GH_TOKEN\"] as const) {\n const value = process.env[key];\n if (value) {\n return value;\n }\n }\n\n const gh = spawnSync(\"gh\", [\"auth\", \"token\"], { encoding: \"utf8\" });\n if (gh.status === 0) {\n const token = gh.stdout.trim();\n if (token) {\n return token;\n }\n }\n\n return undefined;\n}\n\nexport function installDependencies(cwd: string, manager: PackageManager): void {\n const token = resolveGithubPackagesToken();\n const env = token ? { ...process.env, NODE_AUTH_TOKEN: token } : process.env;\n\n const result = spawnSync(manager, [\"install\"], {\n cwd,\n stdio: \"inherit\",\n env,\n });\n\n if (result.status !== 0) {\n throw new Error(`${manager} install failed`);\n }\n}\n\nexport function installPlaygroundDependencies(cwd: string): void {\n const result = spawnSync(\"pnpm\", [\"install\", \"--ignore-workspace\"], {\n cwd,\n stdio: \"inherit\",\n env: process.env,\n });\n\n if (result.status !== 0) {\n throw new Error(\"pnpm install failed\");\n }\n}\n\n/**\n * Build every workspace package so the playground's `link:` deps resolve to\n * compiled `dist/`. Without this, `keystroke dev` fails with\n * `ERR_MODULE_NOT_FOUND` against whichever package was never built. Turbo\n * caches, so this is only slow on the first run.\n */\nexport function buildPlaygroundWorkspace(monorepoRoot: string): void {\n // Build with a clean Node env: the `keystroke-dev` wrapper sets\n // NODE_OPTIONS=--conditions=development, which would make tsdown/turbo resolve\n // their own deps to src/ and fail. Dropping NODE_OPTIONS builds to dist/ normally.\n const { NODE_OPTIONS: _drop, ...buildEnv } = process.env;\n const result = spawnSync(\"pnpm\", [\"run\", \"build\"], {\n cwd: monorepoRoot,\n stdio: \"inherit\",\n env: buildEnv,\n });\n\n if (result.status !== 0) {\n throw new Error(\"workspace build failed (pnpm run build)\");\n }\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { resolveCliRoot } from \"./project/resolve-cli-root\";\n\nexport function readCliVersion(): string {\n const packageJsonPath = join(resolveCliRoot(import.meta.url), \"package.json\");\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { version?: string };\n return pkg.version ?? \"0.0.0\";\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keystrokehq/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/keystrokehq/keystroke.git",
|
|
@@ -19,17 +19,22 @@
|
|
|
19
19
|
"registry": "https://registry.npmjs.org"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
+
"@aws-sdk/client-s3": "^3.1070.0",
|
|
23
|
+
"@aws-sdk/s3-request-presigner": "^3.1070.0",
|
|
22
24
|
"@inquirer/prompts": "^8.4.3",
|
|
23
25
|
"@napi-rs/keyring": "^1.3.0",
|
|
24
|
-
"
|
|
26
|
+
"@parcel/watcher": "^2.5.6",
|
|
27
|
+
"better-sqlite3": "^12.10.0",
|
|
25
28
|
"commander": "^14.0.3",
|
|
26
29
|
"conf": "^15.1.0",
|
|
30
|
+
"drizzle-orm": "^0.45.2",
|
|
27
31
|
"picomatch": "^4.0.4",
|
|
28
32
|
"tsdown": "^0.22.0"
|
|
29
33
|
},
|
|
30
34
|
"devDependencies": {
|
|
31
35
|
"@types/node": "^25.9.1",
|
|
32
36
|
"better-auth": "^1.6.11",
|
|
37
|
+
"es-module-lexer": "^2.1.0",
|
|
33
38
|
"oxlint": "^1.66.0",
|
|
34
39
|
"tsdown": "^0.22.0",
|
|
35
40
|
"tsx": "^4.22.3",
|
|
@@ -44,6 +49,7 @@
|
|
|
44
49
|
"build": "tsx scripts/generate-catalog-versions.ts && tsdown && node scripts/copy-templates.mjs && node scripts/copy-skills-bundle.mjs",
|
|
45
50
|
"generate:catalog-versions": "tsx scripts/generate-catalog-versions.ts",
|
|
46
51
|
"pack:portable": "node scripts/pack.mjs",
|
|
52
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
47
53
|
"link-dev": "bash scripts/link-dev.sh",
|
|
48
54
|
"dev": "tsx src/index.ts",
|
|
49
55
|
"lint": "oxlint .",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dist-B9XaHV_2.mjs","names":["toPosix"],"sources":["../../../packages/build/dist/walk-project-eZ95LOUW.mjs","../../../packages/tsdown-config/deps.js","../../../packages/tsdown-config/index.js","../../../packages/build/dist/index.mjs"],"sourcesContent":["import { readFileSync, readdirSync, realpathSync, statSync } from \"node:fs\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { entryIdFromFile, readKeystrokeIgnoreDirective, shouldSkipKeystrokeModuleFile } from \"@keystrokehq/manifest/discovery\";\nimport { fileURLToPath } from \"node:url\";\n//#region src/ignore-guard-plugin.ts\nfunction toPosix$1(path) {\n\treturn path.split(sep).join(\"/\");\n}\nfunction projectRelativePath(root, filePath) {\n\treturn toPosix$1(relative(root, normalizeBuildFilePath(filePath)));\n}\n/** Normalize paths so /var and /private/var compare equal on macOS. */\nfunction normalizeBuildFilePath(filePath) {\n\tconst absolute = resolve(filePath);\n\ttry {\n\t\treturn realpathSync.native(absolute);\n\t} catch {\n\t\treturn absolute;\n\t}\n}\nfunction normalizeModuleId(id, root) {\n\tif (id.startsWith(\"\\0\")) return null;\n\tconst normalized = normalizeBuildFilePath(id.startsWith(\"file://\") ? fileURLToPath(id) : id);\n\tif (!normalized.startsWith(normalizeBuildFilePath(root))) return null;\n\treturn normalized;\n}\nfunction formatImportGuardError(root, ignoredPath, importer) {\n\tconst ignored = projectRelativePath(root, ignoredPath);\n\tif (importer) return `Cannot import \"${ignored}\" (@keystroke ignore) from \"${projectRelativePath(root, importer)}\". Remove the directive or stop importing it from a shipped module.`;\n\treturn `Cannot import \"${ignored}\" (@keystroke ignore). Remove the directive or stop importing it from a shipped module.`;\n}\n/** Throw when a built module imports a `@keystroke ignore` source file. */\nfunction keystrokeIgnoreGuardPlugin(options) {\n\tconst root = normalizeBuildFilePath(options.root);\n\tconst ignoredFiles = new Set(options.ignoredFiles.map((filePath) => normalizeBuildFilePath(filePath)));\n\tfunction assertNotIgnored(filePath, importer) {\n\t\tconst normalized = normalizeBuildFilePath(filePath);\n\t\tif (!ignoredFiles.has(normalized)) return;\n\t\tthrow new Error(formatImportGuardError(root, normalized, importer));\n\t}\n\treturn {\n\t\tname: \"keystroke-ignore-guard\",\n\t\tasync resolveId(source, importer, resolveOptions) {\n\t\t\tif (resolveOptions?.isEntry || !importer) return null;\n\t\t\tconst resolved = await this.resolve(source, importer, {\n\t\t\t\t...resolveOptions,\n\t\t\t\tskipSelf: true\n\t\t\t});\n\t\t\tif (!resolved) return null;\n\t\t\tassertNotIgnored(typeof resolved === \"string\" ? resolved : resolved.id, importer);\n\t\t\treturn null;\n\t\t},\n\t\tload(id) {\n\t\t\tconst normalized = normalizeModuleId(id, root);\n\t\t\tif (!normalized) return null;\n\t\t\tassertNotIgnored(normalized);\n\t\t\treturn null;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/walk-project.ts\nconst IGNORED_DIRS = new Set([\n\t\"node_modules\",\n\t\"dist\",\n\t\".git\",\n\t\".turbo\",\n\t\"build\",\n\t\"coverage\",\n\t\".keystroke\",\n\t\".cache\",\n\t\"tmp\"\n]);\nconst IGNORED_ENV_FILE = /\\.env/;\nconst IGNORED_LOG_FILE = /\\.log$/;\nfunction isIgnoredFile(name) {\n\treturn IGNORED_ENV_FILE.test(name) || IGNORED_LOG_FILE.test(name);\n}\nfunction toPosix(path) {\n\treturn path.split(sep).join(\"/\");\n}\nfunction isProbablyBinary(buffer) {\n\tconst sampleLength = Math.min(buffer.length, 8e3);\n\tfor (let index = 0; index < sampleLength; index += 1) if (buffer[index] === 0) return true;\n\treturn false;\n}\nfunction classifyBuildEntry(root, srcRoot, filePath) {\n\tconst relativePath = toPosix(relative(root, filePath));\n\tconst agentsPrefix = `${toPosix(relative(root, join(srcRoot, \"agents\")))}/`;\n\tconst workflowsPrefix = `${toPosix(relative(root, join(srcRoot, \"workflows\")))}/`;\n\tconst triggersPrefix = `${toPosix(relative(root, join(srcRoot, \"triggers\")))}/`;\n\tif (relativePath.startsWith(agentsPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"agents\"), filePath, { nestedEntry: \"agent\" });\n\t\treturn id ? {\n\t\t\tentryKey: `agents/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\tif (relativePath.startsWith(workflowsPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"workflows\"), filePath, { nestedEntry: \"workflow\" });\n\t\treturn id ? {\n\t\t\tentryKey: `workflows/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\tif (relativePath.startsWith(triggersPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"triggers\"), filePath, { nestedEntry: \"trigger\" });\n\t\treturn id ? {\n\t\t\tentryKey: `triggers/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\treturn null;\n}\nfunction shouldSkipIgnoredModule(filePath, phase) {\n\treturn shouldSkipKeystrokeModuleFile(readKeystrokeIgnoreDirective(filePath), phase);\n}\nfunction isSrcTypeScriptFile(srcRoot, filePath) {\n\tconst relativePath = toPosix(relative(srcRoot, filePath));\n\tif (relativePath.startsWith(\"..\")) return false;\n\treturn /\\.(ts|mts)$/.test(relativePath);\n}\nfunction walkTree(root, dir, srcRoot, phase, collectSources, sourceFiles, buildEntries, ignoredFiles, totals) {\n\tfor (const name of readdirSync(dir).sort()) {\n\t\tif (collectSources && (sourceFiles.length >= 2e3 || totals.bytes >= 8388608)) return;\n\t\tconst absolute = join(dir, name);\n\t\tconst stats = statSync(absolute);\n\t\tif (stats.isDirectory()) {\n\t\t\tif (IGNORED_DIRS.has(name)) continue;\n\t\t\twalkTree(root, absolute, srcRoot, phase, collectSources, sourceFiles, buildEntries, ignoredFiles, totals);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!stats.isFile()) continue;\n\t\tconst isUnderSrc = isSrcTypeScriptFile(srcRoot, absolute);\n\t\tconst skipIgnored = isUnderSrc ? shouldSkipIgnoredModule(absolute, phase) : false;\n\t\tif (isUnderSrc && skipIgnored) ignoredFiles.push(normalizeBuildFilePath(absolute));\n\t\tconst buildEntry = classifyBuildEntry(root, srcRoot, absolute);\n\t\tif (buildEntry && !skipIgnored) buildEntries[buildEntry.entryKey] = buildEntry.entryPath;\n\t\tif (!collectSources) continue;\n\t\tif (stats.size > 262144 || isIgnoredFile(name)) continue;\n\t\tconst buffer = readFileSync(absolute);\n\t\tif (isProbablyBinary(buffer)) continue;\n\t\ttotals.bytes += buffer.byteLength;\n\t\tsourceFiles.push({\n\t\t\tpath: toPosix(relative(root, absolute)),\n\t\t\tcontents: buffer.toString(\"utf8\"),\n\t\t\thash: createHash(\"sha256\").update(buffer).digest(\"hex\")\n\t\t});\n\t}\n}\n/**\n* One full-tree walk of the project: classifies tsdown entries and optionally\n* collects deploy source files (path + contents + hash) under snapshot limits.\n*/\nfunction walkProject(root, srcDirOrOptions = \"src\", maybeOptions) {\n\tconst srcDir = typeof srcDirOrOptions === \"string\" ? srcDirOrOptions : srcDirOrOptions.srcDir ?? \"src\";\n\tconst options = typeof srcDirOrOptions === \"string\" ? maybeOptions ?? {} : srcDirOrOptions;\n\tconst collectSources = options.collectSources ?? false;\n\tconst phase = options.phase ?? \"build\";\n\tconst sourceFiles = [];\n\tconst buildEntries = {};\n\tconst ignoredFiles = [];\n\twalkTree(root, root, join(root, srcDir), phase, collectSources, sourceFiles, buildEntries, ignoredFiles, { bytes: 0 });\n\treturn {\n\t\tsourceFiles,\n\t\tbuildEntries,\n\t\tignoredFiles\n\t};\n}\n//#endregion\nexport { keystrokeIgnoreGuardPlugin as n, walkProject as t };\n\n//# sourceMappingURL=walk-project-eZ95LOUW.mjs.map","import { isBuiltin } from \"node:module\";\n\n/** Native addons kept external — resolved from the CLI runtime at app start. */\nexport const NATIVE_RUNTIME_DEPS = [\"pg\", \"better-sqlite3\", \"@parcel/watcher\"];\n\n/**\n * Integration packages (`packages/integrations/*`) bundled into the user-app artifact so a\n * project carries its own integration code/version. Their framework imports (`@keystrokehq/keystroke`,\n * `@keystrokehq/action`, …) stay external and resolve from the runtime image. `slack` is excluded —\n * it is a gateway integration the runtime mounts server-side, so it stays in the runtime image.\n */\nexport const BUNDLED_INTEGRATION_PACKAGES = [\n \"exa\",\n \"github\",\n \"gong\",\n \"googlesuper\",\n \"slackbot\",\n \"snowflake\",\n];\n\n/** Matches framework `@keystrokehq/*` (everything except the bundled integration packages). */\nexport const FRAMEWORK_KEYSTROKE_EXTERNAL = new RegExp(\n `^@keystrokehq\\\\/(?!(?:${BUNDLED_INTEGRATION_PACKAGES.join(\"|\")})(?:\\\\/|$))`,\n);\n\nfunction isBundledIntegration(name) {\n if (!name.startsWith(\"@keystrokehq/\")) {\n return false;\n }\n\n return BUNDLED_INTEGRATION_PACKAGES.includes(name.slice(\"@keystrokehq/\".length));\n}\n\n/** Kept external so .d.ts emission does not inline internal/inferred types. */\nexport const LIBRARY_EXTERNAL_DEPS = [\"better-auth\", /^@better-auth\\//, /^better-auth\\//];\n\n/** Non-auth runtime deps kept external for published entry bundles (platform, etc.). */\nexport const BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS = [\n ...NATIVE_RUNTIME_DEPS,\n \"dockerode\",\n \"ssh2\",\n \"cpu-features\",\n \"microsandbox\",\n /^@aws-sdk\\//,\n /^@napi-rs\\//,\n \"hono\",\n /^@hono\\//,\n \"undici\",\n];\n\n/** Kept external when bundling published entry points (cli, keystroke, platform). */\nexport const BUNDLED_ENTRY_EXTERNAL_DEPS = [\n ...BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS,\n ...LIBRARY_EXTERNAL_DEPS,\n];\n\n/** Bundle into CLI — device login uses Better Auth client only. */\nexport const BETTER_AUTH_CLIENT_BUNDLE_PATTERNS = [\n /^better-auth\\/client$/,\n /^better-auth\\/client\\//,\n];\n\n/** Server adapters and root entry — must not ship in the CLI bundle. */\nexport const BETTER_AUTH_SERVER_EXTERNAL_PATTERNS = [\n /^better-auth$/,\n /^@better-auth\\//,\n /^better-auth\\/(?!client(\\/|$)).+/,\n];\n\nexport function isNativeRuntimeDep(id) {\n return NATIVE_RUNTIME_DEPS.some((dep) => id === dep || id.startsWith(`${dep}/`));\n}\n\nfunction packageName(id) {\n if (id.startsWith(\"@\")) {\n const [scope, name] = id.split(\"/\");\n return name ? `${scope}/${name}` : id;\n }\n\n return id.split(\"/\")[0] ?? id;\n}\n\nfunction isRuntimeExternal(id) {\n const name = packageName(id);\n if (isNativeRuntimeDep(name)) {\n return true;\n }\n\n if (name.startsWith(\"@keystrokehq/\")) {\n return !isBundledIntegration(name);\n }\n\n if (name === \"better-auth\" || name.startsWith(\"@better-auth/\")) {\n return true;\n }\n\n return false;\n}\n\n/** Library packages resolve npm deps from node_modules at runtime. */\nexport function libraryBuildDepsConfig() {\n return {\n alwaysBundle: (_id) => null,\n neverBundle: [...NATIVE_RUNTIME_DEPS, /^@keystrokehq\\//, ...LIBRARY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/** Bundle npm deps into dist; resolve @keystrokehq/* and natives from the runtime. */\nexport function userAppBuildDepsConfig() {\n return {\n alwaysBundle: (id, _importer) => {\n if (id.startsWith(\".\") || id.startsWith(\"/\") || isBuiltin(id)) {\n return null;\n }\n\n return isRuntimeExternal(id) ? null : true;\n },\n neverBundle: [...NATIVE_RUNTIME_DEPS, FRAMEWORK_KEYSTROKE_EXTERNAL, ...LIBRARY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/**\n * Published entry packages (cli, keystroke, platform): declare bundled @keystrokehq/*\n * in dependencies (changesets release graph ignores devDependencies). Inlining is\n * driven by alwaysBundle below, not by dep kind. Runtime npm deps stay external.\n */\nexport function bundledEntryDepsConfig() {\n return {\n alwaysBundle: [/^@keystrokehq\\//],\n neverBundle: [...BUNDLED_ENTRY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/** Published CLI: inline better-auth client + @better-auth/*; keep server adapters external. */\nexport const BETTER_AUTH_CLI_BUNDLE_PATTERNS = [\n ...BETTER_AUTH_CLIENT_BUNDLE_PATTERNS,\n /^@better-auth\\//,\n];\n\nexport const BETTER_AUTH_CLI_EXTERNAL_PATTERNS = [\n /^better-auth$/,\n /^better-auth\\/(?!client(\\/|$)).+/,\n /^@better-auth\\/drizzle-adapter/,\n \"drizzle-orm\",\n];\n\n/** Rolldown/tsdown — native bindings; stay in CLI node_modules at runtime. */\nexport const CLI_BUILD_TOOL_EXTERNAL_PATTERNS = [\"tsdown\", \"rolldown\", /^@rolldown\\//, \"tsx\"];\n\n/** CLI: inline better-auth/client; keep server + drizzle adapters external. */\nexport function cliBundledEntryDepsConfig() {\n return {\n alwaysBundle: [/^@keystrokehq\\//, ...BETTER_AUTH_CLI_BUNDLE_PATTERNS],\n neverBundle: [\n ...BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS,\n ...BETTER_AUTH_CLI_EXTERNAL_PATTERNS,\n ...CLI_BUILD_TOOL_EXTERNAL_PATTERNS,\n ],\n onlyBundle: false,\n };\n}\n","import { bundledEntryDepsConfig, libraryBuildDepsConfig, userAppBuildDepsConfig } from \"./deps.js\";\n\nexport {\n isNativeRuntimeDep,\n NATIVE_RUNTIME_DEPS,\n bundledEntryDepsConfig,\n cliBundledEntryDepsConfig,\n libraryBuildDepsConfig,\n userAppBuildDepsConfig,\n} from \"./deps.js\";\n\nexport const baseTsdownConfig = {\n format: [\"esm\", \"cjs\"],\n dts: true,\n clean: true,\n sourcemap: true,\n target: \"node20\",\n deps: libraryBuildDepsConfig(),\n};\n\n/** tsdown config for published bundles (cli, keystroke, platform). */\nexport const bundledEntryTsdownConfig = {\n format: [\"esm\", \"cjs\"],\n dts: true,\n clean: true,\n sourcemap: true,\n target: \"node20\",\n deps: bundledEntryDepsConfig(),\n};\n","import { n as keystrokeIgnoreGuardPlugin, t as walkProject } from \"./walk-project-eZ95LOUW.mjs\";\nimport { t as resolveModuleDirs } from \"./resolve-module-dirs-BPHQhRGy.mjs\";\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\nimport { packAssetDirs } from \"@keystrokehq/sandbox/files\";\nimport { baseTsdownConfig, userAppBuildDepsConfig } from \"@keystrokehq/tsdown-config\";\nimport { build, mergeConfig } from \"tsdown\";\nimport { buildStoredRouteManifestForProject } from \"@keystrokehq/manifest\";\n//#region src/resolve-runtime-artifact.ts\nfunction packageRoot(nodeModules, scope, name) {\n\tconst direct = scope ? join(nodeModules, scope, name) : join(nodeModules, name);\n\tif (existsSync(join(direct, \"package.json\"))) return direct;\n\tconst pnpmDir = join(nodeModules, \".pnpm\");\n\tif (!existsSync(pnpmDir)) return null;\n\tfor (const entry of readdirSync(pnpmDir)) {\n\t\tconst candidate = scope ? join(pnpmDir, entry, \"node_modules\", scope, name) : join(pnpmDir, entry, \"node_modules\", name);\n\t\tif (existsSync(join(candidate, \"package.json\"))) return candidate;\n\t}\n\treturn null;\n}\n/** Resolve a file shipped with `@keystrokehq/build` inside the CLI runtime. */\nfunction resolveRuntimeBuildArtifact(runtimeNodeModules, relativePath) {\n\tconst pkgRoot = packageRoot(runtimeNodeModules, \"@keystrokehq\", \"build\");\n\tif (!pkgRoot) throw new Error(\"Keystroke runtime is missing @keystrokehq/build\");\n\tconst artifact = join(pkgRoot, relativePath);\n\tif (!existsSync(artifact)) throw new Error(`Keystroke runtime artifact not found: ${relativePath}`);\n\treturn artifact;\n}\n//#endregion\n//#region src/vitest-plugin.ts\nconst ASSETS_MODULE$1 = \"@keystrokehq/assets\";\nconst virtualPrefix = `\\0${ASSETS_MODULE$1}:`;\n/** Vitest plugin resolving `@keystrokehq/assets` from disk. */\nfunction agentAssetsVitestPlugin(appRoot = process.cwd()) {\n\tlet manifest = null;\n\treturn {\n\t\tname: \"keystroke-assets\",\n\t\tresolveId(source) {\n\t\t\tif (source !== ASSETS_MODULE$1) return null;\n\t\t\treturn `${virtualPrefix}manifest`;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== `${virtualPrefix}manifest`) return null;\n\t\t\tmanifest ??= packAssetDirs(appRoot);\n\t\t\treturn `export default ${JSON.stringify(manifest)};`;\n\t\t}\n\t};\n}\nfunction findAppRootFromConfig(configFile) {\n\tif (!configFile) return process.cwd();\n\treturn dirname(configFile);\n}\nfunction agentAssetsVitestPluginFromConfig(configFile) {\n\treturn agentAssetsVitestPlugin(findAppRootFromConfig(configFile));\n}\n//#endregion\n//#region src/resolve-build-filter.ts\n/** Resolve exact build-entry keys for a filtered deploy build. */\nfunction resolveBuildFilter(filter, buildEntries) {\n\tif (filter.length === 0) throw new Error(\"At least one --filter entry is required\");\n\tconst matched = {};\n\tfor (const key of [...new Set(filter)]) {\n\t\tconst entryPath = buildEntries[key];\n\t\tif (!entryPath) throw new Error(`Unknown build entry \"${key}\". Use keys like agents/foo or workflows/bar from walkProject.`);\n\t\tmatched[key] = entryPath;\n\t}\n\treturn matched;\n}\n//#endregion\n//#region src/build-filtered.ts\nfunction toPosix(path) {\n\treturn path.replace(/\\\\/g, \"/\");\n}\nfunction distRelativePath(entryKey) {\n\treturn `${entryKey}.mjs`;\n}\nasync function buildSingleEntry(root, entryKey, entryPath, ignoredFiles) {\n\tmkdirSync(join(root, \".keystroke\"), { recursive: true });\n\tconst scratchRoot = mkdtempSync(join(root, \".keystroke\", \"filter-build-\"));\n\tconst outDir = join(scratchRoot, \"dist\");\n\tconst relativePath = distRelativePath(entryKey);\n\tawait build(mergeConfig(baseTsdownConfig, {\n\t\tentry: { [entryKey]: entryPath },\n\t\tformat: [\"esm\"],\n\t\toutDir,\n\t\tclean: true,\n\t\tdts: false,\n\t\tloader: { \".md\": \"text\" },\n\t\tdeps: userAppBuildDepsConfig(),\n\t\tplugins: [keystrokeIgnoreGuardPlugin({\n\t\t\troot,\n\t\t\tignoredFiles\n\t\t})]\n\t}));\n\treturn {\n\t\tscratchRoot,\n\t\trelativePath\n\t};\n}\nasync function manifestEntriesForBuiltModule(root, entryPath, relativePath, contents, sourceMap) {\n\tconst moduleFile = toPosix(relative(root, entryPath));\n\tconst distPath = join(root, \"dist\", relativePath);\n\tconst distMapPath = `${distPath}.map`;\n\tconst previousDist = existsSync(distPath) ? readFileSync(distPath) : void 0;\n\tconst hadMap = existsSync(distMapPath);\n\tconst previousMap = hadMap ? readFileSync(distMapPath) : void 0;\n\tmkdirSync(dirname(distPath), { recursive: true });\n\twriteFileSync(distPath, contents);\n\tif (sourceMap) writeFileSync(distMapPath, sourceMap);\n\ttry {\n\t\treturn (await buildStoredRouteManifestForProject(root, { reloadModules: true })).entries.filter((entry) => \"moduleFile\" in entry && entry.moduleFile === moduleFile);\n\t} finally {\n\t\tif (previousDist) writeFileSync(distPath, previousDist);\n\t\telse rmSync(distPath, { force: true });\n\t\tif (previousMap) writeFileSync(distMapPath, previousMap);\n\t\telse if (sourceMap || hadMap) rmSync(distMapPath, { force: true });\n\t}\n}\n/** Build selected modules in isolation for a filtered deploy merge. */\nasync function buildFilteredApp(options) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst phase = options.phase ?? \"deploy\";\n\tconst collectSources = options.collectSources ?? false;\n\tconst previous = process.cwd();\n\tconst walked = walkProject(root, {\n\t\tsrcDir,\n\t\tcollectSources,\n\t\tphase\n\t});\n\tconst matched = resolveBuildFilter(options.filter, walked.buildEntries);\n\tconst files = [];\n\tconst manifestEntries = [];\n\ttry {\n\t\tprocess.chdir(root);\n\t\tfor (const [entryKey, entryPath] of Object.entries(matched)) {\n\t\t\tconst { scratchRoot, relativePath } = await buildSingleEntry(root, entryKey, entryPath, walked.ignoredFiles);\n\t\t\ttry {\n\t\t\t\tconst builtPath = join(scratchRoot, \"dist\", relativePath);\n\t\t\t\tconst mapPath = `${builtPath}.map`;\n\t\t\t\tconst contents = readFileSync(builtPath);\n\t\t\t\tconst sourceMap = existsSync(mapPath) ? readFileSync(mapPath) : void 0;\n\t\t\t\tfiles.push({\n\t\t\t\t\tentryKey,\n\t\t\t\t\trelativePath,\n\t\t\t\t\tcontents,\n\t\t\t\t\tsourceMap\n\t\t\t\t});\n\t\t\t\tmanifestEntries.push(...await manifestEntriesForBuiltModule(root, entryPath, relativePath, contents, sourceMap));\n\t\t\t} finally {\n\t\t\t\trmSync(scratchRoot, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t\tforce: true\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tprocess.chdir(previous);\n\t}\n\treturn {\n\t\tfiles,\n\t\tmanifestEntries,\n\t\tsourceFiles: walked.sourceFiles\n\t};\n}\n//#endregion\n//#region src/index.ts\nconst ASSETS_MODULE = \"@keystrokehq/assets\";\nconst VIRTUAL_PREFIX = `\\0${ASSETS_MODULE}:`;\nfunction renderAssetModule(manifest) {\n\treturn `export default ${JSON.stringify(manifest)};\\n`;\n}\n/** Rolldown plugin: pack src/skills + src/files and expose `@keystrokehq/assets`. */\nfunction agentAssetsPlugin(options) {\n\tconst srcDir = options.srcDir ?? \"src\";\n\tlet manifest = null;\n\treturn {\n\t\tname: \"keystroke-assets\",\n\t\tbuildStart() {\n\t\t\tmanifest = packAssetDirs(options.root, srcDir);\n\t\t},\n\t\tresolveId(source) {\n\t\t\tif (source !== ASSETS_MODULE) return null;\n\t\t\treturn `${VIRTUAL_PREFIX}manifest`;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== `${VIRTUAL_PREFIX}manifest` || !manifest) return null;\n\t\t\treturn renderAssetModule(manifest);\n\t\t},\n\t\tbuildEnd() {\n\t\t\tif (!manifest) return;\n\t\t\tconst outDir = join(options.root, options.outDir ?? \"dist\", \".keystroke\");\n\t\t\tmkdirSync(outDir, { recursive: true });\n\t\t\twriteFileSync(join(outDir, \"assets.mjs\"), renderAssetModule(manifest));\n\t\t}\n\t};\n}\n/** Full tsdown config for user keystroke apps (config + discovered modules only). */\nfunction createAppBuildConfig(options = {}, walked) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst outDir = options.outDir ?? \"dist\";\n\tconst configEntry = existsSync(join(root, \"keystroke.config.ts\")) ? join(root, \"keystroke.config.ts\") : void 0;\n\tconst walkedResult = walked ?? walkProject(root, {\n\t\tsrcDir,\n\t\tphase: options.phase\n\t});\n\tconst discovered = walkedResult.buildEntries;\n\tconst ignoredFiles = walkedResult.ignoredFiles;\n\tconst entries = {\n\t\t...configEntry ? { config: configEntry } : {},\n\t\t...discovered\n\t};\n\tif (Object.keys(entries).length === 0) throw new Error(\"Nothing to build — add keystroke.config.ts or modules under src/\");\n\treturn mergeConfig(baseTsdownConfig, {\n\t\tentry: entries,\n\t\tformat: [\"esm\"],\n\t\toutDir: join(root, outDir),\n\t\tclean: options.clean ?? true,\n\t\tdts: false,\n\t\tloader: { \".md\": \"text\" },\n\t\tdeps: userAppBuildDepsConfig(),\n\t\tplugins: [keystrokeIgnoreGuardPlugin({\n\t\t\troot,\n\t\t\tignoredFiles\n\t\t}), agentAssetsPlugin({\n\t\t\troot,\n\t\t\tsrcDir,\n\t\t\toutDir\n\t\t})]\n\t});\n}\n/** Build user agents, workflows, triggers, and config to `dist/`. */\nasync function buildApp(options = {}) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst emitManifest = options.emitManifest ?? true;\n\tconst collectSources = options.collectSources ?? false;\n\tconst phase = options.phase ?? \"build\";\n\tconst previous = process.cwd();\n\tconst walked = walkProject(root, {\n\t\tsrcDir,\n\t\tcollectSources,\n\t\tphase\n\t});\n\ttry {\n\t\tprocess.chdir(root);\n\t\tawait build(createAppBuildConfig({\n\t\t\t...options,\n\t\t\troot\n\t\t}, {\n\t\t\tbuildEntries: walked.buildEntries,\n\t\t\tignoredFiles: walked.ignoredFiles\n\t\t}));\n\t\tif (emitManifest) {\n\t\t\tconst { emitStoredRouteManifestForProject } = await import(\"@keystrokehq/manifest\");\n\t\t\tawait emitStoredRouteManifestForProject(root);\n\t\t}\n\t} finally {\n\t\tprocess.chdir(previous);\n\t}\n\treturn { sourceFiles: walked.sourceFiles };\n}\n/**\n* Watch `src/` and rebuild `dist/` on change.\n*\n* NOT true hot reload — each change runs a full tsdown rebuild. Callers should\n* restart the API server in `onRebuild` so discovery picks up new/changed modules.\n*/\nasync function watchApp(options = {}) {\n\tconst { runWatchApp } = await import(\"./watch-app-DTIeKrbl.mjs\");\n\tawait runWatchApp((watchOptions) => buildApp({\n\t\t...watchOptions,\n\t\temitManifest: false,\n\t\tcollectSources: false\n\t}), options);\n}\n//#endregion\nexport { agentAssetsVitestPlugin, agentAssetsVitestPluginFromConfig, buildApp, buildFilteredApp, createAppBuildConfig, resolveBuildFilter, resolveModuleDirs, resolveRuntimeBuildArtifact, watchApp };\n\n//# sourceMappingURL=index.mjs.map"],"mappings":";;;;;;;;;AAMA,SAAS,UAAU,MAAM;CACxB,OAAO,KAAK,MAAM,GAAG,EAAE,KAAK,GAAG;AAChC;AACA,SAAS,oBAAoB,MAAM,UAAU;CAC5C,OAAO,UAAU,SAAS,MAAM,uBAAuB,QAAQ,CAAC,CAAC;AAClE;;AAEA,SAAS,uBAAuB,UAAU;CACzC,MAAM,WAAW,QAAQ,QAAQ;CACjC,IAAI;EACH,OAAO,aAAa,OAAO,QAAQ;CACpC,QAAQ;EACP,OAAO;CACR;AACD;AACA,SAAS,kBAAkB,IAAI,MAAM;CACpC,IAAI,GAAG,WAAW,IAAI,GAAG,OAAO;CAChC,MAAM,aAAa,uBAAuB,GAAG,WAAW,SAAS,IAAI,cAAc,EAAE,IAAI,EAAE;CAC3F,IAAI,CAAC,WAAW,WAAW,uBAAuB,IAAI,CAAC,GAAG,OAAO;CACjE,OAAO;AACR;AACA,SAAS,uBAAuB,MAAM,aAAa,UAAU;CAC5D,MAAM,UAAU,oBAAoB,MAAM,WAAW;CACrD,IAAI,UAAU,OAAO,kBAAkB,QAAQ,8BAA8B,oBAAoB,MAAM,QAAQ,EAAE;CACjH,OAAO,kBAAkB,QAAQ;AAClC;;AAEA,SAAS,2BAA2B,SAAS;CAC5C,MAAM,OAAO,uBAAuB,QAAQ,IAAI;CAChD,MAAM,eAAe,IAAI,IAAI,QAAQ,aAAa,KAAK,aAAa,uBAAuB,QAAQ,CAAC,CAAC;CACrG,SAAS,iBAAiB,UAAU,UAAU;EAC7C,MAAM,aAAa,uBAAuB,QAAQ;EAClD,IAAI,CAAC,aAAa,IAAI,UAAU,GAAG;EACnC,MAAM,IAAI,MAAM,uBAAuB,MAAM,YAAY,QAAQ,CAAC;CACnE;CACA,OAAO;EACN,MAAM;EACN,MAAM,UAAU,QAAQ,UAAU,gBAAgB;GACjD,IAAI,gBAAgB,WAAW,CAAC,UAAU,OAAO;GACjD,MAAM,WAAW,MAAM,KAAK,QAAQ,QAAQ,UAAU;IACrD,GAAG;IACH,UAAU;GACX,CAAC;GACD,IAAI,CAAC,UAAU,OAAO;GACtB,iBAAiB,OAAO,aAAa,WAAW,WAAW,SAAS,IAAI,QAAQ;GAChF,OAAO;EACR;EACA,KAAK,IAAI;GACR,MAAM,aAAa,kBAAkB,IAAI,IAAI;GAC7C,IAAI,CAAC,YAAY,OAAO;GACxB,iBAAiB,UAAU;GAC3B,OAAO;EACR;CACD;AACD;AAGA,MAAM,eAAe,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;AACD,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,SAAS,cAAc,MAAM;CAC5B,OAAO,iBAAiB,KAAK,IAAI,KAAK,iBAAiB,KAAK,IAAI;AACjE;AACA,SAASA,UAAQ,MAAM;CACtB,OAAO,KAAK,MAAM,GAAG,EAAE,KAAK,GAAG;AAChC;AACA,SAAS,iBAAiB,QAAQ;CACjC,MAAM,eAAe,KAAK,IAAI,OAAO,QAAQ,GAAG;CAChD,KAAK,IAAI,QAAQ,GAAG,QAAQ,cAAc,SAAS,GAAG,IAAI,OAAO,WAAW,GAAG,OAAO;CACtF,OAAO;AACR;AACA,SAAS,mBAAmB,MAAM,SAAS,UAAU;CACpD,MAAM,eAAeA,UAAQ,SAAS,MAAM,QAAQ,CAAC;CACrD,MAAM,eAAe,GAAGA,UAAQ,SAAS,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,EAAE;CACzE,MAAM,kBAAkB,GAAGA,UAAQ,SAAS,MAAM,KAAK,SAAS,WAAW,CAAC,CAAC,EAAE;CAC/E,MAAM,iBAAiB,GAAGA,UAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,CAAC,CAAC,EAAE;CAC7E,IAAI,aAAa,WAAW,YAAY,KAAK,cAAc,KAAK,YAAY,KAAK,CAAC,4BAA4B,KAAK,YAAY,GAAG;EACjI,MAAM,KAAK,gBAAgB,KAAK,SAAS,QAAQ,GAAG,UAAU,EAAE,aAAa,QAAQ,CAAC;EACtF,OAAO,KAAK;GACX,UAAU,UAAU;GACpB,WAAW;EACZ,IAAI;CACL;CACA,IAAI,aAAa,WAAW,eAAe,KAAK,cAAc,KAAK,YAAY,KAAK,CAAC,4BAA4B,KAAK,YAAY,GAAG;EACpI,MAAM,KAAK,gBAAgB,KAAK,SAAS,WAAW,GAAG,UAAU,EAAE,aAAa,WAAW,CAAC;EAC5F,OAAO,KAAK;GACX,UAAU,aAAa;GACvB,WAAW;EACZ,IAAI;CACL;CACA,IAAI,aAAa,WAAW,cAAc,KAAK,cAAc,KAAK,YAAY,KAAK,CAAC,4BAA4B,KAAK,YAAY,GAAG;EACnI,MAAM,KAAK,gBAAgB,KAAK,SAAS,UAAU,GAAG,UAAU,EAAE,aAAa,UAAU,CAAC;EAC1F,OAAO,KAAK;GACX,UAAU,YAAY;GACtB,WAAW;EACZ,IAAI;CACL;CACA,OAAO;AACR;AACA,SAAS,wBAAwB,UAAU,OAAO;CACjD,OAAO,8BAA8B,6BAA6B,QAAQ,GAAG,KAAK;AACnF;AACA,SAAS,oBAAoB,SAAS,UAAU;CAC/C,MAAM,eAAeA,UAAQ,SAAS,SAAS,QAAQ,CAAC;CACxD,IAAI,aAAa,WAAW,IAAI,GAAG,OAAO;CAC1C,OAAO,cAAc,KAAK,YAAY;AACvC;AACA,SAAS,SAAS,MAAM,KAAK,SAAS,OAAO,gBAAgB,aAAa,cAAc,cAAc,QAAQ;CAC7G,KAAK,MAAM,QAAQ,YAAY,GAAG,EAAE,KAAK,GAAG;EAC3C,IAAI,mBAAmB,YAAY,UAAU,OAAO,OAAO,SAAS,UAAU;EAC9E,MAAM,WAAW,KAAK,KAAK,IAAI;EAC/B,MAAM,QAAQ,SAAS,QAAQ;EAC/B,IAAI,MAAM,YAAY,GAAG;GACxB,IAAI,aAAa,IAAI,IAAI,GAAG;GAC5B,SAAS,MAAM,UAAU,SAAS,OAAO,gBAAgB,aAAa,cAAc,cAAc,MAAM;GACxG;EACD;EACA,IAAI,CAAC,MAAM,OAAO,GAAG;EACrB,MAAM,aAAa,oBAAoB,SAAS,QAAQ;EACxD,MAAM,cAAc,aAAa,wBAAwB,UAAU,KAAK,IAAI;EAC5E,IAAI,cAAc,aAAa,aAAa,KAAK,uBAAuB,QAAQ,CAAC;EACjF,MAAM,aAAa,mBAAmB,MAAM,SAAS,QAAQ;EAC7D,IAAI,cAAc,CAAC,aAAa,aAAa,WAAW,YAAY,WAAW;EAC/E,IAAI,CAAC,gBAAgB;EACrB,IAAI,MAAM,OAAO,UAAU,cAAc,IAAI,GAAG;EAChD,MAAM,SAAS,aAAa,QAAQ;EACpC,IAAI,iBAAiB,MAAM,GAAG;EAC9B,OAAO,SAAS,OAAO;EACvB,YAAY,KAAK;GAChB,MAAMA,UAAQ,SAAS,MAAM,QAAQ,CAAC;GACtC,UAAU,OAAO,SAAS,MAAM;GAChC,MAAM,WAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK;EACvD,CAAC;CACF;AACD;;;;;AAKA,SAAS,YAAY,MAAM,kBAAkB,OAAO,cAAc;CACjE,MAAM,SAAS,OAAO,oBAAoB,WAAW,kBAAkB,gBAAgB,UAAU;CACjG,MAAM,UAAU,OAAO,oBAAoB,WAAW,gBAAgB,CAAC,IAAI;CAC3E,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,MAAM,QAAQ,QAAQ,SAAS;CAC/B,MAAM,cAAc,CAAC;CACrB,MAAM,eAAe,CAAC;CACtB,MAAM,eAAe,CAAC;CACtB,SAAS,MAAM,MAAM,KAAK,MAAM,MAAM,GAAG,OAAO,gBAAgB,aAAa,cAAc,cAAc,EAAE,OAAO,EAAE,CAAC;CACrH,OAAO;EACN;EACA;EACA;CACD;AACD;;;;ACtKA,MAAa,sBAAsB;CAAC;CAAM;CAAkB;AAAiB;;;;;;;AAQ7E,MAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,+BAA+B,IAAI,OAC9C,yBAAyB,6BAA6B,KAAK,GAAG,EAAE,YAClE;AAEA,SAAS,qBAAqB,MAAM;CAClC,IAAI,CAAC,KAAK,WAAW,eAAe,GAClC,OAAO;CAGT,OAAO,6BAA6B,SAAS,KAAK,MAAM,EAAsB,CAAC;AACjF;;AAGA,MAAa,wBAAwB;CAAC;CAAe;CAAmB;AAAgB;;AAiBxF,MAAa,8BAA8B,CACzC,GAAG;CAdH,GAAG;CACH;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAKG,GACH,GAAG,qBACL;;AAGA,MAAa,qCAAqC,CAChD,yBACA,wBACF;AASA,SAAgB,mBAAmB,IAAI;CACrC,OAAO,oBAAoB,MAAM,QAAQ,OAAO,OAAO,GAAG,WAAW,GAAG,IAAI,EAAE,CAAC;AACjF;AAEA,SAAS,YAAY,IAAI;CACvB,IAAI,GAAG,WAAW,GAAG,GAAG;EACtB,MAAM,CAAC,OAAO,QAAQ,GAAG,MAAM,GAAG;EAClC,OAAO,OAAO,GAAG,MAAM,GAAG,SAAS;CACrC;CAEA,OAAO,GAAG,MAAM,GAAG,EAAE,MAAM;AAC7B;AAEA,SAAS,kBAAkB,IAAI;CAC7B,MAAM,OAAO,YAAY,EAAE;CAC3B,IAAI,mBAAmB,IAAI,GACzB,OAAO;CAGT,IAAI,KAAK,WAAW,eAAe,GACjC,OAAO,CAAC,qBAAqB,IAAI;CAGnC,IAAI,SAAS,iBAAiB,KAAK,WAAW,eAAe,GAC3D,OAAO;CAGT,OAAO;AACT;;AAGA,SAAgB,yBAAyB;CACvC,OAAO;EACL,eAAe,QAAQ;EACvB,aAAa;GAAC,GAAG;GAAqB;GAAmB,GAAG;EAAqB;EACjF,YAAY;CACd;AACF;;AAGA,SAAgB,yBAAyB;CACvC,OAAO;EACL,eAAe,IAAI,cAAc;GAC/B,IAAI,GAAG,WAAW,GAAG,KAAK,GAAG,WAAW,GAAG,KAAK,UAAU,EAAE,GAC1D,OAAO;GAGT,OAAO,kBAAkB,EAAE,IAAI,OAAO;EACxC;EACA,aAAa;GAAC,GAAG;GAAqB;GAA8B,GAAG;EAAqB;EAC5F,YAAY;CACd;AACF;;;;;;AAOA,SAAgB,yBAAyB;CACvC,OAAO;EACL,cAAc,CAAC,iBAAiB;EAChC,aAAa,CAAC,GAAG,2BAA2B;EAC5C,YAAY;CACd;AACF;AAG+C,CAC7C,GAAG,kCAEL;;;ACjIA,MAAa,mBAAmB;CAC9B,QAAQ,CAAC,OAAO,KAAK;CACrB,KAAK;CACL,OAAO;CACP,WAAW;CACX,QAAQ;CACR,MAAM,uBAAuB;AAC/B;AASQ,uBAAuB;;;AClB/B,SAAS,YAAY,aAAa,OAAO,MAAM;CAC9C,MAAM,SAAS,QAAQ,KAAK,aAAa,OAAO,IAAI,IAAI,KAAK,aAAa,IAAI;CAC9E,IAAI,WAAW,KAAK,QAAQ,cAAc,CAAC,GAAG,OAAO;CACrD,MAAM,UAAU,KAAK,aAAa,OAAO;CACzC,IAAI,CAAC,WAAW,OAAO,GAAG,OAAO;CACjC,KAAK,MAAM,SAAS,YAAY,OAAO,GAAG;EACzC,MAAM,YAAY,QAAQ,KAAK,SAAS,OAAO,gBAAgB,OAAO,IAAI,IAAI,KAAK,SAAS,OAAO,gBAAgB,IAAI;EACvH,IAAI,WAAW,KAAK,WAAW,cAAc,CAAC,GAAG,OAAO;CACzD;CACA,OAAO;AACR;;AAEA,SAAS,4BAA4B,oBAAoB,cAAc;CACtE,MAAM,UAAU,YAAY,oBAAoB,gBAAgB,OAAO;CACvE,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,iDAAiD;CAC/E,MAAM,WAAW,KAAK,SAAS,YAAY;CAC3C,IAAI,CAAC,WAAW,QAAQ,GAAG,MAAM,IAAI,MAAM,yCAAyC,cAAc;CAClG,OAAO;AACR;;AA+BA,SAAS,mBAAmB,QAAQ,cAAc;CACjD,IAAI,OAAO,WAAW,GAAG,MAAM,IAAI,MAAM,yCAAyC;CAClF,MAAM,UAAU,CAAC;CACjB,KAAK,MAAM,OAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,GAAG;EACvC,MAAM,YAAY,aAAa;EAC/B,IAAI,CAAC,WAAW,MAAM,IAAI,MAAM,wBAAwB,IAAI,+DAA+D;EAC3H,QAAQ,OAAO;CAChB;CACA,OAAO;AACR;AAGA,SAAS,QAAQ,MAAM;CACtB,OAAO,KAAK,QAAQ,OAAO,GAAG;AAC/B;AACA,SAAS,iBAAiB,UAAU;CACnC,OAAO,GAAG,SAAS;AACpB;AACA,eAAe,iBAAiB,MAAM,UAAU,WAAW,cAAc;CACxE,UAAU,KAAK,MAAM,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;CACvD,MAAM,cAAc,YAAY,KAAK,MAAM,cAAc,eAAe,CAAC;CACzE,MAAM,SAAS,KAAK,aAAa,MAAM;CACvC,MAAM,eAAe,iBAAiB,QAAQ;CAC9C,MAAM,MAAM,YAAY,kBAAkB;EACzC,OAAO,GAAG,WAAW,UAAU;EAC/B,QAAQ,CAAC,KAAK;EACd;EACA,OAAO;EACP,KAAK;EACL,QAAQ,EAAE,OAAO,OAAO;EACxB,MAAM,uBAAuB;EAC7B,SAAS,CAAC,2BAA2B;GACpC;GACA;EACD,CAAC,CAAC;CACH,CAAC,CAAC;CACF,OAAO;EACN;EACA;CACD;AACD;AACA,eAAe,8BAA8B,MAAM,WAAW,cAAc,UAAU,WAAW;CAChG,MAAM,aAAa,QAAQ,SAAS,MAAM,SAAS,CAAC;CACpD,MAAM,WAAW,KAAK,MAAM,QAAQ,YAAY;CAChD,MAAM,cAAc,GAAG,SAAS;CAChC,MAAM,eAAe,WAAW,QAAQ,IAAI,aAAa,QAAQ,IAAI,KAAK;CAC1E,MAAM,SAAS,WAAW,WAAW;CACrC,MAAM,cAAc,SAAS,aAAa,WAAW,IAAI,KAAK;CAC9D,UAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;CAChD,cAAc,UAAU,QAAQ;CAChC,IAAI,WAAW,cAAc,aAAa,SAAS;CACnD,IAAI;EACH,QAAQ,MAAM,mCAAmC,MAAM,EAAE,eAAe,KAAK,CAAC,GAAG,QAAQ,QAAQ,UAAU,gBAAgB,SAAS,MAAM,eAAe,UAAU;CACpK,UAAU;EACT,IAAI,cAAc,cAAc,UAAU,YAAY;OACjD,OAAO,UAAU,EAAE,OAAO,KAAK,CAAC;EACrC,IAAI,aAAa,cAAc,aAAa,WAAW;OAClD,IAAI,aAAa,QAAQ,OAAO,aAAa,EAAE,OAAO,KAAK,CAAC;CAClE;AACD;;AAEA,eAAe,iBAAiB,SAAS;CACxC,MAAM,OAAO,QAAQ,QAAQ,QAAQ,IAAI;CACzC,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,QAAQ,QAAQ,SAAS;CAC/B,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,MAAM,WAAW,QAAQ,IAAI;CAC7B,MAAM,SAAS,YAAY,MAAM;EAChC;EACA;EACA;CACD,CAAC;CACD,MAAM,UAAU,mBAAmB,QAAQ,QAAQ,OAAO,YAAY;CACtE,MAAM,QAAQ,CAAC;CACf,MAAM,kBAAkB,CAAC;CACzB,IAAI;EACH,QAAQ,MAAM,IAAI;EAClB,KAAK,MAAM,CAAC,UAAU,cAAc,OAAO,QAAQ,OAAO,GAAG;GAC5D,MAAM,EAAE,aAAa,iBAAiB,MAAM,iBAAiB,MAAM,UAAU,WAAW,OAAO,YAAY;GAC3G,IAAI;IACH,MAAM,YAAY,KAAK,aAAa,QAAQ,YAAY;IACxD,MAAM,UAAU,GAAG,UAAU;IAC7B,MAAM,WAAW,aAAa,SAAS;IACvC,MAAM,YAAY,WAAW,OAAO,IAAI,aAAa,OAAO,IAAI,KAAK;IACrE,MAAM,KAAK;KACV;KACA;KACA;KACA;IACD,CAAC;IACD,gBAAgB,KAAK,GAAG,MAAM,8BAA8B,MAAM,WAAW,cAAc,UAAU,SAAS,CAAC;GAChH,UAAU;IACT,OAAO,aAAa;KACnB,WAAW;KACX,OAAO;IACR,CAAC;GACF;EACD;CACD,UAAU;EACT,QAAQ,MAAM,QAAQ;CACvB;CACA,OAAO;EACN;EACA;EACA,aAAa,OAAO;CACrB;AACD;AAGA,MAAM,gBAAgB;AACtB,MAAM,iBAAiB,KAAK,cAAc;AAC1C,SAAS,kBAAkB,UAAU;CACpC,OAAO,kBAAkB,KAAK,UAAU,QAAQ,EAAE;AACnD;;AAEA,SAAS,kBAAkB,SAAS;CACnC,MAAM,SAAS,QAAQ,UAAU;CACjC,IAAI,WAAW;CACf,OAAO;EACN,MAAM;EACN,aAAa;GACZ,WAAW,cAAc,QAAQ,MAAM,MAAM;EAC9C;EACA,UAAU,QAAQ;GACjB,IAAI,WAAW,eAAe,OAAO;GACrC,OAAO,GAAG,eAAe;EAC1B;EACA,KAAK,IAAI;GACR,IAAI,OAAO,GAAG,eAAe,aAAa,CAAC,UAAU,OAAO;GAC5D,OAAO,kBAAkB,QAAQ;EAClC;EACA,WAAW;GACV,IAAI,CAAC,UAAU;GACf,MAAM,SAAS,KAAK,QAAQ,MAAM,QAAQ,UAAU,QAAQ,YAAY;GACxE,UAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;GACrC,cAAc,KAAK,QAAQ,YAAY,GAAG,kBAAkB,QAAQ,CAAC;EACtE;CACD;AACD;;AAEA,SAAS,qBAAqB,UAAU,CAAC,GAAG,QAAQ;CACnD,MAAM,OAAO,QAAQ,QAAQ,QAAQ,IAAI;CACzC,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,cAAc,WAAW,KAAK,MAAM,qBAAqB,CAAC,IAAI,KAAK,MAAM,qBAAqB,IAAI,KAAK;CAC7G,MAAM,eAAe,UAAU,YAAY,MAAM;EAChD;EACA,OAAO,QAAQ;CAChB,CAAC;CACD,MAAM,aAAa,aAAa;CAChC,MAAM,eAAe,aAAa;CAClC,MAAM,UAAU;EACf,GAAG,cAAc,EAAE,QAAQ,YAAY,IAAI,CAAC;EAC5C,GAAG;CACJ;CACA,IAAI,OAAO,KAAK,OAAO,EAAE,WAAW,GAAG,MAAM,IAAI,MAAM,kEAAkE;CACzH,OAAO,YAAY,kBAAkB;EACpC,OAAO;EACP,QAAQ,CAAC,KAAK;EACd,QAAQ,KAAK,MAAM,MAAM;EACzB,OAAO,QAAQ,SAAS;EACxB,KAAK;EACL,QAAQ,EAAE,OAAO,OAAO;EACxB,MAAM,uBAAuB;EAC7B,SAAS,CAAC,2BAA2B;GACpC;GACA;EACD,CAAC,GAAG,kBAAkB;GACrB;GACA;GACA;EACD,CAAC,CAAC;CACH,CAAC;AACF;;AAEA,eAAe,SAAS,UAAU,CAAC,GAAG;CACrC,MAAM,OAAO,QAAQ,QAAQ,QAAQ,IAAI;CACzC,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,MAAM,QAAQ,QAAQ,SAAS;CAC/B,MAAM,WAAW,QAAQ,IAAI;CAC7B,MAAM,SAAS,YAAY,MAAM;EAChC;EACA;EACA;CACD,CAAC;CACD,IAAI;EACH,QAAQ,MAAM,IAAI;EAClB,MAAM,MAAM,qBAAqB;GAChC,GAAG;GACH;EACD,GAAG;GACF,cAAc,OAAO;GACrB,cAAc,OAAO;EACtB,CAAC,CAAC;EACF,IAAI,cAAc;GACjB,MAAM,EAAE,sCAAsC,MAAM,OAAO;GAC3D,MAAM,kCAAkC,IAAI;EAC7C;CACD,UAAU;EACT,QAAQ,MAAM,QAAQ;CACvB;CACA,OAAO,EAAE,aAAa,OAAO,YAAY;AAC1C;;;;;;;AAOA,eAAe,SAAS,UAAU,CAAC,GAAG;CACrC,MAAM,EAAE,gBAAgB,MAAM,OAAO;CACrC,MAAM,aAAa,iBAAiB,SAAS;EAC5C,GAAG;EACH,cAAc;EACd,gBAAgB;CACjB,CAAC,GAAG,OAAO;AACZ"}
|