@executioncontrolprotocol/cli 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +47 -3
  2. package/dist/commands/invoke.d.ts +17 -0
  3. package/dist/commands/invoke.d.ts.map +1 -0
  4. package/dist/commands/invoke.js +47 -0
  5. package/dist/commands/invoke.js.map +1 -0
  6. package/dist/commands/serve.d.ts +15 -0
  7. package/dist/commands/serve.d.ts.map +1 -0
  8. package/dist/commands/serve.js +53 -0
  9. package/dist/commands/serve.js.map +1 -0
  10. package/dist/commands/test/rerun.d.ts +16 -0
  11. package/dist/commands/test/rerun.d.ts.map +1 -0
  12. package/dist/commands/test/rerun.js +38 -0
  13. package/dist/commands/test/rerun.js.map +1 -0
  14. package/dist/commands/test/run.d.ts +14 -0
  15. package/dist/commands/test/run.d.ts.map +1 -0
  16. package/dist/commands/test/run.js +36 -0
  17. package/dist/commands/test/run.js.map +1 -0
  18. package/dist/commands/test/start.d.ts +17 -0
  19. package/dist/commands/test/start.d.ts.map +1 -0
  20. package/dist/commands/test/start.js +43 -0
  21. package/dist/commands/test/start.js.map +1 -0
  22. package/dist/commands/test/status.d.ts +12 -0
  23. package/dist/commands/test/status.d.ts.map +1 -0
  24. package/dist/commands/test/status.js +24 -0
  25. package/dist/commands/test/status.js.map +1 -0
  26. package/dist/commands/test.d.ts +9 -0
  27. package/dist/commands/test.d.ts.map +1 -0
  28. package/dist/commands/test.js +32 -0
  29. package/dist/commands/test.js.map +1 -0
  30. package/dist/lib/http/create-serve-handler.d.ts +15 -0
  31. package/dist/lib/http/create-serve-handler.d.ts.map +1 -0
  32. package/dist/lib/http/create-serve-handler.js +34 -0
  33. package/dist/lib/http/create-serve-handler.js.map +1 -0
  34. package/dist/lib/http/create-serve.d.ts +30 -0
  35. package/dist/lib/http/create-serve.d.ts.map +1 -0
  36. package/dist/lib/http/create-serve.js +43 -0
  37. package/dist/lib/http/create-serve.js.map +1 -0
  38. package/dist/lib/http/handle-invoke.d.ts +42 -0
  39. package/dist/lib/http/handle-invoke.d.ts.map +1 -0
  40. package/dist/lib/http/handle-invoke.js +66 -0
  41. package/dist/lib/http/handle-invoke.js.map +1 -0
  42. package/dist/lib/http/read-body.d.ts +7 -0
  43. package/dist/lib/http/read-body.d.ts.map +1 -0
  44. package/dist/lib/http/read-body.js +12 -0
  45. package/dist/lib/http/read-body.js.map +1 -0
  46. package/dist/lib/http/write-json.d.ts +7 -0
  47. package/dist/lib/http/write-json.d.ts.map +1 -0
  48. package/dist/lib/http/write-json.js +11 -0
  49. package/dist/lib/http/write-json.js.map +1 -0
  50. package/dist/lib/test-session-io.d.ts +12 -0
  51. package/dist/lib/test-session-io.d.ts.map +1 -0
  52. package/dist/lib/test-session-io.js +36 -0
  53. package/dist/lib/test-session-io.js.map +1 -0
  54. package/dist/lib/up/handle-request.d.ts.map +1 -1
  55. package/dist/lib/up/handle-request.js +4 -29
  56. package/dist/lib/up/handle-request.js.map +1 -1
  57. package/dist/lib/up/read-body.d.ts +2 -6
  58. package/dist/lib/up/read-body.d.ts.map +1 -1
  59. package/dist/lib/up/read-body.js +2 -11
  60. package/dist/lib/up/read-body.js.map +1 -1
  61. package/package.json +8 -8
package/README.md CHANGED
@@ -9,6 +9,9 @@ This CLI is how you run ECP deterministically in a Node.js / TypeScript ecosyste
9
9
  - Validate workflows against an environment’s registered capabilities
10
10
  - Describe/search environment capabilities for agent/UI discovery
11
11
  - Run workflows and print structured run results
12
+ - Invoke a single capability outside a workflow (`ecp invoke`)
13
+ - Serve an environment over loopback HTTP for `POST /v1/invoke` (`ecp serve`)
14
+ - Test workflows with a persistent session (`ecp test start|run|rerun|status`)
12
15
  - Encode/decode workflows using format extensions (TOON, Fluent, JSON)
13
16
 
14
17
  For the architecture and monorepo package boundaries, start with
@@ -74,9 +77,50 @@ ecp describe --env examples/01-echo/environment.ts
74
77
  ecp search "echo" --env examples/01-echo/environment.ts
75
78
  ```
76
79
 
80
+ ### Test session (`ecp test`)
81
+
82
+ Drive a workflow incrementally with frozen state (distinct from `@executioncontrolprotocol/core/testing` stubs):
83
+
84
+ ```sh
85
+ ecp test start workflow.ts --env environment.ts -o session.json
86
+ ecp test run --to step-b --env environment.ts --session session.json
87
+ ecp test rerun step-a --env environment.ts --session session.json
88
+ ecp test status --session session.json
89
+ ```
90
+
91
+ - `run --to <step-id>` is **inclusive** (runs through that step, then pauses).
92
+ - `rerun <step-id>` re-executes one step and **clears** downstream history and `.as` state keys.
93
+ - Session file schema: `@executioncontrolprotocol.test.session`.
94
+
95
+ Fluent API: `ecp.test(workflow).with({ input }).start()` then `session.runTo(id)` / `session.rerun(id)`.
96
+
97
+ ### Invoke a capability
98
+
99
+ Call a single bound capability without a workflow:
100
+
101
+ ```sh
102
+ ecp invoke @executioncontrolprotocol/test.echo --env examples/01-echo/environment.ts --input input.json
103
+ ```
104
+
105
+ Optional `--uses <provider-capability-id>` overrides the harness default provider. Prints an `InvokeResult` JSON document; exits non-zero when `success` is false.
106
+
107
+ ### Serve (`ecp serve`)
108
+
109
+ Expose any `--env` over loopback HTTP (no auth; loopback-only trust):
110
+
111
+ ```sh
112
+ ecp serve --env examples/01-echo/environment.ts
113
+ ecp serve --env environment.ts --port 3090 --cors-origin http://localhost:5173
114
+ ```
115
+
116
+ - `GET /health` — `{ ok, version }`
117
+ - `POST /v1/invoke` — body `{ capability, input?, provider? }` → `ecp.invoke(...).with(...).process()`
118
+
119
+ Default port **3090** (ECP leet), host `127.0.0.1`.
120
+
77
121
  ### Local daemon (`ecp up`)
78
122
 
79
- Start a loopback HTTP daemon that bridges Ollama for the browser demo (CORS + Private Network Access), then open the demo with a pairing token:
123
+ Ollama/PNA **demo bridge** (fixed local env, not arbitrary `--env`). Prefer `ecp serve` for general HTTP invoke. Start the daemon, then open the demo with a pairing token:
80
124
 
81
125
  ```sh
