@keystrokehq/cli 0.1.24 → 0.1.26

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.
Files changed (31) hide show
  1. package/dist/index.mjs +216 -153
  2. package/dist/index.mjs.map +1 -1
  3. package/dist/{maybe-auto-update-q5MthdI8.mjs → maybe-auto-update-BDvSKDZp.mjs} +2 -2
  4. package/dist/{maybe-auto-update-q5MthdI8.mjs.map → maybe-auto-update-BDvSKDZp.mjs.map} +1 -1
  5. package/dist/skills-bundle/_AGENTS.md +1 -1
  6. package/dist/templates/hello-world/README.md +3 -2
  7. package/dist/{version-DcR3O1UD.mjs → version-pY9N8XlL.mjs} +1 -2
  8. package/dist/version-pY9N8XlL.mjs.map +1 -0
  9. package/package.json +1 -1
  10. package/dist/skills-bundle/skills/keystroke-actions/SKILL.md +0 -160
  11. package/dist/skills-bundle/skills/keystroke-actions/references/catalog-and-imports.md +0 -71
  12. package/dist/skills-bundle/skills/keystroke-agents/SKILL.md +0 -115
  13. package/dist/skills-bundle/skills/keystroke-agents/references/models.md +0 -23
  14. package/dist/skills-bundle/skills/keystroke-agents/references/tools-mcp-codemode.md +0 -85
  15. package/dist/skills-bundle/skills/keystroke-agents/references/workflows-and-testing.md +0 -26
  16. package/dist/skills-bundle/skills/keystroke-apps/SKILL.md +0 -151
  17. package/dist/skills-bundle/skills/keystroke-apps/references/cli-and-catalog.md +0 -104
  18. package/dist/skills-bundle/skills/keystroke-channels/SKILL.md +0 -66
  19. package/dist/skills-bundle/skills/keystroke-channels/references/slack-setup.md +0 -41
  20. package/dist/skills-bundle/skills/keystroke-cli/SKILL.md +0 -93
  21. package/dist/skills-bundle/skills/keystroke-deploy/SKILL.md +0 -93
  22. package/dist/skills-bundle/skills/keystroke-deploy/references/build-and-full-deploy.md +0 -30
  23. package/dist/skills-bundle/skills/keystroke-deploy/references/filtered-deploy.md +0 -50
  24. package/dist/skills-bundle/skills/keystroke-deploy/references/wip-ignore.md +0 -35
  25. package/dist/skills-bundle/skills/keystroke-files/SKILL.md +0 -43
  26. package/dist/skills-bundle/skills/keystroke-skills/SKILL.md +0 -42
  27. package/dist/skills-bundle/skills/keystroke-triggers/SKILL.md +0 -143
  28. package/dist/skills-bundle/skills/keystroke-workflows/SKILL.md +0 -78
  29. package/dist/skills-bundle/skills/keystroke-workflows/references/authoring.md +0 -168
  30. package/dist/skills-bundle/skills/keystroke-workflows/references/testing.md +0 -138
  31. package/dist/version-DcR3O1UD.mjs.map +0 -1
