driggsby 0.2.2 → 0.2.3
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.
|
@@ -36,6 +36,7 @@ export async function runDeploy(options, environment = defaultCredentialEnvironm
|
|
|
36
36
|
const startedAt = io.now();
|
|
37
37
|
const { outcome, createdApp } = await deployProjectFiles({ baseUrl: session.baseUrl, token: session.token }, projectDirectory, config.slug, collected, {
|
|
38
38
|
live: !options.preview,
|
|
39
|
+
...(config.background !== null ? { background: config.background } : {}),
|
|
39
40
|
// The assigned slug is server text, so it prints quoted and
|
|
40
41
|
// length-bounded like every other string this CLI did not author.
|
|
41
42
|
// A validated slug tops out at 63 characters, so the line never
|
package/dist/dev/dev-command.js
CHANGED
|
@@ -52,6 +52,7 @@ export async function runDev(options = {}, environment = defaultCredentialEnviro
|
|
|
52
52
|
try {
|
|
53
53
|
servers = await startDevServers({
|
|
54
54
|
slug: config.slug,
|
|
55
|
+
background: config.background,
|
|
55
56
|
serveDirectory: config.serveDirectory,
|
|
56
57
|
sdkBundle,
|
|
57
58
|
runToolCall: (tool, argumentsObject) => broker.runToolCall(tool, argumentsObject),
|
package/dist/dev/dev-servers.js
CHANGED
|
@@ -117,7 +117,7 @@ async function handleHostRequest(options, hostPort, appOrigin, sseClients, reque
|
|
|
117
117
|
}
|
|
118
118
|
const path = requestPath(request);
|
|
119
119
|
if (request.method === "GET" && path === "/") {
|
|
120
|
-
sendHostPage(response, hostPageHtml(options.slug, appOrigin), appOrigin);
|
|
120
|
+
sendHostPage(response, hostPageHtml(options.slug, appOrigin, options.background), appOrigin);
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
123
|
if (request.method === "GET" && path === "/host.js") {
|
package/dist/dev/host-page.js
CHANGED
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
// The page's script is served as its own file so the page can carry a
|
|
9
9
|
// Content-Security-Policy with no inline scripts.
|
|
10
10
|
//
|
|
11
|
-
//
|
|
11
|
+
// All interpolations below are HTML-safe by construction, not by escaping:
|
|
12
12
|
// `slug` has passed readProjectConfig's strict slug rules (lowercase
|
|
13
|
-
// alphanumerics and dashes only) before runDev ever calls this,
|
|
13
|
+
// alphanumerics and dashes only) before runDev ever calls this,
|
|
14
14
|
// `appOrigin` is built by startDevServers from a literal plus a bound port
|
|
15
|
-
// number
|
|
16
|
-
|
|
15
|
+
// number, and `background` has passed readProjectConfig's strict hex-color
|
|
16
|
+
// rule (or is null). Anything looser than those sources must not be
|
|
17
|
+
// passed here.
|
|
18
|
+
export function hostPageHtml(slug, appOrigin, background) {
|
|
17
19
|
return `<!doctype html>
|
|
18
20
|
<html lang="en" data-app-origin="${appOrigin}">
|
|
19
21
|
<head>
|
|
@@ -45,6 +47,9 @@ export function hostPageHtml(slug, appOrigin) {
|
|
|
45
47
|
flex: 1;
|
|
46
48
|
width: 100%;
|
|
47
49
|
border: none;
|
|
50
|
+
/* The app's declared background from driggsby.json, painted while
|
|
51
|
+
the app loads — the same surface the production host shows. */
|
|
52
|
+
background: ${background ?? "#ffffff"};
|
|
48
53
|
}
|
|
49
54
|
</style>
|
|
50
55
|
</head>
|
|
@@ -66,6 +71,47 @@ export const HOST_PAGE_JS = [
|
|
|
66
71
|
"const APP_ORIGIN = document.documentElement.dataset.appOrigin;",
|
|
67
72
|
'const frame = document.getElementById("app");',
|
|
68
73
|
"",
|
|
74
|
+
"// The app's in-page location (a URL fragment), mirrored into this",
|
|
75
|
+
"// page's own URL and handed back in the hello — the same route sync",
|
|
76
|
+
"// the production host does, same strict shape on both sides.",
|
|
77
|
+
"const APP_ROUTE_PATTERN = /^#[A-Za-z0-9\\/\\-._]{1,256}$/;",
|
|
78
|
+
"",
|
|
79
|
+
"function sanitizeAppRoute(value) {",
|
|
80
|
+
' return typeof value === "string" && APP_ROUTE_PATTERN.test(value) ? value : "";',
|
|
81
|
+
"}",
|
|
82
|
+
"",
|
|
83
|
+
"let appRoute = sanitizeAppRoute(window.location.hash);",
|
|
84
|
+
"",
|
|
85
|
+
"// URL writes are bounded (leading + one trailing per window) because",
|
|
86
|
+
"// the frame controls their rate, and each write is guarded: Safari",
|
|
87
|
+
"// hard-errors on rapid replaceState bursts.",
|
|
88
|
+
"const ROUTE_WRITE_WINDOW_MS = 1000;",
|
|
89
|
+
"let routeWriteTimer = null;",
|
|
90
|
+
"",
|
|
91
|
+
"function writeRouteToUrl() {",
|
|
92
|
+
" if (window.location.hash === appRoute) {",
|
|
93
|
+
" return;",
|
|
94
|
+
" }",
|
|
95
|
+
' const base = window.location.href.split("#")[0];',
|
|
96
|
+
" try {",
|
|
97
|
+
' history.replaceState(history.state, "", base + appRoute);',
|
|
98
|
+
" } catch (error) {",
|
|
99
|
+
" // A refused write costs only URL freshness; the next one retries.",
|
|
100
|
+
" }",
|
|
101
|
+
"}",
|
|
102
|
+
"",
|
|
103
|
+
"function applyRoute(hash) {",
|
|
104
|
+
" appRoute = hash;",
|
|
105
|
+
" if (routeWriteTimer !== null) {",
|
|
106
|
+
" return;",
|
|
107
|
+
" }",
|
|
108
|
+
" writeRouteToUrl();",
|
|
109
|
+
" routeWriteTimer = setTimeout(() => {",
|
|
110
|
+
" routeWriteTimer = null;",
|
|
111
|
+
" writeRouteToUrl();",
|
|
112
|
+
" }, ROUTE_WRITE_WINDOW_MS);",
|
|
113
|
+
"}",
|
|
114
|
+
"",
|
|
69
115
|
"function postToApp(message) {",
|
|
70
116
|
" if (frame.contentWindow) {",
|
|
71
117
|
" frame.contentWindow.postMessage(message, APP_ORIGIN);",
|
|
@@ -114,7 +160,25 @@ export const HOST_PAGE_JS = [
|
|
|
114
160
|
" }",
|
|
115
161
|
" const data = event.data;",
|
|
116
162
|
' if (data.type === "ready") {',
|
|
117
|
-
|
|
163
|
+
" const hello = { protocol: PROTOCOL, type: \"hello\" };",
|
|
164
|
+
' if (appRoute !== "") {',
|
|
165
|
+
" hello.route = appRoute;",
|
|
166
|
+
" }",
|
|
167
|
+
" postToApp(hello);",
|
|
168
|
+
" return;",
|
|
169
|
+
" }",
|
|
170
|
+
' if (data.type === "route") {',
|
|
171
|
+
' // A bare "#" is the explicit cleared sentinel: the app is back at',
|
|
172
|
+
" // its no-hash location, so the page URL drops its fragment.",
|
|
173
|
+
' if (data.hash === "#") {',
|
|
174
|
+
' applyRoute("");',
|
|
175
|
+
" return;",
|
|
176
|
+
" }",
|
|
177
|
+
" const hash = sanitizeAppRoute(data.hash);",
|
|
178
|
+
' if (hash === "") {',
|
|
179
|
+
" return;",
|
|
180
|
+
" }",
|
|
181
|
+
" applyRoute(hash);",
|
|
118
182
|
" return;",
|
|
119
183
|
" }",
|
|
120
184
|
' if (data.type !== "call") {',
|
package/dist/init/templates.js
CHANGED
|
@@ -91,6 +91,27 @@ export const APP_JS = `// Your app's code. Edit anything — driggsby dev reload
|
|
|
91
91
|
// Each watch is a live subscription: the callback runs with a fresh result
|
|
92
92
|
// whenever your Driggsby data changes. The sample data below matches the
|
|
93
93
|
// real result shapes, so the render functions work unchanged either way.
|
|
94
|
+
//
|
|
95
|
+
// These are the tools an app can watch — read-only, nothing else responds:
|
|
96
|
+
//
|
|
97
|
+
// get_overview money rollups + every linked account
|
|
98
|
+
// get_history balances, holdings, or debts over time
|
|
99
|
+
// (history_type is required: "account_balances",
|
|
100
|
+
// "investment_holdings", or "liabilities")
|
|
101
|
+
// list_accounts current balances per linked account
|
|
102
|
+
// list_assets_and_liabilities the full balance sheet, incl. manual items
|
|
103
|
+
// list_findings issues Driggsby has flagged
|
|
104
|
+
// list_investment_holdings current investment positions
|
|
105
|
+
// list_outstanding_debts linked debts with balances and rates
|
|
106
|
+
// list_recurring_transactions subscriptions, bills, and paychecks
|
|
107
|
+
// query_cash_sql SQL over cash transactions ({ sql: "..." })
|
|
108
|
+
// query_investment_sql SQL over investment activity ({ sql: "..." })
|
|
109
|
+
// search_cash_transactions bank and card transaction search
|
|
110
|
+
// search_investment_activity trades, dividends, and transfers
|
|
111
|
+
//
|
|
112
|
+
// Params mirror Driggsby's public MCP tools of the same names, with one
|
|
113
|
+
// simplification: those tools require a "reason" string, but a watch can
|
|
114
|
+
// leave it out — Driggsby fills one in naming the dashboard.
|
|
94
115
|
|
|
95
116
|
// ---------------------------------------------------------------------------
|
|
96
117
|
// Sample data. Every name and number here is invented. It paints only
|
|
@@ -396,6 +417,10 @@ h2 {
|
|
|
396
417
|
font-variant-numeric: tabular-nums;
|
|
397
418
|
}
|
|
398
419
|
`;
|
|
420
|
+
// "background" is the template's own page background (styles.css
|
|
421
|
+
// --background): Driggsby paints it while the app loads, so the loading
|
|
422
|
+
// surface matches the app from the first frame. An agent that re-themes
|
|
423
|
+
// the app should keep this equal to the page's real background color.
|
|
399
424
|
export function driggsbyJsonText(slug) {
|
|
400
|
-
return `{\n "slug": ${JSON.stringify(slug)},\n "serve": "."\n}\n`;
|
|
425
|
+
return `{\n "slug": ${JSON.stringify(slug)},\n "serve": ".",\n "background": "#ffffff"\n}\n`;
|
|
401
426
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "driggsby",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Set up and build on Driggsby, the MCP server for personal finance.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"node": ">=18"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@driggsby/deploy": "0.2.
|
|
32
|
-
"@driggsby/sdk": "0.2.
|
|
31
|
+
"@driggsby/deploy": "0.2.3",
|
|
32
|
+
"@driggsby/sdk": "0.2.3"
|
|
33
33
|
}
|
|
34
34
|
}
|