release: ship v1.5.0 with on-device writing suggestions
Some checks failed
deploy-site / deploy (push) Failing after 33s
portable-unsigned / portable-windows (push) Failing after 4m7s
release / release-windows (push) Failing after 3m16s

Adds next-sentence suggestions while typing, weekly input insights and a
personal phrase memory to the desktop app, and fixes custom instructions so
they process the text instead of inserting the instruction's own wording.
Local model requests are now bounded and individually cancellable.

Bumps the product version to 1.5.0 (Android/iOS build 1050000), refreshes the
landing and web download links, and records the new INPUT feature rows and the
open verification gaps in the infrastructure map.
This commit is contained in:
Yun Chan 2026-09-23 16:04:27 +09:00
parent 99f06c253c
commit 5c11ee2fde
104 changed files with 14410 additions and 174 deletions

View file

@ -882,6 +882,114 @@ const electronAPI = {
getSubscriptionStatus: () =>
invoke<import('@d3ro/core/types').SubscriptionStatusResult>(IPC_CHANNELS.PAYMENT.GET_SUBSCRIPTION_STATUS),
},
// ── Input telemetry (입력 수집 동의 · 리포트) ───────────
inputTelemetry: {
getState: () =>
invoke<import('@d3ro/core/input-intelligence').InputTelemetryState>(
IPC_CHANNELS.INPUT_TELEMETRY.GET_STATE
),
setEnabled: (params: { enabled: boolean }) =>
invoke<import('@d3ro/core/input-intelligence').InputTelemetryState>(
IPC_CHANNELS.INPUT_TELEMETRY.SET_ENABLED,
params
),
setPaused: (params: { paused: boolean }) =>
invoke<import('@d3ro/core/input-intelligence').InputTelemetryState>(
IPC_CHANNELS.INPUT_TELEMETRY.SET_PAUSED,
params
),
getSummary: (params?: { days?: number }) =>
invoke<import('@d3ro/core/input-intelligence').InputInsightsSummary>(
IPC_CHANNELS.INPUT_TELEMETRY.GET_SUMMARY,
params
),
getPrivacyReceipt: () =>
invoke<import('@d3ro/core/input-intelligence').InputPrivacyReceipt>(
IPC_CHANNELS.INPUT_TELEMETRY.GET_PRIVACY_RECEIPT
),
getPhrases: (params?: { limit?: number }) =>
invoke<import('@d3ro/core/input-intelligence').PersonalPhrase[]>(
IPC_CHANNELS.INPUT_TELEMETRY.GET_PHRASES,
params
),
deletePhrase: (params: { id: string }) =>
invoke<boolean>(IPC_CHANNELS.INPUT_TELEMETRY.DELETE_PHRASE, params),
clearAll: () => invoke<void>(IPC_CHANNELS.INPUT_TELEMETRY.CLEAR_ALL),
getGraph: () =>
invoke<import('@d3ro/core/personal-graph').PersonalGraphStats>(
IPC_CHANNELS.INPUT_TELEMETRY.GET_GRAPH
),
queryGraph: (params: { text: string; limit?: number }) =>
invoke<import('@d3ro/core/personal-graph').PersonalGraphQuery>(
IPC_CHANNELS.INPUT_TELEMETRY.QUERY_GRAPH,
params
),
onStateChanged: (
cb: (state: import('@d3ro/core/input-intelligence').InputTelemetryState) => void
): Unsubscribe => on(IPC_CHANNELS.INPUT_TELEMETRY.STATE_CHANGED, cb),
onActivity: (
cb: (payload: {
totals: import('@d3ro/core/input-intelligence').InputActivityBucket
appName: string | null
}) => void
): Unsubscribe => on(IPC_CHANNELS.INPUT_TELEMETRY.ACTIVITY, cb),
},
// ── 다음 문장 제안 (ghost text) ────────────────────────
suggestion: {
getState: () =>
invoke<import('@d3ro/core/input-intelligence').SuggestionState>(
IPC_CHANNELS.SUGGESTION.GET_STATE
),
setConfig: (params: {
enabled?: boolean
modelId?: string | null
triggerDelayMs?: number
minPrefixChars?: number
maxRequestsPerMinute?: number
dailyBudget?: number
overlayInteractive?: boolean
learnTypedText?: boolean
excludedApps?: string[]
requestTimeoutMs?: number
}) =>
invoke<import('@d3ro/core/input-intelligence').SuggestionState>(
IPC_CHANNELS.SUGGESTION.SET_CONFIG,
params
),
requestNow: () => invoke<{ ok: boolean; reason?: string }>(IPC_CHANNELS.SUGGESTION.REQUEST_NOW),
accept: (params?: { index?: number }) =>
invoke<{ ok: boolean; reason?: string }>(IPC_CHANNELS.SUGGESTION.ACCEPT, params),
next: () =>
invoke<import('@d3ro/core/input-intelligence').SuggestionState>(
IPC_CHANNELS.SUGGESTION.NEXT
),
prev: () =>
invoke<import('@d3ro/core/input-intelligence').SuggestionState>(
IPC_CHANNELS.SUGGESTION.PREV
),
dismiss: () => invoke<void>(IPC_CHANNELS.SUGGESTION.DISMISS),
getHistory: (params?: { limit?: number }) =>
invoke<
Array<{
id: string
appName: string | null
prefixText: string
suggestionText: string
model: string | null
latencyMs: number | null
accepted: boolean
createdAt: number
}>
>(IPC_CHANNELS.SUGGESTION.GET_HISTORY, params),
onUpdated: (cb: (state: import('@d3ro/core/input-intelligence').SuggestionState) => void): Unsubscribe =>
on(IPC_CHANNELS.SUGGESTION.UPDATED, cb),
onCleared: (cb: (payload: { reason: string }) => void): Unsubscribe =>
on(IPC_CHANNELS.SUGGESTION.CLEARED, cb),
onStateChanged: (cb: (state: import('@d3ro/core/input-intelligence').SuggestionState) => void): Unsubscribe =>
on(IPC_CHANNELS.SUGGESTION.STATE_CHANGED, cb),
},
} as const
contextBridge.exposeInMainWorld('electronAPI', electronAPI)