@rol1n/pi-kit 0.1.0 → 0.1.1
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/README.md +33 -58
- package/ask-u-questions/README.md +26 -0
- package/{extensions/ask-u-questions → ask-u-questions}/dialog-ui.ts +23 -0
- package/{extensions/ask-u-questions → ask-u-questions}/index.ts +9 -5
- package/{extensions/ask-u-questions → ask-u-questions}/multi-choice.ts +1 -3
- package/{extensions/ask-u-questions → ask-u-questions}/single-choice.ts +1 -3
- package/{extensions/ask-u-questions → ask-u-questions}/tool-renderers.ts +1 -3
- package/ask-u-questions/types.ts +192 -0
- package/continue-signal/README.md +20 -0
- package/{extensions/continue-signal → continue-signal}/index.ts +21 -3
- package/custom-providers/README.md +20 -0
- package/{extensions/custom-providers → custom-providers}/index.ts +16 -2
- package/image-generate/README.md +25 -0
- package/{extensions/image-generate → image-generate}/index.ts +22 -2
- package/{extensions/image-generate → image-generate}/model-selector.ts +1 -1
- package/model-vision/README.md +22 -0
- package/{extensions/multi-harness → multi-harness}/README.md +3 -3
- package/oai-subquota/README.md +22 -0
- package/{extensions/oai-subquota → oai-subquota}/index.ts +16 -6
- package/{extensions/oai-subquota → oai-subquota}/snapshot.ts +127 -1
- package/{extensions/oai-subquota → oai-subquota}/ui.ts +1 -1
- package/package.json +45 -46
- package/prompt-snipaste/README.md +27 -0
- package/{extensions/prompt-snipaste → prompt-snipaste}/renderers.ts +0 -1
- package/{extensions/prompt-snipaste → prompt-snipaste}/snippets.ts +5 -2
- package/{extensions/prompt-snipaste → prompt-snipaste}/types.ts +0 -1
- package/screenshot/README.md +14 -0
- package/srp-theme/README.md +18 -0
- package/{extensions/srp-theme → srp-theme}/footer.ts +0 -1
- package/{extensions/srp-theme → srp-theme}/tps-meter.ts +0 -1
- package/{extensions/subagent → subagent}/README.md +1 -1
- package/tui-asr/README.md +21 -0
- package/{extensions/tui-asr → tui-asr}/dictation.ts +70 -3
- package/{extensions/tui-asr → tui-asr}/index.ts +2 -2
- package/{extensions/tui-asr → tui-asr}/input.ts +30 -1
- package/{extensions/tui-asr → tui-asr}/model-selector.ts +1 -1
- package/web-reach/README.md +19 -0
- package/{extensions/web-reach → web-reach}/page.ts +84 -2
- package/windows-wheel-fix/README.md +12 -0
- package/extensions/ask-u-questions/README.md +0 -32
- package/extensions/ask-u-questions/answers.ts +0 -53
- package/extensions/ask-u-questions/results.ts +0 -83
- package/extensions/ask-u-questions/schema.ts +0 -17
- package/extensions/ask-u-questions/types.ts +0 -45
- package/extensions/ask-u-questions/ui-lock.ts +0 -24
- package/extensions/continue-signal/README.md +0 -28
- package/extensions/continue-signal/renderer.ts +0 -21
- package/extensions/custom-providers/README.md +0 -28
- package/extensions/image-generate/README.md +0 -29
- package/extensions/image-generate/models.ts +0 -19
- package/extensions/model-vision/README.md +0 -28
- package/extensions/oai-subquota/README.md +0 -30
- package/extensions/oai-subquota/api.ts +0 -27
- package/extensions/oai-subquota/auth.ts +0 -34
- package/extensions/oai-subquota/cache.ts +0 -30
- package/extensions/oai-subquota/types.ts +0 -40
- package/extensions/prompt-snipaste/README.md +0 -33
- package/extensions/screenshot/README.md +0 -25
- package/extensions/srp-theme/README.md +0 -24
- package/extensions/subagent/skills/subagent/SKILL.md +0 -70
- package/extensions/tui-asr/README.md +0 -28
- package/extensions/tui-asr/audio.ts +0 -40
- package/extensions/tui-asr/clipboard.ts +0 -30
- package/extensions/tui-asr/providers.ts +0 -25
- package/extensions/web-reach/README.md +0 -37
- package/extensions/web-reach/pdf.ts +0 -42
- package/extensions/web-reach/reader.ts +0 -42
- package/extensions/windows-wheel-fix/README.md +0 -21
- /package/{extensions/custom-providers → custom-providers}/asr/handlers/dashscope.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/asr/index.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/asr/models.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/asr/types.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/chat/index.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/chat/magpie.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/chat/models.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/classifier/index.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/classifier/models.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/image/handlers/dashscope.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/image/handlers/openrouter.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/image/index.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/image/models.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/image/types.ts +0 -0
- /package/{extensions/custom-providers → custom-providers}/types.ts +0 -0
- /package/{extensions/image-generate → image-generate}/files.ts +0 -0
- /package/{extensions/memory-log → memory-log}/README.md +0 -0
- /package/{extensions/memory-log → memory-log}/agent/consolidator/prompt.ts +0 -0
- /package/{extensions/memory-log → memory-log}/agent/consolidator/tools.ts +0 -0
- /package/{extensions/memory-log → memory-log}/agent/cost.ts +0 -0
- /package/{extensions/memory-log → memory-log}/agent/index.ts +0 -0
- /package/{extensions/memory-log → memory-log}/agent/observer/prompt.ts +0 -0
- /package/{extensions/memory-log → memory-log}/agent/observer/tool.ts +0 -0
- /package/{extensions/memory-log → memory-log}/commands/compact.ts +0 -0
- /package/{extensions/memory-log → memory-log}/commands/consolidate.ts +0 -0
- /package/{extensions/memory-log → memory-log}/commands/status.ts +0 -0
- /package/{extensions/memory-log → memory-log}/config.ts +0 -0
- /package/{extensions/memory-log → memory-log}/debug-log.ts +0 -0
- /package/{extensions/memory-log → memory-log}/hooks/compaction-hook.ts +0 -0
- /package/{extensions/memory-log → memory-log}/hooks/compaction-trigger.ts +0 -0
- /package/{extensions/memory-log → memory-log}/hooks/consolidator-trigger.ts +0 -0
- /package/{extensions/memory-log → memory-log}/hooks/observer-trigger.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ids.ts +0 -0
- /package/{extensions/memory-log → memory-log}/index.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ledger/fold.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ledger/index.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ledger/pool.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ledger/progress.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ledger/projection.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ledger/render.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ledger/serialize.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ledger/types.ts +0 -0
- /package/{extensions/memory-log → memory-log}/memory/index-render.ts +0 -0
- /package/{extensions/memory-log → memory-log}/memory/paths.ts +0 -0
- /package/{extensions/memory-log → memory-log}/memory/session.ts +0 -0
- /package/{extensions/memory-log → memory-log}/runtime.ts +0 -0
- /package/{extensions/memory-log → memory-log}/spawn/launch.ts +0 -0
- /package/{extensions/memory-log → memory-log}/spawn/runs.ts +0 -0
- /package/{extensions/memory-log → memory-log}/tokens.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ui/status-controller.ts +0 -0
- /package/{extensions/memory-log → memory-log}/ui/timeline.ts +0 -0
- /package/{extensions/multi-harness → multi-harness}/adapters.mjs +0 -0
- /package/{extensions/multi-harness → multi-harness}/harness-done.mjs +0 -0
- /package/{extensions/multi-harness → multi-harness}/index.ts +0 -0
- /package/{extensions/multi-harness → multi-harness}/ipc.mjs +0 -0
- /package/{extensions/multi-harness → multi-harness}/opencode-plugin.mjs +0 -0
- /package/{extensions/multi-harness → multi-harness}/process-runner.mjs +0 -0
- /package/{extensions/multi-harness → multi-harness}/turn-hook.mjs +0 -0
- /package/{extensions/multi-harness → multi-harness}/worker-bridge.ts +0 -0
- /package/{extensions/prompt-snipaste → prompt-snipaste}/index.ts +0 -0
- /package/{extensions/prompt-snipaste → prompt-snipaste}/menu.ts +0 -0
- /package/{prompts → prompt-snipaste/prompts}/ask-questions.md +0 -0
- /package/{prompts → prompt-snipaste/prompts}/delegate-exploration.md +0 -0
- /package/{prompts → prompt-snipaste/prompts}/diagnose-report.md +0 -0
- /package/{prompts → prompt-snipaste/prompts}/frontend-tech-preset.md +0 -0
- /package/{prompts → prompt-snipaste/prompts}/orchestrator-mode.md +0 -0
- /package/{prompts → prompt-snipaste/prompts}/session-kickoff.md +0 -0
- /package/{prompts → prompt-snipaste/prompts}/verify-not-assume.md +0 -0
- /package/{extensions/srp-theme → srp-theme}/index.ts +0 -0
- /package/{extensions/subagent → subagent}/bridge.ts +0 -0
- /package/{extensions/subagent → subagent}/index.ts +0 -0
- /package/{extensions/subagent → subagent}/mux.ts +0 -0
- /package/{extensions/subagent → subagent}/session.ts +0 -0
- /package/{extensions/subagent → subagent}/ui.ts +0 -0
- /package/{extensions/tui-asr → tui-asr}/status.ts +0 -0
- /package/{extensions/web-reach → web-reach}/html.ts +0 -0
- /package/{extensions/web-reach → web-reach}/index.ts +0 -0
- /package/{extensions/web-reach → web-reach}/rsc.ts +0 -0
- /package/{extensions/web-reach → web-reach}/search.ts +0 -0
- /package/{extensions/web-reach → web-reach}/transport.ts +0 -0
- /package/{extensions/windows-wheel-fix → windows-wheel-fix}/index.ts +0 -0
|
@@ -14,10 +14,10 @@ Also included in `@rol1n/pi-kit`. Enable one copy of the extension.
|
|
|
14
14
|
|
|
15
15
|
## Use
|
|
16
16
|
|
|
17
|
-
Load `
|
|
17
|
+
Load `multi-harness` through the aggregate package, or run from this repository:
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
|
-
pi --no-extensions -e ./
|
|
20
|
+
pi --no-extensions -e ./multi-harness/index.ts
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Example tool calls:
|
|
@@ -60,4 +60,4 @@ Session entries record only worker artifact locations. On session restore/reload
|
|
|
60
60
|
- Windows requires PowerShell 7 (`pwsh`) for external CLI invocation. Encoded PowerShell commands preserve Unicode, multiline tasks, JSON, and quoted paths. CLI hooks and `harness-done.cmd`/`.ps1` wrappers use the same native Windows Node installation. A mux must be available for visible TUIs; otherwise process fallback applies.
|
|
61
61
|
- Existing worktrees, reports, and sessions created by the removed `worktree-studio` extension are left untouched. Its old `the_road_not_taken` tool and two-route manifests are not imported into this runtime. Synchronize platform resources/reload before using the new tool; old running workers should be finished before upgrading.
|
|
62
62
|
|
|
63
|
-
Validation scripts are kept outside the repository. Check extension loading from this repository with `pi --no-extensions -e ./
|
|
63
|
+
Validation scripts are kept outside the repository. Check extension loading from this repository with `pi --no-extensions -e ./multi-harness/index.ts --list-models '<filter>'`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# oai-subquota
|
|
2
|
+
|
|
3
|
+
Monitor OpenAI Codex subscription quota (5-hour and 7-day windows, resets, and credits) when using the `openai-codex` provider.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pi install npm:@rol1n/oai-subquota
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Also included in `@rol1n/pi-kit`.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
| Command | Action |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `/oai-subquota codex` | Render boxed quota summary and refresh footer |
|
|
18
|
+
| `/oai-subquota refresh` | Force a fresh backend query |
|
|
19
|
+
| `/oai-subquota statusline` | Print compact single-line quota text |
|
|
20
|
+
| `/oai-subquota chatgpt` | Inspect parked ChatGPT OAuth quota status |
|
|
21
|
+
|
|
22
|
+
Authenticate with `/login openai-codex`. Snapshots are cached under `$XDG_CACHE_HOME/oai-subquota/usage.json` (or `~/.cache/oai-subquota/usage.json`) for 60 seconds.
|
|
@@ -15,14 +15,24 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import type { AutocompleteItem, ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
import {
|
|
19
|
+
extractAccountFromToken,
|
|
20
|
+
mergeSnapshots,
|
|
21
|
+
parseCodexRateLimitHeaders,
|
|
22
|
+
parseUsageApiResponse,
|
|
23
|
+
queryUsage,
|
|
24
|
+
readCachedSnapshot,
|
|
25
|
+
writeCachedSnapshot,
|
|
26
|
+
type AccountSnapshot,
|
|
27
|
+
type CodexUsageSnapshot,
|
|
28
|
+
type CreditsSnapshot,
|
|
29
|
+
type LimitWindow,
|
|
30
|
+
type RateLimit,
|
|
31
|
+
type ResetsSnapshot,
|
|
32
|
+
} from "./snapshot.ts";
|
|
22
33
|
import { dimText, formatBoxedStatus, formatRightAlignedStatusline, formatStatusline, renderStatusMessage } from "./ui.ts";
|
|
23
|
-
import type { CodexUsageSnapshot } from "./types.ts";
|
|
24
34
|
|
|
25
|
-
export type { LimitWindow, RateLimit, CreditsSnapshot, ResetsSnapshot, AccountSnapshot, CodexUsageSnapshot }
|
|
35
|
+
export type { LimitWindow, RateLimit, CreditsSnapshot, ResetsSnapshot, AccountSnapshot, CodexUsageSnapshot };
|
|
26
36
|
export { bar, formatDuration, formatStatusline, formatBoxedStatus, formatRightAlignedStatusline } from "./ui.ts";
|
|
27
37
|
|
|
28
38
|
const CODEX_PROVIDER = "openai-codex";
|
|
@@ -1,4 +1,48 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
|
|
6
|
+
export interface LimitWindow {
|
|
7
|
+
usedPercent: number;
|
|
8
|
+
leftPercent: number;
|
|
9
|
+
windowSeconds?: number;
|
|
10
|
+
resetAt?: number;
|
|
11
|
+
resetAfterSeconds?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface RateLimit {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
primary?: LimitWindow;
|
|
18
|
+
secondary?: LimitWindow;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CreditsSnapshot {
|
|
22
|
+
hasCredits?: boolean;
|
|
23
|
+
unlimited?: boolean;
|
|
24
|
+
balance?: number | string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ResetsSnapshot {
|
|
28
|
+
availableCount?: number;
|
|
29
|
+
applicableCount?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface AccountSnapshot {
|
|
33
|
+
email?: string;
|
|
34
|
+
plan?: string;
|
|
35
|
+
accountId?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface CodexUsageSnapshot {
|
|
39
|
+
source: "api" | "headers" | "cache";
|
|
40
|
+
fetchedAt: string;
|
|
41
|
+
account: AccountSnapshot;
|
|
42
|
+
defaultLimit?: RateLimit;
|
|
43
|
+
credits?: CreditsSnapshot;
|
|
44
|
+
resets?: ResetsSnapshot;
|
|
45
|
+
}
|
|
2
46
|
|
|
3
47
|
export function isRecord(val: unknown): val is Record<string, unknown> {
|
|
4
48
|
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
@@ -165,3 +209,85 @@ export function mergeSnapshots(existing: CodexUsageSnapshot | undefined, update:
|
|
|
165
209
|
resets: update.resets ?? existing.resets,
|
|
166
210
|
};
|
|
167
211
|
}
|
|
212
|
+
|
|
213
|
+
const JWT_AUTH_CLAIM = "https://api.openai.com/auth";
|
|
214
|
+
const JWT_PROFILE_CLAIM = "https://api.openai.com/profile";
|
|
215
|
+
|
|
216
|
+
function decodeJwtPayload(token: string): Record<string, unknown> | undefined {
|
|
217
|
+
const part = token.split(".")[1];
|
|
218
|
+
if (!part) return undefined;
|
|
219
|
+
try {
|
|
220
|
+
const json = JSON.parse(Buffer.from(part, "base64url").toString("utf8"));
|
|
221
|
+
return isRecord(json) ? json : undefined;
|
|
222
|
+
} catch {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function extractAccountFromToken(token: string): AccountSnapshot {
|
|
228
|
+
const payload = decodeJwtPayload(token);
|
|
229
|
+
if (!payload) return {};
|
|
230
|
+
|
|
231
|
+
const auth = isRecord(payload[JWT_AUTH_CLAIM]) ? payload[JWT_AUTH_CLAIM] : undefined;
|
|
232
|
+
const profile = isRecord(payload[JWT_PROFILE_CLAIM]) ? payload[JWT_PROFILE_CLAIM] : undefined;
|
|
233
|
+
|
|
234
|
+
const accountId = typeof auth?.chatgpt_account_id === "string" ? auth.chatgpt_account_id : undefined;
|
|
235
|
+
const plan = typeof auth?.chatgpt_plan_type === "string" ? auth.chatgpt_plan_type : undefined;
|
|
236
|
+
const email =
|
|
237
|
+
(typeof profile?.email === "string" && profile.email) ||
|
|
238
|
+
(typeof payload.email === "string" && payload.email) ||
|
|
239
|
+
undefined;
|
|
240
|
+
|
|
241
|
+
return { accountId, plan, email };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const USAGE_ENDPOINT = "https://chatgpt.com/backend-api/wham/usage";
|
|
245
|
+
const REQUEST_TIMEOUT_MS = 15_000;
|
|
246
|
+
|
|
247
|
+
export async function queryUsage(accessToken: string, accountId?: string): Promise<Record<string, unknown>> {
|
|
248
|
+
const headers: Record<string, string> = {
|
|
249
|
+
Authorization: `Bearer ${accessToken}`,
|
|
250
|
+
"User-Agent": "codex-cli",
|
|
251
|
+
Accept: "application/json",
|
|
252
|
+
};
|
|
253
|
+
if (accountId) headers["ChatGPT-Account-Id"] = accountId;
|
|
254
|
+
|
|
255
|
+
const res = await fetch(USAGE_ENDPOINT, {
|
|
256
|
+
method: "GET",
|
|
257
|
+
headers,
|
|
258
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
if (res.status === 401 || res.status === 403) throw new Error(`Authentication rejected (HTTP ${res.status}). Please run /login openai-codex.`);
|
|
262
|
+
if (res.status === 429) throw new Error("Rate limit exceeded for usage endpoint (HTTP 429). Please try again later.");
|
|
263
|
+
if (!res.ok) throw new Error(`Usage request failed (HTTP ${res.status}).`);
|
|
264
|
+
|
|
265
|
+
const body = await res.json();
|
|
266
|
+
if (!isRecord(body)) throw new Error("Invalid JSON received from usage endpoint.");
|
|
267
|
+
return body;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function getCachePath(): string {
|
|
271
|
+
const base = process.env.XDG_CACHE_HOME || join(homedir() || ".", ".cache");
|
|
272
|
+
return join(base, "oai-subquota", "usage.json");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export async function readCachedSnapshot(): Promise<CodexUsageSnapshot | undefined> {
|
|
276
|
+
try {
|
|
277
|
+
const raw = await readFile(getCachePath(), "utf8");
|
|
278
|
+
const parsed = JSON.parse(raw);
|
|
279
|
+
return isRecord(parsed) ? (parsed as unknown as CodexUsageSnapshot) : undefined;
|
|
280
|
+
} catch {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export async function writeCachedSnapshot(snapshot: CodexUsageSnapshot): Promise<void> {
|
|
286
|
+
try {
|
|
287
|
+
const file = getCachePath();
|
|
288
|
+
await mkdir(dirname(file), { recursive: true });
|
|
289
|
+
await writeFile(file, `${JSON.stringify(snapshot, null, 2)}\n`, { mode: 0o600 });
|
|
290
|
+
} catch {
|
|
291
|
+
// Non-fatal if filesystem is read-only
|
|
292
|
+
}
|
|
293
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ExtensionCommandContext, ExtensionContext, Theme } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Text, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
-
import type { CodexUsageSnapshot, LimitWindow } from "./
|
|
3
|
+
import type { CodexUsageSnapshot, LimitWindow } from "./snapshot.ts";
|
|
4
4
|
|
|
5
5
|
const USAGE_SETTINGS_URL = "https://chatgpt.com/codex/settings/usage";
|
|
6
6
|
const MONTH_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rol1n/pi-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "A selectable collection of Pi extensions and prompt templates.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "git+
|
|
7
|
+
"url": "git+https://github.com/RolinShmily/pi-kit.git"
|
|
8
8
|
},
|
|
9
9
|
"homepage": "https://github.com/RolinShmily/pi-kit#readme",
|
|
10
10
|
"bugs": {
|
|
@@ -21,42 +21,41 @@
|
|
|
21
21
|
"manifest": "node scripts/package.mjs sync",
|
|
22
22
|
"check": "node scripts/package.mjs check",
|
|
23
23
|
"prepare:extension": "node scripts/package.mjs extension",
|
|
24
|
+
"publish:ci": "node scripts/package.mjs publish",
|
|
24
25
|
"prepack": "node scripts/package.mjs check"
|
|
25
26
|
},
|
|
26
27
|
"publishConfig": {
|
|
27
28
|
"access": "public"
|
|
28
29
|
},
|
|
29
30
|
"files": [
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"extensions/web-reach",
|
|
59
|
-
"extensions/windows-wheel-fix",
|
|
31
|
+
"ask-u-questions/README.md",
|
|
32
|
+
"continue-signal/README.md",
|
|
33
|
+
"custom-providers/README.md",
|
|
34
|
+
"image-generate/README.md",
|
|
35
|
+
"memory-log/README.md",
|
|
36
|
+
"model-vision/README.md",
|
|
37
|
+
"multi-harness/README.md",
|
|
38
|
+
"oai-subquota/README.md",
|
|
39
|
+
"prompt-snipaste/README.md",
|
|
40
|
+
"screenshot/README.md",
|
|
41
|
+
"srp-theme/README.md",
|
|
42
|
+
"subagent/README.md",
|
|
43
|
+
"tui-asr/README.md",
|
|
44
|
+
"web-reach/README.md",
|
|
45
|
+
"windows-wheel-fix/README.md",
|
|
46
|
+
"ask-u-questions",
|
|
47
|
+
"continue-signal",
|
|
48
|
+
"custom-providers",
|
|
49
|
+
"image-generate",
|
|
50
|
+
"memory-log",
|
|
51
|
+
"multi-harness",
|
|
52
|
+
"subagent",
|
|
53
|
+
"oai-subquota",
|
|
54
|
+
"prompt-snipaste",
|
|
55
|
+
"srp-theme",
|
|
56
|
+
"tui-asr",
|
|
57
|
+
"web-reach",
|
|
58
|
+
"windows-wheel-fix",
|
|
60
59
|
"!**/test/**",
|
|
61
60
|
"!**/tests/**",
|
|
62
61
|
"!**/*.{test,spec}.{ts,js,mjs,cjs}",
|
|
@@ -72,23 +71,23 @@
|
|
|
72
71
|
},
|
|
73
72
|
"pi": {
|
|
74
73
|
"extensions": [
|
|
75
|
-
"./
|
|
76
|
-
"./
|
|
77
|
-
"./
|
|
78
|
-
"./
|
|
79
|
-
"./
|
|
80
|
-
"./
|
|
81
|
-
"./
|
|
82
|
-
"./
|
|
83
|
-
"./
|
|
84
|
-
"./
|
|
85
|
-
"./
|
|
86
|
-
"./
|
|
87
|
-
"./
|
|
74
|
+
"./ask-u-questions/index.ts",
|
|
75
|
+
"./continue-signal/index.ts",
|
|
76
|
+
"./custom-providers/index.ts",
|
|
77
|
+
"./image-generate/index.ts",
|
|
78
|
+
"./memory-log/index.ts",
|
|
79
|
+
"./multi-harness/index.ts",
|
|
80
|
+
"./oai-subquota/index.ts",
|
|
81
|
+
"./prompt-snipaste/index.ts",
|
|
82
|
+
"./srp-theme/index.ts",
|
|
83
|
+
"./subagent/index.ts",
|
|
84
|
+
"./tui-asr/index.ts",
|
|
85
|
+
"./web-reach/index.ts",
|
|
86
|
+
"./windows-wheel-fix/index.ts"
|
|
88
87
|
],
|
|
89
88
|
"skills": [],
|
|
90
89
|
"prompts": [
|
|
91
|
-
"./prompts"
|
|
90
|
+
"./prompt-snipaste/prompts"
|
|
92
91
|
],
|
|
93
92
|
"themes": []
|
|
94
93
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# prompt-snipaste
|
|
2
|
+
|
|
3
|
+
Select prompt snippets to prepend or append to the next user message, with live preview and a session transcript card. Bundles 7 built-in prompt snippets under `prompts/`.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pi install npm:@rol1n/prompt-snipaste
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Also included in `@rol1n/pi-kit`.
|
|
12
|
+
|
|
13
|
+
## Use
|
|
14
|
+
|
|
15
|
+
Open with `/snipaste` or `Alt+S`. Navigate with arrow keys, toggle with `Space`, preview with `Tab`, confirm with `Enter`, and cancel with `Escape`.
|
|
16
|
+
|
|
17
|
+
## Frontmatter
|
|
18
|
+
|
|
19
|
+
```markdown
|
|
20
|
+
---
|
|
21
|
+
name: Review checklist
|
|
22
|
+
description: Add review criteria to the next message
|
|
23
|
+
placement: append
|
|
24
|
+
order: 100
|
|
25
|
+
---
|
|
26
|
+
Check correctness, error handling, and missing validation.
|
|
27
|
+
```
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { basename, isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
const BUNDLED_PROMPTS_DIR = join(dirname(fileURLToPath(import.meta.url)), "prompts");
|
|
4
7
|
import { CONFIG_DIR_NAME, getAgentDir, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
5
8
|
import type { Snippet } from "./types.ts";
|
|
6
9
|
|
|
@@ -108,6 +111,7 @@ export function loadSnippets(cwd: string, pi?: ExtensionAPI): Snippet[] {
|
|
|
108
111
|
.filter((command) => command.source === "prompt")
|
|
109
112
|
.map((command) => command.sourceInfo.path);
|
|
110
113
|
const defaultDirs = loadedPromptPaths ? [] : [
|
|
114
|
+
BUNDLED_PROMPTS_DIR,
|
|
111
115
|
join(getAgentDir(), "prompts"),
|
|
112
116
|
join(cwd, CONFIG_DIR_NAME, "prompts"),
|
|
113
117
|
];
|
|
@@ -200,4 +204,3 @@ export function loadSnippets(cwd: string, pi?: ExtensionAPI): Snippet[] {
|
|
|
200
204
|
return a.name.localeCompare(b.name);
|
|
201
205
|
});
|
|
202
206
|
}
|
|
203
|
-
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# screenshot
|
|
2
|
+
|
|
3
|
+
Insert the file path of the most recently modified Windows/WSL system screenshot into Pi's editor via `/screenshot`.
|
|
4
|
+
|
|
5
|
+
Searches standard and localized `Pictures/Screenshots` and OneDrive screenshot directories under `USERPROFILE` on Windows or `/mnt/c/Users` on WSL.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pi install npm:@rol1n/screenshot
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Available as a standalone package (not enabled in `@rol1n/pi-kit` by default).
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# srp-theme
|
|
2
|
+
|
|
3
|
+
Incremental Pi terminal presentation enhancement: adds a `belowEditor` last-prompt preview widget and a real-time streaming TPS (tokens per second) status meter while keeping Pi's native header and footer intact.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pi install npm:@rol1n/srp-theme
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Also included in `@rol1n/pi-kit`.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
/srp-theme on
|
|
17
|
+
/srp-theme off
|
|
18
|
+
```
|
|
@@ -32,4 +32,4 @@ Without a usable multiplexer, the worker backend falls back to a background proc
|
|
|
32
32
|
|
|
33
33
|
## Other delegation packages
|
|
34
34
|
|
|
35
|
-
Use [multi-harness](https://github.com/RolinShmily/pi-kit/tree/main/
|
|
35
|
+
Use [multi-harness](https://github.com/RolinShmily/pi-kit/tree/main/multi-harness) for Codex, Claude, or OpenCode peers. That package shares multiplexer helpers (`mux.ts`) while exposing a separate tool.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# tui-asr
|
|
2
|
+
|
|
3
|
+
Streaming voice dictation for Pi's terminal editor using Aliyun DashScope Paraformer.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pi install npm:@rol1n/tui-asr
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Also included in `@rol1n/pi-kit`. Installing this package automatically installs `@rol1n/custom-providers`.
|
|
12
|
+
|
|
13
|
+
## Commands and shortcuts
|
|
14
|
+
|
|
15
|
+
| Action | Trigger |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Start / stop dictation | `/asr` or `Alt+M` |
|
|
18
|
+
| Cancel dictation | `Alt+N` |
|
|
19
|
+
| Switch ASR model | `/asr model [name]` |
|
|
20
|
+
|
|
21
|
+
Requires `sox` (`rec` on POSIX, `sox -t waveaudio` on Windows) on `PATH` and DashScope credentials via `/login dashscope`, `DASHSCOPE_API_KEY`, or `ALIYUN_API_KEY`.
|
|
@@ -1,11 +1,78 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type
|
|
2
|
+
import { spawn, type ChildProcessByStdio } from "node:child_process";
|
|
3
3
|
import type { Readable } from "node:stream";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ALL_ASR_MODELS,
|
|
6
|
+
createAsrProvider,
|
|
7
|
+
ensureCustomProviders,
|
|
8
|
+
type AsrModelDefinition,
|
|
9
|
+
type StreamingAsrProvider,
|
|
10
|
+
} from "../custom-providers/index.ts";
|
|
5
11
|
import { insertTranscript } from "./input.ts";
|
|
6
|
-
import { ALL_ASR_MODELS, createAsrProvider, resolveProviderApiKey, type StreamingAsrProvider } from "./providers.ts";
|
|
7
12
|
import { createStatusDisplay } from "./status.ts";
|
|
8
13
|
|
|
14
|
+
export { ALL_ASR_MODELS, createAsrProvider, ensureCustomProviders, type AsrModelDefinition, type StreamingAsrProvider };
|
|
15
|
+
|
|
16
|
+
export async function resolveProviderApiKey(provider: string, ctx?: ExtensionContext | null): Promise<string> {
|
|
17
|
+
if (ctx?.modelRegistry) {
|
|
18
|
+
const candidates = provider === "dashscope" ? ["dashscope", "aliyun"] : [provider];
|
|
19
|
+
for (const id of candidates) {
|
|
20
|
+
try {
|
|
21
|
+
const key = await ctx.modelRegistry.getApiKeyForProvider(id);
|
|
22
|
+
if (key?.trim()) return key.trim();
|
|
23
|
+
} catch {}
|
|
24
|
+
try {
|
|
25
|
+
const auth = await ctx.modelRegistry.getProviderAuth(id);
|
|
26
|
+
if (auth?.auth?.apiKey?.trim()) return auth.auth.apiKey.trim();
|
|
27
|
+
} catch {}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const envKey = process.env[`${provider.toUpperCase()}_API_KEY`];
|
|
31
|
+
if (envKey?.trim()) return envKey.trim();
|
|
32
|
+
if (provider === "dashscope") {
|
|
33
|
+
return process.env.ALIYUN_API_KEY?.trim() || "";
|
|
34
|
+
}
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function rmsFromPcm16(buf: Buffer): number {
|
|
39
|
+
if (buf.length < 2) return 0;
|
|
40
|
+
const sampleCount = Math.floor(buf.length / 2);
|
|
41
|
+
let sumSquares = 0;
|
|
42
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
43
|
+
const sample = buf.readInt16LE(i * 2);
|
|
44
|
+
sumSquares += sample * sample;
|
|
45
|
+
}
|
|
46
|
+
const meanSquare = sumSquares / sampleCount;
|
|
47
|
+
return Math.sqrt(meanSquare);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Spawn the existing 16 kHz mono PCM recorder for the current platform. */
|
|
51
|
+
export function spawnRecorder(): ChildProcessByStdio<null, Readable, Readable> {
|
|
52
|
+
const commonAudioArgs = [
|
|
53
|
+
"-q",
|
|
54
|
+
"--buffer", "512",
|
|
55
|
+
"-r", "16000",
|
|
56
|
+
"-c", "1",
|
|
57
|
+
"-b", "16",
|
|
58
|
+
"-e", "signed-integer",
|
|
59
|
+
"-t", "raw",
|
|
60
|
+
"-",
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
let proc: ChildProcessByStdio<null, Readable, Readable>;
|
|
64
|
+
if (process.platform === "win32") {
|
|
65
|
+
proc = spawn("sox", ["-t", "waveaudio", "default", ...commonAudioArgs], { stdio: ["ignore", "pipe", "pipe"] });
|
|
66
|
+
} else {
|
|
67
|
+
try {
|
|
68
|
+
proc = spawn("rec", commonAudioArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
69
|
+
} catch {
|
|
70
|
+
proc = spawn("sox", ["-d", ...commonAudioArgs], { stdio: ["ignore", "pipe", "pipe"] });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return proc;
|
|
74
|
+
}
|
|
75
|
+
|
|
9
76
|
type State = "idle" | "recording" | "stopping";
|
|
10
77
|
|
|
11
78
|
/** Keep recording state, cancellation guards, and cleanup in one session-local controller. */
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import { type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
21
21
|
import type { AutocompleteItem } from "@earendil-works/pi-tui";
|
|
22
|
-
import { ALL_ASR_MODELS, resolveProviderApiKey, type AsrModelDefinition } from "./
|
|
23
|
-
import { createDictationController } from "./dictation.ts";
|
|
22
|
+
import { ALL_ASR_MODELS, createDictationController, ensureCustomProviders, resolveProviderApiKey, type AsrModelDefinition } from "./dictation.ts";
|
|
24
23
|
import { SearchableAsrModelSelectorComponent } from "./model-selector.ts";
|
|
25
24
|
|
|
26
25
|
/** Default startup ASR model ID */
|
|
@@ -31,6 +30,7 @@ const TOGGLE_SHORTCUTS = ["alt+m"];
|
|
|
31
30
|
const CANCEL_SHORTCUTS = ["alt+n"];
|
|
32
31
|
|
|
33
32
|
export default function (pi: ExtensionAPI) {
|
|
33
|
+
ensureCustomProviders(pi);
|
|
34
34
|
let activeModel = DEFAULT_ASR_MODEL;
|
|
35
35
|
|
|
36
36
|
// TUI state
|
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import {
|
|
2
|
+
import { spawn, type ChildProcessByStdio } from "node:child_process";
|
|
3
|
+
|
|
4
|
+
export function copyToClipboard(text: string): boolean {
|
|
5
|
+
try {
|
|
6
|
+
const isWsl =
|
|
7
|
+
process.platform === "linux" &&
|
|
8
|
+
typeof process.env.WSL_DISTRO_NAME === "string";
|
|
9
|
+
|
|
10
|
+
let proc: ChildProcessByStdio<any, any, any>;
|
|
11
|
+
if (isWsl) {
|
|
12
|
+
proc = spawn("clip.exe", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
13
|
+
} else if (process.platform === "win32") {
|
|
14
|
+
proc = spawn("clip", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
15
|
+
} else if (process.platform === "darwin") {
|
|
16
|
+
proc = spawn("pbcopy", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
17
|
+
} else {
|
|
18
|
+
try {
|
|
19
|
+
proc = spawn("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
20
|
+
} catch {
|
|
21
|
+
proc = spawn("xclip", ["-selection", "clipboard"], { stdio: ["pipe", "ignore", "ignore"] });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
proc.stdin.write(text);
|
|
26
|
+
proc.stdin.end();
|
|
27
|
+
return true;
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
3
32
|
|
|
4
33
|
interface EditorLike {
|
|
5
34
|
getText(): string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Input, fuzzyFilter, getKeybindings } from "@earendil-works/pi-tui";
|
|
2
|
-
import type { AsrModelDefinition } from "./
|
|
2
|
+
import type { AsrModelDefinition } from "./dictation.ts";
|
|
3
3
|
|
|
4
4
|
export class SearchableAsrModelSelectorComponent {
|
|
5
5
|
private searchInput = new Input();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# web-reach
|
|
2
|
+
|
|
3
|
+
Keyless web search (`web_search` via Exa MCP) and multi-tier page extraction (`web_fetch` supporting Next.js RSC, semantic HTML-to-Markdown, optional `unpdf` PDF extraction, and Jina Reader fallback).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pi install npm:@rol1n/web-reach
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Also included in `@rol1n/pi-kit`.
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
| Environment variable | Default |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `SRP_WEB_SEARCH_TIMEOUT_MS` | `60000` |
|
|
18
|
+
| `SRP_WEB_FETCH_TIMEOUT_MS` | `20000` |
|
|
19
|
+
| `SRP_WEB_FETCH_MAX_BYTES` | `4194304` (4 MiB) |
|