@oh-my-pi/pi-coding-agent 15.11.6 → 15.11.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/dist/cli.js +114 -71
  3. package/dist/types/cli/bench-cli.d.ts +78 -0
  4. package/dist/types/commands/bench.d.ts +29 -0
  5. package/dist/types/config/model-resolver.d.ts +3 -2
  6. package/dist/types/config/settings-schema.d.ts +72 -0
  7. package/dist/types/edit/renderer.d.ts +1 -0
  8. package/dist/types/modes/components/oauth-selector.d.ts +10 -1
  9. package/dist/types/modes/components/settings-selector.d.ts +8 -1
  10. package/dist/types/modes/components/snapcompact-shape-preview.d.ts +31 -0
  11. package/dist/types/modes/components/tool-execution.d.ts +13 -9
  12. package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +3 -0
  13. package/dist/types/modes/setup-wizard/scenes/types.d.ts +10 -1
  14. package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +3 -0
  15. package/dist/types/session/snapcompact-inline.d.ts +2 -0
  16. package/dist/types/tools/bash.d.ts +2 -0
  17. package/dist/types/tools/eval-render.d.ts +1 -0
  18. package/dist/types/tools/renderers.d.ts +13 -0
  19. package/dist/types/tools/ssh.d.ts +1 -0
  20. package/package.json +11 -11
  21. package/src/cli/bench-cli.ts +437 -0
  22. package/src/cli-commands.ts +1 -0
  23. package/src/commands/bench.ts +42 -0
  24. package/src/config/model-registry.ts +52 -5
  25. package/src/config/model-resolver.ts +36 -5
  26. package/src/config/settings-schema.ts +92 -0
  27. package/src/edit/renderer.ts +5 -0
  28. package/src/hindsight/client.ts +26 -1
  29. package/src/hindsight/state.ts +6 -2
  30. package/src/internal-urls/docs-index.generated.ts +1 -1
  31. package/src/mcp/transports/stdio.ts +81 -7
  32. package/src/modes/components/oauth-selector.ts +67 -7
  33. package/src/modes/components/settings-selector.ts +27 -0
  34. package/src/modes/components/snapcompact-shape-preview-doc.md +11 -0
  35. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  36. package/src/modes/components/tool-execution.ts +18 -10
  37. package/src/modes/controllers/input-controller.ts +8 -6
  38. package/src/modes/controllers/selector-controller.ts +4 -2
  39. package/src/modes/interactive-mode.ts +24 -0
  40. package/src/modes/setup-wizard/index.ts +1 -0
  41. package/src/modes/setup-wizard/scenes/glyph.ts +24 -6
  42. package/src/modes/setup-wizard/scenes/providers.ts +36 -2
  43. package/src/modes/setup-wizard/scenes/sign-in.ts +10 -1
  44. package/src/modes/setup-wizard/scenes/theme.ts +28 -1
  45. package/src/modes/setup-wizard/scenes/types.ts +10 -1
  46. package/src/modes/setup-wizard/scenes/web-search.ts +22 -6
  47. package/src/modes/setup-wizard/wizard-overlay.ts +38 -1
  48. package/src/modes/utils/context-usage.ts +1 -1
  49. package/src/prompts/bench.md +7 -0
  50. package/src/sdk.ts +1 -0
  51. package/src/session/agent-session.ts +5 -0
  52. package/src/session/snapcompact-inline.ts +11 -19
  53. package/src/tools/bash.ts +3 -0
  54. package/src/tools/eval-render.ts +4 -0
  55. package/src/tools/renderers.ts +13 -0
  56. package/src/tools/ssh.ts +3 -0
@@ -1,4 +1,5 @@
1
1
  import { THINKING_EFFORTS } from "@oh-my-pi/pi-ai";
2
+ import { SHAPE_VARIANT_NAMES } from "@oh-my-pi/snapcompact";
2
3
  import { AUTO_THINKING, getConfiguredThinkingLevelMetadata, getThinkingLevelMetadata } from "../thinking";
3
4
  import {
4
5
  TINY_MODEL_DEVICE_DEFAULT,
@@ -1609,6 +1610,97 @@ export const SETTINGS_SCHEMA = {
1609
1610
  },
1610
1611
  },
1611
1612
 
