@cfio/cohort-sync 0.31.1 → 0.31.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4115,8 +4115,8 @@ function serializePaginatedPathAndArgs(udfPath, args, options) {
4115
4115
  });
4116
4116
  return result;
4117
4117
  }
4118
- function serializedQueryTokenIsPaginated(token) {
4119
- return JSON.parse(token).type === "paginated";
4118
+ function serializedQueryTokenIsPaginated(token2) {
4119
+ return JSON.parse(token2).type === "paginated";
4120
4120
  }
4121
4121
 
4122
4122
  // ../../node_modules/.pnpm/convex@1.33.0_patch_hash=l43bztwr6e2lbmpd6ao6hmcg24_react@19.2.1/node_modules/convex/dist/esm/browser/sync/local_state.js
@@ -5768,13 +5768,13 @@ function base64UrlDecode(str) {
5768
5768
  return atob(output);
5769
5769
  }
5770
5770
  }
5771
- function jwtDecode(token, options) {
5772
- if (typeof token !== "string") {
5771
+ function jwtDecode(token2, options) {
5772
+ if (typeof token2 !== "string") {
5773
5773
  throw new InvalidTokenError("Invalid token specified: must be a string");
5774
5774
  }
5775
5775
  options || (options = {});
5776
5776
  const pos = options.header === true ? 0 : 1;
5777
- const part = token.split(".")[pos];
5777
+ const part = token2.split(".")[pos];
5778
5778
  if (typeof part !== "string") {
5779
5779
  throw new InvalidTokenError(
5780
5780
  `Invalid token specified: missing part #${pos + 1}`
@@ -5831,19 +5831,19 @@ var AuthenticationManager = class {
5831
5831
  this.resetAuthState();
5832
5832
  this._logVerbose("pausing WS for auth token fetch");
5833
5833
  this.pauseSocket();
5834
- const token = await this.fetchTokenAndGuardAgainstRace(fetchToken, {
5834
+ const token2 = await this.fetchTokenAndGuardAgainstRace(fetchToken, {
5835
5835
  forceRefreshToken: false
5836
5836
  });
5837
- if (token.isFromOutdatedConfig) {
5837
+ if (token2.isFromOutdatedConfig) {
5838
5838
  return;
5839
5839
  }
5840
- if (token.value) {
5840
+ if (token2.value) {
5841
5841
  this.setAuthState({
5842
5842
  state: "waitingForServerConfirmationOfCachedToken",
5843
5843
  config: { fetchToken, onAuthChange: onChange },
5844
5844
  hasRetried: false
5845
5845
  });
5846
- this.authenticate(token.value);
5846
+ this.authenticate(token2.value);
5847
5847
  } else {
5848
5848
  this.setAuthState({
5849
5849
  state: "initialRefetch",
@@ -5921,21 +5921,21 @@ var AuthenticationManager = class {
5921
5921
  );
5922
5922
  }
5923
5923
  await this.stopSocket();
5924
- const token = await this.fetchTokenAndGuardAgainstRace(
5924
+ const token2 = await this.fetchTokenAndGuardAgainstRace(
5925
5925
  this.authState.config.fetchToken,
5926
5926
  {
5927
5927
  forceRefreshToken: true
5928
5928
  }
5929
5929
  );
5930
- if (token.isFromOutdatedConfig) {
5930
+ if (token2.isFromOutdatedConfig) {
5931
5931
  return;
5932
5932
  }
5933
- if (token.value && this.syncState.isNewAuth(token.value)) {
5934
- this.authenticate(token.value);
5933
+ if (token2.value && this.syncState.isNewAuth(token2.value)) {
5934
+ this.authenticate(token2.value);
5935
5935
  this.setAuthState({
5936
5936
  state: "waitingForServerConfirmationOfFreshToken",
5937
5937
  config: this.authState.config,
5938
- token: token.value,
5938
+ token: token2.value,
5939
5939
  hadAuth: this.authState.state === "notRefetching" || this.authState.state === "waitingForScheduledRefetch"
5940
5940
  });
5941
5941
  } else {
@@ -5955,24 +5955,24 @@ var AuthenticationManager = class {
5955
5955
  return;
5956
5956
  }
5957
5957
  this._logVerbose("refetching auth token");
5958
- const token = await this.fetchTokenAndGuardAgainstRace(
5958
+ const token2 = await this.fetchTokenAndGuardAgainstRace(
5959
5959
  this.authState.config.fetchToken,
5960
5960
  {
5961
5961
  forceRefreshToken: true
5962
5962
  }
5963
5963
  );
5964
- if (token.isFromOutdatedConfig) {
5964
+ if (token2.isFromOutdatedConfig) {
5965
5965
  return;
5966
5966
  }
5967
- if (token.value) {
5968
- if (this.syncState.isNewAuth(token.value)) {
5967
+ if (token2.value) {
5968
+ if (this.syncState.isNewAuth(token2.value)) {
5969
5969
  this.setAuthState({
5970
5970
  state: "waitingForServerConfirmationOfFreshToken",
5971
5971
  hadAuth: this.syncState.hasAuth(),
5972
- token: token.value,
5972
+ token: token2.value,
5973
5973
  config: this.authState.config
5974
5974
  });
5975
- this.authenticate(token.value);
5975
+ this.authenticate(token2.value);
5976
5976
  } else {
5977
5977
  this.setAuthState({
5978
5978
  state: "notRefetching",
@@ -5991,11 +5991,11 @@ var AuthenticationManager = class {
5991
5991
  );
5992
5992
  this.tryRestartSocket();
5993
5993
  }
5994
- scheduleTokenRefetch(token) {
5994
+ scheduleTokenRefetch(token2) {
5995
5995
  if (this.authState.state === "noAuth") {
5996
5996
  return;
5997
5997
  }
5998
- const decodedToken = this.decodeToken(token);
5998
+ const decodedToken = this.decodeToken(token2);
5999
5999
  if (!decodedToken) {
6000
6000
  this.logger.error(
6001
6001
  "Auth token is not a valid JWT, cannot refetch the token"
@@ -6046,14 +6046,14 @@ var AuthenticationManager = class {
6046
6046
  this._logVerbose(
6047
6047
  `fetching token with config version ${originalConfigVersion}`
6048
6048
  );
6049
- const token = await fetchToken(fetchArgs);
6049
+ const token2 = await fetchToken(fetchArgs);
6050
6050
  if (this.configVersion !== originalConfigVersion) {
6051
6051
  this._logVerbose(
6052
6052
  `stale config version, expected ${originalConfigVersion}, got ${this.configVersion}`
6053
6053
  );
6054
6054
  return { isFromOutdatedConfig: true };
6055
6055
  }
6056
- return { isFromOutdatedConfig: false, value: token };
6056
+ return { isFromOutdatedConfig: false, value: token2 };
6057
6057
  }
6058
6058
  stop() {
6059
6059
  this.resetAuthState();
@@ -6096,9 +6096,9 @@ var AuthenticationManager = class {
6096
6096
  }
6097
6097
  this.authState = newAuth;
6098
6098
  }
6099
- decodeToken(token) {
6099
+ decodeToken(token2) {
6100
6100
  try {
6101
- return jwtDecode(token);
6101
+ return jwtDecode(token2);
6102
6102
  } catch (e) {
6103
6103
  this._logVerbose(
6104
6104
  `Error decoding token: ${e instanceof Error ? e.message : "Unknown error"}`
@@ -6241,8 +6241,8 @@ var BaseConvexClient = class {
6241
6241
  this.authenticationManager = new AuthenticationManager(
6242
6242
  this.state,
6243
6243
  {
6244
- authenticate: (token) => {
6245
- const message = this.state.setAuth(token);
6244
+ authenticate: (token2) => {
6245
+ const message = this.state.setAuth(token2);
6246
6246
  this.webSocketManager.sendMessage(message);
6247
6247
  return message.baseVersion;
6248
6248
  },
@@ -6435,10 +6435,10 @@ var BaseConvexClient = class {
6435
6435
  new Set(completedRequests.keys())
6436
6436
  );
6437
6437
  this.handleTransition({
6438
- queries: changedQueryTokens.map((token) => {
6439
- const optimisticResult = this.optimisticQueryResults.rawQueryResult(token);
6438
+ queries: changedQueryTokens.map((token2) => {
6439
+ const optimisticResult = this.optimisticQueryResults.rawQueryResult(token2);
6440
6440
  return {
6441
- token,
6441
+ token: token2,
6442
6442
  modification: {
6443
6443
  kind: "Updated",
6444
6444
  result: optimisticResult
@@ -6701,10 +6701,10 @@ var BaseConvexClient = class {
6701
6701
  wrappedUpdate,
6702
6702
  requestId
6703
6703
  );
6704
- const changedQueries = changedQueryTokens.map((token) => {
6705
- const localResult = this.localQueryResultByToken(token);
6704
+ const changedQueries = changedQueryTokens.map((token2) => {
6705
+ const localResult = this.localQueryResultByToken(token2);
6706
6706
  return {
6707
- token,
6707
+ token: token2,
6708
6708
  modification: {
6709
6709
  kind: "Updated",
6710
6710
  result: localResult === void 0 ? void 0 : {
@@ -6888,22 +6888,22 @@ var PaginatedQueryClient = class {
6888
6888
  */
6889
6889
  subscribe(name, args, options) {
6890
6890
  const canonicalizedUdfPath = canonicalizeUdfPath(name);
6891
- const token = serializePaginatedPathAndArgs(
6891
+ const token2 = serializePaginatedPathAndArgs(
6892
6892
  canonicalizedUdfPath,
6893
6893
  args,
6894
6894
  options
6895
6895
  );
6896
- const unsubscribe = () => this.removePaginatedQuerySubscriber(token);
6897
- const existingEntry = this.paginatedQuerySet.get(token);
6896
+ const unsubscribe = () => this.removePaginatedQuerySubscriber(token2);
6897
+ const existingEntry = this.paginatedQuerySet.get(token2);
6898
6898
  if (existingEntry) {
6899
6899
  existingEntry.numSubscribers += 1;
6900
6900
  return {
6901
- paginatedQueryToken: token,
6901
+ paginatedQueryToken: token2,
6902
6902
  unsubscribe
6903
6903
  };
6904
6904
  }
6905
- this.paginatedQuerySet.set(token, {
6906
- token,
6905
+ this.paginatedQuerySet.set(token2, {
6906
+ token: token2,
6907
6907
  canonicalizedUdfPath,
6908
6908
  args,
6909
6909
  numSubscribers: 1,
@@ -6915,9 +6915,9 @@ var PaginatedQueryClient = class {
6915
6915
  skip: false,
6916
6916
  id: options.id
6917
6917
  });
6918
- this.addPageToPaginatedQuery(token, null, options.initialNumItems);
6918
+ this.addPageToPaginatedQuery(token2, null, options.initialNumItems);
6919
6919
  return {
6920
- paginatedQueryToken: token,
6920
+ paginatedQueryToken: token2,
6921
6921
  unsubscribe
6922
6922
  };
6923
6923
  }
@@ -6928,18 +6928,18 @@ var PaginatedQueryClient = class {
6928
6928
  */
6929
6929
  localQueryResult(name, args, options) {
6930
6930
  const canonicalizedUdfPath = canonicalizeUdfPath(name);
6931
- const token = serializePaginatedPathAndArgs(
6931
+ const token2 = serializePaginatedPathAndArgs(
6932
6932
  canonicalizedUdfPath,
6933
6933
  args,
6934
6934
  options
6935
6935
  );
6936
- return this.localQueryResultByToken(token);
6936
+ return this.localQueryResultByToken(token2);
6937
6937
  }
6938
6938
  /**
6939
6939
  * @internal
6940
6940
  */
6941
- localQueryResultByToken(token) {
6942
- const paginatedQuery = this.paginatedQuerySet.get(token);
6941
+ localQueryResultByToken(token2) {
6942
+ const paginatedQuery = this.paginatedQuerySet.get(token2);
6943
6943
  if (!paginatedQuery) {
6944
6944
  return void 0;
6945
6945
  }
@@ -6949,7 +6949,7 @@ var PaginatedQueryClient = class {
6949
6949
  results: [],
6950
6950
  status: "LoadingFirstPage",
6951
6951
  loadMore: (numItems) => {
6952
- return this.loadMoreOfPaginatedQuery(token, numItems);
6952
+ return this.loadMoreOfPaginatedQuery(token2, numItems);
6953
6953
  }
6954
6954
  };
6955
6955
  }
@@ -6979,7 +6979,7 @@ var PaginatedQueryClient = class {
6979
6979
  results: allResults,
6980
6980
  status,
6981
6981
  loadMore: (numItems) => {
6982
- return this.loadMoreOfPaginatedQuery(token, numItems);
6982
+ return this.loadMoreOfPaginatedQuery(token2, numItems);
6983
6983
  }
6984
6984
  };
6985
6985
  }
@@ -6990,13 +6990,13 @@ var PaginatedQueryClient = class {
6990
6990
  if (changed.length > 0) {
6991
6991
  this.processPaginatedQuerySplits(
6992
6992
  changed,
6993
- (token) => this.client.localQueryResultByToken(token)
6993
+ (token2) => this.client.localQueryResultByToken(token2)
6994
6994
  );
6995
- paginatedQueries = changed.map((token) => ({
6996
- token,
6995
+ paginatedQueries = changed.map((token2) => ({
6996
+ token: token2,
6997
6997
  modification: {
6998
6998
  kind: "Updated",
6999
- result: this.localQueryResultByToken(token)
6999
+ result: this.localQueryResultByToken(token2)
7000
7000
  }
7001
7001
  }));
7002
7002
  }
@@ -7017,9 +7017,9 @@ var PaginatedQueryClient = class {
7017
7017
  *
7018
7018
  * @internal
7019
7019
  */
7020
- loadMoreOfPaginatedQuery(token, numItems) {
7021
- this.mustGetPaginatedQuery(token);
7022
- const lastPageToken = this.queryTokenForLastPageOfPaginatedQuery(token);
7020
+ loadMoreOfPaginatedQuery(token2, numItems) {
7021
+ this.mustGetPaginatedQuery(token2);
7022
+ const lastPageToken = this.queryTokenForLastPageOfPaginatedQuery(token2);
7023
7023
  const lastPageResult = this.client.localQueryResultByToken(lastPageToken);
7024
7024
  if (!lastPageResult) {
7025
7025
  return false;
@@ -7029,7 +7029,7 @@ var PaginatedQueryClient = class {
7029
7029
  return false;
7030
7030
  }
7031
7031
  this.addPageToPaginatedQuery(
7032
- token,
7032
+ token2,
7033
7033
  paginationResult.continueCursor,
7034
7034
  numItems
7035
7035
  );
@@ -7039,10 +7039,10 @@ var PaginatedQueryClient = class {
7039
7039
  queries: [],
7040
7040
  paginatedQueries: [
7041
7041
  {
7042
- token,
7042
+ token: token2,
7043
7043
  modification: {
7044
7044
  kind: "Updated",
7045
- result: this.localQueryResultByToken(token)
7045
+ result: this.localQueryResultByToken(token2)
7046
7046
  }
7047
7047
  }
7048
7048
  ]
@@ -7149,8 +7149,8 @@ var PaginatedQueryClient = class {
7149
7149
  /**
7150
7150
  * @internal
7151
7151
  */
7152
- addPageToPaginatedQuery(token, continueCursor, numItems) {
7153
- const paginatedQuery = this.mustGetPaginatedQuery(token);
7152
+ addPageToPaginatedQuery(token2, continueCursor, numItems) {
7153
+ const paginatedQuery = this.mustGetPaginatedQuery(token2);
7154
7154
  const pageKey = paginatedQuery.nextPageKey++;
7155
7155
  const paginationOpts = {
7156
7156
  cursor: continueCursor,
@@ -7169,8 +7169,8 @@ var PaginatedQueryClient = class {
7169
7169
  paginatedQuery.pageKeyToQuery.set(pageKey, subscription);
7170
7170
  return subscription;
7171
7171
  }
7172
- removePaginatedQuerySubscriber(token) {
7173
- const paginatedQuery = this.paginatedQuerySet.get(token);
7172
+ removePaginatedQuerySubscriber(token2) {
7173
+ const paginatedQuery = this.paginatedQuerySet.get(token2);
7174
7174
  if (!paginatedQuery) {
7175
7175
  return;
7176
7176
  }
@@ -7181,7 +7181,7 @@ var PaginatedQueryClient = class {
7181
7181
  for (const subscription of paginatedQuery.pageKeyToQuery.values()) {
7182
7182
  subscription.unsubscribe();
7183
7183
  }
7184
- this.paginatedQuerySet.delete(token);
7184
+ this.paginatedQuerySet.delete(token2);
7185
7185
  }
7186
7186
  completePaginatedQuerySplit(paginatedQuery, pageKey, splitKey1, splitKey2) {
7187
7187
  const originalQuery = paginatedQuery.pageKeyToQuery.get(pageKey);
@@ -7202,18 +7202,18 @@ var PaginatedQueryClient = class {
7202
7202
  (sub) => sub.queryToken
7203
7203
  );
7204
7204
  }
7205
- queryTokenForLastPageOfPaginatedQuery(token) {
7206
- const paginatedQuery = this.mustGetPaginatedQuery(token);
7205
+ queryTokenForLastPageOfPaginatedQuery(token2) {
7206
+ const paginatedQuery = this.mustGetPaginatedQuery(token2);
7207
7207
  const lastPageKey = paginatedQuery.pageKeys[paginatedQuery.pageKeys.length - 1];
7208
7208
  if (lastPageKey === void 0) {
7209
- throw new Error(`No pages for paginated query ${token}`);
7209
+ throw new Error(`No pages for paginated query ${token2}`);
7210
7210
  }
7211
7211
  return paginatedQuery.pageKeyToQuery.get(lastPageKey).queryToken;
7212
7212
  }
7213
- mustGetPaginatedQuery(token) {
7214
- const paginatedQuery = this.paginatedQuerySet.get(token);
7213
+ mustGetPaginatedQuery(token2) {
7214
+ const paginatedQuery = this.paginatedQuerySet.get(token2);
7215
7215
  if (!paginatedQuery) {
7216
- throw new Error("paginated query no longer exists for token " + token);
7216
+ throw new Error("paginated query no longer exists for token " + token2);
7217
7217
  }
7218
7218
  return paginatedQuery;
7219
7219
  }
@@ -7483,12 +7483,12 @@ var ConvexClient = class {
7483
7483
  /**
7484
7484
  * @internal
7485
7485
  */
7486
- setAdminAuth(token, identity) {
7486
+ setAdminAuth(token2, identity) {
7487
7487
  if (this.closed) {
7488
7488
  throw new Error("ConvexClient has already been closed.");
7489
7489
  }
7490
7490
  if (this.disabled) return;
7491
- this.client.setAdminAuth(token, identity);
7491
+ this.client.setAdminAuth(token2, identity);
7492
7492
  }
7493
7493
  /**
7494
7494
  * @internal
@@ -10082,16 +10082,16 @@ var require_extension = __commonJS({
10082
10082
  throw new SyntaxError("Unexpected end of input");
10083
10083
  }
10084
10084
  if (end === -1) end = i;
10085
- const token = header.slice(start, end);
10085
+ const token2 = header.slice(start, end);
10086
10086
  if (extensionName === void 0) {
10087
- push(offers, token, params);
10087
+ push(offers, token2, params);
10088
10088
  } else {
10089
10089
  if (paramName === void 0) {
10090
- push(params, token, true);
10090
+ push(params, token2, true);
10091
10091
  } else if (mustUnescape) {
10092
- push(params, paramName, token.replace(/\\/g, ""));
10092
+ push(params, paramName, token2.replace(/\\/g, ""));
10093
10093
  } else {
10094
- push(params, paramName, token);
10094
+ push(params, paramName, token2);
10095
10095
  }
10096
10096
  push(offers, extensionName, params);
10097
10097
  }
@@ -11923,6 +11923,34 @@ function isUnauthorizedError(err) {
11923
11923
  if (!data || typeof data !== "object") return false;
11924
11924
  return data.code === "UNAUTHORIZED";
11925
11925
  }
11926
+ function isRecord(value) {
11927
+ return typeof value === "object" && value !== null;
11928
+ }
11929
+ function appErrorMessageFromData(data) {
11930
+ if (!isRecord(data)) return null;
11931
+ return typeof data.message === "string" ? data.message : null;
11932
+ }
11933
+ function getConvexAppErrorMessage(err) {
11934
+ if (err instanceof ConvexError) {
11935
+ const message = appErrorMessageFromData(err.data);
11936
+ if (message) return message;
11937
+ }
11938
+ if (isRecord(err)) {
11939
+ const message = appErrorMessageFromData(err.data);
11940
+ if (message) return message;
11941
+ }
11942
+ if (err instanceof Error) {
11943
+ const prefix = "Uncaught ConvexError: ";
11944
+ if (err.message.startsWith(prefix)) {
11945
+ try {
11946
+ return appErrorMessageFromData(JSON.parse(err.message.slice(prefix.length)));
11947
+ } catch {
11948
+ return null;
11949
+ }
11950
+ }
11951
+ }
11952
+ return null;
11953
+ }
11926
11954
  function tripAuthCircuit() {
11927
11955
  if (authCircuitOpen) return;
11928
11956
  authCircuitOpen = true;
@@ -12443,7 +12471,7 @@ var ALLOWED_METHODS = /* @__PURE__ */ new Set([
12443
12471
  // reload without minting an admin-scope key.
12444
12472
  "secrets.reload"
12445
12473
  ]);
12446
- function buildConnectFrame(id, token, pluginVersion, identity, nonce) {
12474
+ function buildConnectFrame(id, token2, pluginVersion, identity, nonce) {
12447
12475
  const signedAtMs = Date.now();
12448
12476
  const payload = buildDeviceAuthPayloadV3({
12449
12477
  deviceId: identity.deviceId,
@@ -12452,7 +12480,7 @@ function buildConnectFrame(id, token, pluginVersion, identity, nonce) {
12452
12480
  role: "operator",
12453
12481
  scopes: ["operator.read", "operator.write", "operator.admin"],
12454
12482
  signedAtMs,
12455
- token,
12483
+ token: token2,
12456
12484
  nonce,
12457
12485
  platform: process.platform,
12458
12486
  deviceFamily: null
@@ -12478,7 +12506,7 @@ function buildConnectFrame(id, token, pluginVersion, identity, nonce) {
12478
12506
  },
12479
12507
  role: "operator",
12480
12508
  scopes: ["operator.read", "operator.write", "operator.admin"],
12481
- auth: { token },
12509
+ auth: { token: token2 },
12482
12510
  device: {
12483
12511
  id: identity.deviceId,
12484
12512
  publicKey: identity.publicKeyPem,
@@ -12541,12 +12569,12 @@ var GatewayClient = class {
12541
12569
  * @param logger - RuntimeLogger from plugin SDK
12542
12570
  * @param pluginVersion - Version string for the connect frame userAgent
12543
12571
  */
12544
- constructor(port, token, logger, pluginVersion = "0.5.0") {
12572
+ constructor(port, token2, logger, pluginVersion = "0.5.0") {
12545
12573
  this.port = port;
12546
12574
  this.logger = logger;
12547
12575
  this.pluginVersion = pluginVersion;
12548
12576
  this.deviceIdentity = loadOrCreateDeviceIdentity();
12549
- this._getToken = () => token;
12577
+ this._getToken = () => token2;
12550
12578
  }
12551
12579
  /** Token accessor — closure over constructor param */
12552
12580
  _getToken;
@@ -13522,6 +13550,52 @@ function getToolRuntime() {
13522
13550
  };
13523
13551
  }
13524
13552
 
13553
+ // src/llm-usage.ts
13554
+ function token(value) {
13555
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
13556
+ }
13557
+ function objectValue(value) {
13558
+ return value !== null && typeof value === "object" ? value : {};
13559
+ }
13560
+ function normalizeLlmUsage(raw) {
13561
+ const usage = objectValue(raw);
13562
+ const promptDetails = objectValue(usage.prompt_tokens_details);
13563
+ const inputDetails = objectValue(usage.input_tokens_details);
13564
+ const inputTokens = token(usage.input) || token(usage.prompt_tokens) || token(usage.input_tokens);
13565
+ const outputTokens = token(usage.output) || token(usage.completion_tokens) || token(usage.output_tokens);
13566
+ const cachedInputTokens = token(usage.cacheRead) || token(promptDetails.cached_tokens) || token(inputDetails.cached_tokens);
13567
+ const cacheWriteTokens = token(usage.cacheWrite);
13568
+ return {
13569
+ inputTokens,
13570
+ outputTokens,
13571
+ cachedInputTokens,
13572
+ cacheWriteTokens,
13573
+ contextTokens: inputTokens + cachedInputTokens + cacheWriteTokens
13574
+ };
13575
+ }
13576
+
13577
+ // src/model-context.ts
13578
+ function bareModelId(model) {
13579
+ const lower = model.toLowerCase();
13580
+ const slash = lower.lastIndexOf("/");
13581
+ return slash >= 0 ? lower.slice(slash + 1) : lower;
13582
+ }
13583
+ function getModelContextLimit(model) {
13584
+ const m = bareModelId(model);
13585
+ if (m === "gpt-5.5" || m === "gpt-5.5-pro") return 1e6;
13586
+ if (m === "gpt-5.4" || m === "gpt-5.4-pro") return 105e4;
13587
+ if (m === "gpt-5.4-mini" || m === "gpt-5.4-nano") return 4e5;
13588
+ if (m.includes("opus") || m.includes("sonnet") || m.includes("haiku")) return 2e5;
13589
+ if (m.includes("gpt-4o")) return 128e3;
13590
+ if (m.includes("gpt-4-turbo") || m.includes("gpt-4-1")) return 128e3;
13591
+ if (m.includes("gpt-4")) return 8192;
13592
+ if (m.includes("o3") || m.includes("o4-mini")) return 2e5;
13593
+ if (m.includes("gemini-2")) return 1e6;
13594
+ if (m.includes("gemini")) return 128e3;
13595
+ if (m.includes("deepseek")) return 128e3;
13596
+ return 2e5;
13597
+ }
13598
+
13525
13599
  // src/hooks.ts
13526
13600
  var REDACT_KEYS = /* @__PURE__ */ new Set([
13527
13601
  "token",
@@ -13561,10 +13635,10 @@ function dumpCtx(ctx) {
13561
13635
  function dumpEvent(event) {
13562
13636
  return dumpCtx(event);
13563
13637
  }
13564
- var PLUGIN_VERSION = true ? "0.31.1" : "unknown";
13638
+ var PLUGIN_VERSION = true ? "0.31.3" : "unknown";
13565
13639
  function resolveGatewayToken(api) {
13566
- const token = api.config?.gateway?.auth?.token;
13567
- return typeof token === "string" ? token : null;
13640
+ const token2 = api.config?.gateway?.auth?.token;
13641
+ return typeof token2 === "string" ? token2 : null;
13568
13642
  }
13569
13643
  function registerCronEventHandlers(client2, cfg, resolveAgentName, cronTimestampTracker, logger) {
13570
13644
  if (client2.availableEvents.has("cron")) {
@@ -13662,8 +13736,8 @@ function loadSessionsFromDisk(tracker, stateFilePath, logger) {
13662
13736
  } catch {
13663
13737
  }
13664
13738
  }
13665
- function initGatewayClient(port, token, cfg, resolveAgentName, cronTimestampTracker, logger) {
13666
- const client2 = new GatewayClient(port, token, logger, PLUGIN_VERSION);
13739
+ function initGatewayClient(port, token2, cfg, resolveAgentName, cronTimestampTracker, logger) {
13740
+ const client2 = new GatewayClient(port, token2, logger, PLUGIN_VERSION);
13667
13741
  const onConnected = async () => {
13668
13742
  logger.debug(`cohort-sync: gateway client connected (methods=${client2.availableMethods.size}, events=${client2.availableEvents.size})`);
13669
13743
  logger.info(`cohort-sync: gateway client connected (methods=${client2.availableMethods.size}, events=${client2.availableEvents.size})`);
@@ -13748,12 +13822,12 @@ async function handleGatewayStart(event, state) {
13748
13822
  }
13749
13823
  logger.debug("cohort-sync: gateway start: bridge after seed", { bridge: Object.fromEntries(getChannelAgentBridge()) });
13750
13824
  state.gatewayPort = event.port;
13751
- const token = resolveGatewayToken(api);
13752
- if (token) {
13753
- state.gatewayToken = token;
13825
+ const token2 = resolveGatewayToken(api);
13826
+ if (token2) {
13827
+ state.gatewayToken = token2;
13754
13828
  logger.debug("cohort-sync: gateway client connecting", { port: event.port, hasToken: true });
13755
13829
  try {
13756
- const client2 = initGatewayClient(event.port, token, cfg, state.resolveAgentName, state.cronTimestampTracker, logger);
13830
+ const client2 = initGatewayClient(event.port, token2, cfg, state.resolveAgentName, state.cronTimestampTracker, logger);
13757
13831
  state.persistentGwClient = client2;
13758
13832
  state.gwClientInitialized = true;
13759
13833
  if (state.commandUnsubscriber) {
@@ -13983,8 +14057,7 @@ function registerHookHandlers(api, logger, getState) {
13983
14057
  failureKind: event.failureKind
13984
14058
  });
13985
14059
  try {
13986
- const agentId = ctx.agentId ?? "main";
13987
- const agentName = state.resolveAgentName(agentId);
14060
+ const agentName = resolveAgentFromContext(state, ctx);
13988
14061
  const entry = buildActivityEntry(agentName, "model_call_ended", {
13989
14062
  outcome: event.outcome,
13990
14063
  errorCategory: event.errorCategory,
@@ -14003,28 +14076,27 @@ function registerHookHandlers(api, logger, getState) {
14003
14076
  const state = getState();
14004
14077
  if (!state) return;
14005
14078
  const { cfg, tracker, logger: log } = state;
14006
- const usage = event.usage ?? {};
14007
- const contextTokens = (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
14079
+ const usage = normalizeLlmUsage(event.usage);
14008
14080
  const model = event.model ?? state.resolveModel(ctx.agentId ?? "main");
14009
14081
  const contextLimit = state.getModelContextLimit(model);
14010
14082
  const agentId = ctx.agentId ?? "main";
14011
14083
  const agentName = state.resolveAgentName(agentId);
14012
14084
  try {
14013
14085
  const sessionKey = ctx.sessionKey;
14086
+ if (sessionKey && !tracker.hasSession(agentName, sessionKey)) {
14087
+ tracker.addSession(agentName, sessionKey);
14088
+ log.info(`cohort-sync: inferred session for ${agentName} from llm_output (${sessionKey})`);
14089
+ }
14014
14090
  tracker.updateFromLlmOutput(agentName, sessionKey, {
14015
14091
  model,
14016
- tokensIn: usage.input ?? 0,
14017
- tokensOut: usage.output ?? 0,
14018
- cacheReadTokens: usage.cacheRead ?? 0,
14019
- cacheWriteTokens: usage.cacheWrite ?? 0,
14020
- contextTokens,
14092
+ tokensIn: usage.inputTokens,
14093
+ tokensOut: usage.outputTokens,
14094
+ cacheReadTokens: usage.cachedInputTokens,
14095
+ cacheWriteTokens: usage.cacheWriteTokens,
14096
+ contextTokens: usage.contextTokens,
14021
14097
  contextLimit
14022
14098
  });
14023
14099
  tracker.updateSessionKey(agentName, sessionKey);
14024
- if (sessionKey && !tracker.hasSession(agentName, sessionKey)) {
14025
- tracker.addSession(agentName, sessionKey);
14026
- log.info(`cohort-sync: inferred session for ${agentName} from llm_output (${sessionKey})`);
14027
- }
14028
14100
  if (sessionKey) {
14029
14101
  tracker.setSessionAgent(sessionKey, agentName);
14030
14102
  }
@@ -14386,17 +14458,8 @@ function initializeHookState(api, cfg) {
14386
14458
  if (m && typeof m === "object" && "primary" in m) return String(m.primary);
14387
14459
  return "unknown";
14388
14460
  }
14389
- function getModelContextLimit(model) {
14390
- const m = model.toLowerCase();
14391
- if (m.includes("opus") || m.includes("sonnet") || m.includes("haiku")) return 2e5;
14392
- if (m.includes("gpt-4o")) return 128e3;
14393
- if (m.includes("gpt-4-turbo") || m.includes("gpt-4-1")) return 128e3;
14394
- if (m.includes("gpt-4")) return 8192;
14395
- if (m.includes("o3") || m.includes("o4-mini")) return 2e5;
14396
- if (m.includes("gemini-2")) return 1e6;
14397
- if (m.includes("gemini")) return 128e3;
14398
- if (m.includes("deepseek")) return 128e3;
14399
- return 2e5;
14461
+ function getModelContextLimit2(model) {
14462
+ return getModelContextLimit(model);
14400
14463
  }
14401
14464
  const cronStorePath = api.config?.cron?.store ?? path2.join(os2.homedir(), ".openclaw", "cron", "jobs.json");
14402
14465
  const activityBatch = new MicroBatch({
@@ -14457,7 +14520,7 @@ function initializeHookState(api, cfg) {
14457
14520
  config,
14458
14521
  resolveAgentName,
14459
14522
  resolveModel,
14460
- getModelContextLimit,
14523
+ getModelContextLimit: getModelContextLimit2,
14461
14524
  activityBatch,
14462
14525
  cronStorePath,
14463
14526
  stateFilePath,
@@ -14621,6 +14684,21 @@ var plugin = definePluginEntry({
14621
14684
  content: params.comment,
14622
14685
  noReply: params.no_reply ?? false
14623
14686
  });
14687
+ if ("rejected" in result && result.rejected) {
14688
+ if (result.reason === "AGENT_COMMENTS_LOCKED") {
14689
+ return textResult(
14690
+ `Cannot comment on task #${params.task_number}.
14691
+ Reason: ${result.message}
14692
+ Do not re-attempt unless a human unlocks comments.`,
14693
+ result
14694
+ );
14695
+ }
14696
+ return textResult(
14697
+ `Cannot comment on task #${params.task_number}.
14698
+ Reason: ${result.message}`,
14699
+ result
14700
+ );
14701
+ }
14624
14702
  const lines = [`Comment posted on task #${params.task_number}.`];
14625
14703
  if (result.stats) {
14626
14704
  lines.push("");
@@ -14631,7 +14709,10 @@ var plugin = definePluginEntry({
14631
14709
  }
14632
14710
  return textResult(lines.join("\n"), result);
14633
14711
  } catch (err) {
14634
- const msg = err instanceof Error ? err.message : String(err);
14712
+ const msg = [
14713
+ getConvexAppErrorMessage(err),
14714
+ err instanceof Error ? err.message : String(err)
14715
+ ].filter(Boolean).join("\n");
14635
14716
  if (msg.includes("AGENT_COMMENTS_LOCKED")) {
14636
14717
  return textResult(`Cannot comment on task #${params.task_number}.
14637
14718
  Reason: Agent comments are locked on this task.
@@ -72,5 +72,5 @@
72
72
  }
73
73
  }
74
74
  },
75
- "version": "0.31.1"
75
+ "version": "0.31.3"
76
76
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfio/cohort-sync",
3
- "version": "0.31.1",
3
+ "version": "0.31.3",
4
4
  "description": "OpenClaw plugin — syncs agent telemetry, sessions, and activity to the Cohort dashboard",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfio/cohort-sync",
3
- "version": "0.31.1",
3
+ "version": "0.31.3",
4
4
  "description": "OpenClaw plugin — syncs agent telemetry, sessions, and activity to the Cohort dashboard",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.cohort.bot/gateway",