@agi-cli/sdk 0.1.99 → 0.1.101

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@agi-cli/sdk",
3
- "version": "0.1.99",
3
+ "version": "0.1.101",
4
4
  "description": "AI agent SDK for building intelligent assistants - tree-shakable and comprehensive",
5
5
  "author": "ntishxyz",
6
6
  "license": "MIT",
@@ -92,12 +92,16 @@
92
92
  "@ai-sdk/openai-compatible": "^1.0.18",
93
93
  "@openauthjs/openauth": "^0.4.3",
94
94
  "@openrouter/ai-sdk-provider": "^1.2.0",
95
+ "@solana/web3.js": "^1.95.2",
95
96
  "ai": "^5.0.43",
97
+ "bs58": "^6.0.0",
96
98
  "bun-pty": "^0.3.2",
97
99
  "diff": "^8.0.2",
98
100
  "fast-glob": "^3.3.2",
99
101
  "hono": "^4.9.7",
100
102
  "opencode-anthropic-auth": "^0.0.2",
103
+ "tweetnacl": "^1.0.3",
104
+ "x402": "^0.7.1",
101
105
  "zod": "^4.1.8"
102
106
  },
103
107
  "devDependencies": {
@@ -24,6 +24,7 @@ const DEFAULTS: {
24
24
  google: { enabled: true },
25
25
  openrouter: { enabled: false },
26
26
  opencode: { enabled: false },
27
+ solforge: { enabled: false },
27
28
  },
28
29
  };
29
30
 
@@ -31,6 +31,7 @@ export async function isAuthorized(
31
31
  const info = auth[provider];
32
32
  if (info?.type === 'api' && info.key) return true;
33
33
  if (info?.type === 'oauth' && info.refresh && info.access) return true;
34
+ if (info?.type === 'wallet' && info.secret) return true;
34
35
  return false;
35
36
  }
36
37
 
@@ -42,8 +43,13 @@ export async function ensureEnv(
42
43
  if (readEnvKey(provider)) return;
43
44
  const { auth } = await read(projectRoot);
44
45
  const stored = auth[provider];
45
- const key = stored?.type === 'api' ? stored.key : undefined;
46
- if (key) setEnvKey(provider, key);
46
+ const value =
47
+ stored?.type === 'api'
48
+ ? stored.key
49
+ : stored?.type === 'wallet'
50
+ ? stored.secret
51
+ : undefined;
52
+ if (value) setEnvKey(provider, value);
47
53
  }
48
54
 
