@agent-native/core 0.7.83 → 0.8.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/dist/action.js +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +8 -8
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +2 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +44 -18
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/types.d.ts +1 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +54 -11
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/workspacify.d.ts.map +1 -1
- package/dist/cli/workspacify.js +12 -9
- package/dist/cli/workspacify.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +22 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +254 -29
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-chat.d.ts +2 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +11 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/composer/ComposerPlusMenu.js +1 -1
- package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/client/composer/PromptComposer.js +1 -1
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.js +8 -8
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/types.d.ts +1 -1
- package/dist/client/composer/types.d.ts.map +1 -1
- package/dist/client/composer/types.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts +20 -0
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -0
- package/dist/client/{tools/EmbeddedTool.js → extensions/EmbeddedExtension.js} +41 -41
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -0
- package/dist/client/extensions/ExtensionEditor.d.ts +5 -0
- package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -0
- package/dist/client/extensions/ExtensionEditor.js +129 -0
- package/dist/client/extensions/ExtensionEditor.js.map +1 -0
- package/dist/client/{tools → extensions}/ExtensionSlot.d.ts +3 -3
- package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -0
- package/dist/client/{tools → extensions}/ExtensionSlot.js +14 -14
- package/dist/client/extensions/ExtensionSlot.js.map +1 -0
- package/dist/client/extensions/ExtensionViewer.d.ts +5 -0
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -0
- package/dist/client/{tools/ToolViewer.js → extensions/ExtensionViewer.js} +67 -65
- package/dist/client/extensions/ExtensionViewer.js.map +1 -0
- package/dist/client/extensions/ExtensionViewerPage.d.ts +2 -0
- package/dist/client/extensions/ExtensionViewerPage.d.ts.map +1 -0
- package/dist/client/{tools/ToolViewerPage.js → extensions/ExtensionViewerPage.js} +8 -8
- package/dist/client/extensions/ExtensionViewerPage.js.map +1 -0
- package/dist/client/extensions/ExtensionsListPage.d.ts +2 -0
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -0
- package/dist/client/extensions/ExtensionsListPage.js +67 -0
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -0
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts +2 -0
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -0
- package/dist/client/{tools/ToolsSidebarSection.js → extensions/ExtensionsSidebarSection.js} +58 -58
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -0
- package/dist/client/{tools/tool-order.d.ts → extensions/extension-order.d.ts} +2 -2
- package/dist/client/extensions/extension-order.d.ts.map +1 -0
- package/dist/client/{tools/tool-order.js → extensions/extension-order.js} +3 -3
- package/dist/client/extensions/extension-order.js.map +1 -0
- package/dist/client/{tools → extensions}/iframe-bridge.d.ts +11 -11
- package/dist/client/extensions/iframe-bridge.d.ts.map +1 -0
- package/dist/client/{tools → extensions}/iframe-bridge.js +24 -24
- package/dist/client/extensions/iframe-bridge.js.map +1 -0
- package/dist/client/extensions/index.d.ts +14 -0
- package/dist/client/extensions/index.d.ts.map +1 -0
- package/dist/client/extensions/index.js +19 -0
- package/dist/client/extensions/index.js.map +1 -0
- package/dist/client/sse-event-processor.d.ts +2 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +87 -6
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/extensions/actions.d.ts +3 -0
- package/dist/extensions/actions.d.ts.map +1 -0
- package/dist/{tools → extensions}/actions.js +54 -51
- package/dist/extensions/actions.js.map +1 -0
- package/dist/{tools → extensions}/fetch-tool.d.ts +4 -0
- package/dist/extensions/fetch-tool.d.ts.map +1 -0
- package/dist/{tools → extensions}/fetch-tool.js +12 -7
- package/dist/extensions/fetch-tool.js.map +1 -0
- package/dist/extensions/html-shell.d.ts +56 -0
- package/dist/extensions/html-shell.d.ts.map +1 -0
- package/dist/{tools → extensions}/html-shell.js +101 -83
- package/dist/extensions/html-shell.js.map +1 -0
- package/dist/{tools → extensions}/proxy-security.d.ts +2 -2
- package/dist/extensions/proxy-security.d.ts.map +1 -0
- package/dist/{tools → extensions}/proxy-security.js +3 -3
- package/dist/extensions/proxy-security.js.map +1 -0
- package/dist/extensions/routes.d.ts +2 -0
- package/dist/extensions/routes.d.ts.map +1 -0
- package/dist/{tools → extensions}/routes.js +73 -69
- package/dist/extensions/routes.js.map +1 -0
- package/dist/{tools → extensions}/schema.d.ts +44 -38
- package/dist/extensions/schema.d.ts.map +1 -0
- package/dist/{tools → extensions}/schema.js +41 -34
- package/dist/extensions/schema.js.map +1 -0
- package/dist/extensions/slots/routes.d.ts +15 -0
- package/dist/extensions/slots/routes.d.ts.map +1 -0
- package/dist/{tools → extensions}/slots/routes.js +26 -26
- package/dist/extensions/slots/routes.js.map +1 -0
- package/dist/{tools → extensions}/slots/schema.d.ts +24 -21
- package/dist/extensions/slots/schema.d.ts.map +1 -0
- package/dist/extensions/slots/schema.js +79 -0
- package/dist/extensions/slots/schema.js.map +1 -0
- package/dist/extensions/slots/store.d.ts +66 -0
- package/dist/extensions/slots/store.d.ts.map +1 -0
- package/dist/extensions/slots/store.js +238 -0
- package/dist/extensions/slots/store.js.map +1 -0
- package/dist/extensions/store.d.ts +40 -0
- package/dist/extensions/store.d.ts.map +1 -0
- package/dist/{tools → extensions}/store.js +59 -54
- package/dist/extensions/store.js.map +1 -0
- package/dist/extensions/theme.d.ts.map +1 -0
- package/dist/extensions/theme.js.map +1 -0
- package/dist/{tools → extensions}/url-safety.d.ts +5 -3
- package/dist/extensions/url-safety.d.ts.map +1 -0
- package/dist/{tools → extensions}/url-safety.js +11 -4
- package/dist/extensions/url-safety.js.map +1 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +12 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +15 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +64 -10
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/csrf.d.ts +3 -2
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/csrf.js +3 -2
- package/dist/server/csrf.js.map +1 -1
- package/dist/shared/workspace-app-id.d.ts +1 -1
- package/dist/shared/workspace-app-id.d.ts.map +1 -1
- package/dist/shared/workspace-app-id.js +5 -1
- package/dist/shared/workspace-app-id.js.map +1 -1
- package/dist/templates/workspace-root/README.md +5 -4
- package/dist/usage/store.d.ts +1 -1
- package/dist/usage/store.d.ts.map +1 -1
- package/dist/usage/store.js +1 -1
- package/dist/usage/store.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +10 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/actions.md +10 -10
- package/docs/content/extensions.md +230 -0
- package/docs/content/key-concepts.md +2 -2
- package/docs/content/server.md +13 -13
- package/docs/content/sharing.md +2 -2
- package/docs/content/template-dispatch.md +5 -0
- package/docs/content/what-is-agent-native.md +1 -1
- package/package.json +22 -17
- package/src/templates/workspace-root/README.md +5 -4
- package/dist/client/tools/EmbeddedTool.d.ts +0 -20
- package/dist/client/tools/EmbeddedTool.d.ts.map +0 -1
- package/dist/client/tools/EmbeddedTool.js.map +0 -1
- package/dist/client/tools/ExtensionSlot.d.ts.map +0 -1
- package/dist/client/tools/ExtensionSlot.js.map +0 -1
- package/dist/client/tools/ToolEditor.d.ts +0 -5
- package/dist/client/tools/ToolEditor.d.ts.map +0 -1
- package/dist/client/tools/ToolEditor.js +0 -129
- package/dist/client/tools/ToolEditor.js.map +0 -1
- package/dist/client/tools/ToolViewer.d.ts +0 -5
- package/dist/client/tools/ToolViewer.d.ts.map +0 -1
- package/dist/client/tools/ToolViewer.js.map +0 -1
- package/dist/client/tools/ToolViewerPage.d.ts +0 -2
- package/dist/client/tools/ToolViewerPage.d.ts.map +0 -1
- package/dist/client/tools/ToolViewerPage.js.map +0 -1
- package/dist/client/tools/ToolsListPage.d.ts +0 -2
- package/dist/client/tools/ToolsListPage.d.ts.map +0 -1
- package/dist/client/tools/ToolsListPage.js +0 -67
- package/dist/client/tools/ToolsListPage.js.map +0 -1
- package/dist/client/tools/ToolsSidebarSection.d.ts +0 -2
- package/dist/client/tools/ToolsSidebarSection.d.ts.map +0 -1
- package/dist/client/tools/ToolsSidebarSection.js.map +0 -1
- package/dist/client/tools/iframe-bridge.d.ts.map +0 -1
- package/dist/client/tools/iframe-bridge.js.map +0 -1
- package/dist/client/tools/index.d.ts +0 -8
- package/dist/client/tools/index.d.ts.map +0 -1
- package/dist/client/tools/index.js +0 -8
- package/dist/client/tools/index.js.map +0 -1
- package/dist/client/tools/tool-order.d.ts.map +0 -1
- package/dist/client/tools/tool-order.js.map +0 -1
- package/dist/tools/actions.d.ts +0 -3
- package/dist/tools/actions.d.ts.map +0 -1
- package/dist/tools/actions.js.map +0 -1
- package/dist/tools/fetch-tool.d.ts.map +0 -1
- package/dist/tools/fetch-tool.js.map +0 -1
- package/dist/tools/html-shell.d.ts +0 -45
- package/dist/tools/html-shell.d.ts.map +0 -1
- package/dist/tools/html-shell.js.map +0 -1
- package/dist/tools/proxy-security.d.ts.map +0 -1
- package/dist/tools/proxy-security.js.map +0 -1
- package/dist/tools/routes.d.ts +0 -2
- package/dist/tools/routes.d.ts.map +0 -1
- package/dist/tools/routes.js.map +0 -1
- package/dist/tools/schema.d.ts.map +0 -1
- package/dist/tools/schema.js.map +0 -1
- package/dist/tools/slots/routes.d.ts +0 -15
- package/dist/tools/slots/routes.d.ts.map +0 -1
- package/dist/tools/slots/routes.js.map +0 -1
- package/dist/tools/slots/schema.d.ts.map +0 -1
- package/dist/tools/slots/schema.js +0 -76
- package/dist/tools/slots/schema.js.map +0 -1
- package/dist/tools/slots/store.d.ts +0 -66
- package/dist/tools/slots/store.d.ts.map +0 -1
- package/dist/tools/slots/store.js +0 -227
- package/dist/tools/slots/store.js.map +0 -1
- package/dist/tools/store.d.ts +0 -40
- package/dist/tools/store.d.ts.map +0 -1
- package/dist/tools/store.js.map +0 -1
- package/dist/tools/theme.d.ts.map +0 -1
- package/dist/tools/theme.js.map +0 -1
- package/dist/tools/url-safety.d.ts.map +0 -1
- package/dist/tools/url-safety.js.map +0 -1
- package/docs/content/tools.md +0 -205
- /package/dist/{tools → extensions}/theme.d.ts +0 -0
- /package/dist/{tools → extensions}/theme.js +0 -0
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Drizzle schema for the framework
|
|
2
|
+
* Drizzle schema for the framework extensions system.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* call external APIs via a server-side proxy that resolves `${keys.NAME}`
|
|
6
|
-
* secret references.
|
|
7
|
-
* shareable with org/others).
|
|
4
|
+
* Extensions are mini Alpine.js apps that run inside sandboxed iframes. They
|
|
5
|
+
* can call external APIs via a server-side proxy that resolves `${keys.NAME}`
|
|
6
|
+
* secret references. Extensions use the standard sharing model (private by
|
|
7
|
+
* default, shareable with org/others).
|
|
8
8
|
*
|
|
9
9
|
* The tables are auto-created at server boot via `ensureTable()` in store.ts,
|
|
10
10
|
* following the same pattern as `app_secrets`.
|
|
11
|
+
*
|
|
12
|
+
* NOTE: physical SQL table/column names stay as `extensions`, `tool_data`,
|
|
13
|
+
* `tool_shares`, `tool_consents`, `tool_id`, etc. — additive-only schema
|
|
14
|
+
* policy means we never rename DB-level identifiers. The JS/TS surface is
|
|
15
|
+
* renamed to `extensions`/`extension*`; the DB-side names stay so existing
|
|
16
|
+
* deployed rows remain readable.
|
|
11
17
|
*/
|
|
12
|
-
export declare const
|
|
13
|
-
name: "
|
|
18
|
+
export declare const extensions: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
19
|
+
name: "extensions";
|
|
14
20
|
schema: undefined;
|
|
15
21
|
columns: {
|
|
16
22
|
ownerEmail: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
17
23
|
name: "owner_email";
|
|
18
|
-
tableName: "
|
|
24
|
+
tableName: "extensions";
|
|
19
25
|
dataType: "string";
|
|
20
26
|
columnType: "SQLiteText";
|
|
21
27
|
data: string;
|
|
@@ -34,7 +40,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
34
40
|
}>;
|
|
35
41
|
orgId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
36
42
|
name: "org_id";
|
|
37
|
-
tableName: "
|
|
43
|
+
tableName: "extensions";
|
|
38
44
|
dataType: "string";
|
|
39
45
|
columnType: "SQLiteText";
|
|
40
46
|
data: string;
|
|
@@ -53,7 +59,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
53
59
|
}>;
|
|
54
60
|
visibility: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
55
61
|
name: "visibility";
|
|
56
|
-
tableName: "
|
|
62
|
+
tableName: "extensions";
|
|
57
63
|
dataType: "string";
|
|
58
64
|
columnType: "SQLiteText";
|
|
59
65
|
data: "org" | "private" | "public";
|
|
@@ -72,7 +78,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
72
78
|
}>;
|
|
73
79
|
id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
74
80
|
name: "id";
|
|
75
|
-
tableName: "
|
|
81
|
+
tableName: "extensions";
|
|
76
82
|
dataType: "string";
|
|
77
83
|
columnType: "SQLiteText";
|
|
78
84
|
data: string;
|
|
@@ -91,7 +97,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
91
97
|
}>;
|
|
92
98
|
name: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
93
99
|
name: "name";
|
|
94
|
-
tableName: "
|
|
100
|
+
tableName: "extensions";
|
|
95
101
|
dataType: "string";
|
|
96
102
|
columnType: "SQLiteText";
|
|
97
103
|
data: string;
|
|
@@ -110,7 +116,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
110
116
|
}>;
|
|
111
117
|
description: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
112
118
|
name: "description";
|
|
113
|
-
tableName: "
|
|
119
|
+
tableName: "extensions";
|
|
114
120
|
dataType: "string";
|
|
115
121
|
columnType: "SQLiteText";
|
|
116
122
|
data: string;
|
|
@@ -129,7 +135,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
129
135
|
}>;
|
|
130
136
|
content: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
131
137
|
name: "content";
|
|
132
|
-
tableName: "
|
|
138
|
+
tableName: "extensions";
|
|
133
139
|
dataType: "string";
|
|
134
140
|
columnType: "SQLiteText";
|
|
135
141
|
data: string;
|
|
@@ -148,7 +154,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
148
154
|
}>;
|
|
149
155
|
icon: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
150
156
|
name: "icon";
|
|
151
|
-
tableName: "
|
|
157
|
+
tableName: "extensions";
|
|
152
158
|
dataType: "string";
|
|
153
159
|
columnType: "SQLiteText";
|
|
154
160
|
data: string;
|
|
@@ -167,7 +173,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
167
173
|
}>;
|
|
168
174
|
createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
169
175
|
name: "created_at";
|
|
170
|
-
tableName: "
|
|
176
|
+
tableName: "extensions";
|
|
171
177
|
dataType: "string";
|
|
172
178
|
columnType: "SQLiteText";
|
|
173
179
|
data: string;
|
|
@@ -186,7 +192,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
186
192
|
}>;
|
|
187
193
|
updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
188
194
|
name: "updated_at";
|
|
189
|
-
tableName: "
|
|
195
|
+
tableName: "extensions";
|
|
190
196
|
dataType: "string";
|
|
191
197
|
columnType: "SQLiteText";
|
|
192
198
|
data: string;
|
|
@@ -206,7 +212,7 @@ export declare const tools: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
|
|
|
206
212
|
};
|
|
207
213
|
dialect: "sqlite";
|
|
208
214
|
}>;
|
|
209
|
-
export declare const
|
|
215
|
+
export declare const extensionShares: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
210
216
|
name: string;
|
|
211
217
|
schema: undefined;
|
|
212
218
|
columns: {
|
|
@@ -346,11 +352,11 @@ export declare const toolShares: import("drizzle-orm/sqlite-core").SQLiteTableWi
|
|
|
346
352
|
};
|
|
347
353
|
dialect: "sqlite";
|
|
348
354
|
}>;
|
|
349
|
-
export declare const
|
|
350
|
-
export declare const
|
|
351
|
-
export declare const
|
|
352
|
-
export declare const
|
|
353
|
-
export declare const
|
|
355
|
+
export declare const EXTENSIONS_CREATE_SQL = "CREATE TABLE IF NOT EXISTS extensions (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n content TEXT NOT NULL DEFAULT '',\n icon TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n)";
|
|
356
|
+
export declare const EXTENSIONS_CREATE_SQL_PG = "CREATE TABLE IF NOT EXISTS extensions (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n content TEXT NOT NULL DEFAULT '',\n icon TEXT,\n created_at TEXT NOT NULL DEFAULT now(),\n updated_at TEXT NOT NULL DEFAULT now(),\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n)";
|
|
357
|
+
export declare const EXTENSION_SHARES_CREATE_SQL = "CREATE TABLE IF NOT EXISTS tool_shares (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n principal_type TEXT NOT NULL,\n principal_id TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'viewer',\n created_by TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n)";
|
|
358
|
+
export declare const EXTENSION_SHARES_CREATE_SQL_PG = "CREATE TABLE IF NOT EXISTS tool_shares (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n principal_type TEXT NOT NULL,\n principal_id TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'viewer',\n created_by TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT now()\n)";
|
|
359
|
+
export declare const extensionData: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
354
360
|
name: "tool_data";
|
|
355
361
|
schema: undefined;
|
|
356
362
|
columns: {
|
|
@@ -373,7 +379,7 @@ export declare const toolData: import("drizzle-orm/sqlite-core").SQLiteTableWith
|
|
|
373
379
|
}, {}, {
|
|
374
380
|
length: number;
|
|
375
381
|
}>;
|
|
376
|
-
|
|
382
|
+
extensionId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
377
383
|
name: "tool_id";
|
|
378
384
|
tableName: "tool_data";
|
|
379
385
|
dataType: "string";
|
|
@@ -566,16 +572,16 @@ export declare const toolData: import("drizzle-orm/sqlite-core").SQLiteTableWith
|
|
|
566
572
|
};
|
|
567
573
|
dialect: "sqlite";
|
|
568
574
|
}>;
|
|
569
|
-
export declare const
|
|
570
|
-
export declare const
|
|
571
|
-
export declare const
|
|
572
|
-
export declare const
|
|
573
|
-
export declare const
|
|
574
|
-
export declare const
|
|
575
|
-
export declare const
|
|
576
|
-
export declare const
|
|
577
|
-
export declare const
|
|
578
|
-
export declare const
|
|
575
|
+
export declare const EXTENSION_DATA_CREATE_SQL = "CREATE TABLE IF NOT EXISTS tool_data (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n collection TEXT NOT NULL,\n item_id TEXT,\n data TEXT NOT NULL,\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n scope TEXT NOT NULL DEFAULT 'user',\n org_id TEXT,\n scope_key TEXT NOT NULL DEFAULT 'local@localhost',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n)";
|
|
576
|
+
export declare const EXTENSION_DATA_CREATE_SQL_PG = "CREATE TABLE IF NOT EXISTS tool_data (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n collection TEXT NOT NULL,\n item_id TEXT,\n data TEXT NOT NULL,\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n scope TEXT NOT NULL DEFAULT 'user',\n org_id TEXT,\n scope_key TEXT NOT NULL DEFAULT 'local@localhost',\n created_at TEXT NOT NULL DEFAULT now(),\n updated_at TEXT NOT NULL DEFAULT now()\n)";
|
|
577
|
+
export declare const EXTENSION_DATA_ITEM_INDEX_SQL = "CREATE UNIQUE INDEX IF NOT EXISTS tool_data_scoped_item_idx\n ON tool_data (tool_id, collection, scope_key, item_id)";
|
|
578
|
+
export declare const EXTENSION_DATA_ITEM_INDEX_SQL_PG = "CREATE UNIQUE INDEX IF NOT EXISTS tool_data_scoped_item_idx\n ON tool_data (tool_id, collection, scope_key, item_id)";
|
|
579
|
+
export declare const EXTENSION_DATA_DROP_OLD_INDEX_SQL = "DROP INDEX IF EXISTS tool_data_scope_item_idx";
|
|
580
|
+
export declare const EXTENSION_DATA_DROP_OLD_INDEX_SQL_PG = "DROP INDEX IF EXISTS tool_data_scope_item_idx";
|
|
581
|
+
export declare const EXTENSIONS_OWNER_INDEX_SQL = "CREATE INDEX IF NOT EXISTS tools_owner_idx ON tools (owner_email)";
|
|
582
|
+
export declare const EXTENSIONS_ORG_INDEX_SQL = "CREATE INDEX IF NOT EXISTS tools_org_idx ON tools (org_id)";
|
|
583
|
+
export declare const EXTENSION_SHARES_RESOURCE_INDEX_SQL = "CREATE INDEX IF NOT EXISTS tool_shares_resource_idx ON tool_shares (resource_id)";
|
|
584
|
+
export declare const extensionConsents: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
579
585
|
name: "tool_consents";
|
|
580
586
|
schema: undefined;
|
|
581
587
|
columns: {
|
|
@@ -598,7 +604,7 @@ export declare const toolConsents: import("drizzle-orm/sqlite-core").SQLiteTable
|
|
|
598
604
|
}, {}, {
|
|
599
605
|
length: number;
|
|
600
606
|
}>;
|
|
601
|
-
|
|
607
|
+
extensionId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
602
608
|
name: "tool_id";
|
|
603
609
|
tableName: "tool_consents";
|
|
604
610
|
dataType: "string";
|
|
@@ -658,7 +664,7 @@ export declare const toolConsents: import("drizzle-orm/sqlite-core").SQLiteTable
|
|
|
658
664
|
};
|
|
659
665
|
dialect: "sqlite";
|
|
660
666
|
}>;
|
|
661
|
-
export declare const
|
|
662
|
-
export declare const
|
|
663
|
-
export declare const
|
|
667
|
+
export declare const EXTENSION_CONSENTS_CREATE_SQL = "CREATE TABLE IF NOT EXISTS tool_consents (\n viewer_email TEXT NOT NULL,\n tool_id TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n granted_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (viewer_email, tool_id, content_hash)\n)";
|
|
668
|
+
export declare const EXTENSION_CONSENTS_CREATE_SQL_PG = "CREATE TABLE IF NOT EXISTS tool_consents (\n viewer_email TEXT NOT NULL,\n tool_id TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n granted_at TEXT NOT NULL DEFAULT now(),\n PRIMARY KEY (viewer_email, tool_id, content_hash)\n)";
|
|
669
|
+
export declare const EXTENSION_CONSENTS_VIEWER_INDEX_SQL = "CREATE INDEX IF NOT EXISTS tool_consents_viewer_idx ON tool_consents (viewer_email, tool_id)";
|
|
664
670
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/extensions/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASrB,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAmC,CAAC;AAEhE,eAAO,MAAM,qBAAqB,8ZAWhC,CAAC;AAEH,eAAO,MAAM,wBAAwB,sYAWnC,CAAC;AAEH,eAAO,MAAM,2BAA2B,iSAQtC,CAAC;AAEH,eAAO,MAAM,8BAA8B,qRAQzC,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYxB,CAAC;AAEH,eAAO,MAAM,yBAAyB,ubAYpC,CAAC;AAEH,eAAO,MAAM,4BAA4B,+ZAYvC,CAAC;AAEH,eAAO,MAAM,6BAA6B,0HACe,CAAC;AAE1D,eAAO,MAAM,gCAAgC,0HACY,CAAC;AAE1D,eAAO,MAAM,iCAAiC,kDAAkD,CAAC;AACjG,eAAO,MAAM,oCAAoC,kDAAkD,CAAC;AAEpG,eAAO,MAAM,0BAA0B,sEAAsE,CAAC;AAC9G,eAAO,MAAM,wBAAwB,+DAA+D,CAAC;AACrG,eAAO,MAAM,mCAAmC,qFAAqF,CAAC;AActI,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK5B,CAAC;AAEH,eAAO,MAAM,6BAA6B,sPAMxC,CAAC;AAEH,eAAO,MAAM,gCAAgC,0OAM3C,CAAC;AAEH,eAAO,MAAM,mCAAmC,iGAAiG,CAAC"}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Drizzle schema for the framework
|
|
2
|
+
* Drizzle schema for the framework extensions system.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* call external APIs via a server-side proxy that resolves `${keys.NAME}`
|
|
6
|
-
* secret references.
|
|
7
|
-
* shareable with org/others).
|
|
4
|
+
* Extensions are mini Alpine.js apps that run inside sandboxed iframes. They
|
|
5
|
+
* can call external APIs via a server-side proxy that resolves `${keys.NAME}`
|
|
6
|
+
* secret references. Extensions use the standard sharing model (private by
|
|
7
|
+
* default, shareable with org/others).
|
|
8
8
|
*
|
|
9
9
|
* The tables are auto-created at server boot via `ensureTable()` in store.ts,
|
|
10
10
|
* following the same pattern as `app_secrets`.
|
|
11
|
+
*
|
|
12
|
+
* NOTE: physical SQL table/column names stay as `extensions`, `tool_data`,
|
|
13
|
+
* `tool_shares`, `tool_consents`, `tool_id`, etc. — additive-only schema
|
|
14
|
+
* policy means we never rename DB-level identifiers. The JS/TS surface is
|
|
15
|
+
* renamed to `extensions`/`extension*`; the DB-side names stay so existing
|
|
16
|
+
* deployed rows remain readable.
|
|
11
17
|
*/
|
|
12
18
|
import { table, text, now } from "../db/schema.js";
|
|
13
19
|
import { ownableColumns, createSharesTable } from "../sharing/schema.js";
|
|
14
|
-
export const
|
|
20
|
+
export const extensions = table("extensions", {
|
|
15
21
|
id: text("id").primaryKey(),
|
|
16
22
|
name: text("name").notNull(),
|
|
17
23
|
description: text("description").notNull().default(""),
|
|
@@ -21,8 +27,8 @@ export const tools = table("tools", {
|
|
|
21
27
|
updatedAt: text("updated_at").notNull().default(now()),
|
|
22
28
|
...ownableColumns(),
|
|
23
29
|
});
|
|
24
|
-
export const
|
|
25
|
-
export const
|
|
30
|
+
export const extensionShares = createSharesTable("tool_shares");
|
|
31
|
+
export const EXTENSIONS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS extensions (
|
|
26
32
|
id TEXT PRIMARY KEY,
|
|
27
33
|
name TEXT NOT NULL,
|
|
28
34
|
description TEXT NOT NULL DEFAULT '',
|
|
@@ -34,7 +40,7 @@ export const TOOLS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tools (
|
|
|
34
40
|
org_id TEXT,
|
|
35
41
|
visibility TEXT NOT NULL DEFAULT 'private'
|
|
36
42
|
)`;
|
|
37
|
-
export const
|
|
43
|
+
export const EXTENSIONS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS extensions (
|
|
38
44
|
id TEXT PRIMARY KEY,
|
|
39
45
|
name TEXT NOT NULL,
|
|
40
46
|
description TEXT NOT NULL DEFAULT '',
|
|
@@ -46,7 +52,7 @@ export const TOOLS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tools (
|
|
|
46
52
|
org_id TEXT,
|
|
47
53
|
visibility TEXT NOT NULL DEFAULT 'private'
|
|
48
54
|
)`;
|
|
49
|
-
export const
|
|
55
|
+
export const EXTENSION_SHARES_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_shares (
|
|
50
56
|
id TEXT PRIMARY KEY,
|
|
51
57
|
resource_id TEXT NOT NULL,
|
|
52
58
|
principal_type TEXT NOT NULL,
|
|
@@ -55,7 +61,7 @@ export const TOOL_SHARES_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_shares (
|
|
|
55
61
|
created_by TEXT NOT NULL,
|
|
56
62
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
57
63
|
)`;
|
|
58
|
-
export const
|
|
64
|
+
export const EXTENSION_SHARES_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_shares (
|
|
59
65
|
id TEXT PRIMARY KEY,
|
|
60
66
|
resource_id TEXT NOT NULL,
|
|
61
67
|
principal_type TEXT NOT NULL,
|
|
@@ -64,9 +70,9 @@ export const TOOL_SHARES_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_shares
|
|
|
64
70
|
created_by TEXT NOT NULL,
|
|
65
71
|
created_at TEXT NOT NULL DEFAULT now()
|
|
66
72
|
)`;
|
|
67
|
-
export const
|
|
73
|
+
export const extensionData = table("tool_data", {
|
|
68
74
|
id: text("id").primaryKey(),
|
|
69
|
-
|
|
75
|
+
extensionId: text("tool_id").notNull(),
|
|
70
76
|
collection: text("collection").notNull(),
|
|
71
77
|
itemId: text("item_id"),
|
|
72
78
|
data: text("data").notNull(),
|
|
@@ -77,7 +83,7 @@ export const toolData = table("tool_data", {
|
|
|
77
83
|
createdAt: text("created_at").notNull().default(now()),
|
|
78
84
|
updatedAt: text("updated_at").notNull().default(now()),
|
|
79
85
|
});
|
|
80
|
-
export const
|
|
86
|
+
export const EXTENSION_DATA_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_data (
|
|
81
87
|
id TEXT PRIMARY KEY,
|
|
82
88
|
tool_id TEXT NOT NULL,
|
|
83
89
|
collection TEXT NOT NULL,
|
|
@@ -90,7 +96,7 @@ export const TOOL_DATA_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_data (
|
|
|
90
96
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
91
97
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
92
98
|
)`;
|
|
93
|
-
export const
|
|
99
|
+
export const EXTENSION_DATA_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_data (
|
|
94
100
|
id TEXT PRIMARY KEY,
|
|
95
101
|
tool_id TEXT NOT NULL,
|
|
96
102
|
collection TEXT NOT NULL,
|
|
@@ -103,44 +109,45 @@ export const TOOL_DATA_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_data (
|
|
|
103
109
|
created_at TEXT NOT NULL DEFAULT now(),
|
|
104
110
|
updated_at TEXT NOT NULL DEFAULT now()
|
|
105
111
|
)`;
|
|
106
|
-
export const
|
|
112
|
+
export const EXTENSION_DATA_ITEM_INDEX_SQL = `CREATE UNIQUE INDEX IF NOT EXISTS tool_data_scoped_item_idx
|
|
107
113
|
ON tool_data (tool_id, collection, scope_key, item_id)`;
|
|
108
|
-
export const
|
|
114
|
+
export const EXTENSION_DATA_ITEM_INDEX_SQL_PG = `CREATE UNIQUE INDEX IF NOT EXISTS tool_data_scoped_item_idx
|
|
109
115
|
ON tool_data (tool_id, collection, scope_key, item_id)`;
|
|
110
|
-
export const
|
|
111
|
-
export const
|
|
112
|
-
export const
|
|
113
|
-
export const
|
|
114
|
-
export const
|
|
116
|
+
export const EXTENSION_DATA_DROP_OLD_INDEX_SQL = `DROP INDEX IF EXISTS tool_data_scope_item_idx`;
|
|
117
|
+
export const EXTENSION_DATA_DROP_OLD_INDEX_SQL_PG = `DROP INDEX IF EXISTS tool_data_scope_item_idx`;
|
|
118
|
+
export const EXTENSIONS_OWNER_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_owner_idx ON tools (owner_email)`;
|
|
119
|
+
export const EXTENSIONS_ORG_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_org_idx ON tools (org_id)`;
|
|
120
|
+
export const EXTENSION_SHARES_RESOURCE_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_shares_resource_idx ON tool_shares (resource_id)`;
|
|
115
121
|
// ---------------------------------------------------------------------------
|
|
116
|
-
//
|
|
122
|
+
// extension_consents — vestigial, kept for additive-schema compliance
|
|
117
123
|
// ---------------------------------------------------------------------------
|
|
118
124
|
//
|
|
119
|
-
// Originally added for an audit-C1 per-(viewer,
|
|
120
|
-
// gate that prompted viewers to "Run anyway" before non-author
|
|
121
|
-
// execute. We removed the runtime gate after settling on
|
|
122
|
-
// (
|
|
123
|
-
// are sufficient). The table is kept here so
|
|
124
|
-
// migration stay healthy — additive-only schema
|
|
125
|
-
|
|
125
|
+
// Originally added for an audit-C1 per-(viewer, extension, content_hash)
|
|
126
|
+
// consent gate that prompted viewers to "Run anyway" before non-author
|
|
127
|
+
// extensions could execute. We removed the runtime gate after settling on
|
|
128
|
+
// intra-org trust (extensions are shared between trusted teammates; the
|
|
129
|
+
// org-level access controls are sufficient). The table is kept here so
|
|
130
|
+
// deploys that already ran the migration stay healthy — additive-only schema
|
|
131
|
+
// policy means we never drop. Physical name stays `tool_consents`.
|
|
132
|
+
export const extensionConsents = table("tool_consents", {
|
|
126
133
|
viewerEmail: text("viewer_email").notNull(),
|
|
127
|
-
|
|
134
|
+
extensionId: text("tool_id").notNull(),
|
|
128
135
|
contentHash: text("content_hash").notNull(),
|
|
129
136
|
grantedAt: text("granted_at").notNull().default(now()),
|
|
130
137
|
});
|
|
131
|
-
export const
|
|
138
|
+
export const EXTENSION_CONSENTS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_consents (
|
|
132
139
|
viewer_email TEXT NOT NULL,
|
|
133
140
|
tool_id TEXT NOT NULL,
|
|
134
141
|
content_hash TEXT NOT NULL,
|
|
135
142
|
granted_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
136
143
|
PRIMARY KEY (viewer_email, tool_id, content_hash)
|
|
137
144
|
)`;
|
|
138
|
-
export const
|
|
145
|
+
export const EXTENSION_CONSENTS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_consents (
|
|
139
146
|
viewer_email TEXT NOT NULL,
|
|
140
147
|
tool_id TEXT NOT NULL,
|
|
141
148
|
content_hash TEXT NOT NULL,
|
|
142
149
|
granted_at TEXT NOT NULL DEFAULT now(),
|
|
143
150
|
PRIMARY KEY (viewer_email, tool_id, content_hash)
|
|
144
151
|
)`;
|
|
145
|
-
export const
|
|
152
|
+
export const EXTENSION_CONSENTS_VIEWER_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_consents_viewer_idx ON tool_consents (viewer_email, tool_id)`;
|
|
146
153
|
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/extensions/schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Drizzle schema for the framework extensions system.\n *\n * Extensions are mini Alpine.js apps that run inside sandboxed iframes. They\n * can call external APIs via a server-side proxy that resolves `${keys.NAME}`\n * secret references. Extensions use the standard sharing model (private by\n * default, shareable with org/others).\n *\n * The tables are auto-created at server boot via `ensureTable()` in store.ts,\n * following the same pattern as `app_secrets`.\n *\n * NOTE: physical SQL table/column names stay as `extensions`, `tool_data`,\n * `tool_shares`, `tool_consents`, `tool_id`, etc. — additive-only schema\n * policy means we never rename DB-level identifiers. The JS/TS surface is\n * renamed to `extensions`/`extension*`; the DB-side names stay so existing\n * deployed rows remain readable.\n */\n\nimport { table, text, now } from \"../db/schema.js\";\nimport { ownableColumns, createSharesTable } from \"../sharing/schema.js\";\n\nexport const extensions = table(\"extensions\", {\n id: text(\"id\").primaryKey(),\n name: text(\"name\").notNull(),\n description: text(\"description\").notNull().default(\"\"),\n content: text(\"content\").notNull().default(\"\"),\n icon: text(\"icon\"),\n createdAt: text(\"created_at\").notNull().default(now()),\n updatedAt: text(\"updated_at\").notNull().default(now()),\n ...ownableColumns(),\n});\n\nexport const extensionShares = createSharesTable(\"tool_shares\");\n\nexport const EXTENSIONS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS extensions (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n content TEXT NOT NULL DEFAULT '',\n icon TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n)`;\n\nexport const EXTENSIONS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS extensions (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n content TEXT NOT NULL DEFAULT '',\n icon TEXT,\n created_at TEXT NOT NULL DEFAULT now(),\n updated_at TEXT NOT NULL DEFAULT now(),\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n)`;\n\nexport const EXTENSION_SHARES_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_shares (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n principal_type TEXT NOT NULL,\n principal_id TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'viewer',\n created_by TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n)`;\n\nexport const EXTENSION_SHARES_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_shares (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n principal_type TEXT NOT NULL,\n principal_id TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'viewer',\n created_by TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT now()\n)`;\n\nexport const extensionData = table(\"tool_data\", {\n id: text(\"id\").primaryKey(),\n extensionId: text(\"tool_id\").notNull(),\n collection: text(\"collection\").notNull(),\n itemId: text(\"item_id\"),\n data: text(\"data\").notNull(),\n ownerEmail: text(\"owner_email\").notNull().default(\"local@localhost\"),\n scope: text(\"scope\").notNull().default(\"user\"),\n orgId: text(\"org_id\"),\n scopeKey: text(\"scope_key\").notNull().default(\"local@localhost\"),\n createdAt: text(\"created_at\").notNull().default(now()),\n updatedAt: text(\"updated_at\").notNull().default(now()),\n});\n\nexport const EXTENSION_DATA_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_data (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n collection TEXT NOT NULL,\n item_id TEXT,\n data TEXT NOT NULL,\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n scope TEXT NOT NULL DEFAULT 'user',\n org_id TEXT,\n scope_key TEXT NOT NULL DEFAULT 'local@localhost',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n)`;\n\nexport const EXTENSION_DATA_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_data (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n collection TEXT NOT NULL,\n item_id TEXT,\n data TEXT NOT NULL,\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n scope TEXT NOT NULL DEFAULT 'user',\n org_id TEXT,\n scope_key TEXT NOT NULL DEFAULT 'local@localhost',\n created_at TEXT NOT NULL DEFAULT now(),\n updated_at TEXT NOT NULL DEFAULT now()\n)`;\n\nexport const EXTENSION_DATA_ITEM_INDEX_SQL = `CREATE UNIQUE INDEX IF NOT EXISTS tool_data_scoped_item_idx\n ON tool_data (tool_id, collection, scope_key, item_id)`;\n\nexport const EXTENSION_DATA_ITEM_INDEX_SQL_PG = `CREATE UNIQUE INDEX IF NOT EXISTS tool_data_scoped_item_idx\n ON tool_data (tool_id, collection, scope_key, item_id)`;\n\nexport const EXTENSION_DATA_DROP_OLD_INDEX_SQL = `DROP INDEX IF EXISTS tool_data_scope_item_idx`;\nexport const EXTENSION_DATA_DROP_OLD_INDEX_SQL_PG = `DROP INDEX IF EXISTS tool_data_scope_item_idx`;\n\nexport const EXTENSIONS_OWNER_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_owner_idx ON tools (owner_email)`;\nexport const EXTENSIONS_ORG_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_org_idx ON tools (org_id)`;\nexport const EXTENSION_SHARES_RESOURCE_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_shares_resource_idx ON tool_shares (resource_id)`;\n\n// ---------------------------------------------------------------------------\n// extension_consents — vestigial, kept for additive-schema compliance\n// ---------------------------------------------------------------------------\n//\n// Originally added for an audit-C1 per-(viewer, extension, content_hash)\n// consent gate that prompted viewers to \"Run anyway\" before non-author\n// extensions could execute. We removed the runtime gate after settling on\n// intra-org trust (extensions are shared between trusted teammates; the\n// org-level access controls are sufficient). The table is kept here so\n// deploys that already ran the migration stay healthy — additive-only schema\n// policy means we never drop. Physical name stays `tool_consents`.\n\nexport const extensionConsents = table(\"tool_consents\", {\n viewerEmail: text(\"viewer_email\").notNull(),\n extensionId: text(\"tool_id\").notNull(),\n contentHash: text(\"content_hash\").notNull(),\n grantedAt: text(\"granted_at\").notNull().default(now()),\n});\n\nexport const EXTENSION_CONSENTS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_consents (\n viewer_email TEXT NOT NULL,\n tool_id TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n granted_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (viewer_email, tool_id, content_hash)\n)`;\n\nexport const EXTENSION_CONSENTS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_consents (\n viewer_email TEXT NOT NULL,\n tool_id TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n granted_at TEXT NOT NULL DEFAULT now(),\n PRIMARY KEY (viewer_email, tool_id, content_hash)\n)`;\n\nexport const EXTENSION_CONSENTS_VIEWER_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_consents_viewer_idx ON tool_consents (viewer_email, tool_id)`;\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP handler for extension extension-point slots.
|
|
3
|
+
*
|
|
4
|
+
* Mounted at `/_agent-native/slots`. Routes:
|
|
5
|
+
*
|
|
6
|
+
* GET /:slotId/installs — current user's installed widgets for a slot
|
|
7
|
+
* GET /:slotId/available — extensions that declare this slot, scoped to user access
|
|
8
|
+
* POST /:slotId/install — install a extension into a slot (body: { extensionId, position?, config? })
|
|
9
|
+
* DELETE /:slotId/install/:extensionId — uninstall
|
|
10
|
+
* GET /extension/:extensionId — list slot declarations for a specific extension
|
|
11
|
+
* POST /extension/:extensionId — declare a slot target (body: { slotId, config? })
|
|
12
|
+
* DELETE /extension/:extensionId/:slotId — remove a slot declaration
|
|
13
|
+
*/
|
|
14
|
+
export declare function createSlotsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<unknown>>;
|
|
15
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/extensions/slots/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAuBH,wBAAgB,kBAAkB,2FAsBjC"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* HTTP handler for
|
|
2
|
+
* HTTP handler for extension extension-point slots.
|
|
3
3
|
*
|
|
4
4
|
* Mounted at `/_agent-native/slots`. Routes:
|
|
5
5
|
*
|
|
6
6
|
* GET /:slotId/installs — current user's installed widgets for a slot
|
|
7
|
-
* GET /:slotId/available —
|
|
8
|
-
* POST /:slotId/install — install a
|
|
9
|
-
* DELETE /:slotId/install/:
|
|
10
|
-
* GET /
|
|
11
|
-
* POST /
|
|
12
|
-
* DELETE /
|
|
7
|
+
* GET /:slotId/available — extensions that declare this slot, scoped to user access
|
|
8
|
+
* POST /:slotId/install — install a extension into a slot (body: { extensionId, position?, config? })
|
|
9
|
+
* DELETE /:slotId/install/:extensionId — uninstall
|
|
10
|
+
* GET /extension/:extensionId — list slot declarations for a specific extension
|
|
11
|
+
* POST /extension/:extensionId — declare a slot target (body: { slotId, config? })
|
|
12
|
+
* DELETE /extension/:extensionId/:slotId — remove a slot declaration
|
|
13
13
|
*/
|
|
14
14
|
import { defineEventHandler, getMethod, setResponseStatus, } from "h3";
|
|
15
15
|
import { readBody } from "../../server/h3-helpers.js";
|
|
@@ -17,7 +17,7 @@ import { getSession } from "../../server/auth.js";
|
|
|
17
17
|
import { recordChange } from "../../server/poll.js";
|
|
18
18
|
import { runWithRequestContext } from "../../server/request-context.js";
|
|
19
19
|
import { getOrgContext } from "../../org/context.js";
|
|
20
|
-
import {
|
|
20
|
+
import { addExtensionSlotTarget, removeExtensionSlotTarget, listSlotsForExtension, listExtensionsForSlot, installExtensionSlot, uninstallExtensionSlot, listSlotInstallsForUser, } from "./store.js";
|
|
21
21
|
export function createSlotsHandler() {
|
|
22
22
|
return defineEventHandler(async (event) => {
|
|
23
23
|
const method = getMethod(event);
|
|
@@ -37,25 +37,25 @@ export function createSlotsHandler() {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
async function dispatch(event, method, parts) {
|
|
40
|
-
// GET /
|
|
41
|
-
if (method === "GET" && parts.length === 2 && parts[0] === "
|
|
42
|
-
return
|
|
40
|
+
// GET /extension/:extensionId — list a extension's slot declarations
|
|
41
|
+
if (method === "GET" && parts.length === 2 && parts[0] === "extension") {
|
|
42
|
+
return listSlotsForExtension(parts[1]);
|
|
43
43
|
}
|
|
44
|
-
// POST /
|
|
45
|
-
if (method === "POST" && parts.length === 2 && parts[0] === "
|
|
44
|
+
// POST /extension/:extensionId — declare a slot target { slotId, config? }
|
|
45
|
+
if (method === "POST" && parts.length === 2 && parts[0] === "extension") {
|
|
46
46
|
const body = await readBody(event);
|
|
47
47
|
const slotId = String(body?.slotId ?? "").trim();
|
|
48
48
|
if (!slotId) {
|
|
49
49
|
setResponseStatus(event, 400);
|
|
50
50
|
return { error: "slotId is required" };
|
|
51
51
|
}
|
|
52
|
-
const row = await
|
|
52
|
+
const row = await addExtensionSlotTarget(parts[1], slotId, body?.config);
|
|
53
53
|
recordChange({ source: "action", type: "change" });
|
|
54
54
|
return row;
|
|
55
55
|
}
|
|
56
|
-
// DELETE /
|
|
57
|
-
if (method === "DELETE" && parts.length === 3 && parts[0] === "
|
|
58
|
-
await
|
|
56
|
+
// DELETE /extension/:extensionId/:slotId — remove a slot declaration
|
|
57
|
+
if (method === "DELETE" && parts.length === 3 && parts[0] === "extension") {
|
|
58
|
+
await removeExtensionSlotTarget(parts[1], parts[2]);
|
|
59
59
|
recordChange({ source: "action", type: "change" });
|
|
60
60
|
return { ok: true };
|
|
61
61
|
}
|
|
@@ -63,28 +63,28 @@ async function dispatch(event, method, parts) {
|
|
|
63
63
|
if (method === "GET" && parts.length === 2 && parts[1] === "installs") {
|
|
64
64
|
return listSlotInstallsForUser(parts[0]);
|
|
65
65
|
}
|
|
66
|
-
// GET /:slotId/available —
|
|
66
|
+
// GET /:slotId/available — extensions that declare this slot the user can install
|
|
67
67
|
if (method === "GET" && parts.length === 2 && parts[1] === "available") {
|
|
68
|
-
return
|
|
68
|
+
return listExtensionsForSlot(parts[0]);
|
|
69
69
|
}
|
|
70
|
-
// POST /:slotId/install — install {
|
|
70
|
+
// POST /:slotId/install — install { extensionId, position?, config? }
|
|
71
71
|
if (method === "POST" && parts.length === 2 && parts[1] === "install") {
|
|
72
72
|
const body = await readBody(event);
|
|
73
|
-
const
|
|
74
|
-
if (!
|
|
73
|
+
const extensionId = String(body?.extensionId ?? "").trim();
|
|
74
|
+
if (!extensionId) {
|
|
75
75
|
setResponseStatus(event, 400);
|
|
76
|
-
return { error: "
|
|
76
|
+
return { error: "extensionId is required" };
|
|
77
77
|
}
|
|
78
|
-
const row = await
|
|
78
|
+
const row = await installExtensionSlot(extensionId, parts[0], {
|
|
79
79
|
position: body?.position,
|
|
80
80
|
config: body?.config,
|
|
81
81
|
});
|
|
82
82
|
recordChange({ source: "action", type: "change" });
|
|
83
83
|
return row;
|
|
84
84
|
}
|
|
85
|
-
// DELETE /:slotId/install/:
|
|
85
|
+
// DELETE /:slotId/install/:extensionId — uninstall
|
|
86
86
|
if (method === "DELETE" && parts.length === 3 && parts[1] === "install") {
|
|
87
|
-
await
|
|
87
|
+
await uninstallExtensionSlot(parts[2], parts[0]);
|
|
88
88
|
recordChange({ source: "action", type: "change" });
|
|
89
89
|
return { ok: true };
|
|
90
90
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/extensions/slots/routes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HTTP handler for extension extension-point slots.\n *\n * Mounted at `/_agent-native/slots`. Routes:\n *\n * GET /:slotId/installs — current user's installed widgets for a slot\n * GET /:slotId/available — extensions that declare this slot, scoped to user access\n * POST /:slotId/install — install a extension into a slot (body: { extensionId, position?, config? })\n * DELETE /:slotId/install/:extensionId — uninstall\n * GET /extension/:extensionId — list slot declarations for a specific extension\n * POST /extension/:extensionId — declare a slot target (body: { slotId, config? })\n * DELETE /extension/:extensionId/:slotId — remove a slot declaration\n */\n\nimport {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\nimport { readBody } from \"../../server/h3-helpers.js\";\nimport { getSession } from \"../../server/auth.js\";\nimport { recordChange } from \"../../server/poll.js\";\nimport { runWithRequestContext } from \"../../server/request-context.js\";\nimport { getOrgContext } from \"../../org/context.js\";\nimport {\n addExtensionSlotTarget,\n removeExtensionSlotTarget,\n listSlotsForExtension,\n listExtensionsForSlot,\n installExtensionSlot,\n uninstallExtensionSlot,\n listSlotInstallsForUser,\n} from \"./store.js\";\n\nexport function createSlotsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n const parts = pathname ? pathname.split(\"/\") : [];\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n\n const orgCtx = await getOrgContext(event).catch(() => null);\n const userEmail = session.email;\n const orgId = orgCtx?.orgId ?? undefined;\n\n return runWithRequestContext({ userEmail, orgId }, () =>\n dispatch(event, method, parts),\n );\n });\n}\n\nasync function dispatch(\n event: H3Event,\n method: string,\n parts: string[],\n): Promise<unknown> {\n // GET /extension/:extensionId — list a extension's slot declarations\n if (method === \"GET\" && parts.length === 2 && parts[0] === \"extension\") {\n return listSlotsForExtension(parts[1]);\n }\n\n // POST /extension/:extensionId — declare a slot target { slotId, config? }\n if (method === \"POST\" && parts.length === 2 && parts[0] === \"extension\") {\n const body = await readBody(event);\n const slotId = String(body?.slotId ?? \"\").trim();\n if (!slotId) {\n setResponseStatus(event, 400);\n return { error: \"slotId is required\" };\n }\n const row = await addExtensionSlotTarget(parts[1], slotId, body?.config);\n recordChange({ source: \"action\", type: \"change\" });\n return row;\n }\n\n // DELETE /extension/:extensionId/:slotId — remove a slot declaration\n if (method === \"DELETE\" && parts.length === 3 && parts[0] === \"extension\") {\n await removeExtensionSlotTarget(parts[1], parts[2]);\n recordChange({ source: \"action\", type: \"change\" });\n return { ok: true };\n }\n\n // GET /:slotId/installs — current user's installs in slot\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"installs\") {\n return listSlotInstallsForUser(parts[0]);\n }\n\n // GET /:slotId/available — extensions that declare this slot the user can install\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"available\") {\n return listExtensionsForSlot(parts[0]);\n }\n\n // POST /:slotId/install — install { extensionId, position?, config? }\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"install\") {\n const body = await readBody(event);\n const extensionId = String(body?.extensionId ?? \"\").trim();\n if (!extensionId) {\n setResponseStatus(event, 400);\n return { error: \"extensionId is required\" };\n }\n const row = await installExtensionSlot(extensionId, parts[0], {\n position: body?.position,\n config: body?.config,\n });\n recordChange({ source: \"action\", type: \"change\" });\n return row;\n }\n\n // DELETE /:slotId/install/:extensionId — uninstall\n if (method === \"DELETE\" && parts.length === 3 && parts[1] === \"install\") {\n await uninstallExtensionSlot(parts[2], parts[0]);\n recordChange({ source: \"action\", type: \"change\" });\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { error: \"Not found\" };\n}\n"]}
|