@elench/testkit 0.1.98 → 0.1.99

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.
@@ -1,7 +1,8 @@
1
1
  import { Command } from "@oclif/core";
2
- import { sharedFlags } from "./flags.mjs";
2
+ import { sharedFlags } from "../command-flags.mjs";
3
3
  import { executeStatusOperation } from "../operations/status/operation.mjs";
4
4
  import { renderStatusResult } from "../renderers/status/text.mjs";
5
+ import { withAssistantCommandResult } from "../assistant/command-results.mjs";
5
6
 
6
7
  export default class StatusCommand extends Command {
7
8
  static summary = "Show local testkit state";
@@ -11,13 +12,15 @@ export default class StatusCommand extends Command {
11
12
  static flags = sharedFlags;
12
13
 
13
14
  async run() {
14
- const { flags } = await this.parse(StatusCommand);
15
- const results = await executeStatusOperation(flags);
16
- if (!this.jsonEnabled()) {
17
- for (const result of results) {
18
- for (const line of renderStatusResult(result)) this.log(line);
15
+ return withAssistantCommandResult("status", async () => {
16
+ const { flags } = await this.parse(StatusCommand);
17
+ const results = await executeStatusOperation(flags);
18
+ if (!this.jsonEnabled()) {
19
+ for (const result of results) {
20
+ for (const line of renderStatusResult(result)) this.log(line);
21
+ }
19
22
  }
20
- }
21
- return { ok: true, results };
23
+ return { ok: true, results };
24
+ });
22
25
  }
23
26
  }
@@ -1,6 +1,7 @@
1
1
  import { Command, Flags } from "@oclif/core";
2
2
  import { executeTypecheckOperation } from "../operations/typecheck/operation.mjs";
3
3
  import { renderTypecheckResult } from "../renderers/typecheck/text.mjs";
4
+ import { withAssistantCommandResult } from "../assistant/command-results.mjs";
4
5
 
5
6
  export default class TypecheckCommand extends Command {
6
7
  static summary = "Typecheck testkit config, helpers, and suites";
@@ -14,15 +15,17 @@ export default class TypecheckCommand extends Command {
14
15
  };
15
16
 
16
17
  async run() {
17
- const { flags } = await this.parse(TypecheckCommand);
18
- const result = await executeTypecheckOperation(flags);
18
+ return withAssistantCommandResult("typecheck", async () => {
19
+ const { flags } = await this.parse(TypecheckCommand);
20
+ const result = await executeTypecheckOperation(flags);
19
21
 
20
- if (!this.jsonEnabled()) {
21
- for (const line of renderTypecheckResult(result)) {
22
- this.log(line);
22
+ if (!this.jsonEnabled()) {
23
+ for (const line of renderTypecheckResult(result)) {
24
+ this.log(line);
25
+ }
23
26
  }
24
- }
25
27
 
26
- return result;
28
+ return result;
29
+ });
27
30
  }
28
31
  }
@@ -1,4 +1,7 @@
1
1
  export function normalizeCliArgs(argv) {
2
+ if (argv[0] === "help") return normalizeHelpInvocation(argv);
3
+ if (isOclifBuiltinInvocation(argv)) return argv;
4
+
2
5
  const topLevelCommands = new Set([
3
6
  "assistant",
4
7
  "run",
@@ -10,11 +13,6 @@ export function normalizeCliArgs(argv) {
10
13
  "doctor",
11
14
  "browser",
12
15
  "db",
13
- "help",
14
- "--help",
15
- "-h",
16
- "--version",
17
- "-v",
18
16
  ]);
19
17
  const runTypeShortcuts = new Set(["int", "e2e", "scenario", "dal", "load", "pw", "all"]);
20
18
  const valueFlags = new Set([
@@ -95,6 +93,17 @@ export function normalizeCliArgs(argv) {
95
93
  return argv;
96
94
  }
97
95
 
96
+ function isOclifBuiltinInvocation(argv) {
97
+ const first = argv[0];
98
+ if (first === "--help" || first === "-h" || first === "--version" || first === "-v") return true;
99
+ return false;
100
+ }
101
+
102
+ function normalizeHelpInvocation(argv) {
103
+ if (!argv[1]) return ["--help"];
104
+ return [argv[1], ...argv.slice(2), "--help"];
105
+ }
106
+
98
107
  function findPositionals(args, flagsWithValues) {
99
108
  const positionals = [];
100
109
  for (let index = 0; index < args.length; index += 1) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/next-analysis",
3
- "version": "0.1.98",
3
+ "version": "0.1.99",
4
4
  "description": "SWC-backed Next.js source analysis primitives for Erench tools",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit-bridge",
3
- "version": "0.1.98",
3
+ "version": "0.1.99",
4
4
  "description": "Browser bridge helpers for testkit",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "typecheck": "tsc -p tsconfig.json --noEmit"
23
23
  },
24
24
  "dependencies": {
25
- "@elench/testkit-protocol": "0.1.98"
25
+ "@elench/testkit-protocol": "0.1.99"
26
26
  },
27
27
  "private": false
28
28
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit-protocol",
3
- "version": "0.1.98",
3
+ "version": "0.1.99",
4
4
  "description": "Shared browser protocol for testkit bridge and extension consumers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/ts-analysis",
3
- "version": "0.1.98",
3
+ "version": "0.1.99",
4
4
  "description": "TypeScript compiler-backed source analysis primitives for Erench tools",
5
5
  "type": "module",
6
6
  "exports": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit",
3
- "version": "0.1.98",
3
+ "version": "0.1.99",
4
4
  "description": "Assistant-first CLI for running, inspecting, and debugging local testkit suites",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -58,7 +58,7 @@
58
58
  "scripts": {
59
59
  "build:packages": "npm --workspace packages/testkit-protocol run build && npm --workspace packages/ts-analysis run build && npm --workspace packages/next-analysis run build && npm --workspace packages/testkit-bridge run build",
60
60
  "typecheck:packages": "npm --workspace packages/testkit-protocol run typecheck && npm --workspace packages/ts-analysis run typecheck && npm --workspace packages/next-analysis run typecheck && npm --workspace packages/testkit-bridge run typecheck && npm --workspace packages/testkit-extension run compile",
61
- "test": "npm run build:packages && vitest run",
61
+ "test": "npm run build:packages && vitest run && node scripts/live-sandbox/harness.mjs",
62
62
  "test:audit": "node scripts/test-boundary-audit.mjs",
63
63
  "test:unit": "npm run build:packages && npm run test:audit && vitest run --config vitest.unit.config.mjs",
64
64
  "test:integration": "npm run build:packages && vitest run test/integration",
@@ -83,10 +83,10 @@
83
83
  },
84
84
  "dependencies": {
85
85
  "@babel/code-frame": "^7.29.0",
86
- "@elench/next-analysis": "0.1.98",
87
- "@elench/testkit-bridge": "0.1.98",
88
- "@elench/testkit-protocol": "0.1.98",
89
- "@elench/ts-analysis": "0.1.98",
86
+ "@elench/next-analysis": "0.1.99",
87
+ "@elench/testkit-bridge": "0.1.99",
88
+ "@elench/testkit-protocol": "0.1.99",
89
+ "@elench/ts-analysis": "0.1.99",
90
90
  "@oclif/core": "^4.10.6",
91
91
  "esbuild": "^0.25.11",
92
92
  "execa": "^9.5.0",
@@ -1,67 +0,0 @@
1
- export function buildAssistantResponseContract({ tools = [] } = {}) {
2
- return [
3
- "Respond with exactly one JSON object and no surrounding commentary.",
4
- 'Use {"type":"answer","message":"..."} when you can answer directly.',
5
- 'Use {"type":"tool","tool":"<name>","arguments":{...},"commentary":"..."} when you need testkit to act before you answer.',
6
- "Only request one tool at a time.",
7
- `Available tools: ${tools.map((tool) => tool.name).join(", ") || "none"}.`,
8
- ].join("\n");
9
- }
10
-
11
- export function parseAssistantEnvelope(text) {
12
- const raw = String(text || "").trim();
13
- if (!raw) {
14
- return {
15
- type: "answer",
16
- message: "",
17
- };
18
- }
19
-
20
- const candidate = extractJsonObject(raw);
21
- if (!candidate) {
22
- return {
23
- type: "answer",
24
- message: raw,
25
- };
26
- }
27
-
28
- try {
29
- const parsed = JSON.parse(candidate);
30
- if (parsed?.type === "tool" && parsed.tool) {
31
- return {
32
- type: "tool",
33
- tool: String(parsed.tool),
34
- arguments: normalizePlainObject(parsed.arguments),
35
- commentary: parsed.commentary ? String(parsed.commentary) : "",
36
- };
37
- }
38
- if (parsed?.type === "answer") {
39
- return {
40
- type: "answer",
41
- message: parsed.message ? String(parsed.message) : "",
42
- };
43
- }
44
- } catch {
45
- // Fall through to raw answer.
46
- }
47
-
48
- return {
49
- type: "answer",
50
- message: raw,
51
- };
52
- }
53
-
54
- function extractJsonObject(text) {
55
- const fencedMatch = text.match(/```json\s*([\s\S]*?)```/i);
56
- if (fencedMatch?.[1]) return fencedMatch[1].trim();
57
-
58
- const start = text.indexOf("{");
59
- const end = text.lastIndexOf("}");
60
- if (start < 0 || end <= start) return null;
61
- return text.slice(start, end + 1);
62
- }
63
-
64
- function normalizePlainObject(value) {
65
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
66
- return value;
67
- }