@ratio-mcp/dev-server 1.2.0 → 1.3.0

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 (51) hide show
  1. package/dist/data/scope-webhook-map.d.ts +26 -0
  2. package/dist/data/scope-webhook-map.d.ts.map +1 -0
  3. package/dist/data/scope-webhook-map.js +117 -0
  4. package/dist/data/scope-webhook-map.js.map +1 -0
  5. package/dist/index.d.ts +5 -4
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +11 -13
  8. package/dist/index.js.map +1 -1
  9. package/dist/orchestrated-index.d.ts +4 -9
  10. package/dist/orchestrated-index.d.ts.map +1 -1
  11. package/dist/orchestrated-index.js +6 -14
  12. package/dist/orchestrated-index.js.map +1 -1
  13. package/dist/orchestrated-server.d.ts +14 -9
  14. package/dist/orchestrated-server.d.ts.map +1 -1
  15. package/dist/orchestrated-server.js +86 -48
  16. package/dist/orchestrated-server.js.map +1 -1
  17. package/dist/services/session-state.d.ts +36 -16
  18. package/dist/services/session-state.d.ts.map +1 -1
  19. package/dist/services/session-state.js +175 -140
  20. package/dist/services/session-state.js.map +1 -1
  21. package/dist/services/tool-guard.d.ts +29 -9
  22. package/dist/services/tool-guard.d.ts.map +1 -1
  23. package/dist/services/tool-guard.js +76 -50
  24. package/dist/services/tool-guard.js.map +1 -1
  25. package/dist/templates/frontend/.env.example +1 -1
  26. package/dist/templates/frontend/src/pages/Login.tsx +1 -1
  27. package/dist/tools/codegen.d.ts.map +1 -1
  28. package/dist/tools/codegen.js +206 -10
  29. package/dist/tools/codegen.js.map +1 -1
  30. package/dist/tools/get-status.d.ts +3 -0
  31. package/dist/tools/get-status.d.ts.map +1 -0
  32. package/dist/tools/get-status.js +127 -0
  33. package/dist/tools/get-status.js.map +1 -0
  34. package/dist/tools/index.d.ts.map +1 -1
  35. package/dist/tools/index.js +3 -1
  36. package/dist/tools/index.js.map +1 -1
  37. package/dist/tools/lifecycle.js +1 -1
  38. package/dist/tools/lifecycle.js.map +1 -1
  39. package/dist/tools/requirements.d.ts.map +1 -1
  40. package/dist/tools/requirements.js +41 -4
  41. package/dist/tools/requirements.js.map +1 -1
  42. package/dist/tools/scaffold.d.ts.map +1 -1
  43. package/dist/tools/scaffold.js +10 -5
  44. package/dist/tools/scaffold.js.map +1 -1
  45. package/dist/tools/webhooks.d.ts +25 -0
  46. package/dist/tools/webhooks.d.ts.map +1 -1
  47. package/dist/tools/webhooks.js +115 -89
  48. package/dist/tools/webhooks.js.map +1 -1
  49. package/dist/utils/logger.js +17 -17
  50. package/dist/utils/logger.js.map +1 -1
  51. package/package.json +16 -15
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Scope → Webhook Event Recommendations
3
+ *
4
+ * Maps confirmed OAuth scopes to relevant webhook events.
5
+ * Used after define_app_requirements to suggest which webhooks
6
+ * the developer should subscribe to based on their selected scopes.
7
+ *
8
+ * Events are sourced from docs-server/schemas/webhooks.json.
9
+ */
10
+ export interface WebhookRecommendation {
11
+ topic: string;
12
+ description: string;
13
+ resource: string;
14
+ /** Why this event is relevant given the scope */
15
+ reason: string;
16
+ }
17
+ /**
18
+ * Get recommended webhook events based on confirmed scopes.
19
+ * Deduplicates events when multiple scopes map to the same resource.
20
+ */
21
+ export declare function getWebhookRecommendations(scopes: string[]): {
22
+ recommendations: WebhookRecommendation[];
23
+ scopes_matched: string[];
24
+ scopes_without_webhooks: string[];
25
+ };
26
+ //# sourceMappingURL=scope-webhook-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-webhook-map.d.ts","sourceRoot":"","sources":["../../src/data/scope-webhook-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;CAChB;AA4ED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAC3D,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,uBAAuB,EAAE,MAAM,EAAE,CAAC;CACnC,CAkCA"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Scope → Webhook Event Recommendations
3
+ *
4
+ * Maps confirmed OAuth scopes to relevant webhook events.
5
+ * Used after define_app_requirements to suggest which webhooks
6
+ * the developer should subscribe to based on their selected scopes.
7
+ *
8
+ * Events are sourced from docs-server/schemas/webhooks.json.
9
+ */
10
+ /**
11
+ * Map of scope → recommended webhook events.
12
+ * Write scopes inherit their read scope's events.
13
+ */
14
+ const SCOPE_WEBHOOK_MAP = {
15
+ read_orders: [
16
+ {
17
+ topic: 'orders/create',
18
+ description: 'Fired when a new order is created',
19
+ resource: 'orders',
20
+ reason: 'React to new orders in real-time instead of polling',
21
+ },
22
+ {
23
+ topic: 'orders/updated',
24
+ description: 'Fired when an order is updated',
25
+ resource: 'orders',
26
+ reason: 'Track order status changes (shipping, notes, etc.)',
27
+ },
28
+ {
29
+ topic: 'orders/cancelled',
30
+ description: 'Fired when an order is cancelled',
31
+ resource: 'orders',
32
+ reason: 'Handle cancellations immediately (refunds, inventory)',
33
+ },
34
+ {
35
+ topic: 'orders/fulfilled',
36
+ description: 'Fired when an order is fulfilled',
37
+ resource: 'orders',
38
+ reason: 'Trigger post-fulfillment workflows (emails, analytics)',
39
+ },
40
+ {
41
+ topic: 'orders/paid',
42
+ description: 'Fired when an order is paid',
43
+ resource: 'orders',
44
+ reason: 'Track payment completions for revenue reporting',
45
+ },
46
+ ],
47
+ read_products: [
48
+ {
49
+ topic: 'products/create',
50
+ description: 'Fired when a new product is created',
51
+ resource: 'products',
52
+ reason: 'Sync new products to external catalogs or feeds',
53
+ },
54
+ {
55
+ topic: 'products/update',
56
+ description: 'Fired when a product is updated',
57
+ resource: 'products',
58
+ reason: 'Keep product data in sync (price changes, stock updates)',
59
+ },
60
+ {
61
+ topic: 'products/delete',
62
+ description: 'Fired when a product is deleted',
63
+ resource: 'products',
64
+ reason: 'Remove deleted products from external systems',
65
+ },
66
+ ],
67
+ };
68
+ // Write scopes inherit read scope events
69
+ SCOPE_WEBHOOK_MAP['write_orders'] = SCOPE_WEBHOOK_MAP['read_orders'];
70
+ SCOPE_WEBHOOK_MAP['write_products'] = SCOPE_WEBHOOK_MAP['read_products'];
71
+ /** Always-recommended events regardless of scopes */
72
+ const ALWAYS_RECOMMENDED = [
73
+ {
74
+ topic: 'app/uninstalled',
75
+ description: 'Fired when the app is uninstalled by a merchant',
76
+ resource: 'app',
77
+ reason: 'Clean up merchant data and revoke tokens when uninstalled',
78
+ },
79
+ ];
80
+ /**
81
+ * Get recommended webhook events based on confirmed scopes.
82
+ * Deduplicates events when multiple scopes map to the same resource.
83
+ */
84
+ export function getWebhookRecommendations(scopes) {
85
+ const seen = new Set();
86
+ const recommendations = [];
87
+ const scopesMatched = [];
88
+ const scopesWithout = [];
89
+ for (const scope of scopes) {
90
+ const events = SCOPE_WEBHOOK_MAP[scope];
91
+ if (events) {
92
+ scopesMatched.push(scope);
93
+ for (const event of events) {
94
+ if (!seen.has(event.topic)) {
95
+ seen.add(event.topic);
96
+ recommendations.push(event);
97
+ }
98
+ }
99
+ }
100
+ else {
101
+ scopesWithout.push(scope);
102
+ }
103
+ }
104
+ // Always add app/uninstalled
105
+ for (const event of ALWAYS_RECOMMENDED) {
106
+ if (!seen.has(event.topic)) {
107
+ seen.add(event.topic);
108
+ recommendations.push(event);
109
+ }
110
+ }
111
+ return {
112
+ recommendations,
113
+ scopes_matched: scopesMatched,
114
+ scopes_without_webhooks: scopesWithout,
115
+ };
116
+ }
117
+ //# sourceMappingURL=scope-webhook-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-webhook-map.js","sourceRoot":"","sources":["../../src/data/scope-webhook-map.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,11 +2,12 @@
2
2
  /**
3
3
  * Ratio Dev MCP Server — Entry Point
4
4
  *
5
- * This runs the ORCHESTRATED server by default, exposing a single `agent_chat`
6
- * tool that manages the entire app development lifecycle via a state machine.
5
+ * Tool-first architecture: exposes all tools individually with prerequisite guards.
6
+ * The LLM decides what to call; guards enforce the dependency graph.
7
7
  *
8
- * To run the legacy server (24+ individual tools), use:
9
- * RATIO_LEGACY_MODE=true node dist/index.js
8
+ * Modes:
9
+ * Default: Tool-first server (all tools with guards)
10
+ * RATIO_STANDALONE_MODE=true: Standalone server (all tools, no orchestration)
10
11
  */
