pi-ui-extend 0.1.31 → 0.1.32
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/dist/app/model/model-usage-status.d.ts +1 -0
- package/dist/app/model/model-usage-status.js +49 -16
- package/external/pi-tools-suite/src/dcp/config.ts +8 -8
- package/external/pi-tools-suite/src/dcp/prompts.ts +5 -0
- package/external/pi-tools-suite/src/dcp/pruner-metadata.ts +2 -2
- package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +2 -2
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ export type ModelUsageDescriptor = BaseModelUsageDescriptor & ({
|
|
|
8
8
|
readonly kind: "google-antigravity";
|
|
9
9
|
readonly quotaModelKey: string;
|
|
10
10
|
readonly account: AntigravityQuotaAccount;
|
|
11
|
+
readonly accounts?: readonly AntigravityQuotaAccount[];
|
|
11
12
|
});
|
|
12
13
|
export type ModelUsageLimitWindow = {
|
|
13
14
|
readonly remainingPercent: number;
|
|
@@ -35,14 +35,16 @@ export function modelUsageDescriptor(model) {
|
|
|
35
35
|
}
|
|
36
36
|
if (ANTIGRAVITY_QUOTA_PROVIDERS.has(provider)) {
|
|
37
37
|
const quotaModelKey = resolveAntigravityQuotaModelKey(model);
|
|
38
|
-
const
|
|
38
|
+
const accounts = readAllAntigravityQuotaAccounts();
|
|
39
|
+
const account = readActiveAntigravityQuotaAccount(accounts);
|
|
39
40
|
if (!quotaModelKey || !account)
|
|
40
41
|
return undefined;
|
|
41
42
|
return {
|
|
42
43
|
kind: "google-antigravity",
|
|
43
|
-
modelKey: `${model.provider}/${model.id}
|
|
44
|
+
modelKey: `${model.provider}/${model.id}@all:${accounts.map((item) => item.cacheKey).join(",")}`,
|
|
44
45
|
quotaModelKey,
|
|
45
46
|
account,
|
|
47
|
+
accounts,
|
|
46
48
|
};
|
|
47
49
|
}
|
|
48
50
|
return undefined;
|
|
@@ -384,15 +386,9 @@ export function resolveAntigravityQuotaModelKey(model) {
|
|
|
384
386
|
return undefined;
|
|
385
387
|
}
|
|
386
388
|
export function googleAntigravityUsageStatusFromResponse(data, descriptor, now = Date.now()) {
|
|
387
|
-
const
|
|
388
|
-
if (!
|
|
389
|
+
const window = googleAntigravityWindowFromResponse(data, descriptor.quotaModelKey, now);
|
|
390
|
+
if (!window)
|
|
389
391
|
return undefined;
|
|
390
|
-
const resetAt = parseResetTime(quotaInfo.resetTime, now);
|
|
391
|
-
const window = {
|
|
392
|
-
remainingPercent: quotaRemainingPercent(quotaInfo),
|
|
393
|
-
resetAt,
|
|
394
|
-
windowSeconds: Math.max(0, Math.round((resetAt - now) / 1000)),
|
|
395
|
-
};
|
|
396
392
|
const weekly = window.windowSeconds >= DAY_SECONDS ? window : undefined;
|
|
397
393
|
const hourly = weekly ? undefined : window;
|
|
398
394
|
return {
|
|
@@ -404,10 +400,48 @@ export function googleAntigravityUsageStatusFromResponse(data, descriptor, now =
|
|
|
404
400
|
...(hourly ? { hourly } : {}),
|
|
405
401
|
};
|
|
406
402
|
}
|
|
403
|
+
function googleAntigravityWindowFromResponse(data, quotaModelKey, now) {
|
|
404
|
+
const quotaInfo = data.models[quotaModelKey]?.quotaInfo;
|
|
405
|
+
if (!quotaInfo)
|
|
406
|
+
return undefined;
|
|
407
|
+
const resetAt = parseResetTime(quotaInfo.resetTime, now);
|
|
408
|
+
return {
|
|
409
|
+
remainingPercent: quotaRemainingPercent(quotaInfo),
|
|
410
|
+
resetAt,
|
|
411
|
+
windowSeconds: Math.max(0, Math.round((resetAt - now) / 1000)),
|
|
412
|
+
};
|
|
413
|
+
}
|
|
407
414
|
async function queryGoogleAntigravityModelUsage(descriptor) {
|
|
408
415
|
const now = Date.now();
|
|
409
|
-
const
|
|
410
|
-
|
|
416
|
+
const accounts = descriptor.accounts?.length ? descriptor.accounts : [descriptor.account];
|
|
417
|
+
const windows = (await Promise.all(accounts.map(async (account) => {
|
|
418
|
+
try {
|
|
419
|
+
const response = await fetchGoogleAntigravityQuotaForAccount(account, now);
|
|
420
|
+
return googleAntigravityWindowFromResponse(response, descriptor.quotaModelKey, now);
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
return undefined;
|
|
424
|
+
}
|
|
425
|
+
}))).filter((window) => window !== undefined);
|
|
426
|
+
if (windows.length === 0)
|
|
427
|
+
return undefined;
|
|
428
|
+
const resetAt = Math.min(...windows.map((window) => window.resetAt));
|
|
429
|
+
const windowSeconds = Math.max(0, Math.round((resetAt - now) / 1000));
|
|
430
|
+
const aggregateWindow = {
|
|
431
|
+
remainingPercent: clampPercent(Math.round(windows.reduce((sum, window) => sum + window.remainingPercent, 0) / windows.length)),
|
|
432
|
+
resetAt,
|
|
433
|
+
windowSeconds,
|
|
434
|
+
};
|
|
435
|
+
const weekly = aggregateWindow.windowSeconds >= DAY_SECONDS ? aggregateWindow : undefined;
|
|
436
|
+
const hourly = weekly ? undefined : aggregateWindow;
|
|
437
|
+
return {
|
|
438
|
+
modelKey: descriptor.modelKey,
|
|
439
|
+
provider: "google-antigravity",
|
|
440
|
+
updatedAt: now,
|
|
441
|
+
accountEmail: "Σ",
|
|
442
|
+
...(weekly ? { weekly } : {}),
|
|
443
|
+
...(hourly ? { hourly } : {}),
|
|
444
|
+
};
|
|
411
445
|
}
|
|
412
446
|
const GOOGLE_ACCOUNT_QUOTA_WINDOWS = [
|
|
413
447
|
{ label: "Claude Opus", quotaModelKey: "claude-opus-4-6-thinking" },
|
|
@@ -440,8 +474,7 @@ async function queryGoogleAntigravityAccountUsage(now) {
|
|
|
440
474
|
}));
|
|
441
475
|
return results;
|
|
442
476
|
}
|
|
443
|
-
function readActiveAntigravityQuotaAccount() {
|
|
444
|
-
const accounts = readAllAntigravityQuotaAccounts();
|
|
477
|
+
function readActiveAntigravityQuotaAccount(accounts = readAllAntigravityQuotaAccounts()) {
|
|
445
478
|
const credential = readPiAuthSync().antigravity;
|
|
446
479
|
return accounts[clampAccountIndex(credential?.activeIndex, accounts.length)];
|
|
447
480
|
}
|
|
@@ -564,9 +597,9 @@ function googleQuotaResponseFromCachedQuota(cachedQuota, cachedQuotaUpdatedAt, n
|
|
|
564
597
|
return Object.keys(models).length > 0 ? { models } : undefined;
|
|
565
598
|
}
|
|
566
599
|
function addCachedQuotaModels(models, quota, quotaModelKeys, cachedQuotaUpdatedAt, now) {
|
|
567
|
-
if (!quota
|
|
600
|
+
if (!quota)
|
|
568
601
|
return;
|
|
569
|
-
const remainingFraction = quota.remainingFraction;
|
|
602
|
+
const remainingFraction = Number.isFinite(quota.remainingFraction) ? quota.remainingFraction : 0;
|
|
570
603
|
const resetTime = cachedQuotaResetTimeForDisplay(quota.resetTime, cachedQuotaUpdatedAt, now);
|
|
571
604
|
for (const quotaModelKey of quotaModelKeys) {
|
|
572
605
|
models[quotaModelKey] = {
|
|
@@ -24,8 +24,8 @@ export interface DcpConfig {
|
|
|
24
24
|
modelMaxContextLimits?: Record<string, number | string>
|
|
25
25
|
modelMinContextLimits?: Record<string, number | string>
|
|
26
26
|
summaryBuffer: boolean
|
|
27
|
-
nudgeFrequency: number // inject nudge every N context events (default:
|
|
28
|
-
iterationNudgeThreshold: number // nudge after N tool calls since last user msg (default:
|
|
27
|
+
nudgeFrequency: number // inject nudge every N context events (default: 2)
|
|
28
|
+
iterationNudgeThreshold: number // nudge after N tool calls since last user msg (default: 8)
|
|
29
29
|
nudgeForce: "strong" | "soft"
|
|
30
30
|
protectedTools: string[] // these tool outputs always protected from pruning
|
|
31
31
|
protectTags: boolean
|
|
@@ -81,27 +81,27 @@ const DEFAULT_CONFIG: DcpConfig = {
|
|
|
81
81
|
automaticStrategies: true,
|
|
82
82
|
},
|
|
83
83
|
compress: {
|
|
84
|
-
maxContextPercent: 0.
|
|
85
|
-
minContextPercent: 0.
|
|
84
|
+
maxContextPercent: 0.65,
|
|
85
|
+
minContextPercent: 0.25,
|
|
86
86
|
modelMaxContextPercent: {},
|
|
87
87
|
modelMinContextPercent: {},
|
|
88
88
|
summaryBuffer: true,
|
|
89
|
-
nudgeFrequency:
|
|
90
|
-
iterationNudgeThreshold:
|
|
89
|
+
nudgeFrequency: 2,
|
|
90
|
+
iterationNudgeThreshold: 8,
|
|
91
91
|
nudgeForce: "soft",
|
|
92
92
|
protectedTools: ["compress", "write", "edit"],
|
|
93
93
|
protectTags: false,
|
|
94
94
|
protectUserMessages: false,
|
|
95
95
|
autoCandidates: {
|
|
96
96
|
enabled: true,
|
|
97
|
-
minContextPercent: 0.
|
|
97
|
+
minContextPercent: 0.25,
|
|
98
98
|
keepRecentTurns: 2,
|
|
99
99
|
minMessages: 6,
|
|
100
100
|
minTokens: 1500,
|
|
101
101
|
},
|
|
102
102
|
messageMode: {
|
|
103
103
|
enabled: true,
|
|
104
|
-
minContextPercent: 0.
|
|
104
|
+
minContextPercent: 0.25,
|
|
105
105
|
keepRecentTurns: 2,
|
|
106
106
|
mediumTokens: 500,
|
|
107
107
|
highTokens: 5000,
|
|
@@ -174,6 +174,7 @@ You are at or beyond the configured max context threshold. This is an emergency
|
|
|
174
174
|
You MUST use the \`compress\` tool now. Do not continue normal exploration until compression is handled.
|
|
175
175
|
|
|
176
176
|
If you are in the middle of a critical atomic operation, finish that atomic step first, then compress immediately.
|
|
177
|
+
If a completed implementation+verification slice exists, compress it before replying or starting another task.
|
|
177
178
|
|
|
178
179
|
RANGE STRATEGY (MANDATORY)
|
|
179
180
|
Prioritize one large, closed, high-yield compression range first.
|
|
@@ -201,6 +202,8 @@ ACTION REQUIRED: Context usage is high.
|
|
|
201
202
|
Before doing more exploration, look for a closed, self-contained range that no longer needs to stay raw and compress it now.
|
|
202
203
|
|
|
203
204
|
Do not treat this as optional housekeeping. If any completed research, implementation, verification, CI-log inspection, or dead-end debugging slice is present, call the \`compress\` tool before continuing normal work.
|
|
205
|
+
If a completed implementation+verification slice exists, compress it before replying or starting another task.
|
|
206
|
+
High-priority stale tool outputs must be compressed once no exact raw text is needed.
|
|
204
207
|
|
|
205
208
|
RANGE SELECTION
|
|
206
209
|
Prefer older, resolved history. Avoid the newest active working slice unless it is clearly done.
|
|
@@ -222,6 +225,7 @@ If any range is cleanly closed and unlikely to be needed again, use the \`compre
|
|
|
222
225
|
If direction has shifted, compress earlier ranges that are now less relevant.
|
|
223
226
|
|
|
224
227
|
Do not defer this across another batch of searches, reads, CI log fetches, or tests. The next safe action should be compression whenever a closed slice exists.
|
|
228
|
+
High-priority stale tool outputs must be compressed once no exact raw text is needed.
|
|
225
229
|
|
|
226
230
|
Prefer small, closed-range compressions over one broad compression.
|
|
227
231
|
Use message-mode compression for isolated large stale messages.
|
|
@@ -238,6 +242,7 @@ ACTION REQUIRED: You've been iterating for a while after the last user message.
|
|
|
238
242
|
Pause before the next non-atomic tool call. If there is a closed portion that is unlikely to be referenced immediately (for example, finished research before implementation, completed CI-log triage, a verified fix, or a dead-end investigation), use the \`compress\` tool on it now.
|
|
239
243
|
|
|
240
244
|
Do not keep accumulating tool outputs while a completed slice remains raw. If a range is closed, compression is the next safe action.
|
|
245
|
+
If a completed implementation+verification slice exists, compress it before replying or starting another task.
|
|
241
246
|
|
|
242
247
|
Prefer multiple short, closed ranges over one large range when several independent slices are ready.
|
|
243
248
|
Use message-mode compression for isolated large stale messages.
|
|
@@ -149,11 +149,11 @@ export function resolveContextThresholds(
|
|
|
149
149
|
minContextPercent: min ??
|
|
150
150
|
resolveThresholdValue(config.compress.minContextLimit) ??
|
|
151
151
|
resolveThresholdValue(config.compress.minContextPercent) ??
|
|
152
|
-
0.
|
|
152
|
+
0.25,
|
|
153
153
|
maxContextPercent: max ??
|
|
154
154
|
resolveThresholdValue(config.compress.maxContextLimit) ??
|
|
155
155
|
resolveThresholdValue(config.compress.maxContextPercent) ??
|
|
156
|
-
0.
|
|
156
|
+
0.65,
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
159
|
|
|
@@ -291,11 +291,11 @@ export function getNudgeType(
|
|
|
291
291
|
config.compress;
|
|
292
292
|
const minContextPercent = coercePercentThreshold(
|
|
293
293
|
thresholds.minContextPercent ?? config.compress.minContextPercent,
|
|
294
|
-
0.
|
|
294
|
+
0.25,
|
|
295
295
|
);
|
|
296
296
|
const maxContextPercent = coercePercentThreshold(
|
|
297
297
|
thresholds.maxContextPercent ?? config.compress.maxContextPercent,
|
|
298
|
-
0.
|
|
298
|
+
0.65,
|
|
299
299
|
);
|
|
300
300
|
const cadence = Math.max(1, Math.floor(nudgeFrequency));
|
|
301
301
|
|