@getmarrow/mcp 3.9.103 → 3.9.107

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 (92) hide show
  1. package/README.md +43 -6
  2. package/dist/approval-reply.d.ts +2 -0
  3. package/dist/approval-reply.d.ts.map +1 -0
  4. package/dist/approval-reply.js +18 -0
  5. package/dist/approval-reply.js.map +1 -0
  6. package/dist/cli.js +1677 -1636
  7. package/dist/cli.js.map +1 -1
  8. package/dist/codex-plugin-pins.d.ts.map +1 -1
  9. package/dist/codex-plugin-pins.js +18 -0
  10. package/dist/codex-plugin-pins.js.map +1 -1
  11. package/dist/env.d.ts +8 -0
  12. package/dist/env.d.ts.map +1 -1
  13. package/dist/env.js +83 -4
  14. package/dist/env.js.map +1 -1
  15. package/dist/hook-context.d.ts.map +1 -1
  16. package/dist/hook-context.js +25 -0
  17. package/dist/hook-context.js.map +1 -1
  18. package/dist/hook-contract.d.ts +4 -3
  19. package/dist/hook-contract.d.ts.map +1 -1
  20. package/dist/hook-contract.js +43 -6
  21. package/dist/hook-contract.js.map +1 -1
  22. package/dist/hook-pre-action.d.ts +43 -7
  23. package/dist/hook-pre-action.d.ts.map +1 -1
  24. package/dist/hook-pre-action.js +518 -21
  25. package/dist/hook-pre-action.js.map +1 -1
  26. package/dist/hook-tool-policy.d.ts +86 -4
  27. package/dist/hook-tool-policy.d.ts.map +1 -1
  28. package/dist/hook-tool-policy.js +354 -21
  29. package/dist/hook-tool-policy.js.map +1 -1
  30. package/dist/hook.d.ts.map +1 -1
  31. package/dist/hook.js +5 -3
  32. package/dist/hook.js.map +1 -1
  33. package/dist/host-approval-state.d.ts +24 -0
  34. package/dist/host-approval-state.d.ts.map +1 -1
  35. package/dist/host-approval-state.js +68 -0
  36. package/dist/host-approval-state.js.map +1 -1
  37. package/dist/host-approval.d.ts +22 -1
  38. package/dist/host-approval.d.ts.map +1 -1
  39. package/dist/host-approval.js +65 -4
  40. package/dist/host-approval.js.map +1 -1
  41. package/dist/index.d.ts +5 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +8 -1
  44. package/dist/index.js.map +1 -1
  45. package/dist/keyless-server.d.ts +53 -0
  46. package/dist/keyless-server.d.ts.map +1 -0
  47. package/dist/keyless-server.js +230 -0
  48. package/dist/keyless-server.js.map +1 -0
  49. package/dist/normalized-action.d.ts +11 -3
  50. package/dist/normalized-action.d.ts.map +1 -1
  51. package/dist/normalized-action.js +305 -49
  52. package/dist/normalized-action.js.map +1 -1
  53. package/dist/own-server-identity.d.ts +22 -3
  54. package/dist/own-server-identity.d.ts.map +1 -1
  55. package/dist/own-server-identity.js +108 -31
  56. package/dist/own-server-identity.js.map +1 -1
  57. package/dist/own-tool.d.ts +14 -6
  58. package/dist/own-tool.d.ts.map +1 -1
  59. package/dist/own-tool.js +18 -7
  60. package/dist/own-tool.js.map +1 -1
  61. package/dist/seatbelt/env-dump.d.ts +66 -0
  62. package/dist/seatbelt/env-dump.d.ts.map +1 -0
  63. package/dist/seatbelt/env-dump.js +333 -0
  64. package/dist/seatbelt/env-dump.js.map +1 -0
  65. package/dist/seatbelt/env-names.d.ts +22 -0
  66. package/dist/seatbelt/env-names.d.ts.map +1 -0
  67. package/dist/seatbelt/env-names.js +298 -0
  68. package/dist/seatbelt/env-names.js.map +1 -0
  69. package/dist/seatbelt/fallback-copy.d.ts +16 -0
  70. package/dist/seatbelt/fallback-copy.d.ts.map +1 -0
  71. package/dist/seatbelt/fallback-copy.js +68 -0
  72. package/dist/seatbelt/fallback-copy.js.map +1 -0
  73. package/dist/seatbelt/hook.d.ts +21 -2
  74. package/dist/seatbelt/hook.d.ts.map +1 -1
  75. package/dist/seatbelt/hook.js +45 -11
  76. package/dist/seatbelt/hook.js.map +1 -1
  77. package/dist/seatbelt/mapper.d.ts.map +1 -1
  78. package/dist/seatbelt/mapper.js +1592 -85
  79. package/dist/seatbelt/mapper.js.map +1 -1
  80. package/dist/seatbelt/tables.d.ts +1 -1
  81. package/dist/seatbelt/tables.d.ts.map +1 -1
  82. package/dist/seatbelt/tables.js +13 -17
  83. package/dist/seatbelt/tables.js.map +1 -1
  84. package/dist/secret-paths.d.ts +40 -0
  85. package/dist/secret-paths.d.ts.map +1 -0
  86. package/dist/secret-paths.js +59 -0
  87. package/dist/secret-paths.js.map +1 -0
  88. package/dist/session-loop-guard.d.ts.map +1 -1
  89. package/dist/session-loop-guard.js +25 -6
  90. package/dist/session-loop-guard.js.map +1 -1
  91. package/package.json +2 -2
  92. package/server.json +2 -2
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Keyless start of the MCP server. With no Marrow key anywhere the server reads
3
+ * one, the server used to print "MARROW_API_KEY environment variable is
4
+ * required" and exit 1, which hosts show as a broken server. It now answers the
5
+ * MCP protocol with zero tools and an `instructions` string that says how the
6
+ * owner connects a key.
7
+ *
8
+ * Fail closed: keylessStart is true only for a clear "no key". A key, anything
9
+ * key-shaped, a refused owner key file, a base URL the server would refuse, or
10
+ * any doubt runs the real server path exactly as before.
11
+ *
12
+ * The keyless server judges, checks and records nothing. It starts no child
13
+ * process, opens no network and no file, reads no environment, and writes only
14
+ * to stdout and stderr. Hooks are separate entrypoints and are not touched.
15
+ * Protocol handling matches the plugin launcher's keyless stub
16
+ * (marrow-plugins plugins/<plugin>/scripts/marrow-launch.cjs, serveKeyless).
17
+ *
18
+ * Never looser than the exit 1 it replaces: until a valid `initialize` request has
19
+ * been answered, a frame that is not JSON-RPC 2.0 (a Cursor or Claude hook payload
20
+ * piped to the entry, a parse error, an oversize line) or an end of stdin ends the
21
+ * process with the no-key refusal on stderr, nothing on stdout, and exit 1. After
22
+ * an initialize, the end of stdin is exit 0.
23
+ *
24
+ * The key text (URL, activate command, plugin steps, the refusal) is owned by cli.ts
25
+ * and passed in; this file holds no second copy of it.
26
+ */
27
+ export interface KeylessInstructionParts {
28
+ getKeyUrl: string;
29
+ activateCommand: string;
30
+ /** Set when the server runs under the Claude Code plugin: its key steps replace the activate command. */
31
+ pluginSteps?: string;
32
+ }
33
+ /** The `instructions` string of the initialize answer. */
34
+ export declare function keylessInstructions(parts: KeylessInstructionParts): string;
35
+ export interface KeylessTexts {
36
+ instructions: string;
37
+ /** Written to stderr once, when the first initialize is answered. */
38
+ notice: string;
39
+ /** The server's own no-key refusal, written to stderr before the exit 1 that a non-MCP first frame or an early end of stdin gets. */
40
+ refusal: string;
41
+ }
42
+ export declare const KEYLESS_NOTICE = "Marrow: no Marrow key on this machine, so the Marrow MCP server started with no tools. Marrow hooks, where they are set up, keep their free keyless seatbelt.";
43
+ /**
44
+ * Whether the MCP server starts keyless. `resolved` must be the server's own resolveMarrowEnv() result.
45
+ * True only when it found no key (an empty MARROW_API_KEY or MARROW_KEY counts as none, a whitespace one does
46
+ * not), no owner key file was refused, no `--key` argument is given in any form, no fleet key
47
+ * (MARROW_KEY_<SUFFIX>) is set, and the base URL passes the server's own check.
48
+ */
49
+ export declare function keylessStart(resolved: unknown, argv: readonly unknown[], env: Record<string, string | undefined>): boolean;
50
+ export declare function keylessProtocolVersion(params: unknown): string;
51
+ /** Newline-delimited JSON-RPC 2.0 on stdio with zero tools. Exits 0 when stdin ends after an initialize, 1 for a non-MCP start. */
52
+ export declare function serveKeylessMcp(serverVersion: string, texts: KeylessTexts): void;
53
+ //# sourceMappingURL=keyless-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyless-server.d.ts","sourceRoot":"","sources":["../src/keyless-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,yGAAyG;IACzG,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAS1E;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,qIAAqI;IACrI,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,cAAc,kKAAkK,CAAC;AAQ9L;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAe1H;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAO9D;AAED,mIAAmI;AACnI,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAyHhF"}
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ /**
3
+ * Keyless start of the MCP server. With no Marrow key anywhere the server reads
4
+ * one, the server used to print "MARROW_API_KEY environment variable is
5
+ * required" and exit 1, which hosts show as a broken server. It now answers the
6
+ * MCP protocol with zero tools and an `instructions` string that says how the
7
+ * owner connects a key.
8
+ *
9
+ * Fail closed: keylessStart is true only for a clear "no key". A key, anything
10
+ * key-shaped, a refused owner key file, a base URL the server would refuse, or
11
+ * any doubt runs the real server path exactly as before.
12
+ *
13
+ * The keyless server judges, checks and records nothing. It starts no child
14
+ * process, opens no network and no file, reads no environment, and writes only
15
+ * to stdout and stderr. Hooks are separate entrypoints and are not touched.
16
+ * Protocol handling matches the plugin launcher's keyless stub
17
+ * (marrow-plugins plugins/<plugin>/scripts/marrow-launch.cjs, serveKeyless).
18
+ *
19
+ * Never looser than the exit 1 it replaces: until a valid `initialize` request has
20
+ * been answered, a frame that is not JSON-RPC 2.0 (a Cursor or Claude hook payload
21
+ * piped to the entry, a parse error, an oversize line) or an end of stdin ends the
22
+ * process with the no-key refusal on stderr, nothing on stdout, and exit 1. After
23
+ * an initialize, the end of stdin is exit 0.
24
+ *
25
+ * The key text (URL, activate command, plugin steps, the refusal) is owned by cli.ts
26
+ * and passed in; this file holds no second copy of it.
27
+ */
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.KEYLESS_NOTICE = void 0;
30
+ exports.keylessInstructions = keylessInstructions;
31
+ exports.keylessStart = keylessStart;
32
+ exports.keylessProtocolVersion = keylessProtocolVersion;
33
+ exports.serveKeylessMcp = serveKeylessMcp;
34
+ const index_1 = require("./index");
35
+ /** The `instructions` string of the initialize answer. */
36
+ function keylessInstructions(parts) {
37
+ const connect = parts.pluginSteps
38
+ ? `To connect a Marrow account, the owner follows these steps. ${parts.pluginSteps} `
39
+ : `To connect a Marrow account, the owner creates a key at ${parts.getKeyUrl} and runs ${parts.activateCommand} in their own terminal, then restarts this agent host. `;
40
+ return 'This Marrow server started without a Marrow key on this machine, so it has no tools. '
41
+ + 'It does not judge, check or record any action. '
42
+ + (parts.pluginSteps ? '' : 'Marrow hooks, where they are set up on this machine, are separate from this server and keep their free keyless seatbelt; this server does not show whether any are set up. ')
43
+ + connect
44
+ + 'A key can not be added from this chat.';
45
+ }
46
+ exports.KEYLESS_NOTICE = 'Marrow: no Marrow key on this machine, so the Marrow MCP server started with no tools. Marrow hooks, where they are set up, keep their free keyless seatbelt.';
47
+ // The real server's protocolVersion rule (cli.ts noteClientCapabilities): the requested version only when it is one
48
+ // of these AND the client's capabilities.elicitation is an object; every other input gets 2024-11-05.
49
+ const ELICITATION_PROTOCOL_VERSIONS = ['2025-06-18', '2025-11-25'];
50
+ const DEFAULT_PROTOCOL_VERSION = '2024-11-05';
51
+ const MAX_LINE_BYTES = 1024 * 1024;
52
+ /**
53
+ * Whether the MCP server starts keyless. `resolved` must be the server's own resolveMarrowEnv() result.
54
+ * True only when it found no key (an empty MARROW_API_KEY or MARROW_KEY counts as none, a whitespace one does
55
+ * not), no owner key file was refused, no `--key` argument is given in any form, no fleet key
56
+ * (MARROW_KEY_<SUFFIX>) is set, and the base URL passes the server's own check.
57
+ */
58
+ function keylessStart(resolved, argv, env) {
59
+ try {
60
+ if (argv.some((arg) => typeof arg !== 'string' || arg.startsWith('--key')))
61
+ return false;
62
+ if (resolved === null || typeof resolved !== 'object')
63
+ return false;
64
+ const result = resolved;
65
+ if (result.apiKey !== '' || result.missing !== true || result.source !== null || result.ownerFileRefused !== undefined)
66
+ return false;
67
+ // The resolver uses a fleet key only with a direct key and a matching agent identity; one set without them is still a key.
68
+ if (Object.keys(env).some((name) => name.startsWith('MARROW_KEY_') && Boolean(env[name])))
69
+ return false;
70
+ const baseUrl = result.baseUrl || 'https://api.getmarrow.ai';
71
+ if (typeof baseUrl !== 'string')
72
+ return false;
73
+ (0, index_1.validateBaseUrl)(baseUrl);
74
+ return true;
75
+ }
76
+ catch {
77
+ return false;
78
+ }
79
+ }
80
+ function keylessProtocolVersion(params) {
81
+ const record = params && typeof params === 'object' ? params : {};
82
+ const capabilities = record.capabilities && typeof record.capabilities === 'object' ? record.capabilities : {};
83
+ const requested = typeof record.protocolVersion === 'string' ? record.protocolVersion : '';
84
+ const elicits = Boolean(capabilities.elicitation && typeof capabilities.elicitation === 'object')
85
+ && ELICITATION_PROTOCOL_VERSIONS.includes(requested);
86
+ return elicits ? requested : DEFAULT_PROTOCOL_VERSION;
87
+ }
88
+ /** Newline-delimited JSON-RPC 2.0 on stdio with zero tools. Exits 0 when stdin ends after an initialize, 1 for a non-MCP start. */
89
+ function serveKeylessMcp(serverVersion, texts) {
90
+ const has = (object, key) => Object.prototype.hasOwnProperty.call(object, key);
91
+ const send = (id, body) => process.stdout.write(`${JSON.stringify({ jsonrpc: '2.0', id, ...body })}\n`);
92
+ const refuse = (id, code, message) => send(id, { error: { code, message } });
93
+ let initialized = false;
94
+ // Today's no-key exit: the refusal on stderr, nothing on stdout, exit 1.
95
+ function exitAsNoKey() {
96
+ try {
97
+ process.stderr.write(texts.refusal);
98
+ }
99
+ catch {
100
+ // a closed stderr changes nothing
101
+ }
102
+ process.exit(1);
103
+ }
104
+ // A frame that is not a usable JSON-RPC 2.0 message. Before an initialize it proves the process was not started by an MCP host.
105
+ function badFrame(id, code, message) {
106
+ if (!initialized)
107
+ exitAsNoKey();
108
+ refuse(id, code, message);
109
+ }
110
+ function handle(text) {
111
+ let msg;
112
+ try {
113
+ msg = JSON.parse(text);
114
+ }
115
+ catch {
116
+ badFrame(null, -32700, 'Parse error.');
117
+ return;
118
+ }
119
+ if (msg === null || typeof msg !== 'object' || Array.isArray(msg)) {
120
+ badFrame(null, -32600, 'Invalid request.');
121
+ return;
122
+ }
123
+ const request = msg;
124
+ if (request.jsonrpc !== '2.0' || typeof request.method !== 'string') {
125
+ badFrame(null, -32600, 'Invalid request.');
126
+ return;
127
+ }
128
+ if (!has(request, 'id'))
129
+ return; // a notification gets no reply
130
+ const id = request.id;
131
+ if (!(typeof id === 'string' || id === null || (typeof id === 'number' && Number.isFinite(id)))) {
132
+ badFrame(null, -32600, 'Invalid request.');
133
+ return;
134
+ }
135
+ if (request.method === 'initialize') {
136
+ initialized = true;
137
+ try {
138
+ process.stderr.write(texts.notice);
139
+ }
140
+ catch {
141
+ // a closed stderr changes nothing
142
+ }
143
+ send(id, {
144
+ result: {
145
+ protocolVersion: keylessProtocolVersion(request.params),
146
+ capabilities: { tools: { listChanged: false } },
147
+ serverInfo: { name: 'marrow', version: serverVersion },
148
+ instructions: texts.instructions,
149
+ },
150
+ });
151
+ return;
152
+ }
153
+ if (!initialized) {
154
+ refuse(id, -32002, 'Server not initialized. Send initialize first.');
155
+ return;
156
+ }
157
+ switch (request.method) {
158
+ case 'ping':
159
+ send(id, { result: {} });
160
+ return;
161
+ case 'tools/list':
162
+ send(id, { result: { tools: [] } });
163
+ return;
164
+ case 'prompts/list':
165
+ send(id, { result: { prompts: [] } });
166
+ return;
167
+ case 'resources/list':
168
+ send(id, { result: { resources: [] } });
169
+ return;
170
+ case 'resources/templates/list':
171
+ send(id, { result: { resourceTemplates: [] } });
172
+ return;
173
+ case 'tools/call':
174
+ refuse(id, -32602, 'This server has no tools.');
175
+ return;
176
+ default: refuse(id, -32601, 'Method not found.');
177
+ }
178
+ }
179
+ function dispatch(chunks) {
180
+ const text = Buffer.concat(chunks).toString('utf8');
181
+ if (!text.trim())
182
+ return;
183
+ try {
184
+ handle(text);
185
+ }
186
+ catch {
187
+ badFrame(null, -32603, 'Internal error.');
188
+ }
189
+ }
190
+ let chunks = [];
191
+ let size = 0;
192
+ let skipping = false; // inside a line over the limit: dropped up to the next newline, never buffered
193
+ process.stdout.on('error', () => process.exit(initialized ? 0 : 1));
194
+ process.stdin.on('error', () => { process.exitCode = 1; });
195
+ process.stdin.on('data', (data) => {
196
+ const chunk = typeof data === 'string' ? Buffer.from(data, 'utf8') : data;
197
+ let from = 0;
198
+ while (from < chunk.length) {
199
+ const newline = chunk.indexOf(10, from);
200
+ const to = newline === -1 ? chunk.length : newline;
201
+ if (!skipping) {
202
+ size += to - from;
203
+ if (size > MAX_LINE_BYTES) {
204
+ skipping = true;
205
+ chunks = [];
206
+ size = 0;
207
+ badFrame(null, -32600, 'Request too large.');
208
+ }
209
+ else if (to > from) {
210
+ chunks.push(chunk.subarray(from, to));
211
+ }
212
+ }
213
+ if (newline === -1)
214
+ return;
215
+ if (!skipping)
216
+ dispatch(chunks);
217
+ chunks = [];
218
+ size = 0;
219
+ skipping = false;
220
+ from = newline + 1;
221
+ }
222
+ });
223
+ process.stdin.on('end', () => {
224
+ if (!skipping)
225
+ dispatch(chunks);
226
+ if (!initialized)
227
+ exitAsNoKey(); // empty stdin, or an end before any initialize: no MCP host ever spoke
228
+ });
229
+ }
230
+ //# sourceMappingURL=keyless-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyless-server.js","sourceRoot":"","sources":["../src/keyless-server.ts"],"names":[],"mappings":"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"}
@@ -99,6 +99,7 @@ type ToolEvent = {
99
99
  tool_name?: unknown;
100
100
  tool_input?: unknown;
101
101
  };
