@agent-native/core 0.98.2 → 0.98.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.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +10 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +2 -2
- package/corpus/core/src/client/index.ts +2 -0
- package/corpus/core/src/client/settings/DemoModeSection.tsx +6 -6
- package/corpus/core/src/client/settings/SettingsPanel.tsx +31 -211
- package/corpus/core/src/client/settings/agent-settings-search.ts +219 -0
- package/corpus/core/src/client/settings/index.ts +4 -0
- package/corpus/core/src/demo/actions/toggle-demo-mode.ts +2 -2
- package/corpus/core/src/demo/config.ts +6 -6
- package/corpus/core/src/demo/redact.ts +18 -76
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +21 -4
- package/corpus/templates/analytics/AGENTS.md +6 -6
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +429 -244
- package/corpus/templates/analytics/app/components/layout/command-palette-search.ts +93 -0
- package/corpus/templates/analytics/app/hooks/use-replay-storage-status.ts +2 -1
- package/corpus/templates/analytics/app/lib/demo-chart-trend.ts +46 -33
- package/corpus/templates/analytics/app/pages/Settings.tsx +8 -45
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +205 -70
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +32 -16
- package/corpus/templates/analytics/app/pages/settings/settings-search.ts +126 -0
- package/corpus/templates/analytics/changelog/2026-07-12-command-menu-loading-placeholders-now-stay-below-available-r.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-command-menu-search-now-prioritizes-the-best-match.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-demo-charts-preserve-source-movement.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-replay-storage-settings-stay-readable-at-narrow-widths.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-session-replays-preserve-recorded-styling-and-keep-malformed.md +6 -0
- package/dist/agent/production-agent.js +2 -2
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/settings/DemoModeSection.d.ts +3 -3
- package/dist/client/settings/DemoModeSection.js +4 -4
- package/dist/client/settings/DemoModeSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +41 -191
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/agent-settings-search.d.ts +16 -0
- package/dist/client/settings/agent-settings-search.d.ts.map +1 -0
- package/dist/client/settings/agent-settings-search.js +178 -0
- package/dist/client/settings/agent-settings-search.js.map +1 -0
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/index.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/demo/actions/toggle-demo-mode.js +2 -2
- package/dist/demo/actions/toggle-demo-mode.js.map +1 -1
- package/dist/demo/config.js +6 -6
- package/dist/demo/config.js.map +1 -1
- package/dist/demo/redact.d.ts +7 -5
- package/dist/demo/redact.d.ts.map +1 -1
- package/dist/demo/redact.js +19 -54
- package/dist/demo/redact.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SettingsSearchEntry } from "./SettingsTabsPage.js";
|
|
2
|
+
export type SettingsSectionId = "account" | "llm" | "app-models" | "limits" | "voice" | "demo-mode" | "automations" | "secrets" | "hosting" | "database" | "uploads" | "auth" | "email" | "browser" | "background" | "integrations" | "usage" | "a2a";
|
|
3
|
+
export declare const SETTINGS_SECTION_IDS: Set<SettingsSectionId>;
|
|
4
|
+
export declare const ALL_SETTINGS_SECTIONS: readonly SettingsSectionId[];
|
|
5
|
+
export declare const AGENT_SETTINGS_SECTIONS: readonly SettingsSectionId[];
|
|
6
|
+
export declare const CONNECTION_SETTINGS_SECTIONS: readonly SettingsSectionId[];
|
|
7
|
+
export declare const WORKSPACE_SETTINGS_SECTIONS: readonly SettingsSectionId[];
|
|
8
|
+
export declare function buildSectionSearchEntries(sections: readonly SettingsSectionId[]): SettingsSearchEntry[];
|
|
9
|
+
export interface AgentSettingsSearchTab {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
keywords: string;
|
|
13
|
+
searchEntries?: SettingsSearchEntry[];
|
|
14
|
+
}
|
|
15
|
+
export declare function getAgentSettingsSearchTabs(): AgentSettingsSearchTab[];
|
|
16
|
+
//# sourceMappingURL=agent-settings-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-settings-search.d.ts","sourceRoot":"","sources":["../../../src/client/settings/agent-settings-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,KAAK,GACL,YAAY,GACZ,QAAQ,GACR,OAAO,GACP,WAAW,GACX,aAAa,GACb,SAAS,GACT,SAAS,GACT,UAAU,GACV,SAAS,GACT,MAAM,GACN,OAAO,GACP,SAAS,GACT,YAAY,GACZ,cAAc,GACd,OAAO,GACP,KAAK,CAAC;AAEV,eAAO,MAAM,oBAAoB,wBAmB/B,CAAC;AAEH,eAAO,MAAM,qBAAqB,EAAE,SAAS,iBAAiB,EAmB7D,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,SAAS,iBAAiB,EAQ/D,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,SAAS,iBAAiB,EAMpE,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,SAAS,iBAAiB,EAOnE,CAAC;AAiFF,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,GACrC,mBAAmB,EAAE,CAWvB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACvC;AAED,wBAAgB,0BAA0B,IAAI,sBAAsB,EAAE,CA0BrE"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
export const SETTINGS_SECTION_IDS = new Set([
|
|
2
|
+
"account",
|
|
3
|
+
"llm",
|
|
4
|
+
"app-models",
|
|
5
|
+
"limits",
|
|
6
|
+
"voice",
|
|
7
|
+
"demo-mode",
|
|
8
|
+
"automations",
|
|
9
|
+
"secrets",
|
|
10
|
+
"hosting",
|
|
11
|
+
"database",
|
|
12
|
+
"uploads",
|
|
13
|
+
"auth",
|
|
14
|
+
"email",
|
|
15
|
+
"browser",
|
|
16
|
+
"background",
|
|
17
|
+
"integrations",
|
|
18
|
+
"usage",
|
|
19
|
+
"a2a",
|
|
20
|
+
]);
|
|
21
|
+
export const ALL_SETTINGS_SECTIONS = [
|
|
22
|
+
"account",
|
|
23
|
+
"llm",
|
|
24
|
+
"app-models",
|
|
25
|
+
"limits",
|
|
26
|
+
"voice",
|
|
27
|
+
"demo-mode",
|
|
28
|
+
"automations",
|
|
29
|
+
"secrets",
|
|
30
|
+
"hosting",
|
|
31
|
+
"database",
|
|
32
|
+
"uploads",
|
|
33
|
+
"auth",
|
|
34
|
+
"email",
|
|
35
|
+
"browser",
|
|
36
|
+
"background",
|
|
37
|
+
"integrations",
|
|
38
|
+
"usage",
|
|
39
|
+
"a2a",
|
|
40
|
+
];
|
|
41
|
+
export const AGENT_SETTINGS_SECTIONS = [
|
|
42
|
+
"llm",
|
|
43
|
+
"app-models",
|
|
44
|
+
"limits",
|
|
45
|
+
"voice",
|
|
46
|
+
"automations",
|
|
47
|
+
"background",
|
|
48
|
+
"a2a",
|
|
49
|
+
];
|
|
50
|
+
export const CONNECTION_SETTINGS_SECTIONS = [
|
|
51
|
+
"secrets",
|
|
52
|
+
"integrations",
|
|
53
|
+
"email",
|
|
54
|
+
"browser",
|
|
55
|
+
"usage",
|
|
56
|
+
];
|
|
57
|
+
export const WORKSPACE_SETTINGS_SECTIONS = [
|
|
58
|
+
"account",
|
|
59
|
+
"demo-mode",
|
|
60
|
+
"hosting",
|
|
61
|
+
"database",
|
|
62
|
+
"uploads",
|
|
63
|
+
"auth",
|
|
64
|
+
];
|
|
65
|
+
const SETTINGS_SECTION_SEARCH_META = {
|
|
66
|
+
account: {
|
|
67
|
+
label: "Account",
|
|
68
|
+
keywords: "profile photo avatar identity signed in email name",
|
|
69
|
+
},
|
|
70
|
+
llm: {
|
|
71
|
+
label: "LLM",
|
|
72
|
+
keywords: "model claude gpt openai anthropic gemini api key provider ai engine llm",
|
|
73
|
+
},
|
|
74
|
+
"app-models": {
|
|
75
|
+
label: "App Default Model",
|
|
76
|
+
keywords: "default model provider app template composer",
|
|
77
|
+
},
|
|
78
|
+
limits: {
|
|
79
|
+
label: "Agent Limits",
|
|
80
|
+
keywords: "max iterations budget loop timeout runtime",
|
|
81
|
+
},
|
|
82
|
+
voice: {
|
|
83
|
+
label: "Voice Transcription",
|
|
84
|
+
keywords: "microphone dictation speech to text whisper",
|
|
85
|
+
},
|
|
86
|
+
"demo-mode": {
|
|
87
|
+
label: "Demo mode",
|
|
88
|
+
keywords: "fake data anonymize redact screenshot privacy mask",
|
|
89
|
+
},
|
|
90
|
+
automations: {
|
|
91
|
+
label: "Automations",
|
|
92
|
+
keywords: "triggers scheduled events cron jobs",
|
|
93
|
+
},
|
|
94
|
+
secrets: {
|
|
95
|
+
label: "API Keys & Connections",
|
|
96
|
+
keywords: "secrets credentials tokens api keys environment variables",
|
|
97
|
+
},
|
|
98
|
+
hosting: {
|
|
99
|
+
label: "Hosting",
|
|
100
|
+
keywords: "deploy netlify vercel cloudflare builder nitro",
|
|
101
|
+
},
|
|
102
|
+
database: {
|
|
103
|
+
label: "Database",
|
|
104
|
+
keywords: "postgres sqlite neon supabase turso storage sql pglite",
|
|
105
|
+
},
|
|
106
|
+
uploads: {
|
|
107
|
+
label: "File uploads",
|
|
108
|
+
keywords: "files storage s3 avatars attachments bucket blob",
|
|
109
|
+
},
|
|
110
|
+
auth: {
|
|
111
|
+
label: "Authentication",
|
|
112
|
+
keywords: "login signup oauth google github better auth access sso",
|
|
113
|
+
},
|
|
114
|
+
email: {
|
|
115
|
+
label: "Email",
|
|
116
|
+
keywords: "resend sendgrid smtp transactional notifications reports",
|
|
117
|
+
},
|
|
118
|
+
browser: {
|
|
119
|
+
label: "Browser Automation",
|
|
120
|
+
keywords: "web scraping playwright chrome headless",
|
|
121
|
+
},
|
|
122
|
+
background: {
|
|
123
|
+
label: "Background Agent",
|
|
124
|
+
keywords: "code changes branches builder production async",
|
|
125
|
+
},
|
|
126
|
+
integrations: {
|
|
127
|
+
label: "Integrations",
|
|
128
|
+
keywords: "slack telegram whatsapp discord messaging connect",
|
|
129
|
+
},
|
|
130
|
+
usage: {
|
|
131
|
+
label: "Usage",
|
|
132
|
+
keywords: "tokens cost spend billing consumption",
|
|
133
|
+
},
|
|
134
|
+
a2a: {
|
|
135
|
+
label: "Connected Agents (A2A)",
|
|
136
|
+
keywords: "remote agents protocol a2a connected",
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
export function buildSectionSearchEntries(sections) {
|
|
140
|
+
return sections.map((section) => {
|
|
141
|
+
const meta = SETTINGS_SECTION_SEARCH_META[section];
|
|
142
|
+
return {
|
|
143
|
+
id: `section:${section}`,
|
|
144
|
+
label: meta.label,
|
|
145
|
+
keywords: meta.keywords,
|
|
146
|
+
description: meta.description,
|
|
147
|
+
hash: section,
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
export function getAgentSettingsSearchTabs() {
|
|
152
|
+
return [
|
|
153
|
+
{
|
|
154
|
+
id: "agent",
|
|
155
|
+
label: "Agent",
|
|
156
|
+
keywords: "agent model llm limits voice automations",
|
|
157
|
+
searchEntries: buildSectionSearchEntries(AGENT_SETTINGS_SECTIONS),
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: "connections",
|
|
161
|
+
label: "Connections",
|
|
162
|
+
keywords: "connections secrets integrations email browser usage",
|
|
163
|
+
searchEntries: buildSectionSearchEntries(CONNECTION_SETTINGS_SECTIONS),
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "organization",
|
|
167
|
+
label: "Organization",
|
|
168
|
+
keywords: "organization org team members invites collaborators",
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: "workspace",
|
|
172
|
+
label: "Workspace",
|
|
173
|
+
keywords: "workspace account hosting database uploads auth",
|
|
174
|
+
searchEntries: buildSectionSearchEntries(WORKSPACE_SETTINGS_SECTIONS),
|
|
175
|
+
},
|
|
176
|
+
];
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=agent-settings-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-settings-search.js","sourceRoot":"","sources":["../../../src/client/settings/agent-settings-search.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SettingsSearchEntry } from \"./SettingsTabsPage.js\";\n\nexport type SettingsSectionId =\n | \"account\"\n | \"llm\"\n | \"app-models\"\n | \"limits\"\n | \"voice\"\n | \"demo-mode\"\n | \"automations\"\n | \"secrets\"\n | \"hosting\"\n | \"database\"\n | \"uploads\"\n | \"auth\"\n | \"email\"\n | \"browser\"\n | \"background\"\n | \"integrations\"\n | \"usage\"\n | \"a2a\";\n\nexport const SETTINGS_SECTION_IDS = new Set<SettingsSectionId>([\n \"account\",\n \"llm\",\n \"app-models\",\n \"limits\",\n \"voice\",\n \"demo-mode\",\n \"automations\",\n \"secrets\",\n \"hosting\",\n \"database\",\n \"uploads\",\n \"auth\",\n \"email\",\n \"browser\",\n \"background\",\n \"integrations\",\n \"usage\",\n \"a2a\",\n]);\n\nexport const ALL_SETTINGS_SECTIONS: readonly SettingsSectionId[] = [\n \"account\",\n \"llm\",\n \"app-models\",\n \"limits\",\n \"voice\",\n \"demo-mode\",\n \"automations\",\n \"secrets\",\n \"hosting\",\n \"database\",\n \"uploads\",\n \"auth\",\n \"email\",\n \"browser\",\n \"background\",\n \"integrations\",\n \"usage\",\n \"a2a\",\n];\n\nexport const AGENT_SETTINGS_SECTIONS: readonly SettingsSectionId[] = [\n \"llm\",\n \"app-models\",\n \"limits\",\n \"voice\",\n \"automations\",\n \"background\",\n \"a2a\",\n];\n\nexport const CONNECTION_SETTINGS_SECTIONS: readonly SettingsSectionId[] = [\n \"secrets\",\n \"integrations\",\n \"email\",\n \"browser\",\n \"usage\",\n];\n\nexport const WORKSPACE_SETTINGS_SECTIONS: readonly SettingsSectionId[] = [\n \"account\",\n \"demo-mode\",\n \"hosting\",\n \"database\",\n \"uploads\",\n \"auth\",\n];\n\nconst SETTINGS_SECTION_SEARCH_META: Record<\n SettingsSectionId,\n { label: string; keywords: string; description?: string }\n> = {\n account: {\n label: \"Account\",\n keywords: \"profile photo avatar identity signed in email name\",\n },\n llm: {\n label: \"LLM\",\n keywords:\n \"model claude gpt openai anthropic gemini api key provider ai engine llm\",\n },\n \"app-models\": {\n label: \"App Default Model\",\n keywords: \"default model provider app template composer\",\n },\n limits: {\n label: \"Agent Limits\",\n keywords: \"max iterations budget loop timeout runtime\",\n },\n voice: {\n label: \"Voice Transcription\",\n keywords: \"microphone dictation speech to text whisper\",\n },\n \"demo-mode\": {\n label: \"Demo mode\",\n keywords: \"fake data anonymize redact screenshot privacy mask\",\n },\n automations: {\n label: \"Automations\",\n keywords: \"triggers scheduled events cron jobs\",\n },\n secrets: {\n label: \"API Keys & Connections\",\n keywords: \"secrets credentials tokens api keys environment variables\",\n },\n hosting: {\n label: \"Hosting\",\n keywords: \"deploy netlify vercel cloudflare builder nitro\",\n },\n database: {\n label: \"Database\",\n keywords: \"postgres sqlite neon supabase turso storage sql pglite\",\n },\n uploads: {\n label: \"File uploads\",\n keywords: \"files storage s3 avatars attachments bucket blob\",\n },\n auth: {\n label: \"Authentication\",\n keywords: \"login signup oauth google github better auth access sso\",\n },\n email: {\n label: \"Email\",\n keywords: \"resend sendgrid smtp transactional notifications reports\",\n },\n browser: {\n label: \"Browser Automation\",\n keywords: \"web scraping playwright chrome headless\",\n },\n background: {\n label: \"Background Agent\",\n keywords: \"code changes branches builder production async\",\n },\n integrations: {\n label: \"Integrations\",\n keywords: \"slack telegram whatsapp discord messaging connect\",\n },\n usage: {\n label: \"Usage\",\n keywords: \"tokens cost spend billing consumption\",\n },\n a2a: {\n label: \"Connected Agents (A2A)\",\n keywords: \"remote agents protocol a2a connected\",\n },\n};\n\nexport function buildSectionSearchEntries(\n sections: readonly SettingsSectionId[],\n): SettingsSearchEntry[] {\n return sections.map((section) => {\n const meta = SETTINGS_SECTION_SEARCH_META[section];\n return {\n id: `section:${section}`,\n label: meta.label,\n keywords: meta.keywords,\n description: meta.description,\n hash: section,\n };\n });\n}\n\nexport interface AgentSettingsSearchTab {\n id: string;\n label: string;\n keywords: string;\n searchEntries?: SettingsSearchEntry[];\n}\n\nexport function getAgentSettingsSearchTabs(): AgentSettingsSearchTab[] {\n return [\n {\n id: \"agent\",\n label: \"Agent\",\n keywords: \"agent model llm limits voice automations\",\n searchEntries: buildSectionSearchEntries(AGENT_SETTINGS_SECTIONS),\n },\n {\n id: \"connections\",\n label: \"Connections\",\n keywords: \"connections secrets integrations email browser usage\",\n searchEntries: buildSectionSearchEntries(CONNECTION_SETTINGS_SECTIONS),\n },\n {\n id: \"organization\",\n label: \"Organization\",\n keywords: \"organization org team members invites collaborators\",\n },\n {\n id: \"workspace\",\n label: \"Workspace\",\n keywords: \"workspace account hosting database uploads auth\",\n searchEntries: buildSectionSearchEntries(WORKSPACE_SETTINGS_SECTIONS),\n },\n ];\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { SettingsPanel, useAgentSettingsTabs, type SettingsPanelProps, } from "./SettingsPanel.js";
|
|
2
|
+
export { getAgentSettingsSearchTabs, type AgentSettingsSearchTab, } from "./agent-settings-search.js";
|
|
2
3
|
export { SettingsTabsPage, type SettingsSearchEntry, type SettingsTabItem, type SettingsTabsPageProps, } from "./SettingsTabsPage.js";
|
|
3
4
|
export { openBuilderConnectPopup, useBuilderConnectFlow, useBuilderStatus, withBuilderConnectTrackingParams, type BuilderConnectFlow, type BuilderConnectFlowOptions, type BuilderConnectStartOptions, type BuilderStatus, type OpenBuilderConnectPopupOptions, } from "./useBuilderStatus.js";
|
|
4
5
|
export { SecretsSection, type SecretsSectionProps } from "./SecretsSection.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/settings/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,gBAAgB,EAChB,gCAAgC,EAChC,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,aAAa,EAClB,KAAK,8BAA8B,GACpC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/settings/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,0BAA0B,EAC1B,KAAK,sBAAsB,GAC5B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,gBAAgB,EAChB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,gBAAgB,EAChB,gCAAgC,EAChC,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,aAAa,EAClB,KAAK,8BAA8B,GACpC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { SettingsPanel, useAgentSettingsTabs, } from "./SettingsPanel.js";
|
|
2
|
+
export { getAgentSettingsSearchTabs, } from "./agent-settings-search.js";
|
|
2
3
|
export { SettingsTabsPage, } from "./SettingsTabsPage.js";
|
|
3
4
|
export { openBuilderConnectPopup, useBuilderConnectFlow, useBuilderStatus, withBuilderConnectTrackingParams, } from "./useBuilderStatus.js";
|
|
4
5
|
export { SecretsSection } from "./SecretsSection.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/settings/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,GAIjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,gBAAgB,EAChB,gCAAgC,GAMjC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAA4B,MAAM,qBAAqB,CAAC","sourcesContent":["export {\n SettingsPanel,\n useAgentSettingsTabs,\n type SettingsPanelProps,\n} from \"./SettingsPanel.js\";\nexport {\n SettingsTabsPage,\n type SettingsSearchEntry,\n type SettingsTabItem,\n type SettingsTabsPageProps,\n} from \"./SettingsTabsPage.js\";\nexport {\n openBuilderConnectPopup,\n useBuilderConnectFlow,\n useBuilderStatus,\n withBuilderConnectTrackingParams,\n type BuilderConnectFlow,\n type BuilderConnectFlowOptions,\n type BuilderConnectStartOptions,\n type BuilderStatus,\n type OpenBuilderConnectPopupOptions,\n} from \"./useBuilderStatus.js\";\nexport { SecretsSection, type SecretsSectionProps } from \"./SecretsSection.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/settings/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,0BAA0B,GAE3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,gBAAgB,GAIjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,gBAAgB,EAChB,gCAAgC,GAMjC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAA4B,MAAM,qBAAqB,CAAC","sourcesContent":["export {\n SettingsPanel,\n useAgentSettingsTabs,\n type SettingsPanelProps,\n} from \"./SettingsPanel.js\";\nexport {\n getAgentSettingsSearchTabs,\n type AgentSettingsSearchTab,\n} from \"./agent-settings-search.js\";\nexport {\n SettingsTabsPage,\n type SettingsSearchEntry,\n type SettingsTabItem,\n type SettingsTabsPageProps,\n} from \"./SettingsTabsPage.js\";\nexport {\n openBuilderConnectPopup,\n useBuilderConnectFlow,\n useBuilderStatus,\n withBuilderConnectTrackingParams,\n type BuilderConnectFlow,\n type BuilderConnectFlowOptions,\n type BuilderConnectStartOptions,\n type BuilderStatus,\n type OpenBuilderConnectPopupOptions,\n} from \"./useBuilderStatus.js\";\nexport { SecretsSection, type SecretsSectionProps } from \"./SecretsSection.js\";\n"]}
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
ok?: undefined;
|
|
30
29
|
error: string;
|
|
30
|
+
ok?: undefined;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -42,8 +42,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
|
|
|
42
42
|
*/
|
|
43
43
|
export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
44
44
|
ok?: undefined;
|
|
45
|
-
text?: undefined;
|
|
46
45
|
error: string;
|
|
46
|
+
text?: undefined;
|
|
47
47
|
} | {
|
|
48
48
|
error?: undefined;
|
|
49
49
|
ok: boolean;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { defineAction } from "../../action.js";
|
|
3
3
|
import { writeAppState } from "../../application-state/script-helpers.js";
|
|
4
4
|
export default defineAction({
|
|
5
|
-
description: "Turn demo mode on or off. When demo mode is on, the app replaces
|
|
5
|
+
description: "Turn demo mode on or off. When demo mode is on, the app replaces email addresses and numbers with realistic fake data everywhere — in the UI and in what you (the agent) see — while keeping names, free text, labels, IDs, dates, and structure intact so everything still works. Use when the user asks to 'hide my data', 'turn on demo mode', 'anonymize this for a screen share / recording', or similar. This is the same toggle as the Demo mode switch in settings.",
|
|
6
6
|
schema: z.object({
|
|
7
7
|
enabled: z
|
|
8
8
|
.boolean()
|
|
@@ -13,7 +13,7 @@ export default defineAction({
|
|
|
13
13
|
return {
|
|
14
14
|
enabled,
|
|
15
15
|
message: enabled
|
|
16
|
-
? "Demo mode is ON —
|
|
16
|
+
? "Demo mode is ON — emails and numbers are now replaced with deterministic fake data everywhere (UI and agent). Names, free text, labels, IDs, and structure are preserved so everything keeps working."
|
|
17
17
|
: "Demo mode is OFF — real data is shown again.",
|
|
18
18
|
};
|
|
19
19
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle-demo-mode.js","sourceRoot":"","sources":["../../../src/demo/actions/toggle-demo-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAE1E,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"toggle-demo-mode.js","sourceRoot":"","sources":["../../../src/demo/actions/toggle-demo-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAE1E,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,6cAA6c;IAC/c,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,CAAC;aACP,OAAO,EAAE;aACT,QAAQ,CAAC,kDAAkD,CAAC;KAChE,CAAC;IACF,GAAG,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACzB,MAAM,aAAa,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9C,OAAO;YACL,OAAO;YACP,OAAO,EAAE,OAAO;gBACd,CAAC,CAAC,uMAAuM;gBACzM,CAAC,CAAC,8CAA8C;SACnD,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport { writeAppState } from \"../../application-state/script-helpers.js\";\n\nexport default defineAction({\n description:\n \"Turn demo mode on or off. When demo mode is on, the app replaces email addresses and numbers with realistic fake data everywhere — in the UI and in what you (the agent) see — while keeping names, free text, labels, IDs, dates, and structure intact so everything still works. Use when the user asks to 'hide my data', 'turn on demo mode', 'anonymize this for a screen share / recording', or similar. This is the same toggle as the Demo mode switch in settings.\",\n schema: z.object({\n enabled: z\n .boolean()\n .describe(\"true to turn demo mode on, false to turn it off.\"),\n }),\n run: async ({ enabled }) => {\n await writeAppState(\"demo-mode\", { enabled });\n return {\n enabled,\n message: enabled\n ? \"Demo mode is ON — emails and numbers are now replaced with deterministic fake data everywhere (UI and agent). Names, free text, labels, IDs, and structure are preserved so everything keeps working.\"\n : \"Demo mode is OFF — real data is shown again.\",\n };\n },\n});\n"]}
|
package/dist/demo/config.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Demo mode gate.
|
|
3
3
|
*
|
|
4
|
-
* Demo mode replaces
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* keeps working. The redaction WALK (see ./redact.ts) is expensive on
|
|
8
|
-
* payloads, so callers MUST gate it behind this function and only walk
|
|
9
|
-
* returns true.
|
|
4
|
+
* Demo mode replaces email addresses and numbers in every action result with
|
|
5
|
+
* deterministic fake data — for both the UI and what the agent sees — while
|
|
6
|
+
* preserving names, free text, labels, IDs, dates, URLs, and structure so the
|
|
7
|
+
* app keeps working. The redaction WALK (see ./redact.ts) is expensive on
|
|
8
|
+
* large payloads, so callers MUST gate it behind this function and only walk
|
|
9
|
+
* when it returns true.
|
|
10
10
|
*
|
|
11
11
|
* This gate itself is intentionally cheap:
|
|
12
12
|
* - An env-forced deployment (a hosted demo site) short-circuits with zero
|
package/dist/demo/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/demo/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAEtE,MAAM,MAAM,GAAG,KAAK,CAAC;AACrB,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0C,CAAC;AAEhE,oEAAoE;AACpE,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,MAAM,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,gBAAgB,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,CAAC;QACH,IAAI,UAAU,GAAG,GAAG,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,EAAE,mBAAmB,EAAE,GAC3B,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YAC/C,UAAU,GAAG,mBAAmB,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,GAAG,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,CAAC,EAAE,GAAG,MAAM;YAAE,OAAO,GAAG,CAAC,KAAK,CAAC;QACnD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;QACxC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QACnD,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC","sourcesContent":["/**\n * Demo mode gate.\n *\n * Demo mode replaces
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/demo/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAEtE,MAAM,MAAM,GAAG,KAAK,CAAC;AACrB,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0C,CAAC;AAEhE,oEAAoE;AACpE,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,MAAM,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,gBAAgB,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,CAAC;QACH,IAAI,UAAU,GAAG,GAAG,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,EAAE,mBAAmB,EAAE,GAC3B,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YAC/C,UAAU,GAAG,mBAAmB,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,GAAG,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,CAAC,EAAE,GAAG,MAAM;YAAE,OAAO,GAAG,CAAC,KAAK,CAAC;QACnD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;QACxC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QACnD,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC","sourcesContent":["/**\n * Demo mode gate.\n *\n * Demo mode replaces email addresses and numbers in every action result with\n * deterministic fake data — for both the UI and what the agent sees — while\n * preserving names, free text, labels, IDs, dates, URLs, and structure so the\n * app keeps working. The redaction WALK (see ./redact.ts) is expensive on\n * large payloads, so callers MUST gate it behind this function and only walk\n * when it returns true.\n *\n * This gate itself is intentionally cheap:\n * - An env-forced deployment (a hosted demo site) short-circuits with zero\n * I/O — `DEMO_MODE=true`.\n * - The per-user runtime toggle lives in `application_state` under the\n * `demo-mode` key (`{ enabled: boolean }`), written by the settings UI and\n * the `toggle-demo-mode` agent action. It's read behind a short in-process\n * TTL cache keyed by user, so a tight agent tool-call loop doesn't hit the\n * DB on every result.\n */\nimport { readAppState } from \"../application-state/script-helpers.js\";\n\nconst TTL_MS = 3_000;\nconst cache = new Map<string, { value: boolean; at: number }>();\n\n/** Deployment-wide force (hosted demo site). Zero cost — no I/O. */\nexport function isDemoModeForced(): boolean {\n return process.env.DEMO_MODE === \"true\";\n}\n\n/**\n * Whether demo-mode redaction should run for the current request/user.\n * Cheap by design — safe to call before every action result; the expensive\n * walk only happens when this is true.\n */\nexport async function isDemoModeEnabled(): Promise<boolean> {\n if (isDemoModeForced()) return true;\n try {\n let sessionKey = \"_\";\n try {\n const { getRequestUserEmail } =\n await import(\"../server/request-context.js\");\n sessionKey = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL ?? \"_\";\n } catch {\n // request-context unavailable (CLI / non-server) — use default key\n }\n const now = Date.now();\n const hit = cache.get(sessionKey);\n if (hit && now - hit.at < TTL_MS) return hit.value;\n const state = await readAppState(\"demo-mode\");\n const enabled = state?.enabled === true;\n cache.set(sessionKey, { value: enabled, at: now });\n return enabled;\n } catch {\n // No request context / DB unavailable — fail closed (no redaction).\n return false;\n }\n}\n"]}
|
package/dist/demo/redact.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure, dependency-free, deterministic demo-mode redactor.
|
|
3
3
|
*
|
|
4
|
-
* Replaces sensitive values (
|
|
4
|
+
* Replaces sensitive values (emails and free numbers) with stable fake
|
|
5
5
|
* substitutes so a demo looks coherent — the same input always maps to the
|
|
6
6
|
* same fake. Crucially, it NEVER rewrites identifiers, structural tokens, or
|
|
7
|
-
* timestamps
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* timestamps. Names and other free text are deliberately left alone because
|
|
8
|
+
* guessing whether arbitrary text is a person's name is too inaccurate. The
|
|
9
|
+
* string redactor uses a protect-first strategy (mask IDs with opaque
|
|
10
|
+
* placeholders before any transform runs, restore them byte-identical
|
|
11
|
+
* afterwards), and the structure-aware walker additionally protects leaf
|
|
12
|
+
* values by key name.
|
|
11
13
|
*/
|
|
12
14
|
export interface RedactOptions {
|
|
13
15
|
salt?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/demo/redact.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/demo/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAghBD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAE3E;AAsGD,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,CAAC,CAGnE;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAGrD"}
|
package/dist/demo/redact.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure, dependency-free, deterministic demo-mode redactor.
|
|
3
3
|
*
|
|
4
|
-
* Replaces sensitive values (
|
|
4
|
+
* Replaces sensitive values (emails and free numbers) with stable fake
|
|
5
5
|
* substitutes so a demo looks coherent — the same input always maps to the
|
|
6
6
|
* same fake. Crucially, it NEVER rewrites identifiers, structural tokens, or
|
|
7
|
-
* timestamps
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* timestamps. Names and other free text are deliberately left alone because
|
|
8
|
+
* guessing whether arbitrary text is a person's name is too inaccurate. The
|
|
9
|
+
* string redactor uses a protect-first strategy (mask IDs with opaque
|
|
10
|
+
* placeholders before any transform runs, restore them byte-identical
|
|
11
|
+
* afterwards), and the structure-aware walker additionally protects leaf
|
|
12
|
+
* values by key name.
|
|
11
13
|
*/
|
|
12
14
|
/* ------------------------------------------------------------------ *
|
|
13
15
|
* Seeded hash + PRNG (xmur3 seed → mulberry32 stream)
|
|
@@ -56,7 +58,7 @@ function pick(rng, pool) {
|
|
|
56
58
|
* round-trips back through redaction (e.g. you edit a draft that's
|
|
57
59
|
* already showing fake text, it autosaves, then refetches) it is passed
|
|
58
60
|
* through UNCHANGED instead of being re-faked into something new. This
|
|
59
|
-
* is what stops
|
|
61
|
+
* is what stops emails drifting on every edit.
|
|
60
62
|
*
|
|
61
63
|
* Leak-free by construction: no timers, a hard size cap, and lazy TTL purge
|
|
62
64
|
* on write. Works the same per-tab in the browser and per-process on the
|
|
@@ -223,14 +225,6 @@ const LAST_NAMES = [
|
|
|
223
225
|
/* ------------------------------------------------------------------ *
|
|
224
226
|
* Fake value generators (deterministic in value + salt)
|
|
225
227
|
* ------------------------------------------------------------------ */
|
|
226
|
-
function fakeName(original, salt) {
|
|
227
|
-
return memoFake("name", original, salt, () => {
|
|
228
|
-
const rng = seededRng(`name:${original}`, salt);
|
|
229
|
-
const first = pick(rng, FIRST_NAMES);
|
|
230
|
-
const last = pick(rng, LAST_NAMES);
|
|
231
|
-
return `${first} ${last}`;
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
228
|
// Realistic-looking but safe stand-in domains: real consumer providers (the
|
|
235
229
|
// local part is fake, so no real mailbox is implied) plus the canonical
|
|
236
230
|
// reserved fictional-company domains (Contoso/Fabrikam/Northwind), which read
|
|
@@ -427,9 +421,6 @@ function unprotect(text, restore) {
|
|
|
427
421
|
* Transforms (run only on protected text)
|
|
428
422
|
* ------------------------------------------------------------------ */
|
|
429
423
|
const EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
|
|
430
|
-
// 2+ capitalized words (each starts uppercase, allows internal lowercase /
|
|
431
|
-
// apostrophes / hyphens). Single-letter middle initials allowed: `Sarah J Connor`.
|
|
432
|
-
const FULL_NAME_RE = /\b[A-Z][a-zA-Z'’-]*(?:\s+[A-Z](?:[a-zA-Z'’-]*)?){1,3}\b/g;
|
|
433
424
|
// A standalone numeric token: optional currency + sign, digits with optional
|
|
434
425
|
// comma grouping and a single optional decimal part. Bounded so it is NOT
|
|
435
426
|
// adjacent to a letter (placeholders already removed letter-mixed tokens, but
|
|
@@ -438,9 +429,6 @@ const NUMBER_RE = /(^|[^A-Za-z0-9_])([$€£]?)([+-]?)(\d[\d,]*(?:\.\d+)?)(?![A-
|
|
|
438
429
|
function transformEmails(text, salt) {
|
|
439
430
|
return text.replace(EMAIL_RE, (match) => fakeEmail(match, salt));
|
|
440
431
|
}
|
|
441
|
-
function transformNames(text, salt) {
|
|
442
|
-
return text.replace(FULL_NAME_RE, (match) => fakeName(match, salt));
|
|
443
|
-
}
|
|
444
432
|
function isProbablyYear(digits) {
|
|
445
433
|
if (digits.length !== 4)
|
|
446
434
|
return false;
|
|
@@ -475,19 +463,17 @@ function transformNumbers(text, salt) {
|
|
|
475
463
|
/* ------------------------------------------------------------------ *
|
|
476
464
|
* Public: string redactor
|
|
477
465
|
* ------------------------------------------------------------------ */
|
|
478
|
-
function redactDemoStringInternal(text, salt
|
|
466
|
+
function redactDemoStringInternal(text, salt) {
|
|
479
467
|
if (typeof text !== "string" || text.length === 0)
|
|
480
468
|
return text;
|
|
481
469
|
const { text: masked, restore } = protect(text);
|
|
482
470
|
let out = masked;
|
|
483
471
|
out = transformEmails(out, salt);
|
|
484
|
-
if (redactNames)
|
|
485
|
-
out = transformNames(out, salt);
|
|
486
472
|
out = transformNumbers(out, salt);
|
|
487
473
|
return unprotect(out, restore);
|
|
488
474
|
}
|
|
489
475
|
export function redactDemoString(text, opts) {
|
|
490
|
-
return redactDemoStringInternal(text, opts?.salt ?? ""
|
|
476
|
+
return redactDemoStringInternal(text, opts?.salt ?? "");
|
|
491
477
|
}
|
|
492
478
|
/* ------------------------------------------------------------------ *
|
|
493
479
|
* Public: structure-aware redactor
|
|
@@ -495,29 +481,11 @@ export function redactDemoString(text, opts) {
|
|
|
495
481
|
// Keys whose leaf values must NEVER be transformed (still recurse into nested
|
|
496
482
|
// objects/arrays under them). Besides ids/urls/timestamps this also covers
|
|
497
483
|
// code/query-bearing keys (`sql`, `query`, `expression`, `formula`, `code`):
|
|
498
|
-
//
|
|
499
|
-
//
|
|
500
|
-
//
|
|
501
|
-
// RESULTS are what get redacted so the chart still shows fake values.
|
|
484
|
+
// redacting a SQL string mutates literals and can make the query semantically
|
|
485
|
+
// wrong or invalid. The query must run untouched; its RESULTS are what get
|
|
486
|
+
// redacted so the chart still shows fake values.
|
|
502
487
|
const PROTECTED_KEY_RE = /^id$|(^|_)id$|Id$|Ids$|uuid|guid|slug|token|secret|password|passwd|apikey|api_key|hash|sha\d*|etag|cursor|nonce|sessionid|messageid|threadid|nodeid|(^|_)key$|keyid|(^|_)ref$|url$|uri$|href$|src$|path$|filename$|mimetype|mime|^sql$|sql$|query|expression|formula|^code$|createdat|updatedat|deletedat|expiresat|timestamp|.+at$|.+_at$/i;
|
|
503
|
-
// UI labels and chart/dashboard titles often look like person names ("Maya
|
|
504
|
-
// Davis (First-party)", "Clicks by Henry Moore") but are structural labels. Keep
|
|
505
|
-
// them stable while still redacting free-text and contact-style person fields.
|
|
506
|
-
const LABEL_TEXT_KEY_RE = /^(name|title|label)$/i;
|
|
507
488
|
const MAX_DEPTH = 64;
|
|
508
|
-
function isStandalonePersonNameLabel(text) {
|
|
509
|
-
const trimmed = text.trim();
|
|
510
|
-
if (!trimmed)
|
|
511
|
-
return false;
|
|
512
|
-
return /^[A-Z][a-zA-Z'’-]+(?:\s+[A-Z]\.?)?\s+[A-Z][a-zA-Z'’-]+$/.test(trimmed);
|
|
513
|
-
}
|
|
514
|
-
function shouldRedactNamesForChild(key, entry) {
|
|
515
|
-
if (!LABEL_TEXT_KEY_RE.test(key))
|
|
516
|
-
return true;
|
|
517
|
-
// Preserve structural labels/titles, but do not let common contact-shaped
|
|
518
|
-
// fields like `{ name: "Olivia Parker" }` leak real person names.
|
|
519
|
-
return typeof entry === "string" ? isStandalonePersonNameLabel(entry) : true;
|
|
520
|
-
}
|
|
521
489
|
function isPlainObject(value) {
|
|
522
490
|
if (value === null || typeof value !== "object")
|
|
523
491
|
return false;
|
|
@@ -528,9 +496,6 @@ function isPlainObject(value) {
|
|
|
528
496
|
const proto = Object.getPrototypeOf(value);
|
|
529
497
|
return proto === Object.prototype || proto === null;
|
|
530
498
|
}
|
|
531
|
-
function redactDemoStringWithSalt(text, salt, redactNames) {
|
|
532
|
-
return redactDemoStringInternal(text, salt, redactNames);
|
|
533
|
-
}
|
|
534
499
|
function redactNumberLeaf(value, salt) {
|
|
535
500
|
if (!Number.isFinite(value))
|
|
536
501
|
return value;
|
|
@@ -545,14 +510,14 @@ function redactNumberLeaf(value, salt) {
|
|
|
545
510
|
return value;
|
|
546
511
|
return n;
|
|
547
512
|
}
|
|
548
|
-
function walk(value, salt, depth, seen
|
|
513
|
+
function walk(value, salt, depth, seen) {
|
|
549
514
|
if (depth > MAX_DEPTH)
|
|
550
515
|
return value;
|
|
551
516
|
if (value === null || value === undefined)
|
|
552
517
|
return value;
|
|
553
518
|
const t = typeof value;
|
|
554
519
|
if (t === "string") {
|
|
555
|
-
return
|
|
520
|
+
return redactDemoStringInternal(value, salt);
|
|
556
521
|
}
|
|
557
522
|
if (t === "number") {
|
|
558
523
|
return redactNumberLeaf(value, salt);
|
|
@@ -566,7 +531,7 @@ function walk(value, salt, depth, seen, redactNames) {
|
|
|
566
531
|
if (seen.has(value))
|
|
567
532
|
return value;
|
|
568
533
|
seen.add(value);
|
|
569
|
-
const out = value.map((item) => walk(item, salt, depth + 1, seen
|
|
534
|
+
const out = value.map((item) => walk(item, salt, depth + 1, seen));
|
|
570
535
|
seen.delete(value);
|
|
571
536
|
return out;
|
|
572
537
|
}
|
|
@@ -583,7 +548,7 @@ function walk(value, salt, depth, seen, redactNames) {
|
|
|
583
548
|
!(entry instanceof Date)) {
|
|
584
549
|
// Still recurse into nested structures, but the protected key does
|
|
585
550
|
// not transform its own leaf value.
|
|
586
|
-
out[key] = walk(entry, salt, depth + 1, seen
|
|
551
|
+
out[key] = walk(entry, salt, depth + 1, seen);
|
|
587
552
|
}
|
|
588
553
|
else {
|
|
589
554
|
// Leaf under a protected key: pass through completely untouched.
|
|
@@ -591,7 +556,7 @@ function walk(value, salt, depth, seen, redactNames) {
|
|
|
591
556
|
}
|
|
592
557
|
continue;
|
|
593
558
|
}
|
|
594
|
-
out[key] = walk(entry, salt, depth + 1, seen
|
|
559
|
+
out[key] = walk(entry, salt, depth + 1, seen);
|
|
595
560
|
}
|
|
596
561
|
seen.delete(value);
|
|
597
562
|
return out;
|
|
@@ -601,7 +566,7 @@ function walk(value, salt, depth, seen, redactNames) {
|
|
|
601
566
|
}
|
|
602
567
|
export function redactDemoData(value, opts) {
|
|
603
568
|
const salt = opts?.salt ?? "";
|
|
604
|
-
return walk(value, salt, 0, new WeakSet()
|
|
569
|
+
return walk(value, salt, 0, new WeakSet());
|
|
605
570
|
}
|
|
606
571
|
/**
|
|
607
572
|
* Clear the stable-mapping caches. Test-only — the caches are process-global
|