@vtstech/pi-shared 1.2.2 → 1.2.3

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/config-io.js CHANGED
@@ -1,18 +1,8 @@
1
- // shared/config-io.ts
2
- import * as fs from "node:fs";
3
- import * as path from "node:path";
4
- import os from "node:os";
5
-
6
- // shared/debug.ts
7
- var DEBUG_ENABLED = process.env.PI_EXTENSIONS_DEBUG === "1";
8
- function debugLog(module, message, ...args) {
9
- if (!DEBUG_ENABLED) return;
10
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
11
- console.debug(`[pi-ext:${module}] ${timestamp} ${message}`, ...args);
12
- }
13
-
14
- // shared/config-io.ts
15
- var PI_AGENT_DIR = path.join(os.homedir(), ".pi", "agent");
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import os from "os";
4
+ import { debugLog } from "./debug";
5
+ const PI_AGENT_DIR = path.join(os.homedir(), ".pi", "agent");
16
6
  function readJsonConfig(filePath, defaultValue = {}) {
17
7
  try {
18
8
  if (fs.existsSync(filePath)) {
@@ -35,10 +25,10 @@ function writeJsonConfig(filePath, data) {
35
25
  fs.writeFileSync(filePath, content, "utf-8");
36
26
  }
37
27
  }
38
- var SETTINGS_PATH = path.join(PI_AGENT_DIR, "settings.json");
39
- var SECURITY_PATH = path.join(PI_AGENT_DIR, "security.json");
40
- var REACT_MODE_PATH = path.join(PI_AGENT_DIR, "react-mode.json");
41
- var MODEL_TEST_CONFIG_PATH = path.join(PI_AGENT_DIR, "model-test-config.json");
28
+ const SETTINGS_PATH = path.join(PI_AGENT_DIR, "settings.json");
29
+ const SECURITY_PATH = path.join(PI_AGENT_DIR, "security.json");
30
+ const REACT_MODE_PATH = path.join(PI_AGENT_DIR, "react-mode.json");
31
+ const MODEL_TEST_CONFIG_PATH = path.join(PI_AGENT_DIR, "model-test-config.json");
42
32
  function readSettings() {
43
33
  return readJsonConfig(SETTINGS_PATH);
44
34
  }
package/debug.js CHANGED
@@ -1,5 +1,4 @@
1
- // shared/debug.ts
2
- var DEBUG_ENABLED = process.env.PI_EXTENSIONS_DEBUG === "1";
1
+ const DEBUG_ENABLED = process?.env?.PI_EXTENSIONS_DEBUG === "1";
3
2
  function debugLog(module, message, ...args) {
4
3
  if (!DEBUG_ENABLED) return;
5
4
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
package/errors.js CHANGED
@@ -1,51 +1,49 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
-
5
- // shared/errors.ts
6
- var ExtensionError = class extends Error {
4
+ class ExtensionError extends Error {
7
5
  constructor(message, code) {
8
6
  super(message);
9
7
  __publicField(this, "code", code);
10
8
  this.name = "ExtensionError";
11
9
  }
12
- };
13
- var ConfigError = class extends ExtensionError {
10
+ }
11
+ class ConfigError extends ExtensionError {
14
12
  constructor(message) {
15
13
  super(message, "CONFIG_ERROR");
16
14
  this.name = "ConfigError";
17
15
  }
18
- };
19
- var ApiError = class extends ExtensionError {
16
+ }
17
+ class ApiError extends ExtensionError {
20
18
  constructor(message, statusCode, url) {
21
19
  super(message, "API_ERROR");
22
20
  __publicField(this, "statusCode", statusCode);
23
21
  __publicField(this, "url", url);
24
22
  this.name = "ApiError";
25
23
  }
26
- };
27
- var ExtensionTimeoutError = class extends ExtensionError {
24
+ }
25
+ class ExtensionTimeoutError extends ExtensionError {
28
26
  constructor(message, timeoutMs) {
29
27
  super(message, "TIMEOUT");
30
28
  __publicField(this, "timeoutMs", timeoutMs);
31
29
  this.name = "ExtensionTimeoutError";
32
30
  }
33
- };
34
- var SecurityError = class extends ExtensionError {
31
+ }
32
+ class SecurityError extends ExtensionError {
35
33
  constructor(message, rule, detail) {
36
34
  super(message, "SECURITY_VIOLATION");
37
35
  __publicField(this, "rule", rule);
38
36
  __publicField(this, "detail", detail);
39
37
  this.name = "SecurityError";
40
38
  }
41
- };
42
- var ToolError = class extends ExtensionError {
39
+ }
40
+ class ToolError extends ExtensionError {
43
41
  constructor(message, toolName) {
44
42
  super(message, "TOOL_ERROR");
45
43
  __publicField(this, "toolName", toolName);
46
44
  this.name = "ToolError";
47
45
  }
48
- };
46
+ }
49
47
  export {
50
48
  ApiError,
51
49
  ConfigError,
package/format.js CHANGED
@@ -1,4 +1,3 @@
1
- // shared/format.ts
2
1
  function section(title) {
3
2
  return `
4
3
  \u2500\u2500 ${title} ${"\u2500".repeat(Math.max(1, 60 - title.length - 4))}`;
@@ -1,8 +1,7 @@
1
- // shared/model-test-utils.ts
2
1
  import * as fs from "node:fs";
3
2
  import * as os from "node:os";
4
3
  import * as path from "node:path";
5
- var CONFIG = {
4
+ const CONFIG = {
6
5
  // General API settings
7
6
  DEFAULT_TIMEOUT_MS: 999999,
8
7
  // ~16.7 minutes — effectively unlimited for slow models
@@ -41,8 +40,8 @@ var CONFIG = {
41
40
  TEST_DELAY_MS: 1e4
42
41
  // 10 seconds between tests to avoid rate limiting
43
42
  };
44
- var TEST_CONFIG_DIR = path.join(os.homedir(), ".pi", "agent");
45
- var TEST_CONFIG_PATH = path.join(TEST_CONFIG_DIR, "model-test-config.json");
43
+ const TEST_CONFIG_DIR = path.join(os.homedir(), ".pi", "agent");
44
+ const TEST_CONFIG_PATH = path.join(TEST_CONFIG_DIR, "model-test-config.json");
46
45
  function readTestConfig() {
47
46
  try {
48
47
  if (fs.existsSync(TEST_CONFIG_PATH)) {
@@ -70,7 +69,7 @@ function getEffectiveConfig() {
70
69
  TEMPERATURE: userConfig.temperature ?? CONFIG.TEMPERATURE
71
70
  };
72
71
  }
73
- var WEATHER_TOOL_DEFINITION = {
72
+ const WEATHER_TOOL_DEFINITION = {
74
73
  type: "function",
75
74
  function: {
76
75
  name: "get_weather",
@@ -145,9 +144,9 @@ function parseTextToolCall(content) {
145
144
  const { name: _, ...fnArgs } = rawArgs;
146
145
  return { fnName: textToolParsed.name, args: fnArgs };
147
146
  }
148
- var TOOL_SUPPORT_CACHE_DIR = path.join(os.homedir(), ".pi", "agent", "cache");
149
- var TOOL_SUPPORT_CACHE_PATH = path.join(TOOL_SUPPORT_CACHE_DIR, "tool_support.json");
150
- var _toolSupportCacheInMemory = null;
147
+ const TOOL_SUPPORT_CACHE_DIR = path.join(os.homedir(), ".pi", "agent", "cache");
148
+ const TOOL_SUPPORT_CACHE_PATH = path.join(TOOL_SUPPORT_CACHE_DIR, "tool_support.json");
149
+ let _toolSupportCacheInMemory = null;
151
150
  function readToolSupportCache() {
152
151
  try {
153
152
  if (fs.existsSync(TOOL_SUPPORT_CACHE_PATH)) {
@@ -182,10 +181,10 @@ function cacheToolSupport(model, support, family) {
182
181
  _toolSupportCacheInMemory = cache;
183
182
  writeToolSupportCache(cache);
184
183
  }
185
- var TEST_HISTORY_DIR = path.join(os.homedir(), ".pi", "agent", "cache");
186
- var TEST_HISTORY_PATH = path.join(TEST_HISTORY_DIR, "model-test-history.json");
187
- var MAX_HISTORY_PER_MODEL = 50;
188
- var MAX_HISTORY_TOTAL = 500;
184
+ const TEST_HISTORY_DIR = path.join(os.homedir(), ".pi", "agent", "cache");
185
+ const TEST_HISTORY_PATH = path.join(TEST_HISTORY_DIR, "model-test-history.json");
186
+ const MAX_HISTORY_PER_MODEL = 50;
187
+ const MAX_HISTORY_TOTAL = 500;
189
188
  function readTestHistory() {
190
189
  try {
191
190
  if (fs.existsSync(TEST_HISTORY_PATH)) {
@@ -267,9 +266,9 @@ function detectRegression(model, current) {
267
266
  }
268
267
  return regressions;
269
268
  }
270
- var REASONING_PROMPT = `A snail climbs 3 feet up a wall each day, but slides back 2 feet each night. The wall is 10 feet tall. How many days does it take the snail to reach the top? Think step by step and give the final answer on its own line like: ANSWER: <number>`;
271
- var TOOL_SYSTEM_PROMPT = "You are a helpful assistant. Use the available tools when needed.";
272
- var TOOL_USER_PROMPT = "What's the weather like in Paris right now?";
269
+ const REASONING_PROMPT = `A snail climbs 3 feet up a wall each day, but slides back 2 feet each night. The wall is 10 feet tall. How many days does it take the snail to reach the top? Think step by step and give the final answer on its own line like: ANSWER: <number>`;
270
+ const TOOL_SYSTEM_PROMPT = "You are a helpful assistant. Use the available tools when needed.";
271
+ const TOOL_USER_PROMPT = "What's the weather like in Paris right now?";
273
272
  async function testToolUsageUnified(chatFn, model, options) {
274
273
  const tools = options?.tools || [WEATHER_TOOL_DEFINITION];
275
274
  const systemPrompt = options?.systemPrompt || TOOL_SYSTEM_PROMPT;
package/ollama.js CHANGED
@@ -1,22 +1,12 @@
1
- // shared/ollama.ts
2
1
  import * as fs from "node:fs";
3
2
  import * as path from "node:path";
4
3
  import os from "node:os";
5
-
6
- // shared/debug.ts
7
- var DEBUG_ENABLED = process.env.PI_EXTENSIONS_DEBUG === "1";
8
- function debugLog(module, message, ...args) {
9
- if (!DEBUG_ENABLED) return;
10
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
11
- console.debug(`[pi-ext:${module}] ${timestamp} ${message}`, ...args);
12
- }
13
-
14
- // shared/ollama.ts
15
- var EXTENSION_VERSION = "1.2.2";
16
- var MODELS_JSON_PATH = path.join(os.homedir(), ".pi", "agent", "models.json");
17
- var _modelsJsonCache = null;
18
- var _ollamaBaseUrlCache = null;
19
- var CACHE_TTL_MS = 2e3;
4
+ import { debugLog } from "./debug";
5
+ const EXTENSION_VERSION = "1.2.3";
6
+ const MODELS_JSON_PATH = path.join(os.homedir(), ".pi", "agent", "models.json");
7
+ let _modelsJsonCache = null;
8
+ let _ollamaBaseUrlCache = null;
9
+ const CACHE_TTL_MS = 2e3;
20
10
  function getOllamaBaseUrl() {
21
11
  const now = Date.now();
22
12
  if (_ollamaBaseUrlCache && now - _ollamaBaseUrlCache.ts < CACHE_TTL_MS) return _ollamaBaseUrlCache.data;
@@ -71,7 +61,7 @@ function writeModelsJson(data) {
71
61
  _modelsJsonCache = null;
72
62
  _ollamaBaseUrlCache = null;
73
63
  }
74
- var _modelsJsonLock = null;
64
+ let _modelsJsonLock = null;
75
65
  async function acquireModelsJsonLock() {
76
66
  while (_modelsJsonLock) {
77
67
  await _modelsJsonLock;
@@ -99,7 +89,7 @@ async function readModifyWriteModelsJson(modifier) {
99
89
  release();
100
90
  }
101
91
  }
102
- var DEFAULT_RETRY_OPTIONS = {
92
+ const DEFAULT_RETRY_OPTIONS = {
103
93
  maxRetries: 2,
104
94
  baseDelayMs: 1e3,
105
95
  maxDelayMs: 1e4,
@@ -111,7 +101,7 @@ function backoffDelay(attempt, baseDelayMs, maxDelayMs) {
111
101
  const jitter = delay * 0.25 * (Math.random() * 2 - 1);
112
102
  return Math.max(0, Math.round(delay + jitter));
113
103
  }
114
- var RETRYABLE_ERROR_PATTERNS = [
104
+ const RETRYABLE_ERROR_PATTERNS = [
115
105
  "ECONNREFUSED",
116
106
  "ECONNRESET",
117
107
  "ENOTFOUND",
@@ -203,7 +193,7 @@ function isReasoningModel(name) {
203
193
  const lower = name.toLowerCase();
204
194
  return lower.includes("deepseek-r1") || lower.includes("qwq") || /\bo1\b/.test(lower) || /\bo3\b/.test(lower) || lower.includes("qwen3") || lower.includes("reasoning") || lower.includes("thinker") || lower.includes("thinking");
205
195
  }
206
- var BUILTIN_PROVIDERS = {
196
+ const BUILTIN_PROVIDERS = {
207
197
  openrouter: { api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", envKey: "OPENROUTER_API_KEY" },
208
198
  anthropic: { api: "anthropic-messages", baseUrl: "https://api.anthropic.com/v1", envKey: "ANTHROPIC_API_KEY" },
209
199
  google: { api: "gemini", baseUrl: "https://generativelanguage.googleapis.com", envKey: "GOOGLE_API_KEY" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtstech/pi-shared",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Shared utilities for Pi Coding Agent extensions",
5
5
  "exports": {
6
6
  "./config-io": "./config-io.js",
@@ -15,7 +15,12 @@
15
15
  "./test-report": "./test-report.js",
16
16
  "./types": "./types.js"
17
17
  },
18
- "keywords": ["pi-package", "pi", "pi-coding-agent", "pi-extensions"],
18
+ "keywords": [
19
+ "pi-package",
20
+ "pi",
21
+ "pi-coding-agent",
22
+ "pi-extensions"
23
+ ],
19
24
  "license": "MIT",
20
25
  "access": "public",
21
26
  "type": "module",
@@ -24,8 +29,5 @@
24
29
  "repository": {
25
30
  "type": "git",
26
31
  "url": "https://github.com/VTSTech/pi-coding-agent"
27
- },
28
- "peerDependencies": {
29
- "@mariozechner/pi-coding-agent": ">=0.66"
30
32
  }
31
33
  }
package/provider-sync.js CHANGED
@@ -1,4 +1,3 @@
1
- // shared/provider-sync.ts
2
1
  function mergeModels(newModels, oldModels) {
3
2
  const oldModelMap = new Map(oldModels.map((m) => [m.id, m]));
4
3
  return newModels.map((m) => {
package/react-parser.js CHANGED
@@ -1,4 +1,3 @@
1
- // shared/react-parser.ts
2
1
  function sanitizeModelJson(text) {
3
2
  text = text.replace(/:\s*True\b/g, ": true");
4
3
  text = text.replace(/:\s*False\b/g, ": false");
@@ -11,7 +10,7 @@ function sanitizeModelJson(text) {
11
10
  text = text.replace(/\\\\\\\\/g, "\\\\");
12
11
  return text;
13
12
  }
14
- var REACT_DIALECTS = [
13
+ const REACT_DIALECTS = [
15
14
  {
16
15
  name: "react",
17
16
  actionTag: "Action:",
@@ -69,14 +68,14 @@ function buildDialectPatterns(d) {
69
68
  const finalAnswerRe = fT ? new RegExp(`${fT}\\s*([\\s\\S]*?)$`, "i") : void 0;
70
69
  return { thoughtRe, actionRe, actionReSameline, actionReLoose, actionReParen, finalAnswerRe, dialect: d };
71
70
  }
72
- var ALL_DIALECT_PATTERNS = REACT_DIALECTS.map(buildDialectPatterns);
73
- var CLASSIC_PATTERNS = ALL_DIALECT_PATTERNS[0];
74
- var THOUGHT_RE = CLASSIC_PATTERNS.thoughtRe;
75
- var ACTION_RE = CLASSIC_PATTERNS.actionRe;
76
- var ACTION_RE_SAMELINE = CLASSIC_PATTERNS.actionReSameline;
77
- var ACTION_RE_LOOSE = CLASSIC_PATTERNS.actionReLoose;
78
- var ACTION_RE_PAREN = CLASSIC_PATTERNS.actionReParen;
79
- var FINAL_ANSWER_RE = CLASSIC_PATTERNS.finalAnswerRe;
71
+ const ALL_DIALECT_PATTERNS = REACT_DIALECTS.map(buildDialectPatterns);
72
+ const CLASSIC_PATTERNS = ALL_DIALECT_PATTERNS[0];
73
+ const THOUGHT_RE = CLASSIC_PATTERNS.thoughtRe;
74
+ const ACTION_RE = CLASSIC_PATTERNS.actionRe;
75
+ const ACTION_RE_SAMELINE = CLASSIC_PATTERNS.actionReSameline;
76
+ const ACTION_RE_LOOSE = CLASSIC_PATTERNS.actionReLoose;
77
+ const ACTION_RE_PAREN = CLASSIC_PATTERNS.actionReParen;
78
+ const FINAL_ANSWER_RE = CLASSIC_PATTERNS.finalAnswerRe;
80
79
  function extractJsonArgs(rawArgs) {
81
80
  const start = rawArgs.indexOf("{");
82
81
  if (start === -1) return null;
@@ -262,8 +261,8 @@ function extractToolFromJson(obj) {
262
261
  if (!name || typeof args !== "object" || args === null) return null;
263
262
  return { name, args };
264
263
  }
265
- var FUZZY_MIN_PREFIX_LENGTH = 4;
266
- var WORD_MAPPINGS = {
264
+ const FUZZY_MIN_PREFIX_LENGTH = 4;
265
+ const WORD_MAPPINGS = {
267
266
  calculate: ["calculator"],
268
267
  calc: ["calculator"],
269
268
  math: ["calculator"],
@@ -315,7 +314,7 @@ function fuzzyMatchToolName(hallucinated, availableTools) {
315
314
  }
316
315
  return null;
317
316
  }
318
- var ARG_ALIASES = {
317
+ const ARG_ALIASES = {
319
318
  expression: ["expr", "exp", "formula", "calculation", "math"],
320
319
  file_path: ["path", "filepath", "file", "filename", "location"],
321
320
  content: ["text", "data", "body", "value"],
package/security.js CHANGED
@@ -1,59 +1,26 @@
1
- // shared/security.ts
2
- import * as fs2 from "node:fs";
3
- import * as path2 from "node:path";
4
- import os2 from "node:os";
5
-
6
- // shared/debug.ts
7
- var DEBUG_ENABLED = process.env.PI_EXTENSIONS_DEBUG === "1";
8
- function debugLog(module, message, ...args) {
9
- if (!DEBUG_ENABLED) return;
10
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
11
- console.debug(`[pi-ext:${module}] ${timestamp} ${message}`, ...args);
12
- }
13
-
14
- // shared/security.ts
15
- import dns from "node:dns";
16
-
17
- // shared/config-io.ts
18
1
  import * as fs from "node:fs";
19
2
  import * as path from "node:path";
20
3
  import os from "node:os";
21
- var PI_AGENT_DIR = path.join(os.homedir(), ".pi", "agent");
22
- function writeJsonConfig(filePath, data) {
23
- const dir = path.dirname(filePath);
24
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
25
- const content = JSON.stringify(data, null, 2) + "\n";
26
- const tmpPath = filePath + ".tmp";
27
- try {
28
- fs.writeFileSync(tmpPath, content, "utf-8");
29
- fs.renameSync(tmpPath, filePath);
30
- } catch {
31
- fs.writeFileSync(filePath, content, "utf-8");
32
- }
33
- }
34
- var SETTINGS_PATH = path.join(PI_AGENT_DIR, "settings.json");
35
- var SECURITY_PATH = path.join(PI_AGENT_DIR, "security.json");
36
- var REACT_MODE_PATH = path.join(PI_AGENT_DIR, "react-mode.json");
37
- var MODEL_TEST_CONFIG_PATH = path.join(PI_AGENT_DIR, "model-test-config.json");
38
-
39
- // shared/security.ts
40
- var SETTINGS_PATH2 = SETTINGS_PATH;
41
- var SECURITY_CONFIG_PATH = SECURITY_PATH;
42
- var securityModeCache = null;
43
- var securityModeCacheTime = 0;
44
- var SECURITY_CACHE_DURATION_MS = 3e4;
4
+ import { debugLog } from "./debug";
5
+ import dns from "node:dns";
6
+ import { SETTINGS_PATH as _SETTINGS_PATH, SECURITY_PATH, writeJsonConfig } from "./config-io";
7
+ const SETTINGS_PATH = _SETTINGS_PATH;
8
+ const SECURITY_CONFIG_PATH = SECURITY_PATH;
9
+ let securityModeCache = null;
10
+ let securityModeCacheTime = 0;
11
+ const SECURITY_CACHE_DURATION_MS = 3e4;
45
12
  function getSecurityMode() {
46
13
  const now = Date.now();
47
14
  if (securityModeCache && now - securityModeCacheTime < SECURITY_CACHE_DURATION_MS) {
48
15
  return securityModeCache;
49
16
  }
50
17
  try {
51
- if (!fs2.existsSync(SECURITY_CONFIG_PATH)) {
18
+ if (!fs.existsSync(SECURITY_CONFIG_PATH)) {
52
19
  securityModeCache = "max";
53
20
  securityModeCacheTime = now;
54
21
  return "max";
55
22
  }
56
- const raw = fs2.readFileSync(SECURITY_CONFIG_PATH, "utf-8");
23
+ const raw = fs.readFileSync(SECURITY_CONFIG_PATH, "utf-8");
57
24
  const config = JSON.parse(raw);
58
25
  if (config.mode === "basic" || config.mode === "max" || config.mode === "off") {
59
26
  securityModeCache = config.mode;
@@ -74,7 +41,7 @@ function setSecurityMode(mode) {
74
41
  try {
75
42
  const config = { mode, lastUpdated: (/* @__PURE__ */ new Date()).toISOString() };
76
43
  writeJsonConfig(SECURITY_CONFIG_PATH, config);
77
- const verify = JSON.parse(fs2.readFileSync(SECURITY_CONFIG_PATH, "utf-8"));
44
+ const verify = JSON.parse(fs.readFileSync(SECURITY_CONFIG_PATH, "utf-8"));
78
45
  if (verify.mode !== mode) {
79
46
  debugLog("security", `security config write verification failed: expected ${mode}, got ${verify.mode}`);
80
47
  return false;
@@ -86,7 +53,7 @@ function setSecurityMode(mode) {
86
53
  return false;
87
54
  }
88
55
  }
89
- var CRITICAL_COMMANDS = /* @__PURE__ */ new Set([
56
+ const CRITICAL_COMMANDS = /* @__PURE__ */ new Set([
90
57
  // Filesystem destruction (irrecoverable)
91
58
  "mkfs",
92
59
  "dd",
@@ -138,7 +105,7 @@ var CRITICAL_COMMANDS = /* @__PURE__ */ new Set([
138
105
  "chown",
139
106
  "chmod"
140
107
  ]);
141
- var EXTENDED_COMMANDS = /* @__PURE__ */ new Set([
108
+ const EXTENDED_COMMANDS = /* @__PURE__ */ new Set([
142
109
  // File deletion
143
110
  "rm",
144
111
  "rmdir",
@@ -172,11 +139,11 @@ var EXTENDED_COMMANDS = /* @__PURE__ */ new Set([
172
139
  // Version control
173
140
  "git"
174
141
  ]);
175
- var BLOCKED_COMMANDS = /* @__PURE__ */ new Set([
142
+ const BLOCKED_COMMANDS = /* @__PURE__ */ new Set([
176
143
  ...CRITICAL_COMMANDS,
177
144
  ...EXTENDED_COMMANDS
178
145
  ]);
179
- var BLOCKED_URL_ALWAYS = /* @__PURE__ */ new Set([
146
+ const BLOCKED_URL_ALWAYS = /* @__PURE__ */ new Set([
180
147
  // Cloud metadata endpoints
181
148
  "169.254.169.254",
182
149
  // RFC1918 private ranges
@@ -205,7 +172,7 @@ var BLOCKED_URL_ALWAYS = /* @__PURE__ */ new Set([
205
172
  "private.",
206
173
  "intranet."
207
174
  ]);
208
- var BLOCKED_URL_MAX_ONLY = /* @__PURE__ */ new Set([
175
+ const BLOCKED_URL_MAX_ONLY = /* @__PURE__ */ new Set([
209
176
  // Loopback addresses (full 127.0.0.0/8 range)
210
177
  "localhost",
211
178
  "127.",
@@ -235,11 +202,11 @@ var BLOCKED_URL_MAX_ONLY = /* @__PURE__ */ new Set([
235
202
  // Local/internal patterns
236
203
  "local."
237
204
  ]);
238
- var BLOCKED_URL_PATTERNS = /* @__PURE__ */ new Set([
205
+ const BLOCKED_URL_PATTERNS = /* @__PURE__ */ new Set([
239
206
  ...BLOCKED_URL_ALWAYS,
240
207
  ...BLOCKED_URL_MAX_ONLY
241
208
  ]);
242
- var CRITICAL_SYSTEM_DIRS = [
209
+ const CRITICAL_SYSTEM_DIRS = [
243
210
  "/etc",
244
211
  "/root",
245
212
  "/var",
@@ -261,9 +228,9 @@ function validatePath(filePath, allowedDirs) {
261
228
  }
262
229
  let resolved;
263
230
  try {
264
- resolved = path2.resolve(filePath);
231
+ resolved = path.resolve(filePath);
265
232
  try {
266
- resolved = fs2.realpathSync(resolved);
233
+ resolved = fs.realpathSync(resolved);
267
234
  } catch {
268
235
  }
269
236
  } catch {
@@ -279,9 +246,9 @@ function validatePath(filePath, allowedDirs) {
279
246
  "/etc/passwd",
280
247
  "/.ssh/",
281
248
  "/.gnupg/",
282
- path2.join(os2.homedir(), ".ssh"),
283
- path2.join(os2.homedir(), ".gnupg"),
284
- SETTINGS_PATH2,
249
+ path.join(os.homedir(), ".ssh"),
250
+ path.join(os.homedir(), ".gnupg"),
251
+ SETTINGS_PATH,
285
252
  SECURITY_CONFIG_PATH
286
253
  // NOTE: models.json is intentionally excluded from sensitivePaths.
287
254
  // Extensions use readModelsJson()/writeModelsJson() from shared/ollama.ts
@@ -301,7 +268,7 @@ function validatePath(filePath, allowedDirs) {
301
268
  if (allowedDirs) {
302
269
  for (const dir of allowedDirs) {
303
270
  try {
304
- const absDir = path2.resolve(dir);
271
+ const absDir = path.resolve(dir);
305
272
  if (resolved.startsWith(absDir)) return { valid: true, error: "" };
306
273
  } catch {
307
274
  }
@@ -332,10 +299,10 @@ function isPrivateIp(ip) {
332
299
  }
333
300
  async function resolveAndCheckHostname(hostname, blockPrivate = true) {
334
301
  try {
335
- const addresses = await new Promise((resolve2, reject) => {
302
+ const addresses = await new Promise((resolve, reject) => {
336
303
  dns.lookup(hostname, { all: true }, (err, addresses2) => {
337
304
  if (err) reject(err);
338
- else resolve2(addresses2);
305
+ else resolve(addresses2);
339
306
  });
340
307
  });
341
308
  if (!addresses || addresses.length === 0) {
@@ -411,7 +378,7 @@ function isSafeUrl(url, blockSsrf = true, mode = "max") {
411
378
  }
412
379
  return { safe: true, error: "" };
413
380
  }
414
- var INJECTION_PATTERNS = [
381
+ const INJECTION_PATTERNS = [
415
382
  // Semicolon chaining to dangerous commands — mode-independent.
416
383
  // Unlike && (conditional), ; ALWAYS runs the second command.
417
384
  /;\s*(rm|sudo|chmod|chown|mkfs|dd|shred|kill|pkill)\b/i,
@@ -486,12 +453,12 @@ function sanitizeCommand(command) {
486
453
  }
487
454
  return { isSafe: true, error: "", command };
488
455
  }
489
- var AUDIT_DIR = path2.join(os2.homedir(), ".pi", "agent");
490
- var AUDIT_LOG_PATH = path2.join(AUDIT_DIR, "audit.log");
491
- var AUDIT_BUFFER_MAX_ENTRIES = 50;
492
- var AUDIT_FLUSH_INTERVAL_MS = 500;
493
- var _auditBuffer = [];
494
- var _auditFlushTimer = null;
456
+ const AUDIT_DIR = path.join(os.homedir(), ".pi", "agent");
457
+ const AUDIT_LOG_PATH = path.join(AUDIT_DIR, "audit.log");
458
+ const AUDIT_BUFFER_MAX_ENTRIES = 50;
459
+ const AUDIT_FLUSH_INTERVAL_MS = 500;
460
+ let _auditBuffer = [];
461
+ let _auditFlushTimer = null;
495
462
  function ensureAuditFlushTimer() {
496
463
  if (_auditFlushTimer) return;
497
464
  _auditFlushTimer = setInterval(() => {
@@ -507,11 +474,11 @@ function ensureAuditFlushTimer() {
507
474
  function flushAuditBuffer() {
508
475
  if (_auditBuffer.length === 0) return;
509
476
  try {
510
- if (!fs2.existsSync(AUDIT_DIR)) {
511
- fs2.mkdirSync(AUDIT_DIR, { recursive: true });
477
+ if (!fs.existsSync(AUDIT_DIR)) {
478
+ fs.mkdirSync(AUDIT_DIR, { recursive: true });
512
479
  }
513
480
  const batch = _auditBuffer.join("");
514
- fs2.appendFileSync(AUDIT_LOG_PATH, batch, "utf-8");
481
+ fs.appendFileSync(AUDIT_LOG_PATH, batch, "utf-8");
515
482
  } catch (err) {
516
483
  debugLog("security", "audit buffer flush failure", err);
517
484
  }
@@ -522,12 +489,12 @@ function appendAuditEntry(entry) {
522
489
  ensureAuditFlushTimer();
523
490
  const AUDIT_LOG_MAX_SIZE = 5 * 1024 * 1024;
524
491
  try {
525
- if (fs2.existsSync(AUDIT_LOG_PATH)) {
526
- const stat = fs2.statSync(AUDIT_LOG_PATH);
492
+ if (fs.existsSync(AUDIT_LOG_PATH)) {
493
+ const stat = fs.statSync(AUDIT_LOG_PATH);
527
494
  if (stat.size > AUDIT_LOG_MAX_SIZE) {
528
495
  const entries = readRecentAuditEntries(1e3);
529
496
  const content = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
530
- fs2.writeFileSync(AUDIT_LOG_PATH, content, "utf-8");
497
+ fs.writeFileSync(AUDIT_LOG_PATH, content, "utf-8");
531
498
  }
532
499
  }
533
500
  } catch (err) {
@@ -545,10 +512,10 @@ function appendAuditEntry(entry) {
545
512
  }
546
513
  function readRecentAuditEntries(count = 50) {
547
514
  try {
548
- if (!fs2.existsSync(AUDIT_LOG_PATH)) return [];
549
- const fileSize = fs2.statSync(AUDIT_LOG_PATH).size;
515
+ if (!fs.existsSync(AUDIT_LOG_PATH)) return [];
516
+ const fileSize = fs.statSync(AUDIT_LOG_PATH).size;
550
517
  if (fileSize === 0) return [];
551
- const fd = fs2.openSync(AUDIT_LOG_PATH, "r");
518
+ const fd = fs.openSync(AUDIT_LOG_PATH, "r");
552
519
  const bufferSize = 8192;
553
520
  const buffer = Buffer.alloc(bufferSize);
554
521
  const lines = [];
@@ -557,7 +524,7 @@ function readRecentAuditEntries(count = 50) {
557
524
  while (pos > 0 && lines.length < count) {
558
525
  const readSize = Math.min(bufferSize, pos);
559
526
  pos -= readSize;
560
- fs2.readSync(fd, buffer, 0, readSize, pos);
527
+ fs.readSync(fd, buffer, 0, readSize, pos);
561
528
  const chunk = buffer.slice(0, readSize).toString("utf-8");
562
529
  partial = chunk + partial;
563
530
  const lineBreak = partial.lastIndexOf("\n");
@@ -567,7 +534,7 @@ function readRecentAuditEntries(count = 50) {
567
534
  partial = partial.slice(0, lineBreak);
568
535
  }
569
536
  }
570
- fs2.closeSync(fd);
537
+ fs.closeSync(fd);
571
538
  if (partial.trim() && lines.length < count) {
572
539
  lines.unshift(partial);
573
540
  }
@@ -658,7 +625,7 @@ export {
658
625
  CRITICAL_COMMANDS,
659
626
  EXTENDED_COMMANDS,
660
627
  SECURITY_CONFIG_PATH,
661
- SETTINGS_PATH2 as SETTINGS_PATH,
628
+ SETTINGS_PATH,
662
629
  appendAuditEntry,
663
630
  checkBashToolInput,
664
631
  checkFileToolInput,
package/test-report.js CHANGED
@@ -1,39 +1,6 @@
1
- // shared/format.ts
2
- function section(title) {
3
- return `
4
- \u2500\u2500 ${title} ${"\u2500".repeat(Math.max(1, 60 - title.length - 4))}`;
5
- }
6
- function ok(msg) {
7
- return ` \u2705 ${msg}`;
8
- }
9
- function fail(msg) {
10
- return ` \u274C ${msg}`;
11
- }
12
- function warn(msg) {
13
- return ` \u26A0\uFE0F ${msg}`;
14
- }
15
- function info(msg) {
16
- return ` \u2139\uFE0F ${msg}`;
17
- }
18
- function msHuman(ms) {
19
- if (ms < 1e3) return `${ms.toFixed(0)}ms`;
20
- if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
21
- return `${(ms / 6e4).toFixed(1)}m`;
22
- }
23
-
24
- // shared/ollama.ts
25
- import * as path from "node:path";
26
- import os from "node:os";
27
-
28
- // shared/debug.ts
29
- var DEBUG_ENABLED = process.env.PI_EXTENSIONS_DEBUG === "1";
30
-
31
- // shared/ollama.ts
32
- var EXTENSION_VERSION = "1.2.2";
33
- var MODELS_JSON_PATH = path.join(os.homedir(), ".pi", "agent", "models.json");
34
-
35
- // shared/test-report.ts
36
- var branding = [
1
+ import { ok, fail, warn, info, section, msHuman } from "./format";
2
+ import { EXTENSION_VERSION } from "./ollama";
3
+ const branding = [
37
4
  ` \u26A1 Pi Model Benchmark v${EXTENSION_VERSION}`,
38
5
  ` Written by VTSTech`,
39
6
  ` GitHub: https://github.com/VTSTech`,
package/types.js CHANGED
@@ -0,0 +1 @@
1
+ // types — type definitions are erased at compile time