@walkeros/mcp 4.6.1 → 4.7.0-next-1790187973605

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/dist/index.d.ts CHANGED
@@ -1051,8 +1051,8 @@ declare const FRAME_MANAGE_INPUT_SCHEMA: {
1051
1051
  declare const FRAME_HINT_OPEN_PAGE_OR_GET = "Use action \"page\" with a pageKey (a frame\u2019s source.key) to read a page with marks, or action \"get\" with a frameId.";
1052
1052
  declare const FRAME_HINT_NAMES_ARE_DOCUMENTATION = "Frame names are documentation; the marks inside a frame carry the meaning.";
1053
1053
  declare const FRAME_HINT_NONE_YET = "This project has no frames yet. Frames are drawn in Tag Mode or the app, not through this tool.";
1054
- declare const FRAME_HINT_MARK_SPACE = "Marks are in their frame\u2019s own 0..1 space; a child frame sits inside its parent through placements[].rect.";
1055
- declare const FRAME_HINT_READ_KNOWLEDGE = "Use hub_manage action \"knowledge\" with frameId (and markId) to read what people wrote here. A markId is an id from these marks, and an entity action is addressed by its own id, never by its raw text.";
1054
+ declare const FRAME_HINT_MARK_SPACE = "Tag geometry is fractional: a rect is 0..1 of its frame, and an at is 0..1 of its parent tag\u2019s box, or of the frame for a root tag; a child frame sits inside its parent through placements[].rect.";
1055
+ declare const FRAME_HINT_READ_KNOWLEDGE = "Use hub_manage action \"knowledge\" with frameId (and markId) to read what people wrote here. A markId is a tag id from these marks, and a tag\u2019s threadRef is the id of its thread entry there.";
1056
1056
  declare const FRAME_HINT_NONE_ON_PAGE = "No frames on this page. Check the pageKey against the source.key values from action \"list\".";
1057
1057
  declare const FRAME_HINT_EXTENDS_BASE = "This frame extends another and stores only what it adds; read the base frame (extends) for the rest.";
1058
1058
  declare const FRAME_NOT_FOUND_HINT = "Use action \"list\" or \"page\" to find frame ids.";
package/dist/index.js CHANGED
@@ -2024,7 +2024,7 @@ var HUB_MANAGE_INPUT_SCHEMA = {
2024
2024
  'One frame (frm_...), the named rectangle a note hangs on. Action "knowledge" only. Narrower than pageKey, since a page holds several frames.'
2025
2025
  ),
2026
2026
  markId: z8.string().min(1).max(MAX_MARK_ID_LENGTH).optional().describe(
2027
- 'One mark within "frameId". Action "knowledge" only, and refused without frameId, since a mark id alone addresses nothing. Naming a mark is also what attaches the message bodies.'
2027
+ 'One tag within "frameId", by its tag id (the id of an entry in frame_manage marks.tags). Action "knowledge" only, and refused without frameId, since a mark id alone addresses nothing. Naming a mark is also what attaches the message bodies.'
2028
2028
  )
2029
2029
  };
