memeloop 0.0.1 → 0.1.1
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 +63 -0
- package/dist/browser.cjs +1413 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.cts +3066 -0
- package/dist/browser.d.ts +3066 -0
- package/dist/browser.js +43 -0
- package/dist/chunk-2C6BJZI3.js +382 -0
- package/dist/chunk-2C6BJZI3.js.map +1 -0
- package/dist/chunk-426CJUZP.js +630 -0
- package/dist/chunk-426CJUZP.js.map +1 -0
- package/dist/chunk-7ZDTB4VZ.js +63 -0
- package/dist/chunk-7ZDTB4VZ.js.map +1 -0
- package/dist/chunk-AZFYDWIN.js +98 -0
- package/dist/chunk-AZFYDWIN.js.map +1 -0
- package/dist/chunk-BGPU4RR7.js +367 -0
- package/dist/chunk-BGPU4RR7.js.map +1 -0
- package/dist/chunk-CCEFAOSH.js +496 -0
- package/dist/chunk-CCEFAOSH.js.map +1 -0
- package/dist/chunk-FWSY5HOA.js +63 -0
- package/dist/chunk-FWSY5HOA.js.map +1 -0
- package/dist/chunk-GYIOMQMY.js +8726 -0
- package/dist/chunk-GYIOMQMY.js.map +1 -0
- package/dist/chunk-K6P63KD4.js +68 -0
- package/dist/chunk-K6P63KD4.js.map +1 -0
- package/dist/chunk-KFS2EJT6.js +42 -0
- package/dist/chunk-KFS2EJT6.js.map +1 -0
- package/dist/chunk-MAJWHAKR.js +3637 -0
- package/dist/chunk-MAJWHAKR.js.map +1 -0
- package/dist/chunk-MRKY4HGF.js +205 -0
- package/dist/chunk-MRKY4HGF.js.map +1 -0
- package/dist/chunk-T7FSXWFR.js +2744 -0
- package/dist/chunk-T7FSXWFR.js.map +1 -0
- package/dist/chunk-VZKQX5PP.js +1 -0
- package/dist/chunk-VZKQX5PP.js.map +1 -0
- package/dist/chunk-WAI6BODI.js +175 -0
- package/dist/chunk-WAI6BODI.js.map +1 -0
- package/dist/chunk-YMNXDNDW.js +798 -0
- package/dist/chunk-YMNXDNDW.js.map +1 -0
- package/dist/conversation.cjs +208 -0
- package/dist/conversation.cjs.map +1 -0
- package/dist/conversation.d.cts +100 -0
- package/dist/conversation.d.ts +100 -0
- package/dist/conversation.js +21 -0
- package/dist/conversation.js.map +1 -0
- package/dist/device-network-portable.cjs +702 -0
- package/dist/device-network-portable.cjs.map +1 -0
- package/dist/device-network-portable.d.cts +110 -0
- package/dist/device-network-portable.d.ts +110 -0
- package/dist/device-network-portable.js +53 -0
- package/dist/device-network-portable.js.map +1 -0
- package/dist/device-network.cjs +906 -0
- package/dist/device-network.cjs.map +1 -0
- package/dist/device-network.d.cts +6 -0
- package/dist/device-network.d.ts +6 -0
- package/dist/device-network.js +59 -0
- package/dist/device-network.js.map +1 -0
- package/dist/fetchProvider-WWnWnQFP.d.ts +91 -0
- package/dist/fetchProvider-toTHy5Nu.d.cts +91 -0
- package/dist/index.cjs +28051 -5459
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -1320
- package/dist/index.d.ts +94 -1320
- package/dist/index.js +10616 -2420
- package/dist/index.js.map +1 -1
- package/dist/interface-IrKBFtL1.d.cts +493 -0
- package/dist/interface-IrKBFtL1.d.ts +493 -0
- package/dist/llm-providers.cjs +43 -8
- package/dist/llm-providers.cjs.map +1 -1
- package/dist/llm-providers.d.cts +2 -1
- package/dist/llm-providers.d.ts +2 -1
- package/dist/llm-providers.js +4 -2
- package/dist/llm-providers.js.map +1 -1
- package/dist/loop-api.cjs +5227 -2010
- package/dist/loop-api.cjs.map +1 -1
- package/dist/loop-api.d.cts +11 -5
- package/dist/loop-api.d.ts +11 -5
- package/dist/loop-api.js +86 -49
- package/dist/mobile.cjs +2711 -0
- package/dist/mobile.cjs.map +1 -0
- package/dist/mobile.d.cts +6 -0
- package/dist/mobile.d.ts +6 -0
- package/dist/mobile.js +22 -0
- package/dist/mobile.js.map +1 -0
- package/dist/orchestration-portable-BHB_YrNN.d.ts +2192 -0
- package/dist/orchestration-portable-mvYBvGBb.d.cts +2192 -0
- package/dist/orchestration-portable.cjs +9553 -0
- package/dist/orchestration-portable.cjs.map +1 -0
- package/dist/orchestration-portable.d.cts +5 -0
- package/dist/orchestration-portable.d.ts +5 -0
- package/dist/orchestration-portable.js +290 -0
- package/dist/orchestration-portable.js.map +1 -0
- package/dist/pairingInvite-BXPWY3aM.d.cts +149 -0
- package/dist/pairingInvite-Cuz0wuq9.d.ts +149 -0
- package/dist/promptConcat-0WNFTg4l.d.ts +516 -0
- package/dist/promptConcat-D6wr5V-V.d.cts +516 -0
- package/dist/providerRegistry-Bi6pAvSj.d.ts +86 -0
- package/dist/providerRegistry-CPsktuiX.d.cts +86 -0
- package/dist/registry-D0kbxksn.d.cts +393 -0
- package/dist/registry-DDbvhlhs.d.ts +393 -0
- package/dist/remoteClient-B_spK019.d.ts +87 -0
- package/dist/remoteClient-CBggnRy3.d.cts +87 -0
- package/dist/runtime-PGWR6FIV.js +18 -0
- package/dist/runtime-PGWR6FIV.js.map +1 -0
- package/dist/scriptDeploymentPipeline-CXJcC82H.d.ts +2464 -0
- package/dist/scriptDeploymentPipeline-yG1ZhVVI.d.cts +2464 -0
- package/dist/syncCloudDevices-BEqwgrhD.d.ts +49 -0
- package/dist/syncCloudDevices-Ds_Kcgrv.d.cts +49 -0
- package/dist/types-7pYti-k9.d.cts +255 -0
- package/dist/types-CdFVSntj.d.ts +255 -0
- package/package.json +110 -35
- package/dist/anthropic.cjs +0 -72
- package/dist/anthropic.cjs.map +0 -1
- package/dist/anthropic.d.cts +0 -21
- package/dist/anthropic.d.ts +0 -21
- package/dist/anthropic.js +0 -21
- package/dist/anthropic.js.map +0 -1
- package/dist/azure.cjs +0 -72
- package/dist/azure.cjs.map +0 -1
- package/dist/azure.d.cts +0 -21
- package/dist/azure.d.ts +0 -21
- package/dist/azure.js +0 -21
- package/dist/azure.js.map +0 -1
- package/dist/chunk-3CN7DFBL.js +0 -4894
- package/dist/chunk-3CN7DFBL.js.map +0 -1
- package/dist/chunk-4AZ4D7U5.js +0 -32
- package/dist/chunk-4AZ4D7U5.js.map +0 -1
- package/dist/chunk-6ON4XSOV.js +0 -63
- package/dist/chunk-6ON4XSOV.js.map +0 -1
- package/dist/chunk-DJQNGIXX.js +0 -4793
- package/dist/chunk-DJQNGIXX.js.map +0 -1
- package/dist/chunk-FKQP6AOQ.js +0 -32
- package/dist/chunk-FKQP6AOQ.js.map +0 -1
- package/dist/chunk-OVJ7JJBA.js +0 -35
- package/dist/chunk-OVJ7JJBA.js.map +0 -1
- package/dist/chunk-P4UZ7IXC.js +0 -42
- package/dist/chunk-YHJ2AEFR.js +0 -4933
- package/dist/chunk-YHJ2AEFR.js.map +0 -1
- package/dist/chunk-YVK7RYRO.js +0 -4973
- package/dist/chunk-YVK7RYRO.js.map +0 -1
- package/dist/code-assistant.json +0 -114
- package/dist/cohere.cjs +0 -72
- package/dist/cohere.cjs.map +0 -1
- package/dist/cohere.d.cts +0 -21
- package/dist/cohere.d.ts +0 -21
- package/dist/cohere.js +0 -21
- package/dist/cohere.js.map +0 -1
- package/dist/deepseek.cjs +0 -72
- package/dist/deepseek.cjs.map +0 -1
- package/dist/deepseek.d.cts +0 -21
- package/dist/deepseek.d.ts +0 -21
- package/dist/deepseek.js +0 -21
- package/dist/deepseek.js.map +0 -1
- package/dist/dist-65U7OYRG.js +0 -1257
- package/dist/dist-65U7OYRG.js.map +0 -1
- package/dist/fetchProvider-Cu4WkU5O.d.cts +0 -819
- package/dist/fetchProvider-Cu4WkU5O.d.ts +0 -819
- package/dist/frontend-ui-ux.json +0 -105
- package/dist/general-assistant.json +0 -95
- package/dist/git-master.json +0 -51
- package/dist/google-vertex.cjs +0 -72
- package/dist/google-vertex.cjs.map +0 -1
- package/dist/google-vertex.d.cts +0 -21
- package/dist/google-vertex.d.ts +0 -21
- package/dist/google-vertex.js +0 -21
- package/dist/google-vertex.js.map +0 -1
- package/dist/google.cjs +0 -72
- package/dist/google.cjs.map +0 -1
- package/dist/google.d.cts +0 -21
- package/dist/google.d.ts +0 -21
- package/dist/google.js +0 -21
- package/dist/google.js.map +0 -1
- package/dist/groq.cjs +0 -72
- package/dist/groq.cjs.map +0 -1
- package/dist/groq.d.cts +0 -21
- package/dist/groq.d.ts +0 -21
- package/dist/groq.js +0 -21
- package/dist/groq.js.map +0 -1
- package/dist/index.d.mts +0 -3203
- package/dist/index.mjs +0 -7064
- package/dist/index.mjs.map +0 -1
- package/dist/mistral.cjs +0 -72
- package/dist/mistral.cjs.map +0 -1
- package/dist/mistral.d.cts +0 -21
- package/dist/mistral.d.ts +0 -21
- package/dist/mistral.js +0 -21
- package/dist/mistral.js.map +0 -1
- package/dist/multipart-parser-EJCXIUHC.js +0 -372
- package/dist/multipart-parser-EJCXIUHC.js.map +0 -1
- package/dist/openai.cjs +0 -72
- package/dist/openai.cjs.map +0 -1
- package/dist/openai.d.cts +0 -21
- package/dist/openai.d.ts +0 -21
- package/dist/openai.js +0 -21
- package/dist/openai.js.map +0 -1
- package/dist/perplexity.cjs +0 -72
- package/dist/perplexity.cjs.map +0 -1
- package/dist/perplexity.d.cts +0 -21
- package/dist/perplexity.d.ts +0 -21
- package/dist/perplexity.js +0 -21
- package/dist/perplexity.js.map +0 -1
- package/dist/playwright.json +0 -52
- package/dist/promptConcat-BJdazTg5.d.cts +0 -1832
- package/dist/promptConcat-BJdazTg5.d.ts +0 -1832
- package/dist/promptConcat-CAkpni_8.d.cts +0 -1834
- package/dist/promptConcat-CAkpni_8.d.ts +0 -1834
- package/dist/promptConcat-CfH5-GAE.d.cts +0 -1036
- package/dist/promptConcat-ChcAZOOL.d.ts +0 -1036
- package/dist/promptConcat-G5TnJVRy.d.cts +0 -1800
- package/dist/promptConcat-G5TnJVRy.d.ts +0 -1800
- package/dist/promptConcat-L72eowzp.d.ts +0 -1090
- package/dist/promptConcat-eLHdN7K8.d.cts +0 -1090
- package/dist/src-VTSXKG72.js +0 -1409
- package/dist/src-VTSXKG72.js.map +0 -1
- package/dist/togetherai.cjs +0 -72
- package/dist/togetherai.cjs.map +0 -1
- package/dist/togetherai.d.cts +0 -21
- package/dist/togetherai.d.ts +0 -21
- package/dist/togetherai.js +0 -21
- package/dist/togetherai.js.map +0 -1
- package/dist/types-B0Jm2l38.d.cts +0 -767
- package/dist/types-B0Jm2l38.d.ts +0 -767
- package/dist/xai.cjs +0 -72
- package/dist/xai.cjs.map +0 -1
- package/dist/xai.d.cts +0 -21
- package/dist/xai.d.ts +0 -21
- package/dist/xai.js +0 -21
- package/dist/xai.js.map +0 -1
- /package/dist/{chunk-P4UZ7IXC.js.map → browser.js.map} +0 -0
package/dist/browser.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentCreationController,
|
|
3
|
+
AgentDefinitionEditorController,
|
|
4
|
+
AgentSessionController,
|
|
5
|
+
PromptPreviewController,
|
|
6
|
+
TiddlyWikiHttpStorage
|
|
7
|
+
} from "./chunk-YMNXDNDW.js";
|
|
8
|
+
import {
|
|
9
|
+
ALL_CATEGORIES,
|
|
10
|
+
getCategoryConfig,
|
|
11
|
+
isTaskCategory,
|
|
12
|
+
resolveCategory
|
|
13
|
+
} from "./chunk-7ZDTB4VZ.js";
|
|
14
|
+
import {
|
|
15
|
+
REMOTE_ORCHESTRATION_PROTOCOL,
|
|
16
|
+
createFetchOrchestrationTransport,
|
|
17
|
+
createNamespacedOrchestrationClient,
|
|
18
|
+
createReadOnlyOrchestrationClient,
|
|
19
|
+
createRemoteOrchestrationClient,
|
|
20
|
+
createRemoteOrchestrationHandler
|
|
21
|
+
} from "./chunk-CCEFAOSH.js";
|
|
22
|
+
import {
|
|
23
|
+
OrchestrationError
|
|
24
|
+
} from "./chunk-FWSY5HOA.js";
|
|
25
|
+
export {
|
|
26
|
+
ALL_CATEGORIES,
|
|
27
|
+
AgentCreationController,
|
|
28
|
+
AgentDefinitionEditorController,
|
|
29
|
+
AgentSessionController,
|
|
30
|
+
OrchestrationError,
|
|
31
|
+
PromptPreviewController,
|
|
32
|
+
REMOTE_ORCHESTRATION_PROTOCOL,
|
|
33
|
+
TiddlyWikiHttpStorage,
|
|
34
|
+
createFetchOrchestrationTransport,
|
|
35
|
+
createNamespacedOrchestrationClient,
|
|
36
|
+
createReadOnlyOrchestrationClient,
|
|
37
|
+
createRemoteOrchestrationClient,
|
|
38
|
+
createRemoteOrchestrationHandler,
|
|
39
|
+
getCategoryConfig,
|
|
40
|
+
isTaskCategory,
|
|
41
|
+
resolveCategory
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import {
|
|
2
|
+
registerToolParameterSchema
|
|
3
|
+
} from "./chunk-MAJWHAKR.js";
|
|
4
|
+
import {
|
|
5
|
+
registerHook
|
|
6
|
+
} from "./chunk-T7FSXWFR.js";
|
|
7
|
+
|
|
8
|
+
// src/permission/storage.ts
|
|
9
|
+
var TABLE_NAME = "permissions";
|
|
10
|
+
var STORAGE_KEY = "user";
|
|
11
|
+
function loadUserPermissions(database) {
|
|
12
|
+
try {
|
|
13
|
+
const row = database.prepare(`SELECT rulesJson FROM ${TABLE_NAME} WHERE source = ? LIMIT 1`).get(STORAGE_KEY);
|
|
14
|
+
if (row?.rulesJson) {
|
|
15
|
+
return JSON.parse(row.rulesJson);
|
|
16
|
+
}
|
|
17
|
+
} catch {
|
|
18
|
+
}
|
|
19
|
+
return { rules: [], source: "user" };
|
|
20
|
+
}
|
|
21
|
+
function saveUserPermissions(database, set) {
|
|
22
|
+
database.prepare(
|
|
23
|
+
`INSERT OR REPLACE INTO ${TABLE_NAME} (source, rulesJson, updatedAt)
|
|
24
|
+
VALUES (?, ?, ?)`
|
|
25
|
+
).run(set.source, JSON.stringify(set), Date.now());
|
|
26
|
+
}
|
|
27
|
+
var PERMISSIONS_TABLE_DDL = `
|
|
28
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
|
|
29
|
+
source TEXT PRIMARY KEY,
|
|
30
|
+
rulesJson TEXT NOT NULL,
|
|
31
|
+
updatedAt INTEGER NOT NULL
|
|
32
|
+
);
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
// src/loopAPI/tokenTracker.ts
|
|
36
|
+
var TokenTracker = class {
|
|
37
|
+
promptTokens = 0;
|
|
38
|
+
completionTokens = 0;
|
|
39
|
+
contextWindow;
|
|
40
|
+
compactionThreshold;
|
|
41
|
+
outputBuffer;
|
|
42
|
+
compacting = false;
|
|
43
|
+
consecutiveCompactionFailures = 0;
|
|
44
|
+
maxConsecutiveFailures = 3;
|
|
45
|
+
constructor(config) {
|
|
46
|
+
this.contextWindow = config?.contextWindow ?? 2e5;
|
|
47
|
+
this.compactionThreshold = config?.compactionThreshold ?? 0.9;
|
|
48
|
+
this.outputBuffer = config?.outputBuffer ?? 16e3;
|
|
49
|
+
}
|
|
50
|
+
/** Record token usage from an LLM response */
|
|
51
|
+
recordUsage(promptTokens, completionTokens) {
|
|
52
|
+
this.promptTokens += promptTokens;
|
|
53
|
+
this.completionTokens += completionTokens;
|
|
54
|
+
}
|
|
55
|
+
/** Manually set the prompt token count (e.g., from estimation) */
|
|
56
|
+
setPromptTokens(tokens) {
|
|
57
|
+
this.promptTokens = tokens;
|
|
58
|
+
}
|
|
59
|
+
/** Get current usage */
|
|
60
|
+
getUsage() {
|
|
61
|
+
const total = this.promptTokens + this.completionTokens;
|
|
62
|
+
const effectiveWindow = this.contextWindow - this.outputBuffer;
|
|
63
|
+
const usagePercent = total / effectiveWindow;
|
|
64
|
+
return {
|
|
65
|
+
promptTokens: this.promptTokens,
|
|
66
|
+
completionTokens: this.completionTokens,
|
|
67
|
+
totalTokens: total,
|
|
68
|
+
contextWindow: this.contextWindow,
|
|
69
|
+
usagePercent: Math.min(usagePercent, 1),
|
|
70
|
+
shouldCompact: usagePercent >= this.compactionThreshold && !this.compacting
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Check if auto-compaction should be triggered */
|
|
74
|
+
shouldTriggerCompaction() {
|
|
75
|
+
if (this.consecutiveCompactionFailures >= this.maxConsecutiveFailures) return false;
|
|
76
|
+
return this.getUsage().shouldCompact;
|
|
77
|
+
}
|
|
78
|
+
/** Mark that compaction is starting */
|
|
79
|
+
markCompactionStart() {
|
|
80
|
+
this.compacting = true;
|
|
81
|
+
}
|
|
82
|
+
/** Mark that compaction succeeded — reset token counts */
|
|
83
|
+
markCompactionSuccess(estimatedPostTokens) {
|
|
84
|
+
this.compacting = false;
|
|
85
|
+
this.promptTokens = estimatedPostTokens;
|
|
86
|
+
this.completionTokens = 0;
|
|
87
|
+
this.consecutiveCompactionFailures = 0;
|
|
88
|
+
}
|
|
89
|
+
/** Mark that compaction failed */
|
|
90
|
+
markCompactionFailure() {
|
|
91
|
+
this.compacting = false;
|
|
92
|
+
this.consecutiveCompactionFailures++;
|
|
93
|
+
}
|
|
94
|
+
/** Reset all counters */
|
|
95
|
+
reset() {
|
|
96
|
+
this.promptTokens = 0;
|
|
97
|
+
this.completionTokens = 0;
|
|
98
|
+
this.compacting = false;
|
|
99
|
+
this.consecutiveCompactionFailures = 0;
|
|
100
|
+
}
|
|
101
|
+
/** Get a human-readable summary */
|
|
102
|
+
formatUsage() {
|
|
103
|
+
const usage = this.getUsage();
|
|
104
|
+
const promptK = (usage.promptTokens / 1e3).toFixed(1);
|
|
105
|
+
const windowK = (usage.contextWindow / 1e3).toFixed(0);
|
|
106
|
+
const pct = (usage.usagePercent * 100).toFixed(1);
|
|
107
|
+
return `${promptK}K/${windowK}K tokens (${pct}%)`;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// src/llm/providerRegistry.ts
|
|
112
|
+
var ProviderRegistry = class {
|
|
113
|
+
providers = /* @__PURE__ */ new Map();
|
|
114
|
+
register(provider, config) {
|
|
115
|
+
this.providers.set(provider.name, {
|
|
116
|
+
provider,
|
|
117
|
+
config: {
|
|
118
|
+
name: provider.name,
|
|
119
|
+
baseUrl: config?.baseUrl,
|
|
120
|
+
apiKey: config?.apiKey
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
unregister(name) {
|
|
125
|
+
this.providers.delete(name);
|
|
126
|
+
}
|
|
127
|
+
get(name) {
|
|
128
|
+
return this.providers.get(name)?.provider;
|
|
129
|
+
}
|
|
130
|
+
getConfig(name) {
|
|
131
|
+
return this.providers.get(name)?.config;
|
|
132
|
+
}
|
|
133
|
+
upsertConfig(config) {
|
|
134
|
+
const existing = this.providers.get(config.name);
|
|
135
|
+
if (!existing) {
|
|
136
|
+
throw new Error(`Provider not found: ${config.name}`);
|
|
137
|
+
}
|
|
138
|
+
this.providers.set(config.name, {
|
|
139
|
+
provider: existing.provider,
|
|
140
|
+
config: {
|
|
141
|
+
name: config.name,
|
|
142
|
+
baseUrl: config.baseUrl,
|
|
143
|
+
apiKey: config.apiKey
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
list() {
|
|
148
|
+
return Array.from(this.providers.keys()).sort();
|
|
149
|
+
}
|
|
150
|
+
listConfigs() {
|
|
151
|
+
return this.list().map((name) => {
|
|
152
|
+
const config = this.providers.get(name)?.config;
|
|
153
|
+
if (!config) {
|
|
154
|
+
throw new Error(`Provider config missing: ${name}`);
|
|
155
|
+
}
|
|
156
|
+
return { ...config };
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
resolve(modelId) {
|
|
160
|
+
const [providerName, ...rest] = modelId.split("/");
|
|
161
|
+
const registered = this.providers.get(providerName);
|
|
162
|
+
if (!registered) {
|
|
163
|
+
throw new Error(`Provider not found: ${providerName}`);
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
provider: registered.provider,
|
|
167
|
+
providerName,
|
|
168
|
+
modelName: rest.length > 0 ? rest.join("/") : void 0
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// src/plugin/loader.ts
|
|
174
|
+
var loadedPlugins = /* @__PURE__ */ new Map();
|
|
175
|
+
var hookTypes = /* @__PURE__ */ new Set([
|
|
176
|
+
"PreToolUse",
|
|
177
|
+
"PostToolUse",
|
|
178
|
+
"UserPromptSubmit",
|
|
179
|
+
"ContextCompaction",
|
|
180
|
+
"AgentStart",
|
|
181
|
+
"AgentStop"
|
|
182
|
+
]);
|
|
183
|
+
function isHookType(value) {
|
|
184
|
+
return typeof value === "string" && hookTypes.has(value);
|
|
185
|
+
}
|
|
186
|
+
function validatePluginManifest(object) {
|
|
187
|
+
if (!object || typeof object !== "object") return null;
|
|
188
|
+
const manifest = object;
|
|
189
|
+
if (typeof manifest.name !== "string" || manifest.name.trim().length === 0 || typeof manifest.version !== "string" || manifest.version.trim().length === 0) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
name: manifest.name.trim(),
|
|
194
|
+
version: manifest.version.trim(),
|
|
195
|
+
description: typeof manifest.description === "string" ? manifest.description : "",
|
|
196
|
+
exports: validateExports(manifest.exports),
|
|
197
|
+
author: typeof manifest.author === "string" ? manifest.author : void 0,
|
|
198
|
+
minMemeloopVersion: typeof manifest.minMemeloopVersion === "string" ? manifest.minMemeloopVersion : void 0
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function validateExports(object) {
|
|
202
|
+
if (!object || typeof object !== "object") return void 0;
|
|
203
|
+
const exportsRecord = object;
|
|
204
|
+
return {
|
|
205
|
+
tools: Array.isArray(exportsRecord.tools) ? exportsRecord.tools.filter((tool) => typeof tool === "string") : void 0,
|
|
206
|
+
hooks: Array.isArray(exportsRecord.hooks) ? exportsRecord.hooks.filter(isHookType) : void 0
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
async function loadPluginModule(options) {
|
|
210
|
+
const { manifest, module, api, source = "" } = options;
|
|
211
|
+
const validManifest = validatePluginManifest(manifest);
|
|
212
|
+
if (!validManifest) return null;
|
|
213
|
+
if (loadedPlugins.has(validManifest.name)) {
|
|
214
|
+
return loadedPlugins.get(validManifest.name) ?? null;
|
|
215
|
+
}
|
|
216
|
+
if (!module || typeof module.activate !== "function") {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
const cleanup = await module.activate(api);
|
|
220
|
+
const loaded = {
|
|
221
|
+
manifest: validManifest,
|
|
222
|
+
source,
|
|
223
|
+
module,
|
|
224
|
+
cleanup: typeof cleanup === "function" ? cleanup : void 0,
|
|
225
|
+
loadedAt: /* @__PURE__ */ new Date()
|
|
226
|
+
};
|
|
227
|
+
loadedPlugins.set(validManifest.name, loaded);
|
|
228
|
+
return loaded;
|
|
229
|
+
}
|
|
230
|
+
async function loadPluginModules(plugins) {
|
|
231
|
+
const loaded = [];
|
|
232
|
+
for (const plugin of plugins) {
|
|
233
|
+
const result = await loadPluginModule(plugin);
|
|
234
|
+
if (result) loaded.push(result);
|
|
235
|
+
}
|
|
236
|
+
return loaded;
|
|
237
|
+
}
|
|
238
|
+
function unloadPlugin(name) {
|
|
239
|
+
const loaded = loadedPlugins.get(name);
|
|
240
|
+
if (!loaded) return false;
|
|
241
|
+
try {
|
|
242
|
+
loaded.cleanup?.();
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.warn(`[plugin] Error during cleanup of "${name}":`, error);
|
|
245
|
+
}
|
|
246
|
+
loadedPlugins.delete(name);
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
function listPlugins() {
|
|
250
|
+
return Array.from(loadedPlugins.values());
|
|
251
|
+
}
|
|
252
|
+
function getLoadedPlugin(name) {
|
|
253
|
+
return loadedPlugins.get(name);
|
|
254
|
+
}
|
|
255
|
+
function isPluginLoaded(name) {
|
|
256
|
+
return loadedPlugins.has(name);
|
|
257
|
+
}
|
|
258
|
+
function unloadAllPlugins() {
|
|
259
|
+
for (const name of loadedPlugins.keys()) {
|
|
260
|
+
unloadPlugin(name);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/plugin/registry.ts
|
|
265
|
+
var PluginRegistryManager = class {
|
|
266
|
+
pluginRegistrations = /* @__PURE__ */ new Map();
|
|
267
|
+
ensureRegistration(pluginName) {
|
|
268
|
+
const existing = this.pluginRegistrations.get(pluginName);
|
|
269
|
+
if (existing) return existing;
|
|
270
|
+
const reg = {
|
|
271
|
+
pluginName,
|
|
272
|
+
tools: [],
|
|
273
|
+
hooks: []
|
|
274
|
+
};
|
|
275
|
+
this.pluginRegistrations.set(pluginName, reg);
|
|
276
|
+
return reg;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Create a PluginAPI instance that plugins use to register their capabilities.
|
|
280
|
+
*/
|
|
281
|
+
createPluginAPI(options = {}) {
|
|
282
|
+
const toolRegistry = options.toolRegistry;
|
|
283
|
+
const logger = options.logger ?? {
|
|
284
|
+
debug: (...arguments_) => {
|
|
285
|
+
console.debug("[plugin]", ...arguments_);
|
|
286
|
+
},
|
|
287
|
+
info: (...arguments_) => {
|
|
288
|
+
console.info("[plugin]", ...arguments_);
|
|
289
|
+
},
|
|
290
|
+
warn: (...arguments_) => {
|
|
291
|
+
console.warn("[plugin]", ...arguments_);
|
|
292
|
+
},
|
|
293
|
+
error: (...arguments_) => {
|
|
294
|
+
console.error("[plugin]", ...arguments_);
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
return {
|
|
298
|
+
logger,
|
|
299
|
+
registerTool(toolId, impl, schema, effect) {
|
|
300
|
+
if (effect === void 0) {
|
|
301
|
+
toolRegistry?.registerTool(toolId, impl, schema);
|
|
302
|
+
} else {
|
|
303
|
+
toolRegistry?.registerTool(toolId, impl, schema, effect);
|
|
304
|
+
}
|
|
305
|
+
if (schema) {
|
|
306
|
+
registerToolParameterSchema(toolId, schema, {
|
|
307
|
+
displayName: toolId,
|
|
308
|
+
description: `Plugin tool: ${toolId}`
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
registerHook(type, handler, name) {
|
|
313
|
+
const hookName = name ?? `plugin-hook:${type}:${Date.now().toString(36)}`;
|
|
314
|
+
registerHook(type, handler, hookName);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
registerPluginTools(pluginName, tools) {
|
|
319
|
+
const reg = this.ensureRegistration(pluginName);
|
|
320
|
+
for (const [toolId, , schema] of tools) {
|
|
321
|
+
if (schema) {
|
|
322
|
+
registerToolParameterSchema(toolId, schema, {
|
|
323
|
+
displayName: toolId,
|
|
324
|
+
description: `Plugin tool: ${toolId}`
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
reg.tools.push(toolId);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
registerPluginHooks(pluginName, hooks) {
|
|
331
|
+
const reg = this.ensureRegistration(pluginName);
|
|
332
|
+
for (const [type, handler, name] of hooks) {
|
|
333
|
+
const hookName = name ?? `plugin-hook:${pluginName}:${type}:${reg.hooks.length}`;
|
|
334
|
+
registerHook(type, handler, hookName);
|
|
335
|
+
reg.hooks.push({ type, name: hookName });
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
getPluginRegistrations(pluginName) {
|
|
339
|
+
return this.pluginRegistrations.get(pluginName);
|
|
340
|
+
}
|
|
341
|
+
clearPluginRegistrations() {
|
|
342
|
+
this.pluginRegistrations.clear();
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
var defaultPluginRegistryManager = new PluginRegistryManager();
|
|
346
|
+
function createPluginAPI(options = {}) {
|
|
347
|
+
return defaultPluginRegistryManager.createPluginAPI(options);
|
|
348
|
+
}
|
|
349
|
+
function registerPluginTools(pluginName, tools) {
|
|
350
|
+
defaultPluginRegistryManager.registerPluginTools(pluginName, tools);
|
|
351
|
+
}
|
|
352
|
+
function registerPluginHooks(pluginName, hooks) {
|
|
353
|
+
defaultPluginRegistryManager.registerPluginHooks(pluginName, hooks);
|
|
354
|
+
}
|
|
355
|
+
function getPluginRegistrations(pluginName) {
|
|
356
|
+
return defaultPluginRegistryManager.getPluginRegistrations(pluginName);
|
|
357
|
+
}
|
|
358
|
+
function clearPluginRegistrations() {
|
|
359
|
+
defaultPluginRegistryManager.clearPluginRegistrations();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export {
|
|
363
|
+
loadUserPermissions,
|
|
364
|
+
saveUserPermissions,
|
|
365
|
+
PERMISSIONS_TABLE_DDL,
|
|
366
|
+
TokenTracker,
|
|
367
|
+
ProviderRegistry,
|
|
368
|
+
validatePluginManifest,
|
|
369
|
+
loadPluginModule,
|
|
370
|
+
loadPluginModules,
|
|
371
|
+
unloadPlugin,
|
|
372
|
+
listPlugins,
|
|
373
|
+
getLoadedPlugin,
|
|
374
|
+
isPluginLoaded,
|
|
375
|
+
unloadAllPlugins,
|
|
376
|
+
createPluginAPI,
|
|
377
|
+
registerPluginTools,
|
|
378
|
+
registerPluginHooks,
|
|
379
|
+
getPluginRegistrations,
|
|
380
|
+
clearPluginRegistrations
|
|
381
|
+
};
|
|
382
|
+
//# sourceMappingURL=chunk-2C6BJZI3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/permission/storage.ts","../src/loopAPI/tokenTracker.ts","../src/llm/providerRegistry.ts","../src/plugin/loader.ts","../src/plugin/registry.ts"],"sourcesContent":["import type { PermissionSet } from './types.js';\n\nexport interface PermissionSqlStatement {\n get(...arguments_: unknown[]): unknown;\n run(...arguments_: unknown[]): unknown;\n}\n\nexport interface PermissionSqlDatabase {\n prepare(sql: string): PermissionSqlStatement;\n}\n\nconst TABLE_NAME = 'permissions';\nconst STORAGE_KEY = 'user';\n\n/**\n * Load user-level permission set from SQLite.\n *\n * The `permissions` table stores JSON blobs keyed by `source`.\n * Returns an empty set if no persisted rules exist.\n */\nexport function loadUserPermissions(database: PermissionSqlDatabase): PermissionSet {\n try {\n const row = database\n .prepare(`SELECT rulesJson FROM ${TABLE_NAME} WHERE source = ? LIMIT 1`)\n .get(STORAGE_KEY) as { rulesJson: string } | undefined;\n\n if (row?.rulesJson) {\n return JSON.parse(row.rulesJson) as PermissionSet;\n }\n } catch {\n /* Table may not exist yet; return empty */\n }\n\n return { rules: [], source: 'user' };\n}\n\n/**\n * Persist user-level permission set to SQLite.\n *\n * Uses INSERT OR REPLACE so first-time saves work without explicit table detection.\n */\nexport function saveUserPermissions(database: PermissionSqlDatabase, set: PermissionSet): void {\n database.prepare(\n `INSERT OR REPLACE INTO ${TABLE_NAME} (source, rulesJson, updatedAt)\n VALUES (?, ?, ?)`,\n ).run(set.source, JSON.stringify(set), Date.now());\n}\n\n/** SQL statement to create the permissions table during migration. */\nexport const PERMISSIONS_TABLE_DDL = `\n CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (\n source TEXT PRIMARY KEY,\n rulesJson TEXT NOT NULL,\n updatedAt INTEGER NOT NULL\n );\n`;\n","/**\n * Token counting and auto-compaction trigger.\n * Tracks token usage per conversation and triggers compaction when approaching limits.\n *\n * Based on: Claude Code autoCompact + OpenCode autoCompact@95%\n */\n\n/** Rough token estimation: ~4 chars per token (conservative) */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 3.5);\n}\n\n/** Estimate token count for a messages array */\nexport function estimateMessagesTokens(messages: Array<{ content: unknown }>): number {\n let total = 0;\n for (const message of messages) {\n const content = typeof message.content === 'string' ? message.content : JSON.stringify(message.content ?? '');\n total += estimateTokens(content);\n }\n return total;\n}\n\nexport interface TokenTrackerConfig {\n /** Maximum context window in tokens (default: 200000) */\n contextWindow?: number;\n /** Trigger compaction when usage exceeds this fraction (default: 0.90) */\n compactionThreshold?: number;\n /** Buffer tokens reserved for output (default: 16000) */\n outputBuffer?: number;\n}\n\nexport interface TokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n contextWindow: number;\n usagePercent: number;\n shouldCompact: boolean;\n}\n\n/**\n * Tracks token usage and decides when to trigger auto-compaction.\n */\nexport class TokenTracker {\n private promptTokens = 0;\n private completionTokens = 0;\n private readonly contextWindow: number;\n private readonly compactionThreshold: number;\n private readonly outputBuffer: number;\n private compacting = false;\n private consecutiveCompactionFailures = 0;\n private maxConsecutiveFailures = 3;\n\n constructor(config?: TokenTrackerConfig) {\n this.contextWindow = config?.contextWindow ?? 200_000;\n this.compactionThreshold = config?.compactionThreshold ?? 0.9;\n this.outputBuffer = config?.outputBuffer ?? 16_000;\n }\n\n /** Record token usage from an LLM response */\n recordUsage(promptTokens: number, completionTokens: number): void {\n this.promptTokens += promptTokens;\n this.completionTokens += completionTokens;\n }\n\n /** Manually set the prompt token count (e.g., from estimation) */\n setPromptTokens(tokens: number): void {\n this.promptTokens = tokens;\n }\n\n /** Get current usage */\n getUsage(): TokenUsage {\n const total = this.promptTokens + this.completionTokens;\n const effectiveWindow = this.contextWindow - this.outputBuffer;\n const usagePercent = total / effectiveWindow;\n return {\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: total,\n contextWindow: this.contextWindow,\n usagePercent: Math.min(usagePercent, 1.0),\n shouldCompact: usagePercent >= this.compactionThreshold && !this.compacting,\n };\n }\n\n /** Check if auto-compaction should be triggered */\n shouldTriggerCompaction(): boolean {\n if (this.consecutiveCompactionFailures >= this.maxConsecutiveFailures) return false;\n return this.getUsage().shouldCompact;\n }\n\n /** Mark that compaction is starting */\n markCompactionStart(): void {\n this.compacting = true;\n }\n\n /** Mark that compaction succeeded — reset token counts */\n markCompactionSuccess(estimatedPostTokens: number): void {\n this.compacting = false;\n this.promptTokens = estimatedPostTokens;\n this.completionTokens = 0;\n this.consecutiveCompactionFailures = 0;\n }\n\n /** Mark that compaction failed */\n markCompactionFailure(): void {\n this.compacting = false;\n this.consecutiveCompactionFailures++;\n }\n\n /** Reset all counters */\n reset(): void {\n this.promptTokens = 0;\n this.completionTokens = 0;\n this.compacting = false;\n this.consecutiveCompactionFailures = 0;\n }\n\n /** Get a human-readable summary */\n formatUsage(): string {\n const usage = this.getUsage();\n const promptK = (usage.promptTokens / 1000).toFixed(1);\n const windowK = (usage.contextWindow / 1000).toFixed(0);\n const pct = (usage.usagePercent * 100).toFixed(1);\n return `${promptK}K/${windowK}K tokens (${pct}%)`;\n }\n}\n\n/** Interface for a compaction engine that can summarize conversation history */\nexport interface CompactionEngine {\n compact(\n messages: Array<{ role: string; content: unknown }>,\n conversationId: string,\n ): Promise<void>;\n}\n\n/**\n * Auto-compaction hook — call this after each LLM response.\n * Triggers compaction when token usage exceeds threshold.\n *\n * @returns true if compaction was triggered\n */\nexport async function maybeAutoCompact(\n tracker: TokenTracker,\n compactionEngine: CompactionEngine,\n messages: Array<{ role: string; content: unknown }>,\n conversationId: string,\n): Promise<boolean> {\n if (!tracker.shouldTriggerCompaction()) return false;\n\n tracker.markCompactionStart();\n try {\n await compactionEngine.compact(messages, conversationId);\n const estimatedPost = estimateTokens('Summary of previous conversation context.');\n tracker.markCompactionSuccess(estimatedPost);\n return true;\n } catch {\n tracker.markCompactionFailure();\n return false;\n }\n}\n","import type { ILLMProvider } from '../types.js';\n\nexport interface ProviderConfig {\n name: string;\n baseUrl?: string;\n apiKey?: string;\n}\n\nexport interface RegisteredProvider {\n provider: ILLMProvider;\n config: ProviderConfig;\n}\n\nexport class ProviderRegistry {\n private providers = new Map<string, RegisteredProvider>();\n\n register(provider: ILLMProvider, config?: Omit<ProviderConfig, 'name'>): void {\n this.providers.set(provider.name, {\n provider,\n config: {\n name: provider.name,\n baseUrl: config?.baseUrl,\n apiKey: config?.apiKey,\n },\n });\n }\n\n unregister(name: string): void {\n this.providers.delete(name);\n }\n\n get(name: string): ILLMProvider | undefined {\n return this.providers.get(name)?.provider;\n }\n\n getConfig(name: string): ProviderConfig | undefined {\n return this.providers.get(name)?.config;\n }\n\n upsertConfig(config: ProviderConfig): void {\n const existing = this.providers.get(config.name);\n if (!existing) {\n throw new Error(`Provider not found: ${config.name}`);\n }\n this.providers.set(config.name, {\n provider: existing.provider,\n config: {\n name: config.name,\n baseUrl: config.baseUrl,\n apiKey: config.apiKey,\n },\n });\n }\n\n list(): string[] {\n return Array.from(this.providers.keys()).sort();\n }\n\n listConfigs(): ProviderConfig[] {\n return this.list().map((name) => {\n const config = this.providers.get(name)?.config;\n if (!config) {\n throw new Error(`Provider config missing: ${name}`);\n }\n return { ...config };\n });\n }\n\n resolve(modelId: string): { provider: ILLMProvider; providerName: string; modelName?: string } {\n const [providerName, ...rest] = modelId.split('/');\n const registered = this.providers.get(providerName);\n if (!registered) {\n throw new Error(`Provider not found: ${providerName}`);\n }\n return {\n provider: registered.provider,\n providerName,\n modelName: rest.length > 0 ? rest.join('/') : undefined,\n };\n }\n}\n","import type { HookType } from '../loopAPI/hooks/types.js';\nimport type { LoadedPlugin, PluginManifest, PluginModule } from './types.js';\n\nconst loadedPlugins = new Map<string, LoadedPlugin>();\n\nconst hookTypes = new Set<string>([\n 'PreToolUse',\n 'PostToolUse',\n 'UserPromptSubmit',\n 'ContextCompaction',\n 'AgentStart',\n 'AgentStop',\n]);\n\nfunction isHookType(value: unknown): value is HookType {\n return typeof value === 'string' && hookTypes.has(value);\n}\n\nexport function validatePluginManifest(object: unknown): PluginManifest | null {\n if (!object || typeof object !== 'object') return null;\n const manifest = object as Record<string, unknown>;\n if (\n typeof manifest.name !== 'string' ||\n manifest.name.trim().length === 0 ||\n typeof manifest.version !== 'string' ||\n manifest.version.trim().length === 0\n ) {\n return null;\n }\n return {\n name: manifest.name.trim(),\n version: manifest.version.trim(),\n description: typeof manifest.description === 'string' ? manifest.description : '',\n exports: validateExports(manifest.exports),\n author: typeof manifest.author === 'string' ? manifest.author : undefined,\n minMemeloopVersion: typeof manifest.minMemeloopVersion === 'string' ? manifest.minMemeloopVersion : undefined,\n };\n}\n\nfunction validateExports(object: unknown): PluginManifest['exports'] {\n if (!object || typeof object !== 'object') return undefined;\n const exportsRecord = object as Record<string, unknown>;\n return {\n tools: Array.isArray(exportsRecord.tools)\n ? exportsRecord.tools.filter((tool): tool is string => typeof tool === 'string')\n : undefined,\n hooks: Array.isArray(exportsRecord.hooks) ? exportsRecord.hooks.filter(isHookType) : undefined,\n };\n}\n\nexport interface LoadPluginModuleOptions {\n manifest: PluginManifest;\n module: PluginModule;\n api?: unknown;\n source?: string;\n}\n\nexport async function loadPluginModule(\n options: LoadPluginModuleOptions,\n): Promise<LoadedPlugin | null> {\n const { manifest, module, api, source = '' } = options;\n const validManifest = validatePluginManifest(manifest);\n if (!validManifest) return null;\n\n if (loadedPlugins.has(validManifest.name)) {\n return loadedPlugins.get(validManifest.name) ?? null;\n }\n\n if (!module || typeof module.activate !== 'function') {\n return null;\n }\n\n const cleanup = await module.activate(api as never);\n const loaded: LoadedPlugin = {\n manifest: validManifest,\n source,\n module,\n cleanup: typeof cleanup === 'function' ? cleanup : undefined,\n loadedAt: new Date(),\n };\n\n loadedPlugins.set(validManifest.name, loaded);\n return loaded;\n}\n\nexport async function loadPluginModules(\n plugins: LoadPluginModuleOptions[],\n): Promise<LoadedPlugin[]> {\n const loaded: LoadedPlugin[] = [];\n for (const plugin of plugins) {\n const result = await loadPluginModule(plugin);\n if (result) loaded.push(result);\n }\n return loaded;\n}\n\nexport function unloadPlugin(name: string): boolean {\n const loaded = loadedPlugins.get(name);\n if (!loaded) return false;\n\n try {\n loaded.cleanup?.();\n } catch (error) {\n console.warn(`[plugin] Error during cleanup of \"${name}\":`, error);\n }\n\n loadedPlugins.delete(name);\n return true;\n}\n\nexport function listPlugins(): LoadedPlugin[] {\n return Array.from(loadedPlugins.values());\n}\n\nexport function getLoadedPlugin(name: string): LoadedPlugin | undefined {\n return loadedPlugins.get(name);\n}\n\nexport function isPluginLoaded(name: string): boolean {\n return loadedPlugins.has(name);\n}\n\nexport function unloadAllPlugins(): void {\n for (const name of loadedPlugins.keys()) {\n unloadPlugin(name);\n }\n}\n","/**\n * Plugin registry: bridges plugin exports to memeloop's tool and hook registries.\n *\n * Provides a `createPluginAPI()` factory that plugins call during `activate()`\n * to register their tools and hooks with the host runtime.\n *\n * Converted from module-level singletons to an instance class for test isolation\n * and multi-runtime support.\n */\n\nimport { registerHook } from '../loopAPI/hooks/registry.js';\nimport type { HookHandler, HookType } from '../loopAPI/hooks/types.js';\nimport type { ToolOperationEffect } from '../orchestration/resources.js';\nimport { registerToolParameterSchema } from '../tools/schemaRegistry.js';\nimport type { PluginAPI } from './types.js';\n\n/** Plugin API factory options. */\nexport interface PluginAPIOptions {\n toolRegistry?: {\n registerTool(\n id: string,\n impl: unknown,\n schema?: unknown,\n effect?: ToolOperationEffect,\n ): void;\n };\n logger?: PluginAPI['logger'];\n}\n\n/**\n * Track which tools/plugins belong to each plugin so we can clean up on unload.\n */\ninterface PluginRegistration {\n pluginName: string;\n tools: string[];\n hooks: Array<{ type: HookType; name: string }>;\n}\n\n/**\n * Instance-level plugin registration manager.\n */\nexport class PluginRegistryManager {\n private readonly pluginRegistrations = new Map<string, PluginRegistration>();\n\n private ensureRegistration(pluginName: string): PluginRegistration {\n const existing = this.pluginRegistrations.get(pluginName);\n if (existing) return existing;\n const reg: PluginRegistration = {\n pluginName,\n tools: [],\n hooks: [],\n };\n this.pluginRegistrations.set(pluginName, reg);\n return reg;\n }\n\n /**\n * Create a PluginAPI instance that plugins use to register their capabilities.\n */\n createPluginAPI(options: PluginAPIOptions = {}): PluginAPI {\n const toolRegistry = options.toolRegistry;\n const logger = options.logger ?? {\n debug: (...arguments_: unknown[]) => {\n console.debug('[plugin]', ...arguments_);\n },\n info: (...arguments_: unknown[]) => {\n console.info('[plugin]', ...arguments_);\n },\n warn: (...arguments_: unknown[]) => {\n console.warn('[plugin]', ...arguments_);\n },\n error: (...arguments_: unknown[]) => {\n console.error('[plugin]', ...arguments_);\n },\n };\n\n return {\n logger,\n\n registerTool(\n toolId: string,\n impl: (...arguments_: unknown[]) => unknown,\n schema?: unknown,\n effect?: ToolOperationEffect,\n ) {\n if (effect === undefined) {\n toolRegistry?.registerTool(toolId, impl, schema);\n } else {\n toolRegistry?.registerTool(toolId, impl, schema, effect);\n }\n if (schema) {\n registerToolParameterSchema(toolId, schema as object, {\n displayName: toolId,\n description: `Plugin tool: ${toolId}`,\n });\n }\n },\n\n registerHook(type: HookType, handler: HookHandler, name?: string) {\n const hookName = name ?? `plugin-hook:${type}:${Date.now().toString(36)}`;\n registerHook(type, handler, hookName);\n },\n };\n }\n\n registerPluginTools(\n pluginName: string,\n tools: Array<readonly [string, (...arguments_: unknown[]) => unknown, unknown?]>,\n ): void {\n const reg = this.ensureRegistration(pluginName);\n for (const [toolId, , schema] of tools) {\n if (schema) {\n registerToolParameterSchema(toolId, schema as object, {\n displayName: toolId,\n description: `Plugin tool: ${toolId}`,\n });\n }\n reg.tools.push(toolId);\n }\n }\n\n registerPluginHooks(\n pluginName: string,\n hooks: Array<readonly [HookType, HookHandler, string?]>,\n ): void {\n const reg = this.ensureRegistration(pluginName);\n for (const [type, handler, name] of hooks) {\n const hookName = name ?? `plugin-hook:${pluginName}:${type}:${reg.hooks.length}`;\n registerHook(type, handler, hookName);\n reg.hooks.push({ type, name: hookName });\n }\n }\n\n getPluginRegistrations(pluginName: string): PluginRegistration | undefined {\n return this.pluginRegistrations.get(pluginName);\n }\n\n clearPluginRegistrations(): void {\n this.pluginRegistrations.clear();\n }\n}\n\n// ─── Default global instance + backward-compatible function exports ───\n\nconst defaultPluginRegistryManager = new PluginRegistryManager();\n\nexport function getDefaultPluginRegistryManager(): PluginRegistryManager {\n return defaultPluginRegistryManager;\n}\n\nexport function createPluginAPI(options: PluginAPIOptions = {}): PluginAPI {\n return defaultPluginRegistryManager.createPluginAPI(options);\n}\n\nexport function registerPluginTools(\n pluginName: string,\n tools: Array<readonly [string, (...arguments_: unknown[]) => unknown, unknown?]>,\n): void {\n defaultPluginRegistryManager.registerPluginTools(pluginName, tools);\n}\n\nexport function registerPluginHooks(\n pluginName: string,\n hooks: Array<readonly [HookType, HookHandler, string?]>,\n): void {\n defaultPluginRegistryManager.registerPluginHooks(pluginName, hooks);\n}\n\nexport function getPluginRegistrations(pluginName: string): PluginRegistration | undefined {\n return defaultPluginRegistryManager.getPluginRegistrations(pluginName);\n}\n\nexport function clearPluginRegistrations(): void {\n defaultPluginRegistryManager.clearPluginRegistrations();\n}\n"],"mappings":"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","names":[]}
|