myshell-tools 2.4.0 → 2.6.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.
- package/CHANGELOG.md +15 -0
- package/README.md +26 -10
- package/dist/cli.js +33 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/cost.js +4 -1
- package/dist/commands/cost.js.map +1 -1
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/login.d.ts +41 -2
- package/dist/commands/login.js +116 -11
- package/dist/commands/login.js.map +1 -1
- package/dist/core/assess.js +2 -62
- package/dist/core/assess.js.map +1 -1
- package/dist/core/budget.d.ts +26 -0
- package/dist/core/budget.js +37 -0
- package/dist/core/budget.js.map +1 -0
- package/dist/core/history.d.ts +35 -0
- package/dist/core/history.js +116 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/json-envelope.d.ts +49 -0
- package/dist/core/json-envelope.js +117 -0
- package/dist/core/json-envelope.js.map +1 -0
- package/dist/core/orchestrate.js +107 -8
- package/dist/core/orchestrate.js.map +1 -1
- package/dist/core/policy.js +17 -9
- package/dist/core/policy.js.map +1 -1
- package/dist/core/prompt.d.ts +9 -4
- package/dist/core/prompt.js +14 -5
- package/dist/core/prompt.js.map +1 -1
- package/dist/core/review.js +2 -49
- package/dist/core/review.js.map +1 -1
- package/dist/core/route.d.ts +13 -5
- package/dist/core/route.js +20 -6
- package/dist/core/route.js.map +1 -1
- package/dist/core/types.d.ts +37 -0
- package/dist/infra/pricing.d.ts +17 -4
- package/dist/infra/pricing.js +73 -3
- package/dist/infra/pricing.js.map +1 -1
- package/dist/interface/menu.d.ts +12 -0
- package/dist/interface/menu.js +106 -22
- package/dist/interface/menu.js.map +1 -1
- package/dist/providers/detect.d.ts +17 -5
- package/dist/providers/detect.js +56 -4
- package/dist/providers/detect.js.map +1 -1
- package/dist/providers/install.js +1 -0
- package/dist/providers/install.js.map +1 -1
- package/dist/providers/opencode-parse.d.ts +49 -0
- package/dist/providers/opencode-parse.js +181 -0
- package/dist/providers/opencode-parse.js.map +1 -0
- package/dist/providers/opencode.d.ts +43 -0
- package/dist/providers/opencode.js +121 -0
- package/dist/providers/opencode.js.map +1 -0
- package/dist/providers/port.d.ts +1 -1
- package/dist/providers/registry.d.ts +2 -2
- package/dist/providers/registry.js +6 -2
- package/dist/providers/registry.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,21 @@ and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.
|
|
|
11
11
|
- Cross-OS CI execution (requires a public remote).
|
|
12
12
|
- First npm publish.
|
|
13
13
|
|
|
14
|
+
## [2.6.0]
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **opencode provider (experimental, auto-detected)**: third provider alongside claude/codex. Auto-detected when the `opencode` CLI is installed; works immediately via opencode's free hosted models (no keys required), with premium providers (Gemini/Claude/GPT/local/etc.) available through opencode's own `auth login` — myshell-tools never handles the keys. Streams via `opencode run --format json`, reports real per-step token usage AND cost to the ledger via step_finish events (no pricing-table dependency for billing), and appears in the control-panel header + raw-session picker only when installed (no nag otherwise). Cross-vendor review stays honest by comparing the effective vendor from the `provider/model` id.
|
|
18
|
+
- **Routing robustness**: `route()` now prefers a model the provider CLI actually advertises (from detection) and never selects a model the CLI lacks; falls back gracefully when the advertised set matches no pricing entry, never throws. Closes a latent crash where an opencode-only setup (or any escalation that reached manager tier with opencode as the sole available provider) would throw `No models available for tier "…" with providers [opencode]` because the pricing table only had an entry for the `ic` tier. All three tiers (worker/ic/manager) now have opencode pricing entries.
|
|
19
|
+
|
|
20
|
+
## [2.5.0]
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- **Conversation context continuity**: multi-turn conversations now replay a bounded, compacted slice of prior history to the model on each turn — previously every turn was sent cold/stateless, so follow-up questions had no context. The history is token-bounded (most recent 12 turns, ~6 k chars) and assistant confidence-envelopes are stripped before replay to save tokens. Implemented via `src/core/history.ts` (`compactHistory`).
|
|
24
|
+
- **Efficiency engine**: cost-aware cross-vendor review gating via `reviewPolicy: auto | critical-only | off` — cost-saver mode now only runs the double-spend review pass on critical-risk tasks, not every IC invocation. An optional per-task cost budget cap (`Policy.maxCostUsd`) stops escalating/reviewing once spend reaches the cap and accepts the best result so far. Implemented via `src/core/budget.ts` (`budgetExceeded`, `remainingBudget`) and the `reviewPolicy` field in `src/core/policy.ts`.
|
|
25
|
+
- **Container / SSH-friendly sign-in ("code method")**: when the browser/localhost OAuth callback can't be reached (Replit, Codespaces, Gitpod, SSH, or a headless Linux box), `login` now uses a no-localhost flow automatically — `codex login --device-auth` (authorize with a one-time device code) for Codex, and `claude setup-token` (paste an authorization code from claude.ai) for Claude. The environment is auto-detected; force either flow with `myshell-tools login <provider> --code` / `--browser`. A failed browser sign-in now also points at the `--code` fallback.
|
|
26
|
+
- **Settings → "Set as default shell" toggle**: the control-panel Settings screen (`[s]`) now exposes `[2] Set as default shell` alongside the mode picker; toggling it installs/uninstalls the real shell startup hook (same mechanism as `myshell-tools install`/`uninstall`) and only flips the stored flag when the hook write succeeds.
|
|
27
|
+
- **JSON-envelope deduplication**: the brace-depth `{...}` scanner used to extract model confidence/verdict envelopes was duplicated across `assess.ts`, `review.ts`, and `history.ts`. Extracted into a shared pure module `src/core/json-envelope.ts` (`lastJsonObjectWithKey`, `lastJsonObjectBoundsWithKey`); all three consumers now delegate to it. Behaviour is identical; the shared module carries its own thorough test suite.
|
|
28
|
+
|
|
14
29
|
## [2.4.0]
|
|
15
30
|
|
|
16
31
|
### Added
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
`myshell-tools` routes each task to the *cheapest* model likely to succeed, runs it on your real codebase, optionally has a **different vendor** review the result, and shows you exactly what it did and what it truly cost — with **no fabricated data, ever**.
|
|
6
6
|
|
|
7
|
-
> **Status: `2.
|
|
7
|
+
> **Status: `2.6.0` — honest, tested, and real.** Claude, Codex, and opencode (experimental) all work, and provider auth is detected for real.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -39,20 +39,29 @@ myshell-tools
|
|
|
39
39
|
Using one frontier model for everything is wasteful (renaming a variable doesn't need Opus) and single‑model output has blind spots. `myshell-tools` addresses both, honestly:
|
|
40
40
|
|
|
41
41
|
- **Cost‑aware routing** — trivial work goes to the cheap tier (Haiku / GPT‑5 mini), real implementation to the mid tier, hard calls to the flagship. You see the savings as a real number.
|
|
42
|
-
- **
|
|
43
|
-
-
|
|
42
|
+
- **Efficiency modes** — three policy presets control the cost/quality trade-off:
|
|
43
|
+
- `cost-saver` — routes to the cheapest capable model for each tier; only runs the cross-vendor review pass on *critical*-risk tasks (not every IC call). An optional `maxCostUsd` cap halts further escalation/review once spend reaches the limit.
|
|
44
|
+
- `balanced` — the default; routes intelligently and reviews high-risk work.
|
|
45
|
+
- `quality-first` — always reviews IC output for high/critical tasks, regardless of cost.
|
|
46
|
+
- **Cross‑vendor adversarial review** — a *different vendor* checks the first model's output (Codex reviewing Claude, or vice‑versa). Different families, different blind spots. Review gating depends on mode; see Efficiency modes above.
|
|
47
|
+
- **Multi-turn context continuity** — follow-up messages carry real context. Prior conversation turns are compacted into a bounded history block (~6 k chars, most recent 12 turns) and replayed to the model, so it actually knows what was said earlier. Confidence envelopes are stripped before replay to save tokens.
|
|
48
|
+
- **Container / SSH sign-in** — `myshell-tools login` auto-detects headless and cloud-IDE environments (Replit, Codespaces, Gitpod, SSH sessions) and switches to a no-localhost sign-in flow automatically. Force either flow with `--code` or `--browser`.
|
|
49
|
+
- **opencode provider (experimental)** — auto-detected; works instantly with free hosted models (no keys). Add premium providers through opencode's own `auth login`. Route to it explicitly or let the policy fall back to it automatically.
|
|
50
|
+
- **Routing prefers advertised models** — detection passes each provider's actual model list to `route()`, which picks the cheapest model the CLI *actually has*, not just the cheapest in the pricing table. Falls back gracefully if the advertised list doesn't match any pricing entry.
|
|
51
|
+
- **Subscription, not metering** — it drives the **Claude Code**, **Codex**, and **opencode** CLIs you already use. No API keys, no per‑token bill for the free path.
|
|
44
52
|
- **Honest by construction** — every number on screen traces to a real measurement. A suite of *architecture tests* makes fabricated/mock output literally unmergeable.
|
|
45
53
|
|
|
46
54
|
---
|
|
47
55
|
|
|
48
56
|
## Requirements
|
|
49
57
|
|
|
50
|
-
- **Node.js ≥ 20**
|
|
58
|
+
- **Node.js ≥ 20** for the compiled CLI (`dist/`). **Node ≥ 22** is required to run the test suite (see Development below).
|
|
51
59
|
- At least one provider CLI. `npx myshell-tools` will **offer to install** them for you on first run — or you can install manually:
|
|
52
60
|
- **Claude Code** — `npm install -g @anthropic-ai/claude-code`, then sign in when prompted.
|
|
53
61
|
- **Codex** — `npm install -g @openai/codex`, then `codex login`.
|
|
62
|
+
- **opencode** *(experimental, optional)* — auto-detected when the `opencode` CLI is installed. Works immediately with free hosted models (no keys). Premium providers (Gemini, Claude, GPT, local models, etc.) are available through opencode's own `auth login` — myshell-tools never handles the keys. Appears in the control-panel header and session picker only when installed.
|
|
54
63
|
|
|
55
|
-
You need **one** to start; install **both** to unlock cross‑vendor review.
|
|
64
|
+
You need **one** to start; install **both** claude and codex to unlock cross‑vendor review.
|
|
56
65
|
|
|
57
66
|
---
|
|
58
67
|
|
|
@@ -164,7 +173,7 @@ classify ─▶ route(cheapest tier) ─▶ run ─▶ assess
|
|
|
164
173
|
This is a ground‑up rebuild whose first principle is: **the tool never shows fabricated, mocked, or randomized data as if it were real.** It's enforced, not promised:
|
|
165
174
|
|
|
166
175
|
- **Architecture guard tests** fail the build if the UI/command layers contain hardcoded "AI responses", fake metrics, or a digit‑then‑`%` literal; if the orchestration core touches the filesystem, clock, or RNG directly; or if any module other than the entry point can terminate the process.
|
|
167
|
-
- **
|
|
176
|
+
- **1000+ unit/architecture tests + 42 contract tests** (parsers pinned to *recorded real transcripts*), with `tsc --strict`, ESLint, and a clean `npm pack` checked in CI across Windows / macOS / Linux.
|
|
168
177
|
|
|
169
178
|
---
|
|
170
179
|
|
|
@@ -184,12 +193,17 @@ Hexagonal / ports‑and‑adapters:
|
|
|
184
193
|
|
|
185
194
|
## Development
|
|
186
195
|
|
|
196
|
+
**Node ≥ 22 is required to run the test suite.** `npm test` uses
|
|
197
|
+
`node --experimental-strip-types` (native TypeScript stripping, available from
|
|
198
|
+
Node 22+). The compiled runtime (`dist/`) supports Node ≥ 20, so
|
|
199
|
+
`package.json` `engines` is left at `>=20`.
|
|
200
|
+
|
|
187
201
|
```bash
|
|
188
|
-
npm run typecheck
|
|
189
|
-
npm run lint
|
|
190
|
-
npm test
|
|
202
|
+
npm run typecheck # tsc --strict, 0 errors
|
|
203
|
+
npm run lint # ESLint (typescript-eslint strict)
|
|
204
|
+
npm test # unit + architecture tests (requires Node ≥ 22)
|
|
191
205
|
npm run test:contract # parser contract tests vs recorded transcripts
|
|
192
|
-
npm run build
|
|
206
|
+
npm run build # tsc → dist/
|
|
193
207
|
```
|
|
194
208
|
|
|
195
209
|
---
|
|
@@ -203,6 +217,8 @@ Honest snapshot of `2.0.0-alpha.0`:
|
|
|
203
217
|
| Core routing + escalation + cross‑vendor review loop | ✅ implemented & unit‑proven |
|
|
204
218
|
| Claude adapter | ✅ live, validated end‑to‑end on real models |
|
|
205
219
|
| Codex adapter | ✅ built; auto‑activates once `codex` is installed + authed |
|
|
220
|
+
| opencode adapter (experimental) | ✅ auto-detected; free models work without keys |
|
|
221
|
+
| Routing prefers advertised models (never routes to unavailable model) | ✅ |
|
|
206
222
|
| `doctor` / `cost` / REPL / streaming UI | ✅ |
|
|
207
223
|
| Live cross‑vendor demonstration | ⏳ pending Codex auth |
|
|
208
224
|
| Cross‑OS CI run | ⏳ pending a public remote |
|
package/dist/cli.js
CHANGED
|
@@ -40,7 +40,10 @@ Commands:
|
|
|
40
40
|
(none) Open the interactive control panel (default)
|
|
41
41
|
run <task...> Run a one-shot task and exit
|
|
42
42
|
repl Start the plain line REPL (no menu)
|
|
43
|
-
login [provider] Sign in to a provider (claude or codex) via its own OAuth
|
|
43
|
+
login [provider] Sign in to a provider (claude or codex) via its own OAuth.
|
|
44
|
+
Add --code to use the no-localhost flow (paste a code for
|
|
45
|
+
claude, device code for codex) — best inside containers /
|
|
46
|
+
over SSH. Add --browser to force the localhost flow.
|
|
44
47
|
doctor Check provider installation, auth, and environment health
|
|
45
48
|
cost Show real spend from the ledger with a per-model breakdown
|
|
46
49
|
install Write a guarded startup hook to your shell rc file so new
|
|
@@ -51,20 +54,38 @@ Examples:
|
|
|
51
54
|
myshell-tools # open the control panel
|
|
52
55
|
myshell-tools run "refactor the auth module"
|
|
53
56
|
myshell-tools login
|
|
57
|
+
myshell-tools login codex --code # device-code sign-in (no localhost)
|
|
54
58
|
|
|
55
59
|
Repository: https://github.com/hey-vera/myshell-tools
|
|
56
60
|
`;
|
|
57
61
|
/** Build the orchestration dependencies (includes provider detection). */
|
|
58
62
|
async function buildDeps(cwd) {
|
|
63
|
+
const [providers, env] = await Promise.all([
|
|
64
|
+
buildProviders(cwd),
|
|
65
|
+
detectEnvironment(),
|
|
66
|
+
]);
|
|
67
|
+
// Populate advertised model lists from detection so route() can prefer a
|
|
68
|
+
// model the provider CLI actually has. Only include installed providers.
|
|
69
|
+
const availableModels = {};
|
|
70
|
+
if (env.claude.installed && env.claude.availableModels.length > 0) {
|
|
71
|
+
availableModels['claude'] = env.claude.availableModels;
|
|
72
|
+
}
|
|
73
|
+
if (env.codex.installed && env.codex.availableModels.length > 0) {
|
|
74
|
+
availableModels['codex'] = env.codex.availableModels;
|
|
75
|
+
}
|
|
76
|
+
if (env.opencode.installed && env.opencode.availableModels.length > 0) {
|
|
77
|
+
availableModels['opencode'] = env.opencode.availableModels;
|
|
78
|
+
}
|
|
59
79
|
return {
|
|
60
80
|
clock: systemClock,
|
|
61
81
|
session: createSessionWriter({ cwd, id: systemClock.uuid() }),
|
|
62
82
|
ledger: createLedger({ cwd }),
|
|
63
83
|
policy: DEFAULT_POLICY,
|
|
64
|
-
providers
|
|
84
|
+
providers,
|
|
65
85
|
cwd,
|
|
66
86
|
sandbox: 'workspace-write',
|
|
67
87
|
timeoutMs: 120000,
|
|
88
|
+
...(Object.keys(availableModels).length > 0 ? { availableModels } : {}),
|
|
68
89
|
};
|
|
69
90
|
}
|
|
70
91
|
/** Honest one-line welcome: which providers were actually detected. */
|
|
@@ -97,7 +118,16 @@ async function main() {
|
|
|
97
118
|
};
|
|
98
119
|
// ---- Commands that do NOT need provider detection --------------------------
|
|
99
120
|
if (args[0] === 'login') {
|
|
100
|
-
|
|
121
|
+
const rest = args.slice(1);
|
|
122
|
+
// --code / --device → no-localhost paste/device flow; --browser → force the
|
|
123
|
+
// localhost flow. Omitted → auto-detect (headless envs default to code).
|
|
124
|
+
const method = rest.includes('--code') || rest.includes('--device')
|
|
125
|
+
? 'code'
|
|
126
|
+
: rest.includes('--browser')
|
|
127
|
+
? 'browser'
|
|
128
|
+
: undefined;
|
|
129
|
+
const provider = rest.find((a) => !a.startsWith('-'));
|
|
130
|
+
process.exit(await runLogin(out, provider, method !== undefined ? { method } : undefined));
|
|
101
131
|
}
|
|
102
132
|
if (args[0] === 'doctor') {
|
|
103
133
|
process.exit(await runDoctor(out));
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEpC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AACvC,MAAM,OAAO,GAAW,GAAG,CAAC,OAAiB,CAAC;AAE9C,MAAM,IAAI,GAAG;iBACI,OAAO
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/cost.js
CHANGED
|
@@ -35,7 +35,10 @@ export function formatCostReport(entries, color = false) {
|
|
|
35
35
|
return ['No usage recorded yet — run a task first.'];
|
|
36
36
|
}
|
|
37
37
|
const summary = summarizeLedger(entries);
|
|
38
|
-
|
|
38
|
+
// Counterfactual uses the flagship from paid providers only (claude/codex).
|
|
39
|
+
// opencode's zero-cost sentinel entries must not suppress the counterfactual
|
|
40
|
+
// by making the "flagship" appear free.
|
|
41
|
+
const flagship = getCheapestForTier('manager', ['claude', 'codex']);
|
|
39
42
|
// Apples-to-apples: price BOTH the models actually used AND the flagship on the
|
|
40
43
|
// SAME basis (list price × tokens). We do NOT compare the billed total (which
|
|
41
44
|
// includes caching/discounts) against a list-price flagship estimate.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/commands/cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEjE,8EAA8E;AAC9E,+DAA+D;AAC/D,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAsB,EAAE,KAAK,GAAG,KAAK;IACpE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,2CAA2C,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/commands/cost.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -45,7 +45,7 @@ export function buildDoctorReport(env, extras, color) {
|
|
|
45
45
|
lines.push(divider(color));
|
|
46
46
|
// ---- Providers -------------------------------------------------------------
|
|
47
47
|
lines.push(bold('Providers', color));
|
|
48
|
-
for (const ps of [env.claude, env.codex]) {
|
|
48
|
+
for (const ps of [env.claude, env.codex, env.opencode]) {
|
|
49
49
|
if (ps.installed) {
|
|
50
50
|
const versionStr = ps.version !== null ? ps.version : 'unknown';
|
|
51
51
|
lines.push(` ${green('✓', color)} ${bold(ps.id, color)} — installed, version: ${versionStr}`);
|
|
@@ -69,7 +69,7 @@ export function buildDoctorReport(env, extras, color) {
|
|
|
69
69
|
}
|
|
70
70
|
else {
|
|
71
71
|
lines.push(red('No providers found.', color) +
|
|
72
|
-
' Install claude or
|
|
72
|
+
' Install claude, codex, or opencode to use myshell-tools.');
|
|
73
73
|
}
|
|
74
74
|
return lines;
|
|
75
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAY/E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAsB,EACtB,MAAoB,EACpB,KAAc;IAEd,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAE3B,+EAA+E;IAC/E,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3D,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAEjE,sFAAsF;IACtF,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa;QACvC,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC;QAC1B,CAAC,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAC/B,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,KAAK,YAAY,EAAE,CAAC,CAAC;IAErE,+EAA+E;IAC/E,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY;QACrC,CAAC,CAAC,MAAM,CAAC,yCAAyC,EAAE,KAAK,CAAC;QAC1D,CAAC,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAC/B,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,KAAK,WAAW,EAAE,CAAC,CAAC;IAE/D,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAE3B,+EAA+E;IAC/E,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;IAErC,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/login.d.ts
CHANGED
|
@@ -1,20 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* src/commands/login.ts — `myshell-tools login [claude|codex]`.
|
|
2
|
+
* src/commands/login.ts — `myshell-tools login [claude|codex] [--code|--browser]`.
|
|
3
3
|
*
|
|
4
4
|
* Frictionless authentication: rather than make the user remember each vendor's
|
|
5
5
|
* CLI auth command, we delegate to the provider's OWN OAuth flow and inherit the
|
|
6
6
|
* terminal so the browser/device sign-in works in place.
|
|
7
7
|
*
|
|
8
|
+
* Two sign-in methods:
|
|
9
|
+
* - 'browser': the provider's default flow, which spins up a localhost
|
|
10
|
+
* callback server and opens a browser. Great on a laptop; FAILS inside
|
|
11
|
+
* containers / over SSH (Replit, Codespaces, etc.) where localhost can't be
|
|
12
|
+
* reached from the user's browser.
|
|
13
|
+
* - 'code': a no-localhost flow that works anywhere.
|
|
14
|
+
* · claude → `claude setup-token`: prints a link; the user signs in at
|
|
15
|
+
* claude.ai, copies the authorization code, and pastes it back here.
|
|
16
|
+
* · codex → `codex login --device-auth`: prints a URL + one-time code;
|
|
17
|
+
* the user authorizes their ChatGPT account on any device.
|
|
18
|
+
*
|
|
19
|
+
* When no method is forced, we auto-detect: headless/remote environments default
|
|
20
|
+
* to 'code' (so the localhost trap is avoided), everything else to 'browser'.
|
|
21
|
+
*
|
|
8
22
|
* Security: myshell-tools never sees, handles, or stores raw credentials. Each
|
|
9
23
|
* CLI manages its own tokens; we only trigger its login. (This is what keeps the
|
|
10
24
|
* "use your subscription, no API keys" model honest.)
|
|
11
25
|
*/
|
|
12
26
|
import type { OutputSink } from '../interface/render.js';
|
|
13
27
|
import type { ProviderId } from '../providers/port.js';
|
|
28
|
+
/** Which sign-in flow to run. See module docstring. */
|
|
29
|
+
export type LoginMethod = 'browser' | 'code';
|
|
14
30
|
export declare function isProviderId(value: string): value is ProviderId;
|
|
31
|
+
/**
|
|
32
|
+
* Decide whether the current environment can actually reach a localhost OAuth
|
|
33
|
+
* callback / open a browser. Pure (env + platform in, boolean out) so it is
|
|
34
|
+
* hermetically testable.
|
|
35
|
+
*
|
|
36
|
+
* Returns true for environments where the browser/localhost flow typically
|
|
37
|
+
* fails and the code method should be preferred:
|
|
38
|
+
* - Known cloud IDEs / containers (Replit, Codespaces, Gitpod).
|
|
39
|
+
* - SSH sessions (no local browser).
|
|
40
|
+
* - Linux with no X11/Wayland display (headless box — nothing to open).
|
|
41
|
+
*/
|
|
42
|
+
export declare function isHeadlessEnv(env: NodeJS.ProcessEnv, platform: NodeJS.Platform): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the sign-in method to use. An explicit choice always wins; otherwise
|
|
45
|
+
* fall back to environment auto-detection (headless → 'code', else 'browser').
|
|
46
|
+
* Pure / testable.
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveLoginMethod(explicit: LoginMethod | undefined, env: NodeJS.ProcessEnv, platform: NodeJS.Platform): LoginMethod;
|
|
15
49
|
/**
|
|
16
50
|
* Run the interactive sign-in flow for one provider (or all installed providers
|
|
17
51
|
* when no argument is given). Returns 0 on success, 1 only for an invalid
|
|
18
52
|
* argument — individual sign-in failures are reported but do not fail the command.
|
|
53
|
+
*
|
|
54
|
+
* @param opts.method - Force 'browser' or 'code'. When omitted, the method is
|
|
55
|
+
* auto-detected from the environment via {@link resolveLoginMethod}.
|
|
19
56
|
*/
|
|
20
|
-
export declare function runLogin(out: OutputSink, providerArg?: string
|
|
57
|
+
export declare function runLogin(out: OutputSink, providerArg?: string, opts?: {
|
|
58
|
+
method?: LoginMethod;
|
|
59
|
+
}): Promise<number>;
|
package/dist/commands/login.js
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* src/commands/login.ts — `myshell-tools login [claude|codex]`.
|
|
2
|
+
* src/commands/login.ts — `myshell-tools login [claude|codex] [--code|--browser]`.
|
|
3
3
|
*
|
|
4
4
|
* Frictionless authentication: rather than make the user remember each vendor's
|
|
5
5
|
* CLI auth command, we delegate to the provider's OWN OAuth flow and inherit the
|
|
6
6
|
* terminal so the browser/device sign-in works in place.
|
|
7
7
|
*
|
|
8
|
+
* Two sign-in methods:
|
|
9
|
+
* - 'browser': the provider's default flow, which spins up a localhost
|
|
10
|
+
* callback server and opens a browser. Great on a laptop; FAILS inside
|
|
11
|
+
* containers / over SSH (Replit, Codespaces, etc.) where localhost can't be
|
|
12
|
+
* reached from the user's browser.
|
|
13
|
+
* - 'code': a no-localhost flow that works anywhere.
|
|
14
|
+
* · claude → `claude setup-token`: prints a link; the user signs in at
|
|
15
|
+
* claude.ai, copies the authorization code, and pastes it back here.
|
|
16
|
+
* · codex → `codex login --device-auth`: prints a URL + one-time code;
|
|
17
|
+
* the user authorizes their ChatGPT account on any device.
|
|
18
|
+
*
|
|
19
|
+
* When no method is forced, we auto-detect: headless/remote environments default
|
|
20
|
+
* to 'code' (so the localhost trap is avoided), everything else to 'browser'.
|
|
21
|
+
*
|
|
8
22
|
* Security: myshell-tools never sees, handles, or stores raw credentials. Each
|
|
9
23
|
* CLI manages its own tokens; we only trigger its login. (This is what keeps the
|
|
10
24
|
* "use your subscription, no API keys" model honest.)
|
|
@@ -12,47 +26,138 @@
|
|
|
12
26
|
import { execa } from 'execa';
|
|
13
27
|
import { detectProvider, getInstallCommand } from '../providers/detect.js';
|
|
14
28
|
import { bold, dim, green, red } from '../ui/theme.js';
|
|
15
|
-
/** Each provider's
|
|
29
|
+
/** Each provider's default (browser/localhost) sign-in command. */
|
|
16
30
|
const LOGIN_COMMAND = {
|
|
17
31
|
claude: { bin: 'claude', args: ['auth', 'login'] },
|
|
18
32
|
codex: { bin: 'codex', args: ['login'] },
|
|
33
|
+
// opencode ships free models — no credentials required. `opencode auth login -p <provider>`
|
|
34
|
+
// is only needed for premium providers. We default to no-op by pointing at `auth list`
|
|
35
|
+
// so the user sees configured credentials without being forced through a login flow.
|
|
36
|
+
opencode: { bin: 'opencode', args: ['auth', 'list'] },
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Each provider's no-localhost ("code") sign-in command, plus the human steps
|
|
40
|
+
* we print before handing over the terminal so the user knows what to expect.
|
|
41
|
+
*/
|
|
42
|
+
const LOGIN_CODE_COMMAND = {
|
|
43
|
+
claude: {
|
|
44
|
+
bin: 'claude',
|
|
45
|
+
args: ['setup-token'],
|
|
46
|
+
guidance: 'A sign-in link will appear below.\n' +
|
|
47
|
+
' 1. Open it in any browser and sign in at claude.ai.\n' +
|
|
48
|
+
' 2. Copy the authorization code it shows you.\n' +
|
|
49
|
+
' 3. Paste the code back here at the prompt and press Enter.',
|
|
50
|
+
},
|
|
51
|
+
codex: {
|
|
52
|
+
bin: 'codex',
|
|
53
|
+
args: ['login', '--device-auth'],
|
|
54
|
+
guidance: 'A URL and a one-time code will appear below.\n' +
|
|
55
|
+
' 1. On any device, open the URL.\n' +
|
|
56
|
+
' 2. Enter the code shown and authorize your ChatGPT account.\n' +
|
|
57
|
+
' 3. Sign-in completes here automatically once authorized.',
|
|
58
|
+
},
|
|
59
|
+
opencode: {
|
|
60
|
+
bin: 'opencode',
|
|
61
|
+
args: ['auth', 'list'],
|
|
62
|
+
guidance: 'opencode ships free models with no credentials required.\n' +
|
|
63
|
+
' To add a premium provider, run:\n' +
|
|
64
|
+
' opencode auth login -p <provider> -m <method>\n' +
|
|
65
|
+
' e.g. opencode auth login -p anthropic -m apikey',
|
|
66
|
+
},
|
|
19
67
|
};
|
|
20
68
|
export function isProviderId(value) {
|
|
21
|
-
return value === 'claude' || value === 'codex';
|
|
69
|
+
return value === 'claude' || value === 'codex' || value === 'opencode';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Decide whether the current environment can actually reach a localhost OAuth
|
|
73
|
+
* callback / open a browser. Pure (env + platform in, boolean out) so it is
|
|
74
|
+
* hermetically testable.
|
|
75
|
+
*
|
|
76
|
+
* Returns true for environments where the browser/localhost flow typically
|
|
77
|
+
* fails and the code method should be preferred:
|
|
78
|
+
* - Known cloud IDEs / containers (Replit, Codespaces, Gitpod).
|
|
79
|
+
* - SSH sessions (no local browser).
|
|
80
|
+
* - Linux with no X11/Wayland display (headless box — nothing to open).
|
|
81
|
+
*/
|
|
82
|
+
export function isHeadlessEnv(env, platform) {
|
|
83
|
+
if (env['REPL_ID'] !== undefined ||
|
|
84
|
+
env['REPLIT_DEV_DOMAIN'] !== undefined ||
|
|
85
|
+
env['CODESPACES'] !== undefined ||
|
|
86
|
+
env['GITPOD_WORKSPACE_ID'] !== undefined) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
if (env['SSH_CONNECTION'] !== undefined || env['SSH_TTY'] !== undefined) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
if (platform === 'linux' &&
|
|
93
|
+
(env['DISPLAY'] === undefined || env['DISPLAY'] === '') &&
|
|
94
|
+
(env['WAYLAND_DISPLAY'] === undefined || env['WAYLAND_DISPLAY'] === '')) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Resolve the sign-in method to use. An explicit choice always wins; otherwise
|
|
101
|
+
* fall back to environment auto-detection (headless → 'code', else 'browser').
|
|
102
|
+
* Pure / testable.
|
|
103
|
+
*/
|
|
104
|
+
export function resolveLoginMethod(explicit, env, platform) {
|
|
105
|
+
if (explicit !== undefined)
|
|
106
|
+
return explicit;
|
|
107
|
+
return isHeadlessEnv(env, platform) ? 'code' : 'browser';
|
|
22
108
|
}
|
|
23
109
|
/**
|
|
24
110
|
* Run the interactive sign-in flow for one provider (or all installed providers
|
|
25
111
|
* when no argument is given). Returns 0 on success, 1 only for an invalid
|
|
26
112
|
* argument — individual sign-in failures are reported but do not fail the command.
|
|
113
|
+
*
|
|
114
|
+
* @param opts.method - Force 'browser' or 'code'. When omitted, the method is
|
|
115
|
+
* auto-detected from the environment via {@link resolveLoginMethod}.
|
|
27
116
|
*/
|
|
28
|
-
export async function runLogin(out, providerArg) {
|
|
117
|
+
export async function runLogin(out, providerArg, opts) {
|
|
29
118
|
let targets;
|
|
30
119
|
if (providerArg !== undefined) {
|
|
31
120
|
if (!isProviderId(providerArg)) {
|
|
32
|
-
out.write(red(`Unknown provider "${providerArg}". Use: claude or
|
|
121
|
+
out.write(red(`Unknown provider "${providerArg}". Use: claude, codex, or opencode.\n`, out.color));
|
|
33
122
|
return 1;
|
|
34
123
|
}
|
|
35
124
|
targets = [providerArg];
|
|
36
125
|
}
|
|
37
126
|
else {
|
|
38
|
-
targets = ['claude', 'codex'];
|
|
127
|
+
targets = ['claude', 'codex', 'opencode'];
|
|
39
128
|
}
|
|
129
|
+
const method = resolveLoginMethod(opts?.method, process.env, process.platform);
|
|
40
130
|
for (const id of targets) {
|
|
41
131
|
const status = await detectProvider(id);
|
|
42
132
|
if (!status.installed) {
|
|
43
133
|
out.write(dim(`${id}: not installed — skipping. Install with: ${getInstallCommand(id)}\n`, out.color));
|
|
44
134
|
continue;
|
|
45
135
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
136
|
+
// stdio:'inherit' hands the terminal to the provider CLI so its OAuth /
|
|
137
|
+
// device / paste flow runs in place. reject:false so we report rather than throw.
|
|
138
|
+
let result;
|
|
139
|
+
if (method === 'code') {
|
|
140
|
+
const { bin, args, guidance } = LOGIN_CODE_COMMAND[id];
|
|
141
|
+
out.write(bold(`\nSigning in to ${id} — code method (no localhost needed).\n`, out.color));
|
|
142
|
+
out.write(dim(guidance + '\n', out.color));
|
|
143
|
+
result = await execa(bin, [...args], { stdio: 'inherit', reject: false });
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const { bin, args } = LOGIN_COMMAND[id];
|
|
147
|
+
out.write(bold(`\nSigning in to ${id} — a browser window may open…\n`, out.color));
|
|
148
|
+
result = await execa(bin, [...args], { stdio: 'inherit', reject: false });
|
|
149
|
+
}
|
|
51
150
|
if (result.exitCode === 0) {
|
|
52
151
|
out.write(green(`✓ ${id} sign-in complete.\n`, out.color));
|
|
53
152
|
}
|
|
54
153
|
else {
|
|
55
154
|
out.write(red(`✗ ${id} sign-in did not complete (exit ${result.exitCode ?? 'unknown'}).\n`, out.color));
|
|
155
|
+
// The classic container failure mode is a dead localhost callback. Point
|
|
156
|
+
// the user at the code method, which sidesteps localhost entirely.
|
|
157
|
+
if (method === 'browser') {
|
|
158
|
+
out.write(dim(`If the browser/localhost step failed, try the code method instead:\n` +
|
|
159
|
+
` myshell-tools login ${id} --code\n`, out.color));
|
|
160
|
+
}
|
|
56
161
|
}
|
|
57
162
|
}
|
|
58
163
|
return 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
package/dist/core/assess.js
CHANGED
|
@@ -12,70 +12,10 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Pure module: no I/O, no time, no randomness.
|
|
14
14
|
*/
|
|
15
|
+
import { lastJsonObjectWithKey } from './json-envelope.js';
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
17
|
// Helpers
|
|
17
18
|
// ---------------------------------------------------------------------------
|
|
18
|
-
/**
|
|
19
|
-
* Attempt to extract the last JSON object from `text` that looks like a
|
|
20
|
-
* confidence envelope. Returns the raw parsed object or null.
|
|
21
|
-
*
|
|
22
|
-
* Strategy: scan backwards for the last `{...}` block that contains at least
|
|
23
|
-
* the `confidence` key, then try to parse it. This is robust to:
|
|
24
|
-
* - trailing whitespace / newlines
|
|
25
|
-
* - the model emitting extra text after the envelope (we pick the LAST match)
|
|
26
|
-
* - duplicate envelopes (last one wins — the model may have regenerated it)
|
|
27
|
-
* - garbage / truncated JSON elsewhere in the output
|
|
28
|
-
*/
|
|
29
|
-
function extractEnvelope(text) {
|
|
30
|
-
// Find all candidates: substrings that start with '{' and end with '}'
|
|
31
|
-
// We do this by iterating over all '{' positions and trying to match the
|
|
32
|
-
// closing '}', handling depth. We collect all valid JSON objects and
|
|
33
|
-
// return the last one that has a 'confidence' key.
|
|
34
|
-
const candidates = [];
|
|
35
|
-
let i = 0;
|
|
36
|
-
while (i < text.length) {
|
|
37
|
-
const start = text.indexOf('{', i);
|
|
38
|
-
if (start === -1)
|
|
39
|
-
break;
|
|
40
|
-
// Walk forward tracking brace depth to find the matching '}'
|
|
41
|
-
let depth = 0;
|
|
42
|
-
let j = start;
|
|
43
|
-
let foundClose = false;
|
|
44
|
-
while (j < text.length) {
|
|
45
|
-
if (text[j] === '{') {
|
|
46
|
-
depth++;
|
|
47
|
-
}
|
|
48
|
-
else if (text[j] === '}') {
|
|
49
|
-
depth--;
|
|
50
|
-
if (depth === 0) {
|
|
51
|
-
foundClose = true;
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
j++;
|
|
56
|
-
}
|
|
57
|
-
if (foundClose) {
|
|
58
|
-
const candidate = text.slice(start, j + 1);
|
|
59
|
-
try {
|
|
60
|
-
const parsed = JSON.parse(candidate);
|
|
61
|
-
if (parsed !== null &&
|
|
62
|
-
typeof parsed === 'object' &&
|
|
63
|
-
!Array.isArray(parsed) &&
|
|
64
|
-
'confidence' in parsed) {
|
|
65
|
-
candidates.push(parsed);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
// Not valid JSON — skip
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
i = start + 1;
|
|
73
|
-
}
|
|
74
|
-
if (candidates.length === 0)
|
|
75
|
-
return null;
|
|
76
|
-
// Return the last valid envelope (handles duplicate/regenerated envelopes)
|
|
77
|
-
return candidates[candidates.length - 1] ?? null;
|
|
78
|
-
}
|
|
79
19
|
/**
|
|
80
20
|
* Clamp a number to [0, 1].
|
|
81
21
|
*/
|
|
@@ -119,7 +59,7 @@ export function assess(output) {
|
|
|
119
59
|
}
|
|
120
60
|
let envelope;
|
|
121
61
|
try {
|
|
122
|
-
envelope =
|
|
62
|
+
envelope = lastJsonObjectWithKey(output, 'confidence');
|
|
123
63
|
}
|
|
124
64
|
catch {
|
|
125
65
|
return NULL_RESULT;
|