@sayknow-cli/coding-agent 0.3.12 → 0.3.15
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/types/autoresearch/tools/init-experiment.d.ts +1 -1
- package/dist/types/autoresearch/tools/log-experiment.d.ts +2 -2
- package/dist/types/cli/classify-install-target.d.ts +0 -10
- package/dist/types/cli/daemon-cli.d.ts +2 -0
- package/dist/types/cli/initial-message.d.ts +1 -1
- package/dist/types/cli/malloc-env-guard.d.ts +65 -0
- package/dist/types/cli/malloc-env-guard.test.d.ts +1 -0
- package/dist/types/cli/notify-cli.d.ts +3 -1
- package/dist/types/cli/session-picker.d.ts +4 -3
- package/dist/types/cli/update-cli.d.ts +22 -3
- package/dist/types/cli.d.ts +5 -0
- package/dist/types/commands/daemon.d.ts +6 -2
- package/dist/types/commands/launch.d.ts +1 -0
- package/dist/types/commands/notify.d.ts +6 -0
- package/dist/types/commands/web-search.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-changelog.d.ts +4 -4
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +9 -9
- package/dist/types/commit/agentic/tools/schemas.d.ts +9 -9
- package/dist/types/commit/agentic/tools/split-commit.d.ts +9 -9
- package/dist/types/commit/analysis/conventional.d.ts +1 -1
- package/dist/types/commit/analysis/summary.d.ts +1 -1
- package/dist/types/commit/changelog/generate.d.ts +3 -3
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/map-phase.d.ts +1 -1
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +1 -1
- package/dist/types/commit/shared-llm.d.ts +9 -9
- package/dist/types/config/keybindings.d.ts +134 -129
- package/dist/types/config/model-profile-activation.d.ts +1 -0
- package/dist/types/config/model-registry.d.ts +35 -35
- package/dist/types/config/models-config-schema.d.ts +111 -111
- package/dist/types/config/settings-schema.d.ts +56 -16
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/coordinator-mcp/model-preset.d.ts +45 -0
- package/dist/types/coordinator-mcp/policy.d.ts +3 -0
- package/dist/types/coordinator-mcp/server.d.ts +79 -6
- package/dist/types/coordinator-mcp/session-reaper.d.ts +53 -0
- package/dist/types/daemon/control-types.d.ts +10 -0
- package/dist/types/daemon/operator-contract.d.ts +47 -0
- package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/models/catalog.d.ts +4 -0
- package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/shared/errors.d.ts +12 -12
- package/dist/types/discovery/helpers.d.ts +1 -1
- package/dist/types/discovery/substitute-plugin-root.d.ts +0 -4
- package/dist/types/edit/modes/patch.d.ts +2 -2
- package/dist/types/extensibility/extensions/types.d.ts +3 -1
- package/dist/types/goals/tools/goal-tool.d.ts +6 -6
- package/dist/types/i18n/messages/en.d.ts +8 -8
- package/dist/types/internal-urls/local-protocol.d.ts +13 -9
- package/dist/types/lsp/index.d.ts +9 -9
- package/dist/types/lsp/types.d.ts +9 -9
- package/dist/types/main.d.ts +66 -2
- package/dist/types/modes/acp/acp-agent.d.ts +19 -2
- package/dist/types/modes/acp/acp-mode.d.ts +12 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -1
- package/dist/types/modes/components/custom-editor.d.ts +2 -0
- package/dist/types/modes/components/hook-selector.d.ts +5 -0
- package/dist/types/modes/components/irc-sidebar.d.ts +32 -0
- package/dist/types/modes/components/pet-selector.d.ts +11 -0
- package/dist/types/modes/components/sayknow-pet-widget.d.ts +59 -0
- package/dist/types/modes/components/session-selector.d.ts +22 -9
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/status-line/types.d.ts +1 -1
- package/dist/types/modes/components/status-line.d.ts +0 -10
- package/dist/types/modes/components/tool-execution.d.ts +1 -0
- package/dist/types/modes/components/user-message.d.ts +2 -1
- package/dist/types/modes/controllers/event-controller.d.ts +4 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +24 -2
- package/dist/types/modes/irc-observation-ledger.d.ts +22 -0
- package/dist/types/modes/print-mode.d.ts +3 -4
- package/dist/types/modes/rpc/rpc-client.d.ts +7 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +2 -1
- package/dist/types/modes/rpc/rpc-types.d.ts +17 -1
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +8 -0
- package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +5 -0
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +45 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +42 -2
- package/dist/types/modes/theme/defaults/index.d.ts +568 -568
- package/dist/types/modes/types.d.ts +28 -2
- package/dist/types/modes/utils/abort-message.d.ts +1 -1
- package/dist/types/modes/utils/context-usage.d.ts +4 -19
- package/dist/types/modes/utils/irc-message.d.ts +38 -0
- package/dist/types/modes/utils/ui-helpers.d.ts +13 -4
- package/dist/types/notifications/config.d.ts +34 -0
- package/dist/types/notifications/daemon-paths.d.ts +7 -0
- package/dist/types/notifications/index.d.ts +27 -0
- package/dist/types/notifications/lifecycle-control-runtime.d.ts +12 -4
- package/dist/types/notifications/notification-service.d.ts +144 -0
- package/dist/types/notifications/rate-limit-pool.d.ts +27 -9
- package/dist/types/notifications/telegram-daemon-control.d.ts +6 -0
- package/dist/types/notifications/telegram-daemon.d.ts +130 -3
- package/dist/types/notifications/telegram-reference.d.ts +19 -2
- package/dist/types/notifications/topic-registry.d.ts +24 -4
- package/dist/types/registry/agent-registry.d.ts +2 -0
- package/dist/types/rlm/index.d.ts +1 -1
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/secrets/obfuscator.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +40 -3
- package/dist/types/session/cache-economics.d.ts +79 -0
- package/dist/types/session/context-estimation.d.ts +31 -0
- package/dist/types/session/provider-safety-stop.d.ts +5 -0
- package/dist/types/session/session-manager.d.ts +124 -4
- package/dist/types/session/session-storage.d.ts +155 -13
- package/dist/types/setup/credential-auto-import.d.ts +2 -2
- package/dist/types/skc-runtime/session-state-sidecar.d.ts +34 -3
- package/dist/types/skc-runtime/state-schema.d.ts +19 -19
- package/dist/types/skc-runtime/tmux-common.d.ts +6 -0
- package/dist/types/skc-runtime/tmux-owner-isolation-cli.d.ts +5 -0
- package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +309 -0
- package/dist/types/skc-runtime/tmux-sessions.d.ts +49 -17
- package/dist/types/task/agents.d.ts +2 -2
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/task/receipt.d.ts +3 -1
- package/dist/types/task/types.d.ts +35 -27
- package/dist/types/tools/ask-answer-registry.d.ts +5 -0
- package/dist/types/tools/bash.d.ts +1 -1
- package/dist/types/tools/browser/tab-supervisor.d.ts +6 -0
- package/dist/types/tools/browser.d.ts +28 -28
- package/dist/types/tools/computer.d.ts +20 -20
- package/dist/types/tools/cron.d.ts +2 -2
- package/dist/types/tools/debug.d.ts +40 -40
- package/dist/types/tools/gh.d.ts +10 -10
- package/dist/types/tools/image-gen.d.ts +2 -2
- package/dist/types/tools/index.d.ts +58 -6
- package/dist/types/tools/monitor.d.ts +6 -6
- package/dist/types/tools/skill-discovery.d.ts +4 -4
- package/dist/types/tools/subagent.d.ts +12 -12
- package/dist/types/tools/telegram-send.d.ts +7 -0
- package/dist/types/tools/todo-write.d.ts +8 -8
- package/dist/types/utils/external-editor.d.ts +2 -0
- package/dist/types/web/insane/bridge.d.ts +9 -9
- package/dist/types/web/search/index.d.ts +4 -4
- package/package.json +8 -8
- package/scripts/g004-tmux-smoke.ts +196 -36
- package/src/cli/daemon-cli.ts +19 -29
- package/src/cli/malloc-env-guard.test.ts +104 -0
- package/src/cli/malloc-env-guard.ts +149 -0
- package/src/cli/notify-cli.ts +78 -14
- package/src/cli/session-picker.ts +23 -40
- package/src/cli/update-cli.ts +56 -37
- package/src/cli.ts +51 -10
- package/src/commands/daemon.ts +19 -5
- package/src/commands/harness.ts +515 -47
- package/src/commands/launch.ts +11 -3
- package/src/commands/notify.ts +5 -1
- package/src/commands/session.ts +6 -1
- package/src/config/keybindings.ts +5 -0
- package/src/config/model-profile-activation.ts +1 -1
- package/src/config/model-profiles.ts +14 -14
- package/src/config/settings-schema.ts +41 -1
- package/src/config/settings.ts +96 -45
- package/src/coordinator/contract.ts +1 -0
- package/src/coordinator-mcp/model-preset.ts +100 -0
- package/src/coordinator-mcp/policy.ts +30 -0
- package/src/coordinator-mcp/server.ts +2958 -430
- package/src/coordinator-mcp/session-reaper.ts +129 -0
- package/src/daemon/control-types.ts +11 -0
- package/src/daemon/operator-contract.ts +121 -0
- package/src/defaults/skc/extensions/grok-cli-vendor/src/models/catalog.ts +57 -17
- package/src/defaults/skc/extensions/grok-cli-vendor/src/payload/sanitize.ts +15 -2
- package/src/defaults/skc/extensions/grok-cli-vendor/src/provider/register.ts +5 -1
- package/src/extensibility/extensions/runner.ts +1 -1
- package/src/extensibility/extensions/types.ts +3 -1
- package/src/internal-urls/docs-index.generated.ts +10 -9
- package/src/internal-urls/local-protocol.ts +29 -10
- package/src/main.ts +301 -80
- package/src/modes/acp/acp-agent.ts +730 -100
- package/src/modes/acp/acp-mode.ts +29 -2
- package/src/modes/components/assistant-message.ts +32 -3
- package/src/modes/components/bash-execution.ts +43 -13
- package/src/modes/components/custom-editor.ts +5 -0
- package/src/modes/components/footer.ts +3 -3
- package/src/modes/components/hook-selector.ts +12 -0
- package/src/modes/components/irc-sidebar.ts +206 -0
- package/src/modes/components/pet-selector.ts +55 -0
- package/src/modes/components/sayknow-pet-widget.ts +360 -0
- package/src/modes/components/session-selector.ts +222 -221
- package/src/modes/components/settings-selector.ts +10 -0
- package/src/modes/components/status-line/segments.ts +14 -7
- package/src/modes/components/status-line/types.ts +1 -1
- package/src/modes/components/status-line.ts +4 -171
- package/src/modes/components/tool-execution.ts +47 -6
- package/src/modes/components/user-message.ts +26 -9
- package/src/modes/controllers/command-controller.ts +28 -2
- package/src/modes/controllers/event-controller.ts +159 -36
- package/src/modes/controllers/extension-ui-controller.ts +37 -18
- package/src/modes/controllers/input-controller.ts +8 -2
- package/src/modes/controllers/selector-controller.ts +62 -15
- package/src/modes/interactive-mode.ts +199 -7
- package/src/modes/irc-observation-ledger.ts +127 -0
- package/src/modes/print-mode.ts +228 -92
- package/src/modes/rpc/rpc-client.ts +58 -1
- package/src/modes/rpc/rpc-mode.ts +286 -85
- package/src/modes/rpc/rpc-types.ts +15 -1
- package/src/modes/shared/agent-wire/command-dispatch.ts +33 -1
- package/src/modes/shared/agent-wire/command-validation.ts +10 -0
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +45 -2
- package/src/modes/shared/agent-wire/scopes.ts +1 -0
- package/src/modes/shared/agent-wire/unattended-session.ts +288 -1
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +130 -20
- package/src/modes/types.ts +34 -2
- package/src/modes/utils/context-usage.ts +56 -92
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/irc-message.ts +138 -0
- package/src/modes/utils/ui-helpers.ts +216 -50
- package/src/notifications/config.ts +44 -0
- package/src/notifications/daemon-paths.ts +8 -0
- package/src/notifications/index.ts +535 -75
- package/src/notifications/lifecycle-control-runtime.ts +930 -77
- package/src/notifications/notification-service.ts +710 -0
- package/src/notifications/rate-limit-pool.ts +46 -12
- package/src/notifications/telegram-daemon-control.ts +27 -2
- package/src/notifications/telegram-daemon.ts +635 -94
- package/src/notifications/telegram-reference.ts +73 -13
- package/src/notifications/topic-registry.ts +86 -9
- package/src/prompts/system/irc-peer-roster.md +1 -0
- package/src/prompts/system/subagent-system-prompt.md +1 -0
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/prompts/tools/irc.md +1 -1
- package/src/registry/agent-registry.ts +3 -0
- package/src/sdk.ts +52 -1
- package/src/secrets/obfuscator.ts +4 -2
- package/src/session/agent-session.ts +670 -217
- package/src/session/cache-economics.ts +275 -0
- package/src/session/context-estimation.ts +91 -0
- package/src/session/provider-safety-stop.ts +9 -0
- package/src/session/session-dump-format.ts +6 -0
- package/src/session/session-manager.ts +809 -39
- package/src/session/session-storage.ts +582 -38
- package/src/skc-runtime/session-state-sidecar.ts +756 -135
- package/src/skc-runtime/tmux-common.ts +26 -7
- package/src/skc-runtime/tmux-gc.ts +52 -9
- package/src/skc-runtime/tmux-owner-isolation-cli.ts +185 -0
- package/src/skc-runtime/tmux-owner-isolation.ts +2060 -0
- package/src/skc-runtime/tmux-sessions.ts +871 -68
- package/src/slash-commands/builtin-registry.ts +153 -9
- package/src/slash-commands/helpers/context-report.ts +26 -4
- package/src/task/executor.ts +12 -3
- package/src/task/index.ts +8 -0
- package/src/task/receipt.ts +7 -2
- package/src/task/types.ts +26 -0
- package/src/tools/ask-answer-registry.ts +25 -0
- package/src/tools/browser/tab-supervisor.ts +63 -6
- package/src/tools/browser.ts +8 -3
- package/src/tools/index.ts +81 -6
- package/src/tools/sqlite-reader.ts +8 -4
- package/src/tui/output-block.ts +18 -6
- package/src/utils/external-editor.ts +6 -1
|
@@ -21,10 +21,14 @@ import type { EvalExecutionComponent } from "./components/eval-execution";
|
|
|
21
21
|
import type { HookEditorComponent } from "./components/hook-editor";
|
|
22
22
|
import type { HookInputComponent } from "./components/hook-input";
|
|
23
23
|
import type { HookSelectorComponent } from "./components/hook-selector";
|
|
24
|
+
import type { PetMode } from "./components/sayknow-pet-widget";
|
|
24
25
|
import type { StatusLineComponent } from "./components/status-line";
|
|
25
26
|
import type { ToolExecutionHandle } from "./components/tool-execution";
|
|
27
|
+
import type { IrcObservationLedger } from "./irc-observation-ledger";
|
|
26
28
|
import type { OAuthManualInputManager } from "./oauth-manual-input";
|
|
27
29
|
import type { Theme } from "./theme/theme";
|
|
30
|
+
import type { ParsedIrcMessage } from "./utils/irc-message";
|
|
31
|
+
export type TranscriptRebuildPolicy = "replace-identity" | "reconcile-same-transcript";
|
|
28
32
|
export type CompactionQueuedMessage = {
|
|
29
33
|
text: string;
|
|
30
34
|
mode: "steer" | "followUp";
|
|
@@ -49,6 +53,13 @@ export type TodoPhase = {
|
|
|
49
53
|
name: string;
|
|
50
54
|
tasks: TodoItem[];
|
|
51
55
|
};
|
|
56
|
+
export type IrcArrivalSnapshot = Readonly<{
|
|
57
|
+
panelVisible: boolean;
|
|
58
|
+
/** User-requested open state; may be true while the panel yields at narrow widths. */
|
|
59
|
+
panelRequestedVisible: boolean;
|
|
60
|
+
sidebarAvailable: boolean;
|
|
61
|
+
resolvedToggleKey: string | null;
|
|
62
|
+
}>;
|
|
52
63
|
export interface InteractiveModeContext {
|
|
53
64
|
ui: TUI;
|
|
54
65
|
chatContainer: Container;
|
|
@@ -69,6 +80,7 @@ export interface InteractiveModeContext {
|
|
|
69
80
|
historyStorage?: HistoryStorage;
|
|
70
81
|
mcpManager?: MCPManager;
|
|
71
82
|
lspServers?: LspStartupServerInfo[];
|
|
83
|
+
readonly ircLedger: IrcObservationLedger;
|
|
72
84
|
isInitialized: boolean;
|
|
73
85
|
isBackgrounded: boolean;
|
|
74
86
|
isBashMode: boolean;
|
|
@@ -141,6 +153,11 @@ export interface InteractiveModeContext {
|
|
|
141
153
|
setWorkingMessage(message?: string): void;
|
|
142
154
|
applyPendingWorkingMessage(): void;
|
|
143
155
|
ensureLoadingAnimation(): void;
|
|
156
|
+
setPetMode(mode: PetMode): void;
|
|
157
|
+
/** Live-preview a pet skin during a selector without persisting. */
|
|
158
|
+
previewPetMode(mode: PetMode): void;
|
|
159
|
+
/** Re-mount the composer (pet-aware) after an overlay/selector closes. */
|
|
160
|
+
restoreComposer(): void;
|
|
144
161
|
startPendingSubmission(input: {
|
|
145
162
|
text: string;
|
|
146
163
|
images?: ImageContent[];
|
|
@@ -169,22 +186,30 @@ export interface InteractiveModeContext {
|
|
|
169
186
|
addMessageToChat(message: AgentMessage, options?: {
|
|
170
187
|
populateHistory?: boolean;
|
|
171
188
|
}): Component[];
|
|
189
|
+
addLiveIrcObservationToChat(message: ParsedIrcMessage, arrival: IrcArrivalSnapshot): Component[];
|
|
190
|
+
removeRenderedIrcInlineComponents(observationId: string): readonly Component[] | undefined;
|
|
191
|
+
resetRenderedIrcInlineComponents(): readonly (readonly Component[])[];
|
|
172
192
|
renderSessionContext(sessionContext: SessionContext, options?: {
|
|
173
193
|
updateFooter?: boolean;
|
|
174
194
|
populateHistory?: boolean;
|
|
175
195
|
}): void;
|
|
176
|
-
|
|
196
|
+
rebuildInitialMessages(policy: TranscriptRebuildPolicy, prebuiltContext?: SessionContext, options?: {
|
|
177
197
|
preserveExistingChat?: boolean;
|
|
178
198
|
}): void;
|
|
179
199
|
getUserMessageText(message: Message): string;
|
|
200
|
+
getAssistantViewportAnchorId?(message: AssistantMessage): string;
|
|
180
201
|
findLastAssistantMessage(): AssistantMessage | undefined;
|
|
181
202
|
extractAssistantText(message: AssistantMessage): string;
|
|
182
203
|
updateEditorTopBorder(): void;
|
|
183
204
|
updateEditorBorderColor(): void;
|
|
184
|
-
rebuildChatFromMessages(): void;
|
|
205
|
+
rebuildChatFromMessages(policy: TranscriptRebuildPolicy): void;
|
|
185
206
|
setTodos(todos: TodoItem[] | TodoPhase[]): void;
|
|
186
207
|
reloadTodos(): Promise<void>;
|
|
187
208
|
toggleTodoExpansion(): void;
|
|
209
|
+
toggleIrcSidebar(): void;
|
|
210
|
+
captureIrcArrivalSnapshot(): IrcArrivalSnapshot;
|
|
211
|
+
applyIrcSidebarAvailability(enabled: boolean): void;
|
|
212
|
+
resetIrcSidebarSession(): void;
|
|
188
213
|
handleExportCommand(text: string): Promise<void>;
|
|
189
214
|
handleShareCommand(): Promise<void>;
|
|
190
215
|
handleCopyCommand(sub?: string): void;
|
|
@@ -219,6 +244,7 @@ export interface InteractiveModeContext {
|
|
|
219
244
|
refreshSlashCommandState(cwd?: string): Promise<void>;
|
|
220
245
|
showSettingsSelector(): void;
|
|
221
246
|
showThemeSelector(): void;
|
|
247
|
+
showPetSelector(): void;
|
|
222
248
|
showHistorySearch(): void;
|
|
223
249
|
showExtensionsDashboard(): void;
|
|
224
250
|
showAgentsDashboard(): void;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { AgentMessage } from "@sayknow-cli/agent-core";
|
|
2
2
|
import type { Model } from "@sayknow-cli/ai";
|
|
3
|
-
import type { Skill } from "../../extensibility/skills";
|
|
4
3
|
import type { AgentSession } from "../../session/agent-session";
|
|
5
|
-
import type { Tool } from "../../tools";
|
|
6
4
|
import type { theme as Theme } from "../theme/theme";
|
|
5
|
+
export { computeNonMessageTokens, estimateSkillsTokens, estimateToolSchemaTokens, } from "../../session/context-estimation";
|
|
7
6
|
type CategoryId = "systemPrompt" | "systemContext" | "rules" | "tools" | "skills" | "messages" | "lastUserTurn";
|
|
8
7
|
interface CategoryInfo {
|
|
9
8
|
id: CategoryId;
|
|
@@ -17,25 +16,12 @@ export interface ContextBreakdown {
|
|
|
17
16
|
contextWindow: number;
|
|
18
17
|
categories: CategoryInfo[];
|
|
19
18
|
lastUserTurnTokens: number;
|
|
20
|
-
|
|
19
|
+
estimatedCategoryTotal: number;
|
|
20
|
+
usedTokens: number | null;
|
|
21
|
+
source: "provider_anchor" | "heuristic" | "unknown";
|
|
21
22
|
autoCompactBufferTokens: number;
|
|
22
23
|
freeTokens: number;
|
|
23
24
|
}
|
|
24
|
-
export declare function estimateSkillsTokens(skills: readonly Skill[]): number;
|
|
25
|
-
export declare function estimateToolSchemaTokens(tools: ReadonlyArray<Pick<Tool, "name" | "description" | "parameters">>): number;
|
|
26
|
-
/**
|
|
27
|
-
* Compute just the NON-MESSAGE token total: system prompt (with its skills
|
|
28
|
-
* section subtracted, since skills are tokenized separately) + system context
|
|
29
|
-
* (the rest of the system-prompt array) + tools + skills.
|
|
30
|
-
*
|
|
31
|
-
* Exposed so callers like `StatusLineComponent` can cache the non-message
|
|
32
|
-
* total separately from the message total. Non-message inputs (skills,
|
|
33
|
-
* tools, system prompt) change rarely; the message list grows on every
|
|
34
|
-
* streaming turn. Splitting the two lets the caller refresh each on its own
|
|
35
|
-
* cadence — non-message recomputed only when the inputs identity changes,
|
|
36
|
-
* messages walked incrementally as new entries append.
|
|
37
|
-
*/
|
|
38
|
-
export declare function computeNonMessageTokens(session: AgentSession): number;
|
|
39
25
|
/**
|
|
40
26
|
* Compute a breakdown of estimated context usage by category for the active
|
|
41
27
|
* session and model.
|
|
@@ -48,4 +34,3 @@ export declare function computeContextBreakdown(session: AgentSession, options?:
|
|
|
48
34
|
* lines pairing the grid (left) with the legend (right).
|
|
49
35
|
*/
|
|
50
36
|
export declare function renderContextUsage(breakdown: ContextBreakdown, theme: typeof Theme): string;
|
|
51
|
-
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AgentMessage } from "@sayknow-cli/agent-core";
|
|
2
|
+
export type IrcMessageKind = "incoming" | "autoreply" | "relay";
|
|
3
|
+
export type ParsedIrcMessage = {
|
|
4
|
+
observationId: string;
|
|
5
|
+
from: string;
|
|
6
|
+
to: string;
|
|
7
|
+
text: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
kind: IrcMessageKind;
|
|
10
|
+
};
|
|
11
|
+
export interface IrcMessageBlock {
|
|
12
|
+
readonly sender: string;
|
|
13
|
+
readonly recipient: string;
|
|
14
|
+
readonly kind: "incoming" | "autoreply" | "outgoing";
|
|
15
|
+
readonly time: string;
|
|
16
|
+
readonly bodyLines: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
export declare function projectIrcText(text: string, maxUtf8Bytes: number): {
|
|
19
|
+
text: string;
|
|
20
|
+
truncated: boolean;
|
|
21
|
+
utf8Bytes: number;
|
|
22
|
+
};
|
|
23
|
+
/** Normalizes and bounds untrusted IRC identity fields without splitting visible graphemes. */
|
|
24
|
+
export declare function normalizeIrcIdentity(identity: string): string;
|
|
25
|
+
/** Formats IRC observations into display-neutral semantic blocks for both IRC surfaces. */
|
|
26
|
+
export declare function formatIrcMessageBlock(message: ParsedIrcMessage & {
|
|
27
|
+
timestamp: number;
|
|
28
|
+
}): IrcMessageBlock;
|
|
29
|
+
type IrcCustomMessage = Extract<AgentMessage, {
|
|
30
|
+
role: "custom";
|
|
31
|
+
}>;
|
|
32
|
+
export declare function isIrcCustomType(customType: string | undefined): customType is `irc:${IrcMessageKind}`;
|
|
33
|
+
/**
|
|
34
|
+
* Normalizes every supported IRC custom message into its UI observation shape.
|
|
35
|
+
* Legacy records have no UUID, so their immutable payload is used as a stable key.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseIrcMessage(message: IrcCustomMessage): ParsedIrcMessage | undefined;
|
|
38
|
+
export {};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { AgentMessage } from "@sayknow-cli/agent-core";
|
|
2
2
|
import type { AssistantMessage, Message } from "@sayknow-cli/ai";
|
|
3
|
-
import { type Component } from "@sayknow-cli/tui";
|
|
4
|
-
import type { InteractiveModeContext } from "../../modes/types";
|
|
5
|
-
import type
|
|
3
|
+
import { type Component, type TUI } from "@sayknow-cli/tui";
|
|
4
|
+
import type { InteractiveModeContext, IrcArrivalSnapshot, TranscriptRebuildPolicy } from "../../modes/types";
|
|
5
|
+
import { type SessionContext } from "../../session/session-manager";
|
|
6
|
+
import { type ParsedIrcMessage } from "./irc-message";
|
|
7
|
+
export type { TranscriptRebuildPolicy } from "../../modes/types";
|
|
8
|
+
export declare function prepareTranscriptRebuild(ui: TUI, policy: TranscriptRebuildPolicy): void;
|
|
6
9
|
interface RenderInitialMessagesOptions {
|
|
7
10
|
preserveExistingChat?: boolean;
|
|
8
11
|
}
|
|
@@ -23,6 +26,13 @@ export declare class UiHelpers {
|
|
|
23
26
|
#private;
|
|
24
27
|
private ctx;
|
|
25
28
|
constructor(ctx: InteractiveModeContext);
|
|
29
|
+
assistantViewportAnchorId(message: AssistantMessage): string;
|
|
30
|
+
getRenderedIrcInlineComponents(): Map<string, readonly Component[]>;
|
|
31
|
+
removeRenderedIrcInlineComponents(observationId: string): readonly Component[] | undefined;
|
|
32
|
+
resetRenderedIrcInlineComponents(): readonly (readonly Component[])[];
|
|
33
|
+
addLiveIrcObservationToChat(message: ParsedIrcMessage, arrival: IrcArrivalSnapshot): Component[];
|
|
34
|
+
addRebuiltIrcObservationToChat(message: ParsedIrcMessage): Component[];
|
|
35
|
+
resetIrcSidebarHint(): void;
|
|
26
36
|
/** Extract text content from a user message */
|
|
27
37
|
getUserMessageText(message: Message): string;
|
|
28
38
|
/**
|
|
@@ -63,4 +73,3 @@ export declare class UiHelpers {
|
|
|
63
73
|
findLastAssistantMessage(): AssistantMessage | undefined;
|
|
64
74
|
extractAssistantText(message: AssistantMessage): string;
|
|
65
75
|
}
|
|
66
|
-
export {};
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { Settings } from "../config/settings";
|
|
2
|
+
/**
|
|
3
|
+
* Env marker set by SKC's own programmatic separate-process child spawn sites
|
|
4
|
+
* (team workers, harness RPC owners) and carrying the spawning session id.
|
|
5
|
+
*
|
|
6
|
+
* Presence — not the value — marks a session as SKC-spawned. It is consumed
|
|
7
|
+
* (read once, then deleted from the child's own env) at startup so it is
|
|
8
|
+
* per-spawn rather than dynastic: a grandchild is marked only if its own spawn
|
|
9
|
+
* site marks it, never by inheriting a marked ancestor's environment.
|
|
10
|
+
*/
|
|
11
|
+
export declare const SPAWN_PROVENANCE_ENV = "SKC_SPAWNED_BY_SESSION";
|
|
2
12
|
export interface NotificationConfig {
|
|
3
13
|
enabled: boolean;
|
|
4
14
|
botToken?: string;
|
|
@@ -13,6 +23,12 @@ export interface NotificationConfig {
|
|
|
13
23
|
};
|
|
14
24
|
redact: boolean;
|
|
15
25
|
verbosity: "lean" | "verbose";
|
|
26
|
+
/**
|
|
27
|
+
* Which sessions may register a notification endpoint. `all` (default)
|
|
28
|
+
* preserves historical behavior; `primary` suppresses SKC-spawned children
|
|
29
|
+
* (those carrying {@link SPAWN_PROVENANCE_ENV}) unless they explicitly opt in.
|
|
30
|
+
*/
|
|
31
|
+
sessionScope: "all" | "primary";
|
|
16
32
|
idleTimeoutMs: number;
|
|
17
33
|
rich: {
|
|
18
34
|
enabled: boolean;
|
|
@@ -20,6 +36,15 @@ export interface NotificationConfig {
|
|
|
20
36
|
richDraft: {
|
|
21
37
|
enabled: boolean;
|
|
22
38
|
};
|
|
39
|
+
topics: {
|
|
40
|
+
/**
|
|
41
|
+
* Optional Telegram forum-topic name template with `{repo}`, `{branch}`,
|
|
42
|
+
* and `{title}` placeholders. Unset preserves the built-in
|
|
43
|
+
* `{repo}/{branch} - {title}` composition (with its title/repo/branch
|
|
44
|
+
* fallbacks).
|
|
45
|
+
*/
|
|
46
|
+
nameTemplate?: string;
|
|
47
|
+
};
|
|
23
48
|
}
|
|
24
49
|
/** Read typed config from Settings. */
|
|
25
50
|
export declare function getNotificationConfig(settings: Settings): NotificationConfig;
|
|
@@ -51,6 +76,15 @@ export declare function shouldRegisterNotificationsExtension(input: {
|
|
|
51
76
|
parentTaskPrefix?: string;
|
|
52
77
|
/** Role-agent type/name; present for task sessions even if depth metadata is lost. */
|
|
53
78
|
currentAgentType?: string;
|
|
79
|
+
/**
|
|
80
|
+
* True when this session was launched by one of SKC's own programmatic
|
|
81
|
+
* separate-process child spawn sites (marked via {@link SPAWN_PROVENANCE_ENV}).
|
|
82
|
+
* Under `notifications.sessionScope = "primary"` such children are suppressed
|
|
83
|
+
* unless they explicitly opt in, so an interactive parent that fans out work
|
|
84
|
+
* does not flood the paired chat with topics for children the user never
|
|
85
|
+
* asked for. User-opened sessions (CLI/tmux/headless) never carry the marker.
|
|
86
|
+
*/
|
|
87
|
+
spawnedBySkc?: boolean;
|
|
54
88
|
}): boolean;
|
|
55
89
|
/**
|
|
56
90
|
* Resolve whether THIS session should run notifications.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owner heartbeat freshness window. A daemon ownership record older than this
|
|
3
|
+
* (without a live pid) is considered stale. Lives here, in the lightweight
|
|
4
|
+
* paths module, so secret-safe consumers (e.g. the notification service) can
|
|
5
|
+
* reuse it without importing the heavy daemon runtime.
|
|
6
|
+
*/
|
|
7
|
+
export declare const HEARTBEAT_TTL_MS = 20000;
|
|
1
8
|
export interface DaemonPaths {
|
|
2
9
|
dir: string;
|
|
3
10
|
lock: string;
|
|
@@ -176,6 +176,33 @@ export interface SessionReadyFrame {
|
|
|
176
176
|
*/
|
|
177
177
|
export declare function readGitRepoName(cwd: string): string | undefined;
|
|
178
178
|
export declare function notificationsEnabled(): boolean;
|
|
179
|
+
/** Workflow-gate answer shape (unattended mode). */
|
|
180
|
+
interface GateAnswer {
|
|
181
|
+
selected: string[];
|
|
182
|
+
other?: boolean;
|
|
183
|
+
custom?: string;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Discriminated result of mapping a client answer to a workflow-gate answer.
|
|
187
|
+
* `ok: false` means the reply is invalid and the caller must close the exact
|
|
188
|
+
* claim/receipt and reissue the interaction rather than durably accepting it.
|
|
189
|
+
*/
|
|
190
|
+
type GateAnswerResult = {
|
|
191
|
+
ok: true;
|
|
192
|
+
answer: GateAnswer;
|
|
193
|
+
} | {
|
|
194
|
+
ok: false;
|
|
195
|
+
reason: string;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Map a client answer to the workflow-gate answer shape (unattended mode).
|
|
199
|
+
*
|
|
200
|
+
* The protocol defines a numeric reply as an option index, so a number outside
|
|
201
|
+
* `options` is invalid (issue #2030): it must NOT be converted into a free-text
|
|
202
|
+
* `Other` that passes the ask schema and triggers a misleading success ack.
|
|
203
|
+
* Only JSON strings enter the free-text/Other path.
|
|
204
|
+
*/
|
|
205
|
+
export declare function mapAnswerToGate(answerJson: string, options: string[]): GateAnswerResult;
|
|
179
206
|
interface NotificationControlCommandPayload {
|
|
180
207
|
name?: unknown;
|
|
181
208
|
action?: unknown;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type OwnerIsolationProbe } from "../skc-runtime/tmux-owner-isolation";
|
|
2
|
+
import { type SkcTmuxSessionStatus } from "../skc-runtime/tmux-sessions";
|
|
1
3
|
import type { ResumeCandidate, SessionCreateFrame, SessionLifecycleRequest, SessionLifecycleResponse } from "./index";
|
|
2
4
|
import { type AuditEvent, type CreateEffectResult, type LedgerStore, type LifecycleOutcome, type OrchestratorDeps, type ResumeEffectResult } from "./lifecycle-orchestrator";
|
|
3
5
|
/** Minimal view of the native control server this runtime depends on. */
|
|
@@ -24,7 +26,6 @@ export type LifecycleControlServerFactory = (input: {
|
|
|
24
26
|
ownerId: string;
|
|
25
27
|
agentDir: string;
|
|
26
28
|
}) => LifecycleControlServer;
|
|
27
|
-
/** Atomic + fsynced file-backed idempotency ledger store. */
|
|
28
29
|
export declare function fileLedgerStore(idempotencyFile: string): LedgerStore;
|
|
29
30
|
/** Append-only JSONL audit sink (0600). Never receives tokens or raw prompts. */
|
|
30
31
|
export declare function fileAudit(auditPath: string): (e: AuditEvent) => void;
|
|
@@ -44,14 +45,19 @@ export declare function buildCreateArgv(frame: SessionCreateFrame, _ids: {
|
|
|
44
45
|
cwd: string;
|
|
45
46
|
args: string[];
|
|
46
47
|
};
|
|
47
|
-
/** Real daemon-safe tmux launcher:
|
|
48
|
-
export declare function daemonSpawnCreate(env?: NodeJS.ProcessEnv
|
|
48
|
+
/** Real daemon-safe tmux launcher: canonical owner-isolation plan + SKC tags. */
|
|
49
|
+
export declare function daemonSpawnCreate(env?: NodeJS.ProcessEnv, opts?: {
|
|
50
|
+
ownerIsolationProbe?: OwnerIsolationProbe;
|
|
51
|
+
}): (frame: SessionCreateFrame, ids: {
|
|
49
52
|
lifecycleRequestId: string;
|
|
50
53
|
intendedSessionId: string;
|
|
51
54
|
startupPromptRef?: string;
|
|
52
55
|
}) => Promise<CreateEffectResult>;
|
|
53
56
|
/** Real force-close effect (SKC-managed only, id-matched). */
|
|
54
|
-
export declare function daemonCloseSession(env?: NodeJS.ProcessEnv
|
|
57
|
+
export declare function daemonCloseSession(env?: NodeJS.ProcessEnv, deps?: {
|
|
58
|
+
forceClose?: (name: string, env: NodeJS.ProcessEnv, expectedSessionId?: string, sessionStateFile?: string) => Promise<void>;
|
|
59
|
+
findSession?: (name: string, env: NodeJS.ProcessEnv) => SkcTmuxSessionStatus | undefined;
|
|
60
|
+
}): (target: {
|
|
55
61
|
sessionId: string;
|
|
56
62
|
tmuxSession?: string;
|
|
57
63
|
sessionStateFile?: string;
|
|
@@ -63,6 +69,8 @@ export declare function daemonCloseSession(env?: NodeJS.ProcessEnv): (target: {
|
|
|
63
69
|
* cold-restarting exactly one resolved session via the daemon-safe launcher. */
|
|
64
70
|
export declare function daemonResumeSession(env?: NodeJS.ProcessEnv, opts?: {
|
|
65
71
|
sessionsRoot?: string;
|
|
72
|
+
listSessions?: (env: NodeJS.ProcessEnv) => SkcTmuxSessionStatus[];
|
|
73
|
+
ownerIsolationProbe?: OwnerIsolationProbe;
|
|
66
74
|
}): (target: {
|
|
67
75
|
sessionIdOrPrefix: string;
|
|
68
76
|
path?: string;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { Settings } from "../config/settings";
|
|
2
|
+
/**
|
|
3
|
+
* Strip secrets from a human-facing diagnostic string. Redacts the configured
|
|
4
|
+
* bot token (exact match) and any token-shaped substring so health/test details
|
|
5
|
+
* can never leak a credential regardless of where the string originated.
|
|
6
|
+
*/
|
|
7
|
+
export declare function sanitizeDiagnostic(text: string, token?: string): string;
|
|
8
|
+
/** Minimal filesystem surface the service needs; injectable for tests. */
|
|
9
|
+
export interface NotificationServiceFs {
|
|
10
|
+
readdir(dir: string): Promise<string[]>;
|
|
11
|
+
readFile(file: string, encoding: "utf8"): Promise<string>;
|
|
12
|
+
unlink(file: string): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Atomically create `file` with O_EXCL semantics: resolves `true` when this
|
|
15
|
+
* call created it, `false` when it already existed. Used to hold the daemon
|
|
16
|
+
* steal-mutex ({@link DaemonPaths.steal}) during owner-bound lock removal so
|
|
17
|
+
* recovery and a concurrent daemon takeover are mutually exclusive.
|
|
18
|
+
*/
|
|
19
|
+
createExclusive(file: string): Promise<boolean>;
|
|
20
|
+
}
|
|
21
|
+
/** Injectable dependencies shared across service operations. */
|
|
22
|
+
export interface NotificationServiceDeps {
|
|
23
|
+
fs?: NotificationServiceFs;
|
|
24
|
+
now?: () => number;
|
|
25
|
+
pidAlive?: (pid: number) => boolean;
|
|
26
|
+
fetchImpl?: typeof fetch;
|
|
27
|
+
apiBase?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface AdapterConfigView {
|
|
30
|
+
botTokenMasked: string;
|
|
31
|
+
channel: string | undefined;
|
|
32
|
+
configured: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface NotificationStatusReport {
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
redact: boolean;
|
|
37
|
+
verbosity: "lean" | "verbose";
|
|
38
|
+
globallyConfigured: boolean;
|
|
39
|
+
telegram: AdapterConfigView & {
|
|
40
|
+
tokenFingerprint: string | undefined;
|
|
41
|
+
};
|
|
42
|
+
discord: AdapterConfigView;
|
|
43
|
+
slack: AdapterConfigView;
|
|
44
|
+
}
|
|
45
|
+
/** Build a secret-safe structured status snapshot from settings. */
|
|
46
|
+
export declare function buildNotificationStatusReport(settings: Settings): NotificationStatusReport;
|
|
47
|
+
/** Render a status report as human-readable lines (no secrets). */
|
|
48
|
+
export declare function formatNotificationStatusReport(report: NotificationStatusReport): string;
|
|
49
|
+
export type HealthLevel = "ok" | "warn" | "error";
|
|
50
|
+
export interface HealthCheck {
|
|
51
|
+
name: string;
|
|
52
|
+
level: HealthLevel;
|
|
53
|
+
detail: string;
|
|
54
|
+
}
|
|
55
|
+
export interface DaemonHealth {
|
|
56
|
+
present: boolean;
|
|
57
|
+
ownerId: string | undefined;
|
|
58
|
+
pid: number | undefined;
|
|
59
|
+
alive: boolean;
|
|
60
|
+
heartbeatFresh: boolean;
|
|
61
|
+
identityMatches: boolean;
|
|
62
|
+
stopped: boolean;
|
|
63
|
+
}
|
|
64
|
+
export interface EndpointHealth {
|
|
65
|
+
total: number;
|
|
66
|
+
live: number;
|
|
67
|
+
dead: number;
|
|
68
|
+
unknown: number;
|
|
69
|
+
unreadable: number;
|
|
70
|
+
}
|
|
71
|
+
export interface NotificationHealthReport {
|
|
72
|
+
overall: HealthLevel;
|
|
73
|
+
configured: boolean;
|
|
74
|
+
checks: HealthCheck[];
|
|
75
|
+
daemon: DaemonHealth;
|
|
76
|
+
endpoints: EndpointHealth;
|
|
77
|
+
reachability: {
|
|
78
|
+
probed: boolean;
|
|
79
|
+
ok: boolean;
|
|
80
|
+
detail: string;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export interface HealthOptions {
|
|
84
|
+
settings: Settings;
|
|
85
|
+
stateRoot?: string;
|
|
86
|
+
deps?: NotificationServiceDeps;
|
|
87
|
+
/** When true and Telegram is configured, probe the Bot API (getMe) for reachability. */
|
|
88
|
+
probe?: boolean;
|
|
89
|
+
}
|
|
90
|
+
/** Structural (offline-by-default) health of the notification subsystem. */
|
|
91
|
+
export declare function checkNotificationHealth(opts: HealthOptions): Promise<NotificationHealthReport>;
|
|
92
|
+
/** Render a health report as human-readable lines (no secrets). */
|
|
93
|
+
export declare function formatNotificationHealthReport(report: NotificationHealthReport): string;
|
|
94
|
+
export interface NotificationTestResult {
|
|
95
|
+
ok: boolean;
|
|
96
|
+
adapter: "telegram";
|
|
97
|
+
chatId: string | undefined;
|
|
98
|
+
detail: string;
|
|
99
|
+
}
|
|
100
|
+
export interface TestOptions {
|
|
101
|
+
settings: Settings;
|
|
102
|
+
deps?: NotificationServiceDeps;
|
|
103
|
+
text?: string;
|
|
104
|
+
}
|
|
105
|
+
/** Send a one-off test notification through the configured Telegram adapter. */
|
|
106
|
+
export declare function sendNotificationTest(opts: TestOptions): Promise<NotificationTestResult>;
|
|
107
|
+
/** Render a test result as a single human-readable line (no secrets). */
|
|
108
|
+
export declare function formatNotificationTestResult(result: NotificationTestResult): string;
|
|
109
|
+
export interface RecoveredEndpoint {
|
|
110
|
+
sessionId: string;
|
|
111
|
+
pid: number | undefined;
|
|
112
|
+
reason: "stale-flag" | "dead-pid";
|
|
113
|
+
}
|
|
114
|
+
export type DaemonRecoveryAction = "none" | "cleared-dead-owner-lock" | "left-active" | "left-contended" | "owner-superseded" | "orphan-lock-left";
|
|
115
|
+
export interface NotificationRecoveryReport {
|
|
116
|
+
endpointsScanned: number;
|
|
117
|
+
endpointsRemoved: RecoveredEndpoint[];
|
|
118
|
+
endpointsKept: number;
|
|
119
|
+
endpointsUnreadable: number;
|
|
120
|
+
daemon: {
|
|
121
|
+
action: DaemonRecoveryAction;
|
|
122
|
+
detail: string;
|
|
123
|
+
ownerId: string | undefined;
|
|
124
|
+
pid: number | undefined;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export interface RecoveryOptions {
|
|
128
|
+
settings: Settings;
|
|
129
|
+
stateRoot?: string;
|
|
130
|
+
deps?: NotificationServiceDeps;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Ownership-protected cleanup. Removes only DEAD-owner artifacts:
|
|
134
|
+
* per-session endpoint files with positive proof of death (a stale tombstone or
|
|
135
|
+
* a dead recorded pid), and a daemon lock whose recorded owner is confirmed
|
|
136
|
+
* dead. A PID-less endpoint is treated as unknown (not dead) and kept. The
|
|
137
|
+
* daemon lock is removed through {@link removeDeadOwnerLock}, an owner-bound
|
|
138
|
+
* primitive that re-checks ownership under the daemon steal-mutex so it can
|
|
139
|
+
* never race a concurrent takeover. Never removes a live owner's lock, never
|
|
140
|
+
* deletes unreadable files, and never kills a process.
|
|
141
|
+
*/
|
|
142
|
+
export declare function recoverNotifications(opts: RecoveryOptions): Promise<NotificationRecoveryReport>;
|
|
143
|
+
/** Render a recovery report as human-readable lines (no secrets). */
|
|
144
|
+
export declare function formatNotificationRecoveryReport(report: NotificationRecoveryReport): string;
|
|
@@ -29,11 +29,15 @@ export interface RateLimitItem<T = unknown> {
|
|
|
29
29
|
/** Priority lane. */
|
|
30
30
|
lane: RateLimitLane;
|
|
31
31
|
/**
|
|
32
|
-
* Optional coalesce key. Submitting another item with the
|
|
33
|
-
* `(sessionId, lane, coalesceKey)` replaces the queued payload with
|
|
34
|
-
* newer one instead of enqueuing a duplicate (used for live edits).
|
|
32
|
+
* Optional coalesce key. Submitting another unidentifiable item with the
|
|
33
|
+
* same `(sessionId, lane, coalesceKey)` replaces the queued payload with
|
|
34
|
+
* the newer one instead of enqueuing a duplicate (used for live edits).
|
|
35
35
|
*/
|
|
36
36
|
coalesceKey?: string;
|
|
37
|
+
/** Optional stable identifier for exact queued-item removal. Identified items never coalesce. */
|
|
38
|
+
itemId?: string;
|
|
39
|
+
/** Absolute Unix timestamp in ms. The item expires when `now >= deadlineAt`. */
|
|
40
|
+
deadlineAt?: number;
|
|
37
41
|
/** Opaque payload the caller maps to an actual Telegram send. */
|
|
38
42
|
payload: T;
|
|
39
43
|
}
|
|
@@ -46,6 +50,13 @@ export interface RateLimitPoolOptions {
|
|
|
46
50
|
/** Injectable clock in ms. Default `Date.now`. */
|
|
47
51
|
now?: () => number;
|
|
48
52
|
}
|
|
53
|
+
/** The deterministic result of draining queued work at a point in time. */
|
|
54
|
+
export interface RateLimitDrainResult<T = unknown> {
|
|
55
|
+
/** Items granted a token and ready to send. */
|
|
56
|
+
granted: RateLimitItem<T>[];
|
|
57
|
+
/** Items removed because their absolute deadline has elapsed. */
|
|
58
|
+
expired: RateLimitItem<T>[];
|
|
59
|
+
}
|
|
49
60
|
/**
|
|
50
61
|
* A deterministic, pull-based shared rate-limit scheduler.
|
|
51
62
|
*
|
|
@@ -70,19 +81,26 @@ export declare class RateLimitPool<T = unknown> {
|
|
|
70
81
|
/** Current available token count (after refill at `now`). */
|
|
71
82
|
availableTokens(nowMs?: number): number;
|
|
72
83
|
/**
|
|
73
|
-
* Submit an item.
|
|
74
|
-
* the same `(sessionId, lane)
|
|
75
|
-
*
|
|
84
|
+
* Submit an item. Unidentified items with a `coalesceKey` matching a queued
|
|
85
|
+
* item in the same `(sessionId, lane)` replace its payload (latest wins)
|
|
86
|
+
* while preserving FIFO position; identified items are always appended.
|
|
76
87
|
*/
|
|
77
88
|
submit(item: RateLimitItem<T>): void;
|
|
78
89
|
/**
|
|
79
|
-
* Grant as many queued items as tokens allow at `nowMs`.
|
|
80
|
-
*
|
|
81
|
-
* single session monopolises a lane), consuming one token each.
|
|
90
|
+
* Grant as many queued items as tokens allow at `nowMs`. This compatibility
|
|
91
|
+
* wrapper discards items that expired during the drain.
|
|
82
92
|
*/
|
|
83
93
|
drain(nowMs?: number): RateLimitItem<T>[];
|
|
94
|
+
/**
|
|
95
|
+
* Deterministically expire elapsed-deadline items, then grant as many live
|
|
96
|
+
* items as tokens allow. Expired items never consume tokens or receive a
|
|
97
|
+
* grant; both result lists preserve their deterministic queue ordering.
|
|
98
|
+
*/
|
|
99
|
+
drainWithExpired(nowMs?: number): RateLimitDrainResult<T>;
|
|
84
100
|
/** Remove queued items matching `predicate` without consuming tokens. Returns removed items in lane/FIFO order. */
|
|
85
101
|
removeWhere(predicate: (item: RateLimitItem<T>) => boolean): RateLimitItem<T>[];
|
|
102
|
+
/** Remove exactly one queued item by its stable id without consuming a token. */
|
|
103
|
+
removeById(itemId: string): RateLimitItem<T> | undefined;
|
|
86
104
|
private refill;
|
|
87
105
|
/** Pop the next item by lane priority + per-session round-robin fairness. */
|
|
88
106
|
private takeNext;
|
|
@@ -55,10 +55,16 @@ export declare class TelegramDaemonController implements BuiltInDaemonController
|
|
|
55
55
|
status(): Promise<DaemonStatus>;
|
|
56
56
|
private spawnDeps;
|
|
57
57
|
private sleep;
|
|
58
|
+
/**
|
|
59
|
+
* Wait until the captured pid is dead. Ownership-file movement is NOT treated
|
|
60
|
+
* as quiescence here: only actual process death proves the old poller stopped,
|
|
61
|
+
* which is what the no-409 invariant requires before spawning a fresh poller.
|
|
62
|
+
*/
|
|
58
63
|
private waitForPidDeath;
|
|
59
64
|
private result;
|
|
60
65
|
reload(opts?: DaemonOperationOptions): Promise<DaemonOperationResult>;
|
|
61
66
|
stop(opts?: DaemonOperationOptions): Promise<DaemonOperationResult>;
|
|
62
67
|
private stopOrReload;
|
|
68
|
+
/** Clear our own control request unless a newer owner-scoped request replaced it. */
|
|
63
69
|
private clearOwnRequest;
|
|
64
70
|
}
|