clauderipple 0.9.5 → 0.11.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/CHANGELOG.md +118 -0
- package/README.es.md +45 -0
- package/README.ja.md +17 -0
- package/README.ko.md +31 -0
- package/README.md +70 -0
- package/README.pt-BR.md +45 -0
- package/README.zh-CN.md +17 -0
- package/dist/app/assets/icon.icns +0 -0
- package/dist/app/assets/icon.ico +0 -0
- package/dist/app/assets/icon.png +0 -0
- package/dist/app/assets/trayDirectTemplate.png +0 -0
- package/dist/app/assets/trayDirectTemplate@2x.png +0 -0
- package/dist/app/assets/trayDownTemplate.png +0 -0
- package/dist/app/assets/trayDownTemplate@2x.png +0 -0
- package/dist/app/assets/trayTemplate.png +0 -0
- package/dist/app/assets/trayTemplate@2x.png +0 -0
- package/dist/app/assets/trayWarnTemplate.png +0 -0
- package/dist/app/assets/trayWarnTemplate@2x.png +0 -0
- package/dist/app/assets/trayWin.png +0 -0
- package/dist/app/assets/trayWin@2x.png +0 -0
- package/dist/app/assets/trayWinDirect.png +0 -0
- package/dist/app/assets/trayWinDirect@2x.png +0 -0
- package/dist/app/assets/trayWinDown.png +0 -0
- package/dist/app/assets/trayWinDown@2x.png +0 -0
- package/dist/app/assets/trayWinWarn.png +0 -0
- package/dist/app/assets/trayWinWarn@2x.png +0 -0
- package/dist/app/dist/claude-desktop.js +67 -0
- package/dist/app/dist/main.js +423 -110
- package/dist/app/dist/preload.js +21 -0
- package/dist/app/dist/protocol.js +121 -0
- package/dist/app/dist/status-model.js +87 -0
- package/dist/app/dist/window.js +133 -0
- package/dist/app/package.json +1 -1
- package/dist/cli/src/awake-setup.js +314 -0
- package/dist/cli/src/bundle.js +9 -5
- package/dist/cli/src/direct.js +159 -0
- package/dist/cli/src/doctor.js +205 -0
- package/dist/cli/src/hooks/agent-title.js +7 -4
- package/dist/cli/src/index.js +227 -31
- package/dist/cli/src/launchd.js +29 -20
- package/dist/cli/src/launcher.js +215 -0
- package/dist/cli/src/power.js +182 -0
- package/dist/cli/src/registration.js +157 -0
- package/dist/cli/src/remote.js +263 -0
- package/dist/cli/src/schtasks.js +50 -40
- package/dist/cli/src/settings.js +26 -1
- package/dist/cli/src/tray.js +5 -2
- package/dist/mod/hooks/i18n.ts +473 -227
- package/dist/mod/hooks/judge.ts +35 -17
- package/dist/mod/hooks/modes.ts +56 -1
- package/dist/mod/hooks/register.tsx +237 -32
- package/dist/mod/hooks/session.ts +102 -1
- package/dist/mod/hooks/settings.js +7 -3
- package/dist/mod/hooks/settings.ts +9 -4
- package/dist/mod/hooks/stats.ts +25 -1
- package/dist/mod/hooks/ui/agents.tsx +903 -79
- package/dist/mod/hooks/ui/alerts.tsx +20 -17
- package/dist/mod/hooks/ui/art.ts +33 -7
- package/dist/mod/hooks/ui/band.tsx +262 -81
- package/dist/mod/hooks/ui/flat.ts +265 -0
- package/dist/mod/hooks/ui/kit.tsx +70 -55
- package/dist/mod/hooks/ui/look.ts +129 -0
- package/dist/mod/hooks/ui/settings.tsx +71 -46
- package/dist/mod/hooks/ui/setup.tsx +15 -13
- package/dist/mod/hooks/ui/theme.ts +3 -0
- package/dist/mod/hooks/ui/tools.ts +124 -0
- package/dist/mod/hooks/ui/view.ts +120 -4
- package/dist/mod/hooks/workers.ts +33 -6
- package/dist/mod/tests/register.test.tsx +155 -11
- package/dist/mod/tests/ui.test.tsx +408 -27
- package/dist/mod/types/index.d.ts +66 -2
- package/dist/remote/package.json +28 -0
- package/dist/remote/src/away.js +85 -0
- package/dist/remote/src/bridge-client.js +336 -0
- package/dist/remote/src/composer-menu.js +11 -0
- package/dist/remote/src/config.js +102 -0
- package/dist/remote/src/desktop.js +1018 -0
- package/dist/remote/src/e2ee.js +126 -0
- package/dist/remote/src/e2ee.ts +126 -0
- package/dist/remote/src/eventlog.js +298 -0
- package/dist/remote/src/expo-push.js +127 -0
- package/dist/remote/src/folders.js +79 -0
- package/dist/remote/src/fsutil.js +39 -0
- package/dist/remote/src/handoff.js +38 -0
- package/dist/remote/src/host-service.js +168 -0
- package/dist/remote/src/images.js +215 -0
- package/dist/remote/src/local-control.js +138 -0
- package/dist/remote/src/main.js +264 -0
- package/dist/remote/src/permissions.js +124 -0
- package/dist/remote/src/power.js +76 -0
- package/dist/remote/src/processes.js +24 -0
- package/dist/remote/src/protocol.js +32 -0
- package/dist/remote/src/protocol.ts +284 -0
- package/dist/remote/src/push-content.js +32 -0
- package/dist/remote/src/push.js +134 -0
- package/dist/remote/src/receipts.js +111 -0
- package/dist/remote/src/relay.js +438 -0
- package/dist/remote/src/router.js +208 -0
- package/dist/remote/src/sdk-launcher.js +18 -0
- package/dist/remote/src/server.js +706 -0
- package/dist/remote/src/service.js +157 -0
- package/dist/remote/src/sessions.js +1800 -0
- package/dist/remote/src/sidebar-storage.js +211 -0
- package/dist/remote/src/sidebar.js +173 -0
- package/dist/remote/src/tool-details.js +205 -0
- package/dist/remote/src/tool-details.ts +153 -0
- package/dist/remote/src/worktree.js +99 -0
- package/dist/remote/web/app.ts +746 -0
- package/dist/remote/web/conn.ts +193 -0
- package/dist/remote/web/demo.ts +134 -0
- package/dist/remote/web/dom.ts +124 -0
- package/dist/remote/web/esc.ts +4 -0
- package/dist/remote/web/i18n.ts +374 -0
- package/dist/remote/web/icon.svg +1 -0
- package/dist/remote/web/index.html +24 -0
- package/dist/remote/web/manifest.webmanifest +10 -0
- package/dist/remote/web/mascot.ts +60 -0
- package/dist/remote/web/md.ts +78 -0
- package/dist/remote/web/notify.ts +55 -0
- package/dist/remote/web/pushstate.ts +27 -0
- package/dist/remote/web/secure.ts +109 -0
- package/dist/remote/web/sidebar.ts +106 -0
- package/dist/remote/web/style.css +311 -0
- package/dist/remote/web/sw.ts +48 -0
- package/dist/remote/web/timeline.ts +224 -0
- package/dist/remote/web/views.ts +323 -0
- package/dist/router/src/admin.js +331 -5
- package/dist/router/src/awake-win.js +590 -0
- package/dist/router/src/awake.js +432 -0
- package/dist/router/src/config.js +94 -0
- package/dist/router/src/health.js +86 -3
- package/dist/router/src/hold.js +107 -0
- package/dist/router/src/index.js +108 -6
- package/dist/router/src/ingress/server.js +26 -4
- package/dist/router/src/ingress/translate.js +6 -2
- package/dist/router/src/phone.js +82 -0
- package/dist/router/src/power.js +107 -0
- package/dist/router/src/providers/anthropic-usage.js +33 -1
- package/dist/router/src/providers/google/antigravity.js +73 -10
- package/dist/router/src/providers/google/index.js +191 -14
- package/dist/router/src/providers/google/prompt-refusal.js +29 -0
- package/dist/router/src/providers/google/thoughtSignatures.js +13 -0
- package/dist/router/src/providers/google/transport.js +1 -1
- package/dist/router/src/providers/google/usage.js +302 -0
- package/dist/router/src/providers/grok/index.js +18 -0
- package/dist/router/src/providers/grok/usage.js +77 -0
- package/dist/router/src/providers/openai/translate.js +13 -2
- package/dist/router/src/providers/opencode-usage.js +116 -0
- package/dist/router/src/providers/retry.js +4 -1
- package/dist/router/src/proxy.js +371 -261
- package/dist/router/src/remote-host.js +320 -0
- package/dist/router/src/remote-tunnel.js +320 -0
- package/dist/router/src/requestlog.js +48 -39
- package/dist/router/src/tether-win.js +211 -0
- package/dist/router/src/tether.js +712 -0
- package/dist/router/src/usage-history.js +227 -0
- package/dist/router/src/version.js +1 -1
- package/dist/ui/app.js +1083 -59
- package/dist/ui/i18n.js +670 -69
- package/dist/ui/index.html +33 -6
- package/dist/ui/style.css +177 -0
- package/docs/ARCHITECTURE.md +402 -14
- package/package.json +8 -2
package/dist/mod/hooks/judge.ts
CHANGED
|
@@ -5,9 +5,15 @@ import type { Lang } from './i18n.ts'
|
|
|
5
5
|
|
|
6
6
|
const EFFORTS: readonly Effort[] = ['low', 'medium', 'high', 'xhigh', 'max']
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
// "xhigh for unusually difficult investigation, max only for the hardest open-ended problems" left
|
|
9
|
+
// a medium..max range at medium and high: 10-13..10-17 ran ~9,000 Opus requests with no max and 91
|
|
10
|
+
// xhigh, and Jev gave an architecture redesign 2% max (2026-10-19). Above high is now named by
|
|
11
|
+
// what hinges on judgment, so important plans and failed attempts can reach it.
|
|
12
|
+
export const EFFORT_JUDGE_SYSTEM = `Choose the reasoning effort this work deserves. This is a coding agent able to inspect files, run commands, and edit code, not merely answer a chat question.
|
|
13
|
+
Assess work volume, uncertainty, and the cost of mistakes, not message length. A short choice approving a build inherits the size of that build. Closing remarks need little effort. "Think hard" or thorough reasoning requires at least high; an explicit quick answer calls for low.
|
|
14
|
+
Low and medium are only for turns that need no judgment: low for chit-chat, thanks, or a direct answer needing no inspection; medium for one fully specified, low-risk step the user spelled out (run this command, rename this). Ordinary coding that asks the agent to decide, explain why, review, verify, debug with a known direction, delegate, or change more than one thing is high.
|
|
15
|
+
Go above high when the outcome hinges on judgment rather than labor. xhigh: debugging whose cause is unknown, changes across interacting modules, or planning a feature. max: decisions that shape the product or system (architecture, an important plan or strategy, a design meant to last), work where a wrong call risks security, money, or data loss, and problems that earlier attempts in this conversation failed to solve. Not every plan is max; a small or routine plan is high or xhigh.
|
|
16
|
+
When the user says the previous attempt failed, is wrong, or still does not work, choose at least one level above the running effort. Other corrections and steering keep at least the running effort. Consider the current model's strength.
|
|
11
17
|
Return only JSON {"effort":"low|medium|high|xhigh|max","sure":0.0,"why":"short reason"}. Confidence is between zero and one. The reason uses the user's language and at most six words.`
|
|
12
18
|
|
|
13
19
|
/** A terse continuation usually carries no new scope; answers to questions are handled separately. */
|
|
@@ -16,6 +22,11 @@ export function isShortFollowUp(text: string): boolean {
|
|
|
16
22
|
return trimmed.length > 0 && trimmed.length <= 12 && trimmed.split(/\s+/).length <= 2
|
|
17
23
|
}
|
|
18
24
|
|
|
25
|
+
/** "Still broken" is short but asks for more thought, so it is judged rather than inheriting the effort that failed. */
|
|
26
|
+
export function looksLikeRetry(text: string): boolean {
|
|
27
|
+
return /안\s*[돼되]|다시|틀렸|아직|여전|그대로|실패|\bstill\b|\bagain\b|\bwrong\b|\bbroken\b|n['’]?t work|\bfail/i.test(text)
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
export function looksLikeQuestion(assistantTail: string): boolean {
|
|
20
31
|
return assistantTail.slice(-400).includes('?')
|
|
21
32
|
}
|
|
@@ -28,7 +39,7 @@ export function shouldJudge(input: {
|
|
|
28
39
|
if (!input.auto || !['composer', 'bridge', 'sdk'].includes(input.origin) || (!input.text.trim() && !input.attachments?.length) || input.hostCommand) return false
|
|
29
40
|
if (input.modelId !== undefined && !isCacheSafeModel(input.modelId)) return false
|
|
30
41
|
const followup = input.current && input.current.by !== 'manual' && !input.text.trim().startsWith('/') &&
|
|
31
|
-
!input.attachments?.length && isShortFollowUp(input.text) && !looksLikeQuestion(input.assistantTail ?? '')
|
|
42
|
+
!input.attachments?.length && isShortFollowUp(input.text) && !looksLikeRetry(input.text) && !looksLikeQuestion(input.assistantTail ?? '')
|
|
32
43
|
return !followup
|
|
33
44
|
}
|
|
34
45
|
|
|
@@ -110,16 +121,19 @@ function looseVerdictObject(text: string): Record<string, unknown> | undefined {
|
|
|
110
121
|
}
|
|
111
122
|
|
|
112
123
|
const effortCriteria = {
|
|
113
|
-
low: '
|
|
114
|
-
medium: '
|
|
115
|
-
high: '
|
|
116
|
-
xhigh: '
|
|
117
|
-
max: '
|
|
118
|
-
}
|
|
124
|
+
low: 'Chit-chat, thanks, or a direct answer needing no inspection.',
|
|
125
|
+
medium: 'One fully specified, low-risk step the user spelled out.',
|
|
126
|
+
high: 'Ordinary coding: implement, fix, review, or debug with a known direction.',
|
|
127
|
+
xhigh: 'Debugging with an unknown cause, changes across interacting modules, or planning a feature.',
|
|
128
|
+
max: 'Product or architecture decisions, important plans or strategy, security or data-loss risk, or a problem earlier attempts failed to solve.',
|
|
129
|
+
}
|
|
130
|
+
// Read with the brief, the old wording sent 49 of 64 delegated tasks to deep, against 19 from their
|
|
131
|
+
// one-line descriptions alone: a brief's warnings ("do not restart", "read-only", "no guessing")
|
|
132
|
+
// read as high stakes. Re-judged with this wording the same briefs give 28 (2026-10-15, pick log).
|
|
119
133
|
const levelCriteria = {
|
|
120
|
-
light: 'Mechanical chores, repeated
|
|
121
|
-
standard: '
|
|
122
|
-
deep: '
|
|
134
|
+
light: 'Mechanical chores, repeated edits, simple lookups, or one small fix.',
|
|
135
|
+
standard: 'Carry out a designed change, even across several files; research, summarize, or review read-only.',
|
|
136
|
+
deep: 'Subtle debugging, security review, or architecture where a wrong call is costly. Size, file count, or warnings and prohibitions in the brief do not by themselves make work deep.',
|
|
123
137
|
}
|
|
124
138
|
const domainCriteria: Record<Domain, string> = {
|
|
125
139
|
design: 'Visual composition, branding, taste, look and voice of copy.',
|
|
@@ -188,10 +202,14 @@ export function parseJevWorker(json: unknown): WorkerVerdict | undefined {
|
|
|
188
202
|
const effortAnswer = record(reply?.effort)
|
|
189
203
|
const selectedEffort = effort(effortAnswer?.choice)
|
|
190
204
|
if (!domainAnswer || !DOMAINS.includes(domainAnswer.choice as Domain) || !levelAnswer || !LEVELS.includes(levelAnswer.choice as Level) || !effortAnswer || !selectedEffort) return undefined
|
|
191
|
-
// Confidence moves a task up the ladder, so it is the level's question that counts
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
205
|
+
// Confidence moves a task up the ladder, so it is the level's question that counts. The lowest of
|
|
206
|
+
// all three counted before: torn only between frontend and backend, or high and xhigh, a task
|
|
207
|
+
// judged standard was sent a rung up (4 of 16 standard verdicts, pick log 2026-10-12..15).
|
|
208
|
+
const kindAnswer = record(reply?.kind)
|
|
209
|
+
const kind = kindOf(kindAnswer?.choice) ?? 'do'
|
|
210
|
+
const odds = { domain: answerSure(domainAnswer), level: answerSure(levelAnswer), kind: kindAnswer ? answerSure(kindAnswer) : undefined, effort: answerSure(effortAnswer) }
|
|
211
|
+
const known = Object.fromEntries(Object.entries(odds).filter(([, score]) => score !== undefined)) as WorkerVerdict['odds']
|
|
212
|
+
return { domain: domainAnswer.choice as Domain, level: levelAnswer.choice as Level, kind, effort: selectedEffort, ...(odds.level !== undefined ? { sure: odds.level } : {}), ...(Object.keys(known!).length ? { odds: known } : {}), why: '' }
|
|
195
213
|
}
|
|
196
214
|
|
|
197
215
|
export function jevUsage(json: unknown): number {
|
package/dist/mod/hooks/modes.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Operating modes in the session (docs/specs/2026-10-12-worker-tiers.md "Operating modes"): which
|
|
2
2
|
// mode is on, when it ends by itself, and the eager-delegation note. Pure; register.tsx wires them.
|
|
3
3
|
|
|
4
|
-
import type { Hot, Mode, Settings } from '../types'
|
|
4
|
+
import type { Hot, LimitItem, Mode, Settings } from '../types'
|
|
5
5
|
|
|
6
6
|
/** The mode that is on, if the settings name one that exists. */
|
|
7
7
|
export function activeModeOf(s: Pick<Settings, 'modes' | 'activeMode'>): Mode | undefined {
|
|
@@ -91,3 +91,58 @@ export function modeOver(mode: Pick<Mode, 'until'>, since: number | undefined, n
|
|
|
91
91
|
const passed = (at: number) => at > since && at <= now
|
|
92
92
|
return windows.some(w => passed(w.at) || (w.windowMs !== undefined && passed(w.at - w.windowMs)))
|
|
93
93
|
}
|
|
94
|
+
|
|
95
|
+
/** The configured providers of ChatGPT type, from GET /api/status `providers` (name → {type}). */
|
|
96
|
+
export function chatgptProviders(status: unknown): string[] {
|
|
97
|
+
const providers = record(status).providers
|
|
98
|
+
if (!providers || typeof providers !== 'object' || Array.isArray(providers)) return []
|
|
99
|
+
return Object.entries(providers as Record<string, unknown>)
|
|
100
|
+
.filter(([, value]) => record(value).type === 'chatgpt')
|
|
101
|
+
.map(([name]) => name)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Every signed-in ChatGPT account's known windows as the limits row reads them, from GET
|
|
106
|
+
* /api/chatgpt-accounts (`quota.rate_limits.{primary,secondary}` with `reset_at` in epoch
|
|
107
|
+
* seconds or ms, or `reset_after_seconds` from the snapshot's `at`, and `window_minutes`;
|
|
108
|
+
* the same shape `quotaWindows` reads). Paused and needs-login accounts are left out (and take
|
|
109
|
+
* no number), and so is an account with no snapshot. `account` numbers the accounts kept, in
|
|
110
|
+
* answer order. A snapshot is not aged out: the router takes it from the account's own replies,
|
|
111
|
+
* so an account idle for an hour holds an hour-old figure that is still right (measured
|
|
112
|
+
* 2026-10-15: 30 minutes old between uses). Only a window whose reset has passed is dropped,
|
|
113
|
+
* since its figure no longer stands.
|
|
114
|
+
*/
|
|
115
|
+
export function gptLimitsFrom(body: unknown, provider: string, now: number): LimitItem[] {
|
|
116
|
+
const accounts = record(body).accounts
|
|
117
|
+
if (!Array.isArray(accounts)) return []
|
|
118
|
+
const kept = accounts.map(record).filter(account => account.state !== 'paused' && account.state !== 'needs-login' && account.paused !== true)
|
|
119
|
+
const out: LimitItem[] = []
|
|
120
|
+
kept.forEach((account, index) => {
|
|
121
|
+
const quota = record(account.quota)
|
|
122
|
+
const at = quota.at
|
|
123
|
+
if (typeof at !== 'number') return
|
|
124
|
+
const limits = record(quota.rate_limits)
|
|
125
|
+
for (const key of ['primary', 'secondary']) {
|
|
126
|
+
const window = record(limits[key])
|
|
127
|
+
const used = window.used_percent
|
|
128
|
+
if (typeof used !== 'number' || !Number.isFinite(used)) continue
|
|
129
|
+
const minutes = window.window_minutes
|
|
130
|
+
const resetAt = typeof window.reset_at === 'number' ? (window.reset_at > 1e12 ? window.reset_at : window.reset_at * 1000)
|
|
131
|
+
: typeof window.reset_after_seconds === 'number' && typeof at === 'number' ? at + window.reset_after_seconds * 1000 : NaN
|
|
132
|
+
if (Number.isFinite(resetAt) && resetAt <= now) continue
|
|
133
|
+
const kind = minutes === 300 ? 'five_hour' : minutes === 10080 ? 'seven_day' : 'window'
|
|
134
|
+
out.push({
|
|
135
|
+
provider,
|
|
136
|
+
type: 'chatgpt',
|
|
137
|
+
title: 'GPT',
|
|
138
|
+
account: index,
|
|
139
|
+
kind,
|
|
140
|
+
label: '',
|
|
141
|
+
...(typeof minutes === 'number' && minutes > 0 ? { windowMinutes: minutes } : {}),
|
|
142
|
+
percent: Math.round(used * 10) / 10,
|
|
143
|
+
...(Number.isFinite(resetAt) ? { resetsAt: new Date(resetAt).toISOString() } : {}),
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
return out
|
|
148
|
+
}
|