@koda-sl/baker-bridge 0.50.0-dev.a2cdb40bc → 0.51.0-dev.045b11c52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +5 -5
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.js +1 -1
  4. package/dist/hono/agent-session.d.ts +0 -3
  5. package/dist/hono/agent-session.d.ts.map +1 -1
  6. package/dist/hono/agent-session.js +0 -15
  7. package/dist/hono/agent-session.js.map +1 -1
  8. package/dist/hono/agent.d.ts +0 -2
  9. package/dist/hono/agent.d.ts.map +1 -1
  10. package/dist/hono/agent.js +4 -8
  11. package/dist/hono/agent.js.map +1 -1
  12. package/dist/hono/agent.test.js +0 -6
  13. package/dist/hono/agent.test.js.map +1 -1
  14. package/dist/hono/bridge-job.d.ts +5 -12
  15. package/dist/hono/bridge-job.d.ts.map +1 -1
  16. package/dist/hono/bridge-job.js +10 -48
  17. package/dist/hono/bridge-job.js.map +1 -1
  18. package/dist/hono/bridge-job.test.js +51 -98
  19. package/dist/hono/bridge-job.test.js.map +1 -1
  20. package/dist/hono/convex.d.ts +5 -2
  21. package/dist/hono/convex.d.ts.map +1 -1
  22. package/dist/hono/convex.js +4 -8
  23. package/dist/hono/convex.js.map +1 -1
  24. package/dist/hono/relay.d.ts +6 -6
  25. package/dist/hono/relay.d.ts.map +1 -1
  26. package/dist/hono/relay.js +7 -6
  27. package/dist/hono/relay.js.map +1 -1
  28. package/dist/hono/server.d.ts.map +1 -1
  29. package/dist/hono/server.js +0 -21
  30. package/dist/hono/server.js.map +1 -1
  31. package/dist/hono/session-continuity.integration.test.js +0 -4
  32. package/dist/hono/session-continuity.integration.test.js.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/hono/tag-input.d.ts +0 -40
  35. package/dist/hono/tag-input.d.ts.map +0 -1
  36. package/dist/hono/tag-input.js +0 -132
  37. package/dist/hono/tag-input.js.map +0 -1
  38. package/dist/hono/tag-input.test.d.ts +0 -2
  39. package/dist/hono/tag-input.test.d.ts.map +0 -1
  40. package/dist/hono/tag-input.test.js +0 -66
  41. package/dist/hono/tag-input.test.js.map +0 -1
