@gajae-code/coding-agent 0.8.2 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/dist/types/append-only-mode.d.ts +31 -0
- package/dist/types/capability/rule.d.ts +8 -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/update-cli.d.ts +22 -0
- package/dist/types/config/settings-schema.d.ts +119 -1
- 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/gjc-runtime/deep-interview-state.d.ts +5 -2
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +7 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +3 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +26 -0
- package/dist/types/gjc-runtime/tmux-common.d.ts +1 -0
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +42 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +119 -13
- package/dist/types/goals/runtime.d.ts +1 -0
- package/dist/types/hooks/native-skill-hook.d.ts +12 -0
- package/dist/types/modes/components/assistant-message.d.ts +5 -1
- 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/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +4 -0
- 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 +22 -0
- package/dist/types/notifications/index.d.ts +2 -0
- package/dist/types/notifications/lifecycle-commands.d.ts +1 -0
- 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-cli.d.ts +3 -3
- package/dist/types/notifications/telegram-daemon.d.ts +30 -0
- package/dist/types/notifications/telegram-reference.d.ts +7 -0
- package/dist/types/notifications/threaded-render.d.ts +14 -0
- package/dist/types/sdk.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +43 -1
- 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/skill-state/active-state.d.ts +18 -1
- package/dist/types/system-prompt.d.ts +18 -2
- package/dist/types/task/executor.d.ts +1 -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/index.d.ts +1 -0
- package/dist/types/tools/search.d.ts +2 -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/package.json +8 -11
- 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/config-cli.ts +27 -3
- 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 +11 -9
- package/src/cli/update-cli.ts +85 -9
- package/src/cli.ts +26 -0
- package/src/commands/contribution-prep.ts +1 -1
- package/src/config/keybindings.ts +1 -1
- package/src/config/settings-schema.ts +76 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +12 -13
- package/src/defaults/gjc/skills/ralplan/SKILL.md +30 -93
- package/src/defaults/gjc/skills/team/SKILL.md +16 -13
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +59 -4
- package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +30 -0
- package/src/defaults/gjc-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 +181 -219
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +156 -44
- package/src/gjc-runtime/deep-interview-state.ts +31 -2
- package/src/gjc-runtime/launch-tmux.ts +6 -0
- package/src/gjc-runtime/session-state-sidecar.ts +208 -13
- package/src/gjc-runtime/state-writer.ts +15 -0
- package/src/gjc-runtime/team-runtime.ts +175 -19
- package/src/gjc-runtime/tmux-common.ts +1 -0
- package/src/gjc-runtime/ultragoal-guard.ts +55 -66
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +315 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +1602 -143
- package/src/gjc-runtime/workflow-manifest.generated.json +113 -2
- package/src/gjc-runtime/workflow-manifest.ts +74 -1
- package/src/goals/runtime.ts +10 -2
- package/src/hindsight/backend.ts +1 -3
- package/src/hooks/native-skill-hook.ts +95 -4
- package/src/internal-urls/docs-index.generated.ts +18 -9
- package/src/lsp/client.ts +1 -0
- package/src/main.ts +43 -2
- 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/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/controllers/command-controller.ts +39 -2
- package/src/modes/controllers/event-controller.ts +77 -49
- package/src/modes/controllers/extension-ui-controller.ts +8 -1
- package/src/modes/controllers/input-controller.ts +13 -18
- package/src/modes/controllers/selector-controller.ts +41 -0
- package/src/modes/interactive-mode.ts +14 -1
- 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/injected-user-submission.ts +94 -0
- package/src/modes/utils/ui-helpers.ts +17 -4
- package/src/notifications/config-commands.ts +20 -0
- package/src/notifications/config.ts +43 -4
- package/src/notifications/index.ts +105 -9
- package/src/notifications/lifecycle-commands.ts +37 -16
- package/src/notifications/lifecycle-control-runtime.ts +8 -3
- 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-cli.ts +54 -7
- package/src/notifications/telegram-daemon-control.ts +2 -2
- package/src/notifications/telegram-daemon.ts +390 -56
- package/src/notifications/telegram-reference.ts +17 -0
- 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 +26 -19
- 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/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/sdk.ts +68 -30
- package/src/session/agent-session.ts +734 -107
- package/src/session/file-mention-pruning.ts +64 -0
- package/src/session/messages.ts +4 -0
- package/src/session/session-manager.ts +59 -2
- 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 +143 -1
- package/src/system-prompt.ts +57 -16
- package/src/task/executor.ts +125 -20
- package/src/task/fork-context-advisory.ts +2 -7
- package/src/task/fork-context-budget.ts +9 -0
- package/src/task/index.ts +4 -3
- package/src/task/output-manager.ts +4 -2
- 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/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/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
|
@@ -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 () => {};
|
|
@@ -208,6 +212,24 @@ export class ExtensionRunner {
|
|
|
208
212
|
private readonly sessionMetadata?: ExtensionContext["sessionMetadata"],
|
|
209
213
|
) {
|
|
210
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;
|
|
211
233
|
}
|
|
212
234
|
|
|
213
235
|
initialize(
|
|
@@ -396,13 +418,7 @@ export class ExtensionRunner {
|
|
|
396
418
|
}
|
|
397
419
|
|
|
398
420
|
hasHandlers(eventType: string): boolean {
|
|
399
|
-
|
|
400
|
-
const handlers = ext.handlers.get(eventType);
|
|
401
|
-
if (handlers && handlers.length > 0) {
|
|
402
|
-
return true;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
return false;
|
|
421
|
+
return (this.#handlersByEvent.get(eventType)?.length ?? 0) > 0;
|
|
406
422
|
}
|
|
407
423
|
|
|
408
424
|
getMessageRenderer(customType: string): MessageRenderer | undefined {
|
|
@@ -511,11 +527,17 @@ export class ExtensionRunner {
|
|
|
511
527
|
ext: Extension,
|
|
512
528
|
timeoutMs: number,
|
|
513
529
|
): Promise<TResult | undefined> {
|
|
530
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
514
531
|
try {
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
]);
|
|
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
|
+
|
|
519
541
|
if (handlerResult === EXTENSION_HANDLER_TIMEOUT) {
|
|
520
542
|
const error = `handler timed out after ${timeoutMs}ms`;
|
|
521
543
|
logger.warn("Extension handler timed out", {
|
|
@@ -541,73 +563,67 @@ export class ExtensionRunner {
|
|
|
541
563
|
stack,
|
|
542
564
|
});
|
|
543
565
|
return undefined;
|
|
566
|
+
} finally {
|
|
567
|
+
if (timeout !== undefined) {
|
|
568
|
+
clearTimeout(timeout);
|
|
569
|
+
}
|
|
544
570
|
}
|
|
545
571
|
}
|
|
546
572
|
|
|
547
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
|
+
|
|
548
577
|
const ctx = this.createContext();
|
|
549
578
|
let result: SessionBeforeEventResult | SessionCompactingResult | undefined;
|
|
550
579
|
|
|
551
|
-
for (const ext of
|
|
552
|
-
const
|
|
553
|
-
if (!handlers || handlers.length === 0) continue;
|
|
554
|
-
|
|
555
|
-
for (const handler of handlers) {
|
|
556
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
557
|
-
handler,
|
|
558
|
-
event,
|
|
559
|
-
ctx,
|
|
560
|
-
ext,
|
|
561
|
-
extensionHandlerTimeoutMs,
|
|
562
|
-
);
|
|
563
|
-
|
|
564
|
-
if (this.#isSessionBeforeEvent(event) && handlerResult) {
|
|
565
|
-
result = handlerResult as SessionBeforeEventResult;
|
|
566
|
-
if (result.cancel) {
|
|
567
|
-
return result as RunnerEmitResult<TEvent>;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
580
|
+
for (const { ext, handler } of handlers) {
|
|
581
|
+
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
570
582
|
|
|
571
|
-
|
|
572
|
-
|
|
583
|
+
if (this.#isSessionBeforeEvent(event) && handlerResult) {
|
|
584
|
+
result = handlerResult as SessionBeforeEventResult;
|
|
585
|
+
if (result.cancel) {
|
|
586
|
+
return result as RunnerEmitResult<TEvent>;
|
|
573
587
|
}
|
|
574
588
|
}
|
|
589
|
+
|
|
590
|
+
if (event.type === "session.compacting" && handlerResult) {
|
|
591
|
+
result = handlerResult as SessionCompactingResult;
|
|
592
|
+
}
|
|
575
593
|
}
|
|
576
594
|
|
|
577
595
|
return result as RunnerEmitResult<TEvent>;
|
|
578
596
|
}
|
|
579
597
|
|
|
580
598
|
async emitToolResult(event: ToolResultEvent): Promise<ToolResultEventResult | undefined> {
|
|
599
|
+
const handlers = this.#handlersByEvent.get("tool_result") ?? [];
|
|
600
|
+
if (handlers.length === 0) return undefined;
|
|
601
|
+
|
|
581
602
|
const ctx = this.createContext();
|
|
582
603
|
const currentEvent: ToolResultEvent = { ...event };
|
|
583
604
|
let modified = false;
|
|
584
605
|
|
|
585
|
-
for (const ext of
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
}
|
|
607
|
-
if (handlerResult.isError !== undefined) {
|
|
608
|
-
currentEvent.isError = handlerResult.isError;
|
|
609
|
-
modified = true;
|
|
610
|
-
}
|
|
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;
|
|
611
627
|
}
|
|
612
628
|
}
|
|
613
629
|
|
|
@@ -621,34 +637,32 @@ export class ExtensionRunner {
|
|
|
621
637
|
}
|
|
622
638
|
|
|
623
639
|
async emitToolCall(event: ToolCallEvent): Promise<ToolCallEventResult | undefined> {
|
|
640
|
+
const handlers = this.#handlersByEvent.get("tool_call") ?? [];
|
|
641
|
+
if (handlers.length === 0) return undefined;
|
|
642
|
+
|
|
624
643
|
const ctx = this.createContext();
|
|
625
644
|
let result: ToolCallEventResult | undefined;
|
|
626
645
|
|
|
627
|
-
for (const ext of
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
if (handlerResult) {
|
|
636
|
-
result = handlerResult as ToolCallEventResult;
|
|
637
|
-
if (result.block) {
|
|
638
|
-
return result;
|
|
639
|
-
}
|
|
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;
|
|
640
654
|
}
|
|
641
|
-
} catch (err) {
|
|
642
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
643
|
-
const stack = err instanceof Error ? err.stack : undefined;
|
|
644
|
-
this.emitError({
|
|
645
|
-
extensionPath: ext.path,
|
|
646
|
-
event: "tool_call",
|
|
647
|
-
error: message,
|
|
648
|
-
stack,
|
|
649
|
-
});
|
|
650
|
-
return { block: true, reason: `Extension ${ext.path} failed: ${message}` };
|
|
651
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}` };
|
|
652
666
|
}
|
|
653
667
|
}
|
|
654
668
|
|
|
@@ -667,23 +681,15 @@ export class ExtensionRunner {
|
|
|
667
681
|
event: UserBashEvent | UserPythonEvent,
|
|
668
682
|
eventName: "user_bash" | "user_python",
|
|
669
683
|
): Promise<R | undefined> {
|
|
684
|
+
const handlers = this.#handlersByEvent.get(eventName) ?? [];
|
|
685
|
+
if (handlers.length === 0) return undefined;
|
|
686
|
+
|
|
670
687
|
const ctx = this.createContext();
|
|
671
688
|
|
|
672
|
-
for (const ext of
|
|
673
|
-
const
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
for (const handler of handlers) {
|
|
677
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
678
|
-
handler,
|
|
679
|
-
event,
|
|
680
|
-
ctx,
|
|
681
|
-
ext,
|
|
682
|
-
extensionHandlerTimeoutMs,
|
|
683
|
-
);
|
|
684
|
-
if (handlerResult) {
|
|
685
|
-
return handlerResult as R;
|
|
686
|
-
}
|
|
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;
|
|
687
693
|
}
|
|
688
694
|
}
|
|
689
695
|
|
|
@@ -698,35 +704,26 @@ export class ExtensionRunner {
|
|
|
698
704
|
promptPaths: Array<{ path: string; extensionPath: string }>;
|
|
699
705
|
themePaths: Array<{ path: string; extensionPath: string }>;
|
|
700
706
|
}> {
|
|
707
|
+
const handlers = this.#handlersByEvent.get("resources_discover") ?? [];
|
|
708
|
+
if (handlers.length === 0) return { skillPaths: [], promptPaths: [], themePaths: [] };
|
|
701
709
|
const ctx = this.createContext();
|
|
702
710
|
const skillPaths: Array<{ path: string; extensionPath: string }> = [];
|
|
703
711
|
const promptPaths: Array<{ path: string; extensionPath: string }> = [];
|
|
704
712
|
const themePaths: Array<{ path: string; extensionPath: string }> = [];
|
|
705
713
|
|
|
706
|
-
for (const ext of
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
);
|
|
719
|
-
const result = handlerResult as ResourcesDiscoverResult | undefined;
|
|
720
|
-
|
|
721
|
-
if (result?.skillPaths?.length) {
|
|
722
|
-
skillPaths.push(...result.skillPaths.map(path => ({ path, extensionPath: ext.path })));
|
|
723
|
-
}
|
|
724
|
-
if (result?.promptPaths?.length) {
|
|
725
|
-
promptPaths.push(...result.promptPaths.map(path => ({ path, extensionPath: ext.path })));
|
|
726
|
-
}
|
|
727
|
-
if (result?.themePaths?.length) {
|
|
728
|
-
themePaths.push(...result.themePaths.map(path => ({ path, extensionPath: ext.path })));
|
|
729
|
-
}
|
|
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 })));
|
|
730
727
|
}
|
|
731
728
|
}
|
|
732
729
|
|
|
@@ -739,39 +736,33 @@ export class ExtensionRunner {
|
|
|
739
736
|
images: ImageContent[] | undefined,
|
|
740
737
|
source: "interactive" | "rpc" | "extension",
|
|
741
738
|
): Promise<InputEventResult> {
|
|
739
|
+
const handlers = this.#handlersByEvent.get("input") ?? [];
|
|
740
|
+
if (handlers.length === 0) return {};
|
|
741
|
+
|
|
742
742
|
const ctx = this.createContext();
|
|
743
743
|
let currentText = text;
|
|
744
744
|
let currentImages = images;
|
|
745
745
|
|
|
746
|
-
for (const ext of
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
currentImages = result.images ?? currentImages;
|
|
756
|
-
}
|
|
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;
|
|
757
755
|
}
|
|
758
756
|
}
|
|
757
|
+
|
|
759
758
|
return currentText !== text || currentImages !== images ? { text: currentText, images: currentImages } : {};
|
|
760
759
|
}
|
|
761
760
|
|
|
762
761
|
async emitContext(messages: AgentMessage[]): Promise<AgentMessage[]> {
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
// Check if any extensions actually have context handlers before cloning
|
|
766
|
-
let hasContextHandlers = false;
|
|
767
|
-
for (const ext of this.extensions) {
|
|
768
|
-
if (ext.handlers.get("context")?.length) {
|
|
769
|
-
hasContextHandlers = true;
|
|
770
|
-
break;
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
if (!hasContextHandlers) return messages;
|
|
762
|
+
const handlers = this.#handlersByEvent.get("context") ?? [];
|
|
763
|
+
if (handlers.length === 0) return messages;
|
|
774
764
|
|
|
765
|
+
const ctx = this.createContext();
|
|
775
766
|
let currentMessages: AgentMessage[];
|
|
776
767
|
try {
|
|
777
768
|
currentMessages = structuredClone(messages);
|
|
@@ -782,23 +773,12 @@ export class ExtensionRunner {
|
|
|
782
773
|
currentMessages = [...messages];
|
|
783
774
|
}
|
|
784
775
|
|
|
785
|
-
for (const ext of
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
792
|
-
handler,
|
|
793
|
-
event,
|
|
794
|
-
ctx,
|
|
795
|
-
ext,
|
|
796
|
-
extensionHandlerTimeoutMs,
|
|
797
|
-
);
|
|
798
|
-
|
|
799
|
-
if (handlerResult && (handlerResult as ContextEventResult).messages) {
|
|
800
|
-
currentMessages = (handlerResult as ContextEventResult).messages!;
|
|
801
|
-
}
|
|
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!;
|
|
802
782
|
}
|
|
803
783
|
}
|
|
804
784
|
|
|
@@ -806,28 +786,20 @@ export class ExtensionRunner {
|
|
|
806
786
|
}
|
|
807
787
|
|
|
808
788
|
async emitBeforeProviderRequest(payload: unknown): Promise<BeforeProviderRequestEventResult> {
|
|
789
|
+
const handlers = this.#handlersByEvent.get("before_provider_request") ?? [];
|
|
790
|
+
if (handlers.length === 0) return payload;
|
|
791
|
+
|
|
809
792
|
const ctx = this.createContext();
|
|
810
793
|
let currentPayload = payload;
|
|
811
794
|
|
|
812
|
-
for (const ext of
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
};
|
|
821
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
822
|
-
handler,
|
|
823
|
-
event,
|
|
824
|
-
ctx,
|
|
825
|
-
ext,
|
|
826
|
-
extensionHandlerTimeoutMs,
|
|
827
|
-
);
|
|
828
|
-
if (handlerResult !== undefined) {
|
|
829
|
-
currentPayload = handlerResult;
|
|
830
|
-
}
|
|
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;
|
|
831
803
|
}
|
|
832
804
|
}
|
|
833
805
|
|
|
@@ -835,22 +807,20 @@ export class ExtensionRunner {
|
|
|
835
807
|
}
|
|
836
808
|
|
|
837
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
|
+
|
|
838
813
|
const ctx = this.createContext();
|
|
839
814
|
|
|
840
|
-
for (const ext of
|
|
841
|
-
const
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
requestId: response.requestId,
|
|
850
|
-
metadata: response.metadata,
|
|
851
|
-
};
|
|
852
|
-
await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
853
|
-
}
|
|
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);
|
|
854
824
|
}
|
|
855
825
|
}
|
|
856
826
|
|
|
@@ -859,39 +829,31 @@ export class ExtensionRunner {
|
|
|
859
829
|
images: ImageContent[] | undefined,
|
|
860
830
|
systemPrompt: string[],
|
|
861
831
|
): Promise<BeforeAgentStartCombinedResult | undefined> {
|
|
832
|
+
const handlers = this.#handlersByEvent.get("before_agent_start") ?? [];
|
|
833
|
+
if (handlers.length === 0) return undefined;
|
|
834
|
+
|
|
862
835
|
const ctx = this.createContext();
|
|
863
836
|
const messages: NonNullable<BeforeAgentStartEventResult["message"]>[] = [];
|
|
864
837
|
let currentSystemPrompt = systemPrompt;
|
|
865
838
|
let systemPromptModified = false;
|
|
866
839
|
|
|
867
|
-
for (const ext of
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
images,
|
|
876
|
-
systemPrompt: currentSystemPrompt,
|
|
877
|
-
};
|
|
878
|
-
const handlerResult = await this.#runHandlerWithTimeout(
|
|
879
|
-
handler,
|
|
880
|
-
event,
|
|
881
|
-
ctx,
|
|
882
|
-
ext,
|
|
883
|
-
extensionHandlerTimeoutMs,
|
|
884
|
-
);
|
|
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);
|
|
885
848
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
}
|
|
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;
|
|
895
857
|
}
|
|
896
858
|
}
|
|
897
859
|
}
|