@aliou/pi-synthetic 0.4.6 → 0.4.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.
package/package.json CHANGED
@@ -1,27 +1,40 @@
1
1
  {
2
2
  "name": "@aliou/pi-synthetic",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "private": false,
7
+ "keywords": [
8
+ "pi-package",
9
+ "pi-extension",
10
+ "pi"
11
+ ],
4
12
  "repository": {
5
13
  "type": "git",
6
14
  "url": "https://github.com/aliou/pi-synthetic"
7
15
  },
8
- "keywords": [
9
- "pi-package"
10
- ],
11
16
  "pi": {
12
17
  "extensions": [
13
18
  "./src/index.ts"
14
19
  ],
15
20
  "video": "https://assets.aliou.me/pi-extensions/demos/pi-synthetic.mp4"
16
21
  },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "files": [
26
+ "src",
27
+ "README.md"
28
+ ],
17
29
  "peerDependencies": {
18
- "@mariozechner/pi-coding-agent": ">=0.52.7"
30
+ "@mariozechner/pi-coding-agent": ">=0.52.7",
31
+ "@mariozechner/pi-tui": ">=0.51.0"
19
32
  },
20
33
  "devDependencies": {
21
- "@biomejs/biome": "^2.3.13",
34
+ "@aliou/biome-plugins": "^0.3.2",
35
+ "@biomejs/biome": "^2.4.2",
22
36
  "@changesets/cli": "^2.27.11",
23
37
  "@mariozechner/pi-coding-agent": "0.52.7",
24
- "@mariozechner/pi-tui": "0.52.7",
25
38
  "@sinclair/typebox": "^0.34.48",
26
39
  "@types/node": "^25.0.10",
27
40
  "husky": "^9.1.7",
@@ -30,12 +43,16 @@
30
43
  "peerDependenciesMeta": {
31
44
  "@mariozechner/pi-coding-agent": {
32
45
  "optional": true
46
+ },
47
+ "@mariozechner/pi-tui": {
48
+ "optional": true
33
49
  }
34
50
  },
35
51
  "scripts": {
36
52
  "typecheck": "tsc --noEmit",
37
53
  "lint": "biome check",
38
54
  "format": "biome check --write",
55
+ "check:lockfile": "pnpm install --frozen-lockfile --ignore-scripts",
39
56
  "changeset": "changeset",
40
57
  "version": "changeset version",
41
58
  "release": "pnpm changeset publish"
@@ -9,16 +9,6 @@ export function registerQuotasCommand(pi: ExtensionAPI): void {
9
9
  pi.registerCommand("synthetic:quotas", {
10
10
  description: "Display Synthetic API usage quotas",
11
11
  handler: async (_args, ctx) => {
12
- if (!ctx.hasUI) {
13
- const quotas = await fetchQuotas();
14
- if (!quotas) {
15
- console.error("Failed to fetch quotas");
16
- return;
17
- }
18
- console.log(formatQuotasPlain(quotas));
19
- return;
20
- }
21
-
22
12
  const result = await ctx.ui.custom<null>((tui, theme, _kb, done) => {
23
13
  let currentComponent: Component = new QuotasLoadingComponent(theme);
24
14
 
@@ -1,13 +1,6 @@
1
- import type {
2
- ExtensionAPI,
3
- ExtensionContext,
4
- } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
5
2
  import { SYNTHETIC_WEB_SEARCH_TOOL } from "../tools/search";
6
3
 
7
- function notifyDebug(ctx: ExtensionContext, message: string): void {
8
- ctx.ui.notify(`[pi-synthetic:web-search] ${message}`, "info");
9
- }
10
-
11
4
  async function checkSubscriptionAccess(
12
5
  apiKey: string,
13
6
  ): Promise<{ ok: true } | { ok: false; reason: string }> {
@@ -51,48 +44,36 @@ export function registerSyntheticWebSearchHooks(pi: ExtensionAPI): void {
51
44
  let didNotifyDenied = false;
52
45
 
53
46
  // Keep tool inactive at session start. Availability is decided before each agent run.
54
- pi.on("session_start", (_event, ctx) => {
55
- notifyDebug(ctx, "session_start: preparing web search tool");
56
-
47
+ pi.on("session_start", () => {
57
48
  const current = pi.getActiveTools();
58
49
  if (current.includes(SYNTHETIC_WEB_SEARCH_TOOL)) {
59
50
  pi.setActiveTools(
60
51
  current.filter((toolName) => toolName !== SYNTHETIC_WEB_SEARCH_TOOL),
61
52
  );
62
- notifyDebug(ctx, "session_start: tool disabled until subscription check");
63
53
  }
64
54
  });
65
55
 
66
56
  // Verify subscription only when user starts agent execution.
67
57
  pi.on("before_agent_start", async (_event, ctx) => {
68
- notifyDebug(ctx, "before_agent_start: ensuring tool availability");
69
-
70
58
  const apiKey = process.env.SYNTHETIC_API_KEY;
71
59
  if (!apiKey) {
72
60
  hasAccess = false;
73
61
  deniedReason = "SYNTHETIC_API_KEY is not configured";
74
62
  accessCheckPromise = undefined;
75
- notifyDebug(ctx, "before_agent_start: access denied (missing API key)");
76
63
  } else {
77
64
  if (deniedReason === "SYNTHETIC_API_KEY is not configured") {
78
65
  deniedReason = undefined;
79
66
  }
80
67
 
81
68
  if (!hasAccess && !deniedReason) {
82
- notifyDebug(ctx, "before_agent_start: checking subscription access");
83
69
  accessCheckPromise ??= checkSubscriptionAccess(apiKey);
84
70
  const access = await accessCheckPromise;
85
71
 
86
72
  if (!access.ok) {
87
73
  deniedReason = access.reason;
88
- notifyDebug(
89
- ctx,
90
- `before_agent_start: access denied (${access.reason})`,
91
- );
92
74
  } else {
93
75
  hasAccess = true;
94
76
  didNotifyDenied = false;
95
- notifyDebug(ctx, "before_agent_start: access granted");
96
77
  }
97
78
  }
98
79
  }
@@ -103,7 +84,6 @@ export function registerSyntheticWebSearchHooks(pi: ExtensionAPI): void {
103
84
  pi.setActiveTools(
104
85
  current.filter((toolName) => toolName !== SYNTHETIC_WEB_SEARCH_TOOL),
105
86
  );
106
- notifyDebug(ctx, "before_agent_start: tool kept disabled");
107
87
  }
108
88
 
109
89
  if (ctx.hasUI && !didNotifyDenied) {
@@ -112,10 +92,6 @@ export function registerSyntheticWebSearchHooks(pi: ExtensionAPI): void {
112
92
  "warning",
113
93
  );
114
94
  didNotifyDenied = true;
115
- notifyDebug(
116
- ctx,
117
- "before_agent_start: user notified about disabled tool",
118
- );
119
95
  }
120
96
  return;
121
97
  }
@@ -123,7 +99,6 @@ export function registerSyntheticWebSearchHooks(pi: ExtensionAPI): void {
123
99
  const current = pi.getActiveTools();
124
100
  if (!current.includes(SYNTHETIC_WEB_SEARCH_TOOL)) {
125
101
  pi.setActiveTools([...current, SYNTHETIC_WEB_SEARCH_TOOL]);
126
- notifyDebug(ctx, "before_agent_start: tool enabled");
127
102
  }
128
103
  });
129
104
  }
@@ -1,11 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
3
- "changelog": "@changesets/cli/changelog",
4
- "commit": false,
5
- "fixed": [],
6
- "linked": [],
7
- "access": "public",
8
- "baseBranch": "main",
9
- "updateInternalDependencies": "patch",
10
- "ignore": []
11
- }
@@ -1,30 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- pull_request:
5
-
6
- concurrency:
7
- group: ${{ github.workflow }}-${{ github.ref }}
8
- cancel-in-progress: true
9
-
10
- jobs:
11
- check:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v4
15
-
16
- - uses: pnpm/action-setup@v4
17
-
18
- - uses: actions/setup-node@v4
19
- with:
20
- node-version: "22"
21
- cache: "pnpm"
22
-
23
- - name: Install dependencies
24
- run: pnpm install --frozen-lockfile
25
-
26
- - name: Lint
27
- run: pnpm lint
28
-
29
- - name: Typecheck
30
- run: pnpm typecheck
@@ -1,151 +0,0 @@
1
- name: Publish
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- workflow_dispatch:
8
- inputs:
9
- skip-checks:
10
- description: "Skip lint and typecheck"
11
- type: boolean
12
- default: false
13
-
14
- concurrency:
15
- group: ${{ github.workflow }}-${{ github.ref }}
16
- cancel-in-progress: true
17
-
18
- jobs:
19
- check:
20
- if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.skip-checks) }}
21
- runs-on: ubuntu-latest
22
- steps:
23
- - uses: actions/checkout@v4
24
-
25
- - uses: pnpm/action-setup@v4
26
-
27
- - uses: actions/setup-node@v4
28
- with:
29
- node-version: "22"
30
- cache: "pnpm"
31
-
32
- - name: Install dependencies
33
- run: pnpm install --frozen-lockfile
34
-
35
- - name: Lint
36
- run: pnpm lint
37
-
38
- - name: Typecheck
39
- run: pnpm typecheck
40
-
41
- publish:
42
- name: Publish
43
- needs: check
44
- if: ${{ always() && (needs.check.result == 'success' || needs.check.result == 'skipped') }}
45
- runs-on: ubuntu-latest
46
- permissions:
47
- contents: write
48
- packages: write
49
- pull-requests: write
50
- id-token: write
51
-
52
- steps:
53
- - name: Checkout
54
- uses: actions/checkout@v4
55
- with:
56
- fetch-depth: 0
57
-
58
- - name: Setup pnpm
59
- uses: pnpm/action-setup@v4
60
-
61
- - name: Setup Node.js
62
- uses: actions/setup-node@v4
63
- with:
64
- node-version: "22"
65
- registry-url: "https://registry.npmjs.org"
66
- scope: "@aliou"
67
- cache: "pnpm"
68
-
69
- - name: Upgrade npm for OIDC support
70
- run: npm install -g npm@latest
71
-
72
- - name: Install dependencies
73
- run: pnpm install --frozen-lockfile
74
-
75
- - name: Get release info
76
- id: release-info
77
- run: |
78
- pnpm changeset status --output=release.json 2>/dev/null || echo '{"releases":[]}' > release.json
79
- node <<NODE
80
- const fs = require('fs');
81
- const release = JSON.parse(fs.readFileSync('release.json', 'utf8'));
82
- const releases = release.releases?.filter(r => r.type !== 'none') || [];
83
-
84
- let title = 'Version Packages';
85
- let commit = 'Version Packages';
86
- if (releases.length === 1) {
87
- const { name, newVersion } = releases[0];
88
- title = 'Updating ' + name + ' to version ' + newVersion;
89
- commit = name + '@' + newVersion;
90
- } else if (releases.length > 1) {
91
- const summary = releases.map(r => r.name + '@' + r.newVersion).join(', ');
92
- title = 'Updating ' + summary;
93
- commit = summary;
94
- }
95
-
96
- fs.appendFileSync(process.env.GITHUB_OUTPUT, 'title=' + title + '\n');
97
- fs.appendFileSync(process.env.GITHUB_OUTPUT, 'commit=' + commit + '\n');
98
- NODE
99
- rm -f release.json
100
- continue-on-error: true
101
-
102
- - name: Create Release PR or Publish
103
- id: changesets
104
- uses: changesets/action@v1
105
- with:
106
- version: pnpm changeset version
107
- publish: pnpm changeset publish
108
- title: ${{ steps.release-info.outputs.title || 'Version Packages' }}
109
- commit: ${{ steps.release-info.outputs.commit || 'Version Packages' }}
110
- env:
111
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
112
- NPM_CONFIG_PROVENANCE: true
113
-
114
- - name: Create GitHub releases
115
- if: steps.changesets.outputs.published == 'true'
116
- env:
117
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
118
- PUBLISHED_PACKAGES: ${{ steps.changesets.outputs.publishedPackages }}
119
- run: |
120
- node <<'NODE'
121
- const { execSync } = require("node:child_process");
122
-
123
- const published = JSON.parse(process.env.PUBLISHED_PACKAGES || "[]");
124
-
125
- for (const pkg of published) {
126
- const shortName = pkg.name.replace(/^@[^/]+\//, "");
127
- const tag = `${shortName}@${pkg.version}`;
128
-
129
- const existing = execSync(`git tag --list ${tag}`, { encoding: "utf8" }).trim();
130
- if (!existing) {
131
- execSync(`git tag ${tag}`);
132
- execSync(`git push origin ${tag}`);
133
- }
134
-
135
- let hasRelease = false;
136
- try {
137
- const output = execSync(`gh release view ${tag} --json tagName --jq .tagName`, {
138
- stdio: ["ignore", "pipe", "ignore"],
139
- }).toString().trim();
140
- hasRelease = output.length > 0;
141
- } catch {
142
- hasRelease = false;
143
- }
144
-
145
- if (!hasRelease) {
146
- execSync(`gh release create ${tag} --title ${tag} --notes "Release ${tag}"`, {
147
- stdio: "inherit",
148
- });
149
- }
150
- }
151
- NODE
package/.husky/pre-commit DELETED
@@ -1,3 +0,0 @@
1
- pnpm run typecheck
2
- pnpm run lint
3
- pnpm run format
package/AGENTS.md DELETED
@@ -1,69 +0,0 @@
1
- # pi-synthetic
2
-
3
- Public Pi extension providing open-source language models via Synthetic's API. People could be using this, so consider backwards compatibility when making changes.
4
-
5
- Pi is pre-1.0.0, so breaking changes can happen between Pi versions. This extension must stay up to date with Pi or things will break.
6
-
7
- ## Stack
8
-
9
- - TypeScript (strict mode)
10
- - pnpm 10.26.1
11
- - Biome for linting/formatting
12
- - Changesets for versioning
13
-
14
- ## Scripts
15
-
16
- ```bash
17
- pnpm typecheck # Type check
18
- pnpm lint # Lint (runs on pre-commit)
19
- pnpm format # Format
20
- pnpm changeset # Create changeset for versioning
21
- ```
22
-
23
- ## Structure
24
-
25
- ```
26
- src/
27
- index.ts # Extension entry, registers provider
28
- providers/
29
- index.ts # Provider registration
30
- models.ts # Hardcoded model definitions
31
- ```
32
-
33
- ## Conventions
34
-
35
- - API key comes from environment (`SYNTHETIC_API_KEY`)
36
- - Uses OpenAI-compatible API at `https://api.synthetic.new/openai/v1`
37
- - Models are hardcoded in `src/providers/models.ts`
38
- - Update model list when Synthetic adds new models
39
-
40
- ## Adding Models
41
-
42
- Edit `src/providers/models.ts`:
43
-
44
- ```typescript
45
- {
46
- id: "hf:vendor/model-name",
47
- name: "vendor/model-name",
48
- reasoning: true/false,
49
- input: ["text"] or ["text", "image"],
50
- cost: {
51
- input: 0.55, // $ per million tokens
52
- output: 2.19,
53
- cacheRead: 0.55,
54
- cacheWrite: 0
55
- },
56
- contextWindow: 202752,
57
- maxTokens: 65536
58
- }
59
- ```
60
-
61
- Get pricing from `https://api.synthetic.new/openai/v1/models`.
62
-
63
- ## Versioning
64
-
65
- Uses changesets. Run `pnpm changeset` before committing user-facing changes.
66
-
67
- - `patch`: bug fixes, model updates
68
- - `minor`: new models, features
69
- - `major`: breaking changes
package/CHANGELOG.md DELETED
@@ -1,91 +0,0 @@
1
- # @aliou/pi-synthetic
2
-
3
- ## 0.4.6
4
-
5
- ### Patch Changes
6
-
7
- - 6180572: mark pi SDK peer deps as optional to prevent koffi OOM in Gondolin VMs
8
- - fe8094f: register synthetic web search tool at init time and move availability checks to hooks
9
-
10
- ## 0.4.5
11
-
12
- ### Patch Changes
13
-
14
- - 7489bc0: update model list: add nvidia/Kimi-K2.5-NVFP4, remove 6 discontinued models
15
-
16
- ## 0.4.4
17
-
18
- ### Patch Changes
19
-
20
- - 86a3145: Fix quotas command showing duplicate notification in TUI mode
21
- - f94cc6b: fix: register search tool at init time so it's available when pi collects tools
22
-
23
- ## 0.4.3
24
-
25
- ### Patch Changes
26
-
27
- - 7dc1d80: Defer subscription check to session_start for non-blocking extension init.
28
-
29
- ## 0.4.2
30
-
31
- ### Patch Changes
32
-
33
- - d9af905: Add demo video URL for the Pi package browser.
34
-
35
- ## 0.4.1
36
-
37
- ### Patch Changes
38
-
39
- - aba3bb8: fix: use correct /v2/quotas endpoint for subscription access check
40
-
41
- ## 0.4.0
42
-
43
- ### Minor Changes
44
-
45
- - 5cca252: Add `/synthetic:quotas` command to display API usage quotas
46
-
47
- A new slash command that shows your Synthetic API subscription quotas in a rich terminal UI:
48
-
49
- - Visual usage bar with color-coded severity (green/yellow/red based on usage)
50
- - Aligned columns showing limit, used, and remaining requests
51
- - ISO8601 renewal timestamp with relative time formatting (e.g., "in 5 hours")
52
- - Closes on any key press
53
-
54
- The command is only registered when `SYNTHETIC_API_KEY` environment variable is set.
55
-
56
- - a8cacfb: Add Synthetic web search tool
57
-
58
- New tool `synthetic_web_search` allows agents to search the web using Synthetic's zero-data-retention API. Returns search results with titles, URLs, content snippets, and publication dates.
59
-
60
- **Note:** Search is a subscription-only feature. The tool will only be registered if the `SYNTHETIC_API_KEY` belongs to an active subscription (verified via the usage endpoint).
61
-
62
- ## 0.3.0
63
-
64
- ### Minor Changes
65
-
66
- - 5f67daf: Switch from Anthropic to OpenAI API endpoints
67
-
68
- - Change API endpoint from `/anthropic` to `/openai/v1`
69
- - Update from `anthropic-messages` to `openai-completions` API
70
- - Add compatibility flags for proper role handling (`supportsDeveloperRole: false`)
71
- - Use standard `max_tokens` field instead of `max_completion_tokens`
72
-
73
- ## 0.2.0
74
-
75
- ### Minor Changes
76
-
77
- - 58d21ca: Fix model configurations from Synthetic API
78
-
79
- - Update maxTokens for all Synthetic models using values from models.dev (synthetic provider)
80
- - Fix Kimi-K2-Instruct-0905 reasoning flag to false
81
-
82
- ## 0.1.0
83
-
84
- ### Minor Changes
85
-
86
- - 4a32d18: Initial release with 19 open-source models
87
-
88
- - Add Synthetic provider with Anthropic-compatible API
89
- - Support for DeepSeek, Qwen, MiniMax, Kimi, Llama, GLM models
90
- - Vision and reasoning capabilities where available
91
- - Hardcoded model definitions with per-token pricing
package/biome.json DELETED
@@ -1,30 +0,0 @@
1
- {
2
- "$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
3
- "vcs": {
4
- "enabled": true,
5
- "clientKind": "git",
6
- "useIgnoreFile": true
7
- },
8
- "files": {
9
- "includes": ["**/*.ts", "**/*.json"],
10
- "ignoreUnknown": true
11
- },
12
- "assist": {
13
- "actions": {
14
- "source": {
15
- "organizeImports": "on"
16
- }
17
- }
18
- },
19
- "linter": {
20
- "enabled": true,
21
- "rules": {
22
- "recommended": true
23
- }
24
- },
25
- "formatter": {
26
- "enabled": true,
27
- "indentStyle": "space",
28
- "indentWidth": 2
29
- }
30
- }
package/shell.nix DELETED
@@ -1,10 +0,0 @@
1
- {
2
- pkgs ? import <nixpkgs> { },
3
- }:
4
-
5
- pkgs.mkShell {
6
- buildInputs = with pkgs; [
7
- nodejs
8
- pnpm_10
9
- ];
10
- }
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "skipLibCheck": true,
9
- "forceConsistentCasingInFileNames": true,
10
- "resolveJsonModule": true,
11
- "noEmit": true
12
- },
13
- "include": ["src/**/*"],
14
- "exclude": ["node_modules"]
15
- }