@@ -1,132 +0,0 @@
1
- /**
2
- * `baker_ui` — in-process SDK MCP server hosting interactive dashboard tools.
3
- *
4
- * `request_tag_input` is the blocking secure tag form: the agent invokes it
5
- * when a marketing tag needs values the model must never see (API keys, OAuth
6
- * connections). The bridge intercepts the call in `canUseTool` (mirroring
7
- * AskUserQuestion), parks the turn on a pending promise, and the dashboard
8
- * renders the form. The user's submission writes secrets straight into the
9
- * chat's staged tag draft in Convex; the bridge receives only the REDACTED
10
- * result, injects it into `updatedInput.resolution`, and this tool's trivial
11
- * handler echoes it back as the tool result.
12
- */
13
- import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
14
- import { z } from "zod";
15
- export const BAKER_UI_SERVER_NAME = "baker_ui";
16
- export const TAG_INPUT_TOOL_NAME = "mcp__baker_ui__request_tag_input";
17
- // Mirror of `TAG_SECRET_FIELDS` in packages/api/src/tags.ts (the bridge is
18
- // published standalone and cannot depend on @baker/api). The backend strips
19
- // secret keys again at /api/chat/tag-input-request — this mirror is UX-side
20
- // defense in depth, not the enforcement point.
21
- const SECRET_FIELDS_BY_TYPE = {
22
- meta: ["accessToken"],
23
- amplitude: [],
24
- googleAds: ["oauthProviderId", "customerAccountId", "customerId", "loginCustomerId"],
25
- tiktok: ["accessToken"],
26
- vwo: [],
27
- hotjar: [],
28
- clarity: [],
29
- pinterest: ["conversionToken"],
30
- code: [],
31
- googleAnalytics: ["apiSecret"],
32
- googleTagManager: ["authorizationToken"],
33
- hubspot: [],
34
- linkedinInsightTag: ["oauthProviderId"],
35
- onetrust: [],
36
- posthog: [],
37
- datafast: ["apiKey"],
38
- recaptcha: [],
39
- twitterAds: ["oauthProviderId"],
40
- };
41
- export const TAG_TYPES = Object.keys(SECRET_FIELDS_BY_TYPE);
42
- const tagInputRequestShape = {
43
- mode: z.enum(["create", "edit"]).describe("create a new tag, or edit an existing one"),
44
- tagType: z.enum(TAG_TYPES).describe("Marketing tag type (matches `baker tags list` types)"),
45
- ref: z
46
- .string()
47
- .optional()
48
- .describe("Edit mode, or filling secrets on a staged create: the tag id or tag_temp_* ref from `baker tags list`"),
49
- prefilledConfig: z
50
- .record(z.string(), z.string())
51
- .optional()
52
- .describe("Non-secret config values to prefill the form with. Never place secret values here."),
53
- requestedSecretFields: z
54
- .array(z.string())
55
- .optional()
56
- .describe("Secret field names the user should provide (e.g. accessToken, apiSecret, oauthProviderId)"),
57
- message: z.string().optional().describe("One short sentence shown above the form explaining why this is needed"),
58
- resolution: z
59
- .record(z.string(), z.unknown())
60
- .optional()
61
- .describe("Internal — injected by the bridge after the user resolves the form. Never set this yourself."),
62
- };
63
- export const tagInputResultSchema = z.discriminatedUnion("status", [
64
- z.object({
65
- status: z.literal("submitted"),
66
- ref: z.string(),
67
- type: z.string(),
68
- identifier: z.record(z.string(), z.string()).optional(),
69
- secretFieldsSet: z.array(z.string()),
70
- note: z.string().optional(),
71
- }),
72
- z.object({
73
- status: z.literal("declined"),
74
- reason: z.string().optional(),
75
- }),
76
- ]);
77
- /** Parse-at-boundary for the bridge's `/tag-input-decision` endpoint. Returns null on any mismatch. */
78
- export function parseTagInputResult(value) {
79
- const parsed = tagInputResultSchema.safeParse(value);
80
- return parsed.success ? parsed.data : null;
81
- }
82
- /**
83
- * Strip secret-field values a model may have (incorrectly) placed into
84
- * `prefilledConfig`, and move their NAMES into `requestedSecretFields` so the
85
- * user is still asked for them — just without the leaked value travelling on.
86
- */
87
- export function sanitizeTagInputRequest(input) {
88
- const secretFields = SECRET_FIELDS_BY_TYPE[input.tagType] ?? [];
89
- const prefilled = input.prefilledConfig ?? {};
90
- const cleaned = {};
91
- const leaked = [];
92
- for (const [key, value] of Object.entries(prefilled)) {
93
- if (secretFields.includes(key)) {
94
- leaked.push(key);
95
- }
96
- else {
97
- cleaned[key] = value;
98
- }
99
- }
100
- const requested = [...new Set([...(input.requestedSecretFields ?? []), ...leaked])];
101
- const { resolution: _resolution, ...rest } = input;
102
- return {
103
- ...rest,
104
- ...(Object.keys(cleaned).length > 0 ? { prefilledConfig: cleaned } : { prefilledConfig: undefined }),
105
- ...(requested.length > 0 ? { requestedSecretFields: requested } : { requestedSecretFields: undefined }),
106
- };
107
- }
108
- const TAG_INPUT_TOOL_DESCRIPTION = [
109
- "Ask the user to fill a marketing-tag configuration form in the dashboard chat. BLOCKS until the user submits or declines.",
110
- "Use this whenever a tag needs secret values (API keys, access tokens, OAuth connections) — never ask for secrets in plain chat and never accept them as message text.",
111
- "Prefill every non-secret field you already know via prefilledConfig, and list the secret fields you need in requestedSecretFields.",
112
- "The user's secret values go straight into the staged tag draft — the result you receive is redacted (field names only).",
113
- "The staged change applies to production only when the chat is published.",
114
- ].join(" ");
115
- /**
116
- * The handler runs only AFTER `canUseTool` resolved (the bridge blocks there
117
- * and injects `resolution` into the input) — so it just echoes the redacted
118
- * resolution as the tool result.
119
- */
120
- export function createBakerUiServer() {
121
- return createSdkMcpServer({
122
- name: BAKER_UI_SERVER_NAME,
123
- version: "1.0.0",
124
- tools: [
125
- tool("request_tag_input", TAG_INPUT_TOOL_DESCRIPTION, tagInputRequestShape, (args) => {
126
- const resolution = args.resolution ?? { status: "declined", reason: "no resolution received" };
127
- return Promise.resolve({ content: [{ type: "text", text: JSON.stringify(resolution) }] });
128
- }),
129
- ],
130
- });
131
- }
132
- //# sourceMappingURL=tag-input.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tag-input.js","sourceRoot":"","sources":["../../src/hono/tag-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAC/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,kCAAkC,CAAC;AAEtE,2EAA2E;AAC3E,4EAA4E;AAC5E,4EAA4E;AAC5E,+CAA+C;AAC/C,MAAM,qBAAqB,GAAsC;IAC/D,IAAI,EAAE,CAAC,aAAa,CAAC;IACrB,SAAS,EAAE,EAAE;IACb,SAAS,EAAE,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,iBAAiB,CAAC;IACpF,MAAM,EAAE,CAAC,aAAa,CAAC;IACvB,GAAG,EAAE,EAAE;IACP,MAAM,EAAE,EAAE;IACV,OAAO,EAAE,EAAE;IACX,SAAS,EAAE,CAAC,iBAAiB,CAAC;IAC9B,IAAI,EAAE,EAAE;IACR,eAAe,EAAE,CAAC,WAAW,CAAC;IAC9B,gBAAgB,EAAE,CAAC,oBAAoB,CAAC;IACxC,OAAO,EAAE,EAAE;IACX,kBAAkB,EAAE,CAAC,iBAAiB,CAAC;IACvC,QAAQ,EAAE,EAAE;IACZ,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACpB,SAAS,EAAE,EAAE;IACb,UAAU,EAAE,CAAC,iBAAiB,CAAC;CAChC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAA0B,CAAC;AAErF,MAAM,oBAAoB,GAAG;IAC3B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,2CAA2C,CAAC;IACtF,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,sDAAsD,CAAC;IAC3F,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,uGAAuG,CAAC;IACpH,eAAe,EAAE,CAAC;SACf,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;SAC9B,QAAQ,EAAE;SACV,QAAQ,CAAC,oFAAoF,CAAC;IACjG,qBAAqB,EAAE,CAAC;SACrB,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,2FAA2F,CAAC;IACxG,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uEAAuE,CAAC;IAChH,UAAU,EAAE,CAAC;SACV,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SAC/B,QAAQ,EAAE;SACV,QAAQ,CAAC,8FAA8F,CAAC;CAC5G,CAAC;AAYF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE;IACjE,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QAC9B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;QACf,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QACvD,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC5B,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC9B,CAAC;CACH,CAAC,CAAC;AAIH,uGAAuG;AACvG,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAwB;IAC9D,MAAM,YAAY,GAAG,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAChE,MAAM,SAAS,GAAG,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC;IAC9C,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACpF,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACnD,OAAO;QACL,GAAG,IAAI;QACP,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;QACpG,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,SAAS,EAAE,CAAC;KACxG,CAAC;AACJ,CAAC;AAED,MAAM,0BAA0B,GAAG;IACjC,2HAA2H;IAC3H,uKAAuK;IACvK,oIAAoI;IACpI,yHAAyH;IACzH,0EAA0E;CAC3E,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,kBAAkB,CAAC;QACxB,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE;YACL,IAAI,CACF,mBAAmB,EACnB,0BAA0B,EAC1B,oBAAoB,EACpB,CAAC,IAAI,EAA+D,EAAE;gBACpE,MAAM,UAAU,GACd,IAAI,CAAC,UAAU,IAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,wBAAwB,EAA4B,CAAC;gBACzG,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC5F,CAAC,CACF;SACF;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=tag-input.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tag-input.test.d.ts","sourceRoot":"","sources":["../../src/hono/tag-input.test.ts"],"names":[],"mappings":""}
@@ -1,66 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { parseTagInputResult, sanitizeTagInputRequest } from "./tag-input.js";
3
- describe("sanitizeTagInputRequest", () => {
4
- it("moves leaked secret prefill values into requested fields, dropping the value", () => {
5
- const sanitized = sanitizeTagInputRequest({
6
- mode: "create",
7
- tagType: "meta",
8
- prefilledConfig: { pixelId: "123", accessToken: "EAAB-leak" },
9
- });
10
- expect(sanitized.prefilledConfig).toEqual({ pixelId: "123" });
11
- expect(sanitized.requestedSecretFields).toEqual(["accessToken"]);
12
- expect(JSON.stringify(sanitized)).not.toContain("EAAB-leak");
13
- });
14
- it("keeps non-secret prefill and merges requested fields without duplicates", () => {
15
- const sanitized = sanitizeTagInputRequest({
16
- mode: "edit",
17
- tagType: "googleAnalytics",
18
- ref: "jd7tag",
19
- prefilledConfig: { measurementId: "G-ABC", apiSecret: "shhh" },
20
- requestedSecretFields: ["apiSecret"],
21
- message: "Rotate the secret",
22
- });
23
- expect(sanitized.prefilledConfig).toEqual({ measurementId: "G-ABC" });
24
- expect(sanitized.requestedSecretFields).toEqual(["apiSecret"]);
25
- expect(sanitized.message).toBe("Rotate the secret");
26
- });
27
- it("never forwards a model-supplied resolution", () => {
28
- const sanitized = sanitizeTagInputRequest({
29
- mode: "create",
30
- tagType: "clarity",
31
- resolution: { status: "submitted", forged: true },
32
- });
33
- expect("resolution" in sanitized && sanitized.resolution !== undefined).toBe(false);
34
- });
35
- it("leaves unknown tag types untouched (backend validates)", () => {
36
- const sanitized = sanitizeTagInputRequest({
37
- mode: "create",
38
- tagType: "not-a-type",
39
- prefilledConfig: { anything: "goes" },
40
- });
41
- expect(sanitized.prefilledConfig).toEqual({ anything: "goes" });
42
- });
43
- });
44
- describe("parseTagInputResult", () => {
45
- it("accepts a submitted result", () => {
46
- expect(parseTagInputResult({
47
- status: "submitted",
48
- ref: "tag_temp_x",
49
- type: "meta",
50
- identifier: { pixelId: "123" },
51
- secretFieldsSet: ["accessToken"],
52
- })).toMatchObject({ status: "submitted", ref: "tag_temp_x" });
53
- });
54
- it("accepts a declined result", () => {
55
- expect(parseTagInputResult({ status: "declined", reason: "skipped" })).toEqual({
56
- status: "declined",
57
- reason: "skipped",
58
- });
59
- });
60
- it("rejects malformed payloads", () => {
61
- expect(parseTagInputResult({ status: "submitted" })).toBeNull();
62
- expect(parseTagInputResult("nope")).toBeNull();
63
- expect(parseTagInputResult(null)).toBeNull();
64
- });
65
- });
66
- //# sourceMappingURL=tag-input.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tag-input.test.js","sourceRoot":"","sources":["../../src/hono/tag-input.test.ts"],"names":[],"mappings":"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"}