@on-mission/sdk 0.1.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 (46) hide show
  1. package/dist/api.d.ts +20 -0
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/api.js +39 -0
  4. package/dist/api.js.map +1 -0
  5. package/dist/auth.d.ts +65 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +45 -0
  8. package/dist/auth.js.map +1 -0
  9. package/dist/config.d.ts +39 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +28 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/context.d.ts +24 -0
  14. package/dist/context.d.ts.map +1 -0
  15. package/dist/context.js +22 -0
  16. package/dist/context.js.map +1 -0
  17. package/dist/events.d.ts +62 -0
  18. package/dist/events.d.ts.map +1 -0
  19. package/dist/events.js +30 -0
  20. package/dist/events.js.map +1 -0
  21. package/dist/http-server.d.ts +51 -0
  22. package/dist/http-server.d.ts.map +1 -0
  23. package/dist/http-server.js +163 -0
  24. package/dist/http-server.js.map +1 -0
  25. package/dist/index.d.ts +21 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +12 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/ingress.d.ts +133 -0
  30. package/dist/ingress.d.ts.map +1 -0
  31. package/dist/ingress.js +89 -0
  32. package/dist/ingress.js.map +1 -0
  33. package/dist/logging.d.ts +31 -0
  34. package/dist/logging.d.ts.map +1 -0
  35. package/dist/logging.js +77 -0
  36. package/dist/logging.js.map +1 -0
  37. package/dist/sdk.d.ts +116 -0
  38. package/dist/sdk.d.ts.map +1 -0
  39. package/dist/sdk.js +327 -0
  40. package/dist/sdk.js.map +1 -0
  41. package/dist/tool-registry.d.ts +29 -0
  42. package/dist/tool-registry.d.ts.map +1 -0
  43. package/dist/tool-registry.js +37 -0
  44. package/dist/tool-registry.js.map +1 -0
  45. package/dist/tsconfig.tsbuildinfo +1 -0
  46. package/package.json +56 -0
