@sayknow-cli/coding-agent 0.3.1 → 0.3.4
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/bin/skc.js +4 -0
- package/dist/types/cli/mcp-cli.d.ts +25 -0
- package/dist/types/cli/plugin-cli.d.ts +2 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/commands/mcp.d.ts +70 -0
- package/dist/types/commands/plugin.d.ts +6 -0
- package/dist/types/commands/session.d.ts +6 -0
- package/dist/types/config/keybindings.d.ts +2 -2
- package/dist/types/config/model-profile-activation.d.ts +8 -1
- package/dist/types/config/model-profiles.d.ts +2 -2
- package/dist/types/config/model-registry.d.ts +3 -3
- package/dist/types/config/models-config-schema.d.ts +0 -5
- package/dist/types/config/settings-schema.d.ts +79 -68
- package/dist/types/deep-interview/plaintext-gate-guard.d.ts +11 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/skc-plugins/compiler.d.ts +19 -0
- package/dist/types/extensibility/skc-plugins/constrained-hooks.d.ts +29 -0
- package/dist/types/extensibility/skc-plugins/index.d.ts +9 -0
- package/dist/types/extensibility/skc-plugins/injection.d.ts +9 -0
- package/dist/types/extensibility/skc-plugins/installer.d.ts +13 -0
- package/dist/types/extensibility/skc-plugins/mcp-policy.d.ts +26 -0
- package/dist/types/extensibility/skc-plugins/observability.d.ts +27 -0
- package/dist/types/extensibility/skc-plugins/prompt-appendix.d.ts +16 -0
- package/dist/types/extensibility/skc-plugins/registry.d.ts +32 -0
- package/dist/types/extensibility/skc-plugins/runtime-adapters.d.ts +64 -0
- package/dist/types/extensibility/skc-plugins/session-validation.d.ts +42 -0
- package/dist/types/extensibility/skc-plugins/types.d.ts +158 -2
- package/dist/types/extensibility/skc-plugins/validation.d.ts +8 -1
- package/dist/types/i18n/messages/en.d.ts +0 -1
- package/dist/types/main.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +8 -0
- package/dist/types/modes/components/settings-defs.d.ts +0 -1
- package/dist/types/modes/components/status-line/git-utils.d.ts +6 -0
- package/dist/types/modes/theme/defaults/index.d.ts +99 -0
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/notifications/html-format.d.ts +11 -0
- package/dist/types/notifications/index.d.ts +149 -1
- package/dist/types/notifications/lifecycle-commands.d.ts +60 -0
- package/dist/types/notifications/lifecycle-control-runtime.d.ts +98 -0
- package/dist/types/notifications/lifecycle-orchestrator.d.ts +144 -0
- package/dist/types/notifications/operator-runtime.d.ts +52 -0
- package/dist/types/notifications/rate-limit-pool.d.ts +2 -0
- package/dist/types/notifications/recent-activity.d.ts +35 -0
- package/dist/types/notifications/telegram-daemon.d.ts +114 -16
- package/dist/types/notifications/telegram-reference.d.ts +3 -1
- package/dist/types/notifications/topic-registry.d.ts +12 -9
- package/dist/types/runtime-mcp/types.d.ts +7 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +14 -4
- package/dist/types/session/blob-store.d.ts +25 -0
- package/dist/types/session/session-manager.d.ts +57 -0
- package/dist/types/skc-runtime/launch-tmux.d.ts +1 -0
- package/dist/types/skc-runtime/psmux-detect.d.ts +78 -0
- package/dist/types/skc-runtime/state-renderer.d.ts +5 -0
- package/dist/types/skc-runtime/team-runtime.d.ts +2 -0
- package/dist/types/skc-runtime/tmux-common.d.ts +30 -2
- package/dist/types/skc-runtime/tmux-sessions.d.ts +18 -0
- package/dist/types/skc-runtime/ultragoal-guard.d.ts +37 -1
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +80 -0
- package/dist/types/slash-commands/helpers/fast-status-report.d.ts +6 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +9 -1
- package/dist/types/tools/browser/tab-supervisor.d.ts +31 -0
- package/dist/types/tools/composer-bash-policy.d.ts +14 -0
- package/dist/types/tools/computer-gc.d.ts +23 -0
- package/dist/types/tools/cron.d.ts +36 -61
- package/dist/types/tools/index.d.ts +3 -2
- package/dist/types/tools/resource-gc.d.ts +54 -0
- package/dist/types/utils/changelog.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +6 -3
- package/dist/types/web/scrapers/types.d.ts +5 -0
- package/dist/types/web/scrapers/utils.d.ts +7 -1
- package/dist/types/web/search/index.d.ts +1 -0
- package/dist/types/web/search/providers/utils.d.ts +11 -4
- package/package.json +11 -9
- package/scripts/g004-tmux-smoke.ts +100 -0
- package/scripts/g005-daemon-smoke.ts +180 -0
- package/scripts/g011-daemon-path-smoke.ts +153 -0
- package/src/cli/args.ts +0 -1
- package/src/cli/fast-help.ts +29 -2
- package/src/cli/mcp-cli.ts +272 -0
- package/src/cli/plugin-cli.ts +66 -3
- package/src/cli/web-search-cli.ts +5 -0
- package/src/cli.ts +30 -12
- package/src/commands/mcp.ts +117 -0
- package/src/commands/plugin.ts +4 -0
- package/src/commands/session.ts +18 -0
- package/src/config/keybindings.ts +2 -2
- package/src/config/model-profile-activation.ts +62 -8
- package/src/config/model-profiles.ts +3 -4
- package/src/config/model-registry.ts +3 -6
- package/src/config/models-config-schema.ts +1 -1
- package/src/config/settings-schema.ts +88 -103
- package/src/deep-interview/plaintext-gate-guard.ts +94 -0
- package/src/defaults/skc/extensions/grok-cli-vendor/biome.json +1 -1
- package/src/defaults/skc/skills/deep-interview/SKILL.md +7 -6
- package/src/defaults/skc/skills/team/SKILL.md +5 -3
- package/src/defaults/skc/skills/ultragoal/SKILL.md +41 -13
- package/src/export/html/index.ts +2 -2
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +0 -12
- package/src/extensibility/extensions/runner.ts +1 -0
- package/src/extensibility/skc-plugins/compiler.ts +351 -0
- package/src/extensibility/skc-plugins/constrained-hooks.ts +170 -0
- package/src/extensibility/skc-plugins/index.ts +9 -0
- package/src/extensibility/skc-plugins/injection.ts +109 -0
- package/src/extensibility/skc-plugins/installer.ts +434 -0
- package/src/extensibility/skc-plugins/loader.ts +3 -1
- package/src/extensibility/skc-plugins/mcp-policy.ts +239 -0
- package/src/extensibility/skc-plugins/observability.ts +84 -0
- package/src/extensibility/skc-plugins/paths.ts +1 -1
- package/src/extensibility/skc-plugins/prompt-appendix.ts +109 -0
- package/src/extensibility/skc-plugins/registry.ts +180 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +234 -0
- package/src/extensibility/skc-plugins/schema.ts +250 -20
- package/src/extensibility/skc-plugins/session-validation.ts +147 -0
- package/src/extensibility/skc-plugins/types.ts +199 -3
- package/src/extensibility/skc-plugins/validation.ts +80 -0
- package/src/extensibility/skills.ts +15 -0
- package/src/goals/tools/goal-tool.ts +14 -1
- package/src/hooks/skill-state.ts +57 -0
- package/src/i18n/messages/de.ts +0 -1
- package/src/i18n/messages/en.ts +0 -1
- package/src/i18n/messages/es.ts +0 -1
- package/src/i18n/messages/fr.ts +0 -1
- package/src/i18n/messages/ja.ts +0 -1
- package/src/i18n/messages/ko.ts +0 -1
- package/src/i18n/messages/zh.ts +0 -1
- package/src/internal-urls/docs-index.generated.ts +14 -11
- package/src/main.ts +14 -3
- package/src/modes/bridge/bridge-mode.ts +11 -0
- package/src/modes/components/assistant-message.ts +49 -1
- package/src/modes/components/custom-editor.ts +2 -0
- package/src/modes/components/footer.ts +2 -3
- package/src/modes/components/hook-editor.ts +1 -1
- package/src/modes/components/hook-selector.ts +67 -43
- package/src/modes/components/model-selector.ts +65 -12
- package/src/modes/components/settings-defs.ts +1 -2
- package/src/modes/components/settings-selector.ts +2 -7
- package/src/modes/components/status-line/git-utils.ts +25 -0
- package/src/modes/components/status-line.ts +10 -11
- package/src/modes/components/welcome.ts +2 -3
- package/src/modes/controllers/extension-ui-controller.ts +0 -27
- package/src/modes/controllers/selector-controller.ts +59 -11
- package/src/modes/interactive-mode.ts +4 -1
- package/src/modes/shared/agent-wire/scopes.ts +1 -1
- package/src/modes/theme/defaults/gruvbox-dark.json +99 -0
- package/src/modes/theme/defaults/index.ts +2 -0
- package/src/modes/theme/theme.ts +0 -4
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/notifications/html-format.ts +38 -0
- package/src/notifications/index.ts +242 -12
- package/src/notifications/lifecycle-commands.ts +238 -0
- package/src/notifications/lifecycle-control-runtime.ts +405 -0
- package/src/notifications/lifecycle-orchestrator.ts +358 -0
- package/src/notifications/operator-runtime.ts +171 -0
- package/src/notifications/rate-limit-pool.ts +19 -0
- package/src/notifications/recent-activity.ts +132 -0
- package/src/notifications/telegram-daemon.ts +778 -257
- package/src/notifications/telegram-reference.ts +25 -7
- package/src/notifications/topic-registry.ts +23 -9
- package/src/prompts/agents/executor.md +2 -2
- package/src/prompts/system/system-prompt.md +2 -2
- package/src/prompts/tools/cron.md +5 -3
- package/src/prompts/tools/read.md +1 -1
- package/src/runtime-mcp/transports/stdio.ts +38 -4
- package/src/runtime-mcp/types.ts +7 -0
- package/src/sdk.ts +162 -10
- package/src/session/agent-session.ts +210 -74
- package/src/session/blob-store.ts +196 -8
- package/src/session/session-manager.ts +762 -12
- package/src/skc-runtime/launch-tmux.ts +68 -19
- package/src/skc-runtime/psmux-detect.ts +239 -0
- package/src/skc-runtime/state-renderer.ts +13 -0
- package/src/skc-runtime/team-runtime.ts +56 -23
- package/src/skc-runtime/tmux-common.ts +88 -4
- package/src/skc-runtime/tmux-sessions.ts +111 -9
- package/src/skc-runtime/ultragoal-guard.ts +192 -8
- package/src/skc-runtime/ultragoal-runtime.ts +296 -16
- package/src/slash-commands/builtin-registry.ts +23 -3
- package/src/slash-commands/helpers/fast-status-report.ts +13 -3
- package/src/slash-commands/helpers/parse.ts +2 -1
- package/src/system-prompt.ts +9 -0
- package/src/task/executor.ts +31 -7
- package/src/task/index.ts +2 -0
- package/src/tools/ask.ts +5 -1
- package/src/tools/bash.ts +9 -0
- package/src/tools/browser/tab-supervisor.ts +86 -2
- package/src/tools/composer-bash-policy.ts +96 -0
- package/src/tools/computer-gc.ts +66 -0
- package/src/tools/computer.ts +2 -0
- package/src/tools/cron.ts +75 -112
- package/src/tools/fetch.ts +18 -2
- package/src/tools/index.ts +5 -9
- package/src/tools/read.ts +25 -55
- package/src/tools/renderers.ts +0 -2
- package/src/tools/resource-gc.ts +291 -0
- package/src/tools/ultragoal-ask-guard.ts +7 -1
- package/src/utils/changelog.ts +8 -0
- package/src/web/insane/url-guard.ts +18 -14
- package/src/web/scrapers/types.ts +143 -45
- package/src/web/scrapers/utils.ts +70 -19
- package/src/web/search/index.ts +1 -0
- package/src/web/search/providers/utils.ts +22 -5
- package/vendor/insane-search/MANIFEST.json +3 -1
- package/vendor/insane-search/engine/__init__.py +14 -0
- package/vendor/insane-search/engine/content_safety.py +151 -0
- package/vendor/insane-search/engine/fetch_chain.py +32 -0
- package/vendor/insane-search/engine/tests/test_u8.py +216 -0
- package/dist/types/tools/inspect-image-renderer.d.ts +0 -26
- package/dist/types/tools/inspect-image.d.ts +0 -31
- package/src/prompts/tools/inspect-image-system.md +0 -20
- package/src/prompts/tools/inspect-image.md +0 -32
- package/src/tools/inspect-image-renderer.ts +0 -103
- package/src/tools/inspect-image.ts +0 -172
|
@@ -81,6 +81,8 @@ export declare class RateLimitPool<T = unknown> {
|
|
|
81
81
|
* single session monopolises a lane), consuming one token each.
|
|
82
82
|
*/
|
|
83
83
|
drain(nowMs?: number): RateLimitItem<T>[];
|
|
84
|
+
/** Remove queued items matching `predicate` without consuming tokens. Returns removed items in lane/FIFO order. */
|
|
85
|
+
removeWhere(predicate: (item: RateLimitItem<T>) => boolean): RateLimitItem<T>[];
|
|
84
86
|
private refill;
|
|
85
87
|
/** Pop the next item by lane priority + per-session round-robin fairness. */
|
|
86
88
|
private takeNext;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** One ranked recent-session entry surfaced to the picker. */
|
|
2
|
+
export interface RecentSessionEntry {
|
|
3
|
+
/** Session id (the `.jsonl` file stem). */
|
|
4
|
+
sessionId: string;
|
|
5
|
+
/** Working directory / repo path, when recoverable from the header. */
|
|
6
|
+
path?: string;
|
|
7
|
+
/** Branch, when recoverable from the header. */
|
|
8
|
+
branch?: string;
|
|
9
|
+
/** A short title (first user message), when recoverable. */
|
|
10
|
+
title?: string;
|
|
11
|
+
/** Absolute path of the session history (state) file. */
|
|
12
|
+
sessionStateFile: string;
|
|
13
|
+
/** Last-activity epoch-millis (history file mtime). */
|
|
14
|
+
mtimeMs: number;
|
|
15
|
+
/** True when a terminal breadcrumb points at this session file. */
|
|
16
|
+
currentTerminal?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface RecentActivityDeps {
|
|
19
|
+
/** Root holding `<encoded-cwd>/<sessionId>.jsonl` history files. */
|
|
20
|
+
sessionsRoot: string;
|
|
21
|
+
/** Optional breadcrumb session-file paths (current terminals). */
|
|
22
|
+
breadcrumbPaths?: string[];
|
|
23
|
+
/** Max entries to return (default 20). */
|
|
24
|
+
limit?: number;
|
|
25
|
+
/** Injection seam for tests. */
|
|
26
|
+
readFirstLine?: (file: string) => string | undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* List recent sessions ranked by history-file mtime (newest first).
|
|
30
|
+
*
|
|
31
|
+
* Scans `<sessionsRoot>/<encoded-cwd>/<sessionId>.jsonl`, stats each file, and
|
|
32
|
+
* returns up to `limit` entries enriched with header metadata and a
|
|
33
|
+
* `currentTerminal` flag for any breadcrumb-referenced session file.
|
|
34
|
+
*/
|
|
35
|
+
export declare function listRecentSessions(deps: RecentActivityDeps): RecentSessionEntry[];
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import type { Settings } from "../config/settings";
|
|
3
3
|
import type { DaemonRuntimeInfo } from "../daemon/control-types";
|
|
4
|
+
import { type ControlServerLike, type LifecycleControlServerFactory } from "./lifecycle-control-runtime";
|
|
5
|
+
import { NotificationOperatorRuntime, OperatorBackoffPolicy } from "./operator-runtime";
|
|
4
6
|
import { type AliasTable, type CallbackRoute, type PendingAsk } from "./telegram-reference";
|
|
5
7
|
export type EnsureDaemonResult = "owner_spawned" | "attached" | "disabled";
|
|
6
8
|
export interface DaemonState {
|
|
@@ -58,6 +60,22 @@ export declare const CLIENT_PING_PONG_CAPABILITY = "client_ping_pong";
|
|
|
58
60
|
/** Protocol version the daemon advertises in its ClientHello. */
|
|
59
61
|
export declare const NOTIFICATION_PROTOCOL_VERSION = 2;
|
|
60
62
|
export declare function daemonPaths(agentDir: string): DaemonPaths;
|
|
63
|
+
/**
|
|
64
|
+
* Attach session-lifecycle control (create/close/resume) to the running daemon.
|
|
65
|
+
*
|
|
66
|
+
* Wires an already-started, authenticated control server to the lifecycle
|
|
67
|
+
* orchestrator with real daemon-side effects (tmux launcher / force-close /
|
|
68
|
+
* resume), a durable fsynced idempotency ledger + audit JSONL under the agent
|
|
69
|
+
* notifications dir, and strict paired-chat gating. The control server itself
|
|
70
|
+
* (NotificationControlServer) is owned/started by the daemon process; this
|
|
71
|
+
* function only connects it to policy. Returns the orchestrator deps for tests.
|
|
72
|
+
*/
|
|
73
|
+
export declare function startDaemonLifecycleControl(input: {
|
|
74
|
+
controlServer: ControlServerLike;
|
|
75
|
+
pairedChatId: string;
|
|
76
|
+
agentDir: string;
|
|
77
|
+
env?: NodeJS.ProcessEnv;
|
|
78
|
+
}): void;
|
|
61
79
|
export declare function registerNotificationRoot(input: {
|
|
62
80
|
settings: Settings;
|
|
63
81
|
cwd: string;
|
|
@@ -146,6 +164,40 @@ export interface BotApi {
|
|
|
146
164
|
signal?: AbortSignal;
|
|
147
165
|
}): Promise<unknown>;
|
|
148
166
|
}
|
|
167
|
+
export interface TelegramTransportOptions {
|
|
168
|
+
botToken: string;
|
|
169
|
+
apiBase?: string;
|
|
170
|
+
fetchImpl?: typeof fetch;
|
|
171
|
+
setTimeoutImpl?: typeof setTimeout;
|
|
172
|
+
}
|
|
173
|
+
/** Telegram Bot API transport: HTTP JSON/multipart details stay out of daemon orchestration. */
|
|
174
|
+
export declare class TelegramBotTransport implements BotApi {
|
|
175
|
+
#private;
|
|
176
|
+
constructor(opts: TelegramTransportOptions);
|
|
177
|
+
call(method: string, body: unknown, opts?: {
|
|
178
|
+
signal?: AbortSignal;
|
|
179
|
+
}): Promise<unknown>;
|
|
180
|
+
}
|
|
181
|
+
export interface TelegramUpdatePollerOptions {
|
|
182
|
+
botApi: BotApi;
|
|
183
|
+
runtime: NotificationOperatorRuntime;
|
|
184
|
+
backoff: OperatorBackoffPolicy;
|
|
185
|
+
processUpdate: (update: unknown) => Promise<void>;
|
|
186
|
+
}
|
|
187
|
+
/** Owns getUpdates offset, conflict backoff, and per-update error isolation. */
|
|
188
|
+
export declare class TelegramUpdatePoller {
|
|
189
|
+
#private;
|
|
190
|
+
constructor(opts: TelegramUpdatePollerOptions);
|
|
191
|
+
pollOnce(signal?: AbortSignal): Promise<number>;
|
|
192
|
+
}
|
|
193
|
+
/** Mutable dispatch state shared by session frames and inbound Telegram updates. */
|
|
194
|
+
export declare class TelegramEventDispatchState {
|
|
195
|
+
readonly busy: Set<string>;
|
|
196
|
+
readonly inboundReactions: Map<number, {
|
|
197
|
+
messageId: number;
|
|
198
|
+
}>;
|
|
199
|
+
readonly seenUpdateIds: Set<number>;
|
|
200
|
+
}
|
|
149
201
|
/**
|
|
150
202
|
* Cooperative control seam for the daemon run loop. Implemented by the
|
|
151
203
|
* daemon-internal CLI / controller against the owner-scoped control-request
|
|
@@ -174,8 +226,17 @@ export interface TelegramDaemonOptions {
|
|
|
174
226
|
idleTimeoutMs?: number;
|
|
175
227
|
scanIntervalMs?: number;
|
|
176
228
|
pid?: number;
|
|
229
|
+
/** Liveness probe for skipping dead-PID endpoint records in {@link TelegramNotificationDaemon.scanRoots}. */
|
|
230
|
+
pidAlive?: (pid: number) => boolean;
|
|
177
231
|
botApi?: BotApi;
|
|
178
232
|
control?: DaemonControlHooks;
|
|
233
|
+
/**
|
|
234
|
+
* Factory for the session-lifecycle control server. Defaults to the real
|
|
235
|
+
* native NotificationControlServer; tests inject a fake to verify the
|
|
236
|
+
* owner-bound start/stop lifecycle without a socket. When `undefined` AND no
|
|
237
|
+
* default applies (e.g. lifecycle control disabled), no control server starts.
|
|
238
|
+
*/
|
|
239
|
+
createLifecycleControlServer?: LifecycleControlServerFactory | null;
|
|
179
240
|
}
|
|
180
241
|
interface SessionSocket {
|
|
181
242
|
sessionId: string;
|
|
@@ -199,40 +260,72 @@ export declare class TelegramNotificationDaemon {
|
|
|
199
260
|
readonly aliasTable: AliasTable;
|
|
200
261
|
readonly messageRoutes: Map<string | number, CallbackRoute | Omit<CallbackRoute, "answer">>;
|
|
201
262
|
readonly sessions: Map<string, SessionSocket>;
|
|
263
|
+
private readonly runtime;
|
|
264
|
+
private readonly sessionRouter;
|
|
265
|
+
private readonly pollConflictBackoff;
|
|
266
|
+
private readonly loopBackoff;
|
|
202
267
|
private running;
|
|
203
|
-
private offset;
|
|
204
268
|
private readonly fsImpl;
|
|
205
269
|
private readonly botApi;
|
|
206
270
|
private readonly topics;
|
|
207
271
|
private readonly pool;
|
|
208
|
-
private readonly
|
|
272
|
+
private readonly poller;
|
|
273
|
+
private readonly dispatchState;
|
|
274
|
+
/** Identity-bearing sessions by repo/branch surface, used to avoid transient duplicate topics. */
|
|
275
|
+
private readonly topicOwnerByIdentity;
|
|
276
|
+
/** Non-identity frames held until identity creates the correct thread. */
|
|
277
|
+
private readonly pendingThreadedFrames;
|
|
209
278
|
/** True once the daemon has nudged the user to enable Threaded Mode. */
|
|
210
279
|
private threadedFallbackNoticeSent;
|
|
211
280
|
/** Sessions whose identity header was already sent flat (Threaded Mode off). */
|
|
212
281
|
private readonly flatIdentitySent;
|
|
213
282
|
/** Cached result of whether the paired chat is a private chat (flat-fallback gate). */
|
|
214
283
|
private pairedChatPrivate;
|
|
215
|
-
private flushTimer;
|
|
216
|
-
private scanTimer;
|
|
217
|
-
private scanning;
|
|
218
|
-
private typingTimer;
|
|
219
284
|
/** Sessions whose agent loop is currently busy (drives the typing indicator). */
|
|
220
|
-
private
|
|
285
|
+
private get busy();
|
|
221
286
|
/** Inbound update id → originating Telegram message, for delivery reactions. */
|
|
222
|
-
private
|
|
223
|
-
/**
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
private
|
|
287
|
+
private get inboundReactions();
|
|
288
|
+
/**
|
|
289
|
+
* The owner-bound session-lifecycle control server (create/close/resume).
|
|
290
|
+
* Started in {@link run} after ownership is confirmed (so exactly one owner
|
|
291
|
+
* ever runs one), stopped in run()'s finally on any exit path.
|
|
292
|
+
*/
|
|
293
|
+
private controlServer;
|
|
294
|
+
/** True while lifecycle control is active, so the loop keeps polling at idle. */
|
|
295
|
+
private lifecycleControlActive;
|
|
296
|
+
/** Control token (in-memory) the loopback client presents; never persisted/logged. */
|
|
297
|
+
private controlToken;
|
|
298
|
+
/** Loopback WS client to the daemon's own control endpoint (Option A real wire path). */
|
|
299
|
+
private controlClient;
|
|
300
|
+
/** Pending lifecycle responses awaiting a control-endpoint reply, by requestId. */
|
|
301
|
+
private readonly pendingLifecycle;
|
|
302
|
+
/** Monotonic counter for unique lifecycle request ids. */
|
|
303
|
+
private lifecycleSeq;
|
|
229
304
|
/**
|
|
230
305
|
* Cooperatively stop the daemon: set the stop flag and abort the in-flight
|
|
231
306
|
* long poll so the run loop wakes immediately instead of waiting out the
|
|
232
307
|
* ~25s getUpdates timeout. Safe to call from a signal handler.
|
|
233
308
|
*/
|
|
234
309
|
requestStop(_reason?: "reload" | "stop" | "signal"): void;
|
|
310
|
+
private startLifecycleControl;
|
|
311
|
+
/** Stop the lifecycle control server (idempotent); called from run()'s finally. */
|
|
312
|
+
private stopLifecycleControl;
|
|
313
|
+
/**
|
|
314
|
+
* Connect the loopback control client and resolve responses by requestId.
|
|
315
|
+
* Resolves true once the socket is OPEN (bounded), false on error/timeout, so
|
|
316
|
+
* the caller only marks lifecycle control active when commands can be sent.
|
|
317
|
+
*/
|
|
318
|
+
private connectControlClient;
|
|
319
|
+
/** Send a lifecycle frame over the loopback client and await the response. */
|
|
320
|
+
private submitLifecycleFrame;
|
|
321
|
+
private nextLifecycleRequestId;
|
|
322
|
+
/** Build an authenticated lifecycle frame from a parsed command + identity. */
|
|
323
|
+
private buildLifecycleFrame;
|
|
324
|
+
private handleLifecycleCommand;
|
|
325
|
+
/** Map a lifecycle response/error to a user-facing message (G010 surfacing). */
|
|
326
|
+
private formatLifecycleResponse;
|
|
235
327
|
constructor(opts: TelegramDaemonOptions);
|
|
328
|
+
private createSessionRouter;
|
|
236
329
|
loadAliases(): Promise<void>;
|
|
237
330
|
persistAliases(): Promise<void>;
|
|
238
331
|
scanRoots(): Promise<void>;
|
|
@@ -254,7 +347,14 @@ export declare class TelegramNotificationDaemon {
|
|
|
254
347
|
private dropSession;
|
|
255
348
|
private static readonly THREADED_FRAMES;
|
|
256
349
|
private topicNameFor;
|
|
350
|
+
private topicIdentityKey;
|
|
351
|
+
private topicIdentityBase;
|
|
352
|
+
private topicOwnerForIdentity;
|
|
353
|
+
private submitThreadedFrame;
|
|
354
|
+
private rememberPendingThreadedFrame;
|
|
355
|
+
private flushPendingThreadedFrames;
|
|
257
356
|
private ensureTopic;
|
|
357
|
+
private deleteTopic;
|
|
258
358
|
private persistTopics;
|
|
259
359
|
loadTopics(): Promise<void>;
|
|
260
360
|
private downloadTelegramFile;
|
|
@@ -285,8 +385,6 @@ export declare class TelegramNotificationDaemon {
|
|
|
285
385
|
private sendStaleGuidance;
|
|
286
386
|
handleTelegramUpdate(update: unknown): Promise<void>;
|
|
287
387
|
pollOnce(signal?: AbortSignal): Promise<number>;
|
|
288
|
-
/** Abortable sleep honoring the injected timer; resolves early on abort. */
|
|
289
|
-
private sleep;
|
|
290
388
|
/** Sync the bot's Telegram command menu to what the daemon actually handles. */
|
|
291
389
|
registerBotCommands(): Promise<void>;
|
|
292
390
|
run(): Promise<void>;
|
|
@@ -90,10 +90,12 @@ export interface RouteInboundContext {
|
|
|
90
90
|
}
|
|
91
91
|
/** Route a Telegram update to a session/action without I/O. Fail closed under ambiguity. */
|
|
92
92
|
export declare function routeInboundUpdate(update: unknown, ctx: RouteInboundContext): RouteDecision;
|
|
93
|
-
/** Read `{url, token}` from an endpoint discovery file. */
|
|
93
|
+
/** Read `{url, token, pid?, stale?}` from an endpoint discovery file. */
|
|
94
94
|
export declare function readEndpoint(path: string): {
|
|
95
95
|
url: string;
|
|
96
96
|
token: string;
|
|
97
|
+
pid?: number;
|
|
98
|
+
stale?: boolean;
|
|
97
99
|
};
|
|
98
100
|
/** Options for {@link runTelegramReferenceClient}. */
|
|
99
101
|
export interface TelegramReferenceOptions {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-session forum-topic registry for the threaded session surface.
|
|
3
3
|
*
|
|
4
|
-
* Each SKC session owns
|
|
5
|
-
* DM. The topic is created
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Each SKC session owns one active Telegram forum topic in the paired private
|
|
5
|
+
* DM. The topic is created via `createForumTopic`, reused while the session
|
|
6
|
+
* remains active, and removed from the registry when the daemon deletes it on
|
|
7
|
+
* shutdown. The registry also tracks whether the one-time identity header has
|
|
8
|
+
* already been pinned, so it is sent exactly once per active topic, even across
|
|
9
9
|
* reconnects.
|
|
10
10
|
*
|
|
11
11
|
* State is a plain serialisable map persisted beside the daemon state files;
|
|
@@ -45,14 +45,15 @@ export declare class TopicRegistry {
|
|
|
45
45
|
load(state: TopicRegistryState): void;
|
|
46
46
|
/** Resolve the owning session for a topic id (for fail-closed inbound routing). */
|
|
47
47
|
sessionForTopic(topicId: string): string | undefined;
|
|
48
|
+
/** All session ids with a persisted topic record. */
|
|
49
|
+
sessionIds(): string[];
|
|
48
50
|
/** The existing topic record for a session, if any. */
|
|
49
51
|
get(sessionId: string): TopicRecord | undefined;
|
|
50
52
|
/**
|
|
51
|
-
* Return the existing topic for `sessionId`, or create one via
|
|
52
|
-
* (called only on first use).
|
|
53
|
-
* returned without invoking `create`.
|
|
53
|
+
* Return the existing active topic for `sessionId`, or create one via
|
|
54
|
+
* `create` (called only on first use).
|
|
54
55
|
*/
|
|
55
|
-
getOrCreateTopic(sessionId: string, create: () => Promise<string>, now?: () => number): Promise<TopicRecord>;
|
|
56
|
+
getOrCreateTopic(sessionId: string, create: () => Promise<string>, now?: () => number, name?: string): Promise<TopicRecord>;
|
|
56
57
|
/** Mark the identity header as sent for a session. Idempotent. */
|
|
57
58
|
markIdentitySent(sessionId: string): void;
|
|
58
59
|
/** Whether the identity header still needs sending for this session. */
|
|
@@ -62,6 +63,8 @@ export declare class TopicRegistry {
|
|
|
62
63
|
* caller should `editForumTopic`), `false` when already current or unknown.
|
|
63
64
|
*/
|
|
64
65
|
applyName(sessionId: string, name: string): boolean;
|
|
66
|
+
/** Remove a session topic record after Telegram deletes the topic. */
|
|
67
|
+
delete(sessionId: string): boolean;
|
|
65
68
|
/** Serialise for atomic persistence beside the daemon state. */
|
|
66
69
|
serialize(): TopicRegistryState;
|
|
67
70
|
}
|
|
@@ -64,6 +64,13 @@ export interface MCPStdioServerConfig extends MCPServerConfigBase {
|
|
|
64
64
|
command: string;
|
|
65
65
|
args?: string[];
|
|
66
66
|
env?: Record<string, string>;
|
|
67
|
+
/**
|
|
68
|
+
* When true, the child process is NOT given the host environment. Only a
|
|
69
|
+
* minimal OS allowlist (PATH/HOME/temp/locale) plus any explicit `env` keys
|
|
70
|
+
* are passed. Used for third-party plugin-bundle MCP servers so they cannot
|
|
71
|
+
* read host secrets from the inherited environment.
|
|
72
|
+
*/
|
|
73
|
+
noInheritEnv?: boolean;
|
|
67
74
|
cwd?: string;
|
|
68
75
|
}
|
|
69
76
|
/** HTTP server configuration (Streamable HTTP transport) */
|
package/dist/types/sdk.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import "./discovery";
|
|
|
10
10
|
import type { CustomCommandsLoadResult } from "./extensibility/custom-commands";
|
|
11
11
|
import type { CustomTool } from "./extensibility/custom-tools/types";
|
|
12
12
|
import { type ExtensionFactory, type ExtensionUIContext, type LoadExtensionsResult, type ToolDefinition } from "./extensibility/extensions";
|
|
13
|
+
import { type ConstrainedPluginHook } from "./extensibility/skc-plugins/constrained-hooks";
|
|
13
14
|
import { type Skill, type SkillWarning } from "./extensibility/skills";
|
|
14
15
|
import type { FileSlashCommand } from "./extensibility/slash-commands";
|
|
15
16
|
import type { HindsightSessionState } from "./hindsight/state";
|
|
@@ -240,4 +241,5 @@ export interface BuildSystemPromptOptions {
|
|
|
240
241
|
* as separate entries so providers can cache prompt prefixes without concatenating blocks.
|
|
241
242
|
*/
|
|
242
243
|
export declare function buildSystemPrompt(options?: BuildSystemPromptOptions): Promise<BuildSystemPromptResult>;
|
|
244
|
+
export declare function createPluginHooksExtension(hooks: ConstrainedPluginHook[]): ExtensionFactory;
|
|
243
245
|
export declare function createAgentSession(options?: CreateAgentSessionOptions): Promise<CreateAgentSessionResult>;
|
|
@@ -69,6 +69,7 @@ import type { WorkflowGateEmitter } from "../modes/shared/agent-wire/unattended-
|
|
|
69
69
|
import type { PlanModeState } from "../plan-mode/state";
|
|
70
70
|
import { type AgentRegistry } from "../registry/agent-registry";
|
|
71
71
|
import { type DiscoverableMCPSearchIndex, type DiscoverableMCPTool } from "../runtime-mcp/discoverable-tool-metadata";
|
|
72
|
+
import { MCPManager } from "../runtime-mcp/manager";
|
|
72
73
|
import { type SecretObfuscator } from "../secrets/obfuscator";
|
|
73
74
|
import { type DiscoverableTool, type DiscoverableToolSearchIndex } from "../tool-discovery/tool-index";
|
|
74
75
|
import type { AskAnswerSource, ToolSession } from "../tools";
|
|
@@ -77,7 +78,7 @@ import { type TodoItem, type TodoPhase } from "../tools/todo-write";
|
|
|
77
78
|
import type { ClientBridge } from "./client-bridge";
|
|
78
79
|
import { type ContributionPrepOptions, type ContributionPrepResult } from "./contribution-prep";
|
|
79
80
|
import { type CustomMessage } from "./messages";
|
|
80
|
-
import type { BranchSummaryEntry, NewSessionOptions, SessionContext, SessionManager } from "./session-manager";
|
|
81
|
+
import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, SessionContext, SessionManager } from "./session-manager";
|
|
81
82
|
import { ToolChoiceQueue } from "./tool-choice-queue";
|
|
82
83
|
import { YieldQueue } from "./yield-queue";
|
|
83
84
|
/** Session-specific events that extend the core AgentEvent */
|
|
@@ -233,6 +234,13 @@ export interface AgentSessionConfig {
|
|
|
233
234
|
* **MUST NOT** dispose it on their own teardown.
|
|
234
235
|
*/
|
|
235
236
|
ownedAsyncJobManager?: AsyncJobManager;
|
|
237
|
+
/**
|
|
238
|
+
* MCPManager whose lifecycle this session owns (top-level sessions that
|
|
239
|
+
* connected plugin-bundle MCP servers). Only the owned manager is
|
|
240
|
+
* disconnected on dispose; subagents and callers that merely observe the
|
|
241
|
+
* process-global manager **MUST NOT** dispose it on their own teardown.
|
|
242
|
+
*/
|
|
243
|
+
ownedMcpManager?: MCPManager;
|
|
236
244
|
/** Optional fork-context seed used to initialize a child session before its first prompt. */
|
|
237
245
|
forkContextSeed?: ForkContextSeed;
|
|
238
246
|
/** Optional provider state override. Fork-context children should omit this by default. */
|
|
@@ -676,6 +684,7 @@ export declare class AgentSession {
|
|
|
676
684
|
get skillWarnings(): readonly SkillWarning[];
|
|
677
685
|
getTodoPhases(): TodoPhase[];
|
|
678
686
|
setTodoPhases(phases: TodoPhase[]): void;
|
|
687
|
+
applyCompactionPostAppendForTests(compactionEntryId: string, firstKeptEntryId: string, fromExtension?: boolean): Promise<CompactionEntry | undefined>;
|
|
679
688
|
/**
|
|
680
689
|
* Abort current operation and wait for agent to become idle.
|
|
681
690
|
*/
|
|
@@ -807,9 +816,10 @@ export declare class AgentSession {
|
|
|
807
816
|
isFastForSubagentProvider(provider?: string): boolean;
|
|
808
817
|
/**
|
|
809
818
|
* True when the configured `serviceTier` resolves to `"priority"` for the
|
|
810
|
-
* *currently selected model's provider
|
|
811
|
-
* that
|
|
812
|
-
*
|
|
819
|
+
* *currently selected model's provider* AND fast mode was not auto-disabled
|
|
820
|
+
* for that provider this session. This is the current-model EFFECTIVE
|
|
821
|
+
* predicate (what the next request actually does); use {@link isFastForProvider}
|
|
822
|
+
* for pure configured intent (e.g. subagent/`modelRoles` display rows).
|
|
813
823
|
*/
|
|
814
824
|
isFastModeActive(): boolean;
|
|
815
825
|
setServiceTier(serviceTier: ServiceTier | undefined): void;
|
|
@@ -3,6 +3,14 @@ export interface BlobPutResult {
|
|
|
3
3
|
path: string;
|
|
4
4
|
get ref(): string;
|
|
5
5
|
}
|
|
6
|
+
export interface CheckedBlobPutResult extends BlobPutResult {
|
|
7
|
+
bytes: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class BlobCorruptError extends Error {
|
|
10
|
+
readonly hash: string;
|
|
11
|
+
readonly path: string;
|
|
12
|
+
constructor(hash: string, path: string);
|
|
13
|
+
}
|
|
6
14
|
/**
|
|
7
15
|
* Content-addressed blob store for externalizing large binary data (images) from session JSONL files.
|
|
8
16
|
*
|
|
@@ -24,10 +32,22 @@ export declare class BlobStore {
|
|
|
24
32
|
* Returns once the bytes are in the kernel page cache.
|
|
25
33
|
*/
|
|
26
34
|
putSync(data: Buffer): BlobPutResult;
|
|
35
|
+
/**
|
|
36
|
+
* Durably install binary data as an immutable content-addressed blob.
|
|
37
|
+
*
|
|
38
|
+
* Callers that persist references to this blob must mutate canonical session entries only
|
|
39
|
+
* after this method returns successfully. A corrupt pre-existing target is reported with
|
|
40
|
+
* {@link BlobCorruptError}; it is never silently overwritten or trusted.
|
|
41
|
+
*/
|
|
42
|
+
putImmutableSync(data: Buffer): CheckedBlobPutResult;
|
|
27
43
|
/** Read blob by hash, returns Buffer or null if not found. */
|
|
28
44
|
get(hash: string): Promise<Buffer | null>;
|
|
29
45
|
/** Synchronously read blob by hash, returns Buffer or null if not found. */
|
|
30
46
|
getSync(hash: string): Buffer | null;
|
|
47
|
+
/** Read blob by hash and verify its content hash; returns null if not found. */
|
|
48
|
+
getChecked(hash: string): Promise<Buffer | null>;
|
|
49
|
+
/** Synchronously read blob by hash and verify its content hash; returns null if not found. */
|
|
50
|
+
getCheckedSync(hash: string): Buffer | null;
|
|
31
51
|
/** Check if a blob exists. */
|
|
32
52
|
has(hash: string): Promise<boolean>;
|
|
33
53
|
}
|
|
@@ -35,7 +55,9 @@ export declare class EphemeralBlobStore extends BlobStore {
|
|
|
35
55
|
#private;
|
|
36
56
|
constructor(dir: string);
|
|
37
57
|
putSync(data: Buffer): BlobPutResult;
|
|
58
|
+
putImmutableSync(data: Buffer): CheckedBlobPutResult;
|
|
38
59
|
getSync(hash: string): Buffer | null;
|
|
60
|
+
getCheckedSync(hash: string): Buffer | null;
|
|
39
61
|
clear(): void;
|
|
40
62
|
dispose(): void;
|
|
41
63
|
}
|
|
@@ -44,8 +66,11 @@ export declare class MemoryBlobStore extends BlobStore {
|
|
|
44
66
|
constructor();
|
|
45
67
|
put(data: Buffer): Promise<BlobPutResult>;
|
|
46
68
|
putSync(data: Buffer): BlobPutResult;
|
|
69
|
+
putImmutableSync(data: Buffer): CheckedBlobPutResult;
|
|
47
70
|
get(hash: string): Promise<Buffer | null>;
|
|
48
71
|
getSync(hash: string): Buffer | null;
|
|
72
|
+
getChecked(hash: string): Promise<Buffer | null>;
|
|
73
|
+
getCheckedSync(hash: string): Buffer | null;
|
|
49
74
|
has(hash: string): Promise<boolean>;
|
|
50
75
|
}
|
|
51
76
|
export declare class ResidentBlobMissingError extends Error {
|
|
@@ -26,9 +26,51 @@ export interface SessionEntryBase {
|
|
|
26
26
|
parentId: string | null;
|
|
27
27
|
timestamp: string;
|
|
28
28
|
}
|
|
29
|
+
export interface ColdSpillRef {
|
|
30
|
+
kind: "cold_spill";
|
|
31
|
+
ref: string;
|
|
32
|
+
encoding: "utf8" | "json";
|
|
33
|
+
originalChars: number;
|
|
34
|
+
sha256: string;
|
|
35
|
+
bytes: number;
|
|
36
|
+
}
|
|
37
|
+
export interface EvictedContentMarker {
|
|
38
|
+
evictedAt: number;
|
|
39
|
+
reason: "compacted_history";
|
|
40
|
+
compactionEntryId: string;
|
|
41
|
+
firstKeptEntryId: string;
|
|
42
|
+
payloads: Record<string, ColdSpillRef>;
|
|
43
|
+
}
|
|
44
|
+
export interface EvictCompactedContentResult {
|
|
45
|
+
evictedEntries: number;
|
|
46
|
+
hotCharsRemoved: number;
|
|
47
|
+
coldBlobBytes: number;
|
|
48
|
+
payloadRefs: number;
|
|
49
|
+
alreadyEvictedEntries: number;
|
|
50
|
+
coldSpillWriteCount: number;
|
|
51
|
+
coldSpillReadCount: number;
|
|
52
|
+
residentTextReadCount: number;
|
|
53
|
+
residentImageReadCount: number;
|
|
54
|
+
}
|
|
55
|
+
export interface SessionManagerObservabilityStats {
|
|
56
|
+
coldSpillWriteCount: number;
|
|
57
|
+
coldSpillReadCount: number;
|
|
58
|
+
residentTextReadCount: number;
|
|
59
|
+
residentImageReadCount: number;
|
|
60
|
+
publicMaterializerCallCount: number;
|
|
61
|
+
getEntryMaterializerCallCount: number;
|
|
62
|
+
getBranchMaterializerCallCount: number;
|
|
63
|
+
getEntriesMaterializerCallCount: number;
|
|
64
|
+
materializedEntriesCachePopulateCount: number;
|
|
65
|
+
pathOnlyContextBuildCount: number;
|
|
66
|
+
}
|
|
29
67
|
export interface SessionMessageEntry extends SessionEntryBase {
|
|
30
68
|
type: "message";
|
|
31
69
|
message: AgentMessage;
|
|
70
|
+
/** Cold-spill marker: when present, heavy message content was moved to durable
|
|
71
|
+
* content-addressed blobs after compaction. The marker is entry-level session
|
|
72
|
+
* metadata (not a message field) so strict message types stay intact. */
|
|
73
|
+
evictedContent?: EvictedContentMarker;
|
|
32
74
|
}
|
|
33
75
|
export interface ThinkingLevelChangeEntry extends SessionEntryBase {
|
|
34
76
|
type: "thinking_level_change";
|
|
@@ -148,6 +190,8 @@ export interface CustomMessageEntry<T = unknown> extends SessionEntryBase {
|
|
|
148
190
|
display: boolean;
|
|
149
191
|
/** Who initiated this message for billing/attribution semantics. */
|
|
150
192
|
attribution?: MessageAttribution;
|
|
193
|
+
/** Cold-spill marker for custom-message content evicted after compaction. */
|
|
194
|
+
evictedContent?: EvictedContentMarker;
|
|
151
195
|
}
|
|
152
196
|
/** Session entry - has id/parentId for tree structure (returned by "read" methods in SessionManager) */
|
|
153
197
|
export type SessionEntry = SessionMessageEntry | ThinkingLevelChangeEntry | ModelChangeEntry | ServiceTierChangeEntry | CompactionEntry | BranchSummaryEntry | CustomEntry | CustomMessageEntry | LabelEntry | TtsrInjectionEntry | MCPToolSelectionEntry | SessionInitEntry | ModeChangeEntry;
|
|
@@ -480,6 +524,19 @@ export declare class SessionManager {
|
|
|
480
524
|
* Returns undefined if no model change has been recorded.
|
|
481
525
|
*/
|
|
482
526
|
getLastModelChangeRole(): string | undefined;
|
|
527
|
+
evictCompactedContent(firstKeptEntryId: string, compactionEntryId: string): EvictCompactedContentResult;
|
|
528
|
+
getObservabilityStatsForTests(): SessionManagerObservabilityStats;
|
|
529
|
+
hotRetainedMessageCharsForTests(): number;
|
|
530
|
+
getCanonicalEntryForTests(id: string): SessionEntry | undefined;
|
|
531
|
+
getEntryForFidelity(id: string): SessionEntry | undefined;
|
|
532
|
+
getBranchForFidelity(fromId?: string): SessionEntry[];
|
|
533
|
+
/**
|
|
534
|
+
* Walk the active branch without materializing resident blobs or rehydrating
|
|
535
|
+
* cold-spill payloads. Intended for metadata-only scans such as todo-phase
|
|
536
|
+
* sync; callers must not mutate returned entries.
|
|
537
|
+
*/
|
|
538
|
+
getActivePathEntriesCanonical(fromId?: string): SessionEntry[];
|
|
539
|
+
getEntriesForExport(): SessionEntry[];
|
|
483
540
|
getEntry(id: string): SessionEntry | undefined;
|
|
484
541
|
/**
|
|
485
542
|
* Get all direct children of an entry.
|
|
@@ -4,6 +4,7 @@ export { buildSkcTmuxProfileCommands, SKC_DEFAULT_TMUX_SESSION, SKC_TMUX_COMMAND
|
|
|
4
4
|
export declare const SKC_TMUX_LAUNCHED_ENV = "SKC_TMUX_LAUNCHED";
|
|
5
5
|
export declare const SKC_LAUNCH_POLICY_ENV = "SKC_LAUNCH_POLICY";
|
|
6
6
|
export declare const SKC_TMUX_WINDOW_LABEL_MAX_WIDTH = 48;
|
|
7
|
+
export declare const SKC_PSMUX_PROFILE_FORCE_ENV = "SKC_PSMUX_PROFILE_FORCE";
|
|
7
8
|
interface TtyState {
|
|
8
9
|
stdin: boolean;
|
|
9
10
|
stdout: boolean;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows psmux detection and tmux-binary resolution.
|
|
3
|
+
*
|
|
4
|
+
* Recent psmux releases (see docs/compatibility.md in the psmux repo) close
|
|
5
|
+
* the round-trip gap for set-option / show-options user options and the
|
|
6
|
+
* set-window-option profile values skc emits, which is what unblocks the
|
|
7
|
+
* native Windows skc --tmux path. This module detects that capability so skc
|
|
8
|
+
* can pick psmux when tmux is missing on Windows, and so callers can decide
|
|
9
|
+
* whether to treat a given tmux binary as psmux (affecting e.g. the untagged
|
|
10
|
+
* diagnostic wording and namespace handling).
|
|
11
|
+
*
|
|
12
|
+
* The probe is intentionally lightweight: it runs a single tmux -V (or
|
|
13
|
+
* --version) once per process and caches the verdict. Cache invalidation
|
|
14
|
+
* knobs:
|
|
15
|
+
* - force: true re-probes on every call (used by tests).
|
|
16
|
+
* - SKC_PSMUX_FORCE_DETECT=1 re-probes each call.
|
|
17
|
+
* - SKC_PSMUX_DETECTION=off skips probing entirely.
|
|
18
|
+
*/
|
|
19
|
+
export declare const SKC_PSMUX_COMMAND_ENV = "SKC_PSMUX_COMMAND";
|
|
20
|
+
export declare const SKC_PSMUX_DETECTION_ENV = "SKC_PSMUX_DETECTION";
|
|
21
|
+
export declare const SKC_PSMUX_FORCE_DETECT_ENV = "SKC_PSMUX_FORCE_DETECT";
|
|
22
|
+
/** Names that psmux installs as the canonical executable / alias. */
|
|
23
|
+
export declare const PSMUX_BINARY_NAMES: readonly ["psmux", "pmux", "tmux"];
|
|
24
|
+
export type PsmuxSpawnRunner = (command: string, args: string[]) => {
|
|
25
|
+
exitCode: number | null;
|
|
26
|
+
stdout?: string;
|
|
27
|
+
stderr?: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Resolves a tmux-class binary name (e.g. "psmux", "tmux") to an absolute
|
|
31
|
+
* filesystem path or returns null when the binary cannot be located. The
|
|
32
|
+
* default implementation uses `Bun.which`; production callers leave it
|
|
33
|
+
* alone and unit tests inject a stub via `__setBinaryResolverForTests`
|
|
34
|
+
* so the version-banner probe can be exercised hermetically.
|
|
35
|
+
*/
|
|
36
|
+
export type BinaryResolver = (candidate: string) => string | null;
|
|
37
|
+
/** @internal Test-only seam; production code never calls this. */
|
|
38
|
+
export declare function __setBinaryResolverForTests(resolver: BinaryResolver | null): void;
|
|
39
|
+
export declare function envDisabled(value: string | undefined): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Decide whether command resolves to a psmux binary by probing its version
|
|
42
|
+
* output. The result is cached per process unless force is set or
|
|
43
|
+
* SKC_PSMUX_FORCE_DETECT=1.
|
|
44
|
+
*/
|
|
45
|
+
export declare function detectPsmux(command: string, options?: {
|
|
46
|
+
force?: boolean;
|
|
47
|
+
env?: NodeJS.ProcessEnv;
|
|
48
|
+
runner?: PsmuxSpawnRunner;
|
|
49
|
+
}): boolean;
|
|
50
|
+
export interface ResolveSkcTmuxBinaryOptions {
|
|
51
|
+
platform?: NodeJS.Platform;
|
|
52
|
+
env?: NodeJS.ProcessEnv;
|
|
53
|
+
runner?: PsmuxSpawnRunner;
|
|
54
|
+
}
|
|
55
|
+
export interface ResolvedTmuxBinary {
|
|
56
|
+
command: string;
|
|
57
|
+
isPsmux: boolean;
|
|
58
|
+
viaExplicitOverride: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the tmux command SKC should invoke. Honors the existing
|
|
62
|
+
* SKC_TMUX_COMMAND / SKC_TEAM_TMUX_COMMAND overrides; on Windows when no
|
|
63
|
+
* override is set, psmux (installed as psmux, pmux, or tmux) is picked
|
|
64
|
+
* automatically so the default skc --tmux flow lands on a real multiplexer.
|
|
65
|
+
*/
|
|
66
|
+
export declare function resolveSkcTmuxBinary(options?: ResolveSkcTmuxBinaryOptions): ResolvedTmuxBinary;
|
|
67
|
+
/** Test-only helper: drop the in-process detection cache. */
|
|
68
|
+
export declare function clearPsmuxDetectionCache(): void;
|
|
69
|
+
export interface PsmuxProbe {
|
|
70
|
+
command: string;
|
|
71
|
+
versionOutput: string;
|
|
72
|
+
isPsmux: boolean;
|
|
73
|
+
}
|
|
74
|
+
export declare function probePsmux(command: string, options?: {
|
|
75
|
+
env?: NodeJS.ProcessEnv;
|
|
76
|
+
runner?: PsmuxSpawnRunner;
|
|
77
|
+
force?: boolean;
|
|
78
|
+
}): PsmuxProbe;
|
|
@@ -39,6 +39,11 @@ export declare function renderUltragoalStatusMarkdown(summary: {
|
|
|
39
39
|
};
|
|
40
40
|
counts: Record<string, number>;
|
|
41
41
|
goals: unknown[];
|
|
42
|
+
nudgeBudget?: number;
|
|
43
|
+
nudgeCount?: number;
|
|
44
|
+
nudgeRemaining?: number;
|
|
45
|
+
nudgeGoalId?: string;
|
|
46
|
+
nudgeTargetKind?: string;
|
|
42
47
|
}): string;
|
|
43
48
|
export declare function renderTeamStatusMarkdown(snapshot: {
|
|
44
49
|
team_name: string;
|
|
@@ -281,6 +281,8 @@ export declare function persistSkcTeamModeStateSummary(snapshot: SkcTeamSnapshot
|
|
|
281
281
|
export declare function recoverSkcTeamStaleClaims(teamName: string, cwd?: string, env?: NodeJS.ProcessEnv): Promise<SkcTeamLivenessRecoveryResult>;
|
|
282
282
|
type SkcTeamTaskMetadataInput = Partial<Pick<SkcTeamTask, "owner" | "lane" | "required_role" | "allowed_roles" | "depends_on" | "blocked_by">>;
|
|
283
283
|
export declare function resolveSkcWorkerCommand(cwd?: string, env?: NodeJS.ProcessEnv): string;
|
|
284
|
+
/** @internal Exported for unit tests. */
|
|
285
|
+
export declare function buildWorkerCommand(config: SkcTeamConfig, worker: SkcTeamWorker, platform?: NodeJS.Platform): string;
|
|
284
286
|
export type SkcWorkerCheckpointClassification = {
|
|
285
287
|
kind: "clean";
|
|
286
288
|
files: string[];
|