@gajae-code/coding-agent 0.4.2 → 0.4.3
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 +11 -0
- package/dist/types/async/job-manager.d.ts +25 -0
- package/dist/types/commit/model-selection.d.ts +1 -1
- package/dist/types/config/model-registry.d.ts +3 -1
- package/dist/types/config/model-resolver.d.ts +1 -19
- package/dist/types/config/models-config-schema.d.ts +12 -0
- package/dist/types/config/settings-schema.d.ts +15 -1
- package/dist/types/gjc-runtime/goal-mode-request.d.ts +8 -1
- package/dist/types/harness-control-plane/types.d.ts +7 -2
- package/dist/types/modes/acp/acp-event-mapper.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +7 -0
- package/dist/types/modes/shared/agent-wire/command-contract.d.ts +18 -0
- package/dist/types/modes/shared/agent-wire/event-contract.d.ts +84 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +14 -7
- package/dist/types/modes/shared/agent-wire/event-observation.d.ts +37 -0
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +13 -34
- package/dist/types/session/agent-session.d.ts +12 -1
- package/dist/types/session/session-manager.d.ts +1 -1
- package/dist/types/tools/bash.d.ts +2 -0
- package/dist/types/tools/browser/actions.d.ts +54 -0
- package/dist/types/tools/browser.d.ts +80 -0
- package/dist/types/tools/image-gen.d.ts +1 -0
- package/dist/types/tools/index.d.ts +3 -1
- package/dist/types/tools/job.d.ts +1 -1
- package/package.json +7 -7
- package/src/async/job-manager.ts +120 -1
- package/src/commands/ultragoal.ts +7 -1
- package/src/commit/agentic/index.ts +2 -2
- package/src/commit/model-selection.ts +7 -22
- package/src/commit/pipeline.ts +2 -2
- package/src/config/model-registry.ts +17 -9
- package/src/config/model-resolver.ts +14 -84
- package/src/config/models-config-schema.ts +2 -0
- package/src/config/settings-schema.ts +14 -1
- package/src/gjc-runtime/goal-mode-request.ts +21 -1
- package/src/harness-control-plane/owner.ts +3 -3
- package/src/harness-control-plane/rpc-adapter.ts +7 -1
- package/src/harness-control-plane/types.ts +8 -11
- package/src/internal-urls/docs-index.generated.ts +3 -3
- package/src/memories/index.ts +1 -1
- package/src/modes/acp/acp-agent.ts +17 -9
- package/src/modes/acp/acp-event-mapper.ts +33 -1
- package/src/modes/components/custom-editor.ts +19 -3
- package/src/modes/controllers/input-controller.ts +27 -7
- package/src/modes/controllers/selector-controller.ts +7 -1
- package/src/modes/interactive-mode.ts +3 -1
- package/src/modes/rpc/rpc-client.ts +16 -3
- package/src/modes/rpc/rpc-mode.ts +5 -2
- package/src/modes/shared/agent-wire/command-contract.ts +18 -0
- package/src/modes/shared/agent-wire/event-contract.ts +147 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +35 -16
- package/src/modes/shared/agent-wire/event-observation.ts +397 -0
- package/src/modes/shared/agent-wire/protocol.ts +24 -81
- package/src/modes/utils/context-usage.ts +2 -2
- package/src/prompts/agents/explore.md +1 -1
- package/src/prompts/agents/plan.md +1 -1
- package/src/prompts/agents/reviewer.md +1 -1
- package/src/prompts/tools/browser.md +3 -2
- package/src/runtime-mcp/manager.ts +15 -2
- package/src/sdk.ts +3 -1
- package/src/session/agent-session.ts +60 -4
- package/src/session/session-manager.ts +1 -1
- package/src/task/agents.ts +1 -1
- package/src/tools/bash.ts +6 -1
- package/src/tools/browser/actions.ts +189 -0
- package/src/tools/browser.ts +91 -1
- package/src/tools/image-gen.ts +42 -15
- package/src/tools/index.ts +7 -1
- package/src/tools/inspect-image.ts +10 -8
- package/src/tools/job.ts +12 -2
- package/src/tools/monitor.ts +98 -17
- package/src/utils/commit-message-generator.ts +6 -13
- package/src/utils/title-generator.ts +1 -1
- package/dist/types/harness-control-plane/frame-mapper.d.ts +0 -29
- package/src/harness-control-plane/frame-mapper.ts +0 -286
- package/src/priority.json +0 -37
package/src/tools/monitor.ts
CHANGED
|
@@ -47,6 +47,7 @@ export interface MonitorToolDetails {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
const MONITOR_LABEL_MAX = 120;
|
|
50
|
+
const MAX_PENDING_MONITOR_NOTIFICATIONS = 3;
|
|
50
51
|
|
|
51
52
|
function buildMonitorLabel(params: MonitorParams): string {
|
|
52
53
|
const base = `[monitor:${params.kind}] ${params.description}`;
|
|
@@ -89,36 +90,116 @@ export class MonitorTool implements AgentTool<typeof monitorSchema, MonitorToolD
|
|
|
89
90
|
const ownerId = this.session.getAgentId?.() ?? undefined;
|
|
90
91
|
const bash = new BashTool(this.session);
|
|
91
92
|
let deliveredFirstLine = false;
|
|
93
|
+
const controller = { closed: false };
|
|
94
|
+
let currentJobId = "";
|
|
95
|
+
let sequence = 0;
|
|
96
|
+
let latestLine: string | undefined;
|
|
97
|
+
let coalescedCount = 0;
|
|
98
|
+
let flushScheduled = false;
|
|
99
|
+
// Count of notification *sends* (not live queue depth): once it exceeds the
|
|
100
|
+
// cap, each new send first purges older queued notifications for this task,
|
|
101
|
+
// keeping the queue bounded and latest-biased.
|
|
102
|
+
let pendingNotifications = 0;
|
|
103
|
+
const isMonitorMessage = (message: { customType?: string; details?: unknown }) =>
|
|
104
|
+
message.customType === "task-notification" &&
|
|
105
|
+
(message.details as { taskId?: string } | undefined)?.taskId === currentJobId;
|
|
106
|
+
const flushLatest = () => {
|
|
107
|
+
if (!persistent || latestLine === undefined) return;
|
|
108
|
+
const line = latestLine;
|
|
109
|
+
const count = coalescedCount;
|
|
110
|
+
latestLine = undefined;
|
|
111
|
+
coalescedCount = 0;
|
|
112
|
+
flushScheduled = false;
|
|
113
|
+
sendNotification(line, currentJobId, count);
|
|
114
|
+
};
|
|
115
|
+
const closeMonitor = (mode: "purge" | "flush") => {
|
|
116
|
+
// "flush" (natural process exit): deliver the newest pending line so the
|
|
117
|
+
// final state is never lost, then stop. "purge" (explicit cancel / registry
|
|
118
|
+
// eviction): drop the queued backlog. Non-persistent monitors keep their one
|
|
119
|
+
// notification, so they never purge.
|
|
120
|
+
if (mode === "flush") {
|
|
121
|
+
flushLatest();
|
|
122
|
+
controller.closed = true;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
controller.closed = true;
|
|
126
|
+
if (!persistent) return;
|
|
127
|
+
return this.session.purgeQueuedCustomMessages?.(isMonitorMessage);
|
|
128
|
+
};
|
|
129
|
+
const sendNotification = (line: string, jobId: string, count: number) => {
|
|
130
|
+
if (controller.closed) return;
|
|
131
|
+
const notificationId = `${jobId}:${sequence}`;
|
|
132
|
+
const suffix = count > 0 ? `\n(+${count} earlier lines)` : "";
|
|
133
|
+
const content = `<task-notification>\nMonitor task ${jobId} (${params.kind}: ${params.description}) emitted latest state:\n${line}${suffix}\n</task-notification>`;
|
|
134
|
+
const details = {
|
|
135
|
+
taskId: jobId,
|
|
136
|
+
kind: params.kind,
|
|
137
|
+
description: params.description,
|
|
138
|
+
monitor: true,
|
|
139
|
+
notificationId,
|
|
140
|
+
sequence,
|
|
141
|
+
coalescedCount: count,
|
|
142
|
+
};
|
|
143
|
+
pendingNotifications += 1;
|
|
144
|
+
if (pendingNotifications > MAX_PENDING_MONITOR_NOTIFICATIONS) {
|
|
145
|
+
this.session.purgeQueuedCustomMessages?.(
|
|
146
|
+
m =>
|
|
147
|
+
m.customType === "task-notification" &&
|
|
148
|
+
(m.details as { taskId?: string; notificationId?: string } | undefined)?.taskId === jobId &&
|
|
149
|
+
(m.details as { notificationId?: string } | undefined)?.notificationId !== notificationId,
|
|
150
|
+
);
|
|
151
|
+
pendingNotifications = MAX_PENDING_MONITOR_NOTIFICATIONS;
|
|
152
|
+
}
|
|
153
|
+
const sendPromise = this.session.sendCustomMessage?.(
|
|
154
|
+
{ customType: "task-notification", content, display: false, attribution: "agent", details },
|
|
155
|
+
{ triggerTurn: true, deliverAs: "followUp" },
|
|
156
|
+
);
|
|
157
|
+
if (sendPromise) {
|
|
158
|
+
void sendPromise.catch(error => {
|
|
159
|
+
logger.warn("Monitor task-notification delivery failed", {
|
|
160
|
+
error: error instanceof Error ? error.message : String(error),
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
this.session.steer?.({ customType: "task-notification", content, details });
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const schedulePersistentNotification = (line: string) => {
|
|
168
|
+
latestLine = line;
|
|
169
|
+
sequence += 1;
|
|
170
|
+
coalescedCount += flushScheduled ? 1 : 0;
|
|
171
|
+
if (flushScheduled) return;
|
|
172
|
+
flushScheduled = true;
|
|
173
|
+
queueMicrotask(flushLatest);
|
|
174
|
+
};
|
|
92
175
|
const monitorJob = await bash.startMonitorJob(
|
|
93
176
|
{ command: params.command, timeout: params.timeout },
|
|
94
177
|
{
|
|
95
178
|
ownerId,
|
|
96
179
|
label,
|
|
97
180
|
ctx: context,
|
|
181
|
+
shouldAcceptRawLine: () => !controller.closed,
|
|
182
|
+
lifecycle: {
|
|
183
|
+
onCancel: () => closeMonitor("purge"),
|
|
184
|
+
onTerminal: () => closeMonitor("flush"),
|
|
185
|
+
onEvict: () => closeMonitor("purge"),
|
|
186
|
+
onTombstonePurge: () => closeMonitor("purge"),
|
|
187
|
+
},
|
|
98
188
|
onRawLine: (line, jobId) => {
|
|
189
|
+
if (controller.closed) return;
|
|
190
|
+
currentJobId = jobId;
|
|
99
191
|
if (!persistent && deliveredFirstLine) return;
|
|
100
192
|
deliveredFirstLine = true;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
{ customType: "task-notification", content, display: false, attribution: "agent", details },
|
|
105
|
-
{ triggerTurn: true, deliverAs: "followUp" },
|
|
106
|
-
);
|
|
107
|
-
if (sendPromise) {
|
|
108
|
-
void sendPromise.catch(error => {
|
|
109
|
-
logger.warn("Monitor task-notification delivery failed", {
|
|
110
|
-
error: error instanceof Error ? error.message : String(error),
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
} else {
|
|
114
|
-
this.session.steer?.({ customType: "task-notification", content, details });
|
|
115
|
-
}
|
|
116
|
-
if (!persistent) {
|
|
117
|
-
manager.cancel(jobId, ownerId ? { ownerId } : undefined);
|
|
193
|
+
if (persistent) {
|
|
194
|
+
schedulePersistentNotification(line);
|
|
195
|
+
return;
|
|
118
196
|
}
|
|
197
|
+
sendNotification(line, jobId, 0);
|
|
198
|
+
manager.cancel(jobId, ownerId ? { ownerId } : undefined);
|
|
119
199
|
},
|
|
120
200
|
},
|
|
121
201
|
);
|
|
202
|
+
currentJobId = monitorJob.jobId;
|
|
122
203
|
|
|
123
204
|
const startedText = `Monitor started · task ${monitorJob.jobId} · persistent: ${persistent}`;
|
|
124
205
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generate commit messages from diffs using
|
|
2
|
+
* Generate commit messages from diffs using the default model.
|
|
3
3
|
* Follows the same pattern as title-generator.ts.
|
|
4
4
|
*/
|
|
5
5
|
import type { ThinkingLevel } from "@gajae-code/agent-core";
|
|
@@ -9,7 +9,6 @@ import { logger, prompt } from "@gajae-code/utils";
|
|
|
9
9
|
import type { ModelRegistry } from "../config/model-registry";
|
|
10
10
|
import { resolveModelRoleValue } from "../config/model-resolver";
|
|
11
11
|
import type { Settings } from "../config/settings";
|
|
12
|
-
import MODEL_PRIO from "../priority.json" with { type: "json" };
|
|
13
12
|
import commitSystemPrompt from "../prompts/system/commit-message-system.md" with { type: "text" };
|
|
14
13
|
import { toReasoningEffort } from "../thinking";
|
|
15
14
|
|
|
@@ -36,7 +35,7 @@ function filterDiffNoise(diff: string): string {
|
|
|
36
35
|
return filtered.join("\n");
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
function
|
|
38
|
+
function getModelCandidates(
|
|
40
39
|
registry: ModelRegistry,
|
|
41
40
|
settings: Settings,
|
|
42
41
|
): Array<{ model: Model<Api>; thinkingLevel?: ThinkingLevel }> {
|
|
@@ -51,18 +50,12 @@ function getSmolModelCandidates(
|
|
|
51
50
|
};
|
|
52
51
|
|
|
53
52
|
const matchPreferences = { usageOrder: settings.getStorage()?.getModelUsageOrder() };
|
|
54
|
-
const
|
|
53
|
+
const configured = resolveModelRoleValue(settings.getModelRole("default"), availableModels, {
|
|
55
54
|
settings,
|
|
56
55
|
matchPreferences,
|
|
57
56
|
modelRegistry: registry,
|
|
58
57
|
});
|
|
59
|
-
addCandidate(
|
|
60
|
-
|
|
61
|
-
for (const pattern of MODEL_PRIO.smol) {
|
|
62
|
-
const needle = pattern.toLowerCase();
|
|
63
|
-
addCandidate(availableModels.find(m => m.id.toLowerCase() === needle));
|
|
64
|
-
addCandidate(availableModels.find(m => m.id.toLowerCase().includes(needle)));
|
|
65
|
-
}
|
|
58
|
+
addCandidate(configured.model, configured.thinkingLevel);
|
|
66
59
|
|
|
67
60
|
for (const model of availableModels) {
|
|
68
61
|
addCandidate(model);
|
|
@@ -81,9 +74,9 @@ export async function generateCommitMessage(
|
|
|
81
74
|
settings: Settings,
|
|
82
75
|
sessionId?: string,
|
|
83
76
|
): Promise<string | null> {
|
|
84
|
-
const candidates =
|
|
77
|
+
const candidates = getModelCandidates(registry, settings);
|
|
85
78
|
if (candidates.length === 0) {
|
|
86
|
-
logger.debug("commit-msg-generator: no
|
|
79
|
+
logger.debug("commit-msg-generator: no model found");
|
|
87
80
|
return null;
|
|
88
81
|
}
|
|
89
82
|
|
|
@@ -40,7 +40,7 @@ function getTitleModel(registry: ModelRegistry, settings: Settings, currentModel
|
|
|
40
40
|
const availableModels = registry.getAvailable();
|
|
41
41
|
if (availableModels.length === 0) return undefined;
|
|
42
42
|
|
|
43
|
-
const titleModel = resolveRoleSelection(["
|
|
43
|
+
const titleModel = resolveRoleSelection(["default"], settings, availableModels, registry)?.model;
|
|
44
44
|
if (titleModel) return titleModel;
|
|
45
45
|
|
|
46
46
|
if (currentModel) return currentModel;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure mapping from `gjc --mode rpc` event frames (docs/rpc.md) to bounded owner event kinds
|
|
3
|
-
* and {@link ObservedSignal}s. The owner feeds raw frames through this mapper and emits the
|
|
4
|
-
* result via its single-writer #emit — the mapper itself performs NO IO and NO appends.
|
|
5
|
-
*
|
|
6
|
-
* Hard rule: evidence is BOUNDED — only ids, names, categories, statuses, cursors, timestamps,
|
|
7
|
-
* and short codes/messages. Never assistant text, message deltas, command output, or raw args.
|
|
8
|
-
*/
|
|
9
|
-
import type { ObservedSignal } from "./types";
|
|
10
|
-
export interface MappedFrame {
|
|
11
|
-
/** Owner event kind (rpc_*). */
|
|
12
|
-
kind: string;
|
|
13
|
-
/** Bounded observed signal, or null when the frame carries no user-facing signal. */
|
|
14
|
-
signal: ObservedSignal | null;
|
|
15
|
-
/** Bounded evidence — ids/names/statuses/cursors/timestamps/short codes only. */
|
|
16
|
-
evidence: Record<string, unknown>;
|
|
17
|
-
/** Severity for the emitted event. */
|
|
18
|
-
severity: "info" | "warn" | "critical";
|
|
19
|
-
/** Never-drop frames (must be enqueued in order, never coalesced away). */
|
|
20
|
-
semantic: boolean;
|
|
21
|
-
/** Coalescing key for high-frequency non-semantic frames (message id / tool id); null otherwise. */
|
|
22
|
-
coalesceKey: string | null;
|
|
23
|
-
}
|
|
24
|
-
export declare function isTestRunnerTool(toolName?: unknown, command?: unknown): boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Map a single RPC frame. Returns null for frames that carry no observability value
|
|
27
|
-
* (or that the adapter handles itself: `ready`, `response`).
|
|
28
|
-
*/
|
|
29
|
-
export declare function mapRpcFrame(frame: Record<string, unknown>): MappedFrame | null;
|
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure mapping from `gjc --mode rpc` event frames (docs/rpc.md) to bounded owner event kinds
|
|
3
|
-
* and {@link ObservedSignal}s. The owner feeds raw frames through this mapper and emits the
|
|
4
|
-
* result via its single-writer #emit — the mapper itself performs NO IO and NO appends.
|
|
5
|
-
*
|
|
6
|
-
* Hard rule: evidence is BOUNDED — only ids, names, categories, statuses, cursors, timestamps,
|
|
7
|
-
* and short codes/messages. Never assistant text, message deltas, command output, or raw args.
|
|
8
|
-
*/
|
|
9
|
-
import type { ObservedSignal } from "./types";
|
|
10
|
-
|
|
11
|
-
export interface MappedFrame {
|
|
12
|
-
/** Owner event kind (rpc_*). */
|
|
13
|
-
kind: string;
|
|
14
|
-
/** Bounded observed signal, or null when the frame carries no user-facing signal. */
|
|
15
|
-
signal: ObservedSignal | null;
|
|
16
|
-
/** Bounded evidence — ids/names/statuses/cursors/timestamps/short codes only. */
|
|
17
|
-
evidence: Record<string, unknown>;
|
|
18
|
-
/** Severity for the emitted event. */
|
|
19
|
-
severity: "info" | "warn" | "critical";
|
|
20
|
-
/** Never-drop frames (must be enqueued in order, never coalesced away). */
|
|
21
|
-
semantic: boolean;
|
|
22
|
-
/** Coalescing key for high-frequency non-semantic frames (message id / tool id); null otherwise. */
|
|
23
|
-
coalesceKey: string | null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const TEST_RE = /\b(bun test|npm test|yarn test|pnpm test|jest|vitest|pytest|go test|cargo test|mocha|ava)\b/i;
|
|
27
|
-
const TOOL_STATUS_CODES = new Set([
|
|
28
|
-
"aborted",
|
|
29
|
-
"blocked",
|
|
30
|
-
"cancelled",
|
|
31
|
-
"complete",
|
|
32
|
-
"completed",
|
|
33
|
-
"error",
|
|
34
|
-
"failed",
|
|
35
|
-
"ok",
|
|
36
|
-
"pending",
|
|
37
|
-
"running",
|
|
38
|
-
"skipped",
|
|
39
|
-
"success",
|
|
40
|
-
"timeout",
|
|
41
|
-
]);
|
|
42
|
-
|
|
43
|
-
export function isTestRunnerTool(toolName?: unknown, command?: unknown): boolean {
|
|
44
|
-
const name = typeof toolName === "string" ? toolName : "";
|
|
45
|
-
const cmd = typeof command === "string" ? command : "";
|
|
46
|
-
if (/test/i.test(name) && name !== "edit" && name !== "read") return true;
|
|
47
|
-
return TEST_RE.test(cmd);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function str(v: unknown): string | undefined {
|
|
51
|
-
return typeof v === "string" ? v : undefined;
|
|
52
|
-
}
|
|
53
|
-
function num(v: unknown): number | undefined {
|
|
54
|
-
return typeof v === "number" ? v : undefined;
|
|
55
|
-
}
|
|
56
|
-
function boundedMessage(v: unknown): string | undefined {
|
|
57
|
-
const s = typeof v === "string" ? v : undefined;
|
|
58
|
-
return s === undefined ? undefined : s.slice(0, 200);
|
|
59
|
-
}
|
|
60
|
-
function boundedStatus(v: unknown): string | undefined {
|
|
61
|
-
if (typeof v !== "string") return undefined;
|
|
62
|
-
const status = v.trim().toLowerCase();
|
|
63
|
-
return TOOL_STATUS_CODES.has(status) ? status : undefined;
|
|
64
|
-
}
|
|
65
|
-
function recordObject(v: unknown): Record<string, unknown> | undefined {
|
|
66
|
-
return v && typeof v === "object" && !Array.isArray(v) ? (v as Record<string, unknown>) : undefined;
|
|
67
|
-
}
|
|
68
|
-
/** Extract a tool command from real AgentSessionEvent `args` or a flat fixture frame. Bounded use only — never persisted. */
|
|
69
|
-
function toolCommand(frame: Record<string, unknown>): string | undefined {
|
|
70
|
-
const args = recordObject(frame.args);
|
|
71
|
-
const c = args?.command ?? args?.cmd ?? args?.commandLine;
|
|
72
|
-
if (typeof c === "string") return c;
|
|
73
|
-
return str(frame.command) ?? str(frame.commandLine);
|
|
74
|
-
}
|
|
75
|
-
/** Derive a tool status, honoring real `isError` booleans as well as bounded status strings. */
|
|
76
|
-
function toolStatus(frame: Record<string, unknown>): string | undefined {
|
|
77
|
-
if (frame.isError === true) return "error";
|
|
78
|
-
const flatStatus = boundedStatus(frame.status);
|
|
79
|
-
if (flatStatus) return flatStatus;
|
|
80
|
-
for (const candidate of [frame.result, frame.partialResult]) {
|
|
81
|
-
const result = recordObject(candidate);
|
|
82
|
-
if (!result) continue;
|
|
83
|
-
if (result.isError === true) return "error";
|
|
84
|
-
const status = boundedStatus(result.status) ?? boundedStatus(recordObject(result.details)?.status);
|
|
85
|
-
if (status) return status;
|
|
86
|
-
}
|
|
87
|
-
return undefined;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Map a single RPC frame. Returns null for frames that carry no observability value
|
|
92
|
-
* (or that the adapter handles itself: `ready`, `response`).
|
|
93
|
-
*/
|
|
94
|
-
export function mapRpcFrame(frame: Record<string, unknown>): MappedFrame | null {
|
|
95
|
-
const type = str(frame.type);
|
|
96
|
-
if (!type || type === "ready" || type === "response") return null;
|
|
97
|
-
|
|
98
|
-
switch (type) {
|
|
99
|
-
case "agent_start":
|
|
100
|
-
return {
|
|
101
|
-
kind: "rpc_agent_started",
|
|
102
|
-
signal: "SessionStart",
|
|
103
|
-
evidence: {},
|
|
104
|
-
severity: "info",
|
|
105
|
-
semantic: true,
|
|
106
|
-
coalesceKey: null,
|
|
107
|
-
};
|
|
108
|
-
case "turn_start":
|
|
109
|
-
return {
|
|
110
|
-
kind: "rpc_turn_started",
|
|
111
|
-
signal: "prompt-accepted",
|
|
112
|
-
evidence: {},
|
|
113
|
-
severity: "info",
|
|
114
|
-
semantic: true,
|
|
115
|
-
coalesceKey: null,
|
|
116
|
-
};
|
|
117
|
-
case "turn_end":
|
|
118
|
-
return {
|
|
119
|
-
kind: "rpc_turn_ended",
|
|
120
|
-
signal: null,
|
|
121
|
-
evidence: {},
|
|
122
|
-
severity: "info",
|
|
123
|
-
semantic: false,
|
|
124
|
-
coalesceKey: null,
|
|
125
|
-
};
|
|
126
|
-
case "message_start":
|
|
127
|
-
case "message_update":
|
|
128
|
-
case "message_end":
|
|
129
|
-
return {
|
|
130
|
-
kind: "rpc_message_activity",
|
|
131
|
-
signal: null,
|
|
132
|
-
evidence: { phase: type, messageId: str(frame.messageId) ?? null },
|
|
133
|
-
severity: "info",
|
|
134
|
-
semantic: false,
|
|
135
|
-
coalesceKey: `message:${str(frame.messageId) ?? "msg"}`,
|
|
136
|
-
};
|
|
137
|
-
case "tool_execution_start": {
|
|
138
|
-
const toolName = str(frame.toolName);
|
|
139
|
-
const test = isTestRunnerTool(toolName, toolCommand(frame));
|
|
140
|
-
return {
|
|
141
|
-
kind: "rpc_tool_started",
|
|
142
|
-
signal: test ? "test-running" : "tool-call",
|
|
143
|
-
evidence: { toolId: str(frame.toolCallId) ?? null, toolName: toolName ?? null },
|
|
144
|
-
severity: "info",
|
|
145
|
-
semantic: true,
|
|
146
|
-
coalesceKey: null,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
case "tool_execution_update": {
|
|
150
|
-
const toolName = str(frame.toolName);
|
|
151
|
-
const test = isTestRunnerTool(toolName, toolCommand(frame));
|
|
152
|
-
return {
|
|
153
|
-
kind: "rpc_tool_updated",
|
|
154
|
-
signal: test ? "test-running" : null,
|
|
155
|
-
evidence: { toolId: str(frame.toolCallId) ?? null, status: toolStatus(frame) ?? null },
|
|
156
|
-
severity: "info",
|
|
157
|
-
semantic: false,
|
|
158
|
-
coalesceKey: `tool:${str(frame.toolCallId) ?? "tool"}`,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
case "tool_execution_end": {
|
|
162
|
-
const toolName = str(frame.toolName);
|
|
163
|
-
const test = isTestRunnerTool(toolName, toolCommand(frame));
|
|
164
|
-
const status = toolStatus(frame);
|
|
165
|
-
return {
|
|
166
|
-
kind: "rpc_tool_ended",
|
|
167
|
-
signal: test ? "test-running" : "tool-call",
|
|
168
|
-
evidence: {
|
|
169
|
-
toolId: str(frame.toolCallId) ?? null,
|
|
170
|
-
toolName: toolName ?? null,
|
|
171
|
-
status: status ?? null,
|
|
172
|
-
exitCode: num(frame.exitCode) ?? null,
|
|
173
|
-
},
|
|
174
|
-
severity: status === "error" ? "warn" : "info",
|
|
175
|
-
semantic: true,
|
|
176
|
-
coalesceKey: null,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
case "host_tool_call":
|
|
180
|
-
case "host_tool_cancel":
|
|
181
|
-
return {
|
|
182
|
-
kind: "rpc_host_tool",
|
|
183
|
-
signal: "tool-call",
|
|
184
|
-
evidence: { toolName: str(frame.toolName) ?? null },
|
|
185
|
-
severity: "info",
|
|
186
|
-
semantic: false,
|
|
187
|
-
coalesceKey: null,
|
|
188
|
-
};
|
|
189
|
-
case "host_uri_request":
|
|
190
|
-
case "host_uri_cancel":
|
|
191
|
-
return {
|
|
192
|
-
kind: "rpc_host_uri",
|
|
193
|
-
signal: "tool-call",
|
|
194
|
-
evidence: { operation: str(frame.operation) ?? null },
|
|
195
|
-
severity: "info",
|
|
196
|
-
semantic: false,
|
|
197
|
-
coalesceKey: null,
|
|
198
|
-
};
|
|
199
|
-
case "auto_compaction_start":
|
|
200
|
-
case "auto_compaction_end":
|
|
201
|
-
return {
|
|
202
|
-
kind: "rpc_compaction",
|
|
203
|
-
signal: null,
|
|
204
|
-
evidence: { phase: type },
|
|
205
|
-
severity: "info",
|
|
206
|
-
semantic: false,
|
|
207
|
-
coalesceKey: null,
|
|
208
|
-
};
|
|
209
|
-
case "auto_retry_start":
|
|
210
|
-
case "auto_retry_end":
|
|
211
|
-
return {
|
|
212
|
-
kind: "rpc_retry",
|
|
213
|
-
signal: null,
|
|
214
|
-
evidence: { phase: type, reason: boundedMessage(frame.reason) ?? null },
|
|
215
|
-
severity: "warn",
|
|
216
|
-
semantic: false,
|
|
217
|
-
coalesceKey: null,
|
|
218
|
-
};
|
|
219
|
-
case "ttsr_triggered":
|
|
220
|
-
return {
|
|
221
|
-
kind: "rpc_ttsr",
|
|
222
|
-
signal: "error",
|
|
223
|
-
evidence: { reason: boundedMessage(frame.reason) ?? null },
|
|
224
|
-
severity: "warn",
|
|
225
|
-
semantic: true,
|
|
226
|
-
coalesceKey: null,
|
|
227
|
-
};
|
|
228
|
-
case "todo_reminder":
|
|
229
|
-
case "todo_auto_clear":
|
|
230
|
-
return {
|
|
231
|
-
kind: "rpc_todo",
|
|
232
|
-
signal: null,
|
|
233
|
-
evidence: { phase: type },
|
|
234
|
-
severity: "info",
|
|
235
|
-
semantic: false,
|
|
236
|
-
coalesceKey: null,
|
|
237
|
-
};
|
|
238
|
-
case "extension_ui_request":
|
|
239
|
-
return {
|
|
240
|
-
kind: "rpc_extension_request",
|
|
241
|
-
signal: "tool-call",
|
|
242
|
-
evidence: { method: str(frame.method) ?? null },
|
|
243
|
-
severity: "info",
|
|
244
|
-
semantic: false,
|
|
245
|
-
coalesceKey: null,
|
|
246
|
-
};
|
|
247
|
-
case "extension_error":
|
|
248
|
-
return {
|
|
249
|
-
kind: "rpc_extension_error",
|
|
250
|
-
signal: "error",
|
|
251
|
-
evidence: {
|
|
252
|
-
code: str(frame.error) ? boundedMessage(frame.error) : null,
|
|
253
|
-
extensionPath: str(frame.extensionPath) ?? null,
|
|
254
|
-
},
|
|
255
|
-
severity: "critical",
|
|
256
|
-
semantic: true,
|
|
257
|
-
coalesceKey: null,
|
|
258
|
-
};
|
|
259
|
-
case "agent_end": {
|
|
260
|
-
const failed =
|
|
261
|
-
Boolean(frame.error) ||
|
|
262
|
-
frame.aborted === true ||
|
|
263
|
-
str(frame.outcome) === "failed" ||
|
|
264
|
-
str(frame.outcome) === "aborted";
|
|
265
|
-
return failed
|
|
266
|
-
? {
|
|
267
|
-
kind: "rpc_agent_failed",
|
|
268
|
-
signal: "error",
|
|
269
|
-
evidence: { outcome: str(frame.outcome) ?? "failed" },
|
|
270
|
-
severity: "critical",
|
|
271
|
-
semantic: true,
|
|
272
|
-
coalesceKey: null,
|
|
273
|
-
}
|
|
274
|
-
: {
|
|
275
|
-
kind: "rpc_agent_completed",
|
|
276
|
-
signal: "completed",
|
|
277
|
-
evidence: { outcome: "completed" },
|
|
278
|
-
severity: "info",
|
|
279
|
-
semantic: true,
|
|
280
|
-
coalesceKey: null,
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
default:
|
|
284
|
-
return null;
|
|
285
|
-
}
|
|
286
|
-
}
|
package/src/priority.json
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"smol": [
|
|
3
|
-
"cerebras/zai-glm-4.7",
|
|
4
|
-
"cerebras/zai-glm-4.6",
|
|
5
|
-
"cerebras/zai-glm",
|
|
6
|
-
"haiku-4-5",
|
|
7
|
-
"haiku-4.5",
|
|
8
|
-
"haiku",
|
|
9
|
-
"flash",
|
|
10
|
-
"mini"
|
|
11
|
-
],
|
|
12
|
-
"slow": [
|
|
13
|
-
"gpt-5.4",
|
|
14
|
-
"gpt-5.3-codex",
|
|
15
|
-
"gpt-5.3",
|
|
16
|
-
"gpt-5.2-codex",
|
|
17
|
-
"gpt-5.2",
|
|
18
|
-
"gpt-5.1-codex",
|
|
19
|
-
"gpt-5.1",
|
|
20
|
-
"codex",
|
|
21
|
-
"opus-4.6",
|
|
22
|
-
"opus-4-6",
|
|
23
|
-
"opus-4.5",
|
|
24
|
-
"opus-4-5",
|
|
25
|
-
"opus-4.1",
|
|
26
|
-
"opus-4-1",
|
|
27
|
-
"pro"
|
|
28
|
-
],
|
|
29
|
-
"designer": [
|
|
30
|
-
"google-gemini-cli/gemini-3.1-pro",
|
|
31
|
-
"google-gemini-cli/gemini-3-pro",
|
|
32
|
-
"gemini-3.1-pro",
|
|
33
|
-
"gemini-3-1-pro",
|
|
34
|
-
"gemini-3-pro",
|
|
35
|
-
"gemini-3"
|
|
36
|
-
]
|
|
37
|
-
}
|