toolpack-cli 1.0.1 → 1.1.0-SNAPSHOT.202603211

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.
@@ -0,0 +1 @@
1
+ export declare function KnowledgeLoader(): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { useToolpack } from '../context/ToolpackContext.js';
4
+ import { useTheme } from '../theme/ThemeContext.js';
5
+ const BAR_WIDTH = 30;
6
+ export function KnowledgeLoader() {
7
+ const { knowledgeProgress } = useToolpack();
8
+ const { theme } = useTheme();
9
+ if (!knowledgeProgress || knowledgeProgress.phase === 'complete') {
10
+ return null;
11
+ }
12
+ const percentage = Math.min(knowledgeProgress.percentage ?? 0, 99);
13
+ const filled = Math.round((percentage / 100) * BAR_WIDTH);
14
+ const label = knowledgeProgress.phase === 'start'
15
+ ? 'Scanning knowledge sources...'
16
+ : `Embedding content (${percentage}%)`;
17
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.colors.border, paddingX: 2, paddingY: 1, marginBottom: 1, children: [_jsx(Text, { color: theme.colors.primary, children: "Knowledge base initializing\u2026" }), _jsx(Text, { color: theme.colors.text, children: label }), _jsxs(Text, { color: theme.colors.textSecondary, children: ["[", '#'.repeat(Math.max(0, filled)), ' '.repeat(Math.max(0, BAR_WIDTH - filled)), "] ", percentage, "%"] }), knowledgeProgress.currentSource && (_jsxs(Text, { color: theme.colors.textSecondary, children: ["Source: ", knowledgeProgress.currentSource] }))] }));
18
+ }
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { Toolpack, ModeConfig, ToolLogEvent, WorkflowProgress } from 'toolpack-sdk';
2
+ import { Toolpack, ModeConfig, ToolLogEvent, WorkflowProgress, EmbeddingProgressEvent } from 'toolpack-sdk';
3
3
  /**
4
4
  * Clean React Context wrapper for the Toolpack SDK.
5
5
  * Manages SDK-related state only: modes, models, and the toolpack instance.
@@ -47,6 +47,7 @@ interface ToolpackContextType {
47
47
  setToolsUnsupportedWarning: (msg: string) => void;
48
48
  configSource: 'local' | 'global' | 'base' | 'default';
49
49
  activeConfigPath: string | null;
50
+ knowledgeProgress: EmbeddingProgressEvent | null;
50
51
  }
51
52
  export declare function ToolpackProvider({ children }: {
52
53
  children: ReactNode;
@@ -1,11 +1,15 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useEffect, useState, useCallback, } from 'react';
3
- import { Toolpack, createMode, loadRuntimeConfig, getRuntimeConfigStatus, } from 'toolpack-sdk';
3
+ import { Toolpack, createMode, loadRuntimeConfig, getRuntimeConfigStatus, Knowledge, MemoryProvider, MarkdownSource, JSONSource, SQLiteTextSource, } from 'toolpack-sdk';
4
+ import Database from 'better-sqlite3';
4
5
  import { XAIAdapter } from '../custom-providers/XAIAdapter.js';
5
6
  import { skillToolsProject } from '../custom-tools/skill-tools/index.js';
6
7
  import * as fs from 'fs';
7
8
  import * as os from 'os';
8
9
  import * as path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
9
13
  const ToolpackContext = createContext(undefined);
10
14
  export function ToolpackProvider({ children }) {
11
15
  const [toolpack, setToolpack] = useState(null);
@@ -21,6 +25,7 @@ export function ToolpackProvider({ children }) {
21
25
  const [toolsUnsupportedWarning, setToolsUnsupportedWarning] = useState(null);
22
26
  const [configSource, setConfigSource] = useState('default');
23
27
  const [activeConfigPath, setActiveConfigPath] = useState(null);
28
+ const [knowledgeProgress, setKnowledgeProgress] = useState(null);
24
29
  useEffect(() => {
25
30
  async function init() {
26
31
  // Get config status
@@ -41,6 +46,28 @@ export function ToolpackProvider({ children }) {
41
46
  systemPrompt: 'You are a helpful assistant. Provide clear and concise responses.',
42
47
  blockAllTools: true,
43
48
  });
49
+ const knowledgeBasePath = ensureGlobalKnowledgeAssets();
50
+ const kb = await Knowledge.create({
51
+ provider: new MemoryProvider(),
52
+ sources: [
53
+ new MarkdownSource(path.join(knowledgeBasePath, '**/*.md'), { namespace: 'docs' }),
54
+ new JSONSource(path.join(knowledgeBasePath, 'toolpack-cli.json'), {
55
+ chunkBy: 'item',
56
+ contentFields: ['title', 'description'],
57
+ metadataFields: ['id', 'category'],
58
+ namespace: 'json',
59
+ }),
60
+ new SQLiteTextSource(path.join(knowledgeBasePath, 'toolpack-guides.db'), {
61
+ table: 'guides',
62
+ contentColumns: ['title', 'body'],
63
+ metadataColumns: ['category'],
64
+ namespace: 'guides',
65
+ }),
66
+ ],
67
+ onEmbeddingProgress: event => {
68
+ setKnowledgeProgress(event);
69
+ },
70
+ });
44
71
  const instance = await Toolpack.init({
45
72
  defaultMode: 'agent',
46
73
  configPath: tempConfigPath, // Use our merged temp config
@@ -55,6 +82,7 @@ export function ToolpackProvider({ children }) {
55
82
  customModes: [simpleChat],
56
83
  customProviders: [new XAIAdapter()],
57
84
  customTools: [skillToolsProject],
85
+ knowledge: kb,
58
86
  modeOverrides: {
59
87
  agent: {
60
88
  // Override the agent mode system prompt to include skill search and read
@@ -210,6 +238,7 @@ export function ToolpackProvider({ children }) {
210
238
  setToolsUnsupportedWarning,
211
239
  configSource,
212
240
  activeConfigPath,
241
+ knowledgeProgress,
213
242
  }, children: children }));
214
243
  }
215
244
  export function useToolpack() {
@@ -219,3 +248,85 @@ export function useToolpack() {
219
248
  }
220
249
  return context;
221
250
  }
251
+ function ensureGlobalKnowledgeAssets() {
252
+ const bundledDir = path.join(__dirname, '..', '..', 'knowledge');
253
+ const globalDir = path.join(os.homedir(), '.toolpack');
254
+ const targetDir = path.join(globalDir, 'knowledge');
255
+ fs.mkdirSync(globalDir, { recursive: true });
256
+ if (fs.existsSync(bundledDir)) {
257
+ copyDirectoryRecursive(bundledDir, targetDir);
258
+ }
259
+ seedKnowledgeSamples(targetDir);
260
+ return targetDir;
261
+ }
262
+ function copyDirectoryRecursive(source, destination) {
263
+ if (!fs.existsSync(source)) {
264
+ return;
265
+ }
266
+ const stats = fs.statSync(source);
267
+ if (stats.isDirectory()) {
268
+ fs.mkdirSync(destination, { recursive: true });
269
+ for (const entry of fs.readdirSync(source)) {
270
+ const srcPath = path.join(source, entry);
271
+ const destPath = path.join(destination, entry);
272
+ copyDirectoryRecursive(srcPath, destPath);
273
+ }
274
+ return;
275
+ }
276
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
277
+ fs.copyFileSync(source, destination);
278
+ }
279
+ function seedKnowledgeSamples(targetDir) {
280
+ fs.mkdirSync(targetDir, { recursive: true });
281
+ const markdownPath = path.join(targetDir, 'toolpack-overview.md');
282
+ const jsonPath = path.join(targetDir, 'toolpack-cli.json');
283
+ const sqlitePath = path.join(targetDir, 'toolpack-guides.db');
284
+ if (!fs.existsSync(markdownPath)) {
285
+ fs.writeFileSync(markdownPath, `# Toolpack SDK Overview\n\nThe Toolpack SDK provides a provider-agnostic agent runtime with built-in tooling, workflow automation, and knowledge retrieval.\n\n## Highlights\n- Unified API across OpenAI, Anthropic, Gemini, and local providers\n- Configurable agent modes (agent, chat, simpleChat, custom modes)\n- Knowledge module for RAG with Markdown/JSON/SQLite sources\n- Workflow engine with hooks for pre/post tool execution\n\n## CLI Integration\nThe sample CLI demonstrates multi-mode chat, provider switching, history, telemetry, and automatic knowledge bootstrapping.\n`);
286
+ }
287
+ if (!fs.existsSync(jsonPath)) {
288
+ fs.writeFileSync(jsonPath, JSON.stringify([
289
+ {
290
+ id: 'cli_modes',
291
+ title: 'Toolpack CLI Modes',
292
+ description: 'The CLI ships with agent, chat, and simpleChat modes plus an example custom mode.',
293
+ capabilities: ['mode switching', 'history', 'provider selection'],
294
+ category: 'cli',
295
+ },
296
+ {
297
+ id: 'sdk_features',
298
+ title: 'Toolpack SDK Features',
299
+ description: 'Unified provider API, workflow engine, tool telemetry, and knowledge integration.',
300
+ category: 'sdk',
301
+ },
302
+ ], null, 2));
303
+ }
304
+ if (!fs.existsSync(sqlitePath)) {
305
+ fs.mkdirSync(path.dirname(sqlitePath), { recursive: true });
306
+ const db = new Database(sqlitePath);
307
+ try {
308
+ db.exec(`CREATE TABLE IF NOT EXISTS guides (
309
+ id TEXT PRIMARY KEY,
310
+ title TEXT,
311
+ body TEXT,
312
+ category TEXT
313
+ );`);
314
+ const insert = db.prepare('INSERT OR REPLACE INTO guides (id, title, body, category) VALUES (@id, @title, @body, @category)');
315
+ insert.run({
316
+ id: 'sdk_init',
317
+ title: 'Initializing Toolpack SDK',
318
+ body: 'Use Toolpack.init with provider configs, tools flag, knowledge instance, and custom modes to bootstrap your agent runtime.',
319
+ category: 'sdk',
320
+ });
321
+ insert.run({
322
+ id: 'cli_setup',
323
+ title: 'Toolpack CLI Setup',
324
+ body: 'Install dependencies, configure toolpack.config.json, and start via `toolpack` to enter the Ink interface.',
325
+ category: 'cli',
326
+ });
327
+ }
328
+ finally {
329
+ db.close();
330
+ }
331
+ }
332
+ }
@@ -10,10 +10,12 @@ import { HomeInput } from '../components/HomeInput.js';
10
10
  import { ModeSelect } from '../components/common/ModeSelect.js';
11
11
  import { ModelSelect } from '../components/common/ModelSelect.js';
12
12
  import { HistorySelect } from '../components/common/HistorySelect.js';
13
+ import { KnowledgeLoader } from '../components/KnowledgeLoader.js';
13
14
  export function HomeScreen() {
14
15
  const { theme } = useTheme();
15
16
  const { stdout } = useStdout();
16
- const { setMode, setModel, models } = useToolpack();
17
+ const { setMode, setModel, models, knowledgeProgress } = useToolpack();
18
+ const knowledgeReady = !knowledgeProgress || knowledgeProgress.phase === 'complete';
17
19
  const { loadConversation, setScreen } = useConversation();
18
20
  // 0 = TextInput, 1 = Mode, 2 = Model, 3 = History
19
21
  const [focusedIndex, setFocusedIndex] = useState(0);
@@ -37,7 +39,7 @@ export function HomeScreen() {
37
39
  setScreen('settings');
38
40
  }
39
41
  });