49
55
  export async function writeDefaults(
@@ -3,14 +3,15 @@ import { anthropic, createAnthropic } from '@ai-sdk/anthropic';
3
3
  import { google } from '@ai-sdk/google';
4
4
  import { createOpenRouter } from '@openrouter/ai-sdk-provider';
5
5
  import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
6
- import { catalog } from '../../../providers/src/index.ts';
6
+ import { catalog, createSolforgeModel } from '../../../providers/src/index.ts';
7
7
 
8
8
  export type ProviderName =
9
9
  | 'openai'
10
10
  | 'anthropic'
11
11
  | 'google'
12
12
  | 'openrouter'
13
- | 'opencode';
13
+ | 'opencode'
14
+ | 'solforge';
14
15
 
15
16
  export type ModelConfig = {
16
17
  apiKey?: string;
@@ -110,6 +111,27 @@ export async function resolveModel(
110
111
  return ocOpenAI(resolvedModelId);
111
112
  }
112
113
 
114
+ if (provider === 'solforge') {
115
+ const privateKey = config.apiKey || process.env.SOLFORGE_PRIVATE_KEY || '';
116
+ if (!privateKey) {
117
+ throw new Error(
118
+ 'Solforge provider requires SOLFORGE_PRIVATE_KEY (base58 Solana secret).',
119
+ );
120
+ }
121
+ const baseURL = config.baseURL || process.env.SOLFORGE_BASE_URL;
122
+ const rpcURL = process.env.SOLFORGE_SOLANA_RPC_URL;
123
+ const topupAmount = process.env.SOLFORGE_TOPUP_MICRO_USDC;
124
+ return createSolforgeModel(
125
+ model,
126
+ { privateKey },
127
+ {
128
+ baseURL,
129
+ rpcURL,
130
+ topupAmountMicroUsdc: topupAmount,
131
+ },
132
+ );
133
+ }
134
+
113
135
  throw new Error(`Unsupported provider: ${provider}`);
114
136
  }
115
137
 
@@ -20,8 +20,6 @@ export class TerminalManager {
20
20
  private terminals = new Map<string, Terminal>();
21
21
  private cleanupTimers = new Map<string, NodeJS.Timeout>();
22
22
 
23
- constructor() {}
24
-
25
23
  create(options: CreateTerminalOptions): Terminal {
26
24
  if (this.terminals.size >= MAX_TERMINALS) {
27
25
  throw new Error(`Maximum ${MAX_TERMINALS} terminals reached`);
@@ -186,7 +186,8 @@ export function buildTerminalTool(
186
186
 
187
187
  const output = term.read(params.lines);
188
188
  const normalized = output.map(normalizeTerminalLine);
189
- const text = normalized.join('\n').replace(/\u0000/g, '');
189
+ const joined = normalized.join('\n');
190
+ const text = joined.split(String.fromCharCode(0)).join('');
190
191
 
191
192
  const response: {
192
193
  ok: true;
package/src/index.ts CHANGED
@@ -52,6 +52,14 @@ export {
52
52
  readEnvKey,
53
53
  setEnvKey,
54
54
  } from './providers/src/index.ts';
55
+ export {
56
+ createSolforgeFetch,
57
+ createSolforgeModel,
58
+ } from './providers/src/index.ts';
59
+ export type {
60
+ SolforgeAuth,
61
+ SolforgeProviderOptions,
62
+ } from './providers/src/index.ts';
55
63
 
56
64
  // =======================
57
65
  // Authentication (from internal auth module)
@@ -64,8 +64,11 @@ export async function providerBasePrompt(
64
64
  }
65
65
  }
66
66
 
67
- // 2) Provider-family fallback for openrouter/opencode using embedded defaults
68
- if ((id === 'openrouter' || id === 'opencode') && modelId) {
67
+ // 2) Provider-family fallback for openrouter/opencode/solforge using embedded defaults
68
+ if (
69
+ (id === 'openrouter' || id === 'opencode' || id === 'solforge') &&
70
+ modelId
71
+ ) {
69
72
  const family = inferFamilyFromModel(modelId);
70
73
  if (family) {
71
74
  const embedded = (
@@ -0,0 +1,93 @@
1
+ import type {
2
+ ModelInfo,
3
+ ProviderCatalogEntry,
4
+ ProviderId,
5
+ } from '../../types/src/index.ts';
6
+
7
+ type CatalogMap = Partial<Record<ProviderId, ProviderCatalogEntry>>;
8
+
9
+ const SOLFORGE_ID: ProviderId = 'solforge';
10
+ const SOLFORGE_SOURCES: Array<{ id: ProviderId; npm: string }> = [
11
+ {
12
+ id: 'openai',
13
+ npm: '@ai-sdk/openai',
14
+ },
15
+ {
16
+ id: 'anthropic',
17
+ npm: '@ai-sdk/anthropic',
18
+ },
19
+ ];
20
+
21
+ function cloneModel(model: ModelInfo): ModelInfo {
22
+ return {
23
+ ...model,
24
+ modalities: model.modalities
25
+ ? {
26
+ input: model.modalities.input
27
+ ? [...model.modalities.input]
28
+ : undefined,
29
+ output: model.modalities.output
30
+ ? [...model.modalities.output]
31
+ : undefined,
32
+ }
33
+ : undefined,
34
+ cost: model.cost ? { ...model.cost } : undefined,
35
+ limit: model.limit ? { ...model.limit } : undefined,
36
+ provider: model.provider ? { ...model.provider } : undefined,
37
+ };
38
+ }
39
+
40
+ function buildSolforgeEntry(base: CatalogMap): ProviderCatalogEntry | null {
41
+ const solforgeModels = SOLFORGE_SOURCES.flatMap(({ id, npm }) => {
42
+ const sourceModels = base[id]?.models ?? [];
43
+ return sourceModels.map((model) => {
44
+ const cloned = cloneModel(model);
45
+ cloned.provider = { ...(cloned.provider ?? {}), npm };
46
+ return cloned;
47
+ });
48
+ });
49
+
50
+ if (!solforgeModels.length) return null;
51
+
52
+ // Prefer OpenAI-family models first so defaults are stable
53
+ solforgeModels.sort((a, b) => {
54
+ const providerA = a.provider?.npm ?? '';
55
+ const providerB = b.provider?.npm ?? '';
56
+ if (providerA === providerB) {
57
+ return a.id.localeCompare(b.id);
58
+ }
59
+ if (providerA === '@ai-sdk/openai') return -1;
60
+ if (providerB === '@ai-sdk/openai') return 1;
61
+ return providerA.localeCompare(providerB);
62
+ });
63
+
64
+ const defaultModelId = 'gpt-4o-mini';
65
+ const defaultIdx = solforgeModels.findIndex((m) => m.id === defaultModelId);
66
+ if (defaultIdx > 0) {
67
+ const [picked] = solforgeModels.splice(defaultIdx, 1);
68
+ solforgeModels.unshift(picked);
69
+ }
70
+
71
+ return {
72
+ id: SOLFORGE_ID,
73
+ label: 'Solforge',
74
+ env: ['SOLFORGE_PRIVATE_KEY'],
75
+ api: 'https://ai.solforge.sh/v1',
76
+ doc: 'https://ai.solforge.sh/docs',
77
+ npm: '@ai-sdk/openai-compatible',
78
+ models: solforgeModels,
79
+ };
80
+ }
81
+
82
+ export function mergeManualCatalog(
83
+ base: CatalogMap,
84
+ ): Record<ProviderId, ProviderCatalogEntry> {
85
+ const manualEntry = buildSolforgeEntry(base);
86
+ const merged: Record<ProviderId, ProviderCatalogEntry> = {
87
+ ...(base as Record<ProviderId, ProviderCatalogEntry>),
88
+ };
89
+ if (manualEntry) {
90
+ merged[SOLFORGE_ID] = manualEntry;
91
+ }
92
+ return merged;
93
+ }
@@ -0,0 +1,9 @@
1
+ import type {
2
+ ProviderCatalogEntry,
3
+ ProviderId,
4
+ } from '../../types/src/index.ts';
5
+ import { catalog as generatedCatalog } from './catalog.ts';
6
+ import { mergeManualCatalog } from './catalog-manual.ts';
7
+
8
+ export const catalog: Record<ProviderId, ProviderCatalogEntry> =
9
+ mergeManualCatalog(generatedCatalog);