2030
2030
  var annotations8 = {
@@ -2560,7 +2560,7 @@ import { mcpResult as mcpResult9, mcpError as mcpError9 } from "@walkeros/core";
2560
2560
  var FRAME_ID_PATTERN2 = /^frm_[A-Za-z0-9_-]{21}$/;
2561
2561
  var MAX_PAGE_KEY_CHARS = 1024;
2562
2562
  var TITLE9 = "Frames";
2563
- var FRAME_MANAGE_DESCRIPTION = 'Read the frames of a measurement plan: named rectangles with marks inside them, drawn in Tag Mode or in the app. Actions: list (every frame of the project, without marks), page (the frames of one page at any depth, with marks), get (one frame with its marks). Read-only: frames are drawn and edited in Tag Mode or the app, never here. A frame name is documentation; the marks inside it carry the meaning. A frame that extends another stores only what it adds. Use hub_manage action "knowledge" with a frameId or markId to read what people wrote on a frame. A markId is an id read from the marks of a frame here: mark ids come back literal so they can be passed straight back, while the text around them is wrapped as data. An entity action is an object carrying its id beside the raw attribute text, because the id is the address and the raw text is not.';
2563
+ var FRAME_MANAGE_DESCRIPTION = 'Read the frames of a measurement plan: named rectangles with marks inside them, drawn in Tag Mode or in the app. Actions: list (every frame of the project, without marks), page (the frames of one page at any depth, with marks), get (one frame with its marks). Read-only: frames are drawn and edited in Tag Mode or the app, never here. A frame name is documentation; the marks inside it carry the meaning. A frame that extends another stores only what it adds, so its tags may carry only the fields they change. Marks are { tags, note }: tags is one flat list of tags, each with an id, a kind such as entity, property or action, a name, and a parentId naming the tag it sits under; note is the frame\u2019s own description and thread. Use hub_manage action "knowledge" with a frameId or markId to read what people wrote on a frame. A markId is a tag id: a tag\u2019s id, parentId and threadRef come back literal when they have the shape the app mints, so they can be passed straight back; every other string value in the marks is wrapped as data, and so is an object key that is not a plain identifier.';
2564
2564
  var FRAME_MANAGE_INPUT_SCHEMA = {
2565
2565
  action: z9.enum(["list", "page", "get"]).describe(
2566
2566
  "list the project\u2019s frames, read one page with marks, or read one frame"
@@ -2584,8 +2584,8 @@ var annotations9 = {
2584
2584
  var FRAME_HINT_OPEN_PAGE_OR_GET = 'Use action "page" with a pageKey (a frame\u2019s source.key) to read a page with marks, or action "get" with a frameId.';
2585
2585
  var FRAME_HINT_NAMES_ARE_DOCUMENTATION = "Frame names are documentation; the marks inside a frame carry the meaning.";
2586
2586
  var FRAME_HINT_NONE_YET = "This project has no frames yet. Frames are drawn in Tag Mode or the app, not through this tool.";
2587
- var FRAME_HINT_MARK_SPACE = "Marks are in their frame\u2019s own 0..1 space; a child frame sits inside its parent through placements[].rect.";
2588
- var FRAME_HINT_READ_KNOWLEDGE = 'Use hub_manage action "knowledge" with frameId (and markId) to read what people wrote here. A markId is an id from these marks, and an entity action is addressed by its own id, never by its raw text.';
2587
+ var FRAME_HINT_MARK_SPACE = "Tag geometry is fractional: a rect is 0..1 of its frame, and an at is 0..1 of its parent tag\u2019s box, or of the frame for a root tag; a child frame sits inside its parent through placements[].rect.";
2588
+ var FRAME_HINT_READ_KNOWLEDGE = 'Use hub_manage action "knowledge" with frameId (and markId) to read what people wrote here. A markId is a tag id from these marks, and a tag\u2019s threadRef is the id of its thread entry there.';
2589
2589
  var FRAME_HINT_NONE_ON_PAGE = 'No frames on this page. Check the pageKey against the source.key values from action "list".';
2590
2590
  var FRAME_HINT_EXTENDS_BASE = "This frame extends another and stores only what it adds; read the base frame (extends) for the rest.";
2591
2591
  var FRAME_NOT_FOUND_HINT = 'Use action "list" or "page" to find frame ids.';
@@ -2621,67 +2621,59 @@ function serializeLean(frame) {
2621
2621
  function isRecord2(value) {
2622
2622
  return typeof value === "object" && value !== null && !Array.isArray(value);
2623
2623
  }
2624
- function actionMarkId(entityId, raw) {
2625
- return `${entityId}#action.${raw}`;
2626
- }
2627
- var MARK_ADDRESS_KEYS = /* @__PURE__ */ new Set([
2628
- // The mark id itself, and a component of the data and action addresses.
2629
- "id",
2630
- // The first half of an ambient address, `ambient.<kind>.<key>`, and the
2631
- // discriminator a reader branches on.
2632
- "kind",
2633
- // An entity's pointer at another entity, which is that entity's mark id.
2634
- "link",
2635
- // The thread a note became, which action "note_add" takes as threadId.
2636
- "threadRef"
2624
+ var TAG_ID_PATTERN = /^[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*(?:#(?:data\.v?[0-9]+|action\.[0-9]+|context\.[0-9]+|[0-9]+))?$/;
2625
+ var MAX_TAG_ID_CHARS = 200;
2626
+ var THREAD_ID_PATTERN = /^thr_[a-z0-9]{21}$/;
2627
+ var isTagId = (value) => value.length <= MAX_TAG_ID_CHARS && TAG_ID_PATTERN.test(value);
2628
+ var isThreadId = (value) => THREAD_ID_PATTERN.test(value);
2629
+ var TAG_ADDRESSES = /* @__PURE__ */ new Map([
2630
+ // The tag id: the markId `hub_manage` action "knowledge" takes, which the
2631
+ // app joins to the frame id as the anchor key `<frameId>:<markId>`.
2632
+ ["id", isTagId],
2633
+ // The tag this one sits under, which is that tag's id: the only relation
2634
+ // between tags, so a reader joins it to `id` to rebuild the tree, and it is
2635
+ // a markId in its own right.
2636
+ ["parentId", isTagId],
2637
+ // The hub thread this tag's note thread became: the `id` of the thread
2638
+ // entry `hub_manage` action "knowledge" returns for this tag.
2639
+ ["threadRef", isThreadId]
2637
2640
  ]);
2638
- var MARK_ADDRESS_LIST_KEYS = /* @__PURE__ */ new Set([
2639
- // The entities a context band covers, by their mark ids.
2640
- "covers"
2641
- ]);
2642
- var MARK_PAGE_DATA_KEYS = /* @__PURE__ */ new Set(["anchor", "actionAnchors"]);
2643
- function isProseKeyedRecord(key, owner) {
2644
- return key === "data" && typeof owner.kind !== "string";
2645
- }
2646
- function walkMarks(value, inPageData = false) {
2641
+ var NOTE_ADDRESSES = /* @__PURE__ */ new Map(
2642
+ [["threadRef", isThreadId]]
2643
+ );
2644
+ var MARK_KEY_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$-]{0,63}$/;
2645
+ var markKey = (key) => MARK_KEY_PATTERN.test(key) ? key : wrapUserData(key);
2646
+ function walkText(value) {
2647
2647
  if (typeof value === "string") return wrapUserData(value);
2648
- if (Array.isArray(value)) {
2649
- return value.map((item) => walkMarks(item, inPageData));
2650
- }
2648
+ if (Array.isArray(value)) return value.map(walkText);
2651
2649
  if (!isRecord2(value)) return value;
2652
- const entityId = typeof value.id === "string" ? value.id : void 0;
2653
2650
  const out = {};
2654
2651
  for (const [key, child] of Object.entries(value)) {
2655
- if (MARK_PAGE_DATA_KEYS.has(key)) {
2656
- out[key] = walkMarks(child, true);
2657
- } else if (!inPageData && isRecord2(child) && isProseKeyedRecord(key, value)) {
2658
- out[key] = proseKeyedPairs(child);
2652
+ out[markKey(key)] = walkText(child);
2653
+ }
2654
+ return out;
2655
+ }
2656
+ function walkMarks(marks) {
2657
+ const out = {};
2658
+ for (const [key, value] of Object.entries(marks)) {
2659
+ if (key === "tags" && Array.isArray(value)) {
2660
+ out[key] = value.map((tag) => walkAddressed(tag, TAG_ADDRESSES));
2661
+ } else if (key === "note") {
2662
+ out[key] = walkAddressed(value, NOTE_ADDRESSES);
2659
2663
  } else {
2660
- out[key] = walkMarkEntry(key, child, entityId, inPageData);
2664
+ out[markKey(key)] = walkText(value);
2661
2665
  }
2662
2666
  }
2663
2667
  return out;
2664
2668
  }
2665
- function proseKeyedPairs(record) {
2666
- return Object.entries(record).map(([key, value]) => ({
2667
- key: wrapUserData(key),
2668
- value: walkMarks(value)
2669
- }));
2670
- }
2671
- function walkMarkEntry(key, child, entityId, inPageData) {
2672
- if (inPageData) return walkMarks(child, true);
2673
- if (MARK_ADDRESS_KEYS.has(key) && typeof child === "string") return child;
2674
- if (MARK_ADDRESS_LIST_KEYS.has(key) && Array.isArray(child)) {
2675
- return child.map(
2676
- (item) => typeof item === "string" ? item : walkMarks(item)
2677
- );
2678
- }
2679
- if (key === "actions" && entityId !== void 0 && Array.isArray(child)) {
2680
- return child.map(
2681
- (raw) => typeof raw === "string" ? { id: actionMarkId(entityId, raw), raw: wrapUserData(raw) } : walkMarks(raw)
2682
- );
2669
+ function walkAddressed(value, addresses) {
2670
+ if (!isRecord2(value)) return walkText(value);
2671
+ const out = {};
2672
+ for (const [key, field] of Object.entries(value)) {
2673
+ const isAddress = addresses.get(key);
2674
+ out[markKey(key)] = isAddress !== void 0 && typeof field === "string" && isAddress(field) ? field : walkText(field);
2683
2675
  }
2684
- return walkMarks(child);
2676
+ return out;
2685
2677
  }
2686
2678
  function serializeFrame(frame) {
2687
2679
  return {
@@ -2833,7 +2825,7 @@ async function feedbackHandlerBody(client, input) {
2833
2825
  const isAnonymous = explicitAnonymous ?? anonymous ?? true;
2834
2826
  await client.submitFeedback(text, {
2835
2827
  anonymous: isAnonymous,
2836
- version: "4.6.1"
2828
+ version: "4.7.0-next-1790187973605"
2837
2829
  });
2838
2830
  return mcpResult10({ ok: true });
2839
2831
  } catch (error) {
@@ -3196,7 +3188,7 @@ var inputSchema11 = {
3196
3188
  // Override the (optional) CLI `step` shape: the simulate handler hard-requires
3197
3189
  // a target step (no all-steps mode), so the registered schema must be honest.
3198
3190
  step: z12.string().describe(
3199
- 'Required. Target step as "type.name" \u2014 e.g. "source.demo", "destination.gtag", "transformer.router".'
3191
+ 'Required. Target step as "type.name", e.g. "source.demo", "collector.default", "destination.gtag", "transformer.router". A collector step runs enrichment and then collector.next, returning every event the destinations would receive (none after a stop).'
3200
3192
  ),
3201
3193
  verbose: z12.boolean().optional().describe("Include full payload per destination (default: false)"),
3202
3194
  ingest: z12.record(z12.string(), z12.unknown()).optional().describe(
@@ -3469,7 +3461,7 @@ var NPM_SEARCH_URL = "https://registry.npmjs.org/-/v1/search";
3469
3461
  var JSDELIVR_BASE = "https://cdn.jsdelivr.net/npm";
3470
3462
  var WALKEROS_JSON_PATH = "dist/walkerOS.json";
3471
3463
  var CACHE_TTL = 5 * 60 * 1e3;
3472
- var CLIENT_HEADER = "walkeros-mcp/4.6.1";
3464
+ var CLIENT_HEADER = "walkeros-mcp/4.7.0-next-1790187973605";
3473
3465
  function getPackageBaseUrl() {
3474
3466
  return process.env.WALKEROS_APP_URL || void 0;
3475
3467
  }
@@ -24283,9 +24275,10 @@ function registerAddStepPrompt(server) {
24283
24275
  "",
24284
24276
  "Important:",
24285
24277
  "- Read the walkeros://reference/flow-schema resource to understand connection rules.",
24286
- "- Sources connect to pre-collector transformers via `next`.",
24287
- "- Destinations connect to post-collector transformers via `before`.",
24288
- '- Routing supports string IDs, sequences (`["a", "b"]`), or RouteConfig (`{ match?, next }` for gated single-target or `{ match?, one: [...] }` for first-match dispatch). Use `many` (instead of `one`) when every matching entry should run as an independent parallel flow \u2014 restricted to pre-collector positions. Omit `match` for always-match.',
24278
+ "- Sources connect to transformers via `next` (runs before the collector).",
24279
+ "- The collector connects to transformers via `collector.next` (runs once per event before the destination fan-out, for every destination).",
24280
+ "- Destinations connect to transformers via `before` (runs for that destination only; put per-destination filtering here).",
24281
+ '- Routing uses one grammar in every chain field: string IDs, sequences (`["a", "b"]`, where a member\'s own `next` runs right after it), or RouteConfig (`{ match?, next }` for a gated link, `{ match?, one: [...] }` for first-match dispatch, `{ match?, many: [...] }` to fork each match into its own copy that finishes the rest of the path, `{ match?, stop: true }` to drop). A `stop` in `collector.next` drops the event for all destinations. Omit `match` for always-match.',
24289
24282
  "- A transformer entry can be code-bearing (`code`), package-bearing (`package`), or a **pass-through step** (no `code`, no `package`). Pass-through synthesis is automatic at runtime. Three flavors of pass-through: `before`/`next`-only (named hop reusable across destinations), `cache`-only (dedup, rate-limit), or `mapping`-only (declarative event-to-event transform). A pass-through must declare at least one of `before`, `next`, `cache`, or `mapping`.",
24290
24283
  "- The `mapping` field on a transformer step uses the same `Mapping.Config` shape as destinations, but the semantic is event-to-event (mutates the event in place via `policy`, per-rule `policy`, `mapping[].name` for renames, `mapping[].ignore` to drop). Vendor-payload fields (`data`, `silent`) are no-ops at this position.",
24291
24284
  "- Closed schema: unknown top-level keys on a transformer step are errors (catches typos like `dedup` instead of `cache`). `code` + `package` together is a conflict.",
@@ -24424,7 +24417,7 @@ var SERVER_INSTRUCTIONS = `walkerOS is an open-source, privacy-first event data
24424
24417
 
24425
24418
  ## Architecture: Source \u2192 Collector \u2192 Destination(s)
24426
24419
 
24427
- Every component in a flow is a **step**: sources capture events, transformers process them, destinations deliver them, stores provide shared state. Steps connect via \`next\` (pre-collector) and \`before\` (post-collector) chains.
24420
+ Every component in a flow is a **step**: sources capture events, transformers process them, destinations deliver them, stores provide shared state. Steps connect via chains: \`source.next\` runs before the collector, \`collector.next\` runs once per event before the destination fan-out (all destinations), and \`destination.before\` runs for one destination.
24428
24421
 
24429
24422
  ## Flow Config Structure
24430
24423
 
@@ -24452,11 +24445,11 @@ Every component in a flow is a **step**: sources capture events, transformers pr
24452
24445
  - **Contracts** define event schemas using entity-action keying. Can generate FROM mappings or scaffold mappings FROM contracts.
24453
24446
  - **Variables** ($var, $env, $secret, $code, $store) enable DRY, environment-aware config. \`$var.name\` is a reusable flow variable from the top-level \`variables\` block; whole-string refs preserve native type (object/array/scalar), inline interpolation requires a scalar, deep paths via \`$var.name.deep.path\`. \`$env.NAME[:default]\` is an environment variable resolved at bundle/deploy time (non-secret config only). \`$secret.NAME\` is a managed secret the deploy pipeline injects into the server runner at runtime; credentials, tokens, and private keys must use \`$secret\`, not \`$env\`.
24454
24447
  - **Consent** gates destinations, mapping rules, and individual fields. Privacy-first by design.
24455
- - **Routing** wires steps via \`next\` (pre-collector) and \`before\` (post-collector). A route is a string ID, a sequence (\`["a", "b"]\`), or a RouteConfig (\`{ match?, next }\` or \`{ match?, one: [...] }\`). The \`one\` operator dispatches first-match against an ordered list of branches. Use \`many\` (instead of \`one\`) when every matching entry should run as an independent parallel flow \u2014 restricted to pre-collector positions. The optional \`match\` field is omitted to mean always-match (no wildcard literal).
24448
+ - **Routing** uses one grammar in every chain field (\`source.before\`, \`source.next\`, \`transformer.before\`, \`transformer.next\`, \`collector.next\`, \`destination.before\`, \`destination.next\`). A route is a string ID, a sequence (\`["a", "b"]\`), or a RouteConfig: \`{ match?, next }\`, \`{ match?, one: [...] }\` (first match wins), \`{ match?, many: [...] }\` (every match becomes its own copy of the event with its own id and finishes the rest of the path on its own, never merged), or \`{ match?, stop: true }\` (ends that copy). In a sequence, a member's own \`next\` runs right after it, then the sequence continues. \`match\` reads \`{ ingest, event }\` and each route is evaluated when the event reaches it. A \`stop\` in \`collector.next\` drops the event for every destination; per-destination filtering belongs in \`destination.before\`. An array of only route configs is an implicit \`one\`. The optional \`match\` field is omitted to mean always-match (no wildcard literal).
24456
24449
  - **Pass-through steps** are transformer entries with no \`code\` and no \`package\`. The runtime synthesizes the push for them automatically. Three flavors share this shape: a \`before\` / \`next\`-only step (named hop reusable across destinations), a \`cache\`-only step (dedup, rate-limit), and a \`mapping\`-only step (declarative event-to-event transform). A pass-through must declare at least one of \`before\`, \`next\`, \`cache\`, or \`mapping\`.
24457
24450
  - **Mapping at the transformer position** uses the same \`Mapping.Config\` shape as destinations, but the semantic is event-to-event: \`policy\` and per-rule \`policy\`, \`mapping[].name\` (rename), \`mapping[].ignore\` (drop from chain), \`consent\`, and \`include\` apply. Vendor-payload fields (\`data\`, \`silent\`, \`mapping[].data\`) are no-ops at this position.
24458
24451
  - **Closed-schema rule on transformer entries:** known keys only. Operative keys are \`code\`, \`package\`, \`before\`, \`next\`, \`cache\`, \`mapping\`. Combined with structural keys (\`config\`, \`env\`, \`validate\`, \`disabled\`, \`id\`, etc.). Unknown top-level keys on a transformer step are errors (catches typos like \`dedup: {}\` instead of nested under \`cache\`). \`code\` + \`package\` together is a conflict.
24459
- - **Cache** memoizes step output on a configured store. Set \`cache.stop: true\` to short-circuit the chain on HIT (sources default to stop-on-HIT). Set \`cache.namespace\` to prefix keys; omit it to write keys directly. \`CacheRule.match\` is optional, omit for always-match.
24452
+ - **Cache** memoizes step output on a configured store. Set \`cache.stop: true\` to short-circuit the chain on HIT (sources default to stop-on-HIT); in a source chain or \`collector.next\` that halts the event for all destinations. Set \`cache.namespace\` to prefix keys; omit it to write keys directly. \`CacheRule.match\` is optional, omit for always-match.
24460
24453
 
24461
24454
  ## Simulation Tips
24462
24455