@oh-my-pi/pi-ai 17.1.8 → 17.2.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/types/auth-broker/server.d.ts +5 -0
  3. package/dist/types/auth-broker/types.d.ts +4 -0
  4. package/dist/types/auth-storage.d.ts +26 -1
  5. package/dist/types/error/classes.d.ts +5 -1
  6. package/dist/types/error/rate-limit.d.ts +5 -4
  7. package/dist/types/providers/anthropic-client.d.ts +13 -1
  8. package/dist/types/providers/anthropic.d.ts +9 -1
  9. package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
  10. package/dist/types/providers/cursor-pi-args.d.ts +99 -0
  11. package/dist/types/providers/cursor.d.ts +53 -3
  12. package/dist/types/providers/error-message.d.ts +2 -4
  13. package/dist/types/providers/openai-codex-responses.d.ts +10 -0
  14. package/dist/types/providers/openai-responses-wire.d.ts +8 -0
  15. package/dist/types/providers/openai-shared.d.ts +13 -1
  16. package/dist/types/registry/exa.d.ts +8 -0
  17. package/dist/types/registry/registry.d.ts +7 -1
  18. package/dist/types/registry/xai.d.ts +4 -1
  19. package/dist/types/stream.d.ts +2 -0
  20. package/dist/types/types.d.ts +101 -1
  21. package/dist/types/usage/umans.d.ts +2 -0
  22. package/dist/types/utils/block-symbols.d.ts +11 -0
  23. package/dist/types/utils/harmony-leak.d.ts +15 -7
  24. package/dist/types/utils/schema/normalize.d.ts +1 -0
  25. package/package.json +4 -4
  26. package/src/auth-broker/client.ts +5 -1
  27. package/src/auth-broker/server.ts +103 -9
  28. package/src/auth-broker/snapshot-cache.ts +12 -3
  29. package/src/auth-broker/types.ts +6 -0
  30. package/src/auth-storage.ts +439 -28
  31. package/src/error/classes.ts +98 -3
  32. package/src/error/flags.ts +6 -1
  33. package/src/error/rate-limit.ts +18 -12
  34. package/src/providers/amazon-bedrock.ts +3 -3
  35. package/src/providers/anthropic-client.ts +24 -2
  36. package/src/providers/anthropic.ts +31 -6
  37. package/src/providers/cursor/exec-modern.ts +495 -0
  38. package/src/providers/cursor/proto/agent.proto +1007 -0
  39. package/src/providers/cursor-pi-args.ts +135 -0
  40. package/src/providers/cursor.ts +1138 -66
  41. package/src/providers/devin.ts +2 -1
  42. package/src/providers/error-message.ts +3 -1
  43. package/src/providers/openai-codex-responses.ts +106 -26
  44. package/src/providers/openai-completions.ts +19 -4
  45. package/src/providers/openai-responses-wire.ts +8 -0
  46. package/src/providers/openai-responses.ts +12 -1
  47. package/src/providers/openai-shared.ts +75 -12
  48. package/src/registry/api-key-validation.ts +18 -34
  49. package/src/registry/exa.ts +19 -0
  50. package/src/registry/novita.ts +6 -3
  51. package/src/registry/registry.ts +3 -1
  52. package/src/registry/xai.ts +17 -1
  53. package/src/stream.ts +1 -2
  54. package/src/types.ts +115 -0
  55. package/src/usage/umans.ts +192 -0
  56. package/src/utils/block-symbols.ts +12 -0
  57. package/src/utils/harmony-leak.ts +32 -0
  58. package/src/utils/idle-iterator.ts +2 -2
  59. package/src/utils/schema/normalize.ts +140 -38
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Translate a Pi frame's args into the local tool kwargs that run it.
3
+ *
4
+ * Shared deliberately by three consumers: the provider synthesizes a display
5
+ * block from these, the coding-agent bridge executes with them, and the legacy
6
+ * pi shim performs the identical translation for the old wire. Separate
7
+ * hand-rolled copies drift, and the drift is invisible — the transcript shows
8
+ * one operation while a different one runs.
9
+ *
10
+ * Kept apart from `cursor/exec-modern.ts` on purpose: these are pure
11
+ * string/path functions with no protobuf coupling, while that module pulls in
12
+ * `@bufbuild/protobuf` and the generated `agent_pb` graph. The legacy shim is
13
+ * compiled into the bundled virtual module registry, so importing it from a
14
+ * nested path would drag the whole exec implementation in with it — and
15
+ * `./providers/*` is a single-segment wildcard export that cannot serve a
16
+ * nested specifier under bunfs (issue #3442).
17
+ *
18
+ * Every `optional int32` here is presence-sensitive: `0` is a supplied value,
19
+ * not "unset", so it must never be folded into a default.
20
+ */
21
+
22
+ import * as path from "node:path";
23
+
24
+ /**
25
+ * A `pi_read` range composed onto the path as `read`'s inline `:raw:N+K`
26
+ * selector.
27
+ *
28
+ * `read` exposes no range kwargs, so an uncomposed range reads the whole file.
29
+ * `offset` is a 1-indexed start clamped like the reference's
30
+ * `Math.max(0, offset - 1)` over 0-indexed lines; `limit` is a line count.
31
+ * `null` marks a present `limit: 0` — zero lines, which no selector expresses
32
+ * and which must not degrade into a whole-file read.
33
+ *
34
+ * The range is `raw` because a plain `:N+K` deliberately pads with one leading
35
+ * and three trailing context lines: helpful for a human reading a snippet,
36
+ * wrong for a caller that asked for exactly `limit` lines from `offset`. The
37
+ * wire result is an opaque `output` string, so the hashline and line-number
38
+ * gutter that `raw` also drops carry nothing the frame's contract needs.
39
+ * A range-free read keeps the ordinary form — whole-file reads want them.
40
+ */
41
+ export function piReadPath(readPath: string, offset?: number, limit?: number): string | null {
42
+ if (limit !== undefined && Math.floor(limit) <= 0) return null;
43
+ const start = offset !== undefined ? Math.max(1, Math.floor(offset)) : undefined;
44
+ const count = limit !== undefined ? Math.floor(limit) : undefined;
45
+ if (start === undefined && count === undefined) return readPath;
46
+ if (start === undefined) return `${readPath}:raw:1+${count}`;
47
+ return count === undefined ? `${readPath}:raw:${start}-` : `${readPath}:raw:${start}+${count}`;
48
+ }
49
+
50
+ /**
51
+ * The same range as {@link piReadPath}, rendered for a transcript block rather
52
+ * than for execution.
53
+ *
54
+ * Differs only at `limit: 0`, where `piReadPath` returns `null` because no
55
+ * selector reads zero lines and the frame is answered with empty output
56
+ * directly. The block still has to say so: falling back to the bare path there
57
+ * would record a whole-file read whose result is empty, which is the widest
58
+ * possible gap between what a rebuilt transcript shows and what happened.
59
+ * `+0` is never executed — it exists to be read.
60
+ */
61
+ export function piReadDisplayPath(readPath: string, offset?: number, limit?: number): string {
62
+ const composed = piReadPath(readPath, offset, limit);
63
+ if (composed !== null) return composed;
64
+ const start = offset !== undefined ? Math.max(1, Math.floor(offset)) : 1;
65
+ return `${readPath}:raw:${start}+0`;
66
+ }
67
+
68
+ /**
69
+ * A legacy `grep` frame's pagination `offset` as the local tool's file `skip`.
70
+ *
71
+ * `grep` paginates by file and reports "use skip=N for the next page" in that
72
+ * same unit, so the offset maps across directly. A present `0` means "start at
73
+ * the beginning", which is the unskipped search rather than a skip of zero.
74
+ *
75
+ * Shared because both the executing bridge and the provider's transcript
76
+ * synthesis need it: a block showing an unskipped search beside a result from
77
+ * a later file window misreports what was searched.
78
+ */
79
+ export function piGrepSkip(offset?: number): number | undefined {
80
+ return offset !== undefined && offset > 0 ? Math.floor(offset) : undefined;
81
+ }
82
+
83
+ /**
84
+ * Join a Pi frame's optional `path` with the `glob`/`pattern` it scopes.
85
+ *
86
+ * The local `grep`/`glob` tools take one combined path spec. An absolute
87
+ * pattern ignores the path, and an absent or `.` path leaves the pattern
88
+ * standing alone rather than building a `./`- or `//`-prefixed spec.
89
+ *
90
+ * Uses `node:path` rather than string surgery so Windows absolutes (`C:\…`,
91
+ * UNC) are recognised and separators stay normalized.
92
+ */
93
+ export function piJoinPath(basePath: string | undefined, pattern: string): string {
94
+ if (path.isAbsolute(pattern)) return pattern;
95
+ if (!basePath || basePath === ".") return pattern;
96
+ return path.join(basePath, pattern);
97
+ }
98
+
99
+ /**
100
+ * The path a `pi_ls` frame lists.
101
+ *
102
+ * The frame's `limit` is deliberately NOT mapped. It caps directory *entries*
103
+ * (the reference does a flat `readdir` and slices the entry array), while the
104
+ * local `read` tool renders a depth-2 tree with per-directory caps and elision
105
+ * summaries and applies a selector as a *rendered line* slice. Nested rows,
106
+ * headers and "N more" lines all count toward that slice, so `:1+K` would cap
107
+ * a different unit while looking honored — worse than leaving it unset, which
108
+ * at least reports the local listing's own truncation faithfully.
109
+ */
110
+ export function piLsPath(basePath: string | undefined): string {
111
+ return basePath || ".";
112
+ }
113
+
114
+ /** Escape a literal string so the regex-only local `grep` tool matches it verbatim. */
115
+ export function piEscapeRegexLiteral(value: string): string {
116
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
117
+ }
118
+
119
+ /** Clamp a present `optional int32` result cap the way the reference does; `undefined` stays unset. */
120
+ export function piLimit(limit: number | undefined): number | undefined {
121
+ return limit === undefined ? undefined : Math.max(1, Math.floor(limit));
122
+ }
123
+
124
+ /**
125
+ * A `pi_bash` frame's timeout as the local `bash` tool's kwarg.
126
+ *
127
+ * Presence-sensitive like every other `optional int32` here, and unusually
128
+ * load-bearing: `bash` documents `timeout: 0` as "disables the command
129
+ * deadline", so folding a supplied `0` into `undefined` applies the 300s
130
+ * default and kills exactly the long-running command that asked not to be.
131
+ * Negative values have no local meaning and fall back to the default.
132
+ */
133
+ export function piTimeout(timeout: number | undefined): number | undefined {
134
+ return timeout !== undefined && timeout >= 0 ? timeout : undefined;
135
+ }