@getpaseo/server 0.1.99 → 0.1.100

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.
Files changed (22) hide show
  1. package/dist/server/server/agent/provider-registry.js +1 -0
  2. package/dist/server/server/agent/providers/acp-agent.d.ts +19 -1
  3. package/dist/server/server/agent/providers/acp-agent.js +117 -0
  4. package/dist/server/server/agent/providers/claude/agent.js +36 -52
  5. package/dist/server/server/agent/providers/copilot-acp-agent.d.ts +2 -1
  6. package/dist/server/server/agent/providers/copilot-acp-agent.js +10 -0
  7. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +14 -11
  8. package/dist/server/server/agent/providers/opencode/server-manager.js +149 -91
  9. package/dist/server/server/agent/providers/opencode/test-server-manager.d.ts +6 -5
  10. package/dist/server/server/agent/providers/opencode/test-server-manager.js +13 -3
  11. package/dist/server/server/agent/providers/opencode/test-utils/{test-opencode-runtime.d.ts → test-opencode-harness.d.ts} +11 -11
  12. package/dist/server/server/agent/providers/opencode/test-utils/{test-opencode-runtime.js → test-opencode-harness.js} +23 -10
  13. package/dist/server/server/agent/providers/opencode-agent.d.ts +9 -3
  14. package/dist/server/server/agent/providers/opencode-agent.js +26 -38
  15. package/dist/server/server/agent/providers/pi/agent.d.ts +2 -1
  16. package/dist/server/server/agent/providers/pi/agent.js +5 -3
  17. package/dist/server/server/agent/providers/pi/cli-runtime.d.ts +3 -0
  18. package/dist/server/server/agent/providers/pi/cli-runtime.js +6 -3
  19. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +2 -1
  20. package/package.json +5 -5
  21. package/dist/server/server/agent/providers/opencode/runtime.d.ts +0 -28
  22. package/dist/server/server/agent/providers/opencode/runtime.js +0 -5
@@ -51,6 +51,7 @@ const PROVIDER_CLIENT_FACTORIES = {
51
51
  providerParams: options?.providerParams ?? {
52
52
  sessionDir: "~/.omp/agent/sessions",
53
53
  },
54
+ commandsRpcType: "get_available_commands",
54
55
  }),
55
56
  mock: (logger) => new MockLoadTestAgentClient(logger),
56
57
  "mock-slow": () => new MockSlowProviderClient(),
@@ -3,7 +3,7 @@ import type { ProcessTerminator } from "../../../utils/tree-kill.js";
3
3
  import type { ReadableStream as NodeReadableStream, WritableStream as NodeWritableStream } from "node:stream/web";
4
4
  import { ClientSideConnection, type Client as ACPClient, type CreateTerminalRequest, type InitializeResponse, type KillTerminalRequest, type LoadSessionResponse, type NewSessionResponse, type ReadTextFileRequest, type RequestPermissionRequest, type RequestPermissionResponse, type ResumeSessionResponse, type SessionConfigOption, type SessionMode, type SessionModelState, type SessionNotification, type TerminalOutputRequest, type TerminalOutputResponse, type ToolCallContent, type ToolCallLocation, type ToolCallStatus, type ToolKind, type Usage, type WaitForTerminalExitRequest, type WriteTextFileRequest, type Stream as ACPStream } from "@agentclientprotocol/sdk";
5
5
  import type { Logger } from "pino";
6
- import { type AgentCapabilityFlags, type AgentClient, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type AgentUsage, type FetchCatalogOptions, type ImportableProviderSession, type ImportProviderSessionContext, type ImportProviderSessionInput, type ListImportableSessionsOptions, type ProviderCatalog } from "../agent-sdk-types.js";
6
+ import { type AgentCapabilityFlags, type AgentClient, type AgentFeature, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type AgentUsage, type FetchCatalogOptions, type ImportableProviderSession, type ImportProviderSessionContext, type ImportProviderSessionInput, type ListImportableSessionsOptions, type ProviderCatalog } from "../agent-sdk-types.js";
7
7
  import { type ProviderRuntimeSettings } from "../provider-launch-config.js";
