@dbx-tools/appkit-mastra 0.5.1 → 0.6.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.
- package/README.md +22 -7
- package/index.ts +4 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +3 -1
- package/lib/src/config.d.ts +33 -0
- package/lib/src/config.js +6 -1
- package/lib/src/identity.d.ts +80 -0
- package/lib/src/identity.js +95 -0
- package/lib/src/plugin.d.ts +22 -0
- package/lib/src/plugin.js +40 -8
- package/lib/src/server.d.ts +20 -2
- package/lib/src/server.js +32 -13
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/config.ts +39 -0
- package/src/identity.ts +110 -0
- package/src/plugin.ts +40 -7
- package/src/server.ts +50 -12
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which Databricks identity a chat turn's workspace calls run as.
|
|
3
|
+
*
|
|
4
|
+
* Every Databricks call a turn makes - the `/serving-endpoints` catalogue the
|
|
5
|
+
* model picker reads, Genie suggestions, `ask_genie`, and the Statement
|
|
6
|
+
* Execution fetch behind a `[data:<id>]` embed - goes through the workspace
|
|
7
|
+
* client on the ambient AppKit execution context. That context is user-scoped
|
|
8
|
+
* (OBO) whenever the plugin enters `asUser(req)` and the app's service principal
|
|
9
|
+
* otherwise, so ONE decision - do we enter that scope for this request - moves
|
|
10
|
+
* every call site together. This module owns that decision.
|
|
11
|
+
*
|
|
12
|
+
* Why the option exists: OBO requires the caller to be a member of the
|
|
13
|
+
* WORKSPACE, not merely of the Databricks account. An app shared with an
|
|
14
|
+
* account-level group can therefore be opened by someone whose OBO token is
|
|
15
|
+
* perfectly valid but whose every workspace call fails with `Unauthorized
|
|
16
|
+
* access to Org: <workspace-id>`, and granting workspace membership is not
|
|
17
|
+
* always available - a workspace caps membership far below the size of a large
|
|
18
|
+
* account's user group. The app's own service principal already holds the Genie
|
|
19
|
+
* / warehouse / serving / Unity Catalog grants the app was deployed with, and
|
|
20
|
+
* works for every caller.
|
|
21
|
+
*
|
|
22
|
+
* The two modes, from `config.genieIdentity` (env: {@link IDENTITY_ENV}):
|
|
23
|
+
*
|
|
24
|
+
* - `"user"` (default): always OBO. Calls are attributed per user and Genie /
|
|
25
|
+
* Unity Catalog row filters apply per user. Correct whenever every caller is
|
|
26
|
+
* a workspace member. This is the historical behavior, so the option is
|
|
27
|
+
* purely additive - an app that never sets it is unchanged.
|
|
28
|
+
* - `"service-principal"`: always the app service principal. Needs no OBO
|
|
29
|
+
* scopes and works for any caller who can open the app, at the cost of
|
|
30
|
+
* per-user attribution in Genie / Unity Catalog.
|
|
31
|
+
*
|
|
32
|
+
* What `"service-principal"` does NOT change is WHO the turn belongs to. The
|
|
33
|
+
* memory thread's `resourceId`, the per-user cache namespace, and the user
|
|
34
|
+
* metadata on traces still come from the forwarded request headers, so two
|
|
35
|
+
* account users sharing the service principal's data access still get separate
|
|
36
|
+
* conversations and cannot read each other's threads or cached charts. Only the
|
|
37
|
+
* Databricks credential is shared.
|
|
38
|
+
*
|
|
39
|
+
* @module
|
|
40
|
+
*/
|
|
41
|
+
import { ConfigurationError } from "@databricks/appkit";
|
|
42
|
+
import { string } from "@dbx-tools/shared-core";
|
|
43
|
+
/** Environment fallback for `config.genieIdentity`. */
|
|
44
|
+
export const IDENTITY_ENV = "MASTRA_GENIE_IDENTITY";
|
|
45
|
+
/** Every accepted {@link MastraIdentityMode}. */
|
|
46
|
+
export const IDENTITY_MODES = ["user", "service-principal"];
|
|
47
|
+
/**
|
|
48
|
+
* Default mode. `"user"` keeps OBO the only identity unless an app opts in, so
|
|
49
|
+
* adopting this option can never silently widen an existing app's data access.
|
|
50
|
+
*/
|
|
51
|
+
export const DEFAULT_IDENTITY_MODE = "user";
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the configured mode: explicit plugin config, then {@link IDENTITY_ENV},
|
|
54
|
+
* then {@link DEFAULT_IDENTITY_MODE}.
|
|
55
|
+
*
|
|
56
|
+
* An unrecognized value throws rather than falling back, since falling back
|
|
57
|
+
* would silently keep serving OBO - and the 500s it produces - to exactly the
|
|
58
|
+
* callers the option was set to accommodate.
|
|
59
|
+
*/
|
|
60
|
+
export function resolveIdentityMode(configured) {
|
|
61
|
+
const raw = string.trimToNull(configured) ?? string.trimToNull(process.env[IDENTITY_ENV]);
|
|
62
|
+
if (raw === null)
|
|
63
|
+
return DEFAULT_IDENTITY_MODE;
|
|
64
|
+
const mode = raw.toLowerCase();
|
|
65
|
+
if (!IDENTITY_MODES.includes(mode)) {
|
|
66
|
+
throw new ConfigurationError(`genieIdentity must be one of ${IDENTITY_MODES.join(" | ")} (env: ${IDENTITY_ENV})`, { context: { field: "genieIdentity", envVar: IDENTITY_ENV, received: raw } });
|
|
67
|
+
}
|
|
68
|
+
return mode;
|
|
69
|
+
}
|
|
70
|
+
/** Header Databricks Apps forward the signed-in user's id on. */
|
|
71
|
+
export const USER_ID_HEADER = "x-forwarded-user";
|
|
72
|
+
/** Header Databricks Apps forward the signed-in user's email on. */
|
|
73
|
+
export const USER_EMAIL_HEADER = "x-forwarded-email";
|
|
74
|
+
/**
|
|
75
|
+
* The forwarded user id on `req`, or `undefined`. Used to attribute a turn to
|
|
76
|
+
* the real caller in `service-principal` mode, where the Databricks client is
|
|
77
|
+
* the app SP but memory / cache / traces must still key off the user.
|
|
78
|
+
*/
|
|
79
|
+
export function requestUserId(req) {
|
|
80
|
+
return string.trimToNull(req.header(USER_ID_HEADER)) ?? undefined;
|
|
81
|
+
}
|
|
82
|
+
/** The forwarded user email on `req`, or `undefined`. */
|
|
83
|
+
export function requestUserEmail(req) {
|
|
84
|
+
return string.trimToNull(req.header(USER_EMAIL_HEADER)) ?? undefined;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Whether this request should run its Databricks calls as the app service
|
|
88
|
+
* principal rather than OBO. `"service-principal"` always does; `"user"` never
|
|
89
|
+
* does. The request is accepted for symmetry and to leave room for
|
|
90
|
+
* request-scoped policy later; it is unused today.
|
|
91
|
+
*/
|
|
92
|
+
export function useServicePrincipal(mode, _req) {
|
|
93
|
+
return mode === "service-principal";
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaWRlbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVDRztBQUVILE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQU1oRCx1REFBdUQ7QUFDdkQsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLHVCQUF1QixDQUFDO0FBRXBELGlEQUFpRDtBQUNqRCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQWtDLENBQUMsTUFBTSxFQUFFLG1CQUFtQixDQUFDLENBQUM7QUFFM0Y7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQXVCLE1BQU0sQ0FBQztBQUVoRTs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLFVBQThCO0lBQ2hFLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7SUFDMUYsSUFBSSxHQUFHLEtBQUssSUFBSTtRQUFFLE9BQU8scUJBQXFCLENBQUM7SUFDL0MsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLFdBQVcsRUFBd0IsQ0FBQztJQUNyRCxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ25DLE1BQU0sSUFBSSxrQkFBa0IsQ0FDMUIsZ0NBQWdDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsWUFBWSxHQUFHLEVBQ25GLEVBQUUsT0FBTyxFQUFFLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUM3RSxDQUFDO0lBQ0osQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVELGlFQUFpRTtBQUNqRSxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsa0JBQWtCLENBQUM7QUFFakQsb0VBQW9FO0FBQ3BFLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLG1CQUFtQixDQUFDO0FBRXJEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLEdBQW9CO0lBQ2hELE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLElBQUksU0FBUyxDQUFDO0FBQ3BFLENBQUM7QUFFRCx5REFBeUQ7QUFDekQsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEdBQW9CO0lBQ25ELE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7QUFDdkUsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLElBQXdCLEVBQUUsSUFBc0I7SUFDbEYsT0FBTyxJQUFJLEtBQUssbUJBQW1CLENBQUM7QUFDdEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogV2hpY2ggRGF0YWJyaWNrcyBpZGVudGl0eSBhIGNoYXQgdHVybidzIHdvcmtzcGFjZSBjYWxscyBydW4gYXMuXG4gKlxuICogRXZlcnkgRGF0YWJyaWNrcyBjYWxsIGEgdHVybiBtYWtlcyAtIHRoZSBgL3NlcnZpbmctZW5kcG9pbnRzYCBjYXRhbG9ndWUgdGhlXG4gKiBtb2RlbCBwaWNrZXIgcmVhZHMsIEdlbmllIHN1Z2dlc3Rpb25zLCBgYXNrX2dlbmllYCwgYW5kIHRoZSBTdGF0ZW1lbnRcbiAqIEV4ZWN1dGlvbiBmZXRjaCBiZWhpbmQgYSBgW2RhdGE6PGlkPl1gIGVtYmVkIC0gZ29lcyB0aHJvdWdoIHRoZSB3b3Jrc3BhY2VcbiAqIGNsaWVudCBvbiB0aGUgYW1iaWVudCBBcHBLaXQgZXhlY3V0aW9uIGNvbnRleHQuIFRoYXQgY29udGV4dCBpcyB1c2VyLXNjb3BlZFxuICogKE9CTykgd2hlbmV2ZXIgdGhlIHBsdWdpbiBlbnRlcnMgYGFzVXNlcihyZXEpYCBhbmQgdGhlIGFwcCdzIHNlcnZpY2UgcHJpbmNpcGFsXG4gKiBvdGhlcndpc2UsIHNvIE9ORSBkZWNpc2lvbiAtIGRvIHdlIGVudGVyIHRoYXQgc2NvcGUgZm9yIHRoaXMgcmVxdWVzdCAtIG1vdmVzXG4gKiBldmVyeSBjYWxsIHNpdGUgdG9nZXRoZXIuIFRoaXMgbW9kdWxlIG93bnMgdGhhdCBkZWNpc2lvbi5cbiAqXG4gKiBXaHkgdGhlIG9wdGlvbiBleGlzdHM6IE9CTyByZXF1aXJlcyB0aGUgY2FsbGVyIHRvIGJlIGEgbWVtYmVyIG9mIHRoZVxuICogV09SS1NQQUNFLCBub3QgbWVyZWx5IG9mIHRoZSBEYXRhYnJpY2tzIGFjY291bnQuIEFuIGFwcCBzaGFyZWQgd2l0aCBhblxuICogYWNjb3VudC1sZXZlbCBncm91cCBjYW4gdGhlcmVmb3JlIGJlIG9wZW5lZCBieSBzb21lb25lIHdob3NlIE9CTyB0b2tlbiBpc1xuICogcGVyZmVjdGx5IHZhbGlkIGJ1dCB3aG9zZSBldmVyeSB3b3Jrc3BhY2UgY2FsbCBmYWlscyB3aXRoIGBVbmF1dGhvcml6ZWRcbiAqIGFjY2VzcyB0byBPcmc6IDx3b3Jrc3BhY2UtaWQ+YCwgYW5kIGdyYW50aW5nIHdvcmtzcGFjZSBtZW1iZXJzaGlwIGlzIG5vdFxuICogYWx3YXlzIGF2YWlsYWJsZSAtIGEgd29ya3NwYWNlIGNhcHMgbWVtYmVyc2hpcCBmYXIgYmVsb3cgdGhlIHNpemUgb2YgYSBsYXJnZVxuICogYWNjb3VudCdzIHVzZXIgZ3JvdXAuIFRoZSBhcHAncyBvd24gc2VydmljZSBwcmluY2lwYWwgYWxyZWFkeSBob2xkcyB0aGUgR2VuaWVcbiAqIC8gd2FyZWhvdXNlIC8gc2VydmluZyAvIFVuaXR5IENhdGFsb2cgZ3JhbnRzIHRoZSBhcHAgd2FzIGRlcGxveWVkIHdpdGgsIGFuZFxuICogd29ya3MgZm9yIGV2ZXJ5IGNhbGxlci5cbiAqXG4gKiBUaGUgdHdvIG1vZGVzLCBmcm9tIGBjb25maWcuZ2VuaWVJZGVudGl0eWAgKGVudjoge0BsaW5rIElERU5USVRZX0VOVn0pOlxuICpcbiAqICAgLSBgXCJ1c2VyXCJgIChkZWZhdWx0KTogYWx3YXlzIE9CTy4gQ2FsbHMgYXJlIGF0dHJpYnV0ZWQgcGVyIHVzZXIgYW5kIEdlbmllIC9cbiAqICAgICBVbml0eSBDYXRhbG9nIHJvdyBmaWx0ZXJzIGFwcGx5IHBlciB1c2VyLiBDb3JyZWN0IHdoZW5ldmVyIGV2ZXJ5IGNhbGxlciBpc1xuICogICAgIGEgd29ya3NwYWNlIG1lbWJlci4gVGhpcyBpcyB0aGUgaGlzdG9yaWNhbCBiZWhhdmlvciwgc28gdGhlIG9wdGlvbiBpc1xuICogICAgIHB1cmVseSBhZGRpdGl2ZSAtIGFuIGFwcCB0aGF0IG5ldmVyIHNldHMgaXQgaXMgdW5jaGFuZ2VkLlxuICogICAtIGBcInNlcnZpY2UtcHJpbmNpcGFsXCJgOiBhbHdheXMgdGhlIGFwcCBzZXJ2aWNlIHByaW5jaXBhbC4gTmVlZHMgbm8gT0JPXG4gKiAgICAgc2NvcGVzIGFuZCB3b3JrcyBmb3IgYW55IGNhbGxlciB3aG8gY2FuIG9wZW4gdGhlIGFwcCwgYXQgdGhlIGNvc3Qgb2ZcbiAqICAgICBwZXItdXNlciBhdHRyaWJ1dGlvbiBpbiBHZW5pZSAvIFVuaXR5IENhdGFsb2cuXG4gKlxuICogV2hhdCBgXCJzZXJ2aWNlLXByaW5jaXBhbFwiYCBkb2VzIE5PVCBjaGFuZ2UgaXMgV0hPIHRoZSB0dXJuIGJlbG9uZ3MgdG8uIFRoZVxuICogbWVtb3J5IHRocmVhZCdzIGByZXNvdXJjZUlkYCwgdGhlIHBlci11c2VyIGNhY2hlIG5hbWVzcGFjZSwgYW5kIHRoZSB1c2VyXG4gKiBtZXRhZGF0YSBvbiB0cmFjZXMgc3RpbGwgY29tZSBmcm9tIHRoZSBmb3J3YXJkZWQgcmVxdWVzdCBoZWFkZXJzLCBzbyB0d29cbiAqIGFjY291bnQgdXNlcnMgc2hhcmluZyB0aGUgc2VydmljZSBwcmluY2lwYWwncyBkYXRhIGFjY2VzcyBzdGlsbCBnZXQgc2VwYXJhdGVcbiAqIGNvbnZlcnNhdGlvbnMgYW5kIGNhbm5vdCByZWFkIGVhY2ggb3RoZXIncyB0aHJlYWRzIG9yIGNhY2hlZCBjaGFydHMuIE9ubHkgdGhlXG4gKiBEYXRhYnJpY2tzIGNyZWRlbnRpYWwgaXMgc2hhcmVkLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBDb25maWd1cmF0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBzdHJpbmcgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgZXhwcmVzcyBmcm9tIFwiZXhwcmVzc1wiO1xuXG4vKiogSWRlbnRpdHkgYSBjaGF0IHR1cm4ncyBEYXRhYnJpY2tzIGNhbGxzIHJ1biBhcy4gU2VlIHRoZSBtb2R1bGUgZG9jcy4gKi9cbmV4cG9ydCB0eXBlIE1hc3RyYUlkZW50aXR5TW9kZSA9IFwidXNlclwiIHwgXCJzZXJ2aWNlLXByaW5jaXBhbFwiO1xuXG4vKiogRW52aXJvbm1lbnQgZmFsbGJhY2sgZm9yIGBjb25maWcuZ2VuaWVJZGVudGl0eWAuICovXG5leHBvcnQgY29uc3QgSURFTlRJVFlfRU5WID0gXCJNQVNUUkFfR0VOSUVfSURFTlRJVFlcIjtcblxuLyoqIEV2ZXJ5IGFjY2VwdGVkIHtAbGluayBNYXN0cmFJZGVudGl0eU1vZGV9LiAqL1xuZXhwb3J0IGNvbnN0IElERU5USVRZX01PREVTOiByZWFkb25seSBNYXN0cmFJZGVudGl0eU1vZGVbXSA9IFtcInVzZXJcIiwgXCJzZXJ2aWNlLXByaW5jaXBhbFwiXTtcblxuLyoqXG4gKiBEZWZhdWx0IG1vZGUuIGBcInVzZXJcImAga2VlcHMgT0JPIHRoZSBvbmx5IGlkZW50aXR5IHVubGVzcyBhbiBhcHAgb3B0cyBpbiwgc29cbiAqIGFkb3B0aW5nIHRoaXMgb3B0aW9uIGNhbiBuZXZlciBzaWxlbnRseSB3aWRlbiBhbiBleGlzdGluZyBhcHAncyBkYXRhIGFjY2Vzcy5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfSURFTlRJVFlfTU9ERTogTWFzdHJhSWRlbnRpdHlNb2RlID0gXCJ1c2VyXCI7XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgY29uZmlndXJlZCBtb2RlOiBleHBsaWNpdCBwbHVnaW4gY29uZmlnLCB0aGVuIHtAbGluayBJREVOVElUWV9FTlZ9LFxuICogdGhlbiB7QGxpbmsgREVGQVVMVF9JREVOVElUWV9NT0RFfS5cbiAqXG4gKiBBbiB1bnJlY29nbml6ZWQgdmFsdWUgdGhyb3dzIHJhdGhlciB0aGFuIGZhbGxpbmcgYmFjaywgc2luY2UgZmFsbGluZyBiYWNrXG4gKiB3b3VsZCBzaWxlbnRseSBrZWVwIHNlcnZpbmcgT0JPIC0gYW5kIHRoZSA1MDBzIGl0IHByb2R1Y2VzIC0gdG8gZXhhY3RseSB0aGVcbiAqIGNhbGxlcnMgdGhlIG9wdGlvbiB3YXMgc2V0IHRvIGFjY29tbW9kYXRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUlkZW50aXR5TW9kZShjb25maWd1cmVkOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBNYXN0cmFJZGVudGl0eU1vZGUge1xuICBjb25zdCByYXcgPSBzdHJpbmcudHJpbVRvTnVsbChjb25maWd1cmVkKSA/PyBzdHJpbmcudHJpbVRvTnVsbChwcm9jZXNzLmVudltJREVOVElUWV9FTlZdKTtcbiAgaWYgKHJhdyA9PT0gbnVsbCkgcmV0dXJuIERFRkFVTFRfSURFTlRJVFlfTU9ERTtcbiAgY29uc3QgbW9kZSA9IHJhdy50b0xvd2VyQ2FzZSgpIGFzIE1hc3RyYUlkZW50aXR5TW9kZTtcbiAgaWYgKCFJREVOVElUWV9NT0RFUy5pbmNsdWRlcyhtb2RlKSkge1xuICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXG4gICAgICBgZ2VuaWVJZGVudGl0eSBtdXN0IGJlIG9uZSBvZiAke0lERU5USVRZX01PREVTLmpvaW4oXCIgfCBcIil9IChlbnY6ICR7SURFTlRJVFlfRU5WfSlgLFxuICAgICAgeyBjb250ZXh0OiB7IGZpZWxkOiBcImdlbmllSWRlbnRpdHlcIiwgZW52VmFyOiBJREVOVElUWV9FTlYsIHJlY2VpdmVkOiByYXcgfSB9LFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIG1vZGU7XG59XG5cbi8qKiBIZWFkZXIgRGF0YWJyaWNrcyBBcHBzIGZvcndhcmQgdGhlIHNpZ25lZC1pbiB1c2VyJ3MgaWQgb24uICovXG5leHBvcnQgY29uc3QgVVNFUl9JRF9IRUFERVIgPSBcIngtZm9yd2FyZGVkLXVzZXJcIjtcblxuLyoqIEhlYWRlciBEYXRhYnJpY2tzIEFwcHMgZm9yd2FyZCB0aGUgc2lnbmVkLWluIHVzZXIncyBlbWFpbCBvbi4gKi9cbmV4cG9ydCBjb25zdCBVU0VSX0VNQUlMX0hFQURFUiA9IFwieC1mb3J3YXJkZWQtZW1haWxcIjtcblxuLyoqXG4gKiBUaGUgZm9yd2FyZGVkIHVzZXIgaWQgb24gYHJlcWAsIG9yIGB1bmRlZmluZWRgLiBVc2VkIHRvIGF0dHJpYnV0ZSBhIHR1cm4gdG9cbiAqIHRoZSByZWFsIGNhbGxlciBpbiBgc2VydmljZS1wcmluY2lwYWxgIG1vZGUsIHdoZXJlIHRoZSBEYXRhYnJpY2tzIGNsaWVudCBpc1xuICogdGhlIGFwcCBTUCBidXQgbWVtb3J5IC8gY2FjaGUgLyB0cmFjZXMgbXVzdCBzdGlsbCBrZXkgb2ZmIHRoZSB1c2VyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWVzdFVzZXJJZChyZXE6IGV4cHJlc3MuUmVxdWVzdCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBzdHJpbmcudHJpbVRvTnVsbChyZXEuaGVhZGVyKFVTRVJfSURfSEVBREVSKSkgPz8gdW5kZWZpbmVkO1xufVxuXG4vKiogVGhlIGZvcndhcmRlZCB1c2VyIGVtYWlsIG9uIGByZXFgLCBvciBgdW5kZWZpbmVkYC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1ZXN0VXNlckVtYWlsKHJlcTogZXhwcmVzcy5SZXF1ZXN0KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHN0cmluZy50cmltVG9OdWxsKHJlcS5oZWFkZXIoVVNFUl9FTUFJTF9IRUFERVIpKSA/PyB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogV2hldGhlciB0aGlzIHJlcXVlc3Qgc2hvdWxkIHJ1biBpdHMgRGF0YWJyaWNrcyBjYWxscyBhcyB0aGUgYXBwIHNlcnZpY2VcbiAqIHByaW5jaXBhbCByYXRoZXIgdGhhbiBPQk8uIGBcInNlcnZpY2UtcHJpbmNpcGFsXCJgIGFsd2F5cyBkb2VzOyBgXCJ1c2VyXCJgIG5ldmVyXG4gKiBkb2VzLiBUaGUgcmVxdWVzdCBpcyBhY2NlcHRlZCBmb3Igc3ltbWV0cnkgYW5kIHRvIGxlYXZlIHJvb20gZm9yXG4gKiByZXF1ZXN0LXNjb3BlZCBwb2xpY3kgbGF0ZXI7IGl0IGlzIHVudXNlZCB0b2RheS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVNlcnZpY2VQcmluY2lwYWwobW9kZTogTWFzdHJhSWRlbnRpdHlNb2RlLCBfcmVxPzogZXhwcmVzcy5SZXF1ZXN0KTogYm9vbGVhbiB7XG4gIHJldHVybiBtb2RlID09PSBcInNlcnZpY2UtcHJpbmNpcGFsXCI7XG59XG4iXX0=
|
package/lib/src/plugin.d.ts
CHANGED
|
@@ -103,6 +103,12 @@ export declare class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
103
103
|
* {@link buildAgentAndServer} and registered on the Mastra instance.
|
|
104
104
|
*/
|
|
105
105
|
private mcp;
|
|
106
|
+
/**
|
|
107
|
+
* Resolved {@link MastraIdentityMode}: the identity the chat path's Databricks
|
|
108
|
+
* calls run as. Read once at setup so an invalid `genieIdentity` fails the app
|
|
109
|
+
* boot rather than the first request, and so every request agrees.
|
|
110
|
+
*/
|
|
111
|
+
private identityMode;
|
|
106
112
|
/**
|
|
107
113
|
* Dedicated service-principal Lakebase pool backing Mastra memory /
|
|
108
114
|
* storage. Built once in {@link buildAgentAndServer} (outside any
|
|
@@ -112,6 +118,22 @@ export declare class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
112
118
|
*/
|
|
113
119
|
private servicePrincipalPool;
|
|
114
120
|
setup(): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* The plugin instance the chat path's Databricks calls should run through for
|
|
123
|
+
* `req`, honoring {@link identityMode}.
|
|
124
|
+
*
|
|
125
|
+
* In `"user"` mode (the default) this is `this.asUser(req)` - AppKit's own
|
|
126
|
+
* proxy that runs every call inside `runInUserContext`, so `getExecutionContext()`
|
|
127
|
+
* returns the caller's OBO client, exactly as before this option existed. In
|
|
128
|
+
* `"service-principal"` mode it is `this` unwrapped, so the same methods run in
|
|
129
|
+
* the ambient service context and `getExecutionContext()` returns the app
|
|
130
|
+
* service principal's client - the same "just don't enter `asUser`" pattern
|
|
131
|
+
* AppKit's own service-context calls use. One helper covers every workspace
|
|
132
|
+
* call the chat path makes (serving catalogue, Genie suggestions, `ask_genie`
|
|
133
|
+
* via the dispatched agent turn, statement fetch, feedback), so the identity
|
|
134
|
+
* decision lives in one place.
|
|
135
|
+
*/
|
|
136
|
+
private scopedSelf;
|
|
115
137
|
/**
|
|
116
138
|
* When the `lakebase` plugin is registered, auto-enable `storage`
|
|
117
139
|
* and `memory` unless the caller opted out explicitly (`false` or a
|