@agent-native/core-corpus 0.209.2 → 0.209.3-nightly-20261016183441
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 +1 -1
- package/corpus/templates/analytics/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/analytics/actions/update-dashboard.ts +9 -0
- package/corpus/templates/analytics/app/components/auth/SqlQuerySnapshotSessionBridge.tsx +25 -0
- package/corpus/templates/analytics/app/components/dashboard/PanelFreshnessClock.tsx +140 -0
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +104 -48
- package/corpus/templates/analytics/app/components/dashboard/panel-freshness.ts +171 -0
- package/corpus/templates/analytics/app/global.css +59 -0
- package/corpus/templates/analytics/app/i18n/en-US.ts +8 -0
- package/corpus/templates/analytics/app/lib/cost-tracker.ts +122 -16
- package/corpus/templates/analytics/app/lib/query-metrics.ts +50 -13
- package/corpus/templates/analytics/app/lib/sql-query-cache.ts +697 -0
- package/corpus/templates/analytics/app/lib/sql-query-freshness.ts +85 -0
- package/corpus/templates/analytics/app/lib/sql-query-snapshot-session.ts +145 -0
- package/corpus/templates/analytics/app/lib/sql-query.ts +366 -36
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +73 -18
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/filter-vars.ts +45 -12
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +5 -0
- package/corpus/templates/analytics/app/root.tsx +2 -0
- package/corpus/templates/analytics/changelog/2026-10-14-dashboard-charts-now-reappear-instantly-after-a-reload-from-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-14-dashboard-panels-show-fetch-time-in-a-clock-and-label-only-st.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-15-dashboard-query-costs-and-refresh-confirmations-reflect-actu.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-15-dashboard-results-disappear-when-access-is-withdrawn-and-exp.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-16-dashboard-freshness-stays-in-the-title-row-with-compact-upda.md +6 -0
- package/corpus/templates/analytics/changelog/2026-10-16-dashboard-update-status-remains-visible-for-sources-without-.md +6 -0
- package/corpus/templates/analytics/server/lib/bigquery.ts +35 -4
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +2 -3
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +9 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics-cache.ts +2 -2
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +4 -2
- package/corpus/templates/analytics/shared/sql-query-contract.ts +49 -0
- package/corpus/templates/assets/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/brain/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/calendar/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/chat/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/clips/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/content/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/crm/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/design/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +24 -0
- package/corpus/templates/design/app/components/design/types.ts +1 -0
- package/corpus/templates/design/app/lib/design-import.ts +35 -0
- package/corpus/templates/design/app/pages/design-editor/clone-and-pen-edit.ts +11 -0
- package/corpus/templates/design/app/pages/design-editor/command-types.ts +2 -0
- package/corpus/templates/design/app/pages/design-editor/commands/copy-selection.ts +3 -0
- package/corpus/templates/design/app/pages/design-editor/commands/get-selected-layer-snapshots.ts +19 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-selection.ts +118 -20
- package/corpus/templates/design/app/pages/design-editor/domains/use-editor-layer-actions.ts +15 -3
- package/corpus/templates/design/app/pages/design-editor/relative-position-offset.ts +109 -0
- package/corpus/templates/design/changelog/2026-10-15-dragged-layers-use-the-final-release-position.md +6 -0
- package/corpus/templates/design/changelog/2026-10-15-repeated-pastes-preserve-relative-layer-offsets.md +6 -0
- package/corpus/templates/design/changelog/2026-10-15-text-wrapping-hug-widths.md +6 -0
- package/corpus/templates/design/shared/code-layer.ts +2 -1
- package/corpus/templates/design/shared/relative-position-containing-block.ts +40 -0
- package/corpus/templates/dispatch/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/forms/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/mail/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/plan/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/slides/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +137 -118
- package/corpus/templates/slides/changelog/2026-10-16-search-and-preview-reference-decks-before-choosing-one.md +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { DataSourceType } from "@/pages/adhoc/sql-dashboard/types";
|
|
2
|
+
|
|
3
|
+
export type SqlQueryCacheStatus =
|
|
4
|
+
| "live"
|
|
5
|
+
| "app-cache"
|
|
6
|
+
| "provider-cache"
|
|
7
|
+
| "restored"
|
|
8
|
+
| "unknown";
|
|
9
|
+
|
|
10
|
+
export interface SqlQueryFreshness {
|
|
11
|
+
/** When the app received these rows; absent when the source did not say. */
|
|
12
|
+
fetchedAt?: string;
|
|
13
|
+
cache: SqlQueryCacheStatus;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SqlQueryFreshnessInput {
|
|
17
|
+
fetchedAt?: string;
|
|
18
|
+
cached?: boolean;
|
|
19
|
+
providerCacheHit?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* What a result can honestly say about its age. BigQuery always reports a
|
|
24
|
+
* fetch time and cache state, so a missing one is shown as unknown. Other
|
|
25
|
+
* sources report neither, and for them a missing value means "not applicable",
|
|
26
|
+
* so nothing is shown unless the result carries metadata or is a saved copy.
|
|
27
|
+
*/
|
|
28
|
+
export function describeSqlQueryFreshness(
|
|
29
|
+
result: SqlQueryFreshnessInput | undefined,
|
|
30
|
+
options: { source: DataSourceType; restored: boolean },
|
|
31
|
+
): SqlQueryFreshness | undefined {
|
|
32
|
+
if (!result) return undefined;
|
|
33
|
+
const { fetchedAt, cached, providerCacheHit } = result;
|
|
34
|
+
if (options.restored) return { fetchedAt, cache: "restored" };
|
|
35
|
+
const bigQuery = options.source === "bigquery";
|
|
36
|
+
if (
|
|
37
|
+
!bigQuery &&
|
|
38
|
+
fetchedAt === undefined &&
|
|
39
|
+
cached === undefined &&
|
|
40
|
+
providerCacheHit === undefined
|
|
41
|
+
) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
if (cached === true) return { fetchedAt, cache: "app-cache" };
|
|
45
|
+
if (providerCacheHit === true) return { fetchedAt, cache: "provider-cache" };
|
|
46
|
+
if (providerCacheHit === false || !bigQuery) {
|
|
47
|
+
return { fetchedAt, cache: "live" };
|
|
48
|
+
}
|
|
49
|
+
return { fetchedAt, cache: "unknown" };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A result older than this gets an inline age label on its panel; one exactly
|
|
54
|
+
* this old is still routine. The one place to change when the cutoff moves.
|
|
55
|
+
*/
|
|
56
|
+
export const STALE_RESULT_AGE_MS = 60 * 60 * 1000;
|
|
57
|
+
|
|
58
|
+
function fetchedAtMs(fetchedAt: string | undefined): number | undefined {
|
|
59
|
+
if (fetchedAt === undefined) return undefined;
|
|
60
|
+
const ms = Date.parse(fetchedAt);
|
|
61
|
+
return Number.isFinite(ms) ? ms : undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Whether a result is older than `STALE_RESULT_AGE_MS`. An unknown or
|
|
66
|
+
* unreadable fetch time is not stale: an age that cannot be known is never
|
|
67
|
+
* invented, and a fetch time in the future (a skewed clock) is not old.
|
|
68
|
+
*/
|
|
69
|
+
export function isStaleFetchTime(
|
|
70
|
+
fetchedAt: string | undefined,
|
|
71
|
+
now: number,
|
|
72
|
+
): boolean {
|
|
73
|
+
const fetched = fetchedAtMs(fetchedAt);
|
|
74
|
+
return fetched !== undefined && now - fetched > STALE_RESULT_AGE_MS;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Milliseconds until the result turns stale; undefined when it cannot. */
|
|
78
|
+
export function msUntilStale(
|
|
79
|
+
fetchedAt: string | undefined,
|
|
80
|
+
now: number,
|
|
81
|
+
): number | undefined {
|
|
82
|
+
const fetched = fetchedAtMs(fetchedAt);
|
|
83
|
+
if (fetched === undefined) return undefined;
|
|
84
|
+
return Math.max(0, fetched + STALE_RESULT_AGE_MS + 1 - now);
|
|
85
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { isSigningOut } from "@agent-native/core/client/hooks";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
dashboardCacheScope,
|
|
5
|
+
type DashboardCacheSession,
|
|
6
|
+
} from "./prefetch-keys";
|
|
7
|
+
import {
|
|
8
|
+
clearSqlQuerySnapshots,
|
|
9
|
+
readSqlQuerySnapshot,
|
|
10
|
+
removeSqlQuerySnapshot,
|
|
11
|
+
writeSqlQuerySnapshot,
|
|
12
|
+
type SqlQuerySnapshotClear,
|
|
13
|
+
type SqlQuerySnapshotInput,
|
|
14
|
+
type SqlQuerySnapshotRead,
|
|
15
|
+
type SqlQuerySnapshotWrite,
|
|
16
|
+
} from "./sql-query-cache";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Ties the saved SQL results to the signed-in account.
|
|
20
|
+
*
|
|
21
|
+
* The scope is module state rather than a hook ref because a late result can
|
|
22
|
+
* land after the component that asked for it is gone: sign-out unmounts the
|
|
23
|
+
* whole app shell, and a ref in an unmounted component would still hold the
|
|
24
|
+
* old scope. `undefined` means nothing has bound a scope yet and `null` means
|
|
25
|
+
* the session ended; both refuse writes.
|
|
26
|
+
*/
|
|
27
|
+
let boundScope: string | null | undefined;
|
|
28
|
+
|
|
29
|
+
export type SqlQuerySnapshotSessionStatus =
|
|
30
|
+
| "loading"
|
|
31
|
+
| "authenticated"
|
|
32
|
+
| "unauthenticated"
|
|
33
|
+
| "unavailable"
|
|
34
|
+
| "signing-out";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Called from a component mounted outside the session gate, since the gate
|
|
38
|
+
* unmounts everything under it before a sign-out reaches an effect there.
|
|
39
|
+
* Loading and unavailable are transient and change nothing, so a reload keeps
|
|
40
|
+
* the saved results it is about to restore.
|
|
41
|
+
*/
|
|
42
|
+
export function syncSqlQuerySnapshotsToSession(input: {
|
|
43
|
+
status: SqlQuerySnapshotSessionStatus;
|
|
44
|
+
session: DashboardCacheSession | null;
|
|
45
|
+
}): SqlQuerySnapshotClear | undefined {
|
|
46
|
+
if (input.status === "authenticated" && input.session) {
|
|
47
|
+
const accountScope = dashboardCacheScope(input.session);
|
|
48
|
+
boundScope = accountScope;
|
|
49
|
+
return warnIfNotCleared(
|
|
50
|
+
clearSqlQuerySnapshots({ exceptAccountScope: accountScope }),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
if (input.status === "unauthenticated" || input.status === "signing-out") {
|
|
54
|
+
boundScope = null;
|
|
55
|
+
return warnIfNotCleared(clearSqlQuerySnapshots());
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Whether a result fetched for `accountScope` may still be saved. */
|
|
61
|
+
export function canWriteSqlQuerySnapshot(accountScope: string): boolean {
|
|
62
|
+
return boundScope === accountScope && !isSigningOut();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function readSqlQuerySnapshotForSession(options: {
|
|
66
|
+
accountScope: string;
|
|
67
|
+
queryKey: string;
|
|
68
|
+
}): SqlQuerySnapshotRead {
|
|
69
|
+
const read = readSqlQuerySnapshot(options);
|
|
70
|
+
if (read.status === "unavailable") {
|
|
71
|
+
console.warn("[sql-query] saved results unavailable", {
|
|
72
|
+
reason: read.reason,
|
|
73
|
+
errorName: read.errorName,
|
|
74
|
+
});
|
|
75
|
+
} else if (read.status === "miss" && isUnexpectedMiss(read.reason)) {
|
|
76
|
+
console.warn("[sql-query] dropped an unusable saved result", {
|
|
77
|
+
reason: read.reason,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return read;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function removeSqlQuerySnapshotForSession(options: {
|
|
84
|
+
accountScope: string;
|
|
85
|
+
queryKey: string;
|
|
86
|
+
}): SqlQuerySnapshotClear {
|
|
87
|
+
return warnIfNotCleared(removeSqlQuerySnapshot(options));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function writeSqlQuerySnapshotForSession(options: {
|
|
91
|
+
accountScope: string;
|
|
92
|
+
queryKey: string;
|
|
93
|
+
result: SqlQuerySnapshotInput;
|
|
94
|
+
/** A query cancelled after its result arrived must not save it. */
|
|
95
|
+
signal?: AbortSignal;
|
|
96
|
+
}): SqlQuerySnapshotWrite | { status: "skipped"; reason: "session-changed" } {
|
|
97
|
+
if (
|
|
98
|
+
options.signal?.aborted ||
|
|
99
|
+
!canWriteSqlQuerySnapshot(options.accountScope)
|
|
100
|
+
) {
|
|
101
|
+
return { status: "skipped", reason: "session-changed" };
|
|
102
|
+
}
|
|
103
|
+
const write = writeSqlQuerySnapshot({
|
|
104
|
+
accountScope: options.accountScope,
|
|
105
|
+
queryKey: options.queryKey,
|
|
106
|
+
result: options.result,
|
|
107
|
+
});
|
|
108
|
+
if (write.status === "unavailable") {
|
|
109
|
+
console.warn("[sql-query] could not save the result", {
|
|
110
|
+
reason: write.reason,
|
|
111
|
+
errorName: write.errorName,
|
|
112
|
+
});
|
|
113
|
+
} else if (
|
|
114
|
+
write.status === "skipped" &&
|
|
115
|
+
(write.reason === "invalid-result" || write.reason === "invalid-fetched-at")
|
|
116
|
+
) {
|
|
117
|
+
console.warn("[sql-query] result not saved", { reason: write.reason });
|
|
118
|
+
}
|
|
119
|
+
return write;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Absent, expired and another account's copy are ordinary; the rest are not. */
|
|
123
|
+
function isUnexpectedMiss(reason: string): boolean {
|
|
124
|
+
return (
|
|
125
|
+
reason === "corrupt" ||
|
|
126
|
+
reason === "oversized" ||
|
|
127
|
+
reason === "truncated" ||
|
|
128
|
+
reason === "unsupported-version"
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function warnIfNotCleared(clear: SqlQuerySnapshotClear): SqlQuerySnapshotClear {
|
|
133
|
+
if (clear.status === "unavailable") {
|
|
134
|
+
console.warn("[sql-query] could not clear saved results", {
|
|
135
|
+
reason: clear.reason,
|
|
136
|
+
errorName: clear.errorName,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return clear;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** @internal test seam: forgets the bound scope between tests. */
|
|
143
|
+
export function resetSqlQuerySnapshotSessionForTests(): void {
|
|
144
|
+
boundScope = undefined;
|
|
145
|
+
}
|