@trusty-squire/mcp 0.6.14-rc.2 → 0.6.14-rc.21
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/LICENSE +21 -0
- package/dist/api-client.d.ts +45 -0
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +43 -0
- package/dist/api-client.js.map +1 -1
- package/dist/bin.js +12 -0
- package/dist/bin.js.map +1 -1
- package/dist/bot/agent.d.ts +35 -2
- package/dist/bot/agent.d.ts.map +1 -1
- package/dist/bot/agent.js +525 -38
- package/dist/bot/agent.js.map +1 -1
- package/dist/bot/browser.d.ts +8 -0
- package/dist/bot/browser.d.ts.map +1 -1
- package/dist/bot/browser.js +193 -20
- package/dist/bot/browser.js.map +1 -1
- package/dist/bot/index.d.ts +4 -2
- package/dist/bot/index.d.ts.map +1 -1
- package/dist/bot/index.js +17 -3
- package/dist/bot/index.js.map +1 -1
- package/dist/bot/llm-client.d.ts +1 -1
- package/dist/bot/llm-client.d.ts.map +1 -1
- package/dist/bot/onboarding-capture.d.ts +3 -0
- package/dist/bot/onboarding-capture.d.ts.map +1 -1
- package/dist/bot/onboarding-capture.js +70 -5
- package/dist/bot/onboarding-capture.js.map +1 -1
- package/dist/bot/promote-to-skill.d.ts +2 -1
- package/dist/bot/promote-to-skill.d.ts.map +1 -1
- package/dist/bot/promote-to-skill.js +214 -29
- package/dist/bot/promote-to-skill.js.map +1 -1
- package/dist/bot/replay-skill.d.ts +4 -0
- package/dist/bot/replay-skill.d.ts.map +1 -1
- package/dist/bot/replay-skill.js +300 -3
- package/dist/bot/replay-skill.js.map +1 -1
- package/dist/install/cli.d.ts +16 -0
- package/dist/install/cli.d.ts.map +1 -1
- package/dist/install/cli.js +63 -6
- package/dist/install/cli.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +15 -5
- package/dist/session.js.map +1 -1
- package/dist/skill-cli/cli.d.ts +25 -0
- package/dist/skill-cli/cli.d.ts.map +1 -1
- package/dist/skill-cli/cli.js +558 -13
- package/dist/skill-cli/cli.js.map +1 -1
- package/dist/skill-cli/registry-http.d.ts +1 -0
- package/dist/skill-cli/registry-http.d.ts.map +1 -1
- package/dist/skill-cli/registry-http.js +3 -0
- package/dist/skill-cli/registry-http.js.map +1 -1
- package/dist/skill-cli/signing.d.ts +21 -0
- package/dist/skill-cli/signing.d.ts.map +1 -0
- package/dist/skill-cli/signing.js +71 -0
- package/dist/skill-cli/signing.js.map +1 -0
- package/dist/skill-registry-client.d.ts +2 -0
- package/dist/skill-registry-client.d.ts.map +1 -1
- package/dist/skill-registry-client.js +83 -36
- package/dist/skill-registry-client.js.map +1 -1
- package/dist/tools/extract-failures.d.ts +23 -0
- package/dist/tools/extract-failures.d.ts.map +1 -0
- package/dist/tools/extract-failures.js +108 -0
- package/dist/tools/extract-failures.js.map +1 -0
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/provision-any.d.ts +7 -0
- package/dist/tools/provision-any.d.ts.map +1 -1
- package/dist/tools/provision-any.js +346 -45
- package/dist/tools/provision-any.js.map +1 -1
- package/package.json +16 -15
package/dist/bot/index.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// Orchestrates browser + AI agent to sign up for any service
|
|
3
3
|
import { randomBytes } from "crypto";
|
|
4
4
|
import { BrowserController } from "./browser.js";
|
|
5
|
-
import { SignupAgent, LLMCallBudgetExceeded } from "./agent.js";
|
|
5
|
+
import { SignupAgent, LLMCallBudgetExceeded, } from "./agent.js";
|
|
6
6
|
import { withOAuthLock } from "./oauth-lock.js";
|
|
7
|
-
|
|
7
|
+
import { resetCaptureChain } from "./onboarding-capture.js";
|
|
8
|
+
export { LLMCallBudgetExceeded, };
|
|
8
9
|
export { withOAuthLock } from "./oauth-lock.js";
|
|
9
10
|
export { isOAuthProviderId } from "./oauth-providers.js";
|
|
10
11
|
export { BrowserController } from "./browser.js";
|
|
@@ -38,6 +39,12 @@ export class UniversalSignupBot {
|
|
|
38
39
|
return this.runSession(request);
|
|
39
40
|
}
|
|
40
41
|
async runSession(request) {
|
|
42
|
+
// rc.17 — reset the disk-capture chain state so this signup starts
|
|
43
|
+
// a fresh runId + empty chainHead. Otherwise back-to-back signups
|
|
44
|
+
// in the same bot process share runId and the second one's chain
|
|
45
|
+
// looks up the first one's last hash as prev_hash, failing
|
|
46
|
+
// verifyCaptureChain with prev_hash_mismatch.
|
|
47
|
+
resetCaptureChain();
|
|
41
48
|
// Defaults: humanize=true (production behavior — we want to pass
|
|
42
49
|
// Cloudflare/reCAPTCHA scoring). Tests can pass `humanize: false`
|
|
43
50
|
// to skip the behavior-simulation overhead.
|
|
@@ -46,7 +53,14 @@ export class UniversalSignupBot {
|
|
|
46
53
|
});
|
|
47
54
|
// request.llm is `LLMClient | LLMPair | undefined`; SignupAgent's
|
|
48
55
|
// constructor handles all three shapes.
|
|
49
|
-
const agent = new SignupAgent(browser, request.llm
|
|
56
|
+
const agent = new SignupAgent(browser, request.llm, {
|
|
57
|
+
...(request.extractFailureUploader !== undefined
|
|
58
|
+
? { extractFailureUploader: request.extractFailureUploader }
|
|
59
|
+
: {}),
|
|
60
|
+
...(request.roundUploader !== undefined
|
|
61
|
+
? { roundUploader: request.roundUploader }
|
|
62
|
+
: {}),
|
|
63
|
+
});
|
|
50
64
|
try {
|
|
51
65
|
await browser.start();
|
|
52
66
|
const email = request.email || this.generateEmail();
|
package/dist/bot/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bot/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,6DAA6D;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bot/index.ts"],"names":[],"mappings":"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"}
|
package/dist/bot/llm-client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../../src/bot/llm-client.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../../src/bot/llm-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { InteractiveElement } from "./browser.js";
|
|
2
2
|
import type { PostVerifyStep } from "./agent.js";
|
|
3
3
|
export declare const CAPTURE_FORMAT_VERSION: 1;
|
|
4
|
+
export declare function currentRunId(): string | undefined;
|
|
5
|
+
export declare function resetCaptureChain(): void;
|
|
4
6
|
export interface OnboardingRoundCapture {
|
|
5
7
|
service: string;
|
|
6
8
|
round: number;
|
|
@@ -26,6 +28,7 @@ export interface OnboardingCaseFile {
|
|
|
26
28
|
prev_hash: string | null;
|
|
27
29
|
content_hash: string;
|
|
28
30
|
}
|
|
31
|
+
export declare function resolveCaptureDir(): string | null;
|
|
29
32
|
export declare function captureOnboardingRound(entry: OnboardingRoundCapture): void;
|
|
30
33
|
export type ChainVerification = {
|
|
31
34
|
ok: true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding-capture.d.ts","sourceRoot":"","sources":["../../src/bot/onboarding-capture.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"onboarding-capture.d.ts","sourceRoot":"","sources":["../../src/bot/onboarding-capture.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjD,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC;AAUjD,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAWD,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAYD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,SAAS,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAGzC,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAID,MAAM,WAAW,kBAAkB;IACjC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACvC,SAAS,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACzC,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,IAAI,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AA2BD,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAUjD;AAkBD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAuC1E;AAWD,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,kBAAkB,EAAE,CAAA;CAAE,GAC1C;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EACF,iBAAiB,GACjB,eAAe,GACf,oBAAoB,GACpB,eAAe,GACf,WAAW,GACX,aAAa,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,iBAAiB,CA8FnB"}
|
|
@@ -28,10 +28,16 @@
|
|
|
28
28
|
// file. The promoter rejects unknown versions explicitly (E2) rather
|
|
29
29
|
// than failing midway through synthesis on a shape it can't parse.
|
|
30
30
|
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
31
|
+
// **0.6.14-rc.11 — default-on.** Previously inert unless
|
|
32
|
+
// TRUSTY_SQUIRE_ONBOARDING_CAPTURE named a directory; we kept finding
|
|
33
|
+
// stuck-loop bugs (e.g. Railway token-create click no-op) where no
|
|
34
|
+
// captures existed on disk because the env var was never set. Now
|
|
35
|
+
// defaults to `$HOME/.trusty-squire/corpus/onboarding` when the env
|
|
36
|
+
// var is unset or empty. Set the env to a custom path to override;
|
|
37
|
+
// set it to `off` to opt out entirely.
|
|
33
38
|
import { createHash } from "node:crypto";
|
|
34
39
|
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
40
|
+
import { homedir } from "node:os";
|
|
35
41
|
import { join } from "node:path";
|
|
36
42
|
// Capture format version. Bumped when round-shape changes incompatibly.
|
|
37
43
|
// The promoter rejects unknown versions (E2). Same-major minor changes
|
|
@@ -40,6 +46,26 @@ export const CAPTURE_FORMAT_VERSION = 1;
|
|
|
40
46
|
// One run-scoped id so a multi-service process (the batch harness)
|
|
41
47
|
// keeps each service's rounds grouped without collisions.
|
|
42
48
|
let runId;
|
|
49
|
+
// Read the in-process runId. Auto-promote needs to know which run's
|
|
50
|
+
// captures to promote after a successful signup. Returns undefined
|
|
51
|
+
// when no rounds have been captured yet — auto-promote then skips
|
|
52
|
+
// with a useful message rather than promoting nothing.
|
|
53
|
+
export function currentRunId() {
|
|
54
|
+
return runId;
|
|
55
|
+
}
|
|
56
|
+
// rc.17 — reset the per-process capture chain state at the start of a
|
|
57
|
+
// new signup. runId is module-scoped and was previously set once per
|
|
58
|
+
// process; back-to-back signups in one bot process then shared the
|
|
59
|
+
// same runId, so the second signup's round-0 looked up the first
|
|
60
|
+
// signup's last hash via chainHead and wrote a non-null prev_hash —
|
|
61
|
+
// which the chain verifier then rejected as prev_hash_mismatch (Run
|
|
62
|
+
// #3 of the Railway closed-loop test was the canonical case).
|
|
63
|
+
// Called from UniversalSignupBot.runSession() before the bot's first
|
|
64
|
+
// captureOnboardingRound call.
|
|
65
|
+
export function resetCaptureChain() {
|
|
66
|
+
runId = undefined;
|
|
67
|
+
chainHead.clear();
|
|
68
|
+
}
|
|
43
69
|
// Per-(service, runId) chain head. Each new round's `prev_hash` is the
|
|
44
70
|
// previous round's `content_hash`; round 0's `prev_hash` is null. The
|
|
45
71
|
// promoter walks the chain forward and rejects on any break.
|
|
@@ -60,11 +86,50 @@ function computeContentHash(payload) {
|
|
|
60
86
|
hasher.update(JSON.stringify(payload));
|
|
61
87
|
return hasher.digest("hex");
|
|
62
88
|
}
|
|
63
|
-
//
|
|
89
|
+
// Resolve the capture directory. Order:
|
|
90
|
+
// 1. Explicit env var (TRUSTY_SQUIRE_ONBOARDING_CAPTURE) — including
|
|
91
|
+
// the literal "off" / "0" / "false" which suppress capture.
|
|
92
|
+
// 2. Default fallback: `$HOME/.trusty-squire/corpus/onboarding`,
|
|
93
|
+
// EXCEPT under vitest (NODE_ENV=test or VITEST=true) where
|
|
94
|
+
// defaulting on would pollute every test runner's home dir with
|
|
95
|
+
// stray captures from agent-loop tests. Tests that exercise the
|
|
96
|
+
// capture explicitly set the env var via the withCaptureDir
|
|
97
|
+
// helper.
|
|
98
|
+
// Exported so the round-uploader (provision-any.ts) can read the same
|
|
99
|
+
// resolved path without re-implementing the policy.
|
|
100
|
+
export function resolveCaptureDir() {
|
|
101
|
+
const envValue = process.env.TRUSTY_SQUIRE_ONBOARDING_CAPTURE;
|
|
102
|
+
if (envValue !== undefined) {
|
|
103
|
+
const trimmed = envValue.trim();
|
|
104
|
+
if (trimmed.length === 0)
|
|
105
|
+
return isTestEnv() ? null : defaultCaptureDir();
|
|
106
|
+
if (trimmed === "off" || trimmed === "0" || trimmed === "false")
|
|
107
|
+
return null;
|
|
108
|
+
return trimmed;
|
|
109
|
+
}
|
|
110
|
+
if (isTestEnv())
|
|
111
|
+
return null;
|
|
112
|
+
return defaultCaptureDir();
|
|
113
|
+
}
|
|
114
|
+
function isTestEnv() {
|
|
115
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true";
|
|
116
|
+
}
|
|
117
|
+
function defaultCaptureDir() {
|
|
118
|
+
try {
|
|
119
|
+
const home = homedir();
|
|
120
|
+
if (home.length === 0)
|
|
121
|
+
return null;
|
|
122
|
+
return join(home, ".trusty-squire", "corpus", "onboarding");
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Dump one onboarding round to the capture directory.
|
|
64
129
|
// Best-effort: a capture failure must never break a signup run.
|
|
65
130
|
export function captureOnboardingRound(entry) {
|
|
66
|
-
const dir =
|
|
67
|
-
if (dir ===
|
|
131
|
+
const dir = resolveCaptureDir();
|
|
132
|
+
if (dir === null)
|
|
68
133
|
return;
|
|
69
134
|
try {
|
|
70
135
|
mkdirSync(dir, { recursive: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding-capture.js","sourceRoot":"","sources":["../../src/bot/onboarding-capture.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,4DAA4D;AAC5D,EAAE;AACF,sEAAsE;AACtE,gEAAgE;AAChE,uEAAuE;AACvE,iEAAiE;AACjE,yEAAyE;AACzE,EAAE;AACF,sEAAsE;AACtE,uEAAuE;AACvE,sEAAsE;AACtE,kEAAkE;AAClE,yCAAyC;AACzC,EAAE;AACF,yDAAyD;AACzD,oEAAoE;AACpE,uDAAuD;AACvD,oEAAoE;AACpE,mEAAmE;AACnE,8DAA8D;AAC9D,kEAAkE;AAClE,4DAA4D;AAC5D,6DAA6D;AAC7D,WAAW;AACX,EAAE;AACF,sEAAsE;AACtE,qEAAqE;AACrE,mEAAmE;AACnE,EAAE;AACF,oEAAoE;AACpE,
|
|
1
|
+
{"version":3,"file":"onboarding-capture.js","sourceRoot":"","sources":["../../src/bot/onboarding-capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,7 +25,7 @@ export type PromoteResult = {
|
|
|
25
25
|
export interface PromoteRejection {
|
|
26
26
|
kind: "rejected";
|
|
27
27
|
stage: "chain_verification" | "synthesis" | "schema_validation";
|
|
28
|
-
error_kind: "unknown_version" | "hash_mismatch" | "prev_hash_mismatch" | "missing_round" | "no_rounds" | "parse_error" | "no_extract_step" | "ambiguous_text_match" | "missing_text_hint" | "unsupported_step_kind" | "inventory_entry_not_found" | "credential_spec_inference_failed" | "schema_invalid";
|
|
28
|
+
error_kind: "unknown_version" | "hash_mismatch" | "prev_hash_mismatch" | "missing_round" | "no_rounds" | "parse_error" | "no_extract_step" | "ambiguous_text_match" | "missing_text_hint" | "unsupported_step_kind" | "inventory_entry_not_found" | "credential_spec_inference_failed" | "schema_invalid" | "duplicate_credential_produces" | "unparseable_credential_label";
|
|
29
29
|
message: string;
|
|
30
30
|
offending_round?: number;
|
|
31
31
|
offending_step?: number;
|
|
@@ -40,4 +40,5 @@ export interface PromoteRejection {
|
|
|
40
40
|
*/
|
|
41
41
|
export declare const SYNTHESIZER_VERSION: 1;
|
|
42
42
|
export declare function promoteToSkill(input: PromoteInput): PromoteResult;
|
|
43
|
+
export declare function deriveSkillId(candidate: Omit<Skill, "skill_id">): string;
|
|
43
44
|
//# sourceMappingURL=promote-to-skill.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promote-to-skill.d.ts","sourceRoot":"","sources":["../../src/bot/promote-to-skill.ts"],"names":[],"mappings":"AAqCA,OAAO,EAGL,KAAK,KAAK,EAIX,MAAM,4BAA4B,CAAC;AAUpC,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC5B,gBAAgB,CAAC;AAErB;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,oBAAoB,GAAG,WAAW,GAAG,mBAAmB,CAAC;IAChE,UAAU,EACN,iBAAiB,GACjB,eAAe,GACf,oBAAoB,GACpB,eAAe,GACf,WAAW,GACX,aAAa,GACb,iBAAiB,GACjB,sBAAsB,GACtB,mBAAmB,GACnB,uBAAuB,GACvB,2BAA2B,GAC3B,kCAAkC,GAClC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"promote-to-skill.d.ts","sourceRoot":"","sources":["../../src/bot/promote-to-skill.ts"],"names":[],"mappings":"AAqCA,OAAO,EAGL,KAAK,KAAK,EAIX,MAAM,4BAA4B,CAAC;AAUpC,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC5B,gBAAgB,CAAC;AAErB;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,oBAAoB,GAAG,WAAW,GAAG,mBAAmB,CAAC;IAChE,UAAU,EACN,iBAAiB,GACjB,eAAe,GACf,oBAAoB,GACpB,eAAe,GACf,WAAW,GACX,aAAa,GACb,iBAAiB,GACjB,sBAAsB,GACtB,mBAAmB,GACnB,uBAAuB,GACvB,2BAA2B,GAC3B,kCAAkC,GAClC,gBAAgB,GAQhB,+BAA+B,GAC/B,8BAA8B,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;CACjD;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAG,CAAU,CAAC;AAI9C,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,CAiHjE;AAk0BD,wBAAgB,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,MAAM,CAexE"}
|
|
@@ -61,18 +61,44 @@ export function promoteToSkill(input) {
|
|
|
61
61
|
synthesizer_version: SYNTHESIZER_VERSION,
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
-
// Stage 1.b — synthesize the SkillStep array.
|
|
65
|
-
|
|
64
|
+
// Stage 1.b — synthesize the SkillStep array. Always emits single-
|
|
65
|
+
// cred extract kinds; the multi-cred upgrade happens in Stage 1.c.5
|
|
66
|
+
// below as a post-pass. This keeps step synthesis single-purpose.
|
|
67
|
+
const stepsResult = synthesizeSteps(verification.rounds, input.run_id);
|
|
66
68
|
if (stepsResult.kind !== "ok")
|
|
67
69
|
return stepsResult;
|
|
68
70
|
// Stage 1.c — infer signup_url + oauth_provider from round 0 + steps.
|
|
69
71
|
const firstRound = verification.rounds[0];
|
|
70
72
|
const signupUrl = firstRound.state.url;
|
|
71
73
|
const oauthProvider = inferOAuthProvider(stepsResult.steps);
|
|
72
|
-
// Stage 1.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
// Stage 1.c.5 — multi-cred dispatch (Phase B/C per docs/DESIGN-
|
|
75
|
+
// multi-credential.md). Count extract-class steps; if >1 AND each
|
|
76
|
+
// has a distinct derivable `produces` name, upgrade to the multi-
|
|
77
|
+
// cred shape (named extract kinds + multiple credentials). On any
|
|
78
|
+
// failure (collision, unparseable label) we REJECT rather than
|
|
79
|
+
// silently fall back to single-cred — a multi-cred capture with
|
|
80
|
+
// ambiguous labels is operator-fix territory.
|
|
81
|
+
const extractStepIndices = stepsResult.steps
|
|
82
|
+
.map((s, i) => ({ s, i }))
|
|
83
|
+
.filter(({ s }) => s.kind === "extract_via_copy_button" || s.kind === "extract_via_regex");
|
|
84
|
+
const multiCred = extractStepIndices.length > 1;
|
|
85
|
+
let steps = stepsResult.steps;
|
|
86
|
+
let credentials;
|
|
87
|
+
if (multiCred) {
|
|
88
|
+
const multiResult = upgradeToMultiCred(stepsResult.steps, verification.rounds, input.service);
|
|
89
|
+
if (multiResult.kind !== "ok")
|
|
90
|
+
return multiResult;
|
|
91
|
+
steps = multiResult.steps;
|
|
92
|
+
credentials = multiResult.credentials;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Stage 1.d (single-cred) — infer one credential spec from the
|
|
96
|
+
// sole extract step + page. UNCHANGED from pre-multi-cred.
|
|
97
|
+
const credentialResult = inferCredentialSpec(verification.rounds, stepsResult.steps, input.service, input.env_var_suggestion);
|
|
98
|
+
if (credentialResult.kind !== "ok")
|
|
99
|
+
return credentialResult;
|
|
100
|
+
credentials = [credentialResult.spec];
|
|
101
|
+
}
|
|
76
102
|
// Stage 1.e — assemble the candidate skill and validate via Zod.
|
|
77
103
|
// skill_id is derived deterministically from the assembled content
|
|
78
104
|
// so the same captures always produce the same skill_id (test
|
|
@@ -85,8 +111,8 @@ export function promoteToSkill(input) {
|
|
|
85
111
|
version: "v1",
|
|
86
112
|
signup_url: signupUrl,
|
|
87
113
|
oauth_provider: oauthProvider,
|
|
88
|
-
steps
|
|
89
|
-
credentials
|
|
114
|
+
steps,
|
|
115
|
+
credentials,
|
|
90
116
|
source_run_ids: [input.run_id],
|
|
91
117
|
status: "active",
|
|
92
118
|
replays_succeeded: 0,
|
|
@@ -116,14 +142,17 @@ export function promoteToSkill(input) {
|
|
|
116
142
|
};
|
|
117
143
|
}
|
|
118
144
|
}
|
|
119
|
-
function synthesizeSteps(rounds) {
|
|
145
|
+
function synthesizeSteps(rounds, runId) {
|
|
120
146
|
const steps = [];
|
|
121
147
|
for (let i = 0; i < rounds.length; i++) {
|
|
122
148
|
const round = rounds[i];
|
|
123
149
|
// Build the provenance once — every step in this round shares the
|
|
124
|
-
// same (run_id, round_index) pair.
|
|
150
|
+
// same (run_id, round_index) pair. The run_id comes from the
|
|
151
|
+
// promoter's input rather than being derived from the round, so
|
|
152
|
+
// forensics on a published skill point back at the actual run dir
|
|
153
|
+
// (`<service>-<run_id>-r*.json`) rather than a placeholder hash.
|
|
125
154
|
const provenance = {
|
|
126
|
-
run_id:
|
|
155
|
+
run_id: runId,
|
|
127
156
|
round_index: i,
|
|
128
157
|
};
|
|
129
158
|
const translated = translateStep(round.observed, round.inventory, provenance, i);
|
|
@@ -214,12 +243,24 @@ function translateStep(observed, inventory, provenance, roundIndex) {
|
|
|
214
243
|
const hintResult = resolveLabelHint(observed.selector, inventory, roundIndex);
|
|
215
244
|
if (hintResult.kind !== "ok")
|
|
216
245
|
return hintResult;
|
|
246
|
+
// rc.17 — if the captured value looks like the unique-name
|
|
247
|
+
// shape the rc.15 planner prompt told the bot to use
|
|
248
|
+
// (e.g. "agent-zp9q", "ts-x9k2", "mcp-a3b9c2f1"), templatize
|
|
249
|
+
// it to ${TOKEN_NAME} so each replay generates a fresh name.
|
|
250
|
+
// Without this, every promoted skill bakes in the literal
|
|
251
|
+
// name from its capture run — and the very next replay fails
|
|
252
|
+
// at the credential-creating click because that name now
|
|
253
|
+
// already exists on the service (Railway's silent duplicate-
|
|
254
|
+
// name rejection was the canonical case).
|
|
255
|
+
const literal = observed.value;
|
|
256
|
+
const looksGenerated = /^[a-z]{3,15}-[a-z0-9]{4,12}$/.test(literal);
|
|
257
|
+
const valueTemplate = looksGenerated ? "${TOKEN_NAME}" : literal;
|
|
217
258
|
return {
|
|
218
259
|
kind: "ok",
|
|
219
260
|
step: {
|
|
220
261
|
kind: "fill",
|
|
221
262
|
label_hint: hintResult.hint,
|
|
222
|
-
value_template:
|
|
263
|
+
value_template: valueTemplate,
|
|
223
264
|
provenance,
|
|
224
265
|
},
|
|
225
266
|
};
|
|
@@ -456,9 +497,15 @@ function synthesizeExtractStep(observed, inventory, provenance, roundIndex) {
|
|
|
456
497
|
}
|
|
457
498
|
function findCopyButton(inventory) {
|
|
458
499
|
for (const el of inventory) {
|
|
459
|
-
|
|
500
|
+
// rc.19 — also include title (icon-only buttons like Railway's
|
|
501
|
+
// "Copy Code" modal button carry the label there) and iconLabel
|
|
502
|
+
// (which folds in descendant SVG/img alt/aria-label). Without
|
|
503
|
+
// this, the synthesizer picks extract_via_regex for Railway-
|
|
504
|
+
// class flows, then the replay's regex library can't match a
|
|
505
|
+
// bare UUID and the skill replay-fails forever.
|
|
506
|
+
const text = `${el.visibleText ?? ""} ${el.ariaLabel ?? ""} ${el.title ?? ""} ${el.iconLabel ?? ""}`.trim();
|
|
460
507
|
// Same vocabulary as agent.ts:tryCopyButtonExtraction.
|
|
461
|
-
if (/^\s*copy(?:\b|\s|$)|copy\s+(?:api\s*key|secret|token|key|to\s+clipboard)\b/i.test(text)) {
|
|
508
|
+
if (/^\s*copy(?:\b|\s|$)|copy\s+(?:api\s*key|secret|token|code|key|to\s+clipboard)\b/i.test(text)) {
|
|
462
509
|
return el;
|
|
463
510
|
}
|
|
464
511
|
}
|
|
@@ -601,6 +648,158 @@ function inferOAuthProvider(steps) {
|
|
|
601
648
|
}
|
|
602
649
|
return null;
|
|
603
650
|
}
|
|
651
|
+
function upgradeToMultiCred(inputSteps, rounds, service) {
|
|
652
|
+
const seen = new Set();
|
|
653
|
+
const outSteps = [];
|
|
654
|
+
const credentialsByName = new Map();
|
|
655
|
+
for (let i = 0; i < inputSteps.length; i++) {
|
|
656
|
+
const step = inputSteps[i];
|
|
657
|
+
if (step.kind === "extract_via_copy_button") {
|
|
658
|
+
const produces = deriveProducesFromHint(step.near_text_hint);
|
|
659
|
+
if (produces === null) {
|
|
660
|
+
return {
|
|
661
|
+
kind: "rejected",
|
|
662
|
+
stage: "synthesis",
|
|
663
|
+
error_kind: "unparseable_credential_label",
|
|
664
|
+
message: `Extract step at index ${i} has a hint (${JSON.stringify(step.near_text_hint)}) ` +
|
|
665
|
+
`that doesn't normalize to a usable credential name. ` +
|
|
666
|
+
`Multi-credential skills require each extract to name what it produces.`,
|
|
667
|
+
offending_step: i,
|
|
668
|
+
synthesizer_version: SYNTHESIZER_VERSION,
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
if (seen.has(produces)) {
|
|
672
|
+
return {
|
|
673
|
+
kind: "rejected",
|
|
674
|
+
stage: "synthesis",
|
|
675
|
+
error_kind: "duplicate_credential_produces",
|
|
676
|
+
message: `Two extract steps derived the same credential name ` +
|
|
677
|
+
`(${JSON.stringify(produces)}). A multi-credential skill ` +
|
|
678
|
+
`must produce N distinctly-named values; relabel the capture or ` +
|
|
679
|
+
`re-run the signup so each credential gets a unique near-text hint.`,
|
|
680
|
+
offending_step: i,
|
|
681
|
+
synthesizer_version: SYNTHESIZER_VERSION,
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
seen.add(produces);
|
|
685
|
+
outSteps.push({
|
|
686
|
+
kind: "extract_via_copy_button_named",
|
|
687
|
+
near_text_hint: step.near_text_hint,
|
|
688
|
+
produces,
|
|
689
|
+
provenance: step.provenance,
|
|
690
|
+
});
|
|
691
|
+
credentialsByName.set(produces, buildCredentialSpecForMulti(produces, "opaque", service));
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
if (step.kind === "extract_via_regex") {
|
|
695
|
+
// Regex extracts on a multi-cred page derive `produces` from the
|
|
696
|
+
// pattern_name (e.g. "stripe_secret" → "stripe_secret"). The
|
|
697
|
+
// pattern_name is already snake_case and unique per credential
|
|
698
|
+
// type, so it's a natural identifier.
|
|
699
|
+
const produces = step.pattern_name.toLowerCase();
|
|
700
|
+
if (seen.has(produces)) {
|
|
701
|
+
return {
|
|
702
|
+
kind: "rejected",
|
|
703
|
+
stage: "synthesis",
|
|
704
|
+
error_kind: "duplicate_credential_produces",
|
|
705
|
+
message: `Two extract steps target the same regex pattern (` +
|
|
706
|
+
`${produces}). Multi-credential extracts must use distinct ` +
|
|
707
|
+
`patterns; if two credentials share a shape, switch one to ` +
|
|
708
|
+
`a copy_button extraction with a distinguishing near-text hint.`,
|
|
709
|
+
offending_step: i,
|
|
710
|
+
synthesizer_version: SYNTHESIZER_VERSION,
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
seen.add(produces);
|
|
714
|
+
outSteps.push({
|
|
715
|
+
kind: "extract_via_regex_named",
|
|
716
|
+
pattern_name: step.pattern_name,
|
|
717
|
+
produces,
|
|
718
|
+
provenance: step.provenance,
|
|
719
|
+
});
|
|
720
|
+
// Shape hint follows the pattern's known prefix.
|
|
721
|
+
const shape = patternToShapeHint(step.pattern_name);
|
|
722
|
+
credentialsByName.set(produces, buildCredentialSpecForMulti(produces, shape, service));
|
|
723
|
+
continue;
|
|
724
|
+
}
|
|
725
|
+
// Non-extract steps pass through unchanged.
|
|
726
|
+
outSteps.push(step);
|
|
727
|
+
}
|
|
728
|
+
// Capture rounds + ordering preserved so a future caller can correlate
|
|
729
|
+
// step index → round (used by the in-flight schema validator later).
|
|
730
|
+
void rounds;
|
|
731
|
+
return {
|
|
732
|
+
kind: "ok",
|
|
733
|
+
steps: outSteps,
|
|
734
|
+
credentials: Array.from(credentialsByName.values()),
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
// Normalize a free-text credential label into a snake_case `produces`
|
|
738
|
+
// identifier. "API Key Secret" → "api_key_secret". Returns null when
|
|
739
|
+
// the result is empty or doesn't start with a letter (the schema
|
|
740
|
+
// requires `^[a-z][a-z0-9_]*$`).
|
|
741
|
+
function deriveProducesFromHint(hint) {
|
|
742
|
+
const normalized = hint
|
|
743
|
+
.trim()
|
|
744
|
+
.toLowerCase()
|
|
745
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
746
|
+
.replace(/^_+|_+$/g, "");
|
|
747
|
+
if (normalized.length === 0)
|
|
748
|
+
return null;
|
|
749
|
+
if (!/^[a-z]/.test(normalized))
|
|
750
|
+
return null;
|
|
751
|
+
// The schema regex allows only [a-z][a-z0-9_]*. Filter again for safety;
|
|
752
|
+
// any character that slipped through means a unicode edge case.
|
|
753
|
+
if (!/^[a-z][a-z0-9_]*$/.test(normalized))
|
|
754
|
+
return null;
|
|
755
|
+
// Truncate to a reasonable length — avoid pathological inputs producing
|
|
756
|
+
// 200-char `produces` names.
|
|
757
|
+
return normalized.slice(0, 64);
|
|
758
|
+
}
|
|
759
|
+
function patternToShapeHint(patternName) {
|
|
760
|
+
switch (patternName) {
|
|
761
|
+
case "stripe_secret":
|
|
762
|
+
return "prefix:sk_live";
|
|
763
|
+
case "stripe_publishable":
|
|
764
|
+
return "prefix:sk_live";
|
|
765
|
+
case "resend":
|
|
766
|
+
return "prefix:re_";
|
|
767
|
+
case "sendgrid":
|
|
768
|
+
return "prefix:SG.";
|
|
769
|
+
case "mailgun":
|
|
770
|
+
return "prefix:key-";
|
|
771
|
+
case "render":
|
|
772
|
+
return "prefix:rnd_";
|
|
773
|
+
case "sentry_token":
|
|
774
|
+
return "prefix:sntry";
|
|
775
|
+
case "openrouter":
|
|
776
|
+
return "prefix:sk-or-v1-";
|
|
777
|
+
case "anthropic":
|
|
778
|
+
return "prefix:sk-ant-";
|
|
779
|
+
case "openai_legacy":
|
|
780
|
+
return "prefix:sk-";
|
|
781
|
+
default:
|
|
782
|
+
return "opaque";
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
function buildCredentialSpecForMulti(name, shape, service) {
|
|
786
|
+
// Env var: <SERVICE>_<PRODUCES>. Twitter + api_key_secret →
|
|
787
|
+
// TWITTER_API_KEY_SECRET. Maintains the "<SERVICE>_<CRED>" convention
|
|
788
|
+
// and disambiguates the multiple credentials in a multi-cred bundle.
|
|
789
|
+
const upperService = service.toUpperCase().replace(/-/g, "_");
|
|
790
|
+
const upperName = name.toUpperCase();
|
|
791
|
+
const envVar = `${upperService}_${upperName}`;
|
|
792
|
+
return {
|
|
793
|
+
name,
|
|
794
|
+
type: "api_key",
|
|
795
|
+
shape_hint: shape,
|
|
796
|
+
env_var_suggestion: envVar,
|
|
797
|
+
post_extract_validator: {
|
|
798
|
+
min_length: shape === "uuid" ? 36 : 16,
|
|
799
|
+
max_length: shape === "uuid" ? 36 : 512,
|
|
800
|
+
},
|
|
801
|
+
};
|
|
802
|
+
}
|
|
604
803
|
// ── Deterministic helpers ────────────────────────────────────────────
|
|
605
804
|
function deriveEnvVar(service) {
|
|
606
805
|
// Convention: <SERVICE>_API_KEY. Service slug is lowercase-with-
|
|
@@ -619,7 +818,7 @@ function deriveTimestampFromRounds(rounds) {
|
|
|
619
818
|
const offsetMs = parseInt(hash.slice(0, 8), 16) % (365 * 24 * 60 * 60 * 1000);
|
|
620
819
|
return new Date(Date.UTC(2026, 0, 1) + offsetMs).toISOString();
|
|
621
820
|
}
|
|
622
|
-
function deriveSkillId(candidate) {
|
|
821
|
+
export function deriveSkillId(candidate) {
|
|
623
822
|
// Skill IDs are ULID-shaped. We derive a deterministic 26-char
|
|
624
823
|
// string from the candidate's hash so that the same captures
|
|
625
824
|
// produce the same skill_id across runs (test determinism +
|
|
@@ -635,20 +834,6 @@ function deriveSkillId(candidate) {
|
|
|
635
834
|
}
|
|
636
835
|
return out;
|
|
637
836
|
}
|
|
638
|
-
function extractRunIdFromRound(round) {
|
|
639
|
-
// The capture format doesn't store run_id explicitly — it's encoded
|
|
640
|
-
// in the filename. The promoter passes it down via PromoteInput,
|
|
641
|
-
// but synthesizeSteps doesn't have access to that closure. Workaround:
|
|
642
|
-
// since every round in a chain shares a run_id, and the chain is
|
|
643
|
-
// verified before we get here, we can reconstruct it from the
|
|
644
|
-
// content_hash chain by hashing the round's own identifier. For now,
|
|
645
|
-
// we use a placeholder that the test-deterministic hash will pin
|
|
646
|
-
// identically across runs.
|
|
647
|
-
//
|
|
648
|
-
// TODO: refactor to thread run_id through translateStep — this works
|
|
649
|
-
// for tests but obscures provenance. Tracked: not blocking 0.7.0.
|
|
650
|
-
return `derived-${round.content_hash.slice(0, 8)}`;
|
|
651
|
-
}
|
|
652
837
|
function chainRejectionMessage(reason, offendingRound) {
|
|
653
838
|
const where = offendingRound !== undefined ? ` at round ${offendingRound}` : "";
|
|
654
839
|
switch (reason) {
|