82
126
  ecp up
@@ -87,9 +131,9 @@ ecp up --no-open
87
131
  ```
88
132
 
89
133
  - `GET /health` — `{ ok, version, ollamaReachable }` (no auth; used by the demo to enable Ollama)
90
- - `POST /v1/invoke` — Bearer token required; body `{ capability, input?, provider? }`
134
+ - `POST /v1/invoke` — Bearer token required; same body shape as `ecp serve`
91
135
 
92
- Default port **3090** (ECP leet). The demo reads `?token=` (and optional `?bridge=`) automatically. Hosted HTTPS demos need **Chromium** (Chrome/Edge) for Private Network Access. Add extra page origins with `--cors-origin`.
136
+ Default port **3090**. The demo reads `?token=` (and optional `?bridge=`) automatically. Hosted HTTPS demos need **Chromium** (Chrome/Edge) for Private Network Access. Add extra page origins with `--cors-origin`.
93
137
 
94
138
  ### Encode / decode formats
95
139
 
@@ -0,0 +1,17 @@
1
+ import { EnvModuleCommand } from "../lib/env-module-command.js";
2
+ /** Invoke a single capability outside a workflow run. */
3
+ export default class Invoke extends EnvModuleCommand {
4
+ static summary: string;
5
+ static description: string;
6
+ static examples: string[];
7
+ static args: {
8
+ "capability-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
9
+ };
10
+ static flags: {
11
+ input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ uses: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ env: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=invoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/commands/invoke.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE/D,yDAAyD;AACzD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,gBAAgB;IAClD,MAAM,CAAC,OAAO,SAAwB;IAEtC,MAAM,CAAC,WAAW,SAEmD;IAErE,MAAM,CAAC,QAAQ,WAGd;IAED,MAAM,CAAC,IAAI;;MAKV;IAED,MAAM,CAAC,KAAK;;;;MAQX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAiB3B"}
@@ -0,0 +1,47 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { readJsonFile, runWithCommandError } from "../lib/command-helpers.js";
3
+ import { EnvModuleCommand } from "../lib/env-module-command.js";
4
+ /** Invoke a single capability outside a workflow run. */
5
+ export default class Invoke extends EnvModuleCommand {
6
+ static summary = "Invoke a capability";
7
+ static description = "Call a registered capability by id using the runtime and extensions from --env, " +
8
+ "without running a workflow. Prints an InvokeResult JSON document.";
9
+ static examples = [
10
+ "<%= config.bin %> <%= command.id %> @executioncontrolprotocol/test.echo --env examples/01-echo/environment.ts --input input.json",
11
+ "<%= config.bin %> <%= command.id %> @executioncontrolprotocol/harness-browser-nano.evaluate --env environment.ts --input in.json --uses @executioncontrolprotocol/ollama.generate",
12
+ ];
13
+ static args = {
14
+ "capability-id": Args.string({
15
+ required: true,
16
+ description: "Capability id to invoke (e.g. @executioncontrolprotocol/test.echo)",
17
+ }),
18
+ };
19
+ static flags = {
20
+ ...EnvModuleCommand.flags,
21
+ input: Flags.string({
22
+ description: "Path to JSON file with capability input object",
23
+ }),
24
+ uses: Flags.string({
25
+ description: "Optional provider capability override (harness .uses)",
26
+ }),
27
+ };
28
+ async run() {
29
+ const { args, flags } = await this.parse(Invoke);
30
+ let result;
31
+ await runWithCommandError(this, async () => {
32
+ const input = flags.input
33
+ ? await readJsonFile(flags.input, "--input")
34
+ : {};
35
+ const ecp = await this.loadEcp(flags);
36
+ let builder = ecp.invoke(args["capability-id"]).with(input);
37
+ if (flags.uses)
38
+ builder = builder.uses(flags.uses);
39
+ result = await builder.process();
40
+ this.log(JSON.stringify(result, null, 2));
41
+ });
42
+ if (result !== undefined && !result.success) {
43
+ this.error("Capability invoke did not succeed", { exit: 1 });
44
+ }
45
+ }
46
+ }
47
+ //# sourceMappingURL=invoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../src/commands/invoke.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE/D,yDAAyD;AACzD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,gBAAgB;IAClD,MAAM,CAAC,OAAO,GAAG,qBAAqB,CAAA;IAEtC,MAAM,CAAC,WAAW,GAChB,kFAAkF;QAClF,mEAAmE,CAAA;IAErE,MAAM,CAAC,QAAQ,GAAG;QAChB,kIAAkI;QAClI,mLAAmL;KACpL,CAAA;IAED,MAAM,CAAC,IAAI,GAAG;QACZ,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC;YAC3B,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,oEAAoE;SAClF,CAAC;KACH,CAAA;IAED,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,gBAAgB,CAAC,KAAK;QACzB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YAClB,WAAW,EAAE,gDAAgD;SAC9D,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,WAAW,EAAE,uDAAuD;SACrE,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QAChD,IAAI,MAAgC,CAAA;QACpC,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YACzC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK;gBACvB,CAAC,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;gBAC5C,CAAC,CAAC,EAAE,CAAA;YACN,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACrC,IAAI,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAC3D,IAAI,KAAK,CAAC,IAAI;gBAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAClD,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;YAChC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QACF,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,mCAAmC,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;QAC9D,CAAC;IACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { EnvModuleCommand } from "../lib/env-module-command.js";
2
+ /** Serve an environment over loopback HTTP for capability invoke. */
3
+ export default class Serve extends EnvModuleCommand {
4
+ static summary: string;
5
+ static description: string;
6
+ static examples: string[];
7
+ static flags: {
8
+ port: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
9
+ host: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ "cors-origin": import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
11
+ env: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ };
13
+ run(): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE/D,qEAAqE;AACrE,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,gBAAgB;IACjD,MAAM,CAAC,OAAO,SAAmC;IAEjD,MAAM,CAAC,WAAW,SAGyB;IAE3C,MAAM,CAAC,QAAQ,WAGd;IAED,MAAM,CAAC,KAAK;;;;;MAeX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAuB3B"}
@@ -0,0 +1,53 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { DEFAULT_ECP_UP_HOST, DEFAULT_ECP_UP_PORT } from "../lib/up/constants.js";
3
+ import { startEcpServe } from "../lib/http/create-serve.js";
4
+ import { EnvModuleCommand } from "../lib/env-module-command.js";
5
+ /** Serve an environment over loopback HTTP for capability invoke. */
6
+ export default class Serve extends EnvModuleCommand {
7
+ static summary = "Serve an environment over HTTP";
8
+ static description = "Run a loopback HTTP server that exposes POST /v1/invoke for any capability " +
9
+ "bound in --env. No auth (loopback-only trust model). For the Ollama browser " +
10
+ "demo bridge with pairing, use `ecp up`.";
11
+ static examples = [
12
+ "<%= config.bin %> <%= command.id %> --env examples/01-echo/environment.ts",
13
+ "<%= config.bin %> <%= command.id %> --env environment.ts --port 3090 --cors-origin http://localhost:5173",
14
+ ];
15
+ static flags = {
16
+ ...EnvModuleCommand.flags,
17
+ port: Flags.integer({
18
+ description: "Listen port (ECP leet default 3090)",
19
+ default: DEFAULT_ECP_UP_PORT,
20
+ }),
21
+ host: Flags.string({
22
+ description: "Bind host (loopback only by default)",
23
+ default: DEFAULT_ECP_UP_HOST,
24
+ }),
25
+ "cors-origin": Flags.string({
26
+ description: "Extra allowed CORS origin (repeatable)",
27
+ multiple: true,
28
+ default: [],
29
+ }),
30
+ };
31
+ async run() {
32
+ const { flags } = await this.parse(Serve);
33
+ const ecp = await this.loadEcp(flags);
34
+ const daemon = await startEcpServe({
35
+ ecp,
36
+ port: flags.port,
37
+ host: flags.host,
38
+ corsOrigins: flags["cors-origin"],
39
+ });
40
+ const baseURL = `http://${daemon.host}:${daemon.port}`;
41
+ this.log(`ECP serve on ${baseURL}`);
42
+ this.log("GET /health · POST /v1/invoke (no auth; loopback)");
43
+ this.log("Press Ctrl+C to stop.");
44
+ await new Promise((resolve) => {
45
+ const shutdown = () => {
46
+ void daemon.close().finally(() => resolve());
47
+ };
48
+ process.once("SIGINT", shutdown);
49
+ process.once("SIGTERM", shutdown);
50
+ });
51
+ }
52
+ }
53
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAE/D,qEAAqE;AACrE,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,gBAAgB;IACjD,MAAM,CAAC,OAAO,GAAG,gCAAgC,CAAA;IAEjD,MAAM,CAAC,WAAW,GAChB,6EAA6E;QAC7E,8EAA8E;QAC9E,yCAAyC,CAAA;IAE3C,MAAM,CAAC,QAAQ,GAAG;QAChB,2EAA2E;QAC3E,0GAA0G;KAC3G,CAAA;IAED,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,gBAAgB,CAAC,KAAK;QACzB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;YAClB,WAAW,EAAE,qCAAqC;YAClD,OAAO,EAAE,mBAAmB;SAC7B,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,WAAW,EAAE,sCAAsC;YACnD,OAAO,EAAE,mBAAmB;SAC7B,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;YAC1B,WAAW,EAAE,wCAAwC;YACrD,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,EAAE;SACZ,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACzC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QACrC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,GAAG;YACH,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC;SAClC,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,UAAU,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAA;QACtD,IAAI,CAAC,GAAG,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAA;QACnC,IAAI,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAA;QAC7D,IAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;QAEjC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,MAAM,QAAQ,GAAG,GAAG,EAAE;gBACpB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAA;YAC9C,CAAC,CAAA;YACD,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;YAChC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QACnC,CAAC,CAAC,CAAA;IACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { EnvModuleCommand } from "../../lib/env-module-command.js";
2
+ /** Rerun a single step in a test session. */
3
+ export default class TestRerun extends EnvModuleCommand {
4
+ static summary: string;
5
+ static description: string;
6
+ static examples: string[];
7
+ static args: {
8
+ "step-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
9
+ };
10
+ static flags: {
11
+ session: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ env: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=rerun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rerun.d.ts","sourceRoot":"","sources":["../../../src/commands/test/rerun.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAGlE,6CAA6C;AAC7C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,gBAAgB;IACrD,MAAM,CAAC,OAAO,SAAqC;IAEnD,MAAM,CAAC,WAAW,SAEwD;IAE1E,MAAM,CAAC,QAAQ,WAEd;IAED,MAAM,CAAC,IAAI;;MAKV;IAED,MAAM,CAAC,KAAK;;;MAMX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3B"}
@@ -0,0 +1,38 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { runWithCommandError } from "../../lib/command-helpers.js";
3
+ import { EnvModuleCommand } from "../../lib/env-module-command.js";
4
+ import { readTestSessionFile, writeTestSessionFile } from "../../lib/test-session-io.js";
5
+ /** Rerun a single step in a test session. */
6
+ export default class TestRerun extends EnvModuleCommand {
7
+ static summary = "Rerun one step in a test session";
8
+ static description = "Execute a single step against frozen prior state, replace its committed output, " +
9
+ "and clear downstream history and `.as` state keys. Rewrites --session.";
10
+ static examples = [
11
+ "<%= config.bin %> <%= command.id %> echo --env examples/01-echo/environment.ts --session session.json",
12
+ ];
13
+ static args = {
14
+ "step-id": Args.string({
15
+ required: true,
16
+ description: "Step id to rerun",
17
+ }),
18
+ };
19
+ static flags = {
20
+ ...EnvModuleCommand.flags,
21
+ session: Flags.string({
22
+ required: true,
23
+ description: "Path to test session JSON file",
24
+ }),
25
+ };
26
+ async run() {
27
+ const { args, flags } = await this.parse(TestRerun);
28
+ await runWithCommandError(this, async () => {
29
+ const snap = await readTestSessionFile(flags.session);
30
+ const ecp = await this.loadEcp(flags);
31
+ const session = await ecp.restoreTestSession(snap);
32
+ const next = await session.rerun(args["step-id"]);
33
+ await writeTestSessionFile(flags.session, next);
34
+ this.log(JSON.stringify(next, null, 2));
35
+ });
36
+ }
37
+ }
38
+ //# sourceMappingURL=rerun.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rerun.js","sourceRoot":"","sources":["../../../src/commands/test/rerun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAExF,6CAA6C;AAC7C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,gBAAgB;IACrD,MAAM,CAAC,OAAO,GAAG,kCAAkC,CAAA;IAEnD,MAAM,CAAC,WAAW,GAChB,kFAAkF;QAClF,wEAAwE,CAAA;IAE1E,MAAM,CAAC,QAAQ,GAAG;QAChB,uGAAuG;KACxG,CAAA;IAED,MAAM,CAAC,IAAI,GAAG;QACZ,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC;YACrB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,kBAAkB;SAChC,CAAC;KACH,CAAA;IAED,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,gBAAgB,CAAC,KAAK;QACzB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,gCAAgC;SAC9C,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QACnD,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YACzC,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACrD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACrC,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAA;YAClD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;YACjD,MAAM,oBAAoB,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC/C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QACzC,CAAC,CAAC,CAAA;IACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { EnvModuleCommand } from "../../lib/env-module-command.js";
2
+ /** Inclusive run-to within a test session. */
3
+ export default class TestRun extends EnvModuleCommand {
4
+ static summary: string;
5
+ static description: string;
6
+ static examples: string[];
7
+ static flags: {
8
+ to: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ session: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ env: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/test/run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAGlE,8CAA8C;AAC9C,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,gBAAgB;IACnD,MAAM,CAAC,OAAO,SAAsC;IAEpD,MAAM,CAAC,WAAW,SAE0C;IAE5D,MAAM,CAAC,QAAQ,WAEd;IAED,MAAM,CAAC,KAAK;;;;MAUX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3B"}
@@ -0,0 +1,36 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { runWithCommandError } from "../../lib/command-helpers.js";
3
+ import { EnvModuleCommand } from "../../lib/env-module-command.js";
4
+ import { readTestSessionFile, writeTestSessionFile } from "../../lib/test-session-io.js";
5
+ /** Inclusive run-to within a test session. */
6
+ export default class TestRun extends EnvModuleCommand {
7
+ static summary = "Run a test session through a step";
8
+ static description = "Inclusively execute through --to <step-id>, skipping already-completed prior steps " +
9
+ "and freezing state for later reruns. Rewrites --session.";
10
+ static examples = [
11
+ "<%= config.bin %> <%= command.id %> --to echo --env examples/01-echo/environment.ts --session session.json",
12
+ ];
13
+ static flags = {
14
+ ...EnvModuleCommand.flags,
15
+ to: Flags.string({
16
+ required: true,
17
+ description: "Inclusive step id to run through",
18
+ }),
19
+ session: Flags.string({
20
+ required: true,
21
+ description: "Path to test session JSON file",
22
+ }),
23
+ };
24
+ async run() {
25
+ const { flags } = await this.parse(TestRun);
26
+ await runWithCommandError(this, async () => {
27
+ const snap = await readTestSessionFile(flags.session);
28
+ const ecp = await this.loadEcp(flags);
29
+ const session = await ecp.restoreTestSession(snap);
30
+ const next = await session.runTo(flags.to);
31
+ await writeTestSessionFile(flags.session, next);
32
+ this.log(JSON.stringify(next, null, 2));
33
+ });
34
+ }
35
+ }
36
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/test/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAExF,8CAA8C;AAC9C,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,gBAAgB;IACnD,MAAM,CAAC,OAAO,GAAG,mCAAmC,CAAA;IAEpD,MAAM,CAAC,WAAW,GAChB,qFAAqF;QACrF,0DAA0D,CAAA;IAE5D,MAAM,CAAC,QAAQ,GAAG;QAChB,4GAA4G;KAC7G,CAAA;IAED,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,gBAAgB,CAAC,KAAK;QACzB,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC;YACf,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,kCAAkC;SAChD,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,gCAAgC;SAC9C,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC3C,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YACzC,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACrD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACrC,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAA;YAClD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YAC1C,MAAM,oBAAoB,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC/C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QACzC,CAAC,CAAC,CAAA;IACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { WorkflowEnvCommand } from "../../lib/env-module-command.js";
2
+ /** Create a workflow test session file. */
3
+ export default class TestStart extends WorkflowEnvCommand {
4
+ static summary: string;
5
+ static description: string;
6
+ static examples: string[];
7
+ static args: {
8
+ "workflow-path": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
9
+ };
10
+ static flags: {
11
+ input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ env: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/commands/test/start.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AAEpE,2CAA2C;AAC3C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,kBAAkB;IACvD,MAAM,CAAC,OAAO,SAAkC;IAEhD,MAAM,CAAC,WAAW,SAE4C;IAE9D,MAAM,CAAC,QAAQ,WAEd;IAED,MAAM,CAAC,IAAI;;MAEV;IAED,MAAM,CAAC,KAAK;;;;MAUX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAc3B"}
@@ -0,0 +1,43 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { loadWorkflowFile } from "@executioncontrolprotocol/core/loaders";
3
+ import { readJsonFile, runWithCommandError } from "../../lib/command-helpers.js";
4
+ import { writeTestSessionFile } from "../../lib/test-session-io.js";
5
+ import { WorkflowEnvCommand } from "../../lib/env-module-command.js";
6
+ /** Create a workflow test session file. */
7
+ export default class TestStart extends WorkflowEnvCommand {
8
+ static summary = "Start a workflow test session";
9
+ static description = "Create an idle test session snapshot for a workflow. Use `ecp test run --to` " +
10
+ "and `ecp test rerun` to drive execution with frozen state.";
11
+ static examples = [
12
+ "<%= config.bin %> <%= command.id %> examples/01-echo/workflow.ts --env examples/01-echo/environment.ts -o session.json",
13
+ ];
14
+ static args = {
15
+ ...WorkflowEnvCommand.args,
16
+ };
17
+ static flags = {
18
+ ...WorkflowEnvCommand.flags,
19
+ input: Flags.string({
20
+ description: "Path to JSON file with workflow input object",
21
+ }),
22
+ output: Flags.string({
23
+ char: "o",
24
+ required: true,
25
+ description: "Path to write the test session JSON file",
26
+ }),
27
+ };
28
+ async run() {
29
+ const { args, flags } = await this.parse(TestStart);
30
+ await runWithCommandError(this, async () => {
31
+ const input = flags.input
32
+ ? await readJsonFile(flags.input, "--input")
33
+ : {};
34
+ const ecp = await this.loadEcp(flags);
35
+ const workflow = await loadWorkflowFile(args["workflow-path"]);
36
+ const session = await ecp.test(workflow).with({ input }).start();
37
+ const snap = session.snapshot();
38
+ await writeTestSessionFile(flags.output, snap);
39
+ this.log(JSON.stringify(snap, null, 2));
40
+ });
41
+ }
42
+ }
43
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/commands/test/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AAEpE,2CAA2C;AAC3C,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,kBAAkB;IACvD,MAAM,CAAC,OAAO,GAAG,+BAA+B,CAAA;IAEhD,MAAM,CAAC,WAAW,GAChB,+EAA+E;QAC/E,4DAA4D,CAAA;IAE9D,MAAM,CAAC,QAAQ,GAAG;QAChB,wHAAwH;KACzH,CAAA;IAED,MAAM,CAAC,IAAI,GAAG;QACZ,GAAG,kBAAkB,CAAC,IAAI;KAC3B,CAAA;IAED,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,kBAAkB,CAAC,KAAK;QAC3B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YAClB,WAAW,EAAE,8CAA8C;SAC5D,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,0CAA0C;SACxD,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QACnD,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YACzC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK;gBACvB,CAAC,CAAC,MAAM,YAAY,CAA0B,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC;gBACrE,CAAC,CAAC,EAAE,CAAA;YACN,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACrC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAA;YAC9D,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;YAChE,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAA;YAC/B,MAAM,oBAAoB,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YAC9C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QACzC,CAAC,CAAC,CAAA;IACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Command } from "@oclif/core";
2
+ /** Print test session status. */
3
+ export default class TestStatus extends Command {
4
+ static summary: string;
5
+ static description: string;
6
+ static examples: string[];
7
+ static flags: {
8
+ session: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/test/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAE,MAAM,aAAa,CAAA;AAI5C,iCAAiC;AACjC,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,OAAO;IAC7C,MAAM,CAAC,OAAO,SAA6B;IAE3C,MAAM,CAAC,WAAW,SACwD;IAE1E,MAAM,CAAC,QAAQ,WAAiE;IAEhF,MAAM,CAAC,KAAK;;MAMX;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAO3B"}
@@ -0,0 +1,24 @@
1
+ import { Flags, Command } from "@oclif/core";
2
+ import { runWithCommandError } from "../../lib/command-helpers.js";
3
+ import { readTestSessionFile } from "../../lib/test-session-io.js";
4
+ /** Print test session status. */
5
+ export default class TestStatus extends Command {
6
+ static summary = "Show test session status";
7
+ static description = "Print the test session snapshot (status, cursor, state keys, history).";
8
+ static examples = ["<%= config.bin %> <%= command.id %> --session session.json"];
9
+ static flags = {
10
+ ...Command.baseFlags,
11
+ session: Flags.string({
12
+ required: true,
13
+ description: "Path to test session JSON file",
14
+ }),
15
+ };
16
+ async run() {
17
+ const { flags } = await this.parse(TestStatus);
18
+ await runWithCommandError(this, async () => {
19
+ const snap = await readTestSessionFile(flags.session);
20
+ this.log(JSON.stringify(snap, null, 2));
21
+ });
22
+ }
23
+ }
24
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/test/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAElE,iCAAiC;AACjC,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,OAAO;IAC7C,MAAM,CAAC,OAAO,GAAG,0BAA0B,CAAA;IAE3C,MAAM,CAAC,WAAW,GAChB,wEAAwE,CAAA;IAE1E,MAAM,CAAC,QAAQ,GAAG,CAAC,4DAA4D,CAAC,CAAA;IAEhF,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,OAAO,CAAC,SAAS;QACpB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,gCAAgC;SAC9C,CAAC;KACH,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QAC9C,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YACzC,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACrD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QACzC,CAAC,CAAC,CAAA;IACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Command } from "@oclif/core";
2
+ /** Workflow test sessions (run-to / rerun with frozen state). */
3
+ export default class TestTopic extends Command {
4
+ static summary: string;
5
+ static description: string;
6
+ static examples: string[];
7
+ run(): Promise<void>;
8
+ }
9
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAErC,iEAAiE;AACjE,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;IAC5C,MAAM,CAAC,OAAO,SAA8C;IAE5D,MAAM,CAAC,WAAW,SAM8B;IAEhD,MAAM,CAAC,QAAQ,WAKd;IAEK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAe3B"}
@@ -0,0 +1,32 @@
1
+ import { Command } from "@oclif/core";
2
+ /** Workflow test sessions (run-to / rerun with frozen state). */
3
+ export default class TestTopic extends Command {
4
+ static summary = "Test a workflow with a persistent session";
5
+ static description = `Create and drive a test session that freezes workflow state between operations.
6
+
7
+ Subcommands:
8
+ start Create a session file from a workflow
9
+ run Inclusive run-to via --to <step-id>
10
+ rerun Rerun one step and clear downstream state
11
+ status Print session status / cursor / history`;
12
+ static examples = [
13
+ "<%= config.bin %> test start workflow.ts --env environment.ts -o session.json",
14
+ "<%= config.bin %> test run --to step-b --env environment.ts --session session.json",
15
+ "<%= config.bin %> test rerun step-a --env environment.ts --session session.json",
16
+ "<%= config.bin %> test status --session session.json",
17
+ ];
18
+ async run() {
19
+ await this.parse(TestTopic);
20
+ this.log([
21
+ "Usage: ecp test <subcommand>",
22
+ "",
23
+ " start WORKFLOW-PATH Create a session (-o session.json)",
24
+ " run --to STEP-ID Inclusive run through a step",
25
+ " rerun STEP-ID Rerun one step; clear downstream",
26
+ " status Show session snapshot summary",
27
+ "",
28
+ "Run ecp test <cmd> --help for flags.",
29
+ ].join("\n"));
30
+ }
31
+ }
32
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAErC,iEAAiE;AACjE,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,OAAO;IAC5C,MAAM,CAAC,OAAO,GAAG,2CAA2C,CAAA;IAE5D,MAAM,CAAC,WAAW,GAAG;;;;;;kDAM2B,CAAA;IAEhD,MAAM,CAAC,QAAQ,GAAG;QAChB,+EAA+E;QAC/E,oFAAoF;QACpF,iFAAiF;QACjF,sDAAsD;KACvD,CAAA;IAED,KAAK,CAAC,GAAG;QACP,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAC3B,IAAI,CAAC,GAAG,CACN;YACE,8BAA8B;YAC9B,EAAE;YACF,2DAA2D;YAC3D,qDAAqD;YACrD,yDAAyD;YACzD,sDAAsD;YACtD,EAAE;YACF,sCAAsC;SACvC,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAA;IACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { Ecp } from "@executioncontrolprotocol/core";
3
+ /** Dependencies for {@link createServeRequestHandler}. @category CLI */
4
+ export interface ServeRequestHandlerOptions {
5
+ /** Operational ECP instance. */
6
+ ecp: Ecp;
7
+ /** Allowlisted CORS origins (empty = no CORS reflection). */
8
+ allowOrigins: ReadonlySet<string>;
9
+ }
10
+ /**
11
+ * Create the HTTP request handler for `ecp serve` (no auth).
12
+ * @category CLI
13
+ */
14
+ export declare function createServeRequestHandler(options: ServeRequestHandlerOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
15
+ //# sourceMappingURL=create-serve-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-serve-handler.d.ts","sourceRoot":"","sources":["../../../src/lib/http/create-serve-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAMzD,wEAAwE;AACxE,MAAM,WAAW,0BAA0B;IACzC,gCAAgC;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,6DAA6D;IAC7D,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAClC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,0BAA0B,IAIzE,KAAK,eAAe,EACpB,KAAK,cAAc,KAClB,OAAO,CAAC,IAAI,CAAC,CA2BjB"}
@@ -0,0 +1,34 @@
1
+ import { handleInvokePost } from "./handle-invoke.js";
2
+ import { writeJson } from "./write-json.js";
3
+ import { ECP_UP_VERSION } from "../up/constants.js";
4
+ import { setCorsAndPna } from "../up/cors.js";
5
+ /**
6
+ * Create the HTTP request handler for `ecp serve` (no auth).
7
+ * @category CLI
8
+ */
9
+ export function createServeRequestHandler(options) {
10
+ const { ecp, allowOrigins } = options;
11
+ return async function handleServeRequest(req, res) {
12
+ setCorsAndPna(req, res, allowOrigins);
13
+ if (req.method === "OPTIONS") {
14
+ res.writeHead(204);
15
+ res.end();
16
+ return;
17
+ }
18
+ const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "127.0.0.1"}`);
19
+ const pathname = url.pathname;
20
+ if (req.method === "GET" && pathname === "/health") {
21
+ writeJson(res, 200, {
22
+ ok: true,
23
+ version: ECP_UP_VERSION,
24
+ });
25
+ return;
26
+ }
27
+ if (req.method === "POST" && pathname === "/v1/invoke") {
28
+ await handleInvokePost(ecp, req, res);
29
+ return;
30
+ }
31
+ writeJson(res, 404, { error: "Not found" });
32
+ };
33
+ }
34
+ //# sourceMappingURL=create-serve-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-serve-handler.js","sourceRoot":"","sources":["../../../src/lib/http/create-serve-handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAU7C;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAmC;IAC3E,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,OAAO,CAAA;IAErC,OAAO,KAAK,UAAU,kBAAkB,CACtC,GAAoB,EACpB,GAAmB;QAEnB,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,CAAA;QAErC,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;YAClB,GAAG,CAAC,GAAG,EAAE,CAAA;YACT,OAAM;QACR,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAA;QAChF,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAA;QAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACnD,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE;gBAClB,EAAE,EAAE,IAAI;gBACR,OAAO,EAAE,cAAc;aACxB,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;YACvD,MAAM,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;YACrC,OAAM;QACR,CAAC;QAED,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;IAC7C,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type Server } from "node:http";
2
+ import type { Ecp } from "@executioncontrolprotocol/core";
3
+ /** Options for {@link startEcpServe}. @category CLI */
4
+ export interface StartEcpServeOptions {
5
+ /** Initialized operational ECP instance. */
6
+ ecp: Ecp;
7
+ /** Listen port (default 3090). */
8
+ port?: number;
9
+ /** Bind host (default 127.0.0.1). */
10
+ host?: string;
11
+ /** Extra CORS origins. */
12
+ corsOrigins?: string[];
13
+ }
14
+ /** Result of starting `ecp serve`. @category CLI */
15
+ export interface EcpServeServer {
16
+ /** Listening HTTP server. */
17
+ server: Server;
18
+ /** Resolved listen port. */
19
+ port: number;
20
+ /** Resolved bind host. */
21
+ host: string;
22
+ /** Close the HTTP server (does not terminate ECP). */
23
+ close: () => Promise<void>;
24
+ }
25
+ /**
26
+ * Start a loopback HTTP server that exposes `POST /v1/invoke` for an environment.
27
+ * @category CLI
28
+ */
29
+ export declare function startEcpServe(options: StartEcpServeOptions): Promise<EcpServeServer>;
30
+ //# sourceMappingURL=create-serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-serve.d.ts","sourceRoot":"","sources":["../../../src/lib/http/create-serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAA;AACrD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAIzD,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,GAAG,EAAE,GAAG,CAAA;IACR,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAsC1F"}
@@ -0,0 +1,43 @@
1
+ import { createServer } from "node:http";
2
+ import { DEFAULT_ECP_UP_HOST, DEFAULT_ECP_UP_PORT } from "../up/constants.js";
3
+ import { createServeRequestHandler } from "./create-serve-handler.js";
4
+ /**
5
+ * Start a loopback HTTP server that exposes `POST /v1/invoke` for an environment.
6
+ * @category CLI
7
+ */
8
+ export async function startEcpServe(options) {
9
+ const port = options.port ?? DEFAULT_ECP_UP_PORT;
10
+ const host = options.host ?? DEFAULT_ECP_UP_HOST;
11
+ const allowOrigins = new Set(options.corsOrigins ?? []);
12
+ const handler = createServeRequestHandler({
13
+ ecp: options.ecp,
14
+ allowOrigins,
15
+ });
16
+ const server = createServer((req, res) => {
17
+ void handler(req, res).catch((err) => {
18
+ const message = err instanceof Error ? err.message : String(err);
19
+ if (!res.headersSent) {
20
+ res.writeHead(500, { "Content-Type": "application/json" });
21
+ }
22
+ res.end(JSON.stringify({ error: message }));
23
+ });
24
+ });
25
+ await new Promise((resolve, reject) => {
26
+ server.once("error", reject);
27
+ server.listen(port, host, () => {
28
+ server.off("error", reject);
29
+ resolve();
30
+ });
31
+ });
32
+ return {
33
+ server,
34
+ port,
35
+ host,
36
+ close: async () => {
37
+ await new Promise((resolve, reject) => {
38
+ server.close((err) => (err ? reject(err) : resolve()));
39
+ });
40
+ },
41
+ };
42
+ }
43
+ //# sourceMappingURL=create-serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-serve.js","sourceRoot":"","sources":["../../../src/lib/http/create-serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAA;AAErD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC7E,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAA;AA0BrE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,mBAAmB,CAAA;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,mBAAmB,CAAA;IAChD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAA;IAE/D,MAAM,OAAO,GAAG,yBAAyB,CAAC;QACxC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,YAAY;KACb,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,KAAK,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAA;YAC5D,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YAC3B,OAAO,EAAE,CAAA;QACX,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,MAAM;QACN,IAAI;QACJ,IAAI;QACJ,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YACxD,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { Ecp } from "@executioncontrolprotocol/core";
3
+ /** JSON body for `POST /v1/invoke`. @category CLI */
4
+ export interface InvokeHttpBody {
5
+ /** Capability id to invoke. */
6
+ capability?: string;
7
+ /** Capability input payload. */
8
+ input?: unknown;
9
+ /** Optional provider capability override (harness `.uses`). */
10
+ provider?: string;
11
+ }
12
+ /**
13
+ * Parse and validate a `/v1/invoke` request body.
14
+ * @category CLI
15
+ */
16
+ export declare function parseInvokeBody(raw: string): {
17
+ ok: true;
18
+ body: {
19
+ capability: string;
20
+ input: unknown;
21
+ provider?: string;
22
+ };
23
+ } | {
24
+ ok: false;
25
+ error: string;
26
+ };
27
+ /**
28
+ * Run `ecp.invoke` for a parsed invoke body and return the result.
29
+ * @category CLI
30
+ */
31
+ export declare function runHttpInvoke(ecp: Ecp, body: {
32
+ capability: string;
33
+ input: unknown;
34
+ provider?: string;
35
+ }): Promise<import("@executioncontrolprotocol/core").InvokeResult<unknown>>;
36
+ /**
37
+ * Handle `POST /v1/invoke`: read body, invoke, write JSON result.
38
+ * Does not perform authentication.
39
+ * @category CLI
40
+ */
41
+ export declare function handleInvokePost(ecp: Ecp, req: IncomingMessage, res: ServerResponse): Promise<void>;
42
+ //# sourceMappingURL=handle-invoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-invoke.d.ts","sourceRoot":"","sources":["../../../src/lib/http/handle-invoke.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAIzD,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gCAAgC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GACV;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAoB9G;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,2EAIhE;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CAuBf"}
@@ -0,0 +1,66 @@
1
+ import { readRequestBody } from "./read-body.js";
2
+ import { writeJson } from "./write-json.js";
3
+ /**
4
+ * Parse and validate a `/v1/invoke` request body.
5
+ * @category CLI
6
+ */
7
+ export function parseInvokeBody(raw) {
8
+ let parsed;
9
+ try {
10
+ parsed = raw.trim() ? JSON.parse(raw) : {};
11
+ }
12
+ catch {
13
+ return { ok: false, error: "Invalid JSON body" };
14
+ }
15
+ if (typeof parsed.capability !== "string" || !parsed.capability.trim()) {
16
+ return { ok: false, error: "capability is required" };
17
+ }
18
+ return {
19
+ ok: true,
20
+ body: {
21
+ capability: parsed.capability,
22
+ input: parsed.input ?? {},
23
+ ...(typeof parsed.provider === "string" && parsed.provider.trim()
24
+ ? { provider: parsed.provider }
25
+ : {}),
26
+ },
27
+ };
28
+ }
29
+ /**
30
+ * Run `ecp.invoke` for a parsed invoke body and return the result.
31
+ * @category CLI
32
+ */
33
+ export async function runHttpInvoke(ecp, body) {
34
+ const builder = ecp.invoke(body.capability).with(body.input);
35
+ return (body.provider ? builder.uses(body.provider) : builder).process();
36
+ }
37
+ /**
38
+ * Handle `POST /v1/invoke`: read body, invoke, write JSON result.
39
+ * Does not perform authentication.
40
+ * @category CLI
41
+ */
42
+ export async function handleInvokePost(ecp, req, res) {
43
+ let raw;
44
+ try {
45
+ raw = await readRequestBody(req);
46
+ }
47
+ catch (err) {
48
+ const message = err instanceof Error ? err.message : String(err);
49
+ writeJson(res, 400, { error: message });
50
+ return;
51
+ }
52
+ const parsed = parseInvokeBody(raw);
53
+ if (!parsed.ok) {
54
+ writeJson(res, 400, { error: parsed.error });
55
+ return;
56
+ }
57
+ try {
58
+ const result = await runHttpInvoke(ecp, parsed.body);
59
+ writeJson(res, 200, result);
60
+ }
61
+ catch (err) {
62
+ const message = err instanceof Error ? err.message : String(err);
63
+ writeJson(res, 500, { error: message });
64
+ }
65
+ }
66
+ //# sourceMappingURL=handle-invoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-invoke.js","sourceRoot":"","sources":["../../../src/lib/http/handle-invoke.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAY3C;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAW;IAEX,IAAI,MAAsB,CAAA;IAC1B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC,CAAC,CAAC,EAAE,CAAA;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAA;IAClD,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;QACvE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAA;IACvD,CAAC;IACD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,IAAI,EAAE;YACJ,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE;YACzB,GAAG,CAAC,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;gBAC/D,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE;gBAC/B,CAAC,CAAC,EAAE,CAAC;SACR;KACF,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAQ,EACR,IAA+D;IAE/D,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC5D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAA;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAQ,EACR,GAAoB,EACpB,GAAmB;IAEnB,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAA;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;QACvC,OAAM;IACR,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;IACnC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QAC5C,OAAM;IACR,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QACpD,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IACzC,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { IncomingMessage } from "node:http";
2
+ /**
3
+ * Read the full request body as UTF-8 text.
4
+ * @category CLI
5
+ */
6
+ export declare function readRequestBody(req: IncomingMessage): Promise<string>;
7
+ //# sourceMappingURL=read-body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-body.d.ts","sourceRoot":"","sources":["../../../src/lib/http/read-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAEhD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAM3E"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Read the full request body as UTF-8 text.
3
+ * @category CLI
4
+ */
5
+ export async function readRequestBody(req) {
6
+ const chunks = [];
7
+ for await (const chunk of req) {
8
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
9
+ }
10
+ return Buffer.concat(chunks).toString("utf8");
11
+ }
12
+ //# sourceMappingURL=read-body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-body.js","sourceRoot":"","sources":["../../../src/lib/http/read-body.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAoB;IACxD,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IACrE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AAC/C,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ServerResponse } from "node:http";
2
+ /**
3
+ * Write a JSON response with the given status code.
4
+ * @category CLI
5
+ */
6
+ export declare function writeJson(res: ServerResponse, status: number, body: unknown): void;
7
+ //# sourceMappingURL=write-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-json.d.ts","sourceRoot":"","sources":["../../../src/lib/http/write-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAG/C;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAIlF"}
@@ -0,0 +1,11 @@
1
+ import { JSON_MIME } from "../up/constants.js";
2
+ /**
3
+ * Write a JSON response with the given status code.
4
+ * @category CLI
5
+ */
6
+ export function writeJson(res, status, body) {
7
+ const payload = JSON.stringify(body);
8
+ res.writeHead(status, { "Content-Type": JSON_MIME });
9
+ res.end(payload);
10
+ }
11
+ //# sourceMappingURL=write-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-json.js","sourceRoot":"","sources":["../../../src/lib/http/write-json.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAE9C;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,GAAmB,EAAE,MAAc,EAAE,IAAa;IAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IACpC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,CAAA;IACpD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AAClB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { TestSessionSnapshot } from "@executioncontrolprotocol/types";
2
+ /**
3
+ * Read a test session snapshot JSON file.
4
+ * @category CLI
5
+ */
6
+ export declare function readTestSessionFile(path: string): Promise<TestSessionSnapshot>;
7
+ /**
8
+ * Write a test session snapshot JSON file.
9
+ * @category CLI
10
+ */
11
+ export declare function writeTestSessionFile(path: string, snapshot: TestSessionSnapshot): Promise<void>;
12
+ //# sourceMappingURL=test-session-io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-session-io.d.ts","sourceRoot":"","sources":["../../src/lib/test-session-io.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AAE1E;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAwBpF;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAEf"}
@@ -0,0 +1,36 @@
1
+ import { writeFile, readFile } from "node:fs/promises";
2
+ /**
3
+ * Read a test session snapshot JSON file.
4
+ * @category CLI
5
+ */
6
+ export async function readTestSessionFile(path) {
7
+ let raw;
8
+ try {
9
+ raw = await readFile(path, "utf8");
10
+ }
11
+ catch {
12
+ throw new Error(`--session: cannot read file "${path}"`);
13
+ }
14
+ let parsed;
15
+ try {
16
+ parsed = JSON.parse(raw);
17
+ }
18
+ catch (err) {
19
+ const message = err instanceof Error ? err.message : String(err);
20
+ throw new Error(`--session: invalid JSON in "${path}" (${message})`);
21
+ }
22
+ if (!parsed ||
23
+ typeof parsed !== "object" ||
24
+ parsed.schema !== "@executioncontrolprotocol.test.session") {
25
+ throw new Error(`--session: expected schema "@executioncontrolprotocol.test.session" in "${path}"`);
26
+ }
27
+ return parsed;
28
+ }
29
+ /**
30
+ * Write a test session snapshot JSON file.
31
+ * @category CLI
32
+ */
33
+ export async function writeTestSessionFile(path, snapshot) {
34
+ await writeFile(path, JSON.stringify(snapshot, null, 2) + "\n", "utf8");
35
+ }
36
+ //# sourceMappingURL=test-session-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-session-io.js","sourceRoot":"","sources":["../../src/lib/test-session-io.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGtD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAY;IACpD,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,GAAG,CAAC,CAAA;IAC1D,CAAC;IACD,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChE,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,MAAM,OAAO,GAAG,CAAC,CAAA;IACtE,CAAC;IACD,IACE,CAAC,MAAM;QACP,OAAO,MAAM,KAAK,QAAQ;QACzB,MAA8B,CAAC,MAAM,KAAK,wCAAwC,EACnF,CAAC;QACD,MAAM,IAAI,KAAK,CACb,2EAA2E,IAAI,GAAG,CACnF,CAAA;IACH,CAAC;IACD,OAAO,MAA6B,CAAA;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAY,EACZ,QAA6B;IAE7B,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAA;AACzE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"handle-request.d.ts","sourceRoot":"","sources":["../../../src/lib/up/handle-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAMzD,qEAAqE;AACrE,MAAM,WAAW,uBAAuB;IACtC,gCAAgC;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,gCAAgC;IAChC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAA;CAClB;AAQD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,IAInE,KAAK,eAAe,EACpB,KAAK,cAAc,KAClB,OAAO,CAAC,IAAI,CAAC,CA2DjB"}
1
+ {"version":3,"file":"handle-request.d.ts","sourceRoot":"","sources":["../../../src/lib/up/handle-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAOzD,qEAAqE;AACrE,MAAM,WAAW,uBAAuB;IACtC,gCAAgC;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,gCAAgC;IAChC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,IAInE,KAAK,eAAe,EACpB,KAAK,cAAc,KAClB,OAAO,CAAC,IAAI,CAAC,CAwCjB"}
@@ -1,7 +1,8 @@
1
1
  import { listOllamaModels } from "@executioncontrolprotocol/extension-ollama";
2
- import { ECP_UP_VERSION, JSON_MIME } from "./constants.js";
2
+ import { handleInvokePost } from "../http/handle-invoke.js";
3
+ import { writeJson } from "../http/write-json.js";
4
+ import { ECP_UP_VERSION } from "./constants.js";
3
5
  import { readBearerToken, setCorsAndPna } from "./cors.js";
4
- import { readRequestBody } from "./read-body.js";
5
6
  /**
6
7
  * Create the HTTP request handler for `ecp up`.
7
8
  * @category CLI
@@ -39,36 +40,10 @@ export function createUpRequestHandler(options) {
39
40
  writeJson(res, 401, { error: "Unauthorized" });
40
41
  return;
41
42
  }
42
- let body;
43
- try {
44
- const raw = await readRequestBody(req);
45
- body = raw.trim() ? JSON.parse(raw) : {};
46
- }
47
- catch {
48
- writeJson(res, 400, { error: "Invalid JSON body" });
49
- return;
50
- }
51
- if (typeof body.capability !== "string" || !body.capability.trim()) {
52
- writeJson(res, 400, { error: "capability is required" });
53
- return;
54
- }
55
- try {
56
- const builder = ecp.invoke(body.capability).with(body.input ?? {});
57
- const result = await (body.provider ? builder.uses(body.provider) : builder).process();
58
- writeJson(res, 200, result);
59
- }
60
- catch (err) {
61
- const message = err instanceof Error ? err.message : String(err);
62
- writeJson(res, 500, { error: message });
63
- }
43
+ await handleInvokePost(ecp, req, res);
64
44
  return;
65
45
  }
66
46
  writeJson(res, 404, { error: "Not found" });
67
47
  };
68
48
  }
69
- function writeJson(res, status, body) {
70
- const payload = JSON.stringify(body);
71
- res.writeHead(status, { "Content-Type": JSON_MIME });
72
- res.end(payload);
73
- }
74
49
  //# sourceMappingURL=handle-request.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handle-request.js","sourceRoot":"","sources":["../../../src/lib/up/handle-request.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handle-request.js","sourceRoot":"","sources":["../../../src/lib/up/handle-request.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAc1D;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAEvD,OAAO,KAAK,UAAU,eAAe,CACnC,GAAoB,EACpB,GAAmB;QAEnB,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,CAAA;QAErC,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;YAClB,GAAG,CAAC,GAAG,EAAE,CAAA;YACT,OAAM;QACR,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAA;QAChF,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAA;QAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACnD,IAAI,eAAe,GAAG,KAAK,CAAA;YAC3B,IAAI,CAAC;gBACH,MAAM,gBAAgB,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBACxE,eAAe,GAAG,IAAI,CAAA;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,eAAe,GAAG,KAAK,CAAA;YACzB,CAAC;YACD,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE;gBAClB,EAAE,EAAE,IAAI;gBACR,OAAO,EAAE,cAAc;gBACvB,eAAe;aAChB,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;YACvD,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;YACtC,IAAI,CAAC,SAAS,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;gBACtC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAA;gBAC9C,OAAM;YACR,CAAC;YACD,MAAM,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;YACrC,OAAM;QACR,CAAC;QAED,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;IAC7C,CAAC,CAAA;AACH,CAAC"}
@@ -1,7 +1,3 @@
1
- import type { IncomingMessage } from "node:http";
2
- /**
3
- * Read the full request body as UTF-8 text.
4
- * @category CLI
5
- */
6
- export declare function readRequestBody(req: IncomingMessage): Promise<string>;
1
+ /** Re-export for callers that still import from the up path. @category CLI */
2
+ export { readRequestBody } from "../http/read-body.js";
7
3
  //# sourceMappingURL=read-body.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"read-body.d.ts","sourceRoot":"","sources":["../../../src/lib/up/read-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAEhD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAM3E"}
1
+ {"version":3,"file":"read-body.d.ts","sourceRoot":"","sources":["../../../src/lib/up/read-body.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA"}
@@ -1,12 +1,3 @@
1
- /**
2
- * Read the full request body as UTF-8 text.
3
- * @category CLI
4
- */
5
- export async function readRequestBody(req) {
6
- const chunks = [];
7
- for await (const chunk of req) {
8
- chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
9
- }
10
- return Buffer.concat(chunks).toString("utf8");
11
- }
1
+ /** Re-export for callers that still import from the up path. @category CLI */
2
+ export { readRequestBody } from "../http/read-body.js";
12
3
  //# sourceMappingURL=read-body.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"read-body.js","sourceRoot":"","sources":["../../../src/lib/up/read-body.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAoB;IACxD,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IACrE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AAC/C,CAAC"}
1
+ {"version":3,"file":"read-body.js","sourceRoot":"","sources":["../../../src/lib/up/read-body.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@executioncontrolprotocol/cli",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "ECP command-line interface",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -19,19 +19,19 @@
19
19
  "start": "node ./bin/dev.js"
20
20
  },
21
21
  "peerDependencies": {
22
- "@executioncontrolprotocol/core": "^0.10.1",
23
- "@executioncontrolprotocol/types": "^0.10.1",
22
+ "@executioncontrolprotocol/core": "^0.11.0",
23
+ "@executioncontrolprotocol/types": "^0.11.0",
24
24
  "zod": "^3.24.0"
25
25
  },
26
26
  "dependencies": {
27
- "@executioncontrolprotocol/node": "0.10.1",
28
- "@executioncontrolprotocol/secrets": "0.10.1",
29
- "@executioncontrolprotocol/extension-ollama": "0.10.1",
27
+ "@executioncontrolprotocol/node": "0.11.0",
28
+ "@executioncontrolprotocol/secrets": "0.11.0",
29
+ "@executioncontrolprotocol/extension-ollama": "0.11.0",
30
30
  "@oclif/core": "^4.10.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@executioncontrolprotocol/core": "0.10.1",
34
- "@executioncontrolprotocol/types": "0.10.1",
33
+ "@executioncontrolprotocol/core": "0.11.0",
34
+ "@executioncontrolprotocol/types": "0.11.0",
35
35
  "typescript": "^5.7.0",
36
36
  "zod": "^3.24.0"
37
37
  },