alink-cli 0.11.13 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.mjs CHANGED
@@ -11987,7 +11987,10 @@ const ExecutionEnvironmentDescriptor = Struct({
11987
11987
  serverSelfUpdate: optionalKey(ServerSelfUpdateCapability),
11988
11988
  /** Server can stream self-update progress before acknowledging the
11989
11989
  restart. Clients fall back to server.updateServer when absent. */
11990
- serverSelfUpdateProgress: optionalKey(Boolean$1)
11990
+ serverSelfUpdateProgress: optionalKey(Boolean$1),
11991
+ /** Server understands portProxy.list/authorize/revoke. Older servers omit
11992
+ this, so clients must not send those requests under version skew. */
11993
+ portProxy: optionalKey(Boolean$1)
11991
11994
  })
11992
11995
  });
11993
11996
  Literals([
@@ -19572,6 +19575,8 @@ Literals([
19572
19575
  "thread.token-usage.updated",
19573
19576
  "thread.realtime.started",
19574
19577
  "thread.realtime.item-added",
19578
+ "thread.realtime.transcript.delta",
19579
+ "thread.realtime.transcript.done",
19575
19580
  "thread.realtime.audio.delta",
19576
19581
  "thread.realtime.error",
19577
19582
  "thread.realtime.closed",
@@ -19621,6 +19626,8 @@ const ThreadMetadataUpdatedType = Literal("thread.metadata.updated");
19621
19626
  const ThreadTokenUsageUpdatedType = Literal("thread.token-usage.updated");
19622
19627
  const ThreadRealtimeStartedType = Literal("thread.realtime.started");
19623
19628
  const ThreadRealtimeItemAddedType = Literal("thread.realtime.item-added");
19629
+ const ThreadRealtimeTranscriptDeltaType = Literal("thread.realtime.transcript.delta");
19630
+ const ThreadRealtimeTranscriptDoneType = Literal("thread.realtime.transcript.done");
19624
19631
  const ThreadRealtimeAudioDeltaType = Literal("thread.realtime.audio.delta");
19625
19632
  const ThreadRealtimeErrorType = Literal("thread.realtime.error");
19626
19633
  const ThreadRealtimeClosedType = Literal("thread.realtime.closed");
@@ -19715,6 +19722,14 @@ const ThreadTokenUsageUpdatedPayload = Struct({ usage: Struct({
19715
19722
  }) });
19716
19723
  const ThreadRealtimeStartedPayload = Struct({ realtimeSessionId: optional$3(TrimmedNonEmptyStringSchema$1) });
19717
19724
  const ThreadRealtimeItemAddedPayload = Struct({ item: Unknown });
19725
+ const ThreadRealtimeTranscriptDeltaPayload = Struct({
19726
+ role: TrimmedNonEmptyStringSchema$1,
19727
+ delta: String$1
19728
+ });
19729
+ const ThreadRealtimeTranscriptDonePayload = Struct({
19730
+ role: TrimmedNonEmptyStringSchema$1,
19731
+ text: String$1
19732
+ });
19718
19733
  const ThreadRealtimeAudioDeltaPayload = Struct({ audio: Unknown });
19719
19734
  const ThreadRealtimeErrorPayload = Struct({ message: TrimmedNonEmptyStringSchema$1 });
19720
19735
  const ThreadRealtimeClosedPayload = Struct({ reason: optional$3(TrimmedNonEmptyStringSchema$1) });
@@ -20077,6 +20092,16 @@ Union([
20077
20092
  type: ThreadRealtimeItemAddedType,
20078
20093
  payload: ThreadRealtimeItemAddedPayload
20079
20094
  }),
20095
+ Struct({
20096
+ ...ProviderRuntimeEventBase.fields,
20097
+ type: ThreadRealtimeTranscriptDeltaType,
20098
+ payload: ThreadRealtimeTranscriptDeltaPayload
20099
+ }),
20100
+ Struct({
20101
+ ...ProviderRuntimeEventBase.fields,
20102
+ type: ThreadRealtimeTranscriptDoneType,
20103
+ payload: ThreadRealtimeTranscriptDonePayload
20104
+ }),
20080
20105
  Struct({
20081
20106
  ...ProviderRuntimeEventBase.fields,
20082
20107
  type: ThreadRealtimeAudioDeltaType,
@@ -21052,6 +21077,21 @@ const ServerProviderSkill = Struct({
21052
21077
  displayName: optional$3(TrimmedNonEmptyString),
21053
21078
  shortDescription: optional$3(TrimmedNonEmptyString)
21054
21079
  });
21080
+ const ServerProviderUsagePercent = Number$1.check(isGreaterThanOrEqualTo(0)).check(isLessThanOrEqualTo(100));
21081
+ const ServerProviderUsageWindow = Struct({
21082
+ kind: Literals(["session", "weekly"]),
21083
+ label: TrimmedNonEmptyString,
21084
+ usedPercent: ServerProviderUsagePercent,
21085
+ resetsAt: optional$3(IsoDateTime),
21086
+ windowDurationMins: optional$3(NonNegativeInt)
21087
+ });
21088
+ const ServerProviderUsageLimits = Struct({
21089
+ source: Literals(["codexAppServer", "claudeAgentSdk"]),
21090
+ available: Boolean$1,
21091
+ reason: optional$3(TrimmedNonEmptyString),
21092
+ windows: ForwardCompatibleArray(ServerProviderUsageWindow),
21093
+ checkedAt: IsoDateTime
21094
+ });
21055
21095
  /**
21056
21096
  * Availability of a configured provider instance from the runtime's POV.
21057
21097
  *
@@ -21119,6 +21159,7 @@ const ServerProvider = Struct({
21119
21159
  models: ArraySchema(ServerProviderModel),
21120
21160
  slashCommands: ArraySchema(ServerProviderSlashCommand).pipe(withDecodingDefault(succeed$1([]))),
21121
21161
  skills: ArraySchema(ServerProviderSkill).pipe(withDecodingDefault(succeed$1([]))),
21162
+ usageLimits: optional$3(ServerProviderUsageLimits),
21122
21163
  versionAdvisory: optionalKey(ServerProviderVersionAdvisory),
21123
21164
  updateState: optionalKey(ServerProviderUpdateState)
21124
21165
  });
@@ -23285,6 +23326,10 @@ const WS_METHODS = {
23285
23326
  portProxyRevoke: "portProxy.revoke",
23286
23327
  cloudGetRelayClientStatus: "cloud.getRelayClientStatus",
23287
23328
  cloudInstallRelayClient: "cloud.installRelayClient",
23329
+ voiceInputStart: "voiceInput.start",
23330
+ voiceInputAppendAudio: "voiceInput.appendAudio",
23331
+ voiceInputStop: "voiceInput.stop",
23332
+ subscribeVoiceInputTranscript: "subscribeVoiceInputTranscript",
23288
23333
  sourceControlLookupRepository: "sourceControl.lookupRepository",
23289
23334
  sourceControlCloneRepository: "sourceControl.cloneRepository",
23290
23335
  sourceControlPublishRepository: "sourceControl.publishRepository",
@@ -23299,6 +23344,21 @@ const WS_METHODS = {
23299
23344
  subscribeBackgroundPolicy: "subscribeBackgroundPolicy",
23300
23345
  subscribeResourceTelemetry: "subscribeResourceTelemetry"
23301
23346
  };
23347
+ const VoiceInputThread = Struct({ threadId: ThreadId });
23348
+ const VoiceInputAudio = Struct({
23349
+ threadId: ThreadId,
23350
+ data: String$1.check(isMinLength(1), isMaxLength(32e3)),
23351
+ sampleRate: Literal(24e3),
23352
+ numChannels: Literal(1),
23353
+ samplesPerChannel: optional$3(NonNegativeInt)
23354
+ });
23355
+ const VoiceInputTranscriptEvent = Struct({
23356
+ eventId: String$1,
23357
+ role: String$1,
23358
+ text: String$1,
23359
+ final: Boolean$1
23360
+ });
23361
+ var VoiceInputUnavailableError = class extends TaggedErrorClass()("VoiceInputUnavailableError", { message: String$1 }) {};
23302
23362
  const WsServerUpsertKeybindingRpc = make$52(WS_METHODS.serverUpsertKeybinding, {
23303
23363
  payload: ServerUpsertKeybindingInput,
23304
23364
  success: ServerUpsertKeybindingResult,
@@ -23735,6 +23795,23 @@ const WsRpcGroup = make$51(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefre
23735
23795
  success: ResourceTelemetrySnapshot,
23736
23796
  error: EnvironmentAuthorizationError,
23737
23797
  stream: true
23798
+ }), make$52(WS_METHODS.voiceInputStart, {
23799
+ payload: VoiceInputThread,
23800
+ success: Struct({}),
23801
+ error: Union([VoiceInputUnavailableError, EnvironmentAuthorizationError])
23802
+ }), make$52(WS_METHODS.voiceInputAppendAudio, {
23803
+ payload: VoiceInputAudio,
23804
+ success: Struct({}),
23805
+ error: Union([VoiceInputUnavailableError, EnvironmentAuthorizationError])
23806
+ }), make$52(WS_METHODS.voiceInputStop, {
23807
+ payload: VoiceInputThread,
23808
+ success: Struct({}),
23809
+ error: Union([VoiceInputUnavailableError, EnvironmentAuthorizationError])
23810
+ }), make$52(WS_METHODS.subscribeVoiceInputTranscript, {
23811
+ payload: VoiceInputThread,
23812
+ success: VoiceInputTranscriptEvent,
23813
+ error: Union([VoiceInputUnavailableError, EnvironmentAuthorizationError]),
23814
+ stream: true
23738
23815
  }), WsOrchestrationDispatchCommandRpc, WsOrchestrationGetWorkflowScriptRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationSearchThreadsRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
23739
23816
  //#endregion
23740
23817
  //#region ../t3-shared/src/oauthScope.ts
@@ -42307,7 +42384,8 @@ const layer$24 = effect(ServerEnvironment, gen(function* () {
42307
42384
  threadSettlement: true,
42308
42385
  threadSnooze: true,
42309
42386
  threadPinning: true,
42310
- threadTitleRegeneration: true
42387
+ threadTitleRegeneration: true,
42388
+ portProxy: true
42311
42389
  }
42312
42390
  };
42313
42391
  return ServerEnvironment.of({
@@ -51066,6 +51144,21 @@ const observeRpcStreamEffect = (method, effect, traceAttributes) => {
51066
51144
  return withRpcStreamTracing(method, instrumented, traceAttributes);
51067
51145
  };
51068
51146
  //#endregion
51147
+ //#region src/provider/Services/ProviderAdapterRegistry.ts
51148
+ /**
51149
+ * ProviderAdapterRegistry - Service tag for provider adapter lookup.
51150
+ */
51151
+ var ProviderAdapterRegistry = class extends Service$2()("t3/provider/Services/ProviderAdapterRegistry") {};
51152
+ //#endregion
51153
+ //#region src/provider/Services/ProviderSessionDirectory.ts
51154
+ var ProviderSessionDirectory = class extends Service$2()("t3/provider/Services/ProviderSessionDirectory") {};
51155
+ //#endregion
51156
+ //#region src/provider/Services/ProviderService.ts
51157
+ /**
51158
+ * ProviderService - Service tag for provider orchestration.
51159
+ */
51160
+ var ProviderService = class extends Service$2()("t3/provider/Services/ProviderService") {};
51161
+ //#endregion
51069
51162
  //#region src/portProxy.ts
51070
51163
  const ports = /* @__PURE__ */ new Set();
51071
51164
  const methods = /* @__PURE__ */ new Set([
@@ -52471,6 +52564,10 @@ const RPC_REQUIRED_SCOPES = {
52471
52564
  [WS_METHODS.portProxyRevoke]: AuthOrchestrationOperateScope,
52472
52565
  [WS_METHODS.cloudGetRelayClientStatus]: AuthRelayReadScope,
52473
52566
  [WS_METHODS.cloudInstallRelayClient]: AuthRelayWriteScope,
52567
+ [WS_METHODS.voiceInputStart]: AuthOrchestrationOperateScope,
52568
+ [WS_METHODS.voiceInputAppendAudio]: AuthOrchestrationOperateScope,
52569
+ [WS_METHODS.voiceInputStop]: AuthOrchestrationOperateScope,
52570
+ [WS_METHODS.subscribeVoiceInputTranscript]: AuthOrchestrationReadScope,
52474
52571
  [WS_METHODS.sourceControlLookupRepository]: AuthOrchestrationReadScope,
52475
52572
  [WS_METHODS.sourceControlCloneRepository]: AuthOrchestrationOperateScope,
52476
52573
  [WS_METHODS.sourceControlPublishRepository]: AuthOrchestrationOperateScope,
@@ -52682,6 +52779,9 @@ const wsRpcServices = gen(function* () {
52682
52779
  keybindings: yield* Keybindings,
52683
52780
  externalLauncher: yield* ExternalLauncher,
52684
52781
  providerRegistry: yield* ProviderRegistry,
52782
+ providerAdapterRegistry: yield* ProviderAdapterRegistry,
52783
+ providerSessionDirectory: yield* ProviderSessionDirectory,
52784
+ providerService: yield* ProviderService,
52685
52785
  config: yield* ServerConfig,
52686
52786
  lifecycleEvents: yield* ServerLifecycleEvents,
52687
52787
  serverSettings: yield* ServerSettingsService,
@@ -52699,7 +52799,7 @@ const wsRpcServices = gen(function* () {
52699
52799
  });
52700
52800
  const makeWsRpcLayer = (currentSession) => WsRpcGroup.toLayer(gen(function* () {
52701
52801
  const currentSessionId = currentSession.sessionId;
52702
- const { crypto, projectionSnapshotQuery, orchestrationEngine, providerRuntimeIngestion, keybindings, externalLauncher, providerRegistry, config, lifecycleEvents, serverSettings, startup, workspaceEntries, workspaceFileSystem, gitWorkspace, terminalManager, serverEnvironment, backgroundPolicy, serverAuth, bootstrapCredentials, sessions } = yield* wsRpcServices;
52802
+ const { crypto, projectionSnapshotQuery, orchestrationEngine, providerRuntimeIngestion, keybindings, externalLauncher, providerRegistry, providerAdapterRegistry, providerSessionDirectory, providerService, config, lifecycleEvents, serverSettings, startup, workspaceEntries, workspaceFileSystem, gitWorkspace, terminalManager, serverEnvironment, backgroundPolicy, serverAuth, bootstrapCredentials, sessions } = yield* wsRpcServices;
52703
52803
  const providerMaintenanceRunner = yield* ProviderMaintenanceRunner;
52704
52804
  const rpcClientIds = yield* make$64(/* @__PURE__ */ new Set());
52705
52805
  yield* addFinalizer(() => get$3(rpcClientIds).pipe(flatMap$1((clientIds) => forEach(clientIds, (clientId) => backgroundPolicy.removeRpcClient(currentSessionId, clientId), { discard: true })), ignore$1));
@@ -52707,6 +52807,11 @@ const makeWsRpcLayer = (currentSession) => WsRpcGroup.toLayer(gen(function* () {
52707
52807
  message: `The authenticated token is missing required scope: ${requiredScope}.`,
52708
52808
  requiredScope
52709
52809
  });
52810
+ const voiceInputUnavailable = (message) => new VoiceInputUnavailableError({ message });
52811
+ const resolveVoiceInput = (threadId) => providerSessionDirectory.getBinding(threadId).pipe(mapError((cause) => voiceInputUnavailable(cause.message)), flatMap$1((binding) => match$1(binding, {
52812
+ onNone: () => fail(voiceInputUnavailable("Start a Codex conversation before using voice input.")),
52813
+ onSome: (value) => value.provider !== "codex" ? fail(voiceInputUnavailable("Voice input is currently available for Codex only.")) : providerAdapterRegistry.getByInstance(value.providerInstanceId).pipe(mapError((cause) => voiceInputUnavailable(cause.message)))
52814
+ })), flatMap$1((adapter) => adapter.capabilities.realtimeVoiceInput === true && adapter.realtimeVoiceInput ? succeed$1(adapter.realtimeVoiceInput) : fail(voiceInputUnavailable("Update this AgentLink daemon to use Codex voice input."))));
52710
52815
  const authorizeEffect = (requiredScope, effect) => currentSession.scopes.includes(requiredScope) ? effect : fail(authorizationError(requiredScope));
52711
52816
  const authorizeStream = (requiredScope, stream) => currentSession.scopes.includes(requiredScope) ? stream : fail$5(authorizationError(requiredScope));
52712
52817
  const observeRpcEffect$1 = (method, effect, traceAttributes) => observeRpcEffect(method, authorizeEffect(requiredScopeForRpcMethod(method), effect), traceAttributes);
@@ -52872,6 +52977,20 @@ const makeWsRpcLayer = (currentSession) => WsRpcGroup.toLayer(gen(function* () {
52872
52977
  };
52873
52978
  });
52874
52979
  return WsRpcGroup.of({
52980
+ [WS_METHODS.voiceInputStart]: ({ threadId }) => observeRpcEffect$1(WS_METHODS.voiceInputStart, resolveVoiceInput(threadId).pipe(flatMap$1((voice) => voice.start(threadId)), mapError((cause) => cause instanceof VoiceInputUnavailableError ? cause : voiceInputUnavailable(cause.message)), as({})), { "rpc.aggregate": "voice-input" }),
52981
+ [WS_METHODS.voiceInputAppendAudio]: ({ threadId, data, sampleRate, numChannels, samplesPerChannel }) => observeRpcEffect$1(WS_METHODS.voiceInputAppendAudio, resolveVoiceInput(threadId).pipe(flatMap$1((voice) => voice.appendAudio(threadId, {
52982
+ data,
52983
+ sampleRate,
52984
+ numChannels,
52985
+ ...samplesPerChannel !== void 0 ? { samplesPerChannel } : {}
52986
+ })), mapError((cause) => cause instanceof VoiceInputUnavailableError ? cause : voiceInputUnavailable(cause.message)), as({})), { "rpc.aggregate": "voice-input" }),
52987
+ [WS_METHODS.voiceInputStop]: ({ threadId }) => observeRpcEffect$1(WS_METHODS.voiceInputStop, resolveVoiceInput(threadId).pipe(flatMap$1((voice) => voice.stop(threadId)), mapError((cause) => cause instanceof VoiceInputUnavailableError ? cause : voiceInputUnavailable(cause.message)), as({})), { "rpc.aggregate": "voice-input" }),
52988
+ [WS_METHODS.subscribeVoiceInputTranscript]: ({ threadId }) => observeRpcStreamEffect$1(WS_METHODS.subscribeVoiceInputTranscript, resolveVoiceInput(threadId).pipe(as(providerService.streamEvents.pipe(filter$2((event) => event.threadId === threadId && (event.type === "thread.realtime.transcript.delta" || event.type === "thread.realtime.transcript.done")), map$8((event) => ({
52989
+ eventId: event.eventId,
52990
+ role: event.payload.role,
52991
+ text: event.type === "thread.realtime.transcript.delta" ? event.payload.delta : event.payload.text,
52992
+ final: event.type === "thread.realtime.transcript.done"
52993
+ }))))), { "rpc.aggregate": "voice-input" }),
52875
52994
  [ORCHESTRATION_WS_METHODS.dispatchCommand]: (command) => observeRpcEffect$1(ORCHESTRATION_WS_METHODS.dispatchCommand, gen(function* () {
52876
52995
  const normalizedCommand = yield* normalizeDispatchCommand(command);
52877
52996
  const shouldStopSessionAfterArchive = normalizedCommand.type === "thread.archive" ? yield* projectionSnapshotQuery.getThreadShellById(normalizedCommand.threadId).pipe(map$4(match$1({
@@ -54177,9 +54296,6 @@ var ProviderSessionDirectoryPersistenceError = class extends TaggedErrorClass()(
54177
54296
  }
54178
54297
  };
54179
54298
  //#endregion
54180
- //#region src/provider/Services/ProviderSessionDirectory.ts
54181
- var ProviderSessionDirectory = class extends Service$2()("t3/provider/Services/ProviderSessionDirectory") {};
54182
- //#endregion
54183
54299
  //#region src/provider/Layers/ProviderSessionDirectory.ts
54184
54300
  const decodeProviderDriverKindValue = decodeUnknownEffect(ProviderDriverKind);
54185
54301
  function toPersistenceError(operation) {
@@ -54272,12 +54388,6 @@ const ProviderSessionDirectoryLive = effect(ProviderSessionDirectory, gen(functi
54272
54388
  //#endregion
54273
54389
  //#region src/provider/Services/ProviderInstanceRegistry.ts
54274
54390
  var ProviderInstanceRegistry = class extends Service$2()("t3/provider/Services/ProviderInstanceRegistry") {};
54275
- //#endregion
54276
- //#region src/provider/Services/ProviderAdapterRegistry.ts
54277
- /**
54278
- * ProviderAdapterRegistry - Service tag for provider adapter lookup.
54279
- */
54280
- var ProviderAdapterRegistry = class extends Service$2()("t3/provider/Services/ProviderAdapterRegistry") {};
54281
54391
  const ProviderAdapterRegistryLive = effect(ProviderAdapterRegistry, fn("makeProviderAdapterRegistry")(function* () {
54282
54392
  const registry = yield* ProviderInstanceRegistry;
54283
54393
  const getByInstance = (instanceId) => registry.getInstance(instanceId).pipe(flatMap$1((instance) => instance === void 0 ? fail(new ProviderUnsupportedError({ provider: instanceId })) : succeed$1(instance.adapter)));
@@ -54793,12 +54903,6 @@ const layer$3 = effect(ProviderEventLoggers, gen(function* () {
54793
54903
  });
54794
54904
  }));
54795
54905
  //#endregion
54796
- //#region src/provider/Services/ProviderService.ts
54797
- /**
54798
- * ProviderService - Service tag for provider orchestration.
54799
- */
54800
- var ProviderService = class extends Service$2()("t3/provider/Services/ProviderService") {};
54801
- //#endregion
54802
54906
  //#region src/provider/Layers/ProviderService.ts
54803
54907
  /**
54804
54908
  * ProviderServiceLive - Cross-provider orchestration layer.
@@ -55868,6 +55972,7 @@ function buildServerProvider(input) {
55868
55972
  models: input.models,
55869
55973
  slashCommands: [...input.slashCommands ?? []],
55870
55974
  skills: [...input.skills ?? []],
55975
+ ...input.probe.usageLimits ? { usageLimits: input.probe.usageLimits } : {},
55871
55976
  ...versionAdvisory ? { versionAdvisory } : {}
55872
55977
  };
55873
55978
  }
@@ -56077,6 +56182,96 @@ const discoverClaudeSkills = fn("discoverClaudeSkills")(function* (config, cwd,
56077
56182
  return [...skillsByName.values()].sort((left, right) => left.name.localeCompare(right.name));
56078
56183
  });
56079
56184
  //#endregion
56185
+ //#region src/provider/providerUsageLimits.ts
56186
+ const SESSION_WINDOW_DURATION_MINS = 300;
56187
+ const WEEKLY_WINDOW_DURATION_MINS = 10080;
56188
+ function clampPercent(value) {
56189
+ return Number.isFinite(value) ? Math.max(0, Math.min(100, value)) : 0;
56190
+ }
56191
+ function normalizeUsageWindows(windows) {
56192
+ const durations = windows.map((window) => window.windowDurationMins).filter((duration) => Number.isFinite(duration)).toSorted((left, right) => left - right);
56193
+ const shortest = durations[0];
56194
+ const longest = durations.at(-1);
56195
+ return windows.flatMap((window) => {
56196
+ const duration = window.windowDurationMins;
56197
+ if (typeof duration !== "number" || !Number.isFinite(duration)) return [];
56198
+ const kind = duration >= WEEKLY_WINDOW_DURATION_MINS || duration === longest && longest !== shortest ? "weekly" : "session";
56199
+ return [{
56200
+ kind,
56201
+ label: window.label.trim() || (kind === "session" ? "Session" : "Weekly"),
56202
+ usedPercent: clampPercent(window.usedPercent),
56203
+ ...window.resetsAt ? { resetsAt: window.resetsAt } : {},
56204
+ windowDurationMins: Math.max(0, Math.round(duration))
56205
+ }];
56206
+ });
56207
+ }
56208
+ function unavailableUsageLimits(source, checkedAt, reason) {
56209
+ return {
56210
+ source,
56211
+ available: false,
56212
+ reason,
56213
+ windows: [],
56214
+ checkedAt
56215
+ };
56216
+ }
56217
+ function epochSecondsToIso(value) {
56218
+ const dateTime = make$72(value * 1e3);
56219
+ return isSome(dateTime) ? formatIso(dateTime.value) : void 0;
56220
+ }
56221
+ function normalizeIsoTimestamp(value) {
56222
+ if (!value) return void 0;
56223
+ const dateTime = make$72(value);
56224
+ return isSome(dateTime) ? formatIso(dateTime.value) : void 0;
56225
+ }
56226
+ function resolveCodexUsageLimits(input) {
56227
+ const reported = [input.snapshot?.primary, input.snapshot?.secondary].filter((window) => window !== null && window !== void 0 && Number.isFinite(window.usedPercent));
56228
+ const windows = reported.map((window, index) => {
56229
+ const windowDurationMins = window.windowDurationMins ?? (reported.length > 1 && index === 0 ? SESSION_WINDOW_DURATION_MINS : WEEKLY_WINDOW_DURATION_MINS);
56230
+ const resetsAt = typeof window.resetsAt === "number" ? epochSecondsToIso(window.resetsAt) : void 0;
56231
+ return {
56232
+ label: "",
56233
+ usedPercent: window.usedPercent,
56234
+ windowDurationMins,
56235
+ ...resetsAt ? { resetsAt } : {}
56236
+ };
56237
+ });
56238
+ return windows.length === 0 ? unavailableUsageLimits("codexAppServer", input.checkedAt, "No Codex subscription quota windows reported.") : {
56239
+ source: "codexAppServer",
56240
+ available: true,
56241
+ windows: normalizeUsageWindows(windows),
56242
+ checkedAt: input.checkedAt
56243
+ };
56244
+ }
56245
+ function resolveClaudeUsageLimits(input) {
56246
+ const usage = input.usage;
56247
+ const limits = usage?.rate_limits;
56248
+ if (!usage?.rate_limits_available || !limits) return unavailableUsageLimits("claudeAgentSdk", input.checkedAt, "Claude subscription quota is unavailable for this account.");
56249
+ const windows = [{
56250
+ label: "Session",
56251
+ duration: SESSION_WINDOW_DURATION_MINS,
56252
+ limit: limits.five_hour
56253
+ }, {
56254
+ label: "Weekly",
56255
+ duration: WEEKLY_WINDOW_DURATION_MINS,
56256
+ limit: limits.seven_day
56257
+ }].flatMap(({ label, duration, limit }) => {
56258
+ if (!limit || typeof limit.utilization !== "number") return [];
56259
+ const resetsAt = normalizeIsoTimestamp(limit.resets_at);
56260
+ return [{
56261
+ label,
56262
+ usedPercent: limit.utilization,
56263
+ windowDurationMins: duration,
56264
+ ...resetsAt ? { resetsAt } : {}
56265
+ }];
56266
+ });
56267
+ return windows.length === 0 ? unavailableUsageLimits("claudeAgentSdk", input.checkedAt, "No Claude subscription quota windows reported.") : {
56268
+ source: "claudeAgentSdk",
56269
+ available: true,
56270
+ windows: normalizeUsageWindows(windows),
56271
+ checkedAt: input.checkedAt
56272
+ };
56273
+ }
56274
+ //#endregion
56080
56275
  //#region src/provider/Layers/ClaudeProvider.ts
56081
56276
  const DEFAULT_CLAUDE_MODEL_CAPABILITIES = createModelCapabilities({ optionDescriptors: [] });
56082
56277
  const CLAUDE_PRESENTATION = {
@@ -56711,7 +56906,7 @@ const probeClaudeCapabilities = (claudeSettings, environment, cwd) => {
56711
56906
  const claudeEnvironment = yield* makeClaudeEnvironment(claudeSettings, environment);
56712
56907
  const executablePath = yield* resolveClaudeSdkExecutablePath(claudeSettings.binaryPath, claudeEnvironment);
56713
56908
  return yield* tryPromise(async () => {
56714
- const init = await query({
56909
+ const q = query({
56715
56910
  prompt: (async function* () {
56716
56911
  await waitForAbortSignal(abort.signal);
56717
56912
  })(),
@@ -56721,14 +56916,17 @@ const probeClaudeCapabilities = (claudeSettings, environment, cwd) => {
56721
56916
  environment: claudeEnvironment,
56722
56917
  cwd
56723
56918
  })
56724
- }).initializationResult();
56919
+ });
56920
+ const init = await q.initializationResult();
56921
+ const usage = await q.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET().catch(() => void 0);
56725
56922
  const account = init.account;
56726
56923
  return {
56727
56924
  email: account?.email,
56728
56925
  subscriptionType: account?.subscriptionType,
56729
56926
  tokenSource: account?.tokenSource,
56730
56927
  apiProvider: account?.apiProvider,
56731
- slashCommands: parseClaudeInitializationCommands(init.commands)
56928
+ slashCommands: parseClaudeInitializationCommands(init.commands),
56929
+ usage
56732
56930
  };
56733
56931
  });
56734
56932
  }).pipe(ensuring(sync(() => {
@@ -56841,6 +57039,10 @@ const checkClaudeProviderStatus = fn("checkClaudeProviderStatus")(function* (cla
56841
57039
  subscriptionType: capabilities.subscriptionType,
56842
57040
  authMethod: capabilities.tokenSource
56843
57041
  }) ?? apiProviderAuthMetadata(capabilities.apiProvider);
57042
+ const usageLimits = resolveClaudeUsageLimits({
57043
+ checkedAt,
57044
+ ...capabilities.usage ? { usage: capabilities.usage } : {}
57045
+ });
56844
57046
  return buildServerProvider({
56845
57047
  presentation: CLAUDE_PRESENTATION,
56846
57048
  enabled: claudeSettings.enabled,
@@ -56857,7 +57059,8 @@ const checkClaudeProviderStatus = fn("checkClaudeProviderStatus")(function* (cla
56857
57059
  ...capabilities.email ? { email: capabilities.email } : {},
56858
57060
  ...authMetadata ? authMetadata : {}
56859
57061
  },
56860
- ...versionUpgradeMessage ? { message: versionUpgradeMessage } : {}
57062
+ ...versionUpgradeMessage ? { message: versionUpgradeMessage } : {},
57063
+ usageLimits
56861
57064
  }
56862
57065
  });
56863
57066
  });
@@ -78354,6 +78557,7 @@ const makeChildProcessClient = fn("effect-codex-app-server/CodexAppServerClient.
78354
78557
  //#endregion
78355
78558
  //#region src/provider/Layers/CodexProvider.ts
78356
78559
  const isCodexAppServerSpawnError = is(CodexAppServerSpawnError);
78560
+ const RATE_LIMITS_PROBE_TIMEOUT_MS = 3e3;
78357
78561
  const CODEX_APP_SERVER_PROBE_FORCE_KILL_AFTER = "2 seconds";
78358
78562
  const CODEX_PRESENTATION = {
78359
78563
  displayName: "Codex",
@@ -78576,8 +78780,10 @@ const probeCodexAppServerProvider = fn("probeCodexAppServerProvider")(function*
78576
78780
  skills: []
78577
78781
  };
78578
78782
  const [skillsResponse, models] = yield* all([client.request("skills/list", { cwds: [input.cwd] }), requestAllCodexModels(client)], { concurrency: "unbounded" });
78783
+ const rateLimits = getOrUndefined(yield* client.request("account/rateLimits/read", void 0).pipe(timeoutOption(millis(RATE_LIMITS_PROBE_TIMEOUT_MS)), catchCause((cause) => hasInterrupts(cause) ? failCause$1(cause) : succeed$1(none()))))?.rateLimits;
78579
78784
  return {
78580
78785
  account: accountResponse,
78786
+ ...rateLimits ? { rateLimits } : {},
78581
78787
  version,
78582
78788
  models: applyPreferredCodexDefaultModel(appendCustomCodexModels(models, input.customModels ?? [])),
78583
78789
  skills: parseCodexSkillsListResponse(skillsResponse, input.cwd)
@@ -78711,6 +78917,16 @@ const checkCodexProviderStatus = fn("checkCodexProviderStatus")(function* (codex
78711
78917
  });
78712
78918
  const snapshot = probeResult.success.value;
78713
78919
  const accountStatus = accountProbeStatus(snapshot.account);
78920
+ const usageLimits = snapshot.account.account?.type === "apiKey" ? {
78921
+ source: "codexAppServer",
78922
+ available: false,
78923
+ reason: "Usage limits unavailable for API key Codex accounts.",
78924
+ windows: [],
78925
+ checkedAt
78926
+ } : resolveCodexUsageLimits({
78927
+ checkedAt,
78928
+ ...snapshot.rateLimits ? { snapshot: snapshot.rateLimits } : {}
78929
+ });
78714
78930
  return buildServerProvider({
78715
78931
  presentation: CODEX_PRESENTATION,
78716
78932
  enabled: codexSettings.enabled,
@@ -78722,17 +78938,18 @@ const checkCodexProviderStatus = fn("checkCodexProviderStatus")(function* (codex
78722
78938
  version: snapshot.version ?? null,
78723
78939
  status: accountStatus.status,
78724
78940
  auth: accountStatus.auth,
78725
- ...accountStatus.message ? { message: accountStatus.message } : {}
78941
+ ...accountStatus.message ? { message: accountStatus.message } : {},
78942
+ usageLimits
78726
78943
  }
78727
78944
  });
78728
78945
  });
78729
78946
  //#endregion
78730
78947
  //#region src/provider/CodexDeveloperInstructions.ts
78731
- const T3_CODE_BROWSER_TOOL_INSTRUCTIONS = `
78948
+ const AGENTLINK_BROWSER_TOOL_INSTRUCTIONS = `
78732
78949
 
78733
- ## T3 Code collaborative browser
78950
+ ## AgentLink collaborative browser
78734
78951
 
78735
- You are running inside T3 Code. The \`t3-code\` MCP server is the product-native collaborative browser shared with the user. When it exposes \`preview_*\` tools, prefer those tools for browser navigation, inspection, interaction, screenshots, and recordings.
78952
+ You are running inside AgentLink. The \`t3-code\` MCP server is the product-native collaborative browser shared with the user. When it exposes \`preview_*\` tools, prefer those tools for browser navigation, inspection, interaction, screenshots, and recordings.
78736
78953
 
78737
78954
  For browser work, first call \`preview_status\`. If no automation-capable preview is attached, call \`preview_open\` before concluding that the browser is unavailable. Then use \`preview_navigate\`, \`preview_snapshot\`, and the focused interaction tools. Prefer snapshot-provided locators over coordinates.
78738
78955
 
@@ -78858,7 +79075,7 @@ plan content should be human and agent digestible. The final plan must be plan-o
78858
79075
  Do not ask "should I proceed?" in the final output. The user can easily switch out of Plan mode and request implementation if you have included a \`<proposed_plan>\` block in your response. Alternatively, they can decide to stay in Plan mode and continue refining the plan.
78859
79076
 
78860
79077
  Only produce at most one \`<proposed_plan>\` block per turn, and only when you are presenting a complete spec.
78861
- ${T3_CODE_BROWSER_TOOL_INSTRUCTIONS}
79078
+ ${AGENTLINK_BROWSER_TOOL_INSTRUCTIONS}
78862
79079
  </collaboration_mode>`;
78863
79080
  const CODEX_DEFAULT_MODE_DEVELOPER_INSTRUCTIONS = `<collaboration_mode># Collaboration Mode: Default
78864
79081
 
@@ -78871,7 +79088,7 @@ Your active mode changes only when new developer instructions with a different \
78871
79088
  The \`request_user_input\` tool is unavailable in Default mode. If you call it while in Default mode, it will return an error.
78872
79089
 
78873
79090
  In Default mode, strongly prefer making reasonable assumptions and executing the user's request rather than stopping to ask questions. If you absolutely must ask a question because the answer cannot be discovered from local context and a reasonable assumption would be risky, ask the user directly with a concise plain-text question. Never write a multiple choice question as a textual assistant message.
78874
- ${T3_CODE_BROWSER_TOOL_INSTRUCTIONS}
79091
+ ${AGENTLINK_BROWSER_TOOL_INSTRUCTIONS}
78875
79092
  </collaboration_mode>`;
78876
79093
  function toSingleLine(value) {
78877
79094
  return value.replaceAll(/\s+/g, " ").trim();
@@ -78879,7 +79096,7 @@ function toSingleLine(value) {
78879
79096
  function buildCodexDeveloperInstructions(interactionMode, runtime) {
78880
79097
  return `${interactionMode === "plan" ? CODEX_PLAN_MODE_DEVELOPER_INSTRUCTIONS : CODEX_DEFAULT_MODE_DEVELOPER_INSTRUCTIONS}
78881
79098
 
78882
- <runtime_info>In case you're asked: you are running in T3 Code through the Codex harness, as ${toSingleLine(runtime.model)} with ${toSingleLine(runtime.reasoningEffort)} reasoning effort. No need to mention this otherwise.</runtime_info>`;
79099
+ <runtime_info>In case you're asked: you are running in AgentLink through the Codex harness, as ${toSingleLine(runtime.model)} with ${toSingleLine(runtime.reasoningEffort)} reasoning effort. No need to mention this otherwise.</runtime_info>`;
78883
79100
  }
78884
79101
  //#endregion
78885
79102
  //#region src/provider/Layers/CodexSessionRuntime.ts
@@ -79856,6 +80073,26 @@ const makeCodexSessionRuntime = (options) => gen(function* () {
79856
80073
  turnId: effectiveTurnId
79857
80074
  });
79858
80075
  }),
80076
+ startRealtimeVoiceInput: () => gen(function* () {
80077
+ const providerThreadId = yield* readProviderThreadId;
80078
+ yield* client.raw.request("thread/realtime/start", {
80079
+ threadId: providerThreadId,
80080
+ outputModality: "text",
80081
+ transport: { type: "websocket" },
80082
+ clientManagedHandoffs: true
80083
+ });
80084
+ }),
80085
+ appendRealtimeVoiceAudio: (audio) => gen(function* () {
80086
+ const providerThreadId = yield* readProviderThreadId;
80087
+ yield* client.raw.request("thread/realtime/appendAudio", {
80088
+ threadId: providerThreadId,
80089
+ audio
80090
+ });
80091
+ }),
80092
+ stopRealtimeVoiceInput: () => gen(function* () {
80093
+ const providerThreadId = yield* readProviderThreadId;
80094
+ yield* client.raw.request("thread/realtime/stop", { threadId: providerThreadId });
80095
+ }),
79859
80096
  readThread: gen(function* () {
79860
80097
  const providerThreadId = yield* readProviderThreadId;
79861
80098
  yield* initializeClient;
@@ -80793,6 +81030,30 @@ function mapToRuntimeEvents(event, canonicalThreadId) {
80793
81030
  payload: { item: payload.item }
80794
81031
  }];
80795
81032
  }
81033
+ if (event.method === "thread/realtime/transcript/delta") {
81034
+ const payload = readPayload(V2ThreadRealtimeTranscriptDeltaNotification, event.payload);
81035
+ if (!payload) return [];
81036
+ return [{
81037
+ type: "thread.realtime.transcript.delta",
81038
+ ...runtimeEventBase(event, canonicalThreadId),
81039
+ payload: {
81040
+ role: payload.role,
81041
+ delta: payload.delta
81042
+ }
81043
+ }];
81044
+ }
81045
+ if (event.method === "thread/realtime/transcript/done") {
81046
+ const payload = readPayload(V2ThreadRealtimeTranscriptDoneNotification, event.payload);
81047
+ if (!payload) return [];
81048
+ return [{
81049
+ type: "thread.realtime.transcript.done",
81050
+ ...runtimeEventBase(event, canonicalThreadId),
81051
+ payload: {
81052
+ role: payload.role,
81053
+ text: payload.text
81054
+ }
81055
+ }];
81056
+ }
80796
81057
  if (event.method === "thread/realtime/outputAudio/delta") {
80797
81058
  const payload = readPayload(V2ThreadRealtimeOutputAudioDeltaNotification, event.payload);
80798
81059
  if (!payload) return [];
@@ -81098,6 +81359,9 @@ const makeCodexAdapter = fn("makeCodexAdapter")(function* (codexConfig, options)
81098
81359
  return session;
81099
81360
  });
81100
81361
  const interruptTurn = (threadId, turnId) => requireSession(threadId).pipe(flatMap$1((session) => session.runtime.interruptTurn(turnId)), mapError((cause) => cause._tag === "ProviderAdapterSessionNotFoundError" ? cause : mapCodexRuntimeError(threadId, "turn/interrupt", cause)));
81362
+ const startRealtimeVoiceInput = (threadId) => requireSession(threadId).pipe(flatMap$1((session) => session.runtime.startRealtimeVoiceInput()), mapError((cause) => cause._tag === "ProviderAdapterSessionNotFoundError" ? cause : mapCodexRuntimeError(threadId, "thread/realtime/start", cause)));
81363
+ const appendRealtimeVoiceAudio = (threadId, audio) => requireSession(threadId).pipe(flatMap$1((session) => session.runtime.appendRealtimeVoiceAudio(audio)), mapError((cause) => cause._tag === "ProviderAdapterSessionNotFoundError" ? cause : mapCodexRuntimeError(threadId, "thread/realtime/appendAudio", cause)));
81364
+ const stopRealtimeVoiceInput = (threadId) => requireSession(threadId).pipe(flatMap$1((session) => session.runtime.stopRealtimeVoiceInput()), mapError((cause) => cause._tag === "ProviderAdapterSessionNotFoundError" ? cause : mapCodexRuntimeError(threadId, "thread/realtime/stop", cause)));
81101
81365
  const readThread = (input) => {
81102
81366
  const active = sessions.get(input.threadId);
81103
81367
  return (active && !active.stopped ? active.runtime.readThread.pipe(mapError((cause) => mapCodexRuntimeError(input.threadId, "thread/read", cause))) : scoped(gen(function* () {
@@ -81145,10 +81409,18 @@ const makeCodexAdapter = fn("makeCodexAdapter")(function* (codexConfig, options)
81145
81409
  yield* acquireRelease(void_$1, () => stopAll().pipe(andThen(shutdown$1(runtimeEventQueue)), andThen(managedNativeEventLogger?.close() ?? void_$1), ignore$1));
81146
81410
  return {
81147
81411
  provider: PROVIDER,
81148
- capabilities: { sessionModelSwitch: "in-session" },
81412
+ capabilities: {
81413
+ sessionModelSwitch: "in-session",
81414
+ realtimeVoiceInput: true
81415
+ },
81149
81416
  startSession,
81150
81417
  sendTurn,
81151
81418
  interruptTurn,
81419
+ realtimeVoiceInput: {
81420
+ start: startRealtimeVoiceInput,
81421
+ appendAudio: appendRealtimeVoiceAudio,
81422
+ stop: stopRealtimeVoiceInput
81423
+ },
81152
81424
  readThread,
81153
81425
  rollbackThread,
81154
81426
  respondToRequest,
@@ -91397,7 +91669,7 @@ const PlatformServicesLive = unwrap(gen(function* () {
91397
91669
  }));
91398
91670
  const ReactorLayerLive = empty$8.pipe(provideMerge(OrchestrationReactorLive), provideMerge(ProviderRuntimeIngestionLive), provideMerge(ProviderCommandReactorLive), provideMerge(ThreadDeletionReactorLive), provideMerge(RuntimeReceiptBusLive));
91399
91671
  const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(provide(layer$4));
91400
- const ProviderLayerLive = ProviderServiceLive.pipe(provide(ProviderAdapterRegistryLive), provideMerge(ProviderSessionDirectoryLayerLive));
91672
+ const ProviderLayerLive = ProviderServiceLive.pipe(provideMerge(ProviderAdapterRegistryLive), provideMerge(ProviderSessionDirectoryLayerLive));
91401
91673
  const PersistenceLayerLive = empty$8.pipe(provideMerge(layerConfig));
91402
91674
  const WorkspaceEntriesLayerLive = layer$10.pipe(provide(layer$22));
91403
91675
  const WorkspaceLayerLive = mergeAll(layer$22, WorkspaceEntriesLayerLive, layer$9.pipe(provide(layer$22), provide(WorkspaceEntriesLayerLive)));