1613
+ "snapcompact.shape": {
1614
+ type: "enum",
1615
+ values: ["auto", ...SHAPE_VARIANT_NAMES] as const,
1616
+ default: "auto",
1617
+ ui: {
1618
+ tab: "context",
1619
+ group: "Experimental",
1620
+ label: "Snapcompact Shape",
1621
+ description:
1622
+ "Frame shape snapcompact prints text with (compaction archive and inline imaging). Auto picks a shape tuned for the current model.",
1623
+ options: [
1624
+ {
1625
+ value: "auto",
1626
+ label: "Auto",
1627
+ description: "Picks a shape tuned for the current model, falling back to its provider family.",
1628
+ },
1629
+ {
1630
+ value: "8x8r-bw",
1631
+ label: "8x8 repeated, black",
1632
+ description:
1633
+ "unscii square cell, black ink, every line printed twice with the copy on a pale highlight band.",
1634
+ },
1635
+ {
1636
+ value: "8x8r-sent",
1637
+ label: "8x8 repeated, sentence hues",
1638
+ description: "Repeated grid with ink cycling six hues at sentence boundaries.",
1639
+ },
1640
+ {
1641
+ value: "8x8u-bw",
1642
+ label: "8x8, black",
1643
+ description: "Plain unscii square cell, single-printed lines, black ink.",
1644
+ },
1645
+ {
1646
+ value: "8x8u-sent",
1647
+ label: "8x8, sentence hues",
1648
+ description: "Plain unscii square cell with sentence-hue ink.",
1649
+ },
1650
+ {
1651
+ value: "6x6u-bw",
1652
+ label: "6x6 dense, black",
1653
+ description: "unscii squeezed to 6x6 — densest readable cell, fewest frames — in black ink.",
1654
+ },
1655
+ {
1656
+ value: "6x6u-sent",
1657
+ label: "6x6 dense, sentence hues",
1658
+ description: "Densest cell with sentence-hue ink.",
1659
+ },
1660
+ {
1661
+ value: "5x8-bw",
1662
+ label: "5x8 legacy, black",
1663
+ description: "Original X.org 5x8 glyphs on the 2576px frame, black ink.",
1664
+ },
1665
+ {
1666
+ value: "5x8-sent",
1667
+ label: "5x8 legacy, sentence hues",
1668
+ description: "The original snapcompact shape (pre-shape-table sessions rendered this).",
1669
+ },
1670
+ {
1671
+ value: "6x12-dim",
1672
+ label: "6x12, dimmed stopwords",
1673
+ description: "X.org 6x12 glyphs, black ink, function words dimmed gray.",
1674
+ },
1675
+ {
1676
+ value: "8x13-bw",
1677
+ label: "8x13, black",
1678
+ description: "X.org 8x13 glyphs, black ink.",
1679
+ },
1680
+ {
1681
+ value: "8on16-bw",
1682
+ label: "8x13 on 16px pitch, black",
1683
+ description: "8x13 glyphs on an 8x16 cell (extra leading), black ink.",
1684
+ },
1685
+ {
1686
+ value: "doc-8on16-bw",
1687
+ label: "Doc 8on16, black",
1688
+ description: "Two word-wrapped newspaper columns of 8x13 glyphs on a 16px pitch, black ink.",
1689
+ },
1690
+ {
1691
+ value: "doc-8on16-sent",
1692
+ label: "Doc 8on16, sentence hues",
1693
+ description: "Two-column doc layout with sentence-hue ink.",
1694
+ },
1695
+ {
1696
+ value: "doc-8on16-sent-dim",
1697
+ label: "Doc 8on16, sentence hues + dimmed stopwords",
1698
+ description: "Two-column doc layout, sentence-hue ink, function words dimmed gray.",
1699
+ },
1700
+ ],
1701
+ },
1702
+ },
1703
+
1612
1704
  // Branch summaries
