@code-yeongyu/senpi 2026.10.11 → 2026.10.12
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 +46 -0
- package/dist/bundle/chunks/anthropic-messages-GYG6YZY5.js +10 -0
- package/dist/bundle/chunks/{app-server-command-NHDOL4HQ.js → app-server-command-OL6PPUOA.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-EJF2XJ7Q.js → azure-openai-responses-GU6FOSJR.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZABLYCHT.js → chunk-46JEQXD7.js} +1 -1
- package/dist/bundle/chunks/{chunk-VE3D74HN.js → chunk-55VKYA5V.js} +1 -1
- package/dist/bundle/chunks/{chunk-7UNN3YHW.js → chunk-5AVFHHDF.js} +230 -221
- package/dist/bundle/chunks/{chunk-2JE2DOIF.js → chunk-5DPTM5E2.js} +1 -1
- package/dist/bundle/chunks/chunk-5UPUSGP5.js +2 -0
- package/dist/bundle/chunks/chunk-5VMRMY6N.js +16 -0
- package/dist/bundle/chunks/{chunk-7X3VRAM3.js → chunk-7P3QPVTF.js} +1 -1
- package/dist/bundle/chunks/{chunk-T6IYKWIH.js → chunk-BUGZZVQW.js} +1 -1
- package/dist/bundle/chunks/chunk-DL7EFVT2.js +12 -0
- package/dist/bundle/chunks/chunk-E5YUVGLQ.js +11 -0
- package/dist/bundle/chunks/{chunk-RLFQICEY.js → chunk-EQJY2B5F.js} +1 -1
- package/dist/bundle/chunks/{chunk-VYKBN4MR.js → chunk-GC2RU5TS.js} +1 -1
- package/dist/bundle/chunks/chunk-GPKEJOTQ.js +202 -0
- package/dist/bundle/chunks/{chunk-KCVSSFOV.js → chunk-GQ5PWY6P.js} +4 -3
- package/dist/bundle/chunks/{chunk-4GPJOGXZ.js → chunk-I4AEC6MH.js} +1 -1
- package/dist/bundle/chunks/chunk-JXSFGRBE.js +8 -0
- package/dist/bundle/chunks/{chunk-YGCMN2CX.js → chunk-NAY5LB53.js} +1 -1
- package/dist/bundle/chunks/{chunk-EBOD66AS.js → chunk-PBN2CATL.js} +2 -2
- package/dist/bundle/chunks/chunk-PFNBY43W.js +2 -0
- package/dist/bundle/chunks/{chunk-CY2B4QRR.js → chunk-PUWEQK2W.js} +1 -1
- package/dist/bundle/chunks/{chunk-5DBPUQSX.js → chunk-SF6AUNQZ.js} +1 -1
- package/dist/bundle/chunks/{chunk-G2XAU4BX.js → chunk-TMTT5CLA.js} +1 -1
- package/dist/bundle/chunks/{chunk-2JKDZXIY.js → chunk-VWFKLW73.js} +2 -2
- package/dist/bundle/chunks/chunk-WZMSBRTW.js +2 -0
- package/dist/bundle/chunks/{chunk-55HLKZSB.js → chunk-XVJRRLGN.js} +1 -1
- package/dist/bundle/chunks/chunk-Z2PWWBBD.js +31 -0
- package/dist/bundle/chunks/cli-main-RSIYAR4J.js +3 -0
- package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-SWVU2AXJ.js → cloudflare-workers-ai-system-one-LVWRKOUD.js} +1 -1
- package/dist/bundle/chunks/{google-generative-ai-XG4YX6FQ.js → google-generative-ai-JMGYPTXL.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-BBOZ6OUB.js → google-vertex-CI4FPIU7.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-EZ3KEW6V.js → help-fast-path-M7KMBM6K.js} +1 -1
- package/dist/bundle/chunks/host-command-6UR3DSFR.js +2 -0
- package/dist/bundle/chunks/host-lifecycle-2BKCCK5X.js +3 -0
- package/dist/bundle/chunks/host-lifecycle.js +10 -7
- package/dist/bundle/chunks/host-session-command-A2MZHEBP.js +19 -0
- package/dist/bundle/chunks/interactive-mode-EJBMTJOH.js +2 -0
- package/dist/bundle/chunks/{list-tips-WE2YGQM6.js → list-tips-BEQAOA4N.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-RB3ZBCGE.js → mistral-conversations-5OD7662T.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-V4CUQLV7.js → multi-session-host-YYMLHCUA.js} +4 -4
- package/dist/bundle/chunks/{openai-codex-responses-DBTPUXRW.js → openai-codex-responses-FN3UPAFI.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-QAJQC4BY.js → openai-completions-KMUQ3T4M.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-UBJWCEHG.js → openai-responses-V4Q5GVLO.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-WTRDT4ZH.js → package-manager-cli-6A5ZP26E.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-PT6LLBMJ.js +2 -0
- package/dist/bundle/chunks/rpc-mode-XNYJPYUM.js +2 -0
- package/dist/bundle/chunks/runtime-session-ZBHFMT65.js +2 -0
- package/dist/bundle/chunks/{schedule-command-PJVRKAKD.js → schedule-command-FYQG2MFX.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-7TX4XHN4.js +3 -0
- package/dist/bundle/chunks/session-picker-4RNB27SM.js +2 -0
- package/dist/bundle/chunks/session-worker.js +418 -412
- package/dist/bundle/chunks/{typesafe-system-one-B5TW3FHM.js → typesafe-system-one-WUHW7HR4.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/agent-session.d.ts +11 -2
- package/dist/core/agent-session.js +152 -43
- package/dist/core/compaction/compaction.js +2 -0
- package/dist/core/extensions/builtin/anthropic-web-search/index.js +22 -14
- package/dist/core/extensions/builtin/cache-keepalive/index.js +8 -4
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.d.ts +2 -1
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.js +55 -7
- package/dist/core/extensions/builtin/cache-keepalive/startup-activity-gate.d.ts +8 -0
- package/dist/core/extensions/builtin/cache-keepalive/startup-activity-gate.js +25 -0
- package/dist/core/extensions/builtin/compaction/index.js +13 -5
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.js +8 -4
- package/dist/core/extensions/builtin/moved-path-guard/tool-classes.js +1 -0
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts +4 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js +54 -17
- package/dist/core/extensions/builtin/server-search-fallback.d.ts +12 -0
- package/dist/core/extensions/builtin/server-search-fallback.js +50 -0
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +10 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.js +48 -4
- package/dist/core/extensions/builtin/websearch/index.d.ts +1 -1
- package/dist/core/extensions/builtin/websearch/index.js +119 -18
- package/dist/core/extensions/builtin/websearch/server-search.d.ts +11 -0
- package/dist/core/extensions/builtin/websearch/server-search.js +230 -0
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts +2 -0
- package/dist/core/extensions/builtin/websearch/websearch/search-model.js +15 -0
- package/dist/core/extensions/runner.d.ts +8 -1
- package/dist/core/extensions/runner.js +56 -7
- package/dist/core/extensions/types.d.ts +12 -2
- package/dist/core/extensions/user-activity.d.ts +10 -0
- package/dist/core/extensions/user-activity.js +20 -0
- package/dist/core/model-config-schema.d.ts +34 -0
- package/dist/core/model-config-schema.js +2 -0
- package/dist/core/model-config.js +1 -0
- package/dist/core/reserved-keywords.d.ts +28 -0
- package/dist/core/reserved-keywords.js +81 -0
- package/dist/core/retry-fallback/candidates.d.ts +1 -1
- package/dist/core/retry-fallback/candidates.js +1 -12
- package/dist/core/retry-fallback/controller.d.ts +3 -1
- package/dist/core/retry-fallback/controller.js +11 -5
- package/dist/core/retry-fallback/cooldown.d.ts +2 -1
- package/dist/core/retry-fallback/cooldown.js +21 -12
- package/dist/core/retry-fallback/unusable.d.ts +2 -0
- package/dist/core/retry-fallback/unusable.js +14 -2
- package/dist/core/retry-fallback/usage-limit.d.ts +10 -1
- package/dist/core/retry-fallback/usage-limit.js +39 -2
- package/dist/core/session-title-generator.js +2 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.js +7 -1
- package/dist/modes/interactive/composer-user-activity.d.ts +6 -0
- package/dist/modes/interactive/composer-user-activity.js +30 -0
- package/dist/modes/interactive/grok/chrome.js +2 -1
- package/dist/modes/interactive/interactive-mode.js +15 -6
- package/dist/modes/interactive/session-control-registry.js +8 -1
- package/dist/modes/interactive/theme/reserved-keyword-rainbow.d.ts +11 -0
- package/dist/modes/interactive/theme/reserved-keyword-rainbow.js +50 -0
- package/dist/modes/interactive/theme/theme.d.ts +3 -1
- package/dist/modes/interactive/theme/theme.js +9 -0
- package/dist/modes/print-mode.js +7 -2
- package/dist/modes/rpc/connection-handler.js +43 -11
- package/dist/modes/rpc/custom-capability.d.ts +2 -0
- package/dist/modes/rpc/custom-capability.js +2 -0
- package/dist/modes/rpc/host-admission-proxy.d.ts +9 -0
- package/dist/modes/rpc/host-admission-proxy.js +211 -0
- package/dist/modes/rpc/host-admission.d.ts +21 -0
- package/dist/modes/rpc/host-admission.js +59 -0
- package/dist/modes/rpc/host-capabilities.js +2 -1
- package/dist/modes/rpc/host-client-occupancy.d.ts +2 -1
- package/dist/modes/rpc/host-client-occupancy.js +7 -0
- package/dist/modes/rpc/host-decision.d.ts +2 -2
- package/dist/modes/rpc/host-decision.js +4 -0
- package/dist/modes/rpc/host-ensure-types.d.ts +2 -0
- package/dist/modes/rpc/host-ensure.js +31 -3
- package/dist/modes/rpc/host-lifecycle-drain.d.ts +2 -1
- package/dist/modes/rpc/host-lifecycle-drain.js +3 -1
- package/dist/modes/rpc/host-lifecycle-proxy.d.ts +3 -2
- package/dist/modes/rpc/host-lifecycle-proxy.js +10 -19
- package/dist/modes/rpc/host-lifecycle-shutdown.d.ts +2 -0
- package/dist/modes/rpc/host-lifecycle-shutdown.js +3 -1
- package/dist/modes/rpc/host-lifecycle-ticker.d.ts +11 -0
- package/dist/modes/rpc/host-lifecycle-ticker.js +27 -0
- package/dist/modes/rpc/host-lifecycle.js +15 -23
- package/dist/modes/rpc/host-outcome.js +1 -0
- package/dist/modes/rpc/host-protocol-info.d.ts +2 -0
- package/dist/modes/rpc/host-protocol-info.js +1 -0
- package/dist/modes/rpc/host-session-runner.js +22 -1
- package/dist/modes/rpc/host-status-all.js +1 -0
- package/dist/modes/rpc/host-status.d.ts +1 -0
- package/dist/modes/rpc/host-status.js +5 -1
- package/dist/modes/rpc/rpc-client.d.ts +7 -1
- package/dist/modes/rpc/rpc-client.js +12 -0
- package/dist/modes/rpc/rpc-types.d.ts +49 -1
- package/dist/modes/rpc/rpc-types.js +5 -0
- package/dist/modes/rpc/session-command-activity.js +2 -0
- package/dist/modes/rpc/session-held.js +3 -0
- package/docs/extensions.md +13 -1
- package/docs/providers.md +88 -0
- package/docs/rpc.md +150 -5
- package/docs/web-search.md +3 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/anthropic-messages-5QQJVQPZ.js +0 -9
- package/dist/bundle/chunks/chunk-2A3MS2Z7.js +0 -8
- package/dist/bundle/chunks/chunk-6SBY4ZWC.js +0 -2
- package/dist/bundle/chunks/chunk-6WCOSBI7.js +0 -2
- package/dist/bundle/chunks/chunk-E75RO54O.js +0 -14
- package/dist/bundle/chunks/chunk-JMYO34RK.js +0 -2
- package/dist/bundle/chunks/chunk-KRNXUTZJ.js +0 -2
- package/dist/bundle/chunks/chunk-L4HVJWIF.js +0 -11
- package/dist/bundle/chunks/chunk-N5WLLHUE.js +0 -2
- package/dist/bundle/chunks/chunk-NEFNNQSV.js +0 -9
- package/dist/bundle/chunks/chunk-PWIYVLIA.js +0 -9
- package/dist/bundle/chunks/chunk-Q3R44CGT.js +0 -5
- package/dist/bundle/chunks/chunk-QIARZN7G.js +0 -31
- package/dist/bundle/chunks/chunk-QKU6JOA4.js +0 -2
- package/dist/bundle/chunks/chunk-QYWXDE47.js +0 -2
- package/dist/bundle/chunks/chunk-XHELSLN3.js +0 -188
- package/dist/bundle/chunks/chunk-YDJ4HGWO.js +0 -16
- package/dist/bundle/chunks/chunk-ZJHRDQCH.js +0 -2
- package/dist/bundle/chunks/cli-main-TUBNBZNK.js +0 -3
- package/dist/bundle/chunks/host-command-WO7VKJBJ.js +0 -2
- package/dist/bundle/chunks/host-lifecycle-X2J5FTJL.js +0 -3
- package/dist/bundle/chunks/host-session-command-ICBOH5RP.js +0 -19
- package/dist/bundle/chunks/interactive-mode-UGDNCGQ5.js +0 -2
- package/dist/bundle/chunks/rotation-stream-OODURUGZ.js +0 -2
- package/dist/bundle/chunks/rpc-mode-22MCT32O.js +0 -2
- package/dist/bundle/chunks/runtime-session-I4NDNGC5.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-SFPRQBDO.js +0 -3
- package/dist/bundle/chunks/session-picker-3ZQPV7Z3.js +0 -2
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type AssistantMessage } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { SessionEntry } from "../session-manager.ts";
|
|
1
3
|
/**
|
|
2
4
|
* Who a usage limit binds. `model`: the provider refused THIS model only (a
|
|
3
5
|
* Fable-only weekly cap, premium models on a Copilot plan, a model that needs
|
|
@@ -7,7 +9,14 @@
|
|
|
7
9
|
* the chain moves to another provider instead.
|
|
8
10
|
*/
|
|
9
11
|
export type UsageLimitScope = "model" | "account";
|
|
10
|
-
export declare
|
|
12
|
+
export declare class AccountUsageLimitError extends Error {
|
|
13
|
+
constructor(provider: string, raw?: string);
|
|
14
|
+
}
|
|
15
|
+
export declare function usageLimitScope(failure: string | undefined | Pick<AssistantMessage, "errorMessage" | "errorCause">): UsageLimitScope | undefined;
|
|
16
|
+
/** Project advice without mutating the diagnostic-bearing engine message. */
|
|
17
|
+
export declare function describeUsageLimitMessage(message: AssistantMessage): AssistantMessage;
|
|
18
|
+
/** Project an assistant entry without mutating its persisted identity or payload. */
|
|
19
|
+
export declare function describeUsageLimitEntry(entry: SessionEntry): SessionEntry;
|
|
11
20
|
/** The notice clause naming what hit the limit, or undefined when no usage limit caused the switch. */
|
|
12
21
|
export declare function usageLimitCause(from: string, limit: UsageLimitScope | undefined): string | undefined;
|
|
13
22
|
//# sourceMappingURL=usage-limit.d.ts.map
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { isQuotaExhaustionMessage } from "@earendil-works/pi-ai";
|
|
1
|
+
import { describeProviderFailureForUser, isQuotaExhaustionMessage } from "@earendil-works/pi-ai";
|
|
2
2
|
import { rateLimitModelFamily } from "../credential-pool/model-scope.js";
|
|
3
3
|
import { isBillingErrorMessage } from "./billing.js";
|
|
4
|
+
export class AccountUsageLimitError extends Error {
|
|
5
|
+
constructor(provider, raw = "usage limit reached") {
|
|
6
|
+
super(describeProviderFailureForUser(raw, { model: provider, usageLimit: "account" }));
|
|
7
|
+
this.name = "AccountUsageLimitError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
4
10
|
// Subscription limit prose that carries no quota/billing keyword, e.g. Claude's
|
|
5
11
|
// "You've hit your session limit · resets 3pm" and the SDK terminal reasons.
|
|
6
12
|
const SUBSCRIPTION_LIMIT_PATTERN = /\bhit\s+your\b[^.]*\blimit\b|\b(?:session|weekly|monthly|daily|hourly|\d+[- ]hour|usage)\s+limit\b|\bblocking_limit\b|\brapid_refill_breaker\b/i;
|
|
@@ -8,7 +14,13 @@ const SUBSCRIPTION_LIMIT_PATTERN = /\bhit\s+your\b[^.]*\blimit\b|\b(?:session|we
|
|
|
8
14
|
// switch to a different model" (senpi#2660). An ordinary "rate limit exceeded" stays transient.
|
|
9
15
|
const PLAN_MODEL_LIMIT_PATTERN = /\breached\b[^.]*\b(?:free|plan|tier|model)\b[^.]*\blimit\b[\s\S]*\bswitch to (?:a |an )?(?:different|another) model\b/i;
|
|
10
16
|
const MODEL_SCOPE_PATTERN = /\bmodels?\b|\bpremium\b|\b(?:opus|sonnet|haiku|fable|mythos)\b/i;
|
|
11
|
-
export function usageLimitScope(
|
|
17
|
+
export function usageLimitScope(failure) {
|
|
18
|
+
if (typeof failure === "object" && failure.errorCause?.type === "usage_limit") {
|
|
19
|
+
const scope = failure.errorCause.scope;
|
|
20
|
+
if (scope === "account" || scope === "model")
|
|
21
|
+
return scope;
|
|
22
|
+
}
|
|
23
|
+
const errorMessage = typeof failure === "object" ? failure.errorMessage : failure;
|
|
12
24
|
if (errorMessage === undefined)
|
|
13
25
|
return undefined;
|
|
14
26
|
// Claude Code's "You've reached your Fable limit. Switch to another model" carries
|
|
@@ -23,6 +35,31 @@ export function usageLimitScope(errorMessage) {
|
|
|
23
35
|
return undefined;
|
|
24
36
|
return MODEL_SCOPE_PATTERN.test(errorMessage) ? "model" : "account";
|
|
25
37
|
}
|
|
38
|
+
/** Project advice without mutating the diagnostic-bearing engine message. */
|
|
39
|
+
export function describeUsageLimitMessage(message) {
|
|
40
|
+
const scope = usageLimitScope(message);
|
|
41
|
+
if (!scope || message.errorCause?.scope === scope)
|
|
42
|
+
return message;
|
|
43
|
+
return {
|
|
44
|
+
...message,
|
|
45
|
+
errorCause: { type: "usage_limit", scope },
|
|
46
|
+
...(scope === "account"
|
|
47
|
+
? {
|
|
48
|
+
errorMessage: describeProviderFailureForUser(message.errorMessage, {
|
|
49
|
+
model: `${message.provider}/${message.model}`,
|
|
50
|
+
usageLimit: scope,
|
|
51
|
+
}),
|
|
52
|
+
}
|
|
53
|
+
: {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Project an assistant entry without mutating its persisted identity or payload. */
|
|
57
|
+
export function describeUsageLimitEntry(entry) {
|
|
58
|
+
if (entry.type !== "message" || entry.message.role !== "assistant")
|
|
59
|
+
return entry;
|
|
60
|
+
const message = describeUsageLimitMessage(entry.message);
|
|
61
|
+
return message === entry.message ? entry : { ...entry, message };
|
|
62
|
+
}
|
|
26
63
|
/** The notice clause naming what hit the limit, or undefined when no usage limit caused the switch. */
|
|
27
64
|
export function usageLimitCause(from, limit) {
|
|
28
65
|
if (limit === "model")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { normalizeContext } from "@earendil-works/pi-ai";
|
|
2
2
|
import { completeSimple, retryAssistantCall } from "@earendil-works/pi-ai/compat";
|
|
3
|
+
import { withoutServerSearch } from "./extensions/builtin/server-search-fallback.js";
|
|
3
4
|
import { initialTitleReasoning, mandatoryReasoningRetryLevel } from "./session-title-reasoning.js";
|
|
4
5
|
const TITLE_SYSTEM_PROMPT = `Generate a concise title for this coding-agent session.
|
|
5
6
|
|
|
@@ -93,6 +94,7 @@ function buildTitleContext(firstPrompt) {
|
|
|
93
94
|
function buildTitleOptions(options, reasoning) {
|
|
94
95
|
const titleOptions = {
|
|
95
96
|
...options.baseOptions,
|
|
97
|
+
onPayload: withoutServerSearch(options.baseOptions?.onPayload),
|
|
96
98
|
sessionId: options.sessionId,
|
|
97
99
|
cacheRetention: options.model.cacheRetention === "none" ? "none" : "short",
|
|
98
100
|
maxTokens: reasoning === undefined ? TITLE_MAX_TOKENS : REASONING_TITLE_MAX_TOKENS,
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { type CreateModelRuntimeOptions, CredentialSynchronizationError, type Cr
|
|
|
21
21
|
export type { PackageManager, PathMetadata, ProgressCallback, ProgressEvent, ResolvedPaths, ResolvedResource, } from "./core/package-manager.ts";
|
|
22
22
|
export { DefaultPackageManager } from "./core/package-manager.ts";
|
|
23
23
|
export { type ProcessFootprint, type ProcessFootprintMeasure, readOwnFootprint, readProcessFootprint, } from "./core/process-footprint.ts";
|
|
24
|
+
export { findReservedKeywordRuns, findReservedKeywordSpans, type ReservedKeyword, type ReservedKeywordRun, type ReservedKeywordSpan, } from "./core/reserved-keywords.ts";
|
|
24
25
|
export type { ResourceCollision, ResourceDiagnostic, ResourceLoader } from "./core/resource-loader.ts";
|
|
25
26
|
export { DefaultResourceLoader, loadProjectContextFiles } from "./core/resource-loader.ts";
|
|
26
27
|
export { AgentSessionRuntime, type AgentSessionRuntimeDiagnostic, type AgentSessionServices, type CreateAgentSessionFromServicesOptions, type CreateAgentSessionOptions, type CreateAgentSessionResult, type CreateAgentSessionRuntimeFactory, type CreateAgentSessionRuntimeResult, type CreateAgentSessionServicesOptions, createAgentSession, createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, createBashTool, createCodingTools, createEditTool, createFindTool, createGrepTool, createLsTool, createPowerShellTool, createReadOnlyTools, createReadTool, createWriteTool, type PromptTemplate, } from "./core/sdk.ts";
|
|
@@ -36,7 +37,7 @@ export { UnknownCommandError, type UnknownCommandReason } from "./core/unknown-c
|
|
|
36
37
|
export { type ModelRoute, type ModelRouteReason, type ModelRouteRequest, VIRTUAL_MODEL_STATE_ENTRY, type VirtualModelDefinition, type VirtualModelStateData, } from "./core/virtual-models.ts";
|
|
37
38
|
export { connectWebViewService, type WebViewServiceConnection } from "./core/webview/webview-broker.ts";
|
|
38
39
|
export { type MainOptions, main } from "./main.ts";
|
|
39
|
-
export { classifyEndpointLiveness, createHostDaemonPaths, DEFAULT_HOST_LAUNCH_SPEC, daemonDirectoryName, decideHostAction, ENDPOINT_REGISTRY_VERSION, type EndpointKind, type EndpointLiveness, type EnsuredHost, type EnsureHostOptions, endpointProbeTimeoutMs, ensureHost, GENERATION_HANDOFF_CAPABILITY, gcHostEndpoints, type HandoffHostOptions, type HandoffRefusal, type HandoffResult, HOST_EXIT_ERROR, HOST_EXIT_FALLBACK, HOST_EXIT_OK, HOST_EXIT_REFUSED, HOST_EXIT_USAGE, HOST_PROTOCOL_VERSION, type HostAction, type HostDaemonPaths, type HostDecision, type HostDecisionClient, type HostDecisionPolicy, type HostDecisionWarning, type HostEndpointEntry, type HostEndpointIdentitySource, type HostEndpointStatus, HostEnsureRefusedError, type HostGcOptions, type HostGcResult, type HostGenerationRow, type HostLaunchSpec, type HostLaunchSpecCore, HostLaunchSpecError, type HostLaunchSpecRefusal, type HostOutcome, type HostProtocolInfo, type HostRefusalReason, type HostRequest, type HostSessionCounts, type HostStatusOptions, type HostStatusReport, type HostTarget, type HostUpgradePolicy, handoffHost, InteractiveMode, type InteractiveModeOptions, isTransportGoneError, type JsonAgentSessionEvent, listHostEndpoints, loadHostLaunchSpec, type ModelInfo, PINNED_HOST_CLIENT_CAPABILITIES, type PrintModeOptions, type ProbeHostOptions, parseHostLaunchSpec, parseHostProtocolInfo, probeHost, REQUIRED_HOST_CAPABILITIES, type ResolvedHostLaunchSpec, RpcClient, type RpcClientEvent, RpcClientOpenInFlightError, type RpcClientOptions, type RpcCommand, type RpcEventListener, type RpcExtensionEvent, type RpcExtensionUIRequest, type RpcExtensionUIResponse, type RpcResponse, type RpcSessionState, RpcTransportGoneError, readAllHostStatus, readHostStatus, runHostRequest, runPrintMode, runRpcMode, type ShardKind, type StopHostOptions, type StopHostResult, shardKey, shardSocketPath, shardSocketPathForKey, stopHost, TUI_PROBE_TIMEOUT_MS, } from "./modes/index.ts";
|
|
40
|
+
export { classifyEndpointLiveness, createHostDaemonPaths, DEFAULT_HOST_LAUNCH_SPEC, daemonDirectoryName, decideHostAction, ENDPOINT_REGISTRY_VERSION, type EndpointKind, type EndpointLiveness, type EnsuredHost, type EnsureHostOptions, endpointProbeTimeoutMs, ensureHost, GENERATION_HANDOFF_CAPABILITY, gcHostEndpoints, type HandoffHostOptions, type HandoffRefusal, type HandoffResult, HOST_EXIT_ERROR, HOST_EXIT_FALLBACK, HOST_EXIT_OK, HOST_EXIT_REFUSED, HOST_EXIT_USAGE, HOST_PROTOCOL_VERSION, type HostAction, type HostDaemonPaths, type HostDecision, type HostDecisionClient, type HostDecisionPolicy, type HostDecisionWarning, type HostEndpointEntry, type HostEndpointIdentitySource, type HostEndpointStatus, HostEnsureRefusedError, type HostGcOptions, type HostGcResult, type HostGenerationRow, type HostLaunchSpec, type HostLaunchSpecCore, HostLaunchSpecError, type HostLaunchSpecRefusal, type HostOutcome, type HostProtocolInfo, type HostRefusalReason, type HostRequest, type HostSessionCounts, type HostStatusOptions, type HostStatusReport, type HostTarget, type HostUpgradePolicy, handoffHost, InteractiveMode, type InteractiveModeOptions, isTransportGoneError, type JsonAgentSessionEvent, listHostEndpoints, loadHostLaunchSpec, type ModelInfo, PINNED_HOST_CLIENT_CAPABILITIES, type PrintModeOptions, type ProbeHostOptions, parseHostLaunchSpec, parseHostProtocolInfo, probeHost, REQUIRED_HOST_CAPABILITIES, type ResolvedHostLaunchSpec, RpcClient, type RpcClientEvent, RpcClientOpenInFlightError, type RpcClientOptions, type RpcCommand, type RpcEvalCell, type RpcEvalCellSnapshot, type RpcEventListener, type RpcExtensionEvent, type RpcExtensionUIRequest, type RpcExtensionUIResponse, type RpcResponse, type RpcSessionState, RpcTransportGoneError, readAllHostStatus, readHostStatus, runHostRequest, runPrintMode, runRpcMode, type ShardKind, type StopHostOptions, type StopHostResult, shardKey, shardSocketPath, shardSocketPathForKey, stopHost, TUI_PROBE_TIMEOUT_MS, } from "./modes/index.ts";
|
|
40
41
|
export { ArminComponent, AssistantMessageComponent, BashExecutionComponent, BorderedLoader, BranchSummaryMessageComponent, CompactionSummaryMessageComponent, CustomEditor, type CustomEditorOptions, CustomMessageComponent, DynamicBorder, ExtensionEditorComponent, ExtensionInputComponent, ExtensionSelectorComponent, FooterComponent, keyHint, keyText, LoginDialogComponent, ModelSelectorComponent, OAuthSelectorComponent, type RenderDiffOptions, rawKeyHint, renderDiff, SessionSelectorComponent, type SettingsCallbacks, type SettingsConfig, SettingsSelectorComponent, ShowImagesSelectorComponent, SkillInvocationMessageComponent, ThemeSelectorComponent, ThinkingSelectorComponent, ToolExecutionComponent, type ToolExecutionOptions, TreeSelectorComponent, truncateToVisualLines, UserMessageComponent, UserMessageSelectorComponent, type VisualTruncateResult, } from "./modes/interactive/components/index.ts";
|
|
41
42
|
export { getLanguageFromPath, getMarkdownTheme, getSelectListTheme, getSettingsListTheme, highlightCode, initTheme, Theme, type ThemeAppearance, type ThemeBg, type ThemeColor, type ThemeStyle, type ThemeToken, } from "./modes/interactive/theme/theme.ts";
|
|
42
43
|
export { collectOrphanedChildren } from "./modes/rpc/child-reaper.ts";
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ export { CredentialSynchronizationError, ModelRuntime, } from "./core/model-runt
|
|
|
25
25
|
export { DefaultPackageManager } from "./core/package-manager.js";
|
|
26
26
|
// Process memory footprint (phys_footprint / RssAnon / PrivateUsage), read without spawning
|
|
27
27
|
export { readOwnFootprint, readProcessFootprint, } from "./core/process-footprint.js";
|
|
28
|
+
export { findReservedKeywordRuns, findReservedKeywordSpans, } from "./core/reserved-keywords.js";
|
|
28
29
|
export { DefaultResourceLoader, loadProjectContextFiles } from "./core/resource-loader.js";
|
|
29
30
|
// SDK for programmatic usage
|
|
30
31
|
export { AgentSessionRuntime,
|
package/dist/modes/index.d.ts
CHANGED
|
@@ -19,5 +19,5 @@ export { type HostEndpointStatus, readAllHostStatus } from "./rpc/host-status-al
|
|
|
19
19
|
export { type StopHostOptions, type StopHostResult, stopHost } from "./rpc/host-stop.ts";
|
|
20
20
|
export { isTransportGoneError, type ModelInfo, RpcClient, type RpcClientEvent, RpcClientOpenInFlightError, type RpcClientOptions, type RpcEventListener, RpcTransportGoneError, } from "./rpc/rpc-client.ts";
|
|
21
21
|
export { runRpcMode } from "./rpc/rpc-mode.ts";
|
|
22
|
-
export type { RpcCommand, RpcExtensionEvent, RpcExtensionUIRequest, RpcExtensionUIResponse, RpcResponse, RpcSessionState, } from "./rpc/rpc-types.ts";
|
|
22
|
+
export type { RpcCommand, RpcEvalCell, RpcEvalCellSnapshot, RpcExtensionEvent, RpcExtensionUIRequest, RpcExtensionUIResponse, RpcResponse, RpcSessionState, } from "./rpc/rpc-types.ts";
|
|
23
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describeProviderFailureForUser, SERVER_FALLBACK_ABORTED_DIAGNOSTIC, stripTurnRetrySuppressionPrefix, } from "@earendil-works/pi-ai";
|
|
2
|
+
import { usageLimitScope } from "../../../core/retry-fallback/usage-limit.js";
|
|
2
3
|
import { formatDuration } from "../../../utils/duration.js";
|
|
3
4
|
import { formatProviderNativeBody, formatProviderNativeSummary } from "../../provider-native-rendering.js";
|
|
4
5
|
import { theme } from "../theme/theme.js";
|
|
@@ -132,7 +133,12 @@ export function createAssistantRenderDescriptors(message, options) {
|
|
|
132
133
|
// wording so the retry engine can read it; the transcript gets the
|
|
133
134
|
// plain-language version, without the recovery advice a retry still in
|
|
134
135
|
// flight would contradict, and never the internal replay marker.
|
|
135
|
-
const described =
|
|
136
|
+
const described = message.errorCause?.type === "usage_limit" && message.errorCause.scope === "account"
|
|
137
|
+
? message.errorMessage
|
|
138
|
+
: describeProviderFailureForUser(message.errorMessage, {
|
|
139
|
+
model: `${message.provider}/${message.model}`,
|
|
140
|
+
usageLimit: usageLimitScope(message),
|
|
141
|
+
});
|
|
136
142
|
addError(described ?? `Error: ${stripTurnRetrySuppressionPrefix(message.errorMessage ?? "") || "Unknown error"}`);
|
|
137
143
|
break;
|
|
138
144
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EditorComponent } from "@earendil-works/pi-tui";
|
|
2
|
+
/** Extension-supplied text updates the composer but is not terminal input. */
|
|
3
|
+
export declare function insertProgrammaticComposerInput(editor: EditorComponent, data: string): void;
|
|
4
|
+
/** Observe user edits, not setText calls that restore drafts during resume/reload. */
|
|
5
|
+
export declare function observeComposerActivity(editor: EditorComponent, onActivity: () => void): void;
|
|
6
|
+
//# sourceMappingURL=composer-user-activity.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const unobservedInput = new WeakMap();
|
|
2
|
+
/** Extension-supplied text updates the composer but is not terminal input. */
|
|
3
|
+
export function insertProgrammaticComposerInput(editor, data) {
|
|
4
|
+
const handleInput = unobservedInput.get(editor) ?? editor.handleInput.bind(editor);
|
|
5
|
+
handleInput(data);
|
|
6
|
+
}
|
|
7
|
+
/** Observe user edits, not setText calls that restore drafts during resume/reload. */
|
|
8
|
+
export function observeComposerActivity(editor, onActivity) {
|
|
9
|
+
const handleInput = editor.handleInput.bind(editor);
|
|
10
|
+
unobservedInput.set(editor, handleInput);
|
|
11
|
+
editor.handleInput = (data) => {
|
|
12
|
+
const previousText = editor.getText();
|
|
13
|
+
const onSubmit = editor.onSubmit;
|
|
14
|
+
let submitted = false;
|
|
15
|
+
editor.onSubmit = (...args) => {
|
|
16
|
+
submitted = true;
|
|
17
|
+
onSubmit?.(...args);
|
|
18
|
+
};
|
|
19
|
+
try {
|
|
20
|
+
handleInput(data);
|
|
21
|
+
// Submission clears the editor and is handled by prompt admission instead.
|
|
22
|
+
if (!submitted && editor.getText() !== previousText)
|
|
23
|
+
onActivity();
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
editor.onSubmit = onSubmit;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=composer-user-activity.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CustomEditor } from "../components/custom-editor.js";
|
|
2
2
|
import { WorkingStatusIndicator } from "../components/status-indicator.js";
|
|
3
|
-
import { theme } from "../theme/theme.js";
|
|
3
|
+
import { getReservedKeywordHighlight, theme } from "../theme/theme.js";
|
|
4
4
|
import { getGrokChromeTokens } from "./chrome-tokens.js";
|
|
5
5
|
import { GrokFooter } from "./footer.js";
|
|
6
6
|
import { GrokInputCard } from "./input-card.js";
|
|
@@ -60,6 +60,7 @@ export class GrokChrome {
|
|
|
60
60
|
const tokens = getGrokChromeTokens();
|
|
61
61
|
return {
|
|
62
62
|
borderColor: tokens.inputBorder,
|
|
63
|
+
keywordHighlight: getReservedKeywordHighlight(),
|
|
63
64
|
selectList: {
|
|
64
65
|
selectedPrefix: (text) => theme.fg("accent", text),
|
|
65
66
|
selectedText: (text) => tokens.primaryText(text),
|
|
@@ -24,6 +24,7 @@ import { AssistantEditError, assistantTextEquals } from "../../core/edited-assis
|
|
|
24
24
|
import { askUserAnswerDisplayText, formatUserMessage } from "../../core/extensions/builtin/ask-user/format.js";
|
|
25
25
|
import { askUserRenderers } from "../../core/extensions/builtin/ask-user/render.js";
|
|
26
26
|
import { buildNoticeBox } from "../../core/extensions/notice/index.js";
|
|
27
|
+
import { emitUserActivity } from "../../core/extensions/user-activity.js";
|
|
27
28
|
import { FooterDataProvider } from "../../core/footer-data-provider.js";
|
|
28
29
|
import { sessionHolderWarning } from "../../core/foreign-session-holders.js";
|
|
29
30
|
import { appendUncaughtCrashLog, appendUnhandledRejectionLog } from "../../core/hidden-stdout-log.js";
|
|
@@ -106,6 +107,7 @@ import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
|
106
107
|
import { TrustSelectorComponent } from "./components/trust-selector.js";
|
|
107
108
|
import { UserMessageComponent } from "./components/user-message.js";
|
|
108
109
|
import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
|
|
110
|
+
import { insertProgrammaticComposerInput, observeComposerActivity } from "./composer-user-activity.js";
|
|
109
111
|
import { expandEditorSubmission, expandSubmittedText, transferEditorContent } from "./editor-paste-transfer.js";
|
|
110
112
|
import { formatExtensionErrorHeadline, sanitizeTuiErrorMessage } from "./extension-error-format.js";
|
|
111
113
|
import { editFileInExternalEditor, editInExternalEditor } from "./external-editor.js";
|
|
@@ -470,7 +472,7 @@ export class OptimisticUserEchoController {
|
|
|
470
472
|
const IMAGE_MARKER_PATTERN = /\[Image #([1-9]\d*)\]/g;
|
|
471
473
|
/**
|
|
472
474
|
* Attach a clipboard bitmap as an in-memory image behind an atomic
|
|
473
|
-
* `[Image #N]` marker. Returns false when
|
|
475
|
+
* `[Image #N]` marker. Returns false when the paste was unhandled, so the caller
|
|
474
476
|
* falls through to the plain-text clipboard path.
|
|
475
477
|
*
|
|
476
478
|
* The bytes deliberately never touch the filesystem: writing a temp file and
|
|
@@ -496,10 +498,10 @@ async function attachClipboardImage(deps, image) {
|
|
|
496
498
|
if (deps.isCompacting()) {
|
|
497
499
|
// The compaction queue carries text only; an attachment queued behind
|
|
498
500
|
// compaction would be silently lost at delivery, so drop it here with a
|
|
499
|
-
// visible status. Consume the paste
|
|
501
|
+
// visible status. Consume the paste as dropped - the clipboard holds a
|
|
500
502
|
// bitmap, so the plain-text fallback has nothing useful to insert.
|
|
501
503
|
deps.showStatus("Image paste dropped: messages sent during compaction cannot carry images - paste again after compaction finishes");
|
|
502
|
-
return
|
|
504
|
+
return "dropped";
|
|
503
505
|
}
|
|
504
506
|
const processed = await processImage(image.bytes, image.mimeType, {
|
|
505
507
|
autoResizeImages: deps.settings.getImageAutoResize(),
|
|
@@ -521,7 +523,7 @@ async function attachClipboardImage(deps, image) {
|
|
|
521
523
|
mimeType: processed.mimeType,
|
|
522
524
|
});
|
|
523
525
|
deps.requestRender();
|
|
524
|
-
return
|
|
526
|
+
return "attached";
|
|
525
527
|
}
|
|
526
528
|
export class InteractiveMode {
|
|
527
529
|
static confirmsRefusedUnknownCommand(host, text) {
|
|
@@ -764,6 +766,7 @@ export class InteractiveMode {
|
|
|
764
766
|
});
|
|
765
767
|
}
|
|
766
768
|
this.editor = this.defaultEditor;
|
|
769
|
+
observeComposerActivity(this.defaultEditor, () => emitUserActivity(this.session, "draft"));
|
|
767
770
|
this.editorContainer = new Container();
|
|
768
771
|
this.editorContainer.addChild(this.editor);
|
|
769
772
|
this.footerDataProvider = new FooterDataProvider(this.sessionManager.getCwd());
|
|
@@ -2828,7 +2831,7 @@ export class InteractiveMode {
|
|
|
2828
2831
|
this.applyTerminalTitle();
|
|
2829
2832
|
},
|
|
2830
2833
|
custom: (factory, options) => this.showExtensionCustom(factory, options),
|
|
2831
|
-
pasteToEditor: (text) => this.editor
|
|
2834
|
+
pasteToEditor: (text) => insertProgrammaticComposerInput(this.editor, `\x1b[200~${text}\x1b[201~`),
|
|
2832
2835
|
setEditorText: (text) => this.editor.setText(text),
|
|
2833
2836
|
getEditorText: () => this.getExpandedEditorText(),
|
|
2834
2837
|
editor: (title, prefill) => this.withBlockedHostDialog(crypto.randomUUID(), title, () => this.showExtensionEditor(title, prefill)),
|
|
@@ -3377,6 +3380,7 @@ export class InteractiveMode {
|
|
|
3377
3380
|
this.defaultEditor.onSubmit?.(expandSubmittedText(newEditor, text));
|
|
3378
3381
|
};
|
|
3379
3382
|
newEditor.onChange = this.defaultEditor.onChange;
|
|
3383
|
+
observeComposerActivity(newEditor, () => emitUserActivity(this.session, "draft"));
|
|
3380
3384
|
// Copy text (and any collapsed paste/image markers) from previous editor.
|
|
3381
3385
|
// Image payloads live on this instance, so they must be dropped when the
|
|
3382
3386
|
// destination cannot own their markers.
|
|
@@ -3669,6 +3673,7 @@ export class InteractiveMode {
|
|
|
3669
3673
|
const leadingSpace = characterBeforeCursor && !/\s/.test(characterBeforeCursor) ? " " : "";
|
|
3670
3674
|
const trailingSpace = characterAfterCursor && !/\s/.test(characterAfterCursor) ? " " : "";
|
|
3671
3675
|
this.editor.insertTextAtCursor?.(`${leadingSpace}${paths}${trailingSpace}`);
|
|
3676
|
+
emitUserActivity(this.session, "draft");
|
|
3672
3677
|
this.ui.requestRender();
|
|
3673
3678
|
return;
|
|
3674
3679
|
}
|
|
@@ -3682,11 +3687,15 @@ export class InteractiveMode {
|
|
|
3682
3687
|
showStatus: (message) => this.showStatus(message),
|
|
3683
3688
|
requestRender: () => this.ui.requestRender(),
|
|
3684
3689
|
}, image));
|
|
3685
|
-
if (attached)
|
|
3690
|
+
if (attached) {
|
|
3691
|
+
if (attached === "attached")
|
|
3692
|
+
emitUserActivity(this.session, "draft");
|
|
3686
3693
|
return;
|
|
3694
|
+
}
|
|
3687
3695
|
const text = await readClipboardText();
|
|
3688
3696
|
if (text) {
|
|
3689
3697
|
this.editor.insertTextAtCursor?.(text);
|
|
3698
|
+
emitUserActivity(this.session, "draft");
|
|
3690
3699
|
this.ui.requestRender();
|
|
3691
3700
|
}
|
|
3692
3701
|
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { createHash } from "node:crypto";
|
|
13
13
|
import { rmSync } from "node:fs";
|
|
14
14
|
import { chmod, lstat, mkdir, realpath, rm } from "node:fs/promises";
|
|
15
|
+
import { tmpdir } from "node:os";
|
|
15
16
|
import { dirname, join } from "node:path";
|
|
16
17
|
import { engineBuildIdentity } from "../../core/engine-build-identity.js";
|
|
17
18
|
import { createDaemonDirectories, createHostDaemonPaths } from "../rpc/host-daemon-paths.js";
|
|
@@ -35,7 +36,13 @@ export async function resolveTuiSocket(agentDir, instanceId) {
|
|
|
35
36
|
await makePrivateDirectory(dirname(primary));
|
|
36
37
|
return primary;
|
|
37
38
|
}
|
|
38
|
-
const
|
|
39
|
+
const fallbackName = `senpi-rpc-${createHash("sha256").update(agentDir).digest("hex").slice(0, 8)}`;
|
|
40
|
+
const scopedRoot = join(tmpdir(), fallbackName);
|
|
41
|
+
// Test launchers supply a short owned TMPDIR. A normal user's long macOS temp path
|
|
42
|
+
// still needs the original short system fallback to fit sun_path.
|
|
43
|
+
const root = Buffer.byteLength(join(scopedRoot, "tui", name)) <= MAX_SOCKET_PATH_BYTES
|
|
44
|
+
? scopedRoot
|
|
45
|
+
: join("/tmp", fallbackName);
|
|
39
46
|
const tuiRoot = join(root, "tui");
|
|
40
47
|
await makePrivateDirectory(tuiRoot);
|
|
41
48
|
for (const directory of [root, tuiRoot])
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Color, type EditorKeywordHighlight, type TerminalColorMode } from "@earendil-works/pi-tui";
|
|
2
|
+
import type { ThemeAppearance } from "./theme.ts";
|
|
3
|
+
export declare function reservedKeywordColor(appearance: ThemeAppearance, index: number, length: number): Color;
|
|
4
|
+
export interface ReservedKeywordHighlightSource {
|
|
5
|
+
readonly appearance: () => ThemeAppearance;
|
|
6
|
+
readonly colorMode: () => TerminalColorMode;
|
|
7
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
8
|
+
}
|
|
9
|
+
/** `NO_COLOR` (any non-empty value) turns the decoration off entirely. */
|
|
10
|
+
export declare function createReservedKeywordHighlight(source: ReservedKeywordHighlightSource): EditorKeywordHighlight | undefined;
|
|
11
|
+
//# sourceMappingURL=reserved-keyword-rainbow.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { foregroundAnsi, mixColors, parseColor, } from "@earendil-works/pi-tui";
|
|
2
|
+
import { findReservedKeywordRuns } from "../../../core/reserved-keywords.js";
|
|
3
|
+
function spectrum(hexes) {
|
|
4
|
+
const positions = [0, 0.18, 0.36, 0.54, 0.72, 0.9, 1];
|
|
5
|
+
return hexes.map((hex, index) => ({ at: positions[index] ?? 1, color: parseColor(hex) }));
|
|
6
|
+
}
|
|
7
|
+
// The desktop composer's `.composer-reserved-keyword` stops: 700 shades on light surfaces,
|
|
8
|
+
// 400 shades on dark ones, so every stop clears 4.5:1 as text.
|
|
9
|
+
const SPECTRUM = {
|
|
10
|
+
light: spectrum(["#b91c1c", "#c2410c", "#15803d", "#0f766e", "#1d4ed8", "#be185d", "#b91c1c"]),
|
|
11
|
+
dark: spectrum(["#f87171", "#fbbf24", "#4ade80", "#2dd4bf", "#60a5fa", "#f472b6", "#f87171"]),
|
|
12
|
+
};
|
|
13
|
+
// A run spans red through pink; the final stop wraps back to red and is left out so the
|
|
14
|
+
// first and last characters of a keyword never share a colour.
|
|
15
|
+
const SPAN_END = 0.9;
|
|
16
|
+
export function reservedKeywordColor(appearance, index, length) {
|
|
17
|
+
const stops = SPECTRUM[appearance];
|
|
18
|
+
const at = length <= 1 ? 0 : (Math.min(Math.max(index, 0), length - 1) / (length - 1)) * SPAN_END;
|
|
19
|
+
for (let stop = 1; stop < stops.length; stop++) {
|
|
20
|
+
const left = stops[stop - 1];
|
|
21
|
+
const right = stops[stop];
|
|
22
|
+
if (left === undefined || right === undefined || at > right.at)
|
|
23
|
+
continue;
|
|
24
|
+
const amount = right.at === left.at ? 0 : (at - left.at) / (right.at - left.at);
|
|
25
|
+
return mixColors(left.color, right.color, amount, "srgb");
|
|
26
|
+
}
|
|
27
|
+
return stops[0]?.color ?? parseColor("#ffffff");
|
|
28
|
+
}
|
|
29
|
+
/** `NO_COLOR` (any non-empty value) turns the decoration off entirely. */
|
|
30
|
+
export function createReservedKeywordHighlight(source) {
|
|
31
|
+
const noColor = (source.env ?? process.env).NO_COLOR;
|
|
32
|
+
if (noColor !== undefined && noColor !== "")
|
|
33
|
+
return undefined;
|
|
34
|
+
const cache = new Map();
|
|
35
|
+
return {
|
|
36
|
+
find: findReservedKeywordRuns,
|
|
37
|
+
style: (text, index, length) => {
|
|
38
|
+
const appearance = source.appearance();
|
|
39
|
+
const mode = source.colorMode();
|
|
40
|
+
const key = `${appearance}:${mode}:${index}:${length}`;
|
|
41
|
+
let open = cache.get(key);
|
|
42
|
+
if (open === undefined) {
|
|
43
|
+
open = foregroundAnsi(reservedKeywordColor(appearance, index, length), mode);
|
|
44
|
+
cache.set(key, open);
|
|
45
|
+
}
|
|
46
|
+
return `${open}${text}\x1b[39m`;
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=reserved-keyword-rainbow.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
2
|
-
import { type Color, type EditorTheme, type MarkdownTheme, type SelectListTheme, type SettingsListTheme, type TerminalColorMode, type TerminalColors, type TextAttributes } from "@earendil-works/pi-tui";
|
|
2
|
+
import { type Color, type EditorKeywordHighlight, type EditorTheme, type MarkdownTheme, type SelectListTheme, type SettingsListTheme, type TerminalColorMode, type TerminalColors, type TextAttributes } from "@earendil-works/pi-tui";
|
|
3
3
|
import type { SourceInfo } from "../../../core/source-info.ts";
|
|
4
4
|
/** Name of the built-in theme generated from the terminal's colors (`"system"`), used when no theme is set. */
|
|
5
5
|
export { SYSTEM_THEME_NAME } from "./system-theme.ts";
|
|
@@ -147,5 +147,7 @@ export declare function getLanguageFromPath(filePath: string): string | undefine
|
|
|
147
147
|
export declare function getMarkdownTheme(): MarkdownTheme;
|
|
148
148
|
export declare function getSelectListTheme(): SelectListTheme;
|
|
149
149
|
export declare function getEditorTheme(): EditorTheme;
|
|
150
|
+
/** Rainbow for OmO's reserved prompt keywords; it follows the active theme's appearance and colour mode. */
|
|
151
|
+
export declare function getReservedKeywordHighlight(): EditorKeywordHighlight | undefined;
|
|
150
152
|
export declare function getSettingsListTheme(): SettingsListTheme;
|
|
151
153
|
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -5,6 +5,7 @@ import chalk from "chalk";
|
|
|
5
5
|
import { getCustomThemesDir, getThemesDir } from "../../../config.js";
|
|
6
6
|
import { closeWatcher, watchWithErrorHandler } from "../../../utils/fs-watch.js";
|
|
7
7
|
import { highlight, supportsLanguage } from "../../../utils/syntax-highlight.js";
|
|
8
|
+
import { createReservedKeywordHighlight } from "./reserved-keyword-rainbow.js";
|
|
8
9
|
import { generateSystemThemeColors, SYSTEM_THEME_NAME, terminalAppearance } from "./system-theme.js";
|
|
9
10
|
/** Name of the built-in theme generated from the terminal's colors (`"system"`), used when no theme is set. */
|
|
10
11
|
export { SYSTEM_THEME_NAME } from "./system-theme.js";
|
|
@@ -888,9 +889,17 @@ export function getEditorTheme() {
|
|
|
888
889
|
return {
|
|
889
890
|
borderColor: (text) => theme.fg("borderMuted", text),
|
|
890
891
|
mention: (text) => theme.fg("skillMention", `\x1b[1m${text}\x1b[22m`),
|
|
892
|
+
keywordHighlight: getReservedKeywordHighlight(),
|
|
891
893
|
selectList: getSelectListTheme(),
|
|
892
894
|
};
|
|
893
895
|
}
|
|
896
|
+
/** Rainbow for OmO's reserved prompt keywords; it follows the active theme's appearance and colour mode. */
|
|
897
|
+
export function getReservedKeywordHighlight() {
|
|
898
|
+
return createReservedKeywordHighlight({
|
|
899
|
+
appearance: () => theme.appearance,
|
|
900
|
+
colorMode: () => theme.getColorMode(),
|
|
901
|
+
});
|
|
902
|
+
}
|
|
894
903
|
export function getSettingsListTheme() {
|
|
895
904
|
return {
|
|
896
905
|
label: (text, selected) => (selected ? theme.fg("accent", text) : text),
|
package/dist/modes/print-mode.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { describeProviderFailureForUser, stripTurnRetrySuppressionPrefix, } from "@earendil-works/pi-ai";
|
|
9
9
|
import { REQUIRED_COMPACTION_ERROR_MESSAGE } from "../core/agent-session.js";
|
|
10
10
|
import { flushRawStdout, waitForRawStdoutBackpressure, writeRawStdout } from "../core/output-guard.js";
|
|
11
|
-
import { usageLimitCause } from "../core/retry-fallback/usage-limit.js";
|
|
11
|
+
import { usageLimitCause, usageLimitScope } from "../core/retry-fallback/usage-limit.js";
|
|
12
12
|
import { killTrackedDetachedChildren } from "../utils/shell.js";
|
|
13
13
|
import { toJsonEvent } from "./json-event.js";
|
|
14
14
|
import { formatProviderNativeBody, formatProviderNativeSummary } from "./provider-native-rendering.js";
|
|
@@ -157,7 +157,12 @@ export async function runPrintMode(runtimeHost, options) {
|
|
|
157
157
|
if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") {
|
|
158
158
|
// A provider-stream stall or transport drop keeps the classifier wording
|
|
159
159
|
// on the message; stderr gets the plain-language version instead.
|
|
160
|
-
const described =
|
|
160
|
+
const described = assistantMsg.errorCause?.type === "usage_limit" && assistantMsg.errorCause.scope === "account"
|
|
161
|
+
? assistantMsg.errorMessage
|
|
162
|
+
: describeProviderFailureForUser(assistantMsg.errorMessage, {
|
|
163
|
+
model: `${assistantMsg.provider}/${assistantMsg.model}`,
|
|
164
|
+
usageLimit: usageLimitScope(assistantMsg),
|
|
165
|
+
});
|
|
161
166
|
console.error(described ??
|
|
162
167
|
(stripTurnRetrySuppressionPrefix(assistantMsg.errorMessage ?? "") ||
|
|
163
168
|
`Request ${assistantMsg.stopReason}`));
|
|
@@ -26,13 +26,15 @@ import { emitProviderAccountsChanged, subscribeProviderAccountEvents, } from "..
|
|
|
26
26
|
import { ANTHROPIC_SUBSCRIPTION_PROVIDER_ID } from "../../core/extensions/builtin/anthropic-subscription/account-management.js";
|
|
27
27
|
import { isMcpControlInventoryChanged, MCP_CONTROL_INVENTORY_CHANGED_EVENT, MCP_CONTROL_INVENTORY_REQUEST_EVENT, } from "../../core/extensions/builtin/mcp/control-inventory.js";
|
|
28
28
|
import { applyFastMode, resolveServiceTierMemoryModel, } from "../../core/extensions/builtin/service-tier.js";
|
|
29
|
+
import { ExtensionRpcRequestNotFoundError } from "../../core/extensions/runner.js";
|
|
30
|
+
import { describeUsageLimitEntry, describeUsageLimitMessage } from "../../core/retry-fallback/usage-limit.js";
|
|
29
31
|
import { theme } from "../interactive/theme/theme.js";
|
|
30
32
|
import { DURABLE_CLIENT_MESSAGE_ID_CAPABILITY } from "./client-admission-record.js";
|
|
31
33
|
import { ClientAdmissions } from "./client-admissions.js";
|
|
32
34
|
import { handleClientInput } from "./client-input-handler.js";
|
|
33
35
|
import { ClientMessageEvents } from "./client-message-events.js";
|
|
34
36
|
import { ConnectionQuestionBridge, degradeQuestion, sessionQuestionBridges } from "./connection-question-bridge.js";
|
|
35
|
-
import { AUTO_TITLE_SESSIONS_CAPABILITY, buildCustomUnsupportedRequest, CONTINUE_FROM_LEAF_CAPABILITY, DEFAULT_CUSTOM_EXTENSION_LABEL, EXTENSION_EVENTS_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY, QUESTION_CAPABILITY, RETRY_FALLBACK_COMMAND_CAPABILITY, SESSION_HELD_CAPABILITY, } from "./custom-capability.js";
|
|
37
|
+
import { AUTO_TITLE_SESSIONS_CAPABILITY, buildCustomUnsupportedRequest, CONTINUE_FROM_LEAF_CAPABILITY, DEFAULT_CUSTOM_EXTENSION_LABEL, EVAL_CELLS_CAPABILITY, EXTENSION_EVENTS_CAPABILITY, MEDIA_PLACEHOLDERS_CAPABILITY, QUESTION_CAPABILITY, RETRY_FALLBACK_COMMAND_CAPABILITY, SESSION_HELD_CAPABILITY, } from "./custom-capability.js";
|
|
36
38
|
import { createRpcEventOutputBuffer } from "./event-output-buffer.js";
|
|
37
39
|
import { settleExtensionUiResponse } from "./extension-ui-response.js";
|
|
38
40
|
import { HostSessionControl } from "./host-session-control.js";
|
|
@@ -42,7 +44,7 @@ import { protocolIdentity } from "./protocol-identity.js";
|
|
|
42
44
|
import { buildRpcCommandsForSession, createCommandsChangedEvent, rpcCommandListDigest } from "./rpc-command-surface.js";
|
|
43
45
|
import { rpcCommandPayloadError, rpcCommandShapeError, rpcMessageLengthError, sessionRetryFallbackError, } from "./rpc-input-validation.js";
|
|
44
46
|
import { buildRpcSessionState } from "./rpc-session-state.js";
|
|
45
|
-
import { RPC_ERROR_ENTRY_NOT_FOUND, RPC_ERROR_MEDIA_NOT_FOUND, RPC_ERROR_MODEL_NOT_FOUND } from "./rpc-types.js";
|
|
47
|
+
import { RPC_ERROR_ENTRY_NOT_FOUND, RPC_ERROR_EVAL_CELL_NOT_FOUND, RPC_ERROR_EVAL_CELLS_UNAVAILABLE, RPC_ERROR_INVALID_EVAL_CELL_REQUEST, RPC_ERROR_MEDIA_NOT_FOUND, RPC_ERROR_MODEL_NOT_FOUND, } from "./rpc-types.js";
|
|
46
48
|
import { availableModelsData, interruptRunningTurn, unsupportedThinkingLevel } from "./session-control-actions-data.js";
|
|
47
49
|
import { SessionExtensionUiRequests } from "./session-extension-ui-requests.js";
|
|
48
50
|
export { buildRpcSessionState } from "./rpc-session-state.js";
|
|
@@ -738,6 +740,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
738
740
|
MEDIA_PLACEHOLDERS_CAPABILITY,
|
|
739
741
|
DURABLE_CLIENT_MESSAGE_ID_CAPABILITY,
|
|
740
742
|
CONTINUE_FROM_LEAF_CAPABILITY,
|
|
743
|
+
EVAL_CELLS_CAPABILITY,
|
|
741
744
|
...(options.retryFallbackCommand ? [RETRY_FALLBACK_COMMAND_CAPABILITY] : []),
|
|
742
745
|
// Client flags cannot advertise a host guard this classic binding does not run.
|
|
743
746
|
...(options.capabilities ?? []).filter((capability) => capability !== SESSION_HELD_CAPABILITY),
|
|
@@ -1249,11 +1252,22 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1249
1252
|
}
|
|
1250
1253
|
entries = entries.slice(sinceIndex + 1);
|
|
1251
1254
|
}
|
|
1252
|
-
return success(id, "get_entries", {
|
|
1255
|
+
return success(id, "get_entries", {
|
|
1256
|
+
entries: entries.map(describeUsageLimitEntry),
|
|
1257
|
+
leafId: sessionManager.getLeafId(),
|
|
1258
|
+
});
|
|
1253
1259
|
}
|
|
1254
1260
|
case "get_tree": {
|
|
1255
1261
|
const sessionManager = session.sessionManager;
|
|
1256
|
-
|
|
1262
|
+
const tree = sessionManager.getTree();
|
|
1263
|
+
// getTree returns defensive nodes; keep the persisted entries diagnostic-bearing.
|
|
1264
|
+
const nodes = [...tree];
|
|
1265
|
+
for (const node of nodes) {
|
|
1266
|
+
node.entry = describeUsageLimitEntry(node.entry);
|
|
1267
|
+
for (const child of node.children)
|
|
1268
|
+
nodes.push(child);
|
|
1269
|
+
}
|
|
1270
|
+
return success(id, "get_tree", { tree, leafId: sessionManager.getLeafId() });
|
|
1257
1271
|
}
|
|
1258
1272
|
case "get_last_assistant_text": {
|
|
1259
1273
|
const text = session.getLastAssistantText();
|
|
@@ -1277,7 +1291,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1277
1291
|
// Messages
|
|
1278
1292
|
// =================================================================
|
|
1279
1293
|
case "get_messages": {
|
|
1280
|
-
return success(id, "get_messages", {
|
|
1294
|
+
return success(id, "get_messages", {
|
|
1295
|
+
messages: session.messages.map((message) => message.role === "assistant" ? describeUsageLimitMessage(message) : message),
|
|
1296
|
+
});
|
|
1281
1297
|
}
|
|
1282
1298
|
// On-demand fetch of a media block a `media_placeholders` client received as
|
|
1283
1299
|
// an `image_ref` stub. Durable session entries first (they survive the live
|
|
@@ -1302,13 +1318,29 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1302
1318
|
const inventory = recordLoadedSurfaces(true);
|
|
1303
1319
|
return success(id, "get_loaded_surfaces", inventory.data);
|
|
1304
1320
|
}
|
|
1305
|
-
case "extension_request":
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1321
|
+
case "extension_request":
|
|
1322
|
+
case "eval_cells.list":
|
|
1323
|
+
case "eval_cells.peek":
|
|
1324
|
+
case "eval_cells.stop": {
|
|
1325
|
+
const name = command.type === "extension_request" ? command.name.trim() : command.type;
|
|
1326
|
+
if (name.length === 0)
|
|
1327
|
+
return error(id, command.type, "Extension RPC request name cannot be empty");
|
|
1328
|
+
try {
|
|
1329
|
+
const data = await session.extensionRunner.requestRpc(name, command.type === "extension_request" ? command.data : command);
|
|
1330
|
+
return success(id, command.type, data);
|
|
1331
|
+
}
|
|
1332
|
+
catch (cause) {
|
|
1333
|
+
if (cause instanceof ExtensionRpcRequestNotFoundError &&
|
|
1334
|
+
(name === "eval_cells.list" || name === "eval_cells.peek" || name === "eval_cells.stop")) {
|
|
1335
|
+
return error(id, command.type, "Eval cell controls are unavailable in this session", RPC_ERROR_EVAL_CELLS_UNAVAILABLE);
|
|
1336
|
+
}
|
|
1337
|
+
if (cause instanceof Error &&
|
|
1338
|
+
"code" in cause &&
|
|
1339
|
+
(cause.code === RPC_ERROR_EVAL_CELL_NOT_FOUND || cause.code === RPC_ERROR_INVALID_EVAL_CELL_REQUEST)) {
|
|
1340
|
+
return error(id, command.type, cause.message, cause.code);
|
|
1341
|
+
}
|
|
1342
|
+
throw cause;
|
|
1309
1343
|
}
|
|
1310
|
-
const data = await session.extensionRunner.requestRpc(name, command.data);
|
|
1311
|
-
return success(id, "extension_request", data);
|
|
1312
1344
|
}
|
|
1313
1345
|
// =================================================================
|
|
1314
1346
|
// Auth (task 13)
|
|
@@ -17,6 +17,8 @@ import type { RpcExtensionUIRequest } from "./rpc-types.ts";
|
|
|
17
17
|
/** The capability string a client sends in its handshake to opt into the notice. */
|
|
18
18
|
export declare const CUSTOM_UNSUPPORTED_CAPABILITY = "custom_unsupported";
|
|
19
19
|
export declare const EXTENSION_EVENTS_CAPABILITY = "extension_events";
|
|
20
|
+
/** Host protocol support; a session without codemode returns `eval_cells_unavailable`. */
|
|
21
|
+
export declare const EVAL_CELLS_CAPABILITY = "eval_cells";
|
|
20
22
|
export declare const AUTO_TITLE_SESSIONS_CAPABILITY = "auto_title_sessions";
|
|
21
23
|
/** Host capability: the `continue_from_leaf` command starts a turn with no new prompt (#1930). */
|
|
22
24
|
export declare const CONTINUE_FROM_LEAF_CAPABILITY = "continue_from_leaf";
|
|
@@ -17,6 +17,8 @@ import * as crypto from "node:crypto";
|
|
|
17
17
|
/** The capability string a client sends in its handshake to opt into the notice. */
|
|
18
18
|
export const CUSTOM_UNSUPPORTED_CAPABILITY = "custom_unsupported";
|
|
19
19
|
export const EXTENSION_EVENTS_CAPABILITY = "extension_events";
|
|
20
|
+
/** Host protocol support; a session without codemode returns `eval_cells_unavailable`. */
|
|
21
|
+
export const EVAL_CELLS_CAPABILITY = "eval_cells";
|
|
20
22
|
export const AUTO_TITLE_SESSIONS_CAPABILITY = "auto_title_sessions";
|
|
21
23
|
/** Host capability: the `continue_from_leaf` command starts a turn with no new prompt (#1930). */
|
|
22
24
|
export const CONTINUE_FROM_LEAF_CAPABILITY = "continue_from_leaf";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Socket } from "node:net";
|
|
2
|
+
import { type HostAdmission } from "./host-admission.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Requests are size-bounded; each direction awaits downstream socket backpressure.
|
|
5
|
+
* Opens remain concurrent with control commands. Stop refuses every pending open,
|
|
6
|
+
* while other commands retain their wire order and child-owned semantics.
|
|
7
|
+
*/
|
|
8
|
+
export declare function proxyWithAdmission(client: Socket, internal: Socket | undefined, admission: HostAdmission): void;
|
|
9
|
+
//# sourceMappingURL=host-admission-proxy.d.ts.map
|