@fabric-harness/databricks 0.16.1 → 1.0.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 (101) hide show
  1. package/dist/agent.d.ts +45 -0
  2. package/dist/agent.d.ts.map +1 -0
  3. package/dist/agent.js +206 -0
  4. package/dist/agent.js.map +1 -0
  5. package/dist/ai.d.ts +19 -0
  6. package/dist/ai.d.ts.map +1 -0
  7. package/dist/ai.js +22 -0
  8. package/dist/ai.js.map +1 -0
  9. package/dist/app.d.ts +81 -0
  10. package/dist/app.d.ts.map +1 -0
  11. package/dist/app.js +87 -0
  12. package/dist/app.js.map +1 -0
  13. package/dist/client.d.ts +44 -0
  14. package/dist/client.d.ts.map +1 -0
  15. package/dist/client.js +114 -0
  16. package/dist/client.js.map +1 -0
  17. package/dist/consumption.d.ts +45 -0
  18. package/dist/consumption.d.ts.map +1 -0
  19. package/dist/consumption.js +85 -0
  20. package/dist/consumption.js.map +1 -0
  21. package/dist/cost-budget-actuals.d.ts +27 -0
  22. package/dist/cost-budget-actuals.d.ts.map +1 -0
  23. package/dist/cost-budget-actuals.js +265 -0
  24. package/dist/cost-budget-actuals.js.map +1 -0
  25. package/dist/embeddings.d.ts +18 -0
  26. package/dist/embeddings.d.ts.map +1 -0
  27. package/dist/embeddings.js +24 -0
  28. package/dist/embeddings.js.map +1 -0
  29. package/dist/feature-serving.d.ts +17 -0
  30. package/dist/feature-serving.d.ts.map +1 -0
  31. package/dist/feature-serving.js +29 -0
  32. package/dist/feature-serving.js.map +1 -0
  33. package/dist/genie.d.ts +22 -0
  34. package/dist/genie.d.ts.map +1 -0
  35. package/dist/genie.js +60 -0
  36. package/dist/genie.js.map +1 -0
  37. package/dist/governance.d.ts +70 -0
  38. package/dist/governance.d.ts.map +1 -0
  39. package/dist/governance.js +123 -0
  40. package/dist/governance.js.map +1 -0
  41. package/dist/identity.d.ts +72 -0
  42. package/dist/identity.d.ts.map +1 -0
  43. package/dist/identity.js +119 -0
  44. package/dist/identity.js.map +1 -0
  45. package/dist/index.d.ts +143 -80
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +111 -227
  48. package/dist/index.js.map +1 -1
  49. package/dist/lakebase.d.ts +49 -0
  50. package/dist/lakebase.d.ts.map +1 -0
  51. package/dist/lakebase.js +25 -0
  52. package/dist/lakebase.js.map +1 -0
  53. package/dist/lakeflow.d.ts +28 -0
  54. package/dist/lakeflow.d.ts.map +1 -0
  55. package/dist/lakeflow.js +75 -0
  56. package/dist/lakeflow.js.map +1 -0
  57. package/dist/mlflow-tracing.d.ts +111 -0
  58. package/dist/mlflow-tracing.d.ts.map +1 -0
  59. package/dist/mlflow-tracing.js +167 -0
  60. package/dist/mlflow-tracing.js.map +1 -0
  61. package/dist/mock-provider.d.ts +26 -0
  62. package/dist/mock-provider.d.ts.map +1 -0
  63. package/dist/mock-provider.js +66 -0
  64. package/dist/mock-provider.js.map +1 -0
  65. package/dist/model.d.ts +29 -0
  66. package/dist/model.d.ts.map +1 -0
  67. package/dist/model.js +50 -0
  68. package/dist/model.js.map +1 -0
  69. package/dist/persistence.d.ts +73 -0
  70. package/dist/persistence.d.ts.map +1 -0
  71. package/dist/persistence.js +82 -0
  72. package/dist/persistence.js.map +1 -0
  73. package/dist/serving-usage.d.ts +48 -0
  74. package/dist/serving-usage.d.ts.map +1 -0
  75. package/dist/serving-usage.js +100 -0
  76. package/dist/serving-usage.js.map +1 -0
  77. package/dist/sql-exec.d.ts +17 -0
  78. package/dist/sql-exec.d.ts.map +1 -0
  79. package/dist/sql-exec.js +36 -0
  80. package/dist/sql-exec.js.map +1 -0
  81. package/dist/sql-sandbox.d.ts +1 -1
  82. package/dist/sql-sandbox.d.ts.map +1 -1
  83. package/dist/sql-sandbox.js +1 -1
  84. package/dist/sql-sandbox.js.map +1 -1
  85. package/dist/telemetry-sink.d.ts +29 -0
  86. package/dist/telemetry-sink.d.ts.map +1 -0
  87. package/dist/telemetry-sink.js +129 -0
  88. package/dist/telemetry-sink.js.map +1 -0
  89. package/dist/tools.d.ts +71 -0
  90. package/dist/tools.d.ts.map +1 -0
  91. package/dist/tools.js +176 -0
  92. package/dist/tools.js.map +1 -0
  93. package/dist/vector-search.d.ts +24 -0
  94. package/dist/vector-search.d.ts.map +1 -0
  95. package/dist/vector-search.js +63 -0
  96. package/dist/vector-search.js.map +1 -0
  97. package/dist/volumes-attachment-store.d.ts +64 -0
  98. package/dist/volumes-attachment-store.d.ts.map +1 -0
  99. package/dist/volumes-attachment-store.js +172 -0
  100. package/dist/volumes-attachment-store.js.map +1 -0
  101. package/package.json +20 -3
