@stfade/pi-read-delegator 1.0.0
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 +107 -0
- package/bash-filter.d.ts +37 -0
- package/bash-filter.js +242 -0
- package/config.d.ts +31 -0
- package/config.js +169 -0
- package/index.d.ts +61 -0
- package/index.js +260 -0
- package/package.json +46 -0
- package/reader-manager.d.ts +71 -0
- package/reader-manager.js +274 -0
- package/templates/reader.md +8 -0
- package/tool-blocker.d.ts +59 -0
- package/tool-blocker.js +140 -0
- package/ui.d.ts +59 -0
- package/ui.js +273 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tool-blocker.ts — Tool removal and restoration for pi-read-delegator
|
|
3
|
+
*
|
|
4
|
+
* Pi's Extension API exposes:
|
|
5
|
+
* agent.getTools() → ToolDefinition[]
|
|
6
|
+
* agent.removeTool(name) → void
|
|
7
|
+
* agent.addTool(definition) → void
|
|
8
|
+
*
|
|
9
|
+
* We store removed tool definitions in a Map so they can be restored later.
|
|
10
|
+
*/
|
|
11
|
+
/** Minimal shape for a Pi tool definition. */
|
|
12
|
+
export interface ToolDefinition {
|
|
13
|
+
name: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
/** The Pi agent interface this module operates on. */
|
|
18
|
+
export interface ExtensionAgent {
|
|
19
|
+
getTools(): ToolDefinition[];
|
|
20
|
+
removeTool(name: string): void;
|
|
21
|
+
addTool(definition: ToolDefinition): void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Remove the listed tools from the agent.
|
|
25
|
+
* Saves their definitions so they can be restored later.
|
|
26
|
+
* If a tool is already removed, it is silently skipped.
|
|
27
|
+
*/
|
|
28
|
+
export declare function blockTools(agent: ExtensionAgent, tools: string[]): void;
|
|
29
|
+
/**
|
|
30
|
+
* Restore all previously blocked tools to the agent.
|
|
31
|
+
* If a tool was never removed, it is skipped.
|
|
32
|
+
*/
|
|
33
|
+
export declare function restoreTools(agent: ExtensionAgent): void;
|
|
34
|
+
/**
|
|
35
|
+
* Temporarily allow the main model to use blocked tools for one operation.
|
|
36
|
+
*
|
|
37
|
+
* 1. Restore the tools
|
|
38
|
+
* 2. Await the callback (which performs the read)
|
|
39
|
+
* 3. Re-block the tools
|
|
40
|
+
*
|
|
41
|
+
* @param agent The Pi agent
|
|
42
|
+
* @param blockedTools List of tool names that should stay blocked normally
|
|
43
|
+
* @param callback Async function to run while tools are available
|
|
44
|
+
* @returns The callback's return value
|
|
45
|
+
*/
|
|
46
|
+
export declare function tempAllowOnce<T>(agent: ExtensionAgent, blockedTools: string[], callback: () => Promise<T>): Promise<T>;
|
|
47
|
+
/**
|
|
48
|
+
* Check whether a given tool is currently blocked.
|
|
49
|
+
*/
|
|
50
|
+
export declare function isBlocked(toolName: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Get the list of currently blocked tool names.
|
|
53
|
+
*/
|
|
54
|
+
export declare function getBlockedTools(): string[];
|
|
55
|
+
/**
|
|
56
|
+
* Clear all blocked tool state (useful for testing / full reset).
|
|
57
|
+
*/
|
|
58
|
+
export declare function reset(): void;
|
|
59
|
+
//# sourceMappingURL=tool-blocker.d.ts.map
|
package/tool-blocker.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* tool-blocker.ts — Tool removal and restoration for pi-read-delegator
|
|
4
|
+
*
|
|
5
|
+
* Pi's Extension API exposes:
|
|
6
|
+
* agent.getTools() → ToolDefinition[]
|
|
7
|
+
* agent.removeTool(name) → void
|
|
8
|
+
* agent.addTool(definition) → void
|
|
9
|
+
*
|
|
10
|
+
* We store removed tool definitions in a Map so they can be restored later.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.blockTools = blockTools;
|
|
14
|
+
exports.restoreTools = restoreTools;
|
|
15
|
+
exports.tempAllowOnce = tempAllowOnce;
|
|
16
|
+
exports.isBlocked = isBlocked;
|
|
17
|
+
exports.getBlockedTools = getBlockedTools;
|
|
18
|
+
exports.reset = reset;
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Tool blocker state
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
/** Stores tool definitions that were removed, keyed by tool name. */
|
|
23
|
+
const removedTools = new Map();
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Public API
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/**
|
|
28
|
+
* Remove the listed tools from the agent.
|
|
29
|
+
* Saves their definitions so they can be restored later.
|
|
30
|
+
* If a tool is already removed, it is silently skipped.
|
|
31
|
+
*/
|
|
32
|
+
function blockTools(agent, tools) {
|
|
33
|
+
const currentTools = agent.getTools();
|
|
34
|
+
for (const toolName of tools) {
|
|
35
|
+
// Skip if already removed
|
|
36
|
+
if (removedTools.has(toolName))
|
|
37
|
+
continue;
|
|
38
|
+
const definition = currentTools.find((t) => t.name === toolName);
|
|
39
|
+
if (definition) {
|
|
40
|
+
removedTools.set(toolName, definition);
|
|
41
|
+
try {
|
|
42
|
+
agent.removeTool(toolName);
|
|
43
|
+
console.log(`[pi-read-delegator] Blocked tool: ${toolName}`);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
console.error(`[pi-read-delegator] Failed to block tool "${toolName}": ${err}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Restore all previously blocked tools to the agent.
|
|
53
|
+
* If a tool was never removed, it is skipped.
|
|
54
|
+
*/
|
|
55
|
+
function restoreTools(agent) {
|
|
56
|
+
for (const [toolName, definition] of removedTools.entries()) {
|
|
57
|
+
try {
|
|
58
|
+
agent.addTool(definition);
|
|
59
|
+
console.log(`[pi-read-delegator] Restored tool: ${toolName}`);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
console.error(`[pi-read-delegator] Failed to restore tool "${toolName}": ${err}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
removedTools.clear();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Temporarily allow the main model to use blocked tools for one operation.
|
|
69
|
+
*
|
|
70
|
+
* 1. Restore the tools
|
|
71
|
+
* 2. Await the callback (which performs the read)
|
|
72
|
+
* 3. Re-block the tools
|
|
73
|
+
*
|
|
74
|
+
* @param agent The Pi agent
|
|
75
|
+
* @param blockedTools List of tool names that should stay blocked normally
|
|
76
|
+
* @param callback Async function to run while tools are available
|
|
77
|
+
* @returns The callback's return value
|
|
78
|
+
*/
|
|
79
|
+
async function tempAllowOnce(agent, blockedTools, callback) {
|
|
80
|
+
// Restore temporarily
|
|
81
|
+
const restoredNow = [];
|
|
82
|
+
// We need to get the definitions from our map, but they might not be there
|
|
83
|
+
// if the tools were never initially blocked. In that case, we just re-block
|
|
84
|
+
// the names after.
|
|
85
|
+
for (const toolName of blockedTools) {
|
|
86
|
+
const definition = removedTools.get(toolName);
|
|
87
|
+
if (definition) {
|
|
88
|
+
try {
|
|
89
|
+
agent.addTool(definition);
|
|
90
|
+
// Remove from the map temporarily so restoreTools doesn't double-restore
|
|
91
|
+
removedTools.delete(toolName);
|
|
92
|
+
restoredNow.push(toolName);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
console.error(`[pi-read-delegator] Failed to temporarily restore "${toolName}": ${err}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
// Run the callback while tools are available
|
|
101
|
+
const result = await callback();
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
// Re-block the tools we restored
|
|
106
|
+
for (const toolName of restoredNow) {
|
|
107
|
+
// Find the definition from agent's current tool list before removing
|
|
108
|
+
const currentTools = agent.getTools();
|
|
109
|
+
const definition = currentTools.find((t) => t.name === toolName);
|
|
110
|
+
if (definition) {
|
|
111
|
+
removedTools.set(toolName, definition);
|
|
112
|
+
try {
|
|
113
|
+
agent.removeTool(toolName);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
console.error(`[pi-read-delegator] Failed to re-block "${toolName}": ${err}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check whether a given tool is currently blocked.
|
|
124
|
+
*/
|
|
125
|
+
function isBlocked(toolName) {
|
|
126
|
+
return removedTools.has(toolName);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get the list of currently blocked tool names.
|
|
130
|
+
*/
|
|
131
|
+
function getBlockedTools() {
|
|
132
|
+
return Array.from(removedTools.keys());
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clear all blocked tool state (useful for testing / full reset).
|
|
136
|
+
*/
|
|
137
|
+
function reset() {
|
|
138
|
+
removedTools.clear();
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=tool-blocker.js.map
|
package/ui.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ui.ts — Localization, status bar, and logging for pi-read-delegator
|
|
3
|
+
*
|
|
4
|
+
* Detects the user's language preference (config → Pi settings → OS → "en")
|
|
5
|
+
* and provides localized messages. Manages a status bar indicator.
|
|
6
|
+
*/
|
|
7
|
+
export type Status = "active" | "idle" | "error";
|
|
8
|
+
/** Minimal Pi agent interface for the status bar API. */
|
|
9
|
+
export interface AgentWithStatusBar {
|
|
10
|
+
/** Set text to display in the Pi status bar. */
|
|
11
|
+
setStatusBarText(text: string): void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the effective language.
|
|
15
|
+
*
|
|
16
|
+
* Priority:
|
|
17
|
+
* 1. Explicit language in config (if not "auto")
|
|
18
|
+
* 2. Pi's own language setting from ~/.pi/settings.json
|
|
19
|
+
* 3. Operating system locale (first two chars)
|
|
20
|
+
* 4. Fallback "en"
|
|
21
|
+
*/
|
|
22
|
+
export declare function getLanguage(configLang?: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Retrieve a localized message by key.
|
|
25
|
+
*
|
|
26
|
+
* Falls back to English if the current language doesn't have the key.
|
|
27
|
+
*/
|
|
28
|
+
export declare function msg(key: string, lang?: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Explicitly set the current language (for /read-delegator lang <code>).
|
|
31
|
+
*/
|
|
32
|
+
export declare function setLanguage(lang: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Initialize the status bar with the given agent.
|
|
35
|
+
*/
|
|
36
|
+
export declare function initStatusBar(agent: AgentWithStatusBar): void;
|
|
37
|
+
/**
|
|
38
|
+
* Update the status bar indicator.
|
|
39
|
+
*/
|
|
40
|
+
export declare function updateStatusBar(status: Status): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get the current status.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getStatus(): Status;
|
|
45
|
+
/**
|
|
46
|
+
* Log a one-line Reader event using the current language.
|
|
47
|
+
*
|
|
48
|
+
* Prepend "[pi-read-delegator]" for easy filtering.
|
|
49
|
+
*/
|
|
50
|
+
export declare function log(key: string, detail?: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Log an error with the standard prefix.
|
|
53
|
+
*/
|
|
54
|
+
export declare function logError(key: string, detail?: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Log a warning with the standard prefix.
|
|
57
|
+
*/
|
|
58
|
+
export declare function logWarn(key: string, detail?: string): void;
|
|
59
|
+
//# sourceMappingURL=ui.d.ts.map
|
package/ui.js
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ui.ts — Localization, status bar, and logging for pi-read-delegator
|
|
4
|
+
*
|
|
5
|
+
* Detects the user's language preference (config → Pi settings → OS → "en")
|
|
6
|
+
* and provides localized messages. Manages a status bar indicator.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.getLanguage = getLanguage;
|
|
43
|
+
exports.msg = msg;
|
|
44
|
+
exports.setLanguage = setLanguage;
|
|
45
|
+
exports.initStatusBar = initStatusBar;
|
|
46
|
+
exports.updateStatusBar = updateStatusBar;
|
|
47
|
+
exports.getStatus = getStatus;
|
|
48
|
+
exports.log = log;
|
|
49
|
+
exports.logError = logError;
|
|
50
|
+
exports.logWarn = logWarn;
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const os = __importStar(require("os"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Language detection
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Language map of all translatable messages.
|
|
59
|
+
*
|
|
60
|
+
* Adding a new language means adding a record for every key.
|
|
61
|
+
*/
|
|
62
|
+
const messages = {
|
|
63
|
+
reader_calling: {
|
|
64
|
+
tr: "🔍 Reader: sorgu çalıştırılıyor…",
|
|
65
|
+
en: "🔍 Reader: executing query…",
|
|
66
|
+
},
|
|
67
|
+
reader_done: {
|
|
68
|
+
tr: "✅ Reader: tamamlandı",
|
|
69
|
+
en: "✅ Reader: done",
|
|
70
|
+
},
|
|
71
|
+
reader_failed: {
|
|
72
|
+
tr: "❌ Reader: başarısız - ",
|
|
73
|
+
en: "❌ Reader: failed - ",
|
|
74
|
+
},
|
|
75
|
+
deps_missing: {
|
|
76
|
+
tr: "⚠️ pi-subagents yüklü değil. Yüklensin mi? [E/h]",
|
|
77
|
+
en: "⚠️ pi-subagents not installed. Install now? [Y/n]",
|
|
78
|
+
},
|
|
79
|
+
deps_installing: {
|
|
80
|
+
tr: "📦 pi-subagents yükleniyor…",
|
|
81
|
+
en: "📦 Installing pi-subagents…",
|
|
82
|
+
},
|
|
83
|
+
deps_failed: {
|
|
84
|
+
tr: "❌ Kurulum başarısız. Elle yükleyin.",
|
|
85
|
+
en: "❌ Installation failed. Install manually.",
|
|
86
|
+
},
|
|
87
|
+
status_active: {
|
|
88
|
+
tr: "● aktif",
|
|
89
|
+
en: "● active",
|
|
90
|
+
},
|
|
91
|
+
status_idle: {
|
|
92
|
+
tr: "○ boşta",
|
|
93
|
+
en: "○ idle",
|
|
94
|
+
},
|
|
95
|
+
status_error: {
|
|
96
|
+
tr: "⚠ hata",
|
|
97
|
+
en: "⚠ error",
|
|
98
|
+
},
|
|
99
|
+
blocked: {
|
|
100
|
+
tr: "🚫 Engellendi: ",
|
|
101
|
+
en: "🚫 Blocked: ",
|
|
102
|
+
},
|
|
103
|
+
already_blocked: {
|
|
104
|
+
tr: "⚠ Araçlar zaten engellenmiş.",
|
|
105
|
+
en: "⚠ Tools are already blocked.",
|
|
106
|
+
},
|
|
107
|
+
already_enabled: {
|
|
108
|
+
tr: "⚠ Araçlar zaten aktif.",
|
|
109
|
+
en: "⚠ Tools are already active.",
|
|
110
|
+
},
|
|
111
|
+
enabled: {
|
|
112
|
+
tr: "✅ pi-read-delegator etkin",
|
|
113
|
+
en: "✅ pi-read-delegator enabled",
|
|
114
|
+
},
|
|
115
|
+
disabled: {
|
|
116
|
+
tr: "🔓 pi-read-delegator devre dışı — tüm araçlar serbest",
|
|
117
|
+
en: "🔓 pi-read-delegator disabled — all tools free",
|
|
118
|
+
},
|
|
119
|
+
config_saved: {
|
|
120
|
+
tr: "💾 Konfigürasyon kaydedildi",
|
|
121
|
+
en: "💾 Configuration saved",
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
// Cached language code determined at init time.
|
|
125
|
+
let currentLang = "en";
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Public API
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
/**
|
|
130
|
+
* Resolve the effective language.
|
|
131
|
+
*
|
|
132
|
+
* Priority:
|
|
133
|
+
* 1. Explicit language in config (if not "auto")
|
|
134
|
+
* 2. Pi's own language setting from ~/.pi/settings.json
|
|
135
|
+
* 3. Operating system locale (first two chars)
|
|
136
|
+
* 4. Fallback "en"
|
|
137
|
+
*/
|
|
138
|
+
function getLanguage(configLang) {
|
|
139
|
+
// 1. Explicit config override
|
|
140
|
+
if (configLang && configLang !== "auto") {
|
|
141
|
+
currentLang = configLang;
|
|
142
|
+
return currentLang;
|
|
143
|
+
}
|
|
144
|
+
// 2. Pi's own setting
|
|
145
|
+
try {
|
|
146
|
+
const piSettingsPath = path.join(os.homedir(), ".pi", "settings.json");
|
|
147
|
+
if (fs.existsSync(piSettingsPath)) {
|
|
148
|
+
const raw = fs.readFileSync(piSettingsPath, "utf-8");
|
|
149
|
+
const settings = JSON.parse(raw);
|
|
150
|
+
if (typeof settings.language === "string") {
|
|
151
|
+
currentLang = settings.language;
|
|
152
|
+
return currentLang;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// Silently fall through
|
|
158
|
+
}
|
|
159
|
+
// 3. OS locale (e.g., "tr-TR" → "tr")
|
|
160
|
+
try {
|
|
161
|
+
const locale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
162
|
+
const short = locale.split("-")[0];
|
|
163
|
+
if (short && short.length === 2 && messages.reader_calling[short]) {
|
|
164
|
+
currentLang = short;
|
|
165
|
+
return currentLang;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// Silently fall through
|
|
170
|
+
}
|
|
171
|
+
// 4. Fallback
|
|
172
|
+
currentLang = "en";
|
|
173
|
+
return currentLang;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Retrieve a localized message by key.
|
|
177
|
+
*
|
|
178
|
+
* Falls back to English if the current language doesn't have the key.
|
|
179
|
+
*/
|
|
180
|
+
function msg(key, lang) {
|
|
181
|
+
const langCode = lang ?? currentLang;
|
|
182
|
+
const entry = messages[key];
|
|
183
|
+
if (!entry)
|
|
184
|
+
return `??? ${key} ???`;
|
|
185
|
+
return entry[langCode] ?? entry.en ?? key;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Explicitly set the current language (for /read-delegator lang <code>).
|
|
189
|
+
*/
|
|
190
|
+
function setLanguage(lang) {
|
|
191
|
+
currentLang = lang;
|
|
192
|
+
}
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
// Status bar
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
let statusBarAgent = null;
|
|
197
|
+
let currentStatus = "idle";
|
|
198
|
+
/**
|
|
199
|
+
* Initialize the status bar with the given agent.
|
|
200
|
+
*/
|
|
201
|
+
function initStatusBar(agent) {
|
|
202
|
+
statusBarAgent = agent;
|
|
203
|
+
updateStatusBar("idle");
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Update the status bar indicator.
|
|
207
|
+
*/
|
|
208
|
+
function updateStatusBar(status) {
|
|
209
|
+
currentStatus = status;
|
|
210
|
+
if (!statusBarAgent)
|
|
211
|
+
return;
|
|
212
|
+
let text;
|
|
213
|
+
switch (status) {
|
|
214
|
+
case "active":
|
|
215
|
+
text = msg("status_active");
|
|
216
|
+
break;
|
|
217
|
+
case "error":
|
|
218
|
+
text = msg("status_error");
|
|
219
|
+
break;
|
|
220
|
+
default:
|
|
221
|
+
text = msg("status_idle");
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
statusBarAgent.setStatusBarText(`pi-read-delegator: ${text}`);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// Graceful fallback — not all Pi versions support status bar
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get the current status.
|
|
233
|
+
*/
|
|
234
|
+
function getStatus() {
|
|
235
|
+
return currentStatus;
|
|
236
|
+
}
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// Logging
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
/**
|
|
241
|
+
* Log a one-line Reader event using the current language.
|
|
242
|
+
*
|
|
243
|
+
* Prepend "[pi-read-delegator]" for easy filtering.
|
|
244
|
+
*/
|
|
245
|
+
function log(key, detail) {
|
|
246
|
+
const prefix = "[pi-read-delegator]";
|
|
247
|
+
const message = msg(key);
|
|
248
|
+
if (detail) {
|
|
249
|
+
console.log(`${prefix} ${message}${detail}`);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
console.log(`${prefix} ${message}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Log an error with the standard prefix.
|
|
257
|
+
*/
|
|
258
|
+
function logError(key, detail) {
|
|
259
|
+
const prefix = "[pi-read-delegator]";
|
|
260
|
+
const message = msg(key);
|
|
261
|
+
const full = detail ? `${message}${detail}` : message;
|
|
262
|
+
console.error(`${prefix} ${full}`);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Log a warning with the standard prefix.
|
|
266
|
+
*/
|
|
267
|
+
function logWarn(key, detail) {
|
|
268
|
+
const prefix = "[pi-read-delegator]";
|
|
269
|
+
const message = msg(key);
|
|
270
|
+
const full = detail ? `${message}${detail}` : message;
|
|
271
|
+
console.warn(`${prefix} ${full}`);
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=ui.js.map
|