11
12
  export {};
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;GASG"}
package/dist/index.js CHANGED
@@ -2,43 +2,41 @@
2
2
  /**
3
3
  * Ratio Dev MCP Server — Entry Point
4
4
  *
5
- * This runs the ORCHESTRATED server by default, exposing a single `agent_chat`
6
- * tool that manages the entire app development lifecycle via a state machine.
5
+ * Tool-first architecture: exposes all tools individually with prerequisite guards.
6
+ * The LLM decides what to call; guards enforce the dependency graph.
7
7
  *
8
- * To run the legacy server (24+ individual tools), use:
9
- * RATIO_LEGACY_MODE=true node dist/index.js
8
+ * Modes:
9
+ * Default: Tool-first server (all tools with guards)
10
+ * RATIO_STANDALONE_MODE=true: Standalone server (all tools, no orchestration)
10
11
  */
11
12
  // Load .env BEFORE any other imports so process.env is populated
12
- // Must use dynamic imports to ensure dotenv runs before constants.ts is evaluated
13
13
  import { config } from 'dotenv';
14
14
  import { resolve, dirname } from 'path';
15
15
  import { fileURLToPath } from 'url';
16
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
17
- // __dirname = dist/ → go up to: dev-server/ → packages/ → ratio-mcp-v2/
18
17
  const envPath = resolve(__dirname, '..', '..', '..', '.env');
