dsh-workbuddy-xdpool 1.2.0 → 1.4.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/lib/client.js CHANGED
@@ -275,6 +275,10 @@ window.__ModuleLoader__.load({
275
275
  .dsm-workbuddy-xdpool-auto-job-name{flex:0 0 72px;color:var(--dsw-alias-label-primary,#e8e8ea)}
276
276
  .dsm-workbuddy-xdpool-auto-job-when{flex:1 1 auto;font-variant-numeric:tabular-nums}
277
277
  .dsm-workbuddy-xdpool-auto-job-last{flex:0 0 auto;text-align:right;font-variant-numeric:tabular-nums}
278
+ /* The job detail wraps to its own full-width line: it is a list of reward
279
+ titles, which needs the whole row rather than a cramped right-hand slot. */
280
+ .dsm-workbuddy-xdpool-auto-job-detail{flex:1 1 100%;color:var(--dsw-alias-label-secondary,#b8bcc4);line-height:1.5;word-break:break-word}
281
+ .dsm-workbuddy-xdpool-auto-job-note{flex:0 0 auto;color:var(--dsw-alias-label-secondary,#b8bcc4)}
278
282
  .dsm-workbuddy-xdpool-auto-run{flex:0 0 auto;padding:2px 8px;font-size:10px;line-height:16px}
279
283
  /* Reserved credits: one inline number field per account. */
280
284
  .dsm-workbuddy-xdpool-reserve{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:8px;padding-top:8px;border-top:1px dashed var(--dsw-alias-border-l2,#36373b);font-size:11px;color:var(--dsw-alias-label-dimmed,#8a97b5)}
@@ -362,10 +366,11 @@ window.__ModuleLoader__.load({
362
366
  const AUTOMATION_POLL_MS = 2e3;
363
367
  const AUTOMATION_POLL_ATTEMPTS = 90;
364
368
  const AUTOMATION_JOBS = [
369
+ "checkin",
365
370
  "report",
366
371
  "tasks",
367
- "checkin",
368
- "streak"
372
+ "streak",
373
+ "travel"
369
374
  ];
370
375
  /** Read one job's configured hours off the status document. */
371
376
  function automationHours(status, kind) {
@@ -376,6 +381,7 @@ window.__ModuleLoader__.load({
376
381
  case "tasks": return automation.taskHours;
377
382
  case "checkin": return automation.checkinHours;
378
383
  case "streak": return automation.streakHours;
384
+ case "travel": return automation.travelHours;
379
385
  }
380
386
  }
381
387
  /** Read one job's last-run record off the status document. */
@@ -1132,6 +1138,14 @@ window.__ModuleLoader__.load({
1132
1138
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1133
1139
  className: "dsm-workbuddy-xdpool-auto-job-last",
1134
1140
  children: job?.lastRunDate === void 0 ? t?.("row.autoNever") ?? "not run yet" : `${job.lastRunDate} · ${job.ok}${job.failed > 0 ? `/${job.failed}` : ""}`
1141
+ }),
1142
+ job?.progress === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1143
+ className: "dsm-workbuddy-xdpool-auto-job-note",
1144
+ children: job.progress
1145
+ }),
1146
+ job?.detail === void 0 || job.detail.length === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1147
+ className: "dsm-workbuddy-xdpool-auto-job-detail",
1148
+ children: job.detail.join(" · ")
1135
1149
  })
1136
1150
  ]
1137
1151
  }, kind);
@@ -1767,13 +1781,14 @@ window.__ModuleLoader__.load({
1767
1781
  "row.autoOn": "On",
1768
1782
  "row.autoOff": "Off",
1769
1783
  "row.autoBusy": "Saving…",
1770
- "row.autoHintOn": "Reports activity, claims task rewards and checks in once a day.",
1784
+ "row.autoHintOn": "Checks in, reports activity, claims task and streak rewards, and runs the buddy trip — every day.",
1771
1785
  "row.autoHintOff": "Off: no background requests are made for you.",
1772
1786
  "row.autoJob_report": "Activity report",
1773
1787
  "row.autoJob_tasks": "Task rewards",
1774
1788
  "row.autoJob_checkin": "Daily check-in",
1775
1789
  "row.autoJob_streak": "Streak bonus",
1776
- "row.autoHourNone": "not scheduled",
1790
+ "row.autoJob_travel": "Buddy trip",
1791
+ "row.autoHourNone": "skipped today",
1777
1792
  "row.autoNever": "not run yet",
1778
1793
  "row.autoRun": "Run now",
1779
1794
  "row.autoRunning": "Running…",
@@ -1895,14 +1910,15 @@ window.__ModuleLoader__.load({
1895
1910
  "row.autoOn": "已开启",
1896
1911
  "row.autoOff": "已关闭",
1897
1912
  "row.autoBusy": "保存中…",
1898
- "row.autoHintOn": "每天自动活跃上报、领取任务奖励并签到。",
1913
+ "row.autoHintOn": "每天自动签到、上报活跃、领取任务奖励与连登奖励,并照看猫猫旅行。",
1899
1914
  "row.autoHintOff": "已关闭:不会替你发起任何后台请求。",
1900
1915
  "row.autoJob_report": "活跃上报",
1901
1916
  "row.autoJob_tasks": "任务奖励",
1902
1917
  "row.autoJob_checkin": "每日签到",
1903
1918
  "row.autoJob_streak": "连登奖励",
1904
- "row.autoHourNone": "未排程",
1905
- "row.autoNever": "尚未执行",
1919
+ "row.autoJob_travel": "猫猫旅行",
1920
+ "row.autoHourNone": "当天不跑",
1921
+ "row.autoNever": "还没跑过",
1906
1922
  "row.autoRun": "立即运行",
1907
1923
  "row.autoRunning": "运行中…",
1908
1924
  "row.autoRan": "完成:{count} 个账号正常,{failed} 个失败",
package/lib/index.d.ts CHANGED
@@ -164,6 +164,32 @@ export declare function expertActualUseEvent(expert: MarketExpert, conversationI
164
164
  */
165
165
  export declare function expertChatEvents(expert: MarketExpert, conversationId: string, requestId: string): Record<string, unknown>[];
166
166
  //#endregion
167
+ //#region src/context-budget.d.ts
168
+ /**
169
+ * Context-window budgeting for the WorkBuddy shim.
170
+ *
171
+ * The upstream answers `context_length_exceeded` (business code 11115) when a
172
+ * request overruns the model's window. Rather than bouncing that back to the
173
+ * user as a dead turn, the shim compacts the conversation on the fly:
174
+ *
175
+ * 1. estimate the prompt cost locally (cheap, no round trip);
176
+ * 2. drop the oldest turns while keeping `system` + the newest exchange;
177
+ * 3. if that still overruns, ask the model itself to summarise the middle of
178
+ * the conversation and splice that summary back in as a system message.
179
+ *
180
+ * Everything here is pure and synchronous-free except `summarizeMessages`,
181
+ * which the caller drives through an injected chat function so this module
182
+ * stays testable without a network.
183
+ *
184
+ * @module dsh-workbuddy-xdpool/context-budget
185
+ */
186
+ /** One OpenAI chat message, narrowed to the fields we must preserve. */
187
+ interface ChatMessage {
188
+ role: string;
189
+ content: unknown;
190
+ [key: string]: unknown;
191
+ }
192
+ //#endregion
167
193
  //#region src/upstream.d.ts
168
194
  /** Upstream failure classes the shim maps onto distinct HTTP answers. */
169
195
  type UpstreamErrorKind = 'hard_credit' | 'soft_rate' | 'session_dead' | 'not_found' | 'server' | 'client';
@@ -388,6 +414,24 @@ export declare class WorkBuddyUpstreamClient {
388
414
  * business code 11128), and flatten `tool_choice` into its string form.
389
415
  */
390
416
  prepareChatBody(raw: string): string;
417
+ /**
418
+ * Parse a raw OpenAI chat body without normalising it.
419
+ *
420
+ * The compactor needs the message array as objects, while `chatStream` only
421
+ * accepts the serialised string form.
422
+ */
423
+ parseChatBody(raw: string): Record<string, unknown> | undefined;
424
+ /** Re-serialise `base` with a rewritten `messages` array, still normalised. */
425
+ buildChatBody(base: Record<string, unknown>, messages: readonly ChatMessage[]): string;
426
+ /**
427
+ * Run one NON-streaming completion and return the assistant text.
428
+ *
429
+ * Used only for internal compaction (summarising dropped turns). The chat
430
+ * endpoint itself always streams, so this reassembles the SSE frames into a
431
+ * single string. Throws on any failure: the compactor then falls back to
432
+ * plain truncation rather than failing the user's turn.
433
+ */
434
+ completeChat(credential: WorkBuddyCredential, prepared: string, signal?: AbortSignal): Promise<string>;
391
435
  /** Forward one chat completion. Never throws for upstream failures. */
392
436
  chatStream(credential: WorkBuddyCredential, prepared: string, signal?: AbortSignal): Promise<ChatStreamResult>;
393
437
  /** POST the token-refresh endpoint; the caller merges the outcome. */
@@ -1151,6 +1195,16 @@ interface SchedulerLogger {
1151
1195
  interface AutomationJobState {
1152
1196
  /** `YYYY-MM-DD` of the last completed run, or undefined if it never ran. */
1153
1197
  lastRunDate?: string;
1198
+ /**
1199
+ * The scheduled SLOT of the last run, as `YYYY-MM-DDTHH`.
1200
+ *
1201
+ * The tick de-duplicates on this rather than on the date: keying on the date
1202
+ * alone caps every job at one run a day, which is wrong for a job with two
1203
+ * time points — blocking the cat loop's second pass would leave the cat out
1204
+ * until tomorrow. Per slot a job runs once in each configured hour, while a
1205
+ * repeat tick inside the same hour is still refused.
1206
+ */
1207
+ lastRunSlot?: string;
1154
1208
  /** Epoch ms of the last completed run. */
1155
1209
  lastRunAtMs?: number;
1156
1210
  /** Accounts that completed without throwing. */
@@ -1164,6 +1218,23 @@ interface AutomationJobState {
1164
1218
  /** Tasks claimed by the task job on the last run. */
1165
1219
  claimed: number;
1166
1220
  /** Human-readable summary of the last run. */
1221
+ /**
1222
+ * What this run actually did, in the words of the task board.
1223
+ *
1224
+ * `message` is a count ("3 accounts, 5 tasks claimed"); this is the list a
1225
+ * person can check off — the reward titles the pass collected. A row showing
1226
+ * only a bare number cannot answer "did it do the thing I care about", which
1227
+ * is the question the panel exists to answer.
1228
+ */
1229
+ detail?: readonly string[];
1230
+ /**
1231
+ * A pending milestone worth naming, when there is one.
1232
+ *
1233
+ * Streak tiers are why this exists: every tier reads `locked` until enough
1234
+ * consecutive days accumulate, and "locked" on its own reads as "broken"
1235
+ * rather than "come back in four days".
1236
+ */
1237
+ progress?: string;
1167
1238
  message?: string;
1168
1239
  }
1169
1240
  /**
@@ -1794,6 +1865,15 @@ interface PoolWebAutomationJob {
1794
1865
  claimed: number;
1795
1866
  /** One-line summary of the last run. */
1796
1867
  message?: string;
1868
+ /**
1869
+ * What the last run actually did, in the words of the task board.
1870
+ *
1871
+ * `message` is a count; this is the list a person can check off, which is
1872
+ * what turns a row from "it ran" into "it did the things I care about".
1873
+ */
1874
+ detail?: readonly string[];
1875
+ /** A pending milestone worth naming, e.g. the next streak tier countdown. */
1876
+ progress?: string;
1797
1877
  }
1798
1878
  /**
1799
1879
  * Automation block on the status document.
@@ -1812,6 +1892,7 @@ interface PoolWebAutomation {
1812
1892
  reportHours: readonly number[];
1813
1893
  taskHours: readonly number[];
1814
1894
  streakHours: readonly number[];
1895
+ travelHours: readonly number[];
1815
1896
  jobs: {
1816
1897
  checkin: PoolWebAutomationJob;
1817
1898
  report: PoolWebAutomationJob;