@keystrokehq/cli 0.1.4 → 0.1.6
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-CWgqwAeq.mjs +19268 -0
- package/dist/dist-CWgqwAeq.mjs.map +1 -0
- package/dist/dist-DohqaxIM.mjs +3 -0
- package/dist/{dist-C47GdlWY.mjs → dist-H53GUsol.mjs} +1019 -183
- package/dist/dist-H53GUsol.mjs.map +1 -0
- package/dist/{dist-CJL2zYbP.mjs → dist-jchdNGBU.mjs} +62 -5
- package/dist/dist-jchdNGBU.mjs.map +1 -0
- package/dist/index.mjs +973 -377
- package/dist/index.mjs.map +1 -1
- package/dist/{maybe-auto-update-B0kal2FM.mjs → maybe-auto-update-ClXO7U-6.mjs} +2 -2
- package/dist/{maybe-auto-update-B0kal2FM.mjs.map → maybe-auto-update-ClXO7U-6.mjs.map} +1 -1
- package/dist/pack-artifact-DVnIKrsg-CETr40a-.mjs +112 -0
- package/dist/pack-artifact-DVnIKrsg-CETr40a-.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-Dxl3y5p6.mjs → version-CiPDVUdk.mjs} +10 -14
- package/dist/version-CiPDVUdk.mjs.map +1 -0
- package/package.json +8 -2
- package/dist/dist-C47GdlWY.mjs.map +0 -1
- package/dist/dist-CJL2zYbP.mjs.map +0 -1
- package/dist/dist-Ch53z2P3.mjs +0 -3
- package/dist/dist-CwR72_PS.mjs +0 -1887
- package/dist/dist-CwR72_PS.mjs.map +0 -1
- 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-Dxl3y5p6.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 { Mn as originFromPublicUrl, at as LOCAL_PLATFORM_ORIGIN } from "./dist-H53GUsol.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-CiPDVUdk.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-CiPDVUdk.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.6",
|
|
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 .",
|