@gajae-code/coding-agent 0.12.5 → 0.12.6
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 +32 -0
- package/README.md +4 -1
- package/dist/types/eval/backend.d.ts +2 -2
- package/dist/types/exec/bash-executor.d.ts +10 -8
- package/dist/types/extensibility/extensions/runner.d.ts +9 -7
- package/dist/types/gjc-runtime/launch-tmux.d.ts +22 -3
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
- package/dist/types/gjc-runtime/team-launch.d.ts +3 -1
- package/dist/types/gjc-runtime/team-runtime.d.ts +14 -2
- package/dist/types/gjc-runtime/team-store.d.ts +0 -4
- package/dist/types/gjc-runtime/team-workers.d.ts +5 -0
- package/dist/types/gjc-runtime/tmux-common.d.ts +1 -0
- package/dist/types/gjc-runtime/tmux-provider-context.d.ts +57 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +8 -1
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +3 -0
- package/dist/types/gjc-runtime/ultragoal-review-source.d.ts +83 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +57 -4
- package/dist/types/internal-urls/registry-helpers.d.ts +18 -0
- package/dist/types/modes/components/gjc-bundle-settings.d.ts +1 -0
- package/dist/types/modes/components/plugin-settings.d.ts +2 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +18 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +13 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +1 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -3
- package/dist/types/sdk/bus/index.d.ts +4 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -2
- package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -3
- package/dist/types/sdk/bus/topic-registry.d.ts +63 -3
- package/dist/types/sdk/host/host.d.ts +23 -2
- package/dist/types/sdk/host/reverse-leases.d.ts +7 -4
- package/dist/types/session/agent-session.d.ts +5 -4
- package/dist/types/session/artifacts.d.ts +8 -5
- package/dist/types/session/attempt-record-store.d.ts +19 -0
- package/dist/types/session/client-bridge.d.ts +14 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +5 -2
- package/dist/types/session/messages.d.ts +4 -1
- package/dist/types/session/session-manager.d.ts +6 -4
- package/dist/types/session/session-storage.d.ts +8 -0
- package/dist/types/session/streaming-output.d.ts +32 -0
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +178 -0
- package/dist/types/tools/bash.d.ts +1 -1
- package/dist/types/tools/fetch.d.ts +3 -0
- package/dist/types/tools/output-meta.d.ts +37 -5
- package/dist/types/tools/tool-result.d.ts +1 -0
- package/dist/types/utils/artifact-id.d.ts +2 -0
- package/package.json +8 -8
- package/scripts/capture-sticky-viewport-showcase.ts +131 -5
- package/scripts/verify-gjc-sdk-canonicalization.ts +128 -183
- package/scripts/verify-sticky-viewport-showcase.ts +620 -93
- package/src/config/model-profiles.ts +8 -0
- package/src/config/settings-schema.ts +17 -3
- package/src/cursor.ts +20 -13
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +5 -2
- package/src/eval/backend.ts +2 -2
- package/src/exec/bash-executor.ts +425 -151
- package/src/extensibility/extensions/runner.ts +80 -6
- package/src/extensibility/extensions/wrapper.ts +22 -15
- package/src/extensibility/runtime-skill-discovery.ts +4 -6
- package/src/gjc-runtime/launch-tmux.ts +309 -293
- package/src/gjc-runtime/managed-owner-supervisor.ts +6 -2
- package/src/gjc-runtime/psmux-detect.ts +52 -6
- package/src/gjc-runtime/team-launch.ts +50 -2
- package/src/gjc-runtime/team-runtime.ts +716 -251
- package/src/gjc-runtime/team-store.ts +25 -7
- package/src/gjc-runtime/team-workers.ts +161 -1
- package/src/gjc-runtime/tmux-common.ts +16 -4
- package/src/gjc-runtime/tmux-gc.ts +37 -5
- package/src/gjc-runtime/tmux-owner-isolation.ts +2 -0
- package/src/gjc-runtime/tmux-provider-context.ts +451 -0
- package/src/gjc-runtime/tmux-sessions.ts +409 -156
- package/src/gjc-runtime/ultragoal-change-set.ts +90 -44
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +7 -0
- package/src/gjc-runtime/ultragoal-review-source.ts +378 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +640 -159
- package/src/gjc-runtime/workflow-manifest.generated.json +40 -1
- package/src/gjc-runtime/workflow-manifest.ts +12 -0
- package/src/internal-urls/agent-protocol.ts +98 -38
- package/src/internal-urls/artifact-protocol.ts +28 -17
- package/src/internal-urls/docs-index.generated.ts +5 -5
- package/src/internal-urls/local-protocol.ts +39 -18
- package/src/internal-urls/registry-helpers.ts +62 -0
- package/src/modes/acp/acp-agent.ts +51 -13
- package/src/modes/acp/acp-client-bridge.ts +154 -11
- package/src/modes/components/gjc-bundle-settings.ts +2 -0
- package/src/modes/components/plugin-settings.ts +5 -0
- package/src/modes/components/settings-selector.ts +4 -0
- package/src/modes/controllers/selector-controller.ts +1 -0
- package/src/prompts/tools/bash.md +2 -2
- package/src/prompts/tools/monitor.md +4 -4
- package/src/sdk/acp/adapter.ts +200 -9
- package/src/sdk/broker/broker.ts +93 -10
- package/src/sdk/broker/lifecycle-ledger.ts +227 -11
- package/src/sdk/broker/lifecycle.ts +691 -92
- package/src/sdk/bus/chat-daemon-control.ts +32 -6
- package/src/sdk/bus/index.ts +347 -14
- package/src/sdk/bus/telegram-daemon-contract.ts +4 -2
- package/src/sdk/bus/telegram-daemon.ts +283 -44
- package/src/sdk/bus/topic-registry.ts +133 -10
- package/src/sdk/host/host.ts +187 -9
- package/src/sdk/host/reverse-leases.ts +249 -42
- package/src/sdk/session.ts +7 -6
- package/src/session/agent-session.ts +930 -354
- package/src/session/artifacts.ts +211 -74
- package/src/session/attempt-record-store.ts +106 -0
- package/src/session/client-bridge.ts +15 -0
- package/src/session/internal/managed-session-scope.ts +252 -67
- package/src/session/internal/managed-session-storage.ts +105 -5
- package/src/session/messages.ts +32 -7
- package/src/session/session-manager.ts +19 -21
- package/src/session/session-storage.ts +146 -24
- package/src/session/streaming-output.ts +198 -40
- package/src/task/index.ts +45 -0
- package/src/task/provider-retry-status.ts +4 -1
- package/src/task/receipt.ts +4 -0
- package/src/task/render.ts +30 -0
- package/src/task/types.ts +34 -0
- package/src/tools/bash.ts +818 -239
- package/src/tools/eval.ts +99 -4
- package/src/tools/fetch.ts +77 -15
- package/src/tools/find.ts +7 -3
- package/src/tools/monitor.ts +7 -1
- package/src/tools/output-meta.ts +706 -116
- package/src/tools/search.ts +9 -4
- package/src/tools/tool-result.ts +1 -0
- package/src/utils/artifact-id.ts +6 -0
|
@@ -2,12 +2,20 @@
|
|
|
2
2
|
* Extension runner - executes extensions and manages their lifecycle.
|
|
3
3
|
*/
|
|
4
4
|
import type { AgentMessage } from "@gajae-code/agent-core";
|
|
5
|
-
import type {
|
|
5
|
+
import type { AttemptScope } from "@gajae-code/agent-core/attempt-scope";
|
|
6
|
+
import type {
|
|
7
|
+
AttemptScopeRef,
|
|
8
|
+
CredentialDisabledEvent,
|
|
9
|
+
ImageContent,
|
|
10
|
+
Model,
|
|
11
|
+
ProviderResponseMetadata,
|
|
12
|
+
} from "@gajae-code/ai";
|
|
6
13
|
import type { KeyId } from "@gajae-code/tui";
|
|
7
14
|
import { logger } from "@gajae-code/utils";
|
|
8
15
|
import type { ModelRegistry } from "../../config/model-registry";
|
|
9
16
|
import type { WorkflowGateEmitter } from "../../modes/shared/agent-wire/workflow-gate-broker";
|
|
10
17
|
import { type Theme, theme } from "../../modes/theme/theme";
|
|
18
|
+
import type { AttemptRecordStore } from "../../session/attempt-record-store";
|
|
11
19
|
import { createReadonlySessionManager, type SessionManager } from "../../session/session-manager";
|
|
12
20
|
import type {
|
|
13
21
|
AfterProviderResponseEvent,
|
|
@@ -176,6 +184,7 @@ export class ExtensionRunner {
|
|
|
176
184
|
#uiContext: ExtensionUIContext;
|
|
177
185
|
#errorListeners: Set<ExtensionErrorListener> = new Set();
|
|
178
186
|
#handlersByEvent: Map<string, IndexedHandler[]> = new Map();
|
|
187
|
+
#attemptRecordStore: AttemptRecordStore | undefined;
|
|
179
188
|
|
|
180
189
|
#getModel: () => Model | undefined = () => undefined;
|
|
181
190
|
#isIdleFn: () => boolean = () => true;
|
|
@@ -504,6 +513,27 @@ export class ExtensionRunner {
|
|
|
504
513
|
return (this.#handlersByEvent.get(eventType)?.length ?? 0) > 0;
|
|
505
514
|
}
|
|
506
515
|
|
|
516
|
+
setAttemptRecordStore(store: AttemptRecordStore): void {
|
|
517
|
+
this.#attemptRecordStore = store;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
#markAttemptExecuted(scope: AttemptScopeRef | undefined): void {
|
|
521
|
+
if (scope !== undefined) this.#attemptRecordStore?.markExecuted(scope as AttemptScope);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Scope-presence guard. When the AttemptScope facility is active but a
|
|
526
|
+
* handler-capable delivery lacks a scope, the handler is still delivered
|
|
527
|
+
* (backward-compatible) but NO mark is recorded. The record stays
|
|
528
|
+
* unknown/missing → `isClean` returns false → admission refuses
|
|
529
|
+
* (fail-closed at the decision point, not at delivery).
|
|
530
|
+
*/
|
|
531
|
+
#requireScopeOrFailClosed(_scope: AttemptScopeRef | undefined, _eventLabel: string): void {
|
|
532
|
+
// No throw — handler is delivered (backward-compatible); mark is not
|
|
533
|
+
// recorded when scope is absent. isClean returns false for an
|
|
534
|
+
// unmarked scope → admission refuses (fail-closed at decision point).
|
|
535
|
+
}
|
|
536
|
+
|
|
507
537
|
getMessageRenderer(customType: string): MessageRenderer | undefined {
|
|
508
538
|
for (const ext of this.extensions) {
|
|
509
539
|
const renderer = ext.messageRenderers.get(customType);
|
|
@@ -704,15 +734,22 @@ export class ExtensionRunner {
|
|
|
704
734
|
async emit<TEvent extends RunnerEmitEvent>(
|
|
705
735
|
event: TEvent,
|
|
706
736
|
continueWhile?: () => boolean,
|
|
737
|
+
scope?: AttemptScopeRef,
|
|
707
738
|
): Promise<RunnerEmitResult<TEvent>> {
|
|
708
739
|
const handlers = this.#handlersByEvent.get(event.type) ?? [];
|
|
709
740
|
if (handlers.length === 0) return undefined as RunnerEmitResult<TEvent>;
|
|
741
|
+
this.#requireScopeOrFailClosed(scope, event.type);
|
|
710
742
|
|
|
711
743
|
const ctx = this.createContext();
|
|
712
744
|
let result: SessionBeforeEventResult | SessionCompactingResult | undefined;
|
|
745
|
+
let marked = false;
|
|
713
746
|
|
|
714
747
|
for (const { ext, handler } of handlers) {
|
|
715
748
|
if (continueWhile && !continueWhile()) return result as RunnerEmitResult<TEvent>;
|
|
749
|
+
if (!marked) {
|
|
750
|
+
this.#markAttemptExecuted(scope);
|
|
751
|
+
marked = true;
|
|
752
|
+
}
|
|
716
753
|
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
717
754
|
if (continueWhile && !continueWhile()) return result as RunnerEmitResult<TEvent>;
|
|
718
755
|
|
|
@@ -731,15 +768,21 @@ export class ExtensionRunner {
|
|
|
731
768
|
return result as RunnerEmitResult<TEvent>;
|
|
732
769
|
}
|
|
733
770
|
|
|
734
|
-
async emitToolResult(event: ToolResultEvent): Promise<ToolResultEventResult | undefined> {
|
|
771
|
+
async emitToolResult(event: ToolResultEvent, scope?: AttemptScopeRef): Promise<ToolResultEventResult | undefined> {
|
|
735
772
|
const handlers = this.#handlersByEvent.get("tool_result") ?? [];
|
|
736
773
|
if (handlers.length === 0) return undefined;
|
|
774
|
+
this.#requireScopeOrFailClosed(scope, "tool_result");
|
|
737
775
|
|
|
738
776
|
const ctx = this.createContext();
|
|
739
777
|
const currentEvent: ToolResultEvent = { ...event };
|
|
740
778
|
let modified = false;
|
|
779
|
+
let marked = false;
|
|
741
780
|
|
|
742
781
|
for (const { ext, handler } of handlers) {
|
|
782
|
+
if (!marked) {
|
|
783
|
+
this.#markAttemptExecuted(scope);
|
|
784
|
+
marked = true;
|
|
785
|
+
}
|
|
743
786
|
const handlerResult = (await this.#runHandlerWithTimeout(
|
|
744
787
|
handler,
|
|
745
788
|
currentEvent,
|
|
@@ -772,14 +815,20 @@ export class ExtensionRunner {
|
|
|
772
815
|
};
|
|
773
816
|
}
|
|
774
817
|
|
|
775
|
-
async emitToolCall(event: ToolCallEvent): Promise<ToolCallEventResult | undefined> {
|
|
818
|
+
async emitToolCall(event: ToolCallEvent, scope?: AttemptScopeRef): Promise<ToolCallEventResult | undefined> {
|
|
776
819
|
const handlers = this.#handlersByEvent.get("tool_call") ?? [];
|
|
777
820
|
if (handlers.length === 0) return undefined;
|
|
821
|
+
this.#requireScopeOrFailClosed(scope, "tool_call");
|
|
778
822
|
|
|
779
823
|
const ctx = this.createContext();
|
|
780
824
|
let result: ToolCallEventResult | undefined;
|
|
825
|
+
let marked = false;
|
|
781
826
|
|
|
782
827
|
for (const { ext, handler } of handlers) {
|
|
828
|
+
if (!marked) {
|
|
829
|
+
this.#markAttemptExecuted(scope);
|
|
830
|
+
marked = true;
|
|
831
|
+
}
|
|
783
832
|
try {
|
|
784
833
|
const handlerResult = await handler(event, ctx);
|
|
785
834
|
|
|
@@ -894,9 +943,10 @@ export class ExtensionRunner {
|
|
|
894
943
|
return currentText !== text || currentImages !== images ? { text: currentText, images: currentImages } : {};
|
|
895
944
|
}
|
|
896
945
|
|
|
897
|
-
async emitContext(messages: AgentMessage[]): Promise<AgentMessage[]> {
|
|
946
|
+
async emitContext(messages: AgentMessage[], scope?: AttemptScopeRef): Promise<AgentMessage[]> {
|
|
898
947
|
const handlers = this.#handlersByEvent.get("context") ?? [];
|
|
899
948
|
if (handlers.length === 0) return messages;
|
|
949
|
+
this.#requireScopeOrFailClosed(scope, "context");
|
|
900
950
|
|
|
901
951
|
const ctx = this.createContext();
|
|
902
952
|
let currentMessages: AgentMessage[];
|
|
@@ -908,8 +958,13 @@ export class ExtensionRunner {
|
|
|
908
958
|
// return new message arrays rather than mutating in place.
|
|
909
959
|
currentMessages = [...messages];
|
|
910
960
|
}
|
|
961
|
+
let marked = false;
|
|
911
962
|
|
|
912
963
|
for (const { ext, handler } of handlers) {
|
|
964
|
+
if (!marked) {
|
|
965
|
+
this.#markAttemptExecuted(scope);
|
|
966
|
+
marked = true;
|
|
967
|
+
}
|
|
913
968
|
const event: ContextEvent = { type: "context", messages: currentMessages };
|
|
914
969
|
const handlerResult = await this.#runHandlerWithTimeout(handler, event, ctx, ext, extensionHandlerTimeoutMs);
|
|
915
970
|
|
|
@@ -921,14 +976,23 @@ export class ExtensionRunner {
|
|
|
921
976
|
return currentMessages;
|
|
922
977
|
}
|
|
923
978
|
|
|
924
|
-
async emitBeforeProviderRequest(
|
|
979
|
+
async emitBeforeProviderRequest(
|
|
980
|
+
payload: unknown,
|
|
981
|
+
scope?: AttemptScopeRef,
|
|
982
|
+
): Promise<BeforeProviderRequestEventResult> {
|
|
925
983
|
const handlers = this.#handlersByEvent.get("before_provider_request") ?? [];
|
|
926
984
|
if (handlers.length === 0) return payload;
|
|
985
|
+
this.#requireScopeOrFailClosed(scope, "before_provider_request");
|
|
927
986
|
|
|
928
987
|
const ctx = this.createContext();
|
|
929
988
|
let currentPayload = payload;
|
|
989
|
+
let marked = false;
|
|
930
990
|
|
|
931
991
|
for (const { ext, handler } of handlers) {
|
|
992
|
+
if (!marked) {
|
|
993
|
+
this.#markAttemptExecuted(scope);
|
|
994
|
+
marked = true;
|
|
995
|
+
}
|
|
932
996
|
const event: BeforeProviderRequestEvent = {
|
|
933
997
|
type: "before_provider_request",
|
|
934
998
|
payload: currentPayload,
|
|
@@ -942,13 +1006,23 @@ export class ExtensionRunner {
|
|
|
942
1006
|
return currentPayload;
|
|
943
1007
|
}
|
|
944
1008
|
|
|
945
|
-
async emitAfterProviderResponse(
|
|
1009
|
+
async emitAfterProviderResponse(
|
|
1010
|
+
response: ProviderResponseMetadata,
|
|
1011
|
+
_model?: Model,
|
|
1012
|
+
scope?: AttemptScopeRef,
|
|
1013
|
+
): Promise<void> {
|
|
946
1014
|
const handlers = this.#handlersByEvent.get("after_provider_response") ?? [];
|
|
947
1015
|
if (handlers.length === 0) return;
|
|
1016
|
+
this.#requireScopeOrFailClosed(scope, "after_provider_response");
|
|
948
1017
|
|
|
949
1018
|
const ctx = this.createContext();
|
|
1019
|
+
let marked = false;
|
|
950
1020
|
|
|
951
1021
|
for (const { ext, handler } of handlers) {
|
|
1022
|
+
if (!marked) {
|
|
1023
|
+
this.#markAttemptExecuted(scope);
|
|
1024
|
+
marked = true;
|
|
1025
|
+
}
|
|
952
1026
|
const event: AfterProviderResponseEvent = {
|
|
953
1027
|
type: "after_provider_response",
|
|
954
1028
|
status: response.status,
|
|
@@ -109,15 +109,19 @@ export class ExtensionToolWrapper<TParameters extends TSchema = TSchema, TDetail
|
|
|
109
109
|
onUpdate?: AgentToolUpdateCallback<TDetails, TParameters>,
|
|
110
110
|
context?: AgentToolContext,
|
|
111
111
|
) {
|
|
112
|
+
const scope = context?.attemptScope;
|
|
112
113
|
// Emit tool_call event - extensions can block execution
|
|
113
114
|
if (this.runner.hasHandlers("tool_call")) {
|
|
114
115
|
try {
|
|
115
|
-
const callResult = (await this.runner.emitToolCall(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
const callResult = (await this.runner.emitToolCall(
|
|
117
|
+
{
|
|
118
|
+
type: "tool_call",
|
|
119
|
+
toolName: this.tool.name,
|
|
120
|
+
toolCallId,
|
|
121
|
+
input: params as Record<string, unknown>,
|
|
122
|
+
},
|
|
123
|
+
scope,
|
|
124
|
+
)) as ToolCallEventResult | undefined;
|
|
121
125
|
|
|
122
126
|
if (callResult?.block) {
|
|
123
127
|
const reason = callResult.reason || "Tool execution was blocked by an extension";
|
|
@@ -147,15 +151,18 @@ export class ExtensionToolWrapper<TParameters extends TSchema = TSchema, TDetail
|
|
|
147
151
|
|
|
148
152
|
// Emit tool_result event - extensions can modify the result and error status
|
|
149
153
|
if (this.runner.hasHandlers("tool_result")) {
|
|
150
|
-
const resultResult = await this.runner.emitToolResult(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
const resultResult = await this.runner.emitToolResult(
|
|
155
|
+
{
|
|
156
|
+
type: "tool_result",
|
|
157
|
+
toolName: this.tool.name,
|
|
158
|
+
toolCallId,
|
|
159
|
+
input: params as Record<string, unknown>,
|
|
160
|
+
content: result.content,
|
|
161
|
+
details: result.details,
|
|
162
|
+
isError: !!executionError,
|
|
163
|
+
},
|
|
164
|
+
scope,
|
|
165
|
+
);
|
|
159
166
|
|
|
160
167
|
if (resultResult) {
|
|
161
168
|
const modifiedContent: (TextContent | ImageContent)[] = resultResult.content ?? result.content;
|
|
@@ -132,15 +132,13 @@ function isAllowedByPolicy(
|
|
|
132
132
|
return true;
|
|
133
133
|
}
|
|
134
134
|
function matchesQuery(candidate: RuntimeSkillDiscoveryCandidate, query: string): boolean {
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
135
|
+
const terms = query.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
136
|
+
if (terms.length === 0) return true;
|
|
137
|
+
if (terms.includes(candidate.name.toLowerCase())) return true;
|
|
137
138
|
const haystack = [candidate.name, candidate.description, candidate.source, ...(candidate.useWhen ?? [])]
|
|
138
139
|
.join("\n")
|
|
139
140
|
.toLowerCase();
|
|
140
|
-
return
|
|
141
|
-
.split(/\s+/)
|
|
142
|
-
.filter(Boolean)
|
|
143
|
-
.every(term => haystack.includes(term));
|
|
141
|
+
return terms.every(term => haystack.includes(term));
|
|
144
142
|
}
|
|
145
143
|
|
|
146
144
|
async function realPathOrSelf(filePath: string): Promise<string> {
|