@totalreclaw/totalreclaw 3.3.1-rc.13 → 3.3.1-rc.15
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 +94 -0
- package/config.ts +11 -0
- package/embedding.ts +40 -4
- package/index.ts +6 -0
- package/package.json +14 -4
- package/qa-bug-report.ts +84 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,100 @@ All notable changes to `@totalreclaw/totalreclaw` (the OpenClaw plugin) are docu
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [3.3.1-rc.15] — 2026-04-24
|
|
8
|
+
|
|
9
|
+
Install-time unblock for bandwidth-constrained hosts. Lazy-loads the ONNX
|
|
10
|
+
runtime instead of forcing a ~216MB download during `openclaw plugins
|
|
11
|
+
install`.
|
|
12
|
+
|
|
13
|
+
### Lazy-loaded ONNX / `@huggingface/transformers`
|
|
14
|
+
|
|
15
|
+
`openclaw plugins install @totalreclaw/totalreclaw` on slow hosts (VPNs,
|
|
16
|
+
CI containers with limited bandwidth, metered connections) was exceeding
|
|
17
|
+
the plugin-install timeout mid-download and getting SIGTERM'd, leaving
|
|
18
|
+
the plugin partially installed. Root cause: `@huggingface/transformers`
|
|
19
|
+
was a direct `dependency`, which transitively pulled
|
|
20
|
+
`onnxruntime-node`'s postinstall binary fetch (~216MB from GitHub
|
|
21
|
+
Releases).
|
|
22
|
+
|
|
23
|
+
- `@huggingface/transformers` and `onnxruntime-node` moved from
|
|
24
|
+
`dependencies` to optional `peerDependencies`
|
|
25
|
+
(`peerDependenciesMeta.<name>.optional: true`). npm v7+ and the
|
|
26
|
+
OpenClaw install path (`--legacy-peer-deps`) both skip these by
|
|
27
|
+
default — plugin install is now lean.
|
|
28
|
+
- `embedding.ts` converts the static
|
|
29
|
+
`import { AutoTokenizer, AutoModel, pipeline } from
|
|
30
|
+
'@huggingface/transformers'` into a dynamic `await import(...)` on
|
|
31
|
+
the first `generateEmbedding` call. If the optional peer is missing,
|
|
32
|
+
the error surfaces a clear install hint:
|
|
33
|
+
`npm install @huggingface/transformers`.
|
|
34
|
+
- New regression test `lazy-load-embedding.test.ts` asserts the
|
|
35
|
+
invariants (no top-level static runtime import; heavy packages not in
|
|
36
|
+
`dependencies`; peer-dep `optional` flag set) so a future refactor
|
|
37
|
+
can't silently reintroduce the install-time block.
|
|
38
|
+
|
|
39
|
+
**User impact:** users on constrained hosts can now install the plugin
|
|
40
|
+
without the 216MB download. Users who want semantic memory (recall /
|
|
41
|
+
search over encrypted facts) install `@huggingface/transformers`
|
|
42
|
+
separately — one-time, resumable if it times out.
|
|
43
|
+
|
|
44
|
+
Fixes [issue #92][i92] (QA bug 6 of 10, split from #84).
|
|
45
|
+
|
|
46
|
+
[i92]: https://github.com/p-diogo/totalreclaw-internal/issues/92
|
|
47
|
+
|
|
48
|
+
## [3.3.1-rc.14] — 2026-04-24
|
|
49
|
+
|
|
50
|
+
Coordinated version bump with Python `2.3.1rc14`. Two narrow bug fixes
|
|
51
|
+
found during rc.13 user QA on 2026-04-24:
|
|
52
|
+
|
|
53
|
+
### RC-gated QA bug tool — target-repo hardening
|
|
54
|
+
|
|
55
|
+
`totalreclaw_report_qa_bug` now refuses to file to any repo that isn't
|
|
56
|
+
internal. rc.13 user QA surfaced agent-filed bug reports leaking to the
|
|
57
|
+
public `p-diogo/totalreclaw` tracker despite the tool's default target
|
|
58
|
+
being `p-diogo/totalreclaw-internal`.
|
|
59
|
+
|
|
60
|
+
- New env var: `TOTALRECLAW_QA_REPO` lets operators point the tool at a
|
|
61
|
+
private fork. The default stays `p-diogo/totalreclaw-internal`.
|
|
62
|
+
- New `resolveQaRepo(...)` guard: rejects any slug that is on the
|
|
63
|
+
public-repo denylist (includes `p-diogo/totalreclaw`,
|
|
64
|
+
`...-website`, `...-relay`, `...-plugin`, `...-hermes`) OR does not
|
|
65
|
+
end in `-internal`. The check runs before the HTTP POST is
|
|
66
|
+
constructed, so rejection never leaves the client.
|
|
67
|
+
- `CONFIG.qaRepoOverride` surfaces the env var through `config.ts`
|
|
68
|
+
(keeps scanner-sensitive `process.env` reads centralized).
|
|
69
|
+
- Regression test in `qa-bug-report.test.ts` mocks the public slug
|
|
70
|
+
and asserts `fetch` is NEVER called.
|
|
71
|
+
|
|
72
|
+
Labels on filing unchanged — still emits `qa-bug`, `pending-triage`,
|
|
73
|
+
`severity:<...>`, `component:<...>`, `rc:<...>`.
|
|
74
|
+
|
|
75
|
+
### Relay pair page — PIN paste button UX
|
|
76
|
+
|
|
77
|
+
The paste button on the step-1 PIN screen was silently failing under
|
|
78
|
+
certain browser states. rc.14 rewrites the handler with a proper
|
|
79
|
+
error taxonomy:
|
|
80
|
+
|
|
81
|
+
- Capability probe up front — `navigator.clipboard.readText` missing →
|
|
82
|
+
clear "Paste unavailable on this browser" toast.
|
|
83
|
+
- `NotAllowedError` → "Clipboard access denied — type the 6 digits
|
|
84
|
+
manually" (covers iOS Safari permission denial).
|
|
85
|
+
- Empty clipboard → "Clipboard is empty — copy the PIN from your chat
|
|
86
|
+
first".
|
|
87
|
+
- Non-digit content → "Clipboard has no digits — copy the 6-digit PIN
|
|
88
|
+
first".
|
|
89
|
+
- Every failure path focuses the first PIN cell so the user can fall
|
|
90
|
+
through to manual typing without another click.
|
|
91
|
+
- Errors log to `console.warn` with name + message so future failures
|
|
92
|
+
are diagnosable from browser devtools.
|
|
93
|
+
|
|
94
|
+
The mockup at `docs/mockups/rc13-pair-wizard/wizard.js` gets the same
|
|
95
|
+
rewrite for parity — the relay's `scripts/sync-pair-preview.mjs`
|
|
96
|
+
regenerates `/pair-preview/` from this source.
|
|
97
|
+
|
|
98
|
+
Fix also applies to the "Paste all 12 words" import-grid button on the
|
|
99
|
+
relay production page (same taxonomy, same focus-fallback).
|
|
100
|
+
|
|
7
101
|
## [3.3.1-rc.13] — 2026-04-24
|
|
8
102
|
|
|
9
103
|
Coordinated version bump with Python `2.3.1rc13`. No substantive
|
package/config.ts
CHANGED
|
@@ -203,6 +203,17 @@ export const CONFIG = {
|
|
|
203
203
|
return process.env.TOTALRECLAW_QA_GITHUB_TOKEN || process.env.GITHUB_TOKEN || '';
|
|
204
204
|
},
|
|
205
205
|
|
|
206
|
+
// 3.3.1-rc.14: optional target-repo override for the RC-gated QA
|
|
207
|
+
// bug-report tool. The `qa-bug-report` module enforces a
|
|
208
|
+
// "slug ends in `-internal`" rule on whatever is resolved here, so
|
|
209
|
+
// this override is only useful for forks / mirrors of the internal
|
|
210
|
+
// tracker. Leaving unset uses the production default
|
|
211
|
+
// (`p-diogo/totalreclaw-internal`). Read via getter so operators can
|
|
212
|
+
// flip the var at runtime.
|
|
213
|
+
get qaRepoOverride(): string {
|
|
214
|
+
return process.env.TOTALRECLAW_QA_REPO || '';
|
|
215
|
+
},
|
|
216
|
+
|
|
206
217
|
// Paths
|
|
207
218
|
home,
|
|
208
219
|
billingCachePath: path.join(home, '.totalreclaw', 'billing-cache.json'),
|
package/embedding.ts
CHANGED
|
@@ -8,11 +8,44 @@
|
|
|
8
8
|
* embedding model breaks search across an existing vault, so the
|
|
9
9
|
* `TOTALRECLAW_EMBEDDING_MODEL` user-facing env var was removed in v1.
|
|
10
10
|
*
|
|
11
|
-
* Dependencies: @huggingface/transformers
|
|
11
|
+
* Dependencies: @huggingface/transformers is declared as an optional peer
|
|
12
|
+
* dependency. It is lazy-loaded on the first `generateEmbedding` call so
|
|
13
|
+
* `openclaw plugins install @totalreclaw/totalreclaw` does not block on the
|
|
14
|
+
* ~216MB onnxruntime-node native-binary download. Install it separately to
|
|
15
|
+
* enable semantic search: `npm install @huggingface/transformers`.
|
|
12
16
|
*/
|
|
13
17
|
|
|
18
|
+
// Type-only import — erased at compile time, no runtime dep on the package.
|
|
14
19
|
// @ts-ignore - @huggingface/transformers types may not be perfect
|
|
15
|
-
import {
|
|
20
|
+
import type { FeatureExtractionPipeline } from '@huggingface/transformers';
|
|
21
|
+
|
|
22
|
+
type HFTransformers = typeof import('@huggingface/transformers');
|
|
23
|
+
|
|
24
|
+
/** Cached module handle after first successful dynamic import. */
|
|
25
|
+
let transformersModule: HFTransformers | null = null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Lazily import @huggingface/transformers. The package is declared as an
|
|
29
|
+
* optional peer dependency so the plugin installs on bandwidth-constrained
|
|
30
|
+
* hosts without pulling the onnxruntime-node native binary (~216MB). On first
|
|
31
|
+
* use, try to load it; if the user never installed it, surface a clear
|
|
32
|
+
* actionable error with the install command.
|
|
33
|
+
*/
|
|
34
|
+
async function loadTransformers(): Promise<HFTransformers> {
|
|
35
|
+
if (transformersModule) return transformersModule;
|
|
36
|
+
try {
|
|
37
|
+
// @ts-ignore - dynamic import target is the optional peer dep
|
|
38
|
+
transformersModule = (await import('@huggingface/transformers')) as HFTransformers;
|
|
39
|
+
return transformersModule;
|
|
40
|
+
} catch (err) {
|
|
41
|
+
const hint =
|
|
42
|
+
'[TotalReclaw] @huggingface/transformers is not installed. ' +
|
|
43
|
+
'Semantic memory requires it (one-time ~216MB download of ONNX runtime + model). ' +
|
|
44
|
+
'Install with: npm install @huggingface/transformers';
|
|
45
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
46
|
+
throw new Error(`${hint}\nUnderlying load error: ${detail}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
16
49
|
|
|
17
50
|
interface ModelConfig {
|
|
18
51
|
id: string;
|
|
@@ -45,14 +78,17 @@ let activeModel: ModelConfig | null = null;
|
|
|
45
78
|
/**
|
|
46
79
|
* Generate an embedding vector for the given text.
|
|
47
80
|
*
|
|
48
|
-
* On first call,
|
|
49
|
-
*
|
|
81
|
+
* On first call, dynamically imports @huggingface/transformers (requires it
|
|
82
|
+
* to be installed — see module docstring) and downloads the ONNX model
|
|
83
|
+
* (cached after download). Subsequent calls reuse the loaded module + model
|
|
84
|
+
* and run in ~100ms.
|
|
50
85
|
*/
|
|
51
86
|
export async function generateEmbedding(
|
|
52
87
|
text: string,
|
|
53
88
|
options?: { isQuery?: boolean },
|
|
54
89
|
): Promise<number[]> {
|
|
55
90
|
if (!activeModel) {
|
|
91
|
+
const { AutoTokenizer, AutoModel, pipeline } = await loadTransformers();
|
|
56
92
|
activeModel = getModelConfig();
|
|
57
93
|
console.error(`[TotalReclaw] Downloading embedding model (${activeModel.size}, one-time setup)...`);
|
|
58
94
|
console.error('[TotalReclaw] This enables semantic search across your encrypted memories.');
|
package/index.ts
CHANGED
|
@@ -5280,10 +5280,16 @@ const plugin = {
|
|
|
5280
5280
|
details: { error: 'missing_github_token' },
|
|
5281
5281
|
};
|
|
5282
5282
|
}
|
|
5283
|
+
// rc.14 — `repo` is resolved inside `postQaBugIssue` via
|
|
5284
|
+
// `resolveQaRepo(...)`, which reads `TOTALRECLAW_QA_REPO` and
|
|
5285
|
+
// refuses any slug that isn't a `-internal` fork. Pass the
|
|
5286
|
+
// config-surfaced override so env reads stay in config.ts.
|
|
5287
|
+
const repoOverride = CONFIG.qaRepoOverride || undefined;
|
|
5283
5288
|
const result = await postQaBugIssue(
|
|
5284
5289
|
params as unknown as import('./qa-bug-report.js').QaBugArgs,
|
|
5285
5290
|
{
|
|
5286
5291
|
githubToken: token,
|
|
5292
|
+
repo: repoOverride,
|
|
5287
5293
|
logger: api.logger,
|
|
5288
5294
|
},
|
|
5289
5295
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@totalreclaw/totalreclaw",
|
|
3
|
-
"version": "3.3.1-rc.
|
|
3
|
+
"version": "3.3.1-rc.15",
|
|
4
4
|
"description": "End-to-end encrypted, agent-portable memory for OpenClaw and any LLM-agent runtime. XChaCha20-Poly1305 with protobuf v4 + on-chain Memory Taxonomy v1 (claim / preference / directive / commitment / episode / summary).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -31,16 +31,26 @@
|
|
|
31
31
|
"author": "TotalReclaw Team",
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@huggingface/transformers": "^4.0.1",
|
|
35
34
|
"@totalreclaw/client": "^1.2.0",
|
|
36
35
|
"@totalreclaw/core": "^2.1.1",
|
|
37
36
|
"@types/qrcode": "^1.5.6",
|
|
38
37
|
"@types/ws": "^8.5.12",
|
|
39
|
-
"onnxruntime-node": "^1.24.0",
|
|
40
38
|
"qrcode": "^1.5.4",
|
|
41
39
|
"qrcode-terminal": "^0.12.0",
|
|
42
40
|
"ws": "^8.18.3"
|
|
43
41
|
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@huggingface/transformers": "^4.0.1",
|
|
44
|
+
"onnxruntime-node": "^1.24.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"@huggingface/transformers": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"onnxruntime-node": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
44
54
|
"files": [
|
|
45
55
|
"*.ts",
|
|
46
56
|
"import-adapters/",
|
|
@@ -54,7 +64,7 @@
|
|
|
54
64
|
"skill.json"
|
|
55
65
|
],
|
|
56
66
|
"scripts": {
|
|
57
|
-
"test": "npx tsx manifest-shape.test.ts && npx tsx config-schema.test.ts && npx tsx llm-profile-reader.test.ts && npx tsx llm-client.test.ts && npx tsx llm-client-retry.test.ts && npx tsx gateway-url.test.ts && npx tsx retype-setscope.test.ts && npx tsx tool-gating.test.ts && npx tsx onboarding-noninteractive.test.ts && npx tsx pair-cli-json.test.ts && npx tsx pair-qr.test.ts && npx tsx pair-remote-client.test.ts && npx tsx qa-bug-report.test.ts && npx tsx nonce-serialization.test.ts && npx tsx phrase-safety-registry.test.ts",
|
|
67
|
+
"test": "npx tsx manifest-shape.test.ts && npx tsx config-schema.test.ts && npx tsx llm-profile-reader.test.ts && npx tsx llm-client.test.ts && npx tsx llm-client-retry.test.ts && npx tsx gateway-url.test.ts && npx tsx retype-setscope.test.ts && npx tsx tool-gating.test.ts && npx tsx onboarding-noninteractive.test.ts && npx tsx pair-cli-json.test.ts && npx tsx pair-qr.test.ts && npx tsx pair-remote-client.test.ts && npx tsx qa-bug-report.test.ts && npx tsx nonce-serialization.test.ts && npx tsx phrase-safety-registry.test.ts && npx tsx lazy-load-embedding.test.ts",
|
|
58
68
|
"check-scanner": "node ../scripts/check-scanner.mjs",
|
|
59
69
|
"prepublishOnly": "node ../scripts/check-scanner.mjs"
|
|
60
70
|
},
|
package/qa-bug-report.ts
CHANGED
|
@@ -18,6 +18,13 @@
|
|
|
18
18
|
* POST. BIP-39 phrases, API keys, Telegram bot tokens, and bearer tokens
|
|
19
19
|
* in headers all become `<REDACTED>` in the posted issue. Refer to
|
|
20
20
|
* `redactSecrets()` for the exact rule set.
|
|
21
|
+
*
|
|
22
|
+
* Target repo safety: the default target is `p-diogo/totalreclaw-internal`.
|
|
23
|
+
* Operators can override via the `TOTALRECLAW_QA_REPO` env var, but only
|
|
24
|
+
* to another slug ending in `-internal`. Any other slug — including the
|
|
25
|
+
* public `p-diogo/totalreclaw` — is rejected with a loud error. rc.13 QA
|
|
26
|
+
* surfaced a repo-slug drift where QA findings leaked to the public
|
|
27
|
+
* tracker; rc.14 adds this fail-loud guard.
|
|
21
28
|
*/
|
|
22
29
|
|
|
23
30
|
// ---------------------------------------------------------------------------
|
|
@@ -148,7 +155,12 @@ export interface QaBugArgs {
|
|
|
148
155
|
export interface QaBugDeps {
|
|
149
156
|
/** GitHub personal-access token with `repo` scope. */
|
|
150
157
|
githubToken: string;
|
|
151
|
-
/**
|
|
158
|
+
/**
|
|
159
|
+
* Repo to post to. Defaults to `resolveQaRepo(null)` → reads
|
|
160
|
+
* `TOTALRECLAW_QA_REPO` env var and falls back to
|
|
161
|
+
* `p-diogo/totalreclaw-internal`. Pass a slug (tests only) to
|
|
162
|
+
* bypass env-var lookup.
|
|
163
|
+
*/
|
|
152
164
|
repo?: string;
|
|
153
165
|
/**
|
|
154
166
|
* Abstract fetch for testing — defaults to global `fetch`. Intentionally
|
|
@@ -160,6 +172,76 @@ export interface QaBugDeps {
|
|
|
160
172
|
logger?: { info: (msg: string) => void; warn: (msg: string) => void };
|
|
161
173
|
}
|
|
162
174
|
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Target repo guard — fail-loud on any repo that isn't the internal tracker.
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
|
|
179
|
+
export const DEFAULT_QA_REPO = 'p-diogo/totalreclaw-internal';
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Known-public repo slugs that must never receive QA bug reports. The
|
|
183
|
+
* structural rule (`endsWith('-internal')`) below should already block
|
|
184
|
+
* these, but the explicit denylist is a belt-and-braces safety against
|
|
185
|
+
* a future rename that accidentally drops the `-internal` suffix.
|
|
186
|
+
*/
|
|
187
|
+
export const PUBLIC_REPOS_DENYLIST: ReadonlySet<string> = new Set([
|
|
188
|
+
'p-diogo/totalreclaw',
|
|
189
|
+
'p-diogo/totalreclaw-website',
|
|
190
|
+
'p-diogo/totalreclaw-relay',
|
|
191
|
+
'p-diogo/totalreclaw-plugin',
|
|
192
|
+
'p-diogo/totalreclaw-hermes',
|
|
193
|
+
]);
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Resolve the target repo for a QA bug filing.
|
|
197
|
+
*
|
|
198
|
+
* Precedence: explicit override → `TOTALRECLAW_QA_REPO` env → default.
|
|
199
|
+
* Throws if the slug is on the public denylist or does not end in
|
|
200
|
+
* `-internal`. rc.13 QA found agent-filed bug reports leaking to the
|
|
201
|
+
* public repo; this guard makes any such drift fail loudly rather than
|
|
202
|
+
* silently leak RC ship-stopper detail.
|
|
203
|
+
*
|
|
204
|
+
* `TOTALRECLAW_QA_REPO` is the documented override var. The env-var
|
|
205
|
+
* read lives in `config.ts` (CONFIG.qaRepoOverride) so this module
|
|
206
|
+
* never touches process environment directly — keeps the plugin
|
|
207
|
+
* scanner-sim clean because this file also performs a GitHub HTTPS
|
|
208
|
+
* request (env + network in the same file would trip OpenClaw's
|
|
209
|
+
* env-harvesting heuristic).
|
|
210
|
+
*
|
|
211
|
+
* Pass the env-resolved slug (or `null`/empty for default) as
|
|
212
|
+
* `override`. Tests can inject via the second arg.
|
|
213
|
+
*/
|
|
214
|
+
export function resolveQaRepo(
|
|
215
|
+
override?: string | null,
|
|
216
|
+
env?: Record<string, string | undefined>,
|
|
217
|
+
): string {
|
|
218
|
+
// `env` is only for test injection — production callers should
|
|
219
|
+
// pre-resolve the env value via CONFIG.qaRepoOverride and pass it as
|
|
220
|
+
// `override`. The env lookup is a last-resort fallback that works in
|
|
221
|
+
// Node but is NEVER the primary path in production.
|
|
222
|
+
const envOverride = env ? env.TOTALRECLAW_QA_REPO : undefined;
|
|
223
|
+
const raw = (override || envOverride || DEFAULT_QA_REPO).trim();
|
|
224
|
+
if (!raw || !raw.includes('/')) {
|
|
225
|
+
throw new Error(`invalid QA repo slug '${raw}': expected 'owner/name' format`);
|
|
226
|
+
}
|
|
227
|
+
if (PUBLIC_REPOS_DENYLIST.has(raw)) {
|
|
228
|
+
throw new Error(
|
|
229
|
+
`refusing to file QA bug to PUBLIC repo '${raw}'. ` +
|
|
230
|
+
'QA bug reports contain RC ship-stopper detail that must not ' +
|
|
231
|
+
"leak to public. Set TOTALRECLAW_QA_REPO to a repo ending in " +
|
|
232
|
+
"'-internal' (e.g. p-diogo/totalreclaw-internal).",
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
if (!raw.endsWith('-internal')) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
`refusing to file QA bug to repo '${raw}': slug must end in ` +
|
|
238
|
+
"'-internal' (structural safety rule). Override via " +
|
|
239
|
+
'TOTALRECLAW_QA_REPO only to another internal fork.',
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
return raw;
|
|
243
|
+
}
|
|
244
|
+
|
|
163
245
|
const VALID_INTEGRATIONS = new Set([
|
|
164
246
|
'plugin',
|
|
165
247
|
'hermes',
|
|
@@ -260,7 +342,7 @@ export async function postQaBugIssue(
|
|
|
260
342
|
if ('error' in validation) throw new Error(`invalid args: ${validation.error}`);
|
|
261
343
|
if (!deps.githubToken) throw new Error('githubToken is required');
|
|
262
344
|
|
|
263
|
-
const repo = deps.repo ??
|
|
345
|
+
const repo = resolveQaRepo(deps.repo ?? null);
|
|
264
346
|
const url = `https://api.github.com/repos/${repo}/issues`;
|
|
265
347
|
|
|
266
348
|
const title = `[qa-bug] ${redactSecrets(args.title)}`;
|