@sayknow-cli/coding-agent 0.3.7 → 0.3.9
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/append-only-mode.d.ts +31 -0
- package/dist/types/capability/rule.d.ts +8 -0
- package/dist/types/cli/completion-cli.d.ts +41 -0
- package/dist/types/cli/config-cli.d.ts +1 -0
- package/dist/types/cli/fixture-report.d.ts +20 -0
- package/dist/types/cli/fixture-report.test.d.ts +1 -0
- package/dist/types/cli/nofile-limit.d.ts +11 -0
- package/dist/types/cli/notify-cli.d.ts +7 -0
- package/dist/types/cli/update-cli.d.ts +22 -0
- package/dist/types/cli.d.ts +124 -1
- package/dist/types/commands/completion.d.ts +29 -0
- package/dist/types/commands/config.d.ts +3 -0
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/config/file-lock.d.ts +7 -6
- package/dist/types/config/keybindings.d.ts +2 -2
- package/dist/types/config/model-profile-activation.d.ts +6 -0
- package/dist/types/config/model-profiles.d.ts +1 -0
- package/dist/types/config/settings-schema.d.ts +119 -1
- package/dist/types/config/settings.d.ts +8 -0
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/export/ttsr.d.ts +14 -3
- package/dist/types/extensibility/extensions/runner.d.ts +2 -1
- package/dist/types/extensibility/extensions/types.d.ts +8 -0
- package/dist/types/goals/runtime.d.ts +1 -0
- package/dist/types/hooks/native-skill-hook.d.ts +12 -0
- package/dist/types/main.d.ts +4 -1
- package/dist/types/modes/components/assistant-message.d.ts +5 -1
- package/dist/types/modes/components/model-selector.d.ts +4 -0
- package/dist/types/modes/components/queued-message-selector.d.ts +12 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/status-line.d.ts +9 -0
- package/dist/types/modes/components/thinking-selector.d.ts +2 -2
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/event-controller.d.ts +5 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -3
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +4 -0
- package/dist/types/modes/print-mode.d.ts +13 -1
- package/dist/types/modes/prompt-action-autocomplete.d.ts +1 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +1 -3
- package/dist/types/modes/rpc/rpc-socket-security.d.ts +3 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +14 -0
- package/dist/types/modes/shared/agent-wire/event-contract.d.ts +19 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +23 -1
- package/dist/types/modes/types.d.ts +3 -0
- package/dist/types/modes/utils/injected-user-submission.d.ts +52 -0
- package/dist/types/modes/utils/ui-helpers.d.ts +1 -0
- package/dist/types/notifications/config-commands.d.ts +9 -0
- package/dist/types/notifications/config.d.ts +30 -1
- package/dist/types/notifications/daemon-paths.d.ts +1 -0
- package/dist/types/notifications/index.d.ts +8 -3
- package/dist/types/notifications/lifecycle-commands.d.ts +12 -3
- package/dist/types/notifications/lifecycle-control-runtime.d.ts +2 -1
- package/dist/types/notifications/reply-sent-store.d.ts +53 -0
- package/dist/types/notifications/rich-draft.d.ts +68 -0
- package/dist/types/notifications/rich-render.d.ts +90 -0
- package/dist/types/notifications/telegram-daemon.d.ts +45 -3
- package/dist/types/notifications/telegram-reference.d.ts +7 -5
- package/dist/types/notifications/threaded-render.d.ts +14 -0
- package/dist/types/runtime-api-key.d.ts +7 -0
- package/dist/types/sdk.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +61 -6
- package/dist/types/session/agent-storage.d.ts +1 -0
- package/dist/types/session/file-mention-pruning.d.ts +8 -0
- package/dist/types/session/messages.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +17 -1
- package/dist/types/skc-runtime/deep-interview-ambiguity.d.ts +39 -0
- package/dist/types/skc-runtime/deep-interview-recorder.d.ts +10 -1
- package/dist/types/skc-runtime/deep-interview-state.d.ts +17 -2
- package/dist/types/skc-runtime/session-state-sidecar.d.ts +7 -0
- package/dist/types/skc-runtime/state-writer.d.ts +3 -0
- package/dist/types/skc-runtime/tmux-common.d.ts +1 -0
- package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +42 -0
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +120 -13
- package/dist/types/skill-state/active-state.d.ts +18 -1
- package/dist/types/system-prompt.d.ts +18 -2
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/task/fork-context-budget.d.ts +7 -0
- package/dist/types/task/token-log.d.ts +30 -0
- package/dist/types/task/token-log.test.d.ts +1 -0
- package/dist/types/tools/bisect.d.ts +81 -0
- package/dist/types/tools/computer.d.ts +2 -2
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/search.d.ts +2 -2
- package/dist/types/tools/ultragoal-ask-guard.d.ts +9 -2
- package/dist/types/utils/file-mentions.d.ts +14 -0
- package/dist/types/utils/git.d.ts +32 -0
- package/dist/types/utils/pasted-image-path.d.ts +30 -0
- package/dist/types/web/scrapers/youtube.d.ts +8 -0
- package/dist/types/workflow/workflow-intent-diff.d.ts +8 -2
- package/dist/types/workflow/workflow-intent-report-consumer.d.ts +50 -0
- package/dist/types/workflow/workflow-intent-report-schema.d.ts +2 -0
- package/dist/types/workflow/workflow-intent-report.d.ts +48 -0
- package/package.json +8 -8
- package/src/append-only-mode.ts +58 -0
- package/src/autoresearch/prompt.md +1 -1
- package/src/autoresearch/tools/log-experiment.ts +1 -1
- package/src/capability/rule.ts +9 -0
- package/src/cli/completion-cli.ts +234 -0
- package/src/cli/config-cli.ts +61 -9
- package/src/cli/fast-help.ts +1 -0
- package/src/cli/fixture-report.test.ts +230 -0
- package/src/cli/fixture-report.ts +171 -0
- package/src/cli/nofile-limit.ts +48 -0
- package/src/cli/notify-cli.ts +103 -17
- package/src/cli/telegram-cli.ts +1 -1
- package/src/cli/update-cli.ts +148 -33
- package/src/cli.ts +29 -1
- package/src/commands/completion.ts +84 -0
- package/src/commands/config.ts +2 -0
- package/src/commands/contribution-prep.ts +1 -1
- package/src/commands/deep-interview.ts +2 -1
- package/src/config/file-lock.ts +73 -34
- package/src/config/keybindings.ts +3 -3
- package/src/config/model-profile-activation.ts +65 -0
- package/src/config/model-profiles.ts +31 -2
- package/src/config/settings-schema.ts +76 -1
- package/src/config/settings.ts +22 -0
- package/src/defaults/skc/skills/team/SKILL.md +17 -14
- package/src/defaults/skc/skills/ultragoal/SKILL.md +59 -4
- package/src/defaults/skc/skills/ultragoal/pipeline-validation-contracts.md +30 -0
- package/src/defaults/skc-defaults.ts +9 -0
- package/src/discovery/helpers.ts +10 -0
- package/src/discovery/index.ts +1 -0
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +60 -2
- package/src/export/ttsr.ts +96 -18
- package/src/extensibility/extensions/runner.ts +183 -219
- package/src/extensibility/extensions/types.ts +9 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +156 -44
- package/src/goals/runtime.ts +10 -2
- package/src/hindsight/backend.ts +1 -3
- package/src/hooks/native-skill-hook.ts +124 -4
- package/src/internal-urls/docs-index.generated.ts +17 -8
- package/src/lsp/client.ts +1 -0
- package/src/main.ts +95 -43
- package/src/memories/index.ts +12 -1
- package/src/modes/components/assistant-message.ts +241 -82
- package/src/modes/components/custom-editor.ts +1 -0
- package/src/modes/components/footer.ts +7 -2
- package/src/modes/components/model-selector.ts +54 -11
- package/src/modes/components/queued-message-selector.ts +92 -0
- package/src/modes/components/settings-selector.ts +4 -0
- package/src/modes/components/status-line.ts +167 -54
- package/src/modes/components/thinking-selector.ts +10 -8
- package/src/modes/components/tool-execution.ts +44 -19
- package/src/modes/components/welcome.ts +181 -44
- package/src/modes/controllers/command-controller.ts +40 -4
- package/src/modes/controllers/event-controller.ts +77 -49
- package/src/modes/controllers/extension-ui-controller.ts +12 -11
- package/src/modes/controllers/input-controller.ts +192 -35
- package/src/modes/controllers/selector-controller.ts +168 -24
- package/src/modes/interactive-mode.ts +56 -16
- package/src/modes/print-mode.ts +43 -4
- package/src/modes/prompt-action-autocomplete.ts +21 -20
- package/src/modes/rpc/rpc-mode.ts +32 -12
- package/src/modes/rpc/rpc-socket-security.ts +13 -1
- package/src/modes/rpc/rpc-types.ts +9 -0
- package/src/modes/shared/agent-wire/command-validation.ts +4 -0
- package/src/modes/shared/agent-wire/event-contract.ts +22 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +82 -0
- package/src/modes/shared/agent-wire/scopes.ts +1 -0
- package/src/modes/types.ts +3 -0
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/injected-user-submission.ts +94 -0
- package/src/modes/utils/ui-helpers.ts +20 -7
- package/src/notifications/config-commands.ts +20 -0
- package/src/notifications/config.ts +52 -5
- package/src/notifications/daemon-paths.ts +2 -0
- package/src/notifications/index.ts +144 -18
- package/src/notifications/lifecycle-commands.ts +74 -23
- package/src/notifications/lifecycle-control-runtime.ts +8 -3
- package/src/notifications/lifecycle-orchestrator.ts +19 -6
- package/src/notifications/reply-sent-store.ts +134 -0
- package/src/notifications/rich-draft.ts +107 -0
- package/src/notifications/rich-render.ts +142 -0
- package/src/notifications/telegram-daemon-control.ts +5 -3
- package/src/notifications/telegram-daemon.ts +606 -98
- package/src/notifications/telegram-reference.ts +17 -16
- package/src/notifications/threaded-render.ts +45 -2
- package/src/prompts/agents/architect.md +19 -10
- package/src/prompts/agents/critic.md +16 -18
- package/src/prompts/agents/executor.md +14 -11
- package/src/prompts/agents/planner.md +18 -13
- package/src/prompts/ci-green-request.md +3 -8
- package/src/prompts/goals/goal-continuation.md +0 -5
- package/src/prompts/goals/goal-mode-active.md +0 -5
- package/src/prompts/system/agent-creation-architect.md +2 -2
- package/src/prompts/system/plan-mode-active.md +1 -1
- package/src/prompts/system/plan-mode-subagent.md +3 -3
- package/src/prompts/system/project-prompt.md +0 -13
- package/src/prompts/system/subagent-system-prompt.md +3 -2
- package/src/prompts/system/system-prompt.md +29 -17
- package/src/prompts/system/volatile-project-context.md +10 -0
- package/src/prompts/system/web-search.md +4 -7
- package/src/prompts/tools/apply-patch.md +6 -0
- package/src/prompts/tools/ast-edit.md +1 -0
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/bisect.md +22 -0
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/computer.md +2 -2
- package/src/prompts/tools/cron.md +0 -2
- package/src/prompts/tools/eval.md +2 -2
- package/src/prompts/tools/find.md +1 -1
- package/src/prompts/tools/github.md +6 -6
- package/src/prompts/tools/goal.md +1 -3
- package/src/prompts/tools/image-gen.md +12 -5
- package/src/prompts/tools/irc.md +5 -4
- package/src/prompts/tools/job.md +2 -2
- package/src/prompts/tools/lsp.md +1 -1
- package/src/prompts/tools/monitor.md +2 -2
- package/src/prompts/tools/patch.md +2 -2
- package/src/prompts/tools/replace.md +2 -21
- package/src/prompts/tools/rewind.md +1 -1
- package/src/prompts/tools/search-tool-bm25.md +6 -11
- package/src/prompts/tools/search.md +1 -1
- package/src/prompts/tools/skill.md +3 -2
- package/src/prompts/tools/ssh.md +2 -1
- package/src/prompts/tools/subagent.md +2 -2
- package/src/prompts/tools/task.md +4 -5
- package/src/prompts/tools/todo-write.md +1 -1
- package/src/prompts/tools/vim.md +1 -0
- package/src/prompts/tools/web-search.md +2 -0
- package/src/prompts/tools/write.md +8 -2
- package/src/runtime-api-key.ts +16 -0
- package/src/sdk.ts +88 -36
- package/src/session/agent-session.ts +1013 -141
- package/src/session/agent-storage.ts +4 -0
- package/src/session/file-mention-pruning.ts +64 -0
- package/src/session/messages.ts +4 -0
- package/src/session/session-manager.ts +103 -4
- package/src/skc-runtime/deep-interview-ambiguity.ts +206 -0
- package/src/skc-runtime/deep-interview-recorder.ts +62 -8
- package/src/skc-runtime/deep-interview-state.ts +44 -2
- package/src/skc-runtime/session-state-sidecar.ts +263 -20
- package/src/skc-runtime/state-runtime.ts +12 -2
- package/src/skc-runtime/state-writer.ts +15 -0
- package/src/skc-runtime/tmux-common.ts +1 -0
- package/src/skc-runtime/ultragoal-guard.ts +55 -66
- package/src/skc-runtime/ultragoal-receipt-freshness.ts +315 -0
- package/src/skc-runtime/ultragoal-runtime.ts +1672 -159
- package/src/skc-runtime/workflow-manifest.generated.json +113 -2
- package/src/skc-runtime/workflow-manifest.ts +74 -1
- package/src/skill-state/active-state.ts +141 -5
- package/src/skill-state/deep-interview-mutation-guard.ts +67 -3
- package/src/slash-commands/builtin-registry.ts +296 -72
- package/src/system-prompt.ts +57 -16
- package/src/task/executor.ts +132 -24
- package/src/task/fork-context-advisory.ts +2 -7
- package/src/task/fork-context-budget.ts +9 -0
- package/src/task/index.ts +13 -6
- package/src/task/output-manager.ts +20 -8
- package/src/task/receipt.ts +26 -7
- package/src/task/token-log.test.ts +188 -0
- package/src/task/token-log.ts +179 -0
- package/src/tools/bisect.ts +367 -0
- package/src/tools/computer.ts +246 -43
- package/src/tools/index.ts +3 -0
- package/src/tools/output-meta.ts +116 -4
- package/src/tools/search.ts +8 -2
- package/src/tools/skill.ts +15 -0
- package/src/tools/telegram-send.ts +6 -0
- package/src/tools/ultragoal-ask-guard.ts +39 -5
- package/src/utils/file-mentions.ts +39 -7
- package/src/utils/git.ts +73 -0
- package/src/utils/pasted-image-path.ts +170 -0
- package/src/web/scrapers/youtube.ts +24 -12
- package/src/workflow/workflow-intent-diff.ts +29 -6
- package/src/workflow/workflow-intent-report-consumer.ts +221 -0
- package/src/workflow/workflow-intent-report-schema.ts +129 -0
- package/src/workflow/workflow-intent-report.ts +135 -0
|
@@ -111,6 +111,8 @@ type RunnerEmitResult<TEvent extends RunnerEmitEvent> = TEvent extends { type: "
|
|
|
111
111
|
: TEvent extends { type: "session.compacting" }
|
|
112
112
|
? SessionCompactingResult | undefined
|
|
113
113
|
: undefined;
|
|
114
|
+
type Handler = Extension["handlers"] extends Map<string, Array<infer T>> ? T : never;
|
|
115
|
+
type IndexedHandler = { ext: Extension; handler: Handler };
|
|
114
116
|
|
|
115
117
|
export type NewSessionHandler = (options?: {
|
|
116
118
|
parentSession?: string;
|
|
@@ -173,6 +175,8 @@ const noOpUIContext: ExtensionUIContext = {
|
|
|
173
175
|
export class ExtensionRunner {
|
|
174
176
|
#uiContext: ExtensionUIContext;
|
|
175
177
|
#errorListeners: Set<ExtensionErrorListener> = new Set();
|
|
178
|
+
#handlersByEvent: Map<string, IndexedHandler[]> = new Map();
|
|
179
|
+
|
|
176
180
|
#getModel: () => Model | undefined = () => undefined;
|
|
177
181
|
#isIdleFn: () => boolean = () => true;
|
|
178
182
|
#waitForIdleFn: () => Promise<void> = async () => {};
|
|
@@ -205,8 +209,27 @@ export class ExtensionRunner {
|
|
|
205
209
|
private readonly cwd: string,
|
|
206
210
|
private readonly sessionManager: SessionManager,
|
|
207
211
|
private readonly modelRegistry: ModelRegistry,
|
|
212
|
+
private readonly sessionMetadata?: ExtensionContext["sessionMetadata"],
|
|
208
213
|
) {
|
|
209
214
|
this.#uiContext = noOpUIContext;
|
|
215
|
+
this.#handlersByEvent = ExtensionRunner.#indexHandlers(extensions);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
static #indexHandlers(extensions: Extension[]): Map<string, IndexedHandler[]> {
|
|
219
|
+
const handlersByEvent = new Map<string, IndexedHandler[]>();
|
|
220
|
+
for (const ext of extensions) {
|
|
221
|
+
for (const [eventType, handlers] of ext.handlers) {
|
|
222
|
+
let indexedHandlers = handlersByEvent.get(eventType);
|
|
223
|
+
if (!indexedHandlers) {
|
|
224
|
+
indexedHandlers = [];
|
|
225
|
+
handlersByEvent.set(eventType, indexedHandlers);
|
|
226
|
+
}
|
|
227
|
+
for (const handler of handlers) {
|
|
228
|
+
indexedHandlers.push({ ext, handler });
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return handlersByEvent;
|
|
210
233
|
}
|
|
211
234
|
|
|
212
235
|
initialize(
|
|
@@ -395,13 +418,7 @@ export class ExtensionRunner {
|
|
|
395
418
|
}
|
|
396
419
|
|
|
397
420
|
hasHandlers(eventType: string): boolean {
|
|
398
|
-
|
|
399
|
-
const handlers = ext.handlers.get(eventType);
|
|
400
|
-
if (handlers && handlers.length > 0) {
|
|
401
|
-
return true;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
return false;
|
|
421
|
+
return (this.#handlersByEvent.get(eventType)?.length ?? 0) > 0;
|
|
405
422
|
}
|
|
406
423
|
|
|
407
424
|
getMessageRenderer(customType: string): MessageRenderer | undefined {
|
|
@@ -458,6 +475,7 @@ export class ExtensionRunner {
|
|
|
458
475
|
hasUI: this.hasUI(),
|
|
459
476
|
cwd: this.cwd,
|
|
460
477
|
sessionManager: this.sessionManager,
|
|
478
|
+
sessionMetadata: this.sessionMetadata,
|
|
461
479
|
modelRegistry: this.modelRegistry,
|
|
462
480
|
get model() {
|
|
463
481
|
return getModel();
|
|
@@ -509,11 +527,17 @@ export class ExtensionRunner {
|
|
|
509
527
|
ext: Extension,
|
|
510
528
|
timeoutMs: number,
|
|
511
529
|
): Promise<TResult | undefined> {
|
|
530
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
512
531
|
try {
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
]);
|
|
532
|
+
const timeoutPromise = new Promise<typeof EXTENSION_HANDLER_TIMEOUT>(resolve => {
|
|
533
|
+
timeout = setTimeout(() => resolve(EXTENSION_HANDLER_TIMEOUT), timeoutMs);
|
|
534
|
+
});
|
|
535
|
+
const handlerResult = await Promise.race([Promise.resolve(handler(event, ctx)), timeoutPromise]);
|
|
536
|
+
if (timeout !== undefined) {
|
|
537
|
+
clearTimeout(timeout);
|
|
538
|
+
timeout = undefined;
|
|
539
|
+
}
|
|
540
|
+
|
|
517
541
|
if (handlerResult === EXTENSION_HANDLER_TIMEOUT) {
|
|
518
542
|
const error = `handler timed out after ${timeoutMs}ms`;
|
|
519
543
|
logger.warn("Extension handler timed out", {
|
|
@@ -539,73 +563,67 @@ export class ExtensionRunner {
|
|
|
539
563
|
stack,
|
|
540
564
|
});
|
|
541
565
|
return undefined;
|
|
566
|
+
} finally {
|
|
567
|
+
if (timeout !== undefined) {
|
|
568
|
+
clearTimeout(timeout);
|
|
569
|
+
}
|
|
542
570
|
}
|
|
543
571
|
}
|
|
544
572
|
|
|
545
573
|
async emit<TEvent extends RunnerEmitEvent>(event: TEvent): Promise<RunnerEmitResult<TEvent>> {
|
|
574
|
+
const handlers = this.#handlersByEvent.get(event.type) ?? [];
|
|
575
|
+
if (handlers.length === 0) return undefined as RunnerEmitResult<TEvent>;
|
|
576
|
+
|
|
546
577
|
const ctx = this.createContext();
|
|
547
578
|
let result: SessionBeforeEventResult | SessionCompactingResult | undefined;
|
|
548
579
|
|
|
549
|
-
for (const ext of
|
|
550
|
-
const
|
|
551
|
-
if (!handlers || handlers.length === 0) continue;
|
|
552
|
-
|
|
553
|
-
for (const handler of handlers) {
|
|
554
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
555
|
-
handler,
|
|
556
|
-
event,
|
|
557
|
-
ctx,
|
|
558
|
-
ext,
|
|
559
|
-
extensionHandlerTimeoutMs,
|
|
560
|
-
);
|
|
561
|
-
|
|
562
|
-
if (this.#isSessionBeforeEvent(event) && handlerResult) {
|
|
563
|
-
result = handlerResult as SessionBeforeEventResult;
|
|
564
|
-
if (result.cancel) {
|
|
565
|
-
return result as RunnerEmitResult<TEvent>;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
580
|
+
for (const { ext, handler } of handlers) {
|
|
581
|
+
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
568
582
|
|
|
569
|
-
|
|
570
|
-
|
|
583
|
+
if (this.#isSessionBeforeEvent(event) && handlerResult) {
|
|
584
|
+
result = handlerResult as SessionBeforeEventResult;
|
|
585
|
+
if (result.cancel) {
|
|
586
|
+
return result as RunnerEmitResult<TEvent>;
|
|
571
587
|
}
|
|
572
588
|
}
|
|
589
|
+
|
|
590
|
+
if (event.type === "session.compacting" && handlerResult) {
|
|
591
|
+
result = handlerResult as SessionCompactingResult;
|
|
592
|
+
}
|
|
573
593
|
}
|
|
574
594
|
|
|
575
595
|
return result as RunnerEmitResult<TEvent>;
|
|
576
596
|
}
|
|
577
597
|
|
|
578
598
|
async emitToolResult(event: ToolResultEvent): Promise<ToolResultEventResult | undefined> {
|
|
599
|
+
const handlers = this.#handlersByEvent.get("tool_result") ?? [];
|
|
600
|
+
if (handlers.length === 0) return undefined;
|
|
601
|
+
|
|
579
602
|
const ctx = this.createContext();
|
|
580
603
|
const currentEvent: ToolResultEvent = { ...event };
|
|
581
604
|
let modified = false;
|
|
582
605
|
|
|
583
|
-
for (const ext of
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
if (handlerResult.isError !== undefined) {
|
|
606
|
-
currentEvent.isError = handlerResult.isError;
|
|
607
|
-
modified = true;
|
|
608
|
-
}
|
|
606
|
+
for (const { ext, handler } of handlers) {
|
|
607
|
+
const handlerResult = (await this.#runHandlerWithTimeout(
|
|
608
|
+
handler,
|
|
609
|
+
currentEvent,
|
|
610
|
+
ctx,
|
|
611
|
+
ext,
|
|
612
|
+
extensionHandlerTimeoutMs,
|
|
613
|
+
)) as ToolResultEventResult | undefined;
|
|
614
|
+
if (!handlerResult) continue;
|
|
615
|
+
|
|
616
|
+
if (handlerResult.content !== undefined) {
|
|
617
|
+
currentEvent.content = handlerResult.content;
|
|
618
|
+
modified = true;
|
|
619
|
+
}
|
|
620
|
+
if (handlerResult.details !== undefined) {
|
|
621
|
+
currentEvent.details = handlerResult.details;
|
|
622
|
+
modified = true;
|
|
623
|
+
}
|
|
624
|
+
if (handlerResult.isError !== undefined) {
|
|
625
|
+
currentEvent.isError = handlerResult.isError;
|
|
626
|
+
modified = true;
|
|
609
627
|
}
|
|
610
628
|
}
|
|
611
629
|
|
|
@@ -619,34 +637,32 @@ export class ExtensionRunner {
|
|
|
619
637
|
}
|
|
620
638
|
|
|
621
639
|
async emitToolCall(event: ToolCallEvent): Promise<ToolCallEventResult | undefined> {
|
|
640
|
+
const handlers = this.#handlersByEvent.get("tool_call") ?? [];
|
|
641
|
+
if (handlers.length === 0) return undefined;
|
|
642
|
+
|
|
622
643
|
const ctx = this.createContext();
|
|
623
644
|
let result: ToolCallEventResult | undefined;
|
|
624
645
|
|
|
625
|
-
for (const ext of
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
if (handlerResult) {
|
|
634
|
-
result = handlerResult as ToolCallEventResult;
|
|
635
|
-
if (result.block) {
|
|
636
|
-
return result;
|
|
637
|
-
}
|
|
646
|
+
for (const { ext, handler } of handlers) {
|
|
647
|
+
try {
|
|
648
|
+
const handlerResult = await handler(event, ctx);
|
|
649
|
+
|
|
650
|
+
if (handlerResult) {
|
|
651
|
+
result = handlerResult as ToolCallEventResult;
|
|
652
|
+
if (result.block) {
|
|
653
|
+
return result;
|
|
638
654
|
}
|
|
639
|
-
} catch (err) {
|
|
640
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
641
|
-
const stack = err instanceof Error ? err.stack : undefined;
|
|
642
|
-
this.emitError({
|
|
643
|
-
extensionPath: ext.path,
|
|
644
|
-
event: "tool_call",
|
|
645
|
-
error: message,
|
|
646
|
-
stack,
|
|
647
|
-
});
|
|
648
|
-
return { block: true, reason: `Extension ${ext.path} failed: ${message}` };
|
|
649
655
|
}
|
|
656
|
+
} catch (err) {
|
|
657
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
658
|
+
const stack = err instanceof Error ? err.stack : undefined;
|
|
659
|
+
this.emitError({
|
|
660
|
+
extensionPath: ext.path,
|
|
661
|
+
event: "tool_call",
|
|
662
|
+
error: message,
|
|
663
|
+
stack,
|
|
664
|
+
});
|
|
665
|
+
return { block: true, reason: `Extension ${ext.path} failed: ${message}` };
|
|
650
666
|
}
|
|
651
667
|
}
|
|
652
668
|
|
|
@@ -665,23 +681,15 @@ export class ExtensionRunner {
|
|
|
665
681
|
event: UserBashEvent | UserPythonEvent,
|
|
666
682
|
eventName: "user_bash" | "user_python",
|
|
667
683
|
): Promise<R | undefined> {
|
|
684
|
+
const handlers = this.#handlersByEvent.get(eventName) ?? [];
|
|
685
|
+
if (handlers.length === 0) return undefined;
|
|
686
|
+
|
|
668
687
|
const ctx = this.createContext();
|
|
669
688
|
|
|
670
|
-
for (const ext of
|
|
671
|
-
const
|
|
672
|
-
if (
|
|
673
|
-
|
|
674
|
-
for (const handler of handlers) {
|
|
675
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
676
|
-
handler,
|
|
677
|
-
event,
|
|
678
|
-
ctx,
|
|
679
|
-
ext,
|
|
680
|
-
extensionHandlerTimeoutMs,
|
|
681
|
-
);
|
|
682
|
-
if (handlerResult) {
|
|
683
|
-
return handlerResult as R;
|
|
684
|
-
}
|
|
689
|
+
for (const { ext, handler } of handlers) {
|
|
690
|
+
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
691
|
+
if (handlerResult) {
|
|
692
|
+
return handlerResult as R;
|
|
685
693
|
}
|
|
686
694
|
}
|
|
687
695
|
|
|
@@ -696,35 +704,26 @@ export class ExtensionRunner {
|
|
|
696
704
|
promptPaths: Array<{ path: string; extensionPath: string }>;
|
|
697
705
|
themePaths: Array<{ path: string; extensionPath: string }>;
|
|
698
706
|
}> {
|
|
707
|
+
const handlers = this.#handlersByEvent.get("resources_discover") ?? [];
|
|
708
|
+
if (handlers.length === 0) return { skillPaths: [], promptPaths: [], themePaths: [] };
|
|
699
709
|
const ctx = this.createContext();
|
|
700
710
|
const skillPaths: Array<{ path: string; extensionPath: string }> = [];
|
|
701
711
|
const promptPaths: Array<{ path: string; extensionPath: string }> = [];
|
|
702
712
|
const themePaths: Array<{ path: string; extensionPath: string }> = [];
|
|
703
713
|
|
|
704
|
-
for (const ext of
|
|
705
|
-
const
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
);
|
|
717
|
-
const result = handlerResult as ResourcesDiscoverResult | undefined;
|
|
718
|
-
|
|
719
|
-
if (result?.skillPaths?.length) {
|
|
720
|
-
skillPaths.push(...result.skillPaths.map(path => ({ path, extensionPath: ext.path })));
|
|
721
|
-
}
|
|
722
|
-
if (result?.promptPaths?.length) {
|
|
723
|
-
promptPaths.push(...result.promptPaths.map(path => ({ path, extensionPath: ext.path })));
|
|
724
|
-
}
|
|
725
|
-
if (result?.themePaths?.length) {
|
|
726
|
-
themePaths.push(...result.themePaths.map(path => ({ path, extensionPath: ext.path })));
|
|
727
|
-
}
|
|
714
|
+
for (const { ext, handler } of handlers) {
|
|
715
|
+
const event: ResourcesDiscoverEvent = { type: "resources_discover", cwd, reason };
|
|
716
|
+
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
717
|
+
const result = handlerResult as ResourcesDiscoverResult | undefined;
|
|
718
|
+
|
|
719
|
+
if (result?.skillPaths?.length) {
|
|
720
|
+
skillPaths.push(...result.skillPaths.map(path => ({ path, extensionPath: ext.path })));
|
|
721
|
+
}
|
|
722
|
+
if (result?.promptPaths?.length) {
|
|
723
|
+
promptPaths.push(...result.promptPaths.map(path => ({ path, extensionPath: ext.path })));
|
|
724
|
+
}
|
|
725
|
+
if (result?.themePaths?.length) {
|
|
726
|
+
themePaths.push(...result.themePaths.map(path => ({ path, extensionPath: ext.path })));
|
|
728
727
|
}
|
|
729
728
|
}
|
|
730
729
|
|
|
@@ -737,39 +736,33 @@ export class ExtensionRunner {
|
|
|
737
736
|
images: ImageContent[] | undefined,
|
|
738
737
|
source: "interactive" | "rpc" | "extension",
|
|
739
738
|
): Promise<InputEventResult> {
|
|
739
|
+
const handlers = this.#handlersByEvent.get("input") ?? [];
|
|
740
|
+
if (handlers.length === 0) return {};
|
|
741
|
+
|
|
740
742
|
const ctx = this.createContext();
|
|
741
743
|
let currentText = text;
|
|
742
744
|
let currentImages = images;
|
|
743
745
|
|
|
744
|
-
for (const ext of
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
currentImages = result.images ?? currentImages;
|
|
754
|
-
}
|
|
746
|
+
for (const { ext, handler } of handlers) {
|
|
747
|
+
const event: InputEvent = { type: "input", text: currentText, images: currentImages, source };
|
|
748
|
+
const result = (await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs)) as
|
|
749
|
+
| InputEventResult
|
|
750
|
+
| undefined;
|
|
751
|
+
if (result?.handled) return result;
|
|
752
|
+
if (result?.text !== undefined) {
|
|
753
|
+
currentText = result.text;
|
|
754
|
+
currentImages = result.images ?? currentImages;
|
|
755
755
|
}
|
|
756
756
|
}
|
|
757
|
+
|
|
757
758
|
return currentText !== text || currentImages !== images ? { text: currentText, images: currentImages } : {};
|
|
758
759
|
}
|
|
759
760
|
|
|
760
761
|
async emitContext(messages: AgentMessage[]): Promise<AgentMessage[]> {
|
|
761
|
-
const
|
|
762
|
-
|
|
763
|
-
// Check if any extensions actually have context handlers before cloning
|
|
764
|
-
let hasContextHandlers = false;
|
|
765
|
-
for (const ext of this.extensions) {
|
|
766
|
-
if (ext.handlers.get("context")?.length) {
|
|
767
|
-
hasContextHandlers = true;
|
|
768
|
-
break;
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
if (!hasContextHandlers) return messages;
|
|
762
|
+
const handlers = this.#handlersByEvent.get("context") ?? [];
|
|
763
|
+
if (handlers.length === 0) return messages;
|
|
772
764
|
|
|
765
|
+
const ctx = this.createContext();
|
|
773
766
|
let currentMessages: AgentMessage[];
|
|
774
767
|
try {
|
|
775
768
|
currentMessages = structuredClone(messages);
|
|
@@ -780,23 +773,12 @@ export class ExtensionRunner {
|
|
|
780
773
|
currentMessages = [...messages];
|
|
781
774
|
}
|
|
782
775
|
|
|
783
|
-
for (const ext of
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
790
|
-
handler,
|
|
791
|
-
event,
|
|
792
|
-
ctx,
|
|
793
|
-
ext,
|
|
794
|
-
extensionHandlerTimeoutMs,
|
|
795
|
-
);
|
|
796
|
-
|
|
797
|
-
if (handlerResult && (handlerResult as ContextEventResult).messages) {
|
|
798
|
-
currentMessages = (handlerResult as ContextEventResult).messages!;
|
|
799
|
-
}
|
|
776
|
+
for (const { ext, handler } of handlers) {
|
|
777
|
+
const event: ContextEvent = { type: "context", messages: currentMessages };
|
|
778
|
+
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
779
|
+
|
|
780
|
+
if (handlerResult && (handlerResult as ContextEventResult).messages) {
|
|
781
|
+
currentMessages = (handlerResult as ContextEventResult).messages!;
|
|
800
782
|
}
|
|
801
783
|
}
|
|
802
784
|
|
|
@@ -804,28 +786,20 @@ export class ExtensionRunner {
|
|
|
804
786
|
}
|
|
805
787
|
|
|
806
788
|
async emitBeforeProviderRequest(payload: unknown): Promise<BeforeProviderRequestEventResult> {
|
|
789
|
+
const handlers = this.#handlersByEvent.get("before_provider_request") ?? [];
|
|
790
|
+
if (handlers.length === 0) return payload;
|
|
791
|
+
|
|
807
792
|
const ctx = this.createContext();
|
|
808
793
|
let currentPayload = payload;
|
|
809
794
|
|
|
810
|
-
for (const ext of
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
};
|
|
819
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
820
|
-
handler,
|
|
821
|
-
event,
|
|
822
|
-
ctx,
|
|
823
|
-
ext,
|
|
824
|
-
extensionHandlerTimeoutMs,
|
|
825
|
-
);
|
|
826
|
-
if (handlerResult !== undefined) {
|
|
827
|
-
currentPayload = handlerResult;
|
|
828
|
-
}
|
|
795
|
+
for (const { ext, handler } of handlers) {
|
|
796
|
+
const event: BeforeProviderRequestEvent = {
|
|
797
|
+
type: "before_provider_request",
|
|
798
|
+
payload: currentPayload,
|
|
799
|
+
};
|
|
800
|
+
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
801
|
+
if (handlerResult !== undefined) {
|
|
802
|
+
currentPayload = handlerResult;
|
|
829
803
|
}
|
|
830
804
|
}
|
|
831
805
|
|
|
@@ -833,22 +807,20 @@ export class ExtensionRunner {
|
|
|
833
807
|
}
|
|
834
808
|
|
|
835
809
|
async emitAfterProviderResponse(response: ProviderResponseMetadata, _model?: Model): Promise<void> {
|
|
810
|
+
const handlers = this.#handlersByEvent.get("after_provider_response") ?? [];
|
|
811
|
+
if (handlers.length === 0) return;
|
|
812
|
+
|
|
836
813
|
const ctx = this.createContext();
|
|
837
814
|
|
|
838
|
-
for (const ext of
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
requestId: response.requestId,
|
|
848
|
-
metadata: response.metadata,
|
|
849
|
-
};
|
|
850
|
-
await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
851
|
-
}
|
|
815
|
+
for (const { ext, handler } of handlers) {
|
|
816
|
+
const event: AfterProviderResponseEvent = {
|
|
817
|
+
type: "after_provider_response",
|
|
818
|
+
status: response.status,
|
|
819
|
+
headers: response.headers,
|
|
820
|
+
requestId: response.requestId,
|
|
821
|
+
metadata: response.metadata,
|
|
822
|
+
};
|
|
823
|
+
await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
852
824
|
}
|
|
853
825
|
}
|
|
854
826
|
|
|
@@ -857,39 +829,31 @@ export class ExtensionRunner {
|
|
|
857
829
|
images: ImageContent[] | undefined,
|
|
858
830
|
systemPrompt: string[],
|
|
859
831
|
): Promise<BeforeAgentStartCombinedResult | undefined> {
|
|
832
|
+
const handlers = this.#handlersByEvent.get("before_agent_start") ?? [];
|
|
833
|
+
if (handlers.length === 0) return undefined;
|
|
834
|
+
|
|
860
835
|
const ctx = this.createContext();
|
|
861
836
|
const messages: NonNullable<BeforeAgentStartEventResult["message"]>[] = [];
|
|
862
837
|
let currentSystemPrompt = systemPrompt;
|
|
863
838
|
let systemPromptModified = false;
|
|
864
839
|
|
|
865
|
-
for (const ext of
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
images,
|
|
874
|
-
systemPrompt: currentSystemPrompt,
|
|
875
|
-
};
|
|
876
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
877
|
-
handler,
|
|
878
|
-
event,
|
|
879
|
-
ctx,
|
|
880
|
-
ext,
|
|
881
|
-
extensionHandlerTimeoutMs,
|
|
882
|
-
);
|
|
840
|
+
for (const { ext, handler } of handlers) {
|
|
841
|
+
const event: BeforeAgentStartEvent = {
|
|
842
|
+
type: "before_agent_start",
|
|
843
|
+
prompt,
|
|
844
|
+
images,
|
|
845
|
+
systemPrompt: currentSystemPrompt,
|
|
846
|
+
};
|
|
847
|
+
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
883
848
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
}
|
|
849
|
+
if (handlerResult) {
|
|
850
|
+
const result = handlerResult as BeforeAgentStartEventResult;
|
|
851
|
+
if (result.message) {
|
|
852
|
+
messages.push(result.message);
|
|
853
|
+
}
|
|
854
|
+
if (result.systemPrompt !== undefined) {
|
|
855
|
+
currentSystemPrompt = result.systemPrompt;
|
|
856
|
+
systemPromptModified = true;
|
|
893
857
|
}
|
|
894
858
|
}
|
|
895
859
|
}
|
|
@@ -285,6 +285,13 @@ export interface CompactOptions {
|
|
|
285
285
|
onError?: (error: Error) => void;
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
export interface ExtensionSessionMetadata {
|
|
289
|
+
kind: "main" | "sub";
|
|
290
|
+
taskDepth: number;
|
|
291
|
+
parentTaskPrefix?: string;
|
|
292
|
+
currentAgentType?: string;
|
|
293
|
+
}
|
|
294
|
+
|
|
288
295
|
/**
|
|
289
296
|
* Context passed to extension event handlers.
|
|
290
297
|
*/
|
|
@@ -306,6 +313,8 @@ export interface ExtensionContext {
|
|
|
306
313
|
cwd: string;
|
|
307
314
|
/** Session manager (read-only) */
|
|
308
315
|
sessionManager: ReadonlySessionManager;
|
|
316
|
+
/** Session classification supplied by the SDK for extension policy decisions. */
|
|
317
|
+
sessionMetadata?: ExtensionSessionMetadata;
|
|
309
318
|
/** Model registry for API key resolution */
|
|
310
319
|
modelRegistry: ModelRegistry;
|
|
311
320
|
/** Current model (may be undefined) */
|