19
18
  config({ path: envPath });
20
19
  async function main() {
21
- // Dynamic imports — these run AFTER dotenv has loaded env vars
22
20
  const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
23
21
  const { createOrchestratedServer } = await import('./orchestrated-server.js');
24
22
  const { createDevServer } = await import('./server.js');
25
23
  const { logger } = await import('./utils/logger.js');
26
- const legacyMode = process.env.RATIO_LEGACY_MODE === 'true';
24
+ const standaloneMode = process.env.RATIO_STANDALONE_MODE === 'true';
27
25
  logger.info(`Loaded .env from: ${envPath}`);
28
26
  logger.info(`RATIO_API_BASE_URL = ${process.env.RATIO_API_BASE_URL || '(not set, using default)'}`);
29
- if (legacyMode) {
30
- logger.info('Starting Ratio Dev MCP Server (Legacy Mode — 24+ tools)...');
27
+ if (standaloneMode) {
28
+ logger.info('Starting Ratio Dev MCP Server (Standalone Mode)...');
31
29
  const server = createDevServer();
32
30
  const transport = new StdioServerTransport();
33
31
  await server.connect(transport);
34
- logger.info('Ratio Dev MCP Server (Legacy) is running on stdio');
32
+ logger.info('Ratio Dev MCP Server (Standalone) is running on stdio');
35
33
  }
36
34
  else {
37
- logger.info('Starting Ratio Dev MCP Server (Orchestrated — single agent_chat tool)...');
35
+ logger.info('Starting Ratio Dev MCP Server (Tool-First Architecture)...');
38
36
  const server = createOrchestratedServer();
39
37
  const transport = new StdioServerTransport();
40
38
  await server.connect(transport);
41
- logger.info('Ratio Dev MCP Server (Orchestrated) is running on stdio');
39
+ logger.info('Ratio Dev MCP Server (Tool-First) is running on stdio');
42
40
  }
43
41
  }
44
42
  main().catch((error) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAEH,iEAAiE;AACjE,kFAAkF;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,wEAAwE;AACxE,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7D,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAE1B,KAAK,UAAU,IAAI;IACjB,+DAA+D;IAC/D,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,2CAA2C,CAAC,CAAC;IAC3F,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAC9E,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IACxD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAErD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,MAAM,CAAC;IAE5D,MAAM,CAAC,IAAI,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,0BAA0B,EAAE,CAAC,CAAC;IAEpG,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IACnE,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;GASG;AAEH,iEAAiE;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7D,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAE1B,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,2CAA2C,CAAC,CAAC;IAC3F,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAC9E,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IACxD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAErD,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,MAAM,CAAC;IAEpE,MAAM,CAAC,IAAI,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,0BAA0B,EAAE,CAAC,CAAC;IAEpG,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -1,16 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Orchestrated Ratio Dev MCP Server — Entry Point
3
+ * Ratio Dev MCP Server — Orchestrated Entry Point
4
4
  *
5
- * This is the production entry point that exposes a SINGLE `agent_chat` tool
6
- * instead of 24+ individual tools. The internal state machine ensures the
7
- * correct tool is called at the right time in the right order.
5
+ * Tool-first architecture: exposes all tools individually with prerequisite guards.
6
+ * The LLM decides what to call; guards enforce the dependency graph.
8
7
  *
9
- * Usage:
10
- * node dist/orchestrated-index.js
11
- *
12
- * Or via the bin alias:
13
- * ratio-dev-orchestrated
8
+ * This is the production entry point.
14
9
  */
15
10
  export {};
16
11
  //# sourceMappingURL=orchestrated-index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrated-index.d.ts","sourceRoot":"","sources":["../src/orchestrated-index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG"}
1
+ {"version":3,"file":"orchestrated-index.d.ts","sourceRoot":"","sources":["../src/orchestrated-index.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG"}
@@ -1,38 +1,30 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Orchestrated Ratio Dev MCP Server — Entry Point
3
+ * Ratio Dev MCP Server — Orchestrated Entry Point
4
4
  *
5
- * This is the production entry point that exposes a SINGLE `agent_chat` tool
6
- * instead of 24+ individual tools. The internal state machine ensures the
7
- * correct tool is called at the right time in the right order.
5
+ * Tool-first architecture: exposes all tools individually with prerequisite guards.
6
+ * The LLM decides what to call; guards enforce the dependency graph.
8
7
  *
9
- * Usage:
10
- * node dist/orchestrated-index.js
11
- *
12
- * Or via the bin alias:
13
- * ratio-dev-orchestrated
8
+ * This is the production entry point.
14
9
  */
15
10
  // Load .env BEFORE any other imports so process.env is populated
16
- // Must use dynamic imports to ensure dotenv runs before constants.ts is evaluated
17
11
  import { config } from 'dotenv';
18
12
  import { resolve, dirname } from 'path';
19
13
  import { fileURLToPath } from 'url';
20
14
  const __dirname = dirname(fileURLToPath(import.meta.url));
21
- // __dirname = dist/ → go up to: dev-server/ → packages/ → ratio-mcp-v2/
22
15
  const envPath = resolve(__dirname, '..', '..', '..', '.env');
23
16
  config({ path: envPath });
24
17
  async function main() {
25
- // Dynamic imports — these run AFTER dotenv has loaded env vars
26
18
  const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
27
19
  const { createOrchestratedServer } = await import('./orchestrated-server.js');
28
20
  const { logger } = await import('./utils/logger.js');
29
21
  logger.info(`Loaded .env from: ${envPath}`);
30
22
  logger.info(`RATIO_API_BASE_URL = ${process.env.RATIO_API_BASE_URL || '(not set, using default)'}`);
31
- logger.info('Starting Ratio Dev MCP Server (Orchestrated Mode)...');
23
+ logger.info('Starting Ratio Dev MCP Server (Tool-First Architecture)...');
32
24
  const server = createOrchestratedServer();
33
25
  const transport = new StdioServerTransport();
34
26
  await server.connect(transport);
35
- logger.info('Ratio Dev MCP Server (Orchestrated) is running on stdio');
27
+ logger.info('Ratio Dev MCP Server (Tool-First) is running on stdio');
36
28
  }
37
29
  main().catch((error) => {
38
30
  console.error('Fatal error:', error);
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrated-index.js","sourceRoot":"","sources":["../src/orchestrated-index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAEH,iEAAiE;AACjE,kFAAkF;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,wEAAwE;AACxE,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7D,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAE1B,KAAK,UAAU,IAAI;IACjB,+DAA+D;IAC/D,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,2CAA2C,CAAC,CAAC;IAC3F,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAC9E,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAErD,MAAM,CAAC,IAAI,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,0BAA0B,EAAE,CAAC,CAAC;IACpG,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IAEpE,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;AACzE,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"orchestrated-index.js","sourceRoot":"","sources":["../src/orchestrated-index.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;AAEH,iEAAiE;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7D,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAE1B,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,2CAA2C,CAAC,CAAC;IAC3F,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAC9E,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAErD,MAAM,CAAC,IAAI,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,0BAA0B,EAAE,CAAC,CAAC;IACpG,MAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IAE1E,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;AACvE,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -1,16 +1,21 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  /**
3
- * Create the Orchestrated Ratio Dev MCP Server.
3
+ * Create the Tool-First Ratio Dev MCP Server.
4
4
  *
5
- * Unlike the original server (which exposes 24+ individual tools),
6
- * this server exposes a SINGLE `agent_chat` tool that orchestrates
7
- * the entire app development lifecycle through a state machine.
5
+ * Exposes all tools individually (not a single agent_chat).
6
+ * Each tool call passes through the prerequisite guard.
7
+ * The LLM decides what to call based on user intent and get_status output.
8
8
  *
9
- * Benefits:
10
- * - LLM doesn't need to decide tool ordering — the orchestrator handles it
11
- * - Flow integrity is guaranteed steps can't be skipped or called out of order
12
- * - Simpler LLM integration — one tool to learn instead of 24
13
- * - Production-grade reliability deterministic state transitions
9
+ * Guard enforcement:
10
+ * - If prerequisites are met tool executes normally
11
+ * - If prerequisites are NOT met returns structured error with:
12
+ * - What's missing
13
+ * - The full chain of tools needed to unblock
14
+ * - A hint for the LLM to self-correct
15
+ *
16
+ * Session recording:
17
+ * - On success, tool results are parsed to extract context (appId, scopes, etc.)
18
+ * - This context drives future guard checks
14
19
  */
15
20
  export declare function createOrchestratedServer(): McpServer;
16
21
  //# sourceMappingURL=orchestrated-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrated-server.d.ts","sourceRoot":"","sources":["../src/orchestrated-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,IAAI,SAAS,CAsDpD"}
1
+ {"version":3,"file":"orchestrated-server.d.ts","sourceRoot":"","sources":["../src/orchestrated-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQpE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,IAAI,SAAS,CAyFpD"}
@@ -1,63 +1,101 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { DEV_SERVER_NAME, DEV_SERVER_VERSION } from '@ratio-mcp/shared';
3
- import { agentChatTool } from './tools/agent-chat.js';
3
+ import { allDevTools } from './tools/index.js';
4
4
  import { logger } from './utils/logger.js';
5
+ import { checkToolPrerequisites } from './services/tool-guard.js';
6
+ import { recordToolSuccess } from './services/session-state.js';
5
7
  /**
6
- * Create the Orchestrated Ratio Dev MCP Server.
8
+ * Create the Tool-First Ratio Dev MCP Server.
7
9
  *
8
- * Unlike the original server (which exposes 24+ individual tools),
9
- * this server exposes a SINGLE `agent_chat` tool that orchestrates
10
- * the entire app development lifecycle through a state machine.
10
+ * Exposes all tools individually (not a single agent_chat).
11
+ * Each tool call passes through the prerequisite guard.
12
+ * The LLM decides what to call based on user intent and get_status output.
11
13
  *
12
- * Benefits:
13
- * - LLM doesn't need to decide tool ordering — the orchestrator handles it
14
- * - Flow integrity is guaranteed steps can't be skipped or called out of order
15
- * - Simpler LLM integration — one tool to learn instead of 24
16
- * - Production-grade reliability deterministic state transitions
14
+ * Guard enforcement:
15
+ * - If prerequisites are met tool executes normally
16
+ * - If prerequisites are NOT met returns structured error with:
17
+ * - What's missing
18
+ * - The full chain of tools needed to unblock
19
+ * - A hint for the LLM to self-correct
20
+ *
21
+ * Session recording:
22
+ * - On success, tool results are parsed to extract context (appId, scopes, etc.)
23
+ * - This context drives future guard checks
17
24
  */
18
25
  export function createOrchestratedServer() {
19
26
  const server = new McpServer({
20
27
  name: `${DEV_SERVER_NAME}-orchestrated`,
21
28
  version: DEV_SERVER_VERSION,
22
29
  });
23
- // Register the single unified tool
24
- const shape = agentChatTool.inputSchema.shape;
25
- server.tool(agentChatTool.name, agentChatTool.description, shape, async (args) => {
26
- logger.toolCall(agentChatTool.name, args);
27
- const startTime = Date.now();
28
- try {
29
- const result = await agentChatTool.handler(args);
30
- const duration = Date.now() - startTime;
31
- logger.toolResult(agentChatTool.name, duration, result);
32
- return {
33
- content: [
34
- {
35
- type: 'text',
36
- text: JSON.stringify(result, null, 2),
37
- },
38
- ],
39
- };
40
- }
41
- catch (error) {
42
- const duration = Date.now() - startTime;
43
- logger.toolError(agentChatTool.name, duration, error);
44
- const message = error instanceof Error ? error.message : String(error);
45
- return {
46
- content: [
47
- {
48
- type: 'text',
49
- text: JSON.stringify({
50
- error: true,
51
- message,
52
- tool: agentChatTool.name,
53
- }, null, 2),
54
- },
55
- ],
56
- isError: true,
57
- };
58
- }
59
- });
60
- logger.info(`${DEV_SERVER_NAME}-orchestrated initialized with single agent_chat tool`);
30
+ // Register all tools with guard middleware
31
+ for (const tool of allDevTools) {
32
+ const shape = tool.inputSchema.shape;
33
+ server.tool(tool.name, tool.description, shape, async (args) => {
34
+ logger.toolCall(tool.name, args);
35
+ const startTime = Date.now();
36
+ // ── Guard: check prerequisites before executing ──────────────
37
+ const guard = checkToolPrerequisites(tool.name);
38
+ if (!guard.allowed) {
39
+ const duration = Date.now() - startTime;
40
+ logger.info(`BLOCKED ${tool.name} (${duration}ms): ${guard.message}`);
41
+ return {
42
+ content: [
43
+ {
44
+ type: 'text',
45
+ text: JSON.stringify({
46
+ error: true,
47
+ blocked: true,
48
+ tool: tool.name,
49
+ message: guard.message,
50
+ required_tools: guard.requiredTools,
51
+ chain: guard.chain,
52
+ hint: guard.hint || `Call ${guard.requiredTools?.join(' → ')} first, then retry ${tool.name}.`,
53
+ doc_hint: 'If you are unsure about any platform detail, call lookup_docs or get_status before proceeding.',
54
+ }, null, 2),
55
+ },
56
+ ],
57
+ isError: true,
58
+ };
59
+ }
60
+ // ── Execute tool ────────────────────────────────────────────
61
+ try {
62
+ const result = await tool.handler(args);
63
+ const duration = Date.now() - startTime;
64
+ logger.toolResult(tool.name, duration, result);
65
+ // Record success in session state
66
+ recordToolSuccess(tool.name, result);
67
+ return {
68
+ content: [
69
+ {
70
+ type: 'text',
71
+ text: JSON.stringify(result, null, 2),
72
+ },
73
+ ],
74
+ };
75
+ }
76
+ catch (error) {
77
+ const duration = Date.now() - startTime;
78
+ logger.toolError(tool.name, duration, error);
79
+ const message = error instanceof Error ? error.message : String(error);
80
+ return {
81
+ content: [
82
+ {
83
+ type: 'text',
84
+ text: JSON.stringify({
85
+ error: true,
86
+ message,
87
+ tool: tool.name,
88
+ doc_hint: 'If this error is about an API detail, call lookup_docs to verify the correct usage.',
89
+ }, null, 2),
90
+ },
91
+ ],
92
+ isError: true,
93
+ };
94
+ }
95
+ });
96
+ logger.debug(`Registered tool: ${tool.name}`);
97
+ }
98
+ logger.info(`${DEV_SERVER_NAME}-orchestrated initialized with ${allDevTools.length} tools (tool-first architecture)`);
61
99
  return server;
62
100
  }
63
101
  //# sourceMappingURL=orchestrated-server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrated-server.js","sourceRoot":"","sources":["../src/orchestrated-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,wBAAwB;IACtC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,GAAG,eAAe,eAAe;QACvC,OAAO,EAAE,kBAAkB;KAC5B,CAAC,CAAC;IAEH,mCAAmC;IACnC,MAAM,KAAK,GAAI,aAAa,CAAC,WAA0C,CAAC,KAAK,CAAC;IAE9E,MAAM,CAAC,IAAI,CACT,aAAa,CAAC,IAAI,EAClB,aAAa,CAAC,WAAW,EACzB,KAAK,EACL,KAAK,EAAE,IAA6B,EAAE,EAAE;QACtC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACxC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YAExD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;qBACtC;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACxC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YAEtD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,IAAI;4BACX,OAAO;4BACP,IAAI,EAAE,aAAa,CAAC,IAAI;yBACzB,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,uDAAuD,CAAC,CAAC;IACvF,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"orchestrated-server.js","sourceRoot":"","sources":["../src/orchestrated-server.ts"],"names":[],"mappings":"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"}
@@ -1,29 +1,23 @@
1
1
  /**
2
- * In-memory session state tracker.
2
+ * In-memory session state tracker (per-app).
3
3
  *
4
- * Tracks which tools have been called successfully and what data has been
5
- * collected so far. This lets the tool-guard decide whether a tool's
6
- * prerequisites are met before allowing it to execute.
4
+ * Auth state is global (one developer per stdio session).
5
+ * App state is scoped per app ID supports working on multiple apps.
7
6
  *
8
- * Single-user (stdio MCP), so a simple module-level object is fine.
7
+ * Single-user (stdio MCP), so module-level state is fine.
9
8
  * For multi-user (Streamable HTTP), this would move to Redis.
10
9
  */
11
- export interface SessionState {
12
- /** Tools that completed successfully (set of tool names) */
10
+ /** Per-app state: tracks tool completion and collected context for one app */
11
+ export interface AppState {
13
12
  completedTools: Set<string>;
14
- /** Key data collected during the flow */
15
13
  context: {
16
- authMode?: 'login' | 'signup';
17
- signupEmail?: string;
18
- developerId?: string;
19
- developerToken?: string;
20
- appId?: string;
21
14
  appName?: string;
22
15
  clientId?: string;
23
16
  clientSecret?: string;
24
17
  confirmedScopes?: string[];
25
18
  scopesConfirmed?: boolean;
26
19
  webhooksConfigured?: boolean;
20
+ webhookIds?: string[];
27
21
  buildUploaded?: boolean;
28
22
  submittedForReview?: boolean;
29
23
  appApproved?: boolean;
@@ -37,17 +31,43 @@ export interface SessionState {
37
31
  zipPath?: string;
38
32
  latestVersionId?: string;
39
33
  };
34
+ }
35
+ /** Global session state: auth + per-app state */
36
+ export interface SessionState {
37
+ /** Global: tools completed at session level (auth tools) */
38
+ completedTools: Set<string>;
39
+ /** Global context (auth + active app's context flattened for backward compat) */
40
+ context: {
41
+ authMode?: 'login' | 'signup';
42
+ signupEmail?: string;
43
+ developerId?: string;
44
+ developerToken?: string;
45
+ /** Currently active app ID (for tools that don't pass app_id explicitly) */
46
+ activeAppId?: string;
47
+ /** Active app's ID (backward compat — same as activeAppId) */
48
+ appId?: string;
49
+ } & AppState['context'];
50
+ /** Per-app state, keyed by app ID */
51
+ apps: Record<string, AppState>;
40
52
  /** Timestamp of last tool call */
41
53
  lastActivity: number;
42
54
  }
43
- /** Get current session state (read-only snapshot) */
44
- export declare function getSession(): Readonly<SessionState>;
55
+ /** Get current session state (read-only reference) */
56
+ export declare function getSession(): SessionState;
57
+ /** Get state for a specific app */
58
+ export declare function getAppState(appId: string): AppState | undefined;
59
+ /** Get the currently active app ID */
60
+ export declare function getActiveAppId(): string | undefined;
61
+ /** Set the active app ID */
62
+ export declare function setActiveAppId(appId: string): void;
45
63
  /** Record that a tool completed successfully and extract relevant context */
46
64
  export declare function recordToolSuccess(toolName: string, result: unknown): void;
47
65
  /** Reset session (for testing or starting a new flow) */
48
66
  export declare function resetSession(): void;
49
- /** Check if a specific tool has been completed */
67
+ /** Check if a specific tool has been completed (global or active app) */
50
68
  export declare function hasCompleted(toolName: string): boolean;
51
69
  /** Check if ANY of the given tools has been completed */
52
70
  export declare function hasCompletedAny(toolNames: string[]): boolean;
71
+ /** Get all completed tools (global + active app) */
72
+ export declare function getAllCompletedTools(): string[];
53
73
  //# sourceMappingURL=session-state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-state.d.ts","sourceRoot":"","sources":["../../src/services/session-state.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAE5B,yCAAyC;IACzC,OAAO,EAAE;QACP,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;QAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF,kCAAkC;IAClC,YAAY,EAAE,MAAM,CAAC;CACtB;AAgBD,qDAAqD;AACrD,wBAAgB,UAAU,IAAI,QAAQ,CAAC,YAAY,CAAC,CAEnD;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAyOzE;AAED,yDAAyD;AACzD,wBAAgB,YAAY,IAAI,IAAI,CAGnC;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAE5D"}
1
+ {"version":3,"file":"session-state.d.ts","sourceRoot":"","sources":["../../src/services/session-state.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAIH,8EAA8E;AAC9E,MAAM,WAAW,QAAQ;IACvB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAE5B,iFAAiF;IACjF,OAAO,EAAE;QACP,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;QAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,4EAA4E;QAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,8DAA8D;QAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAExB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE/B,kCAAkC;IAClC,YAAY,EAAE,MAAM,CAAC;CACtB;AA4BD,sDAAsD;AACtD,wBAAgB,UAAU,IAAI,YAAY,CAEzC;AAED,mCAAmC;AACnC,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAE/D;AAED,sCAAsC;AACtC,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CAEnD;AAED,4BAA4B;AAC5B,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAuNzE;AA2BD,yDAAyD;AACzD,wBAAgB,YAAY,IAAI,IAAI,CAGnC;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOtD;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAE5D;AAED,oDAAoD;AACpD,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAS/C"}