package/dist/api.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * API Client
3
+ *
4
+ * Typed tRPC client for all SDK -> Mission gateway communication.
5
+ * The public SDK surface stays the same (`mission.auth.get()`, etc.),
6
+ * while transport details are centralized here.
7
+ */
8
+ import type { GatewayRouter } from '@mission/api/gateway';
9
+ import { createTRPCProxyClient } from '@trpc/client';
10
+ import type { PluginContext } from './context';
11
+ type GatewayClient = ReturnType<typeof createTRPCProxyClient<GatewayRouter>>;
12
+ export type ApiClient = {
13
+ trpc: GatewayClient;
14
+ baseUrl: string;
15
+ setToken: (token: string) => void;
16
+ getToken: () => string;
17
+ };
18
+ export declare const createApiClient: (ctx: PluginContext) => ApiClient;
19
+ export {};
20
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,qBAAqB,EAAiB,MAAM,cAAc,CAAA;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAE9C,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,aAAa,CAAC,CAAC,CAAA;AAE5E,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,QAAQ,EAAE,MAAM,MAAM,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,KAAK,aAAa,KAAG,SA+BpD,CAAA"}
package/dist/api.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * API Client
3
+ *
4
+ * Typed tRPC client for all SDK -> Mission gateway communication.
5
+ * The public SDK surface stays the same (`mission.auth.get()`, etc.),
6
+ * while transport details are centralized here.
7
+ */
8
+ import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
9
+ export const createApiClient = (ctx) => {
10
+ const baseUrl = ctx.apiUrl.replace(/\/$/, '');
11
+ let currentToken = ctx.pluginToken;
12
+ const trpc = createTRPCProxyClient({
13
+ links: [
14
+ httpBatchLink({
15
+ url: `${baseUrl}/api/trpc`,
16
+ headers() {
17
+ const headers = {
18
+ 'X-Mission-Installation-Id': ctx.installationId
19
+ };
20
+ if (currentToken) {
21
+ headers.Authorization = `Bearer ${currentToken}`;
22
+ }
23
+ return headers;
24
+ }
25
+ })
26
+ ]
27
+ });
28
+ return {
29
+ trpc,
30
+ baseUrl,
31
+ setToken: (token) => {
32
+ currentToken = token;
33
+ },
34
+ getToken: () => {
35
+ return currentToken;
36
+ }
37
+ };
38
+ };
39
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAYnE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAkB,EAAa,EAAE;IAC/D,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC7C,IAAI,YAAY,GAAG,GAAG,CAAC,WAAW,CAAA;IAElC,MAAM,IAAI,GAAG,qBAAqB,CAAgB;QAChD,KAAK,EAAE;YACL,aAAa,CAAC;gBACZ,GAAG,EAAE,GAAG,OAAO,WAAW;gBAC1B,OAAO;oBACL,MAAM,OAAO,GAA2B;wBACtC,2BAA2B,EAAE,GAAG,CAAC,cAAc;qBAChD,CAAA;oBACD,IAAI,YAAY,EAAE,CAAC;wBACjB,OAAO,CAAC,aAAa,GAAG,UAAU,YAAY,EAAE,CAAA;oBAClD,CAAC;oBACD,OAAO,OAAO,CAAA;gBAChB,CAAC;aACF,CAAC;SACH;KACF,CAAC,CAAA;IAEF,OAAO;QACL,IAAI;QACJ,OAAO;QACP,QAAQ,EAAE,CAAC,KAAa,EAAQ,EAAE;YAChC,YAAY,GAAG,KAAK,CAAA;QACtB,CAAC;QACD,QAAQ,EAAE,GAAW,EAAE;YACrB,OAAO,YAAY,CAAA;QACrB,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Auth Module
3
+ *
4
+ * Unified interface for all authentication credentials.
5
+ * `mission.auth.get()` returns a single object containing:
6
+ * - User-provided credentials (API keys, tokens, secrets from the connection form)
7
+ * - OAuth token data (for managed auth providers like Google, Slack)
8
+ *
9
+ * Plugin authors always call `auth.get()` regardless of auth type.
10
+ *
11
+ * For managed auth (Nango-backed), the SDK caches tokens and refreshes
12
+ * transparently. See docs/technical-designs/managed-auth-nango.md.
13
+ *
14
+ * For custom auth, credentials are collected via a connection form
15
+ * defined in mission.json's `auth.credentials` schema.
16
+ *
17
+ * Transport: tRPC mutation/query via Mission gateway API.
18
+ */
19
+ import type { ApiClient } from './api';
20
+ /**
21
+ * OAuth credentials returned for managed auth providers.
22
+ * The control plane handles token refresh (via Nango or equivalent).
23
+ */
24
+ export type OAuthCredentials = {
25
+ /** The current access token string. */
26
+ accessToken: string;
27
+ /** When this token expires (ISO 8601 or epoch ms). */
28
+ expiresAt: string | number;
29
+ /** Scopes that were granted. */
30
+ scopes: string[];
31
+ /** The provider identifier (e.g. 'google', 'slack'). */
32
+ provider: string;
33
+ };
34
+ /**
35
+ * The unified auth response.
36
+ *
37
+ * For custom auth (Sentry, Twilio, etc.):
38
+ * { credentials: { authToken: 'sntrys_...', organization: 'my-org' } }
39
+ *
40
+ * For managed OAuth (Gmail, Slack, etc.):
41
+ * { credentials: {}, oauth: { accessToken: 'ya29...', ... } }
42
+ *
43
+ * For mixed (future: OAuth + user-provided extras):
44
+ * { credentials: { webhookSecret: '...' }, oauth: { accessToken: '...', ... } }
45
+ */
46
+ export type AuthCredentials = {
47
+ /** User-provided credential values from the connection form. */
48
+ credentials: Record<string, string>;
49
+ /** OAuth token data. Present when auth.type is "managed". */
50
+ oauth?: OAuthCredentials;
51
+ };
52
+ export type AuthModule = {
53
+ /**
54
+ * Get all authentication data for this plugin installation.
55
+ *
56
+ * Returns user-provided credentials (API keys, tokens from the
57
+ * connection form) and, for managed OAuth providers, a current
58
+ * access token that the SDK keeps refreshed.
59
+ *
60
+ * This is safe to call repeatedly — the SDK caches internally.
61
+ */
62
+ get: () => Promise<AuthCredentials>;
63
+ };
64
+ export declare function createAuthModule(api: ApiClient): AuthModule;
65
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAA;IACnB,sDAAsD;IACtD,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1B,gCAAgC;IAChC,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,6DAA6D;IAC7D,KAAK,CAAC,EAAE,gBAAgB,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB;;;;;;;;OAQG;IACH,GAAG,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAA;CACpC,CAAA;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,GAAG,UAAU,CAyB3D"}
package/dist/auth.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Auth Module
3
+ *
4
+ * Unified interface for all authentication credentials.
5
+ * `mission.auth.get()` returns a single object containing:
6
+ * - User-provided credentials (API keys, tokens, secrets from the connection form)
7
+ * - OAuth token data (for managed auth providers like Google, Slack)
8
+ *
9
+ * Plugin authors always call `auth.get()` regardless of auth type.
10
+ *
11
+ * For managed auth (Nango-backed), the SDK caches tokens and refreshes
12
+ * transparently. See docs/technical-designs/managed-auth-nango.md.
13
+ *
14
+ * For custom auth, credentials are collected via a connection form
15
+ * defined in mission.json's `auth.credentials` schema.
16
+ *
17
+ * Transport: tRPC mutation/query via Mission gateway API.
18
+ */
19
+ // ─── Factory ─────────────────────────────────────────────────────────────────
20
+ export function createAuthModule(api) {
21
+ // Cache for managed OAuth tokens
22
+ let cachedAuth = null;
23
+ const CACHE_TTL_MS = 4 * 60 * 1000; // Refresh 4 min before typical 1h expiry
24
+ function isCacheValid() {
25
+ if (!cachedAuth)
26
+ return false;
27
+ // If there's no OAuth component, credentials are static — cache forever
28
+ if (!cachedAuth.data.oauth)
29
+ return true;
30
+ // If there is OAuth, check if the token is still fresh
31
+ const elapsed = Date.now() - cachedAuth.fetchedAt;
32
+ return elapsed < CACHE_TTL_MS;
33
+ }
34
+ return {
35
+ get: async () => {
36
+ if (isCacheValid()) {
37
+ return cachedAuth.data;
38
+ }
39
+ const auth = (await api.trpc.plugin.getAuth.query({}));
40
+ cachedAuth = { data: auth, fetchedAt: Date.now() };
41
+ return auth;
42
+ }
43
+ };
44
+ }
45
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAqDH,gFAAgF;AAEhF,MAAM,UAAU,gBAAgB,CAAC,GAAc;IAC7C,iCAAiC;IACjC,IAAI,UAAU,GAAwD,IAAI,CAAA;IAC1E,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,yCAAyC;IAE5E,SAAS,YAAY;QACnB,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAA;QAC7B,wEAAwE;QACxE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QACvC,uDAAuD;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,SAAS,CAAA;QACjD,OAAO,OAAO,GAAG,YAAY,CAAA;IAC/B,CAAC;IAED,OAAO;QACL,GAAG,EAAE,KAAK,IAA8B,EAAE;YACxC,IAAI,YAAY,EAAE,EAAE,CAAC;gBACnB,OAAO,UAAW,CAAC,IAAI,CAAA;YACzB,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAoB,CAAA;YACzE,UAAU,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAA;YAClD,OAAO,IAAI,CAAA;QACb,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Config Module
3
+ *
4
+ * Fetches per-installation configuration from the control plane.
5
+ * Accepts optional defaults so plugins always get a complete config
6
+ * object without manual merging.
7
+ *
8
+ * The control plane stores config per AppConnection. Values are set
9
+ * by the user in the App's settings UI (defined by configSchema in
10
+ * mission.json). The SDK merges platform values over provided defaults
11
+ * so the returned object is always complete.
12
+ *
13
+ * Transport: tRPC query via Mission gateway API.
14
+ *
15
+ * See docs/product/apps.md § App configuration state.
16
+ */
17
+ import type { ApiClient } from './api';
18
+ export type ConfigModule = {
19
+ /**
20
+ * Fetch the full configuration object for this plugin installation.
21
+ *
22
+ * If `defaults` are provided, the SDK merges platform-stored values
23
+ * over them, so the result is always a complete `T` with no undefined
24
+ * fields. Without defaults, returns whatever the platform has stored.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const config = await mission.config.get<GmailConfig>({
29
+ * watchLabels: ['INBOX'],
30
+ * maxResults: 20,
31
+ * signatureLine: ''
32
+ * })
33
+ * // config is guaranteed to have all three fields
34
+ * ```
35
+ */
36
+ get: <T = Record<string, unknown>>(defaults?: Partial<T>) => Promise<T>;
37
+ };
38
+ export declare function createConfigModule(api: ApiClient): ConfigModule;
39
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;;;;;;;;;;;OAgBG;IACH,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;CACxE,CAAA;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,SAAS,GAAG,YAAY,CAgB/D"}
package/dist/config.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Config Module
3
+ *
4
+ * Fetches per-installation configuration from the control plane.
5
+ * Accepts optional defaults so plugins always get a complete config
6
+ * object without manual merging.
7
+ *
8
+ * The control plane stores config per AppConnection. Values are set
9
+ * by the user in the App's settings UI (defined by configSchema in
10
+ * mission.json). The SDK merges platform values over provided defaults
11
+ * so the returned object is always complete.
12
+ *
13
+ * Transport: tRPC query via Mission gateway API.
14
+ *
15
+ * See docs/product/apps.md § App configuration state.
16
+ */
17
+ export function createConfigModule(api) {
18
+ return {
19
+ get: async (defaults) => {
20
+ const platformValues = (await api.trpc.plugin.getConfig.query({}));
21
+ if (defaults) {
22
+ return { ...defaults, ...platformValues };
23
+ }
24
+ return platformValues;
25
+ }
26
+ };
27
+ }
28
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAyBH,MAAM,UAAU,kBAAkB,CAAC,GAAc;IAC/C,OAAO;QACL,GAAG,EAAE,KAAK,EACR,QAAqB,EACT,EAAE;YACd,MAAM,cAAc,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAC3D,EAAE,CACH,CAAe,CAAA;YAEhB,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,cAAc,EAAO,CAAA;YAChD,CAAC;YAED,OAAO,cAAmB,CAAA;QAC5B,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Plugin Context
3
+ *
4
+ * Bootstrapped from environment variables injected by the Mission control plane
5
+ * when it starts the plugin process inside the Daytona sandbox.
6
+ *
7
+ * See docs/technical-designs/plugin-architecture.md §4.5.
8
+ */
9
+ export type PluginContext = {
10
+ /** Mission control plane API base URL. */
11
+ apiUrl: string;
12
+ /** JWT scoped to this plugin installation (for outbound API calls). */
13
+ pluginToken: string;
14
+ /** Stable identifier for this plugin installation (per-workspace). */
15
+ installationId: string;
16
+ /** Port assigned by the control plane for this plugin's HTTP server. */
17
+ pluginPort: number;
18
+ };
19
+ /**
20
+ * Read plugin context from process environment variables.
21
+ * These are injected by the Mission control plane when starting the plugin.
22
+ */
23
+ export declare function readContextFromEnv(): PluginContext;
24
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,aAAa,GAAG;IAC1B,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAA;IACd,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,cAAc,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,aAAa,CAQlD"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Plugin Context
3
+ *
4
+ * Bootstrapped from environment variables injected by the Mission control plane
5
+ * when it starts the plugin process inside the Daytona sandbox.
6
+ *
7
+ * See docs/technical-designs/plugin-architecture.md §4.5.
8
+ */
9
+ /**
10
+ * Read plugin context from process environment variables.
11
+ * These are injected by the Mission control plane when starting the plugin.
12
+ */
13
+ export function readContextFromEnv() {
14
+ const portStr = process.env.MISSION_PLUGIN_PORT;
15
+ return {
16
+ apiUrl: process.env.MISSION_API_URL ?? 'http://localhost:8665',
17
+ pluginToken: process.env.MISSION_PLUGIN_TOKEN ?? '',
18
+ installationId: process.env.MISSION_INSTALLATION_ID ?? '',
19
+ pluginPort: portStr ? Number.parseInt(portStr, 10) : 3000
20
+ };
21
+ }
22
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAA;IAC/C,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,uBAAuB;QAC9D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE;QACnD,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE;QACzD,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;KAC1D,CAAA;AACH,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Events Module
3
+ *
4
+ * Plugins send messages to the agent when external events occur.
5
+ * This is the ONLY event type plugins emit — there are no domain-specific
6
+ * event types (no 'gmail.push_notification', no 'sentry.issue.created').
7
+ *
8
+ * The plugin's job is to:
9
+ * 1. Receive external data (webhooks, streams) via ingress
10
+ * 2. Process and interpret that data
11
+ * 3. Tell the agent what happened and what to do about it
12
+ *
13
+ * The platform routes the message to the appropriate agent(s) based
14
+ * on the plugin's App configuration and the workspace's agent routing.
15
+ *
16
+ * Transport: tRPC mutation via Mission gateway API.
17
+ *
18
+ * See docs/product/apps.md § Communication model → Events.
19
+ */
20
+ import type { ApiClient } from './api';
21
+ /**
22
+ * A message from a plugin to the agent.
23
+ *
24
+ * Plugins process their domain-specific inbound data and produce
25
+ * human-readable messages that agents can reason about.
26
+ */
27
+ export type AgentMessage = {
28
+ /**
29
+ * Human-readable message describing what happened.
30
+ * This is what the agent sees and reasons about.
31
+ *
32
+ * @example "New email from john@example.com: \"Q3 Report Review\" — requesting approval on budget figures."
33
+ * @example "Sentry alert: TypeError in auth.ts — 47 events in the last hour affecting 12 users."
34
+ * @example "Inbound phone call from +1-555-0123. Caller is asking about order status."
35
+ */
36
+ message: string;
37
+ /**
38
+ * Structured context data the agent can reference.
39
+ * Include IDs, metadata, and any data that helps the agent
40
+ * take follow-up actions using the plugin's tools.
41
+ */
42
+ context?: Record<string, unknown>;
43
+ /**
44
+ * Optional deduplication key to prevent duplicate processing.
45
+ * If the platform has already processed a message with this key,
46
+ * it will be silently dropped.
47
+ */
48
+ deduplicationKey?: string;
49
+ };
50
+ export type EventsModule = {
51
+ /**
52
+ * Send a message to the agent about an external event.
53
+ *
54
+ * The platform routes it to the appropriate agent(s) based on
55
+ * the workspace's routing configuration.
56
+ *
57
+ * Fire-and-forget — the API handles delivery.
58
+ */
59
+ send: (message: AgentMessage) => Promise<void>;
60
+ };
61
+ export declare function createEventsModule(api: ApiClient): EventsModule;
62
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;;OAOG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAEjC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;;OAOG;IACH,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/C,CAAA;AAID,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,SAAS,GAAG,YAAY,CAQ/D"}
package/dist/events.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Events Module
3
+ *
4
+ * Plugins send messages to the agent when external events occur.
5
+ * This is the ONLY event type plugins emit — there are no domain-specific
6
+ * event types (no 'gmail.push_notification', no 'sentry.issue.created').
7
+ *
8
+ * The plugin's job is to:
9
+ * 1. Receive external data (webhooks, streams) via ingress
10
+ * 2. Process and interpret that data
11
+ * 3. Tell the agent what happened and what to do about it
12
+ *
13
+ * The platform routes the message to the appropriate agent(s) based
14
+ * on the plugin's App configuration and the workspace's agent routing.
15
+ *
16
+ * Transport: tRPC mutation via Mission gateway API.
17
+ *
18
+ * See docs/product/apps.md § Communication model → Events.
19
+ */
20
+ // ─── Factory ─────────────────────────────────────────────────────────────────
21
+ export function createEventsModule(api) {
22
+ return {
23
+ send: async (message) => {
24
+ void api.trpc.plugin.sendEvent.mutate(message).catch((err) => {
25
+ console.error('[Events] send failed:', err);
26
+ });
27
+ }
28
+ };
29
+ }
30
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAkDH,gFAAgF;AAEhF,MAAM,UAAU,kBAAkB,CAAC,GAAc;IAC/C,OAAO;QACL,IAAI,EAAE,KAAK,EAAE,OAAqB,EAAiB,EAAE;YACnD,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBACpE,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAA;YAC7C,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * HTTP Server
3
+ *
4
+ * Internal HTTP server that runs inside the plugin's Daytona sandbox.
5
+ * This is the inbound entrypoint for all traffic to the plugin:
6
+ *
7
+ * Mission API → Daytona Preview URL → this server:
8
+ * POST /_mission/tools/:toolName — tool call dispatch
9
+ * GET /_mission/health — health check
10
+ * GET /_mission/ping — keep-alive ping (resets Daytona auto-stop)
11
+ *
12
+ * External services → Daytona Signed Preview URL → this server:
13
+ * POST /{ingressPath} — webhook delivery
14
+ * GET /{ingressPath} (ws upgrade) — WebSocket stream (e.g., Twilio media)
15
+ *
16
+ * The server is started by mission.connect() and stopped during graceful shutdown.
17
+ * Plugin authors never interact with it directly — they register tool handlers
18
+ * and ingress handlers through the SDK, and this server routes to them.
19
+ *
20
+ * See docs/technical-designs/plugin-architecture.md §4.1.
21
+ * See docs/technical-designs/daytona-sandbox-runtime.md §2-3.
22
+ */
23
+ import * as http from 'node:http';
24
+ export type RouteHandler = (req: ParsedRequest) => Promise<{
25
+ status: number;
26
+ headers?: Record<string, string>;
27
+ body?: string;
28
+ }>;
29
+ export type ParsedRequest = {
30
+ method: string;
31
+ path: string;
32
+ headers: Record<string, string>;
33
+ body: string;
34
+ query: Record<string, string>;
35
+ /** The matched route parameter, e.g., the tool name from /_mission/tools/:name */
36
+ params: Record<string, string>;
37
+ };
38
+ export type PluginHttpServer = {
39
+ /** Start listening on the given port. */
40
+ start: (port: number) => Promise<void>;
41
+ /** Stop the server gracefully. */
42
+ stop: () => Promise<void>;
43
+ /** Register a route handler. Supports simple patterns like /_mission/tools/:name */
44
+ route: (method: string, pattern: string, handler: RouteHandler) => void;
45
+ /** The underlying Node HTTP server (for WebSocket upgrades if needed). */
46
+ server: http.Server | null;
47
+ /** The port the server is listening on. */
48
+ port: number;
49
+ };
50
+ export declare function createHttpServer(): PluginHttpServer;
51
+ //# sourceMappingURL=http-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAIjC,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC;IACzD,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAC,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,yCAAyC;IACzC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,kCAAkC;IAClC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,oFAAoF;IACpF,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;IACvE,0EAA0E;IAC1E,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;IAC1B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAmED,wBAAgB,gBAAgB,IAAI,gBAAgB,CAwGnD"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * HTTP Server
3
+ *
4
+ * Internal HTTP server that runs inside the plugin's Daytona sandbox.
5
+ * This is the inbound entrypoint for all traffic to the plugin:
6
+ *
7
+ * Mission API → Daytona Preview URL → this server:
8
+ * POST /_mission/tools/:toolName — tool call dispatch
9
+ * GET /_mission/health — health check
10
+ * GET /_mission/ping — keep-alive ping (resets Daytona auto-stop)
11
+ *
12
+ * External services → Daytona Signed Preview URL → this server:
13
+ * POST /{ingressPath} — webhook delivery
14
+ * GET /{ingressPath} (ws upgrade) — WebSocket stream (e.g., Twilio media)
15
+ *
16
+ * The server is started by mission.connect() and stopped during graceful shutdown.
17
+ * Plugin authors never interact with it directly — they register tool handlers
18
+ * and ingress handlers through the SDK, and this server routes to them.
19
+ *
20
+ * See docs/technical-designs/plugin-architecture.md §4.1.
21
+ * See docs/technical-designs/daytona-sandbox-runtime.md §2-3.
22
+ */
23
+ import * as http from 'node:http';
24
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
25
+ function parseQueryString(qs) {
26
+ const params = {};
27
+ if (!qs)
28
+ return params;
29
+ for (const pair of qs.split('&')) {
30
+ const [key, value] = pair.split('=');
31
+ if (key) {
32
+ params[decodeURIComponent(key)] = decodeURIComponent(value ?? '');
33
+ }
34
+ }
35
+ return params;
36
+ }
37
+ function readBody(req) {
38
+ return new Promise((resolve, reject) => {
39
+ const chunks = [];
40
+ req.on('data', (chunk) => chunks.push(chunk));
41
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
42
+ req.on('error', reject);
43
+ });
44
+ }
45
+ function matchRoute(routes, method, path) {
46
+ const pathSegments = path.split('/').filter(Boolean);
47
+ for (const route of routes) {
48
+ if (route.method !== method && route.method !== '*')
49
+ continue;
50
+ const routeSegments = route.segments;
51
+ if (routeSegments.length !== pathSegments.length)
52
+ continue;
53
+ const params = {};
54
+ let match = true;
55
+ for (let i = 0; i < routeSegments.length; i++) {
56
+ const routeSeg = routeSegments[i];
57
+ const pathSeg = pathSegments[i];
58
+ if (routeSeg.startsWith(':')) {
59
+ params[routeSeg.slice(1)] = pathSeg;
60
+ }
61
+ else if (routeSeg !== pathSeg) {
62
+ match = false;
63
+ break;
64
+ }
65
+ }
66
+ if (match)
67
+ return { route, params };
68
+ }
69
+ return null;
70
+ }
71
+ // ─── Factory ─────────────────────────────────────────────────────────────────
72
+ export function createHttpServer() {
73
+ const routes = [];
74
+ let server = null;
75
+ let _listenPort = 0;
76
+ const pluginServer = {
77
+ server: null,
78
+ port: 0,
79
+ route(method, pattern, handler) {
80
+ routes.push({
81
+ method: method.toUpperCase(),
82
+ pattern,
83
+ segments: pattern.split('/').filter(Boolean),
84
+ handler
85
+ });
86
+ },
87
+ start(port) {
88
+ return new Promise((resolve, reject) => {
89
+ server = http.createServer(async (req, res) => {
90
+ const urlParts = (req.url ?? '/').split('?');
91
+ const path = urlParts[0];
92
+ const queryString = urlParts[1] ?? '';
93
+ const method = (req.method ?? 'GET').toUpperCase();
94
+ const matched = matchRoute(routes, method, path);
95
+ if (!matched) {
96
+ res.writeHead(404, { 'Content-Type': 'application/json' });
97
+ res.end(JSON.stringify({ error: 'Not found', path }));
98
+ return;
99
+ }
100
+ try {
101
+ const body = await readBody(req);
102
+ const headers = {};
103
+ for (const [key, value] of Object.entries(req.headers)) {
104
+ if (typeof value === 'string') {
105
+ headers[key.toLowerCase()] = value;
106
+ }
107
+ }
108
+ const parsed = {
109
+ method,
110
+ path,
111
+ headers,
112
+ body,
113
+ query: parseQueryString(queryString),
114
+ params: matched.params
115
+ };
116
+ const result = await matched.route.handler(parsed);
117
+ const responseHeaders = {
118
+ 'Content-Type': 'application/json',
119
+ ...(result.headers ?? {})
120
+ };
121
+ res.writeHead(result.status, responseHeaders);
122
+ res.end(result.body ?? '');
123
+ }
124
+ catch (err) {
125
+ console.error('[HttpServer] Handler error:', err);
126
+ res.writeHead(500, { 'Content-Type': 'application/json' });
127
+ res.end(JSON.stringify({
128
+ error: 'Internal server error',
129
+ message: err instanceof Error ? err.message : String(err)
130
+ }));
131
+ }
132
+ });
133
+ server.on('error', reject);
134
+ server.listen(port, () => {
135
+ _listenPort = port;
136
+ pluginServer.server = server;
137
+ pluginServer.port = port;
138
+ console.error(`[HttpServer] Listening on port ${port}`);
139
+ resolve();
140
+ });
141
+ });
142
+ },
143
+ stop() {
144
+ return new Promise((resolve, reject) => {
145
+ if (!server) {
146
+ resolve();
147
+ return;
148
+ }
149
+ server.close(err => {
150
+ if (err) {
151
+ reject(err);
152
+ }
153
+ else {
154
+ console.error('[HttpServer] Server stopped');
155
+ resolve();
156
+ }
157
+ });
158
+ });
159
+ }
160
+ };
161
+ return pluginServer;
162
+ }
163
+ //# sourceMappingURL=http-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.js","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAiCjC,gFAAgF;AAEhF,SAAS,gBAAgB,CAAC,EAAU;IAClC,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,IAAI,CAAC,EAAE;QAAE,OAAO,MAAM,CAAA;IACtB,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACpC,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,kBAAkB,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;QACnE,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,GAAyB;IACzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAA;QAC3B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;QACrD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACrE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;AACJ,CAAC;AASD,SAAS,UAAU,CACjB,MAAe,EACf,MAAc,EACd,IAAY;IAEZ,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAEpD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG;YAAE,SAAQ;QAE7D,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAA;QACpC,IAAI,aAAa,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM;YAAE,SAAQ;QAE1D,MAAM,MAAM,GAA2B,EAAE,CAAA;QACzC,IAAI,KAAK,GAAG,IAAI,CAAA;QAEhB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;YACjC,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAA;YAC/B,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAA;YACrC,CAAC;iBAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;gBAChC,KAAK,GAAG,KAAK,CAAA;gBACb,MAAK;YACP,CAAC;QACH,CAAC;QAED,IAAI,KAAK;YAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;IACrC,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,gFAAgF;AAEhF,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAY,EAAE,CAAA;IAC1B,IAAI,MAAM,GAAuB,IAAI,CAAA;IACrC,IAAI,WAAW,GAAG,CAAC,CAAA;IAEnB,MAAM,YAAY,GAAqB;QACrC,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,CAAC;QAEP,KAAK,CAAC,MAAc,EAAE,OAAe,EAAE,OAAqB;YAC1D,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;gBAC5B,OAAO;gBACP,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;gBAC5C,OAAO;aACR,CAAC,CAAA;QACJ,CAAC;QAED,KAAK,CAAC,IAAY;YAChB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;oBAC5C,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;oBAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;oBACxB,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;oBACrC,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAA;oBAElD,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;oBAEhD,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAA;wBAC1D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;wBACrD,OAAM;oBACR,CAAC;oBAED,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAA;wBAChC,MAAM,OAAO,GAA2B,EAAE,CAAA;wBAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;4BACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gCAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAA;4BACpC,CAAC;wBACH,CAAC;wBAED,MAAM,MAAM,GAAkB;4BAC5B,MAAM;4BACN,IAAI;4BACJ,OAAO;4BACP,IAAI;4BACJ,KAAK,EAAE,gBAAgB,CAAC,WAAW,CAAC;4BACpC,MAAM,EAAE,OAAO,CAAC,MAAM;yBACvB,CAAA;wBAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;wBAElD,MAAM,eAAe,GAA2B;4BAC9C,cAAc,EAAE,kBAAkB;4BAClC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;yBAC1B,CAAA;wBAED,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;wBAC7C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;oBAC5B,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAA;wBACjD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAA;wBAC1D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;4BACb,KAAK,EAAE,uBAAuB;4BAC9B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBAC1D,CAAC,CACH,CAAA;oBACH,CAAC;gBACH,CAAC,CAAC,CAAA;gBAEF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAE1B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;oBACvB,WAAW,GAAG,IAAI,CAAA;oBAClB,YAAY,CAAC,MAAM,GAAG,MAAM,CAAA;oBAC5B,YAAY,CAAC,IAAI,GAAG,IAAI,CAAA;oBACxB,OAAO,CAAC,KAAK,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAA;oBACvD,OAAO,EAAE,CAAA;gBACX,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC;QAED,IAAI;YACF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,OAAO,EAAE,CAAA;oBACT,OAAM;gBACR,CAAC;gBACD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;oBACjB,IAAI,GAAG,EAAE,CAAC;wBACR,MAAM,CAAC,GAAG,CAAC,CAAA;oBACb,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;wBAC5C,OAAO,EAAE,CAAA;oBACX,CAAC;gBACH,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;IAED,OAAO,YAAY,CAAA;AACrB,CAAC"}