8
8
  export declare function summarizeACPRequestError(error: unknown): {
9
9
  message: string;
@@ -24,6 +24,7 @@ interface ACPAgentClientOptions {
24
24
  modelTransformer?: (models: AgentModelDefinition[]) => AgentModelDefinition[];
25
25
  sessionResponseTransformer?: (response: SessionStateResponse) => SessionStateResponse;
26
26
  configOptionsTransformer?: (configOptions: SessionConfigOption[]) => SessionConfigOption[];
27
+ configFeatureOptions?: ACPConfigFeatureOption[];
27
28
  modeIdTransformer?: (modeId: string) => string | null;
28
29
  toolSnapshotTransformer?: (snapshot: ACPToolSnapshot) => ACPToolSnapshot;
29
30
  providerModeWriter?: (context: ACPProviderModeWriterContext) => Promise<ACPProviderModeWriteResult>;
@@ -43,6 +44,7 @@ interface ACPAgentSessionOptions {
43
44
  modelTransformer?: (models: AgentModelDefinition[]) => AgentModelDefinition[];
44
45
  sessionResponseTransformer?: (response: SessionStateResponse) => SessionStateResponse;
45
46
  configOptionsTransformer?: (configOptions: SessionConfigOption[]) => SessionConfigOption[];
47
+ configFeatureOptions?: ACPConfigFeatureOption[];
46
48
  modeIdTransformer?: (modeId: string) => string | null;
47
49
  toolSnapshotTransformer?: (snapshot: ACPToolSnapshot) => ACPToolSnapshot;
48
50
  providerModeWriter?: (context: ACPProviderModeWriterContext) => Promise<ACPProviderModeWriteResult>;
@@ -76,6 +78,16 @@ interface TerminalExit {
76
78
  exitCode?: number | null;
77
79
  signal?: string | null;
78
80
  }
81
+ export interface ACPConfigFeatureOption {
82
+ id: string;
83
+ configId: string;
84
+ category: string;
85
+ label: string;
86
+ description?: string;
87
+ tooltip?: string;
88
+ icon?: string;
89
+ emptyOptionLabel?: string;
90
+ }
79
91
  type SelectConfigOption = Extract<SessionConfigOption, {
80
92
  type: "select";
81
93
  }>;
@@ -134,6 +146,7 @@ export declare function deriveModesFromACP(fallbackModes: AgentMode[], modeState
134
146
  currentModeId: string | null;
135
147
  };
136
148
  export declare function deriveModelDefinitionsFromACP(provider: string, models: SessionModelState | null | undefined, configOptions?: SessionConfigOption[] | null): AgentModelDefinition[];
149
+ export declare function deriveFeaturesFromACP(configOptions: SessionConfigOption[] | null | undefined, featureOptions: ACPConfigFeatureOption[]): AgentFeature[];
137
150
  export declare class ACPAgentClient implements AgentClient {
138
151
  readonly provider: string;
139
152
  readonly capabilities: AgentCapabilityFlags;
@@ -144,6 +157,7 @@ export declare class ACPAgentClient implements AgentClient {
144
157
  private readonly modelTransformer?;
145
158
  private readonly sessionResponseTransformer?;
146
159
  private readonly configOptionsTransformer?;
160
+ private readonly configFeatureOptions;
147
161
  private readonly modeIdTransformer?;
148
162
  private readonly toolSnapshotTransformer?;
149
163
  private readonly providerModeWriter?;
@@ -156,6 +170,7 @@ export declare class ACPAgentClient implements AgentClient {
156
170
  createSession(config: AgentSessionConfig, launchContext?: AgentLaunchContext): Promise<AgentSession>;
157
171
  resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, launchContext?: AgentLaunchContext): Promise<AgentSession>;
158
172
  fetchCatalog(options: FetchCatalogOptions): Promise<ProviderCatalog>;
173
+ listFeatures(config: AgentSessionConfig): Promise<AgentFeature[]>;
159
174
  listImportableSessions(options?: ListImportableSessionsOptions): Promise<ImportableProviderSession[]>;
160
175
  importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../agent-sdk-types.js").ImportedProviderSession>;
161
176
  isAvailable(): Promise<boolean>;
@@ -182,6 +197,7 @@ export declare class ACPAgentSession implements AgentSession, ACPClient {
182
197
  protected readonly modelTransformer?: (models: AgentModelDefinition[]) => AgentModelDefinition[];
183
198
  private readonly sessionResponseTransformer?;
184
199
  private readonly configOptionsTransformer?;
200
+ private readonly configFeatureOptions;
185
201
  private readonly modeIdTransformer?;
186
202
  private readonly toolSnapshotTransformer?;
187
203
  private readonly providerModeWriter?;
@@ -236,6 +252,7 @@ export declare class ACPAgentSession implements AgentSession, ACPClient {
236
252
  getRuntimeInfo(): Promise<AgentRuntimeInfo>;
237
253
  getAvailableModes(): Promise<AgentMode[]>;
238
254
  getCurrentMode(): Promise<string | null>;
255
+ get features(): AgentFeature[];
239
256
  private ensureCommandsReadyDeferred;
240
257
  private settleCommandsReady;
241
258
  private waitForCommandsReady;
@@ -246,6 +263,7 @@ export declare class ACPAgentSession implements AgentSession, ACPClient {
246
263
  setModel(modelId: string | null): Promise<void>;
247
264
  private setModelWithSelection;
248
265
  setThinkingOption(thinkingOptionId: string | null): Promise<void>;
266
+ setFeature(featureId: string, value: unknown): Promise<void>;
249
267
  private applyConfigOptionResponse;
250
268
  getPendingPermissions(): AgentPermissionRequest[];
251
269
  respondToPermission(requestId: string, response: AgentPermissionResponse): Promise<void>;
@@ -257,6 +257,26 @@ export function deriveModelDefinitionsFromACP(provider, models, configOptions) {
257
257
  metadata: option.metadata,
258
258
  }));
259
259
  }
260
+ export function deriveFeaturesFromACP(configOptions, featureOptions) {
261
+ return featureOptions.flatMap((featureOption) => {
262
+ const option = findSelectConfigFeatureOption(configOptions, featureOption);
263
+ if (!option) {
264
+ return [];
265
+ }
266
+ return [
267
+ {
268
+ type: "select",
269
+ id: featureOption.id,
270
+ label: featureOption.label,
271
+ description: featureOption.description,
272
+ tooltip: featureOption.tooltip,
273
+ icon: featureOption.icon,
274
+ value: option.currentValue ?? null,
275
+ options: deriveConfigFeatureSelectOptions(option, featureOption),
276
+ },
277
+ ];
278
+ });
279
+ }
260
280
  export class ACPAgentClient {
261
281
  constructor(options) {
262
282
  this.provider = options.provider;
@@ -272,6 +292,7 @@ export class ACPAgentClient {
272
292
  this.modelTransformer = options.modelTransformer;
273
293
  this.sessionResponseTransformer = options.sessionResponseTransformer;
274
294
  this.configOptionsTransformer = options.configOptionsTransformer;
295
+ this.configFeatureOptions = options.configFeatureOptions ?? [];
275
296
  this.modeIdTransformer = options.modeIdTransformer;
276
297
  this.toolSnapshotTransformer = options.toolSnapshotTransformer;
277
298
  this.providerModeWriter = options.providerModeWriter;
@@ -291,6 +312,7 @@ export class ACPAgentClient {
291
312
  modelTransformer: this.modelTransformer,
292
313
  sessionResponseTransformer: this.sessionResponseTransformer,
293
314
  configOptionsTransformer: this.configOptionsTransformer,
315
+ configFeatureOptions: this.configFeatureOptions,
294
316
  modeIdTransformer: this.modeIdTransformer,
295
317
  toolSnapshotTransformer: this.toolSnapshotTransformer,
296
318
  providerModeWriter: this.providerModeWriter,
@@ -329,6 +351,7 @@ export class ACPAgentClient {
329
351
  modelTransformer: this.modelTransformer,
330
352
  sessionResponseTransformer: this.sessionResponseTransformer,
331
353
  configOptionsTransformer: this.configOptionsTransformer,
354
+ configFeatureOptions: this.configFeatureOptions,
332
355
  modeIdTransformer: this.modeIdTransformer,
333
356
  toolSnapshotTransformer: this.toolSnapshotTransformer,
334
357
  providerModeWriter: this.providerModeWriter,
@@ -364,6 +387,24 @@ export class ACPAgentClient {
364
387
  await this.closeProbe(probe);
365
388
  }
366
389
  }
390
+ async listFeatures(config) {
391
+ if (this.configFeatureOptions.length === 0) {
392
+ return [];
393
+ }
394
+ this.assertProvider(config);
395
+ const probe = await this.spawnProcess(PROBE_ENV);
396
+ try {
397
+ const response = await this.runACPRequest(() => probe.connection.newSession({
398
+ cwd: config.cwd,
399
+ mcpServers: [],
400
+ }));
401
+ const transformed = this.transformSessionResponse(response);
402
+ return deriveFeaturesFromACP(transformed.configOptions, this.configFeatureOptions);
403
+ }
404
+ finally {
405
+ await this.closeProbe(probe);
406
+ }
407
+ }
367
408
  async listImportableSessions(options) {
368
409
  const probe = await this.spawnProcess(PROBE_ENV);
369
410
  try {
@@ -582,6 +623,7 @@ export class ACPAgentSession {
582
623
  this.modelTransformer = options.modelTransformer;
583
624
  this.sessionResponseTransformer = options.sessionResponseTransformer;
584
625
  this.configOptionsTransformer = options.configOptionsTransformer;
626
+ this.configFeatureOptions = options.configFeatureOptions ?? [];
585
627
  this.modeIdTransformer = options.modeIdTransformer;
586
628
  this.toolSnapshotTransformer = options.toolSnapshotTransformer;
587
629
  this.providerModeWriter = options.providerModeWriter;
@@ -739,6 +781,9 @@ export class ACPAgentSession {
739
781
  async getCurrentMode() {
740
782
  return this.currentMode;
741
783
  }
784
+ get features() {
785
+ return deriveFeaturesFromACP(this.configOptions, this.configFeatureOptions);
786
+ }
742
787
  ensureCommandsReadyDeferred() {
743
788
  if (this.commandsReadyDeferred || this.commandsReadySettled || this.cachedCommands.length > 0) {
744
789
  return;
@@ -1015,6 +1060,37 @@ export class ACPAgentSession {
1015
1060
  thinkingOptionId: this.thinkingOptionId,
1016
1061
  });
1017
1062
  }
1063
+ async setFeature(featureId, value) {
1064
+ if (!this.connection || !this.sessionId) {
1065
+ throw new Error("ACP session not initialized");
1066
+ }
1067
+ const featureOption = this.configFeatureOptions.find((option) => option.id === featureId);
1068
+ if (!featureOption) {
1069
+ throw new Error(`Unknown ${this.provider} feature: ${featureId}`);
1070
+ }
1071
+ const option = findSelectConfigFeatureOption(this.configOptions, featureOption);
1072
+ if (!option) {
1073
+ throw new Error(`${this.provider} does not expose ACP feature '${featureId}'`);
1074
+ }
1075
+ const requestedValue = normalizeConfigFeatureValue(value);
1076
+ const choice = findSelectConfigChoice({ option, value: requestedValue });
1077
+ if (!choice) {
1078
+ throw new Error(`${this.provider} feature '${featureId}' does not include option '${requestedValue}'`);
1079
+ }
1080
+ const response = await this.connection.setSessionConfigOption({
1081
+ sessionId: this.sessionId,
1082
+ configId: option.id,
1083
+ value: requestedValue,
1084
+ });
1085
+ const currentValue = this.applyConfigOptionResponse({
1086
+ response,
1087
+ configId: option.id,
1088
+ category: featureOption.category,
1089
+ requestedValue,
1090
+ label: featureOption.label,
1091
+ });
1092
+ this.config.featureValues = { ...this.config.featureValues, [featureId]: currentValue };
1093
+ }
1018
1094
  applyConfigOptionResponse({ response, configId, category, requestedValue, label, }) {
1019
1095
  this.configOptions = this.transformConfigOptions(response.configOptions);
1020
1096
  const responseOption = findSelectConfigOption({
@@ -1386,6 +1462,13 @@ export class ACPAgentSession {
1386
1462
  if (this.config.thinkingOptionId && this.config.thinkingOptionId !== this.thinkingOptionId) {
1387
1463
  await this.setThinkingOption(this.config.thinkingOptionId);
1388
1464
  }
1465
+ const configuredFeatureValues = this.config.featureValues ?? {};
1466
+ for (const featureOption of this.configFeatureOptions) {
1467
+ if (!Object.prototype.hasOwnProperty.call(configuredFeatureValues, featureOption.id)) {
1468
+ continue;
1469
+ }
1470
+ await this.setFeature(featureOption.id, configuredFeatureValues[featureOption.id]);
1471
+ }
1389
1472
  }
1390
1473
  warnInvalidSelection(value, message) {
1391
1474
  this.logger.warn({ value }, message);
@@ -1671,6 +1754,12 @@ function findSelectConfigOption({ configOptions, category, id, }) {
1671
1754
  const option = configOptions?.find((entry) => entry.type === "select" && entry.category === category && (!id || entry.id === id));
1672
1755
  return option ?? null;
1673
1756
  }
1757
+ function findSelectConfigFeatureOption(configOptions, featureOption) {
1758
+ const option = configOptions?.find((entry) => entry.type === "select" &&
1759
+ entry.id === featureOption.configId &&
1760
+ entry.category === featureOption.category);
1761
+ return option ?? null;
1762
+ }
1674
1763
  function findSelectConfigChoice({ option, value, }) {
1675
1764
  if (!option) {
1676
1765
  return null;
@@ -1690,6 +1779,34 @@ function flattenSelectOptions(options) {
1690
1779
  }
1691
1780
  return flattened;
1692
1781
  }
1782
+ function deriveConfigFeatureSelectOptions(option, featureOption) {
1783
+ return flattenSelectOptions(option.options).map((choice) => ({
1784
+ id: choice.value,
1785
+ label: normalizeConfigFeatureOptionLabel(choice, featureOption),
1786
+ description: choice.description ?? undefined,
1787
+ isDefault: choice.value === option.currentValue,
1788
+ metadata: choice.group ? { group: choice.group } : undefined,
1789
+ }));
1790
+ }
1791
+ function normalizeConfigFeatureOptionLabel(choice, featureOption) {
1792
+ const name = choice.name.trim();
1793
+ if (name) {
1794
+ return name;
1795
+ }
1796
+ if (choice.value === "" && featureOption.emptyOptionLabel) {
1797
+ return featureOption.emptyOptionLabel;
1798
+ }
1799
+ return choice.value;
1800
+ }
1801
+ function normalizeConfigFeatureValue(value) {
1802
+ if (typeof value === "string") {
1803
+ return value;
1804
+ }
1805
+ if (value === null) {
1806
+ return "";
1807
+ }
1808
+ throw new Error(`ACP feature value must be a string`);
1809
+ }
1693
1810
  function deriveSelectorOptions(configOptions, category) {
1694
1811
  const option = findSelectConfigOption({ configOptions, category });
1695
1812
  if (!option) {
@@ -1252,23 +1252,6 @@ function readLegacyResultUsageTokens(usage) {
1252
1252
  const usageRecord = toObjectRecord(usage);
1253
1253
  return usageRecord ? readUsageTokenTotal(usageRecord) : undefined;
1254
1254
  }
1255
- function readCurrentContextUsage(value) {
1256
- const record = toObjectRecord(value);
1257
- if (!record) {
1258
- return undefined;
1259
- }
1260
- const totalTokens = record.totalTokens;
1261
- if (typeof totalTokens !== "number" || !Number.isFinite(totalTokens) || totalTokens < 0) {
1262
- return undefined;
1263
- }
1264
- const maxTokens = record.maxTokens;
1265
- return {
1266
- totalTokens,
1267
- ...(typeof maxTokens === "number" && Number.isFinite(maxTokens) && maxTokens > 0
1268
- ? { maxTokens }
1269
- : {}),
1270
- };
1271
- }
1272
1255
  function isClaudeSubagentToolName(name) {
1273
1256
  return name === "Task" || name === "Agent";
1274
1257
  }
@@ -1280,6 +1263,7 @@ class ClaudeContextUsageState {
1280
1263
  beginTurn() {
1281
1264
  this.streamRequestInputTokens = undefined;
1282
1265
  this.streamRequestOutputTokens = undefined;
1266
+ this.compactedContextWindowUsedTokens = undefined;
1283
1267
  }
1284
1268
  setInitialContextWindowMaxTokens(contextWindowMaxTokens) {
1285
1269
  this.contextWindowMaxTokens = contextWindowMaxTokens;
@@ -1291,11 +1275,6 @@ class ClaudeContextUsageState {
1291
1275
  }
1292
1276
  return this.contextWindowMaxTokens;
1293
1277
  }
1294
- recordCurrentContextUsage(usage) {
1295
- if (usage?.maxTokens !== undefined) {
1296
- this.contextWindowMaxTokens = usage.maxTokens;
1297
- }
1298
- }
1299
1278
  buildStreamUsageEvent(event) {
1300
1279
  const streamEvent = toObjectRecord(event);
1301
1280
  if (!streamEvent) {
@@ -1326,7 +1305,7 @@ class ClaudeContextUsageState {
1326
1305
  }
1327
1306
  return this.createUsageUpdatedEvent(usedTokens);
1328
1307
  }
1329
- buildResultUsage(message, modelUsage, currentContextUsage) {
1308
+ buildResultUsage(message, modelUsage) {
1330
1309
  try {
1331
1310
  if (!message.usage) {
1332
1311
  return undefined;
@@ -1338,7 +1317,6 @@ class ClaudeContextUsageState {
1338
1317
  totalCostUsd: message.total_cost_usd,
1339
1318
  };
1340
1319
  const modelContextWindowMaxTokens = this.recordModelUsage(modelUsage ?? message.modelUsage);
1341
- this.recordCurrentContextUsage(currentContextUsage);
1342
1320
  if (this.contextWindowMaxTokens !== undefined) {
1343
1321
  usage.contextWindowMaxTokens = this.contextWindowMaxTokens;
1344
1322
  }
@@ -1347,13 +1325,14 @@ class ClaudeContextUsageState {
1347
1325
  }
1348
1326
  const activeResultUsageTokens = readActiveUsageTokens(message.usage) ??
1349
1327
  (this.completedResultTurns === 0 ? readLegacyResultUsageTokens(message.usage) : undefined);
1350
- const usedTokens = currentContextUsage?.totalTokens ?? this.streamUsedTokens() ?? activeResultUsageTokens;
1328
+ const usedTokens = this.streamUsedTokens() ?? activeResultUsageTokens ?? this.compactedContextWindowUsedTokens;
1351
1329
  if (usedTokens !== undefined) {
1352
1330
  usage.contextWindowUsedTokens = usedTokens;
1353
1331
  }
1354
1332
  return usage;
1355
1333
  }
1356
1334
  finally {
1335
+ this.compactedContextWindowUsedTokens = undefined;
1357
1336
  this.completedResultTurns += 1;
1358
1337
  }
1359
1338
  }
@@ -1362,7 +1341,8 @@ class ClaudeContextUsageState {
1362
1341
  typeof this.streamRequestOutputTokens !== "number") {
1363
1342
  return undefined;
1364
1343
  }
1365
- return this.streamRequestInputTokens + this.streamRequestOutputTokens;
1344
+ const usedTokens = this.streamRequestInputTokens + this.streamRequestOutputTokens;
1345
+ return usedTokens > 0 ? usedTokens : undefined;
1366
1346
  }
1367
1347
  createUsageUpdatedEvent(contextWindowUsedTokens) {
1368
1348
  const usage = {
@@ -1377,6 +1357,23 @@ class ClaudeContextUsageState {
1377
1357
  usage,
1378
1358
  };
1379
1359
  }
1360
+ buildCompactionUsageEvent(postTokens) {
1361
+ this.streamRequestInputTokens = undefined;
1362
+ this.streamRequestOutputTokens = undefined;
1363
+ this.compactedContextWindowUsedTokens = postTokens;
1364
+ const usage = {};
1365
+ if (this.contextWindowMaxTokens !== undefined) {
1366
+ usage.contextWindowMaxTokens = this.contextWindowMaxTokens;
1367
+ }
1368
+ if (postTokens !== undefined) {
1369
+ usage.contextWindowUsedTokens = postTokens;
1370
+ }
1371
+ return {
1372
+ type: "usage_updated",
1373
+ provider: "claude",
1374
+ usage,
1375
+ };
1376
+ }
1380
1377
  }
1381
1378
  class ClaudeAgentSession {
1382
1379
  constructor(config, options) {
@@ -2659,7 +2656,7 @@ class ClaudeAgentSession {
2659
2656
  if (await this.handleMissingResumedConversation(message, activeQuery)) {
2660
2657
  return true;
2661
2658
  }
2662
- await this.routeSdkMessageFromPump(message, activeQuery);
2659
+ await this.routeSdkMessageFromPump(message);
2663
2660
  return false;
2664
2661
  };
2665
2662
  const drainActiveQuery = async () => {
@@ -2727,7 +2724,7 @@ class ClaudeAgentSession {
2727
2724
  message.type === "tool_progress" ||
2728
2725
  (message.type === "system" && message.subtype === "task_notification"));
2729
2726
  }
2730
- async routeSdkMessageFromPump(message, activeQuery) {
2727
+ async routeSdkMessageFromPump(message) {
2731
2728
  if (this.shouldSuppressStaleResult(message)) {
2732
2729
  return;
2733
2730
  }
@@ -2750,7 +2747,7 @@ class ClaudeAgentSession {
2750
2747
  identifiers,
2751
2748
  rawEvent: message,
2752
2749
  }, "provider.claude.parsed_event");
2753
- const events = await this.buildPumpedMessageEvents(message, activeQuery, identifiers.messageId, turnId);
2750
+ const events = await this.buildPumpedMessageEvents(message, identifiers.messageId, turnId);
2754
2751
  if (events.length === 0) {
2755
2752
  return;
2756
2753
  }
@@ -2773,14 +2770,10 @@ class ClaudeAgentSession {
2773
2770
  }
2774
2771
  this.dispatchEvents(events);
2775
2772
  }
2776
- async buildPumpedMessageEvents(message, activeQuery, messageIdHint, turnId) {
2777
- const currentContextUsage = message.type === "result" && message.subtype === "success"
2778
- ? await this.queryCurrentContextUsage(activeQuery)
2779
- : undefined;
2773
+ async buildPumpedMessageEvents(message, messageIdHint, turnId) {
2780
2774
  const messageEvents = this.translateMessageToEvents(message, {
2781
2775
  suppressAssistantText: true,
2782
2776
  suppressReasoning: true,
2783
- currentContextUsage,
2784
2777
  });
2785
2778
  const assistantTimelineEvents = this.timelineAssembler
2786
2779
  .consume({
@@ -2795,16 +2788,6 @@ class ClaudeAgentSession {
2795
2788
  }));
2796
2789
  return [...messageEvents, ...assistantTimelineEvents];
2797
2790
  }
2798
- async queryCurrentContextUsage(activeQuery) {
2799
- try {
2800
- const usage = await withTimeout(activeQuery.getContextUsage(), 3000, "timeout");
2801
- return readCurrentContextUsage(usage);
2802
- }
2803
- catch (error) {
2804
- this.logger.debug({ err: error }, "Claude context usage query failed");
2805
- return undefined;
2806
- }
2807
- }
2808
2791
  async handleMissingResumedConversation(message, activeQuery) {
2809
2792
  const staleResumeError = this.readMissingResumedConversationError(message);
2810
2793
  if (!staleResumeError) {
@@ -2895,9 +2878,7 @@ class ClaudeAgentSession {
2895
2878
  this.appendStreamEventEvents(message, events, options);
2896
2879
  break;
2897
2880
  case "result":
2898
- this.appendResultEvents(message, events, {
2899
- currentContextUsage: options?.currentContextUsage,
2900
- });
2881
+ this.appendResultEvents(message, events);
2901
2882
  break;
2902
2883
  default:
2903
2884
  break;
@@ -2963,6 +2944,7 @@ class ClaudeAgentSession {
2963
2944
  },
2964
2945
  provider: "claude",
2965
2946
  });
2947
+ events.push(this.contextUsage.buildCompactionUsageEvent(compactMetadata?.postTokens));
2966
2948
  return;
2967
2949
  }
2968
2950
  if (message.subtype === "task_notification") {
@@ -3067,8 +3049,8 @@ class ClaudeAgentSession {
3067
3049
  events.push({ type: "timeline", item, provider: "claude" });
3068
3050
  }
3069
3051
  }
3070
- appendResultEvents(message, events, options) {
3071
- const usage = this.convertUsage(message, message.modelUsage, options?.currentContextUsage);
3052
+ appendResultEvents(message, events) {
3053
+ const usage = this.convertUsage(message, message.modelUsage);
3072
3054
  if (message.subtype === "success") {
3073
3055
  // Built-in slash commands (e.g. /voice, /usage, "Unknown command: …")
3074
3056
  // run client-side in the Claude CLI with no model turn — output_tokens
@@ -3212,8 +3194,8 @@ class ClaudeAgentSession {
3212
3194
  }
3213
3195
  return null;
3214
3196
  }
3215
- convertUsage(message, modelUsage, currentContextUsage) {
3216
- return this.contextUsage.buildResultUsage(message, modelUsage, currentContextUsage);
3197
+ convertUsage(message, modelUsage) {
3198
+ return this.contextUsage.buildResultUsage(message, modelUsage);
3217
3199
  }
3218
3200
  enqueueTimeline(item) {
3219
3201
  this.pushEvent({ type: "timeline", item, provider: "claude" });
@@ -3899,7 +3881,9 @@ function readCompactionMetadata(source) {
3899
3881
  const trigger = typeof metadata.trigger === "string" ? metadata.trigger : undefined;
3900
3882
  const preTokensRaw = metadata.preTokens ?? metadata.pre_tokens;
3901
3883
  const preTokens = typeof preTokensRaw === "number" ? preTokensRaw : undefined;
3902
- return { trigger, preTokens };
3884
+ const postTokensRaw = metadata.postTokens ?? metadata.post_tokens;
3885
+ const postTokens = typeof postTokensRaw === "number" ? postTokensRaw : undefined;
3886
+ return { trigger, preTokens, postTokens };
3903
3887
  }
3904
3888
  return null;
3905
3889
  }
@@ -2,8 +2,9 @@ import type { Logger } from "pino";
2
2
  import type { SessionConfigOption } from "@agentclientprotocol/sdk";
3
3
  import type { AgentMode } from "../agent-sdk-types.js";
4
4
  import { type ProviderRuntimeSettings } from "../provider-launch-config.js";
5
- import { ACPAgentClient, type ACPBeforeModeWriteResult, type ACPProviderModeWriteResult, type ACPProviderModeWriterContext, type SessionStateResponse } from "./acp-agent.js";
5
+ import { ACPAgentClient, type ACPConfigFeatureOption, type ACPBeforeModeWriteResult, type ACPProviderModeWriteResult, type ACPProviderModeWriterContext, type SessionStateResponse } from "./acp-agent.js";
6
6
  export declare const COPILOT_ALLOW_ALL_MODE_ID = "allow-all";
7
+ export declare const COPILOT_AGENT_FEATURE_OPTION: ACPConfigFeatureOption;
7
8
  export declare const COPILOT_MODES: AgentMode[];
8
9
  interface CopilotACPAgentClientOptions {
9
10
  logger: Logger;
@@ -20,6 +20,15 @@ export const COPILOT_ALLOW_ALL_MODE_ID = "allow-all";
20
20
  const COPILOT_ALLOW_ALL_CONFIG_ID = "allow_all";
21
21
  const COPILOT_ALLOW_ALL_ON = "on";
22
22
  const COPILOT_ALLOW_ALL_OFF = "off";
23
+ export const COPILOT_AGENT_FEATURE_OPTION = {
24
+ id: "agent",
25
+ configId: "agent",
26
+ category: "_agent",
27
+ label: "Agent",
28
+ description: "Use a Copilot custom agent profile",
29
+ tooltip: "Select Copilot agent",
30
+ emptyOptionLabel: "Default",
31
+ };
23
32
  export const COPILOT_MODES = [
24
33
  {
25
34
  id: COPILOT_AGENT_MODE_ID,
@@ -47,6 +56,7 @@ export class CopilotACPAgentClient extends ACPAgentClient {
47
56
  defaultModes: COPILOT_MODES,
48
57
  sessionResponseTransformer: transformCopilotSessionResponse,
49
58
  configOptionsTransformer: transformCopilotConfigOptions,
59
+ configFeatureOptions: [COPILOT_AGENT_FEATURE_OPTION],
50
60
  modeIdTransformer: transformCopilotModeId,
51
61
  providerModeWriter: writeCopilotProviderMode,
52
62
  beforeModeWriter: beforeCopilotModeWriter,
@@ -16,10 +16,10 @@ export interface OpenCodeServerManagerLike {
16
16
  port: number;
17
17
  url: string;
18
18
  }>;
19
- acquire(options: {
20
- force: boolean;
21
- env?: Record<string, string>;
22
- }): Promise<OpenCodeServerAcquisition>;
19
+ acquireCurrent(): Promise<OpenCodeServerAcquisition>;
20
+ acquireNew(): Promise<OpenCodeServerAcquisition>;
21
+ acquireDedicated(env: Record<string, string>): Promise<OpenCodeServerAcquisition>;
22
+ shutdown(): Promise<void>;
23
23
  }
24
24
  export interface OpenCodeServerGeneration {
25
25
  process: ChildProcess;
@@ -27,7 +27,11 @@ export interface OpenCodeServerGeneration {
27
27
  url: string;
28
28
  refCount: number;
29
29
  retired: boolean;
30
+ ready: Promise<void>;
30
31
  managedProcessId?: string;
32
+ managedProcessRecord?: Promise<{
33
+ id: string;
34
+ } | null>;
31
35
  }
32
36
  export type OpenCodePortAllocator = () => Promise<number>;
33
37
  export type OpenCodeCommandPrefixResolver = () => Promise<{
@@ -50,7 +54,7 @@ export declare class OpenCodeServerManager implements OpenCodeServerManagerLike
50
54
  private currentServer;
51
55
  private retiredServers;
52
56
  private startPromise;
53
- private forcedRefreshPromise;
57
+ private newServerPromise;
54
58
  private readonly logger;
55
59
  private readonly runtimeSettings?;
56
60
  private readonly runtimeSettingsKey;
@@ -66,21 +70,20 @@ export declare class OpenCodeServerManager implements OpenCodeServerManagerLike
66
70
  port: number;
67
71
  url: string;
68
72
  }>;
69
- acquire(options: {
70
- force: boolean;
71
- env?: Record<string, string>;
72
- }): Promise<OpenCodeServerAcquisition>;
73
+ acquireCurrent(): Promise<OpenCodeServerAcquisition>;
74
+ acquireNew(): Promise<OpenCodeServerAcquisition>;
75
+ acquireDedicated(env: Record<string, string>): Promise<OpenCodeServerAcquisition>;
73
76
  private acquireServer;
74
- private getForcedRefreshServer;
77
+ private getNewServer;
75
78
  private getCurrentServer;
76
79
  private rotateCurrentServer;
77
- private startDedicatedServer;
78
80
  private startServer;
79
81
  shutdown(): Promise<void>;
80
82
  private cleanupRetiredServers;
81
83
  private killServer;
82
84
  private recordManagedServerProcess;
83
85
  private removeManagedProcessRecordWhenResolved;
86
+ private removeManagedServerRecord;
84
87
  private removeManagedProcessId;
85
88
  }
86
89
  //# sourceMappingURL=server-manager.d.ts.map