1613
1705
  "branchSummary.enabled": {
1614
1706
  type: "boolean",
@@ -579,6 +579,11 @@ function wrapEditRendererLine(line: string, width: number): string[] {
579
579
 
580
580
  export const editToolRenderer = {
581
581
  mergeCallAndResult: true,
582
+ // Pending preview is a TAIL window of the streamed diff ("… N more lines
583
+ // above" + last rows); the result render re-anchors the block top-first, so
584
+ // committing the preview's settled head would strand a stale call-box
585
+ // fragment in native scrollback.
586
+ provisionalPendingPreview: true,
582
587
 
583
588
  renderCall(
584
589
  args: EditRenderArgs,
@@ -546,7 +546,7 @@ interface BuiltMemoryItem {
546
546
  function buildMemoryItem(item: MemoryItemInput): BuiltMemoryItem {
547
547
  const out: BuiltMemoryItem = { content: item.content };
548
548
  if (item.timestamp !== undefined) {
549
- out.timestamp = item.timestamp instanceof Date ? item.timestamp.toISOString() : item.timestamp;
549
+ out.timestamp = item.timestamp instanceof Date ? formatDateWithLocalOffset(item.timestamp) : item.timestamp;
550
550
  }
551
551
  if (item.context !== undefined) out.context = item.context;
552
552
  if (item.metadata !== undefined) out.metadata = item.metadata;
@@ -558,6 +558,31 @@ function buildMemoryItem(item: MemoryItemInput): BuiltMemoryItem {
558
558
  return out;
559
559
  }
560
560
 
561
+ function formatDateWithLocalOffset(date: Date): string {
562
+ const offsetMinutes = date.getTimezoneOffset();
563
+ const offsetSign = offsetMinutes <= 0 ? "+" : "-";
564
+ const absoluteOffset = Math.abs(offsetMinutes);
565
+ const offsetHours = Math.floor(absoluteOffset / 60);
566
+ const offsetRemainderMinutes = absoluteOffset % 60;
567
+ const milliseconds = date.getMilliseconds();
568
+ const millisecondsPart = milliseconds === 0 ? "" : `.${pad3(milliseconds)}`;
569
+ return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}T${pad2(
570
+ date.getHours(),
571
+ )}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}${millisecondsPart}${offsetSign}${pad2(
572
+ offsetHours,
573
+ )}:${pad2(offsetRemainderMinutes)}`;
574
+ }
575
+
576
+ function pad2(value: number): string {
577
+ return value < 10 ? `0${value}` : String(value);
578
+ }
579
+
580
+ function pad3(value: number): string {
581
+ if (value < 10) return `00${value}`;
582
+ if (value < 100) return `0${value}`;
583
+ return String(value);
584
+ }
585
+
561
586
  function buildQueryString(query: Record<string, unknown>): string {
562
587
  const params = new URLSearchParams();
563
588
  for (const [key, value] of Object.entries(query)) {
@@ -26,6 +26,7 @@ const RETAIN_FLUSH_INTERVAL_MS = 5_000;
26
26
  interface PendingRetainItem {
27
27
  content: string;
28
28
  context?: string;
29
+ timestamp: Date;
29
30
  }
30
31
 
31
32
  interface RecallOutcome {
@@ -84,7 +85,7 @@ export class HindsightRetainQueue {
84
85
  if (this.#closed) {
85
86
  throw new Error("Hindsight retain queue is closed.");
86
87
  }
87
- this.#items.push({ content, context });
88
+ this.#items.push({ content, context, timestamp: new Date() });
88
89
 
89
90
  if (this.#items.length >= RETAIN_FLUSH_BATCH_SIZE) {
90
91
  void this.flush();
@@ -154,6 +155,7 @@ export class HindsightRetainQueue {
154
155
  context: item.context ?? state.config.retainContext,
155
156
  metadata: { session_id: sessionId },
156
157
  tags: state.retainTags,
158
+ timestamp: item.timestamp,
157
159
  }));
158
160
  await state.client.retainBatch(state.bankId, batch, { async: true });
159
161
  if (state.config.debug) {
@@ -281,6 +283,7 @@ export class HindsightSessionState {
281
283
  }
282
284
 
283
285
  async retainSession(messages: HindsightMessage[]): Promise<void> {
286
+ const retainedAt = new Date();
284
287
  const retainFullWindow = this.config.retainMode === "full-session";
285
288
  let target: HindsightMessage[];
286
289
  let documentId: string;
@@ -291,7 +294,7 @@ export class HindsightSessionState {
291
294
  } else {
292
295
  const windowTurns = this.config.retainEveryNTurns + this.config.retainOverlapTurns;
293
296
  target = sliceLastTurnsByUserBoundary(messages, windowTurns);
294
- documentId = `${this.sessionId}-${Date.now()}`;
297
+ documentId = `${this.sessionId}-${retainedAt.getTime()}`;
295
298
  }
296
299
 
297
300
  const { transcript } = prepareRetentionTranscript(target, true);
@@ -303,6 +306,7 @@ export class HindsightSessionState {
303
306
  context: this.config.retainContext,
304
307
  metadata: { session_id: this.sessionId },
305
308
  tags: this.retainTags,
309
+ timestamp: retainedAt,
306
310
  async: true,
307
311
  });
308
312
  }