40
- return (_jsxs(Box, { width: stdout.columns, height: stdout.rows - 1, flexDirection: "column", position: "relative", children: [_jsxs(Box, { width: "100%", alignItems: "center", flexDirection: "column", paddingTop: 6, flexShrink: 0, children: [_jsx(Logo, {}), _jsx(AppInfo, {})] }), _jsx(Box, { flexGrow: 1, width: "100%", justifyContent: "center", alignItems: "center", flexDirection: "column", children: _jsx(Box, { width: "80%", children: _jsx(HomeInput, { focusedIndex: focusedIndex, showModeSelect: showModeSelect, setShowModeSelect: setShowModeSelect, showModelSelect: showModelSelect, setShowModelSelect: setShowModelSelect, showHistorySelect: showHistorySelect, setShowHistorySelect: setShowHistorySelect }) }) }), _jsx(Box, { width: "100%", flexDirection: "column", alignItems: "center", paddingBottom: 1, flexShrink: 0, children: _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.colors.textSecondary, children: [_jsx(Text, { color: "#eab308", bold: true, children: "\u2022 Note" }), ' ', "If you are using local models, make sure to have them downloaded and available."] }) }) }), showModeSelect && (_jsx(ModeSelect, { onSelect: val => {
42
+ return (_jsxs(Box, { width: stdout.columns, height: stdout.rows - 1, flexDirection: "column", position: "relative", children: [_jsxs(Box, { width: "100%", alignItems: "center", flexDirection: "column", paddingTop: 6, flexShrink: 0, children: [_jsx(Logo, {}), _jsx(AppInfo, {}), knowledgeProgress && knowledgeProgress.phase !== 'complete' && (_jsx(Box, { width: "100%", marginTop: 1, alignItems: "center", justifyContent: "center", children: _jsx(KnowledgeLoader, {}) }))] }), _jsx(Box, { flexGrow: 1, width: "100%", justifyContent: "center", alignItems: "center", flexDirection: "column", children: knowledgeReady ? (_jsx(Box, { width: "80%", children: _jsx(HomeInput, { focusedIndex: focusedIndex, showModeSelect: showModeSelect, setShowModeSelect: setShowModeSelect, showModelSelect: showModelSelect, setShowModelSelect: setShowModelSelect, showHistorySelect: showHistorySelect, setShowHistorySelect: setShowHistorySelect }) })) : (_jsx(Text, { color: theme.colors.textSecondary, children: "Preparing knowledge workspace\u2026" })) }), _jsx(Box, { width: "100%", flexDirection: "column", alignItems: "center", paddingBottom: 1, flexShrink: 0, children: _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.colors.textSecondary, children: [_jsx(Text, { color: "#eab308", bold: true, children: "\u2022 Note" }), ' ', "If you are using local models, make sure to have them downloaded and available."] }) }) }), showModeSelect && (_jsx(ModeSelect, { onSelect: val => {
41
43
  setMode(val);
42
44
  setShowModeSelect(false);
43
45
  setFocusedIndex(0); // Return focus to input
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolpack-cli",
3
- "version": "1.0.1",
3
+ "version": "1.1.0-SNAPSHOT.202603211",
4
4
  "description": "Rich interactive command-line interface directly powering the Toolpack SDK",
5
5
  "license": "Apache-2.0",
6
6
  "preferGlobal": true,
@@ -56,7 +56,7 @@
56
56
  "node-pty": "^1.1.0",
57
57
  "open": "^11.0.0",
58
58
  "react": "^18.2.0",
59
- "toolpack-sdk": "latest",
59
+ "toolpack-sdk": "1.1.0-SNAPSHOT",
60
60
  "uuid": "^13.0.0"
61
61
  },
62
62
  "devDependencies": {