@@ -0,0 +1,17 @@
1
+ import type { JsonObject, ToolDef } from '@fabric-harness/sdk';
2
+ import type { DatabricksRestClient } from './client.js';
3
+ export interface DatabricksFeatureLookupToolOptions {
4
+ /** Feature Serving endpoint name (serves features from an online table / feature spec). */
5
+ endpoint: string;
6
+ name?: string;
7
+ description?: string;
8
+ }
9
+ /**
10
+ * Low-latency feature lookup from a Databricks **Feature Serving** endpoint (backed by an Online
11
+ * Table). The model passes primary-key records; the endpoint returns the served feature values.
12
+ * Drives serving consumption and keeps features governed by Unity Catalog under the bundle principal.
13
+ */
14
+ export declare function databricksFeatureLookupTool(client: DatabricksRestClient, options: DatabricksFeatureLookupToolOptions): ToolDef<{
15
+ records: JsonObject[];
16
+ }, unknown>;
17
+ //# sourceMappingURL=feature-serving.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-serving.d.ts","sourceRoot":"","sources":["../src/feature-serving.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,kCAAkC;IACjD,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,kCAAkC,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,EAAE,OAAO,CAAC,CAsBlK"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Low-latency feature lookup from a Databricks **Feature Serving** endpoint (backed by an Online
3
+ * Table). The model passes primary-key records; the endpoint returns the served feature values.
4
+ * Drives serving consumption and keeps features governed by Unity Catalog under the bundle principal.
5
+ */
6
+ export function databricksFeatureLookupTool(client, options) {
7
+ return {
8
+ name: options.name ?? 'databricks_feature_lookup',
9
+ description: options.description ?? 'Look up low-latency features for primary-key records from a Databricks Feature Serving endpoint.',
10
+ inputSchema: {
11
+ type: 'object',
12
+ additionalProperties: false,
13
+ properties: {
14
+ records: {
15
+ type: 'array',
16
+ items: { type: 'object', additionalProperties: true },
17
+ minItems: 1,
18
+ description: 'Primary-key records, e.g. [{ "user_id": 123 }].',
19
+ },
20
+ },
21
+ required: ['records'],
22
+ },
23
+ metadata: { effect: 'read', provider: 'databricks', service: 'feature-serving' },
24
+ execute: (input) => client.post(`/serving-endpoints/${encodeURIComponent(options.endpoint)}/invocations`, {
25
+ dataframe_records: input.records,
26
+ }),
27
+ };
28
+ }
29
+ //# sourceMappingURL=feature-serving.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-serving.js","sourceRoot":"","sources":["../src/feature-serving.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAA4B,EAAE,OAA2C;IACnH,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,2BAA2B;QACjD,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,kGAAkG;QACtI,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,UAAU,EAAE;gBACV,OAAO,EAAE;oBACP,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE;oBACrD,QAAQ,EAAE,CAAC;oBACX,WAAW,EAAE,iDAAiD;iBAC/D;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,CAAC;SACtB;QACD,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE;QAChF,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,EAAE;YACxG,iBAAiB,EAAE,KAAK,CAAC,OAAO;SACjC,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { ToolDef } from '@fabric-harness/sdk';
2
+ import type { DatabricksRestClient } from './client.js';
3
+ export interface DatabricksGenieToolOptions {
4
+ /** AI/BI Genie space id. */
5
+ spaceId: string;
6
+ name?: string;
7
+ description?: string;
8
+ pollIntervalMs?: number;
9
+ timeoutMs?: number;
10
+ }
11
+ /**
12
+ * AI/BI Genie — delegate a natural-language analytics question to a governed Genie space. Genie
13
+ * generates and runs SQL on the warehouse and returns an answer; this tool returns the answer text,
14
+ * the generated SQL, and the result rows. Pass `conversationId` to continue a multi-turn thread.
15
+ *
16
+ * Genie response field names vary by API version — parsed defensively; smoke-test against a live space.
17
+ */
18
+ export declare function databricksGenieTool(client: DatabricksRestClient, options: DatabricksGenieToolOptions): ToolDef<{
19
+ question: string;
20
+ conversationId?: string;
21
+ }, unknown>;
22
+ //# sourceMappingURL=genie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"genie.d.ts","sourceRoot":"","sources":["../src/genie.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,0BAA0B;IACzC,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,OAAO,CAAC,CAoDtK"}
package/dist/genie.js ADDED
@@ -0,0 +1,60 @@
1
+ const TERMINAL_STATES = new Set(['COMPLETED', 'FAILED', 'CANCELLED', 'QUERY_RESULT_EXPIRED']);
2
+ const enc = encodeURIComponent;
3
+ /**
4
+ * AI/BI Genie — delegate a natural-language analytics question to a governed Genie space. Genie
5
+ * generates and runs SQL on the warehouse and returns an answer; this tool returns the answer text,
6
+ * the generated SQL, and the result rows. Pass `conversationId` to continue a multi-turn thread.
7
+ *
8
+ * Genie response field names vary by API version — parsed defensively; smoke-test against a live space.
9
+ */
10
+ export function databricksGenieTool(client, options) {
11
+ const intervalMs = options.pollIntervalMs ?? 2000;
12
+ const timeoutMs = options.timeoutMs ?? 120_000;
13
+ const space = `/api/2.0/genie/spaces/${enc(options.spaceId)}`;
14
+ return {
15
+ name: options.name ?? 'databricks_genie_ask',
16
+ description: options.description ?? 'Ask a natural-language analytics question in a Databricks AI/BI Genie space; returns the answer, generated SQL, and result rows.',
17
+ inputSchema: {
18
+ type: 'object',
19
+ additionalProperties: false,
20
+ properties: { question: { type: 'string' }, conversationId: { type: 'string' } },
21
+ required: ['question'],
22
+ },
23
+ metadata: { effect: 'execute', provider: 'databricks', service: 'genie' },
24
+ async execute(input) {
25
+ let conversationId = input.conversationId;
26
+ let messageId;
27
+ if (conversationId) {
28
+ const res = await client.post(`${space}/conversations/${enc(conversationId)}/messages`, { content: input.question });
29
+ messageId = String(res.message_id ?? res.id ?? '');
30
+ }
31
+ else {
32
+ const res = await client.post(`${space}/start-conversation`, { content: input.question });
33
+ conversationId = String(res.conversation_id ?? res.conversation?.id ?? '');
34
+ messageId = String(res.message_id ?? res.message?.id ?? '');
35
+ }
36
+ const messagePath = `${space}/conversations/${enc(conversationId)}/messages/${enc(messageId)}`;
37
+ const deadline = Date.now() + timeoutMs;
38
+ let message = await client.get(messagePath);
39
+ while (!TERMINAL_STATES.has(message.status ?? '') && Date.now() < deadline) {
40
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
41
+ message = await client.get(messagePath);
42
+ }
43
+ const text = message.attachments?.map((a) => a.text?.content).filter(Boolean).join('\n') || undefined;
44
+ const sql = message.attachments?.find((a) => a.query?.query)?.query?.query;
45
+ let result;
46
+ if (sql) {
47
+ result = await client.get(`${messagePath}/query-result`).catch(() => undefined);
48
+ }
49
+ return {
50
+ conversationId,
51
+ messageId,
52
+ status: message.status,
53
+ ...(text ? { text } : {}),
54
+ ...(sql ? { sql } : {}),
55
+ ...(result !== undefined ? { result } : {}),
56
+ };
57
+ },
58
+ };
59
+ }
60
+ //# sourceMappingURL=genie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"genie.js","sourceRoot":"","sources":["../src/genie.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { ApprovalPolicyRule, CapabilityPolicy, JsonObject, ToolDef } from '@fabric-harness/sdk';
2
+ /**
3
+ * Governance for Databricks tools is **layered on top of Unity Catalog, never a replacement.** UC
4
+ * enforces table/row/column ACLs natively via the acting principal (see identity.ts). These helpers
5
+ * add the things UC doesn't: an **audit/lineage** stamp on every tool call, **approval routing** for
6
+ * sensitive operations, and an **egress allowlist** pinned to the workspace — all expressed through
7
+ * the SDK's existing `CapabilityPolicy`, so the loop enforces them without a bespoke engine.
8
+ */
9
+ export interface DatabricksLineageRecord {
10
+ tool: string;
11
+ /** From the tool's `metadata.service` (e.g. 'sql', 'unity-catalog', 'jobs'). */
12
+ service?: string;
13
+ provider?: string;
14
+ /** Stable label for the acting principal — never the token. */
15
+ principal?: string;
16
+ /** Durable submission owning this tool call (v2 correlation, from the ambient submission context). */
17
+ submissionId?: string;
18
+ attemptId?: string;
19
+ tenantId?: string;
20
+ catalog?: string;
21
+ schema?: string;
22
+ input: JsonObject;
23
+ startedAt: string;
24
+ finishedAt: string;
25
+ ok: boolean;
26
+ error?: string;
27
+ }
28
+ export interface DatabricksGovernanceOptions {
29
+ /** Stable label for the acting principal, recorded in lineage. Never pass a token here. */
30
+ principal?: string;
31
+ /** Sink for lineage/audit records. Defaults to no-op; wire to OTel / `onEvent` at the app layer. */
32
+ onLineage?: (record: DatabricksLineageRecord) => void;
33
+ /**
34
+ * Optional belt-and-suspenders catalog allowlist. Calls whose input references a catalog outside
35
+ * the list are rejected before execution. UC remains the source of truth; this is defense in depth.
36
+ */
37
+ catalogs?: string[];
38
+ /** Clock injection for tests. */
39
+ now?: () => Date;
40
+ }
41
+ /** Wraps one Databricks tool to stamp lineage/audit and enforce the optional catalog allowlist. */
42
+ export declare function withGovernance<I, O>(tool: ToolDef<I, O>, options?: DatabricksGovernanceOptions): ToolDef<I, O>;
43
+ /** Wraps a set of Databricks tools with {@link withGovernance}. */
44
+ export declare function withGovernanceTools(tools: ToolDef[], options?: DatabricksGovernanceOptions): ToolDef[];
45
+ export interface DatabricksApprovalRuleOptions {
46
+ /** Opaque approval audience (e.g. 'data-steward'). */
47
+ audience: string;
48
+ /** Restrict to these `metadata.service` values. Default: gate every write/execute tool. */
49
+ services?: string[];
50
+ reason?: string;
51
+ ttlSeconds?: number;
52
+ }
53
+ /** Builds approval rules (one per gated tool) for `CapabilityPolicy.toolPolicy.approvalRules`. */
54
+ export declare function databricksApprovalRules(tools: ToolDef[], options: DatabricksApprovalRuleOptions): ApprovalPolicyRule[];
55
+ export interface DatabricksGovernancePolicyOptions {
56
+ tools: ToolDef[];
57
+ /** Workspace host(s) to pin outbound egress to (URL or bare host). */
58
+ host?: string | string[];
59
+ /** When set, sensitive tools route to this approval audience. */
60
+ stewardAudience?: string;
61
+ approvalServices?: string[];
62
+ ttlSeconds?: number;
63
+ }
64
+ /**
65
+ * Assembles a `CapabilityPolicy` for a Databricks tool set: approval routing for sensitive
66
+ * operations (if `stewardAudience` is set) plus an egress allowlist pinned to the workspace host(s).
67
+ * Used by the `databricks()` bundle; can also be merged into an agent's own policy.
68
+ */
69
+ export declare function databricksGovernancePolicy(options: DatabricksGovernancePolicyOptions): CapabilityPolicy;
70
+ //# sourceMappingURL=governance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance.d.ts","sourceRoot":"","sources":["../src/governance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAErG;;;;;;GAMG;AAEH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,2FAA2F;IAC3F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oGAAoG;IACpG,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACtD;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAeD,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,GAAE,2BAAgC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAkDlH;AAED,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,GAAE,2BAAgC,GAAG,OAAO,EAAE,CAE1G;AAED,MAAM,WAAW,6BAA6B;IAC5C,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD,kGAAkG;AAClG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,6BAA6B,GAAG,kBAAkB,EAAE,CAUtH;AAED,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAcD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,iCAAiC,GAAG,gBAAgB,CAcvG"}
@@ -0,0 +1,123 @@
1
+ import { currentSubmissionContext, redactJson } from '@fabric-harness/sdk';
2
+ function metaString(tool, key) {
3
+ const value = tool.metadata?.[key];
4
+ return typeof value === 'string' ? value : undefined;
5
+ }
6
+ function inputString(input, key) {
7
+ if (input && typeof input === 'object' && key in input) {
8
+ const value = input[key];
9
+ if (typeof value === 'string')
10
+ return value;
11
+ }
12
+ return undefined;
13
+ }
14
+ /** Wraps one Databricks tool to stamp lineage/audit and enforce the optional catalog allowlist. */
15
+ export function withGovernance(tool, options = {}) {
16
+ const inner = tool.execute;
17
+ if (!inner)
18
+ return tool;
19
+ const now = options.now ?? (() => new Date());
20
+ return {
21
+ ...tool,
22
+ metadata: { ...(tool.metadata ?? {}), governed: true },
23
+ async execute(input, context) {
24
+ const catalog = inputString(input, 'catalog');
25
+ const schema = inputString(input, 'schema');
26
+ if (options.catalogs && catalog && !options.catalogs.includes(catalog)) {
27
+ throw new Error(`databricks governance: catalog "${catalog}" is not in the allowed list (${options.catalogs.join(', ')}).`);
28
+ }
29
+ const startedAt = now().toISOString();
30
+ const service = metaString(tool, 'service');
31
+ const provider = metaString(tool, 'provider');
32
+ // Correlate with the durable submission owning this turn (set by the
33
+ // submission runner); the acting principal falls back to the actor's
34
+ // governed identity when no explicit label was configured.
35
+ const submission = currentSubmissionContext();
36
+ const principal = options.principal ?? submission?.actor?.principal?.id;
37
+ const base = {
38
+ tool: tool.name,
39
+ ...(service !== undefined ? { service } : {}),
40
+ ...(provider !== undefined ? { provider } : {}),
41
+ ...(principal !== undefined ? { principal } : {}),
42
+ ...(submission
43
+ ? {
44
+ submissionId: submission.submissionId,
45
+ attemptId: submission.attemptId,
46
+ ...(submission.tenantId !== undefined ? { tenantId: submission.tenantId } : {}),
47
+ }
48
+ : {}),
49
+ ...(catalog !== undefined ? { catalog } : {}),
50
+ ...(schema !== undefined ? { schema } : {}),
51
+ // Redact secret-ish keys before the input enters the audit/lineage record.
52
+ input: redactJson((input ?? {})),
53
+ startedAt,
54
+ };
55
+ try {
56
+ const result = await inner(input, context);
57
+ options.onLineage?.({ ...base, finishedAt: now().toISOString(), ok: true });
58
+ return result;
59
+ }
60
+ catch (error) {
61
+ options.onLineage?.({ ...base, finishedAt: now().toISOString(), ok: false, error: error instanceof Error ? error.message : String(error) });
62
+ throw error;
63
+ }
64
+ },
65
+ };
66
+ }
67
+ /** Wraps a set of Databricks tools with {@link withGovernance}. */
68
+ export function withGovernanceTools(tools, options = {}) {
69
+ return tools.map((tool) => withGovernance(tool, options));
70
+ }
71
+ function shouldGate(tool, services) {
72
+ if (services)
73
+ return services.includes(metaString(tool, 'service') ?? '');
74
+ const effect = tool.metadata?.effect;
75
+ return effect === 'write' || effect === 'execute';
76
+ }
77
+ /** Builds approval rules (one per gated tool) for `CapabilityPolicy.toolPolicy.approvalRules`. */
78
+ export function databricksApprovalRules(tools, options) {
79
+ return tools
80
+ .filter((tool) => shouldGate(tool, options.services))
81
+ .map((tool) => ({
82
+ pattern: tool.name,
83
+ audience: options.audience,
84
+ // ${name} is templated by the policy layer at request time — keep it literal here.
85
+ reason: options.reason ?? 'Databricks ${name} requires data-steward approval.',
86
+ ...(options.ttlSeconds !== undefined ? { ttlSeconds: options.ttlSeconds } : {}),
87
+ }));
88
+ }
89
+ function toHostPatterns(host) {
90
+ if (!host)
91
+ return [];
92
+ const list = Array.isArray(host) ? host : [host];
93
+ return list.map((entry) => {
94
+ try {
95
+ return new URL(entry.includes('://') ? entry : `https://${entry}`).host;
96
+ }
97
+ catch {
98
+ return entry;
99
+ }
100
+ });
101
+ }
102
+ /**
103
+ * Assembles a `CapabilityPolicy` for a Databricks tool set: approval routing for sensitive
104
+ * operations (if `stewardAudience` is set) plus an egress allowlist pinned to the workspace host(s).
105
+ * Used by the `databricks()` bundle; can also be merged into an agent's own policy.
106
+ */
107
+ export function databricksGovernancePolicy(options) {
108
+ const policy = {};
109
+ if (options.stewardAudience) {
110
+ policy.toolPolicy = {
111
+ approvalRules: databricksApprovalRules(options.tools, {
112
+ audience: options.stewardAudience,
113
+ ...(options.approvalServices ? { services: options.approvalServices } : {}),
114
+ ...(options.ttlSeconds !== undefined ? { ttlSeconds: options.ttlSeconds } : {}),
115
+ }),
116
+ };
117
+ }
118
+ const hosts = toHostPatterns(options.host);
119
+ if (hosts.length > 0)
120
+ policy.network = { mode: 'allowlist', hosts };
121
+ return policy;
122
+ }
123
+ //# sourceMappingURL=governance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance.js","sourceRoot":"","sources":["../src/governance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import type { FabricPrincipal } from '@fabric-harness/sdk';
2
+ /**
3
+ * A bearer-token resolver awaited per request. Shape matches what {@link DatabricksRestClient},
4
+ * {@link databricksFoundationModelProvider} (via `tokenProvider`), and the Lakebase store accept,
5
+ * so a single principal threads through model calls, data calls, and state.
6
+ */
7
+ export type DatabricksTokenProvider = () => Promise<string>;
8
+ export type DatabricksPrincipal =
9
+ /** Personal access token. Dev / single-user only. */
10
+ {
11
+ kind: 'pat';
12
+ token: string;
13
+ label?: string;
14
+ }
15
+ /** OAuth machine-to-machine (client-credentials). The agent acts as one governed identity. */
16
+ | {
17
+ kind: 'service-principal';
18
+ host: string;
19
+ clientId: string;
20
+ clientSecret: string;
21
+ /** OAuth scope; defaults to `all-apis`. */
22
+ scope?: string;
23
+ /** Refresh this many seconds before expiry to avoid using a token that expires mid-flight. Default 60. */
24
+ refreshSkewSeconds?: number;
25
+ fetchImpl?: typeof fetch;
26
+ }
27
+ /**
28
+ * On-behalf-of a specific end user. The caller binds the user's token resolver (e.g. from a
29
+ * channel `actor`), so Unity Catalog enforces *that human's* grants. The resolver is responsible
30
+ * for its own caching/refresh.
31
+ */
32
+ | {
33
+ kind: 'on-behalf-of';
34
+ userToken: () => string | Promise<string>;
35
+ label?: string;
36
+ };
37
+ /** Builds a cached, auto-refreshing token provider for a Databricks principal. */
38
+ export declare function databricksIdentity(principal: DatabricksPrincipal): DatabricksTokenProvider;
39
+ /**
40
+ * The service principal a Databricks App runs as, from the standard app
41
+ * runtime environment (`DATABRICKS_HOST` / `DATABRICKS_CLIENT_ID` /
42
+ * `DATABRICKS_CLIENT_SECRET`). Returns `undefined` when any variable is
43
+ * missing, so callers can fall back to explicit configuration.
44
+ */
45
+ export declare function appServicePrincipalFromEnv(env?: Record<string, string | undefined>): Extract<DatabricksPrincipal, {
46
+ kind: 'service-principal';
47
+ }> | undefined;
48
+ /**
49
+ * On-behalf-of principal from Databricks Apps user-authorization headers:
50
+ * the platform forwards the signed-in user's access token as
51
+ * `x-forwarded-access-token` (plus `x-forwarded-email`/`x-forwarded-user`).
52
+ * Returns `undefined` when the request carries no user token (e.g. app
53
+ * service-to-service traffic) so callers fall back to the app principal.
54
+ */
55
+ export declare function onBehalfOfFromHeaders(headers: Headers | Record<string, string | string[] | undefined>): Extract<DatabricksPrincipal, {
56
+ kind: 'on-behalf-of';
57
+ }> | undefined;
58
+ export interface FabricPrincipalOverrides {
59
+ id?: string;
60
+ /** Unity Catalog principal name, when it differs from the id. */
61
+ ucPrincipal?: string;
62
+ displayName?: string;
63
+ /** Mark a service principal as the hosting app's own identity. */
64
+ asAppPrincipal?: boolean;
65
+ }
66
+ /**
67
+ * Map a Databricks principal onto the SDK's {@link FabricPrincipal} so the
68
+ * governed identity rides submissions → tool calls → lineage/cost records.
69
+ * Never carries a token — ids and labels only.
70
+ */
71
+ export declare function fabricPrincipalFor(principal: DatabricksPrincipal, overrides?: FabricPrincipalOverrides): FabricPrincipal;
72
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;AAE5D,MAAM,MAAM,mBAAmB;AAC7B,qDAAqD;AACnD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AAChD,8FAA8F;GAC5F;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0GAA0G;IAC1G,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AACH;;;;GAIG;GACD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAQxF,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,mBAAmB,GAAG,uBAAuB,CAU1F;AA+CD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAqD,GAC1F,OAAO,CAAC,mBAAmB,EAAE;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,CAAC,GAAG,SAAS,CAWzE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAC/D,OAAO,CAAC,mBAAmB,EAAE;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC,GAAG,SAAS,CAUpE;AAED,MAAM,WAAW,wBAAwB;IACvC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,mBAAmB,EAAE,SAAS,GAAE,wBAA6B,GAAG,eAAe,CAiB5H"}
@@ -0,0 +1,119 @@
1
+ import { redactText } from '@fabric-harness/sdk';
2
+ /** Builds a cached, auto-refreshing token provider for a Databricks principal. */
3
+ export function databricksIdentity(principal) {
4
+ if (principal.kind === 'pat') {
5
+ const { token } = principal;
6
+ return async () => token;
7
+ }
8
+ if (principal.kind === 'on-behalf-of') {
9
+ const { userToken } = principal;
10
+ return async () => userToken();
11
+ }
12
+ return servicePrincipalProvider(principal);
13
+ }
14
+ function servicePrincipalProvider(principal) {
15
+ const host = principal.host.replace(/\/$/, '');
16
+ const scope = principal.scope ?? 'all-apis';
17
+ const skewMs = (principal.refreshSkewSeconds ?? 60) * 1000;
18
+ const fetchImpl = principal.fetchImpl ?? fetch;
19
+ const basic = base64(`${principal.clientId}:${principal.clientSecret}`);
20
+ let cached;
21
+ let inflight;
22
+ const refresh = async () => {
23
+ const response = await fetchImpl(`${host}/oidc/v1/token`, {
24
+ method: 'POST',
25
+ headers: {
26
+ authorization: `Basic ${basic}`,
27
+ 'content-type': 'application/x-www-form-urlencoded',
28
+ },
29
+ body: `grant_type=client_credentials&scope=${encodeURIComponent(scope)}`,
30
+ });
31
+ if (!response.ok) {
32
+ const text = redactText(await response.text(), { additionalSecrets: [principal.clientSecret] });
33
+ throw new Error(`databricks oauth: ${response.status} ${response.statusText}: ${text.slice(0, 500)}`);
34
+ }
35
+ const json = (await response.json());
36
+ if (!json.access_token)
37
+ throw new Error('databricks oauth: response missing access_token.');
38
+ const ttlMs = (json.expires_in ?? 3600) * 1000;
39
+ cached = { token: json.access_token, refreshAtMs: Date.now() + Math.max(0, ttlMs - skewMs) };
40
+ return json.access_token;
41
+ };
42
+ return async () => {
43
+ if (cached && Date.now() < cached.refreshAtMs)
44
+ return cached.token;
45
+ // Dedupe concurrent refreshes so a burst of requests triggers a single token exchange.
46
+ if (!inflight)
47
+ inflight = refresh().finally(() => { inflight = undefined; });
48
+ return inflight;
49
+ };
50
+ }
51
+ function base64(value) {
52
+ if (typeof Buffer !== 'undefined')
53
+ return Buffer.from(value, 'utf8').toString('base64');
54
+ return btoa(value);
55
+ }
56
+ // ─── Identity propagation (v2, workstream C3) ───────────────────────────────
57
+ /**
58
+ * The service principal a Databricks App runs as, from the standard app
59
+ * runtime environment (`DATABRICKS_HOST` / `DATABRICKS_CLIENT_ID` /
60
+ * `DATABRICKS_CLIENT_SECRET`). Returns `undefined` when any variable is
61
+ * missing, so callers can fall back to explicit configuration.
62
+ */
63
+ export function appServicePrincipalFromEnv(env = typeof process !== 'undefined' ? process.env : {}) {
64
+ const host = env.DATABRICKS_HOST;
65
+ const clientId = env.DATABRICKS_CLIENT_ID;
66
+ const clientSecret = env.DATABRICKS_CLIENT_SECRET;
67
+ if (!host || !clientId || !clientSecret)
68
+ return undefined;
69
+ return {
70
+ kind: 'service-principal',
71
+ host: host.includes('://') ? host : `https://${host}`,
72
+ clientId,
73
+ clientSecret,
74
+ };
75
+ }
76
+ /**
77
+ * On-behalf-of principal from Databricks Apps user-authorization headers:
78
+ * the platform forwards the signed-in user's access token as
79
+ * `x-forwarded-access-token` (plus `x-forwarded-email`/`x-forwarded-user`).
80
+ * Returns `undefined` when the request carries no user token (e.g. app
81
+ * service-to-service traffic) so callers fall back to the app principal.
82
+ */
83
+ export function onBehalfOfFromHeaders(headers) {
84
+ const read = (name) => {
85
+ if (typeof headers.get === 'function')
86
+ return headers.get(name) ?? undefined;
87
+ const value = headers[name];
88
+ return Array.isArray(value) ? value[0] : value;
89
+ };
90
+ const token = read('x-forwarded-access-token');
91
+ if (!token)
92
+ return undefined;
93
+ const label = read('x-forwarded-email') ?? read('x-forwarded-user');
94
+ return { kind: 'on-behalf-of', userToken: () => token, ...(label ? { label } : {}) };
95
+ }
96
+ /**
97
+ * Map a Databricks principal onto the SDK's {@link FabricPrincipal} so the
98
+ * governed identity rides submissions → tool calls → lineage/cost records.
99
+ * Never carries a token — ids and labels only.
100
+ */
101
+ export function fabricPrincipalFor(principal, overrides = {}) {
102
+ if (principal.kind === 'service-principal') {
103
+ const id = overrides.id ?? principal.clientId;
104
+ return {
105
+ kind: overrides.asAppPrincipal ? 'app-principal' : 'service-principal',
106
+ id,
107
+ ucPrincipal: overrides.ucPrincipal ?? id,
108
+ ...(overrides.displayName ? { displayName: overrides.displayName } : {}),
109
+ };
110
+ }
111
+ const id = overrides.id ?? principal.label ?? (principal.kind === 'pat' ? 'pat-user' : 'on-behalf-of-user');
112
+ return {
113
+ kind: 'user',
114
+ id,
115
+ ...(overrides.ucPrincipal ? { ucPrincipal: overrides.ucPrincipal } : {}),
116
+ ...(overrides.displayName ? { displayName: overrides.displayName } : {}),
117
+ };
118
+ }
119
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAsCjD,kFAAkF;AAClF,MAAM,UAAU,kBAAkB,CAAC,SAA8B;IAC/D,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;QAC5B,OAAO,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC;IAC3B,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACtC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC;QAChC,OAAO,KAAK,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,wBAAwB,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,wBAAwB,CAAC,SAAsE;IACtG,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,UAAU,CAAC;IAC5C,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,kBAAkB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IAC3D,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,IAAI,KAAK,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;IAExE,IAAI,MAA+B,CAAC;IACpC,IAAI,QAAqC,CAAC;IAE1C,MAAM,OAAO,GAAG,KAAK,IAAqB,EAAE;QAC1C,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,gBAAgB,EAAE;YACxD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,SAAS,KAAK,EAAE;gBAC/B,cAAc,EAAE,mCAAmC;aACpD;YACD,IAAI,EAAE,uCAAuC,kBAAkB,CAAC,KAAK,CAAC,EAAE;SACzE,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,iBAAiB,EAAE,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAChG,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACxG,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmD,CAAC;QACvF,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAC5F,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC;QAC/C,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC;QAC7F,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC,CAAC;IAEF,OAAO,KAAK,IAAI,EAAE;QAChB,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,WAAW;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC;QACnE,uFAAuF;QACvF,IAAI,CAAC,QAAQ;YAAE,QAAQ,GAAG,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACxF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC;AAED,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAA0C,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;IAE3F,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC;IACjC,MAAM,QAAQ,GAAG,GAAG,CAAC,oBAAoB,CAAC;IAC1C,MAAM,YAAY,GAAG,GAAG,CAAC,wBAAwB,CAAC;IAClD,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IAC1D,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE;QACrD,QAAQ;QACR,YAAY;KACb,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAgE;IAEhE,MAAM,IAAI,GAAG,CAAC,IAAY,EAAsB,EAAE;QAChD,IAAI,OAAQ,OAAmB,CAAC,GAAG,KAAK,UAAU;YAAE,OAAQ,OAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;QACvG,MAAM,KAAK,GAAI,OAAyD,CAAC,IAAI,CAAC,CAAC;QAC/E,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACjD,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACpE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACvF,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAA8B,EAAE,YAAsC,EAAE;IACzG,IAAI,SAAS,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;QAC3C,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,QAAQ,CAAC;QAC9C,OAAO;YACL,IAAI,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,mBAAmB;YACtE,EAAE;YACF,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,EAAE;YACxC,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzE,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC5G,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,EAAE;QACF,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzE,CAAC;AACJ,CAAC"}