@cremini/skillpack 1.1.1 → 1.1.2
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 +5 -10
- package/package.json +1 -1
- package/runtime/server/dist/agent.js +140 -118
- package/runtime/server/dist/agent.js.map +1 -1
- package/runtime/web/index.html +1 -0
- package/runtime/web/js/api-key-dialog.js +44 -4
package/README.md
CHANGED
|
@@ -2,22 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Skillpack by Cremini is built on the idea of distributed intelligence, much like cremini mushrooms that grow from a vast, interconnected mycelial network.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Use Case
|
|
6
|
+
The main use case is to **run local agents on your computer and integrate them with Slack or Telegram** so they can work for you and your team—operating entirely on your machine to keep all team data local and private, while continuously improving by learning new skills.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npx @cremini/skillpack create
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
If skills and tools are like LEGO pieces, a skill pack is the master piece that assembles them into a complete solution.
|
|
14
|
-
|
|
15
|
-
Each Skill Pack should organize different skills to address a well-defined problem or complete specific tasks. For example, research a company by gathering information from various sources and create a PowerPoint presentation based on the findings.
|
|
8
|
+
If skills and tools are like LEGO pieces, a skill pack is the master piece that assembles them into a complete solution. Go to [skillpack.sh](https://skillpack.sh) to download skillpacks.Each Skill Pack should organize different skills to address a well-defined problem or complete specific tasks. For example, research a company by gathering information from various sources and create a PowerPoint presentation based on the findings.
|
|
16
9
|
|
|
17
10
|
## Quick Start
|
|
18
11
|
|
|
19
12
|
### Create a Skill Pack Interactively
|
|
20
13
|
|
|
14
|
+
One command orchestrates [Skills](https://skills.sh) and tools into a Local Agent that users can download and run it on their own computer to get work done. It can also connect to chat platforms like Slack or Telegram, allowing you to easily send instructions to your local agent team anytime.
|
|
15
|
+
|
|
21
16
|
```bash
|
|
22
17
|
npx @cremini/skillpack create
|
|
23
18
|
```
|
package/package.json
CHANGED
|
@@ -34,6 +34,7 @@ function getLifecycleTrigger(channelId) {
|
|
|
34
34
|
export class PackAgent {
|
|
35
35
|
options;
|
|
36
36
|
channels = new Map();
|
|
37
|
+
pendingSessionCreations = new Map();
|
|
37
38
|
constructor(options) {
|
|
38
39
|
this.options = options;
|
|
39
40
|
}
|
|
@@ -44,135 +45,156 @@ export class PackAgent {
|
|
|
44
45
|
const existing = this.channels.get(channelId);
|
|
45
46
|
if (existing)
|
|
46
47
|
return existing;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
48
|
+
const pendingCreation = this.pendingSessionCreations.get(channelId);
|
|
49
|
+
if (pendingCreation)
|
|
50
|
+
return pendingCreation;
|
|
51
|
+
const createSessionPromise = (async () => {
|
|
52
|
+
const { apiKey, rootDir, provider, modelId } = this.options;
|
|
53
|
+
const authStorage = AuthStorage.inMemory({
|
|
54
|
+
[provider]: { type: "api_key", key: apiKey },
|
|
55
|
+
});
|
|
56
|
+
authStorage.setRuntimeApiKey(provider, apiKey);
|
|
57
|
+
const modelRegistry = new ModelRegistry(authStorage);
|
|
58
|
+
const model = modelRegistry.find(provider, modelId);
|
|
59
|
+
const sessionManager = SessionManager.inMemory();
|
|
60
|
+
const skillsPath = path.resolve(rootDir, "skills");
|
|
61
|
+
log(`[PackAgent] Loading skills from: ${skillsPath}`);
|
|
62
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
63
|
+
cwd: rootDir,
|
|
64
|
+
additionalSkillPaths: [skillsPath],
|
|
65
|
+
});
|
|
66
|
+
await resourceLoader.reload();
|
|
67
|
+
const { session } = await createAgentSession({
|
|
68
|
+
cwd: rootDir,
|
|
69
|
+
authStorage,
|
|
70
|
+
modelRegistry,
|
|
71
|
+
sessionManager,
|
|
72
|
+
resourceLoader,
|
|
73
|
+
model,
|
|
74
|
+
});
|
|
75
|
+
const channelSession = {
|
|
76
|
+
session,
|
|
77
|
+
running: false,
|
|
78
|
+
pending: Promise.resolve(),
|
|
79
|
+
};
|
|
80
|
+
this.channels.set(channelId, channelSession);
|
|
81
|
+
return channelSession;
|
|
82
|
+
})();
|
|
83
|
+
this.pendingSessionCreations.set(channelId, createSessionPromise);
|
|
84
|
+
try {
|
|
85
|
+
return await createSessionPromise;
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
this.pendingSessionCreations.delete(channelId);
|
|
89
|
+
}
|
|
73
90
|
}
|
|
74
91
|
async handleMessage(channelId, text, onEvent) {
|
|
75
92
|
const cs = await this.getOrCreateSession(channelId);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
const run = async () => {
|
|
94
|
+
cs.running = true;
|
|
95
|
+
let turnHadVisibleOutput = false;
|
|
96
|
+
// Subscribe to agent events and forward to adapter
|
|
97
|
+
const unsubscribe = cs.session.subscribe((event) => {
|
|
98
|
+
switch (event.type) {
|
|
99
|
+
case "agent_start":
|
|
100
|
+
log("\n=== [AGENT SESSION START] ===");
|
|
101
|
+
log("System Prompt:\n", cs.session.systemPrompt);
|
|
102
|
+
log("============================\n");
|
|
103
|
+
onEvent({ type: "agent_start" });
|
|
104
|
+
break;
|
|
105
|
+
case "message_start":
|
|
106
|
+
log(`\n--- [Message Start: ${event.message?.role}] ---`);
|
|
107
|
+
if (event.message?.role === "user") {
|
|
108
|
+
log(JSON.stringify(event.message.content, null, 2));
|
|
109
|
+
}
|
|
110
|
+
onEvent({ type: "message_start", role: event.message?.role ?? "" });
|
|
111
|
+
break;
|
|
112
|
+
case "message_update":
|
|
113
|
+
if (event.assistantMessageEvent?.type === "text_delta") {
|
|
114
|
+
turnHadVisibleOutput = true;
|
|
115
|
+
write(event.assistantMessageEvent.delta);
|
|
116
|
+
onEvent({
|
|
117
|
+
type: "text_delta",
|
|
118
|
+
delta: event.assistantMessageEvent.delta,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
else if (event.assistantMessageEvent?.type === "thinking_delta") {
|
|
122
|
+
turnHadVisibleOutput = true;
|
|
123
|
+
onEvent({
|
|
124
|
+
type: "thinking_delta",
|
|
125
|
+
delta: event.assistantMessageEvent.delta,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
case "message_end":
|
|
130
|
+
log(`\n--- [Message End: ${event.message?.role}] ---`);
|
|
131
|
+
if (event.message?.role === "assistant") {
|
|
132
|
+
const diagnostics = getAssistantDiagnostics(event.message);
|
|
133
|
+
if (diagnostics) {
|
|
134
|
+
log(`[Assistant Diagnostics] stopReason=${diagnostics.stopReason} text=${diagnostics.hasText ? "yes" : "no"} toolCalls=${diagnostics.toolCalls}`);
|
|
135
|
+
if (diagnostics.errorMessage) {
|
|
136
|
+
log(`[Assistant Error] ${diagnostics.errorMessage}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
onEvent({ type: "message_end", role: event.message?.role ?? "" });
|
|
141
|
+
break;
|
|
142
|
+
case "tool_execution_start":
|
|
96
143
|
turnHadVisibleOutput = true;
|
|
97
|
-
|
|
144
|
+
log(`\n>>> [Tool Start: ${event.toolName}] >>>`);
|
|
145
|
+
log("Args:", JSON.stringify(event.args, null, 2));
|
|
98
146
|
onEvent({
|
|
99
|
-
type: "
|
|
100
|
-
|
|
147
|
+
type: "tool_start",
|
|
148
|
+
toolName: event.toolName,
|
|
149
|
+
toolInput: event.args,
|
|
101
150
|
});
|
|
102
|
-
|
|
103
|
-
|
|
151
|
+
break;
|
|
152
|
+
case "tool_execution_end":
|
|
104
153
|
turnHadVisibleOutput = true;
|
|
154
|
+
log(`<<< [Tool End: ${event.toolName}] <<<`);
|
|
155
|
+
log(`Error: ${event.isError ? "Yes" : "No"}`);
|
|
105
156
|
onEvent({
|
|
106
|
-
type: "
|
|
107
|
-
|
|
157
|
+
type: "tool_end",
|
|
158
|
+
toolName: event.toolName,
|
|
159
|
+
isError: event.isError,
|
|
160
|
+
result: event.result,
|
|
108
161
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
log(`<<< [Tool End: ${event.toolName}] <<<`);
|
|
137
|
-
log(`Error: ${event.isError ? "Yes" : "No"}`);
|
|
138
|
-
onEvent({
|
|
139
|
-
type: "tool_end",
|
|
140
|
-
toolName: event.toolName,
|
|
141
|
-
isError: event.isError,
|
|
142
|
-
result: event.result,
|
|
143
|
-
});
|
|
144
|
-
break;
|
|
145
|
-
case "agent_end":
|
|
146
|
-
log("\n=== [AGENT SESSION END] ===\n");
|
|
147
|
-
onEvent({ type: "agent_end" });
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
try {
|
|
152
|
-
await cs.session.prompt(text);
|
|
153
|
-
const lastMessage = cs.session.state.messages.at(-1);
|
|
154
|
-
const diagnostics = getAssistantDiagnostics(lastMessage);
|
|
155
|
-
if (diagnostics?.errorMessage) {
|
|
156
|
-
return {
|
|
157
|
-
stopReason: diagnostics.stopReason,
|
|
158
|
-
errorMessage: diagnostics.errorMessage,
|
|
159
|
-
};
|
|
162
|
+
break;
|
|
163
|
+
case "agent_end":
|
|
164
|
+
log("\n=== [AGENT SESSION END] ===\n");
|
|
165
|
+
onEvent({ type: "agent_end" });
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
try {
|
|
170
|
+
await cs.session.prompt(text);
|
|
171
|
+
const lastMessage = cs.session.state.messages.at(-1);
|
|
172
|
+
const diagnostics = getAssistantDiagnostics(lastMessage);
|
|
173
|
+
if (diagnostics?.errorMessage) {
|
|
174
|
+
return {
|
|
175
|
+
stopReason: diagnostics.stopReason,
|
|
176
|
+
errorMessage: diagnostics.errorMessage,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
if (diagnostics &&
|
|
180
|
+
!diagnostics.hasText &&
|
|
181
|
+
diagnostics.toolCalls === 0 &&
|
|
182
|
+
!turnHadVisibleOutput) {
|
|
183
|
+
return {
|
|
184
|
+
stopReason: diagnostics.stopReason,
|
|
185
|
+
errorMessage: "Assistant returned no visible output. Check the server logs for details.",
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return { stopReason: diagnostics?.stopReason ?? "unknown" };
|
|
160
189
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
!turnHadVisibleOutput) {
|
|
165
|
-
return {
|
|
166
|
-
stopReason: diagnostics.stopReason,
|
|
167
|
-
errorMessage: "Assistant returned no visible output. Check the server logs for details.",
|
|
168
|
-
};
|
|
190
|
+
finally {
|
|
191
|
+
cs.running = false;
|
|
192
|
+
unsubscribe();
|
|
169
193
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
unsubscribe();
|
|
175
|
-
}
|
|
194
|
+
};
|
|
195
|
+
const resultPromise = cs.pending.catch(() => undefined).then(run);
|
|
196
|
+
cs.pending = resultPromise.then(() => undefined, () => undefined);
|
|
197
|
+
return resultPromise;
|
|
176
198
|
}
|
|
177
199
|
async handleCommand(command, channelId) {
|
|
178
200
|
switch (command) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAavC,MAAM,KAAK,GAAG,IAAI,CAAC;AACnB,MAAM,GAAG,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;AAClE,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAapE,SAAS,uBAAuB,CAAC,OAAY;IAC3C,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,SAAS,CAAC;IACnD,MAAM,YAAY,GAChB,OAAO,CAAC,YAAY;QACpB,CAAC,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,SAAS;YACjD,CAAC,CAAC,WAAW,UAAU,EAAE;YACzB,CAAC,CAAC,EAAE,CAAC,CAAC;IAEV,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,MAAM,IAAI,GAAG,OAAO;SACjB,MAAM,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;SAC5C,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;SACnC,IAAI,CAAC,EAAE,CAAC;SACR,IAAI,EAAE,CAAC;IACV,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAC9B,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,UAAU,CACzC,CAAC,MAAM,CAAC;IAET,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC;AAC3E,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,IAAI,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,UAAU,CAAC;IACzD,IAAI,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC;IACnD,OAAO,KAAK,CAAC;AACf,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
package/runtime/web/index.html
CHANGED
|
@@ -151,6 +151,7 @@
|
|
|
151
151
|
</div>
|
|
152
152
|
<div class="settings-modal-footer">
|
|
153
153
|
<p id="apikey-status" class="status-text"></p>
|
|
154
|
+
<button id="restart-apikey-btn" class="secondary-btn" hidden>Restart Service</button>
|
|
154
155
|
<button id="save-apikey-btn" class="primary-btn">Save API Key</button>
|
|
155
156
|
</div>
|
|
156
157
|
</dialog>
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
* 独立的 Dialog,从原 SettingDialog 的 API Key 部分拆分出来。
|
|
6
6
|
*/
|
|
7
7
|
import { state } from "./config.js";
|
|
8
|
-
import { saveConfigData } from "./api.js";
|
|
8
|
+
import { saveConfigData, restartRuntime } from "./api.js";
|
|
9
9
|
|
|
10
10
|
// --- DOM Elements ---
|
|
11
11
|
let dialog;
|
|
12
12
|
let openBtn;
|
|
13
13
|
let closeBtn;
|
|
14
14
|
let saveBtn;
|
|
15
|
+
let restartBtn;
|
|
15
16
|
let providerSelect;
|
|
16
17
|
let apiKeyInput;
|
|
17
18
|
let statusEl;
|
|
@@ -23,6 +24,7 @@ export function initApiKeyDialog() {
|
|
|
23
24
|
openBtn = document.getElementById("open-apikey-btn");
|
|
24
25
|
closeBtn = document.getElementById("close-apikey-btn");
|
|
25
26
|
saveBtn = document.getElementById("save-apikey-btn");
|
|
27
|
+
restartBtn = document.getElementById("restart-apikey-btn");
|
|
26
28
|
providerSelect = document.getElementById("apikey-provider-select");
|
|
27
29
|
apiKeyInput = document.getElementById("apikey-input");
|
|
28
30
|
statusEl = document.getElementById("apikey-status");
|
|
@@ -38,6 +40,9 @@ export function initApiKeyDialog() {
|
|
|
38
40
|
if (saveBtn) {
|
|
39
41
|
saveBtn.addEventListener("click", handleSave);
|
|
40
42
|
}
|
|
43
|
+
if (restartBtn) {
|
|
44
|
+
restartBtn.addEventListener("click", handleRestart);
|
|
45
|
+
}
|
|
41
46
|
if (providerSelect) {
|
|
42
47
|
providerSelect.addEventListener("change", updatePlaceholder);
|
|
43
48
|
}
|
|
@@ -134,11 +139,21 @@ async function handleSave() {
|
|
|
134
139
|
state.config.runtimeControl = res.runtimeControl;
|
|
135
140
|
state.restartRequired = !!res.requiresRestart;
|
|
136
141
|
|
|
137
|
-
setStatus("API key saved successfully", "success");
|
|
138
142
|
updateApiKeyButton();
|
|
139
143
|
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
if (res.requiresRestart) {
|
|
145
|
+
setStatus(
|
|
146
|
+
res.runtimeControl?.canManagedRestart
|
|
147
|
+
? "API key saved. Restart service to apply changes."
|
|
148
|
+
: "API key saved. Restart the service manually to apply changes.",
|
|
149
|
+
"warning",
|
|
150
|
+
);
|
|
151
|
+
updateRestartButton(!!res.runtimeControl?.canManagedRestart);
|
|
152
|
+
} else {
|
|
153
|
+
setStatus("API key saved successfully", "success");
|
|
154
|
+
// 延迟关闭让用户看到成功消息
|
|
155
|
+
setTimeout(() => close(), 1200);
|
|
156
|
+
}
|
|
142
157
|
} catch (err) {
|
|
143
158
|
setStatus("Save failed: " + err.message, "error");
|
|
144
159
|
} finally {
|
|
@@ -146,6 +161,31 @@ async function handleSave() {
|
|
|
146
161
|
}
|
|
147
162
|
}
|
|
148
163
|
|
|
164
|
+
async function handleRestart() {
|
|
165
|
+
if (!restartBtn) return;
|
|
166
|
+
|
|
167
|
+
restartBtn.disabled = true;
|
|
168
|
+
if (saveBtn) saveBtn.disabled = true;
|
|
169
|
+
setStatus("Restarting service...", "warning");
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
await restartRuntime();
|
|
173
|
+
setTimeout(() => {
|
|
174
|
+
window.location.reload();
|
|
175
|
+
}, 6000);
|
|
176
|
+
} catch (err) {
|
|
177
|
+
if (saveBtn) saveBtn.disabled = false;
|
|
178
|
+
restartBtn.disabled = false;
|
|
179
|
+
setStatus("Restart failed: " + err.message, "error");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function updateRestartButton(show) {
|
|
184
|
+
if (!restartBtn) return;
|
|
185
|
+
restartBtn.hidden = !show;
|
|
186
|
+
restartBtn.disabled = false;
|
|
187
|
+
}
|
|
188
|
+
|
|
149
189
|
function setStatus(message, status) {
|
|
150
190
|
if (!statusEl) return;
|
|
151
191
|
statusEl.textContent = message;
|