lody 0.97.2 → 0.99.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/grok-acp.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createInterface } from "node:readline";
2
- import { r as runtimeManifest } from "./chunks/runtime-manifest-DqfOlvSw.js";
3
- import { L as LODY_EXTENSION_METHODS } from "./chunks/methods-CvEDMahD.js";
2
+ import { r as runtimeManifest } from "./chunks/runtime-manifest-DZsDOOW3.js";
4
3
  import { L as LODY_PLAN_MODE_CONFIG_ID, c as createPlanModeConfigOption } from "./chunks/plan-mode-BLOER-fv.js";
4
+ import { L as LODY_EXTENSION_METHODS } from "./chunks/methods-CvEDMahD.js";
5
5
  import { S as SessionUsageAccumulator } from "./chunks/usage-DY4Eg1Mf.js";
6
6
  import { spawn } from "node:child_process";
7
7
  function update(sessionId, value) {
@@ -336,10 +336,58 @@ function legacyOptions(result) {
336
336
  const options = result?._meta?.[contract.sessionConfigMeta]?.options;
337
337
  return Array.isArray(options) ? options : [];
338
338
  }
339
- function readReasoningEfforts(model) {
339
+ function readReasoningOptions(model) {
340
340
  const raw = model?._meta?.reasoningEfforts ?? model?._meta?.reasoning_efforts;
341
341
  if (!Array.isArray(raw)) return [];
342
- return raw.map((item) => typeof item === "string" ? item : item?.id ?? item?.reasoningEffort).filter((item) => typeof item === "string");
342
+ return raw.map((item) => {
343
+ if (typeof item === "string") {
344
+ return {
345
+ id: item,
346
+ value: item,
347
+ name: optionName(item),
348
+ description: null,
349
+ default: false
350
+ };
351
+ }
352
+ const id = item?.id ?? item?.reasoningEffort ?? item?.value;
353
+ const value = item?.value ?? item?.reasoningEffort ?? item?.id;
354
+ if (typeof id !== "string" || typeof value !== "string") return void 0;
355
+ return {
356
+ id,
357
+ value,
358
+ name: typeof item.label === "string" ? item.label : optionName(id),
359
+ description: typeof item.description === "string" ? item.description : null,
360
+ default: item.default === true
361
+ };
362
+ }).filter(Boolean);
363
+ }
364
+ function readReasoningEfforts(model) {
365
+ return readReasoningOptions(model).map((option) => option.id);
366
+ }
367
+ function reasoningOptionsFromConfig(option) {
368
+ if (!Array.isArray(option?.options)) return [];
369
+ return option.options.map((item) => {
370
+ if (!item || typeof item.value !== "string") return void 0;
371
+ return {
372
+ id: item.value,
373
+ value: item.value,
374
+ name: typeof item.name === "string" ? item.name : optionName(item.value),
375
+ description: typeof item.description === "string" ? item.description : null,
376
+ default: false
377
+ };
378
+ }).filter(Boolean);
379
+ }
380
+ function reasoningSelector(options, reportedValue) {
381
+ if (typeof reportedValue !== "string") return void 0;
382
+ return options.find((option) => option.id === reportedValue)?.id ?? options.find((option) => option.value === reportedValue)?.id;
383
+ }
384
+ function standardConfigOptions(result) {
385
+ return Array.isArray(result?.configOptions) ? result.configOptions.filter(
386
+ (option) => option && typeof option === "object" && typeof option.id === "string"
387
+ ) : [];
388
+ }
389
+ function configOption(options, id) {
390
+ return options.find((option) => option.id === id);
343
391
  }
344
392
  function readModelSnapshot(params) {
345
393
  if (!params || typeof params !== "object" || !Array.isArray(params.availableModels)) {
@@ -414,6 +462,23 @@ function translateSessionStart(message) {
414
462
  permissionMode
415
463
  };
416
464
  }
465
+ function translateInitialize(message) {
466
+ const params = message.params ?? {};
467
+ const clientCapabilities = params.clientCapabilities ?? {};
468
+ return {
469
+ ...message,
470
+ params: {
471
+ ...params,
472
+ clientCapabilities: {
473
+ ...clientCapabilities,
474
+ _meta: {
475
+ ...clientCapabilities._meta ?? {},
476
+ [contract.userMessageEchoCapability]: false
477
+ }
478
+ }
479
+ }
480
+ };
481
+ }
417
482
  class GrokAcpCompatibilityProxy {
418
483
  constructor({ deferSessionResponseUntilModelSnapshot = false } = {}) {
419
484
  this.sessions = /* @__PURE__ */ new Map();
@@ -431,18 +496,63 @@ class GrokAcpCompatibilityProxy {
431
496
  applyCurrentModel(state, currentModelId, reportedReasoningEffort) {
432
497
  const previousModelId = state.currentModelId;
433
498
  const currentModel = state.models.find((model) => model.modelId === currentModelId);
434
- const reasoningEfforts = readReasoningEfforts(currentModel);
499
+ const reasoningOptions = readReasoningOptions(currentModel);
500
+ const reasoningEfforts = reasoningOptions.map((option) => option.id);
435
501
  const metadataReasoningEffort = currentModel?._meta?.reasoningEffort ?? currentModel?._meta?.reasoning_effort;
436
502
  state.currentModelId = currentModelId;
437
503
  if (reasoningEfforts.length === 0) {
438
- if (previousModelId !== currentModelId) state.reasoningEfforts = [];
504
+ if (previousModelId !== currentModelId) {
505
+ state.reasoningOptions = [];
506
+ state.reasoningEfforts = [];
507
+ }
439
508
  if (typeof reportedReasoningEffort === "string") {
440
509
  state.reasoningEffort = reportedReasoningEffort;
441
510
  }
442
511
  return;
443
512
  }
513
+ state.reasoningOptions = reasoningOptions;
444
514
  state.reasoningEfforts = reasoningEfforts;
445
- state.reasoningEffort = typeof reportedReasoningEffort === "string" && reasoningEfforts.includes(reportedReasoningEffort) ? reportedReasoningEffort : previousModelId === currentModelId && reasoningEfforts.includes(state.reasoningEffort) ? state.reasoningEffort : typeof metadataReasoningEffort === "string" && reasoningEfforts.includes(metadataReasoningEffort) ? metadataReasoningEffort : reasoningEfforts[0];
515
+ const reportedValue = reasoningSelector(reasoningOptions, reportedReasoningEffort) ?? (typeof reportedReasoningEffort === "string" ? reportedReasoningEffort : void 0);
516
+ const metadataValue = reasoningSelector(reasoningOptions, metadataReasoningEffort) ?? (typeof metadataReasoningEffort === "string" ? metadataReasoningEffort : void 0);
517
+ state.reasoningEffort = reportedValue !== void 0 ? reportedValue : previousModelId === currentModelId && typeof state.reasoningEffort === "string" ? state.reasoningEffort : metadataValue ?? reasoningOptions.find((option) => option.default)?.id ?? reasoningEfforts[0];
518
+ }
519
+ applyRuntimeConfigOptions(state, options) {
520
+ if (!Array.isArray(options)) return;
521
+ state.runtimeConfigOptions = options.filter(
522
+ (option) => option && typeof option === "object" && typeof option.id === "string" && option.id !== LODY_PLAN_MODE_CONFIG_ID && option.id !== "permission_mode" && option.id !== "interaction_mode"
523
+ );
524
+ const modelOption = configOption(state.runtimeConfigOptions, "model");
525
+ if (Array.isArray(modelOption?.options)) {
526
+ state.models = modelOption.options.filter((option) => option && typeof option.value === "string").map((option) => {
527
+ const existing = state.models.find((model) => model.modelId === option.value);
528
+ return {
529
+ ...existing ?? {},
530
+ modelId: option.value,
531
+ name: typeof option.name === "string" ? option.name : existing?.name ?? option.value,
532
+ description: option.description ?? existing?.description
533
+ };
534
+ });
535
+ }
536
+ if (typeof modelOption?.currentValue === "string") {
537
+ this.applyCurrentModel(state, modelOption.currentValue);
538
+ }
539
+ const reasoningOption = configOption(state.runtimeConfigOptions, "reasoning_effort");
540
+ if (!reasoningOption) return;
541
+ const currentModel = state.models.find((model) => model.modelId === state.currentModelId);
542
+ const metadataReasoningOptions = readReasoningOptions(currentModel);
543
+ if (metadataReasoningOptions.length) {
544
+ state.reasoningOptions = metadataReasoningOptions;
545
+ state.reasoningEfforts = metadataReasoningOptions.map((option) => option.id);
546
+ } else {
547
+ state.reasoningOptions = reasoningOptionsFromConfig(reasoningOption);
548
+ state.reasoningEfforts = state.reasoningOptions.map((option) => option.id);
549
+ }
550
+ const selected = reasoningSelector(state.reasoningOptions, reasoningOption.currentValue);
551
+ if (selected !== void 0) {
552
+ state.reasoningEffort = selected;
553
+ } else if (typeof reasoningOption.currentValue === "string") {
554
+ state.reasoningEffort = reasoningOption.currentValue;
555
+ }
446
556
  }
447
557
  applyModelSnapshot(state, snapshot) {
448
558
  state.models = snapshot.availableModels;
@@ -573,9 +683,10 @@ class GrokAcpCompatibilityProxy {
573
683
  return { toRuntime: [...cancelled.toRuntime, message], toClient: cancelled.toClient };
574
684
  }
575
685
  if (message.method === "initialize" && message.id !== void 0) {
576
- this.clientCapabilities = params.clientCapabilities ?? {};
686
+ const translated2 = translateInitialize(message);
687
+ this.clientCapabilities = translated2.params.clientCapabilities;
577
688
  this.pending.set(message.id, { kind: "initialize" });
578
- return { toRuntime: [message], toClient: [] };
689
+ return { toRuntime: [translated2], toClient: [] };
579
690
  }
580
691
  if (message.method === LODY_EXTENSION_METHODS.rateLimitsGet) {
581
692
  return {
@@ -616,7 +727,9 @@ class GrokAcpCompatibilityProxy {
616
727
  }
617
728
  const { sessionId, configId, value } = params;
618
729
  const state = this.sessions.get(sessionId);
619
- if (!state || (configId === LODY_PLAN_MODE_CONFIG_ID ? typeof value !== "boolean" : typeof value !== "string")) {
730
+ const runtimeOption = configOption(state?.runtimeConfigOptions ?? [], configId);
731
+ const expectsBoolean = configId === LODY_PLAN_MODE_CONFIG_ID || runtimeOption?.type === "boolean";
732
+ if (!state || (expectsBoolean ? typeof value !== "boolean" : typeof value !== "string")) {
620
733
  return {
621
734
  toRuntime: [],
622
735
  toClient: [errorResponse(message.id, "Unknown Grok session or invalid config value")]
@@ -659,7 +772,7 @@ class GrokAcpCompatibilityProxy {
659
772
  toClient: [errorResponse(message.id, "Unsupported Grok reasoning effort")]
660
773
  };
661
774
  }
662
- translated = {
775
+ translated = configOption(state.runtimeConfigOptions, configId) ? message : {
663
776
  jsonrpc: "2.0",
664
777
  id: message.id,
665
778
  method: "session/set_model",
@@ -667,12 +780,12 @@ class GrokAcpCompatibilityProxy {
667
780
  sessionId,
668
781
  modelId: state.currentModelId,
669
782
  _meta: {
670
- [contract.reasoningEffortMeta]: value
783
+ [contract.reasoningEffortMeta]: state.reasoningOptions.find((option) => option.id === value)?.value ?? value
671
784
  }
672
785
  }
673
786
  };
674
787
  } else if (configId === "model") {
675
- translated = {
788
+ translated = configOption(state.runtimeConfigOptions, configId) ? message : {
676
789
  jsonrpc: "2.0",
677
790
  id: message.id,
678
791
  method: "session/set_model",
@@ -688,6 +801,8 @@ class GrokAcpCompatibilityProxy {
688
801
  method: "session/set_mode",
689
802
  params: { sessionId, modeId }
690
803
  };
804
+ } else if (configOption(state.runtimeConfigOptions, configId)) {
805
+ translated = message;
691
806
  } else {
692
807
  return unsupportedConfigOption(message.id, configId);
693
808
  }
@@ -792,17 +907,21 @@ class GrokAcpCompatibilityProxy {
792
907
  }
793
908
  const state = this.sessions.get(pending.sessionId);
794
909
  if (!state) return { toRuntime: [], toClient: [message] };
795
- if (pending.configId === "model") this.applyCurrentModel(state, pending.value);
796
- if (pending.configId === "reasoning_effort") state.reasoningEffort = pending.value;
797
- if (pending.configId === LODY_PLAN_MODE_CONFIG_ID || pending.configId === "interaction_mode")
798
- state.interactionMode = pending.value;
910
+ if (message.error) return { toRuntime: [], toClient: [message] };
911
+ if (Array.isArray(message.result?.configOptions)) {
912
+ this.applyRuntimeConfigOptions(state, message.result.configOptions);
913
+ } else {
914
+ if (pending.configId === "model") this.applyCurrentModel(state, pending.value);
915
+ if (pending.configId === "reasoning_effort") state.reasoningEffort = pending.value;
916
+ if (pending.configId === LODY_PLAN_MODE_CONFIG_ID || pending.configId === "interaction_mode")
917
+ state.interactionMode = pending.value;
918
+ }
799
919
  return {
800
920
  toRuntime: [],
801
921
  toClient: [
802
922
  {
803
- jsonrpc: "2.0",
804
- id: message.id,
805
- result: { configOptions: this.configOptions(state) }
923
+ ...message,
924
+ result: { ...message.result ?? {}, configOptions: this.configOptions(state) }
806
925
  }
807
926
  ]
808
927
  };
@@ -846,6 +965,21 @@ class GrokAcpCompatibilityProxy {
846
965
  toClient: usage ? [message, usage] : [message]
847
966
  };
848
967
  }
968
+ if (message.method === "session/update" && update2?.sessionUpdate === "config_option_update" && Array.isArray(update2.configOptions)) {
969
+ this.applyRuntimeConfigOptions(state, update2.configOptions);
970
+ return {
971
+ toRuntime: [],
972
+ toClient: [
973
+ {
974
+ ...message,
975
+ params: {
976
+ ...message.params,
977
+ update: { ...update2, configOptions: this.configOptions(state) }
978
+ }
979
+ }
980
+ ]
981
+ };
982
+ }
849
983
  if (message.method === "session/update" && update2?.sessionUpdate === "current_mode_update") {
850
984
  const interactionMode = INTERACTION_FROM_RUNTIME[update2.currentModeId];
851
985
  if (!interactionMode) return passthrough;
@@ -874,6 +1008,13 @@ class GrokAcpCompatibilityProxy {
874
1008
  if (typeof modelId === "string") {
875
1009
  this.applyCurrentModel(state, modelId, reasoningEffort);
876
1010
  }
1011
+ const publishesStandardConfig = configOption(state.runtimeConfigOptions, "model") !== void 0 || configOption(state.runtimeConfigOptions, "reasoning_effort") !== void 0;
1012
+ if (publishesStandardConfig) {
1013
+ return {
1014
+ toRuntime: [this.internalRequest("context", sessionId)],
1015
+ toClient: []
1016
+ };
1017
+ }
877
1018
  return {
878
1019
  toRuntime: [this.internalRequest("context", sessionId)],
879
1020
  toClient: [
@@ -898,12 +1039,25 @@ class GrokAcpCompatibilityProxy {
898
1039
  const legacy = legacyOptions(result);
899
1040
  const legacyModels = legacy.filter((option) => option.category === "model");
900
1041
  const legacyEfforts = legacy.filter((option) => option.category === "mode");
1042
+ const hasRuntimeConfigOptions = Array.isArray(result.configOptions);
1043
+ const runtimeConfigOptions = standardConfigOptions(result);
1044
+ const runtimeModelOption = configOption(runtimeConfigOptions, "model");
1045
+ const runtimeReasoningOption = configOption(runtimeConfigOptions, "reasoning_effort");
901
1046
  const availableModels = result.models?.availableModels ?? [];
902
- const currentModelId = result.models?.currentModelId ?? legacyModels.find((option) => option.selected)?.id ?? old?.currentModelId;
1047
+ const currentModelId = result.models?.currentModelId ?? runtimeModelOption?.currentValue ?? legacyModels.find((option) => option.selected)?.id ?? old?.currentModelId;
903
1048
  const currentModel = availableModels.find((model) => model.modelId === currentModelId);
904
- const metadataEfforts = readReasoningEfforts(currentModel);
905
- const reasoningEfforts = metadataEfforts.length ? metadataEfforts : legacyEfforts.map((option) => option.id);
906
- return {
1049
+ const metadataReasoningOptions = readReasoningOptions(currentModel);
1050
+ const runtimeReasoningOptions = reasoningOptionsFromConfig(runtimeReasoningOption);
1051
+ const legacyReasoningOptions = legacyEfforts.map((option) => ({
1052
+ id: option.id,
1053
+ value: option.id,
1054
+ name: option.label ?? optionName(option.id),
1055
+ description: option.description ?? null,
1056
+ default: false
1057
+ }));
1058
+ const reasoningOptions = metadataReasoningOptions.length ? metadataReasoningOptions : runtimeReasoningOptions.length ? runtimeReasoningOptions : legacyReasoningOptions;
1059
+ const reportedReasoningEffort = runtimeReasoningOption?.currentValue ?? legacyEfforts.find((option) => option.selected)?.id ?? currentModel?._meta?.reasoningEffort ?? currentModel?._meta?.reasoning_effort;
1060
+ const state = {
907
1061
  sessionId,
908
1062
  clientIdentifier: clientIdentifier ?? old?.clientIdentifier,
909
1063
  interactionMode: INTERACTION_FROM_RUNTIME[result.modes?.currentModeId] ?? old?.interactionMode ?? "agent",
@@ -913,11 +1067,15 @@ class GrokAcpCompatibilityProxy {
913
1067
  name: option.label,
914
1068
  description: option.description
915
1069
  })),
916
- reasoningEfforts,
917
- reasoningEffort: legacyEfforts.find((option) => option.selected)?.id ?? old?.reasoningEffort ?? reasoningEfforts[0],
1070
+ runtimeConfigOptions: hasRuntimeConfigOptions ? runtimeConfigOptions : old?.runtimeConfigOptions ?? [],
1071
+ reasoningOptions,
1072
+ reasoningEfforts: reasoningOptions.map((option) => option.id),
1073
+ reasoningEffort: reasoningSelector(reasoningOptions, reportedReasoningEffort) ?? (typeof reportedReasoningEffort === "string" ? reportedReasoningEffort : void 0) ?? old?.reasoningEffort ?? reasoningOptions.find((option) => option.default)?.id ?? reasoningOptions[0]?.id,
918
1074
  usageAccumulator: old?.usageAccumulator ?? new SessionUsageAccumulator(),
919
1075
  usageRefreshPromptIds: old?.usageRefreshPromptIds ?? /* @__PURE__ */ new Set()
920
1076
  };
1077
+ if (hasRuntimeConfigOptions) this.applyRuntimeConfigOptions(state, runtimeConfigOptions);
1078
+ return state;
921
1079
  }
922
1080
  configOptions(state) {
923
1081
  const permissions = [
@@ -943,7 +1101,53 @@ class GrokAcpCompatibilityProxy {
943
1101
  "_permission"
944
1102
  )
945
1103
  ];
946
- if (state.currentModelId) {
1104
+ const runtimeOptions = state.runtimeConfigOptions ?? [];
1105
+ const emittedRuntimeIds = /* @__PURE__ */ new Set();
1106
+ for (const runtimeOption of runtimeOptions) {
1107
+ if (runtimeOption.id === "model") {
1108
+ emittedRuntimeIds.add(runtimeOption.id);
1109
+ options.push({
1110
+ ...runtimeOption,
1111
+ ...state.currentModelId ? { currentValue: state.currentModelId } : {},
1112
+ ...state.models.length ? {
1113
+ options: state.models.map((model) => {
1114
+ const published = runtimeOption.options?.find(
1115
+ (option) => option?.value === model.modelId
1116
+ );
1117
+ return {
1118
+ ...published,
1119
+ value: model.modelId,
1120
+ name: published?.name || model.name || model.modelId,
1121
+ description: published?.description ?? model.description ?? null
1122
+ };
1123
+ })
1124
+ } : {}
1125
+ });
1126
+ } else if (runtimeOption.id === "reasoning_effort" && state.reasoningOptions.length && state.reasoningEffort) {
1127
+ emittedRuntimeIds.add(runtimeOption.id);
1128
+ options.push({
1129
+ ...runtimeOption,
1130
+ ...state.reasoningEffort ? { currentValue: state.reasoningEffort } : {},
1131
+ ...state.reasoningOptions.length ? {
1132
+ options: state.reasoningOptions.map((option) => {
1133
+ const published = runtimeOption.options?.find(
1134
+ (candidate) => candidate?.value === option.id
1135
+ );
1136
+ return {
1137
+ ...published,
1138
+ value: option.id,
1139
+ name: published?.name || option.name || optionName(option.id),
1140
+ description: published?.description ?? option.description ?? null
1141
+ };
1142
+ })
1143
+ } : {}
1144
+ });
1145
+ } else if (runtimeOption.id !== "model" && runtimeOption.id !== "reasoning_effort") {
1146
+ emittedRuntimeIds.add(runtimeOption.id);
1147
+ options.push(runtimeOption);
1148
+ }
1149
+ }
1150
+ if (state.currentModelId && !emittedRuntimeIds.has("model")) {
947
1151
  options.push(
948
1152
  selectOption(
949
1153
  "model",
@@ -959,17 +1163,17 @@ class GrokAcpCompatibilityProxy {
959
1163
  )
960
1164
  );
961
1165
  }
962
- if (state.reasoningEfforts.length && state.reasoningEffort) {
1166
+ if (state.reasoningOptions.length && state.reasoningEffort && !emittedRuntimeIds.has("reasoning_effort")) {
963
1167
  options.push(
964
1168
  selectOption(
965
1169
  "reasoning_effort",
966
1170
  "Reasoning Effort",
967
1171
  "Controls how much reasoning the model performs",
968
1172
  state.reasoningEffort,
969
- state.reasoningEfforts.map((value) => ({
970
- value,
971
- name: optionName(value),
972
- description: null
1173
+ state.reasoningOptions.map((option) => ({
1174
+ value: option.id,
1175
+ name: option.name,
1176
+ description: option.description
973
1177
  })),
974
1178
  "thought_level"
975
1179
  )