@@ -1,138 +0,0 @@
1
- # Testing & debugging workflows
2
-
3
- ## Unit tests (in-process, no server)
4
-
5
- Test through `executeWorkflow` from `@keystrokehq/keystroke/workflow` — it parses input/output and wires up the action/sub-workflow runners. **Never call `workflow.run(...)` directly at the top level of a test**: outside a run it has no durable context (`workflow.run(input)` returns an unresolvable step; `workflow.run(input, ctx)` skips the checkpoint boundary). Inside another workflow body, `await otherWorkflow.run(input)` *is* the correct first-class sub-workflow step.
6
-
7
- `executeWorkflow` runs the workflow via the durable replay engine and resolves to a `ReplayResult`: `{ status: "completed", output }`, `{ status: "failed", error }`, `{ status: "suspended", items }` (when the body hits `ctx.sleep`/`ctx.hook`), or `{ status: "canceled" }`. Assert on `status` and read `output`.
8
-
9
- `keystroke init` scaffolds Vitest and a starter test (e.g. `src/workflows/greeting.test.ts`):
10
-
11
- ```ts
12
- import { describe, expect, it } from "vitest";
13
- import { executeWorkflow } from "@keystrokehq/keystroke/workflow";
14
- import greeting from "./greeting";
15
-
16
- describe("greeting workflow", () => {
17
- it("returns a greeting for a name", async () => {
18
- const result = await executeWorkflow(greeting, { name: "Ada" });
19
- expect(result).toEqual({ status: "completed", output: { greeting: "Hello, Ada!" } });
20
- });
21
- });
22
- ```
23
-
24
- Use `pnpm test:unit` for `src/**/*.test.ts`. Integration tests (`*.int.test.ts`) load `.env` and skip when required keys are unset (`pnpm test:int`).
25
-
26
- For multi-step workflows:
27
-
28
- ```ts
29
- import { describe, expect, it } from "vitest";
30
- import { executeWorkflow } from "@keystrokehq/keystroke/workflow";
31
- import workflow from "../signup-pipeline";
32
-
33
- it("runs the pipeline", async () => {
34
- const result = await executeWorkflow(workflow, {
35
- name: "Ada",
36
- email: "ada@acme.com",
37
- company: "Acme",
38
- });
39
-
40
- expect(result.status).toBe("completed");
41
- if (result.status === "completed") {
42
- expect(result.output).toMatchObject({ channel: "#pipeline" });
43
- }
44
- });
45
- ```
46
-
47
- Deterministic actions (pure logic, no network/LLM) need no mocks — run the workflow and assert.
48
-
49
- ## Stub expensive actions by seeding the event log
50
-
51
- Steps are checkpointed in the durable event log as `step_completed` events keyed by a stable **correlation id**. Before running a step the action runner checks the log for that correlation id; pre-seed a `step_completed` event to skip real work (LLM/agent/HTTP calls) and feed a fixture:
52
-
53
- ```ts
54
- import { executeWorkflow, MemoryEventLog } from "@keystrokehq/keystroke/workflow";
55
- import workflow from "../signup-pipeline";
56
-
57
- it("drafts without calling the agent", async () => {
58
- const eventLog = new MemoryEventLog();
59
- const runId = "test-run";
60
-
61
- // correlation id = `step:<actionKey>#<occurrence>` (occurrence starts at 0),
62
- // or `step:<stepId>` if the step used `.stepId("...")`.
63
- await eventLog.append({
64
- runId,
65
- type: "step_completed",
66
- correlationId: "step:research-signup#0",
67
- data: { brief: "stubbed brief" }, // the action output goes in `data` directly
68
- });
69
-
70
- const result = await executeWorkflow(
71
- workflow,
72
- { name: "Ada", email: "ada@acme.com", company: "Acme" },
73
- { runId, eventLog },
74
- );
75
-
76
- expect(result.status).toBe("completed");
77
- if (result.status === "completed") {
78
- expect(result.output).toMatchObject({ brief: "stubbed brief" });
79
- }
80
- });
81
- ```
82
-
83
- Rules:
84
-
85
- - Pass a fixed `runId` and the same `MemoryEventLog` to `executeWorkflow`.
86
- - The correlation id is `step:<slug>#<occurrence>` — `#0` for the first call to that action/agent, `#1` for the second, and so on — unless an explicit step id was set (`action.stepId("x")` or `agent.prompt(input, { stepId: "x" })`), in which case it is `step:x`.
87
- - The action **output** is stored as the event `data` directly (no wrapper). It is re-validated against the action's output schema, so it must be schema-valid.
88
-
89
- This is the preferred mock: schema-checked, no module-mock hoisting, and it still exercises the real `run` orchestration (branching, loops, output shape) — only the action bodies are stubbed.
90
-
91
- ## Mock the integration instead (alternative)
92
-
93
- When you'd rather stub the underlying dependency (e.g. the agent inside an action) or assert how it was called, use `vi.mock`:
94
-
95
- `agent.prompt()` resolves to a `PromptResponse` — `{ sessionId, messages, error, canceled?, output? }` (`output` is the parsed result when the prompt was called with an `outputSchema`), **not** a bare messages array. Mock that shape:
96
-
97
- ```ts
98
- import { vi } from "vitest";
99
-
100
- vi.mock("../agents/support", () => ({
101
- default: {
102
- prompt: vi.fn().mockResolvedValue({
103
- sessionId: "test-session",
104
- messages: [{ role: "assistant", content: "mocked" }],
105
- error: null,
106
- }),
107
- },
108
- }));
109
- ```
110
-
111
- ## Assert the input/output contract
112
-
113
- Validation happens at the `executeWorkflow` boundary, so contract tests are free:
114
-
115
- ```ts
116
- await expect(executeWorkflow(workflow, { email: "x" } as never)).rejects.toThrow();
117
- ```
118
-
119
- ## Debug runs from the CLI
120
-
121
- ```bash
122
- keystroke workflow run signup-pipeline --input '{"name":"Ada","email":"ada@acme.com","company":"Acme"}'
123
- keystroke workflow runs list signup-pipeline
124
- keystroke workflow runs get signup-pipeline <run-id> --include steps,trace
125
- ```
126
-
127
- `steps` shows which actions ran and failed. `trace` links nested agent calls.
128
-
129
- ### Trigger-fired runs
130
-
131
- When a cron/webhook/poll fired the workflow:
132
-
133
- ```bash
134
- keystroke trigger runs list signup:signup-pipeline
135
- keystroke trigger runs get signup:signup-pipeline <run-id> --include workflows,trace
136
- ```
137
-
138
- While developing triggers, prefer `keystroke workflow run` until the workflow logic is solid.
@@ -1 +0,0 @@
1
- {"version":3,"file":"version-DcR3O1UD.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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"}