102
+ export declare const KNOWN_KEY_PREFIX: RegExp;
102
103
  /** A value shaped like a key, token or password hash (mixed-case random text, long hex, known prefixes). */
103
104
  export declare function looksLikeKey(value: string): boolean;
104
105
  type NameClass = 'credential' | 'ambiguous' | 'reference' | 'plain';
@@ -129,6 +130,13 @@ export declare function normalizeShellCommand(command: string, deadline?: number
129
130
  * word ever leaves the machine.
130
131
  */
131
132
  export declare function deployCommandText(command: string): string | null;
133
+ /** runOptionsKey as a standalone identity (no deadline), for the exact target of a call (hook-contract exactHookTarget). */
134
+ export declare function shellToolRunOptionsKey(event: ToolEvent): string | null;
135
+ /**
136
+ * The keyed hash of a hold's exact target (hook-contract exactHookTarget): the same sub-key as keyTextHash, its own
137
+ * domain. null without a usable device key (the caller then makes a target nothing can match).
138
+ */
139
+ export declare function keyedTargetHash(parts: unknown): string | null;
132
140
  /**
133
141
  * The normalized action of a hook event. `deadlineAt` bounds the time it may
134
142
  * take (default one second from now): past it, or past the size limits, the
@@ -142,9 +150,9 @@ export declare function deployCommandText(command: string): string | null;
142
150
  * credentials replaced, so two actions that differ anywhere else never share a
143
151
  * correlation, hold or key, and a retry that differs only in a certain
144
152
  * credential (an OTP) still does. A placeholder keys the raw input (up to
145
- * 1 MB). Input a host adapter cut or dropped, input over 1 MB and a missing or
146
- * unsafe salt give a random nonce: the action matches nothing (it is asked
147
- * again). `salt` is a test seam (undefined: the device salt).
153
+ * 1 MB). Input a host adapter cut or dropped, input over 1 MB and a machine with neither a
154
+ * device salt nor a usable host-approval state (exactSalt) give a random nonce: the action matches
155
+ * nothing (it is asked again). `salt` is a test seam (undefined: the device salt).
148
156
  */
149
157
  export declare function normalizedHookAction(event: ToolEvent, options?: {
150
158
  deadlineAt?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"normalized-action.d.ts","sourceRoot":"","sources":["../src/normalized-action.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7J,yGAAyG;IACzG,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB,CAAC;AAMF,yHAAyH;AACzH,eAAO,MAAM,cAAc,QAAS,CAAC;AAWrC,KAAK,SAAS,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AA8C/D,4GAA4G;AAC5G,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAUnD;AAgDD,KAAK,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;AAEpE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAW1D;AAm5BD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAWjJ;AAwHD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyChE;AA0KD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAAG,oBAAoB,CA4BxI"}
1
+ {"version":3,"file":"normalized-action.d.ts","sourceRoot":"","sources":["../src/normalized-action.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7J,yGAAyG;IACzG,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB,CAAC;AAMF,yHAAyH;AACzH,eAAO,MAAM,cAAc,QAAS,CAAC;AAWrC,KAAK,SAAS,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AA2C/D,eAAO,MAAM,gBAAgB,QAAoZ,CAAC;AAelb,4GAA4G;AAC5G,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAUnD;AAgDD,KAAK,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;AAEpE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAW1D;AAy/BD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAWjJ;AAwID;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyChE;AAuCD,4HAA4H;AAC5H,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAEtE;AA+MD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAK7D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAAG,oBAAoB,CA0CxI"}