@fickydev/pigent 0.1.22 → 0.1.24
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/CHANGELOG.md +14 -0
- package/TODO.md +4 -0
- package/package.json +1 -1
- package/src/agents/AgentRunner.ts +5 -2
- package/src/agents/BotCommandHandler.ts +6 -4
- package/src/channels/telegram/TelegramApi.ts +29 -2
- package/src/channels/telegram/TelegramPollingAdapter.ts +87 -1
- package/src/channels/telegram/types.ts +12 -0
- package/src/channels/types.ts +7 -0
- package/src/config/skillRefs.ts +6 -0
- package/src/daemon/AgentDaemon.ts +60 -12
- package/src/pi/PiAgentRunner.ts +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.1.24 - 2026-05-19
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added Telegram working status UX with `sendChatAction` typing heartbeats and an editable `Working…` message while agent runs execute.
|
|
10
|
+
|
|
11
|
+
## 0.1.23 - 2026-05-18
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Made `task-management` a runtime default active skill so task tools are available even when existing user configs do not list the skill.
|
|
16
|
+
|
|
3
17
|
## 0.1.22 - 2026-05-18
|
|
4
18
|
|
|
5
19
|
### Added
|
package/TODO.md
CHANGED
|
@@ -90,6 +90,8 @@
|
|
|
90
90
|
- [ ] Implement `TelegramApi`
|
|
91
91
|
- [x] `getUpdates`
|
|
92
92
|
- [x] `sendMessage`
|
|
93
|
+
- [x] `editMessageText`
|
|
94
|
+
- [x] `sendChatAction`
|
|
93
95
|
- [x] error handling
|
|
94
96
|
- [x] retry/backoff
|
|
95
97
|
- [x] `answerCallbackQuery`
|
|
@@ -100,6 +102,7 @@
|
|
|
100
102
|
- [x] offset tracking
|
|
101
103
|
- [x] graceful stop
|
|
102
104
|
- [x] update normalization
|
|
105
|
+
- [x] visible working status with typing indicator and editable status message
|
|
103
106
|
- [x] Persist Telegram offset in DB
|
|
104
107
|
|
|
105
108
|
## Routing
|
|
@@ -173,6 +176,7 @@
|
|
|
173
176
|
- [x] Add max task runs per hour rate limit
|
|
174
177
|
- [x] Add `/task status` or similar command
|
|
175
178
|
- [x] Add task management as agent skill + tools (natural language task CRUD)
|
|
179
|
+
- [x] Activate task-management by default for all sessions
|
|
176
180
|
- [x] Improve task-management prompt guidance for reminder/proactive-message refusal
|
|
177
181
|
|
|
178
182
|
## Policy And Safety
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { InboundMessage } from "../channels/types";
|
|
3
3
|
import type { LoadedAgentConfig } from "../config/schemas";
|
|
4
|
-
import { hasSkillRef, listBuiltInSkills, parseSessionSkills, skillDisplayName, uniqueSkillRefs } from "../config/skillRefs";
|
|
4
|
+
import { defaultActiveSkills, hasSkillRef, listBuiltInSkills, parseSessionSkills, skillDisplayName, uniqueSkillRefs } from "../config/skillRefs";
|
|
5
5
|
import type { Repositories } from "../db/repositories";
|
|
6
6
|
import type { AgentSessionRow } from "../db/schema";
|
|
7
7
|
import { logger } from "../logging/logger";
|
|
@@ -177,6 +177,7 @@ export class AgentRunner {
|
|
|
177
177
|
|
|
178
178
|
private hasSkill(agent: LoadedAgentConfig, session: AgentSessionRow, skillName: string): boolean {
|
|
179
179
|
const allSkills = [
|
|
180
|
+
...defaultActiveSkills(),
|
|
180
181
|
...(agent.profile ? (this.registry.getProfile(agent.profile)?.defaultSkills ?? []) : []),
|
|
181
182
|
...agent.skills,
|
|
182
183
|
...parseSessionSkills(session.sessionSkills),
|
|
@@ -218,11 +219,12 @@ export class AgentRunner {
|
|
|
218
219
|
if (!agent) return "";
|
|
219
220
|
|
|
220
221
|
const profile = this.registry.getProfile(agent.profile);
|
|
222
|
+
const defaultSkills = defaultActiveSkills();
|
|
221
223
|
const profileSkills = profile?.defaultSkills ?? [];
|
|
222
224
|
const agentSkills = agent.skills;
|
|
223
225
|
const sessionSkills = parseSessionSkills(session.sessionSkills);
|
|
224
226
|
const builtInSkills = listBuiltInSkills(import.meta.dir);
|
|
225
|
-
const activeSkills = uniqueSkillRefs([...profileSkills, ...agentSkills, ...sessionSkills]);
|
|
227
|
+
const activeSkills = uniqueSkillRefs([...defaultSkills, ...profileSkills, ...agentSkills, ...sessionSkills]);
|
|
226
228
|
const knownSkills = uniqueSkillRefs([...builtInSkills, ...activeSkills]).sort((a, b) =>
|
|
227
229
|
skillDisplayName(a).localeCompare(skillDisplayName(b)),
|
|
228
230
|
);
|
|
@@ -235,6 +237,7 @@ export class AgentRunner {
|
|
|
235
237
|
const active = hasSkillRef(activeSkills, name);
|
|
236
238
|
const sources = [];
|
|
237
239
|
|
|
240
|
+
if (hasSkillRef(defaultSkills, name)) sources.push("default");
|
|
238
241
|
if (hasSkillRef(profileSkills, name)) sources.push("profile");
|
|
239
242
|
if (hasSkillRef(agentSkills, name)) sources.push("agent");
|
|
240
243
|
if (hasSkillRef(sessionSkills, name)) sources.push("session");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { InboundMessage, InlineKeyboardButton } from "../channels/types";
|
|
3
3
|
import type { LoadedAgentConfig, LoadedProfileConfig, ModelChoiceConfig } from "../config/schemas";
|
|
4
|
-
import { hasSkillRef, listBuiltInSkills, parseSessionSkills, skillDisplayName, uniqueSkillRefs } from "../config/skillRefs";
|
|
4
|
+
import { defaultActiveSkills, hasSkillRef, listBuiltInSkills, parseSessionSkills, skillDisplayName, uniqueSkillRefs } from "../config/skillRefs";
|
|
5
5
|
import type { AgentSessionRow } from "../db/schema";
|
|
6
6
|
import type { Repositories } from "../db/repositories";
|
|
7
7
|
import { PiAgentRunner, type PiContextUsage } from "../pi/PiAgentRunner";
|
|
@@ -249,11 +249,12 @@ export class BotCommandHandler {
|
|
|
249
249
|
|
|
250
250
|
const agent = sessionResult.agent;
|
|
251
251
|
const profile = this.registry.getProfile(agent.profile);
|
|
252
|
+
const defaultSkills = defaultActiveSkills();
|
|
252
253
|
const profileSkills = profile?.defaultSkills ?? [];
|
|
253
254
|
const agentSkills = agent.skills;
|
|
254
255
|
const sessionSkills = parseSessionSkills(sessionResult.session.sessionSkills);
|
|
255
256
|
const builtInSkills = listBuiltInSkills(import.meta.dir);
|
|
256
|
-
const activeSkills = uniqueSkillRefs([...profileSkills, ...agentSkills, ...sessionSkills]);
|
|
257
|
+
const activeSkills = uniqueSkillRefs([...defaultSkills, ...profileSkills, ...agentSkills, ...sessionSkills]);
|
|
257
258
|
const knownSkills = uniqueSkillRefs([...builtInSkills, ...activeSkills]).sort((a, b) =>
|
|
258
259
|
skillDisplayName(a).localeCompare(skillDisplayName(b)),
|
|
259
260
|
);
|
|
@@ -265,7 +266,7 @@ export class BotCommandHandler {
|
|
|
265
266
|
"Session: " + sessionResult.session.id,
|
|
266
267
|
"",
|
|
267
268
|
"Available skills:",
|
|
268
|
-
...formatSkillRows(knownSkills, { profileSkills, agentSkills, sessionSkills, builtInSkills }),
|
|
269
|
+
...formatSkillRows(knownSkills, { defaultSkills, profileSkills, agentSkills, sessionSkills, builtInSkills }),
|
|
269
270
|
"",
|
|
270
271
|
"Legend: ✅ active, ⬜ available but inactive",
|
|
271
272
|
"Load on the fly: /skills add <skill>",
|
|
@@ -596,7 +597,7 @@ function formatDuration(ms: number): string {
|
|
|
596
597
|
|
|
597
598
|
function formatSkillRows(
|
|
598
599
|
skills: string[],
|
|
599
|
-
sources: { profileSkills: string[]; agentSkills: string[]; sessionSkills: string[]; builtInSkills: string[] },
|
|
600
|
+
sources: { defaultSkills: string[]; profileSkills: string[]; agentSkills: string[]; sessionSkills: string[]; builtInSkills: string[] },
|
|
600
601
|
): string[] {
|
|
601
602
|
if (skills.length === 0) return ["none"];
|
|
602
603
|
|
|
@@ -604,6 +605,7 @@ function formatSkillRows(
|
|
|
604
605
|
const name = skillDisplayName(skill);
|
|
605
606
|
const sourceLabels = [];
|
|
606
607
|
|
|
608
|
+
if (hasSkillRef(sources.defaultSkills, name)) sourceLabels.push("default");
|
|
607
609
|
if (hasSkillRef(sources.profileSkills, name)) sourceLabels.push("profile");
|
|
608
610
|
if (hasSkillRef(sources.agentSkills, name)) sourceLabels.push("agent");
|
|
609
611
|
if (hasSkillRef(sources.sessionSkills, name)) sourceLabels.push("session");
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
TelegramAnswerCallbackQueryResponse,
|
|
3
|
+
TelegramEditMessageTextResponse,
|
|
3
4
|
TelegramGetMeResponse,
|
|
4
5
|
TelegramGetUpdatesResponse,
|
|
6
|
+
TelegramSendChatActionResponse,
|
|
5
7
|
TelegramSendMessageResponse,
|
|
6
8
|
TelegramSetMyCommandsResponse,
|
|
7
9
|
TelegramUpdate,
|
|
@@ -68,14 +70,39 @@ export class TelegramApi {
|
|
|
68
70
|
text: string;
|
|
69
71
|
threadId?: string | null;
|
|
70
72
|
inlineKeyboard?: InlineKeyboardButton[][];
|
|
71
|
-
}): Promise<
|
|
72
|
-
await this.request<TelegramSendMessageResponse>("sendMessage", {
|
|
73
|
+
}): Promise<number | null> {
|
|
74
|
+
const response = await this.request<TelegramSendMessageResponse>("sendMessage", {
|
|
73
75
|
chat_id: input.chatId,
|
|
74
76
|
text: input.text,
|
|
75
77
|
message_thread_id: input.threadId ? Number(input.threadId) : undefined,
|
|
76
78
|
disable_web_page_preview: true,
|
|
77
79
|
reply_markup: input.inlineKeyboard ? toTelegramInlineKeyboard(input.inlineKeyboard) : undefined,
|
|
78
80
|
});
|
|
81
|
+
|
|
82
|
+
return response.result?.message_id ?? null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async editMessageText(input: {
|
|
86
|
+
chatId: string;
|
|
87
|
+
messageId: number;
|
|
88
|
+
text: string;
|
|
89
|
+
inlineKeyboard?: InlineKeyboardButton[][];
|
|
90
|
+
}): Promise<void> {
|
|
91
|
+
await this.request<TelegramEditMessageTextResponse>("editMessageText", {
|
|
92
|
+
chat_id: input.chatId,
|
|
93
|
+
message_id: input.messageId,
|
|
94
|
+
text: input.text,
|
|
95
|
+
disable_web_page_preview: true,
|
|
96
|
+
reply_markup: input.inlineKeyboard ? toTelegramInlineKeyboard(input.inlineKeyboard) : undefined,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async sendChatAction(input: { chatId: string; action: "typing"; threadId?: string | null }): Promise<void> {
|
|
101
|
+
await this.request<TelegramSendChatActionResponse>("sendChatAction", {
|
|
102
|
+
chat_id: input.chatId,
|
|
103
|
+
action: input.action,
|
|
104
|
+
message_thread_id: input.threadId ? Number(input.threadId) : undefined,
|
|
105
|
+
});
|
|
79
106
|
}
|
|
80
107
|
|
|
81
108
|
async answerCallbackQuery(input: { callbackQueryId: string; text?: string }): Promise<void> {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RuntimeKvRepository } from "../../db/repositories/RuntimeKvRepository";
|
|
2
2
|
import { logger } from "../../logging/logger";
|
|
3
|
-
import type { ChannelAdapter, InboundMessage, MessageHandler, OutboundMessage } from "../types";
|
|
3
|
+
import type { ChannelAdapter, InboundMessage, MessageHandler, OutboundMessage, RunStatusHandle } from "../types";
|
|
4
4
|
import { TelegramApi, type TelegramBotCommand } from "./TelegramApi";
|
|
5
5
|
import type { TelegramCallbackQuery, TelegramMessage, TelegramUpdate } from "./types";
|
|
6
6
|
|
|
@@ -63,6 +63,14 @@ export class TelegramPollingAdapter implements ChannelAdapter {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
createRunStatus(message: OutboundMessage): RunStatusHandle {
|
|
67
|
+
if (message.channel !== "telegram") {
|
|
68
|
+
throw new Error(`unsupported channel for telegram adapter: ${message.channel}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return new TelegramRunStatusHandle(this.options.api, message);
|
|
72
|
+
}
|
|
73
|
+
|
|
66
74
|
private async poll(handler: MessageHandler): Promise<void> {
|
|
67
75
|
while (this.running) {
|
|
68
76
|
try {
|
|
@@ -161,6 +169,84 @@ function normalizeTelegramCallbackQuery(updateId: number, callbackQuery: Telegra
|
|
|
161
169
|
};
|
|
162
170
|
}
|
|
163
171
|
|
|
172
|
+
class TelegramRunStatusHandle implements RunStatusHandle {
|
|
173
|
+
private messageId: number | null = null;
|
|
174
|
+
private typingTimer: ReturnType<typeof setInterval> | null = null;
|
|
175
|
+
|
|
176
|
+
constructor(
|
|
177
|
+
private readonly api: TelegramApi,
|
|
178
|
+
private readonly message: OutboundMessage,
|
|
179
|
+
) {}
|
|
180
|
+
|
|
181
|
+
async start(): Promise<void> {
|
|
182
|
+
await this.sendTyping();
|
|
183
|
+
this.messageId = await this.api.sendMessage({
|
|
184
|
+
chatId: this.message.chatId,
|
|
185
|
+
threadId: this.message.threadId,
|
|
186
|
+
text: this.message.text,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
this.typingTimer = setInterval(() => {
|
|
190
|
+
void this.sendTyping();
|
|
191
|
+
}, 4000);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async complete(message: OutboundMessage): Promise<void> {
|
|
195
|
+
await this.stopAndPublish(message);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async fail(message: OutboundMessage): Promise<void> {
|
|
199
|
+
await this.stopAndPublish(message);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private async stopAndPublish(message: OutboundMessage): Promise<void> {
|
|
203
|
+
this.stopTyping();
|
|
204
|
+
|
|
205
|
+
if (this.messageId) {
|
|
206
|
+
try {
|
|
207
|
+
await this.api.editMessageText({
|
|
208
|
+
chatId: message.chatId,
|
|
209
|
+
messageId: this.messageId,
|
|
210
|
+
text: message.text,
|
|
211
|
+
inlineKeyboard: message.inlineKeyboard,
|
|
212
|
+
});
|
|
213
|
+
return;
|
|
214
|
+
} catch (error) {
|
|
215
|
+
logger.warn("telegram status edit failed; sending final message", {
|
|
216
|
+
error: error instanceof Error ? error.message : String(error),
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
await this.api.sendMessage({
|
|
222
|
+
chatId: message.chatId,
|
|
223
|
+
threadId: message.threadId,
|
|
224
|
+
text: message.text,
|
|
225
|
+
inlineKeyboard: message.inlineKeyboard,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private async sendTyping(): Promise<void> {
|
|
230
|
+
try {
|
|
231
|
+
await this.api.sendChatAction({
|
|
232
|
+
chatId: this.message.chatId,
|
|
233
|
+
threadId: this.message.threadId,
|
|
234
|
+
action: "typing",
|
|
235
|
+
});
|
|
236
|
+
} catch (error) {
|
|
237
|
+
logger.debug("telegram typing indicator failed", {
|
|
238
|
+
error: error instanceof Error ? error.message : String(error),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private stopTyping(): void {
|
|
244
|
+
if (!this.typingTimer) return;
|
|
245
|
+
clearInterval(this.typingTimer);
|
|
246
|
+
this.typingTimer = null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
164
250
|
function sleep(ms: number): Promise<void> {
|
|
165
251
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
166
252
|
}
|
|
@@ -63,6 +63,18 @@ export type TelegramAnswerCallbackQueryResponse = {
|
|
|
63
63
|
description?: string;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
+
export type TelegramEditMessageTextResponse = {
|
|
67
|
+
ok: boolean;
|
|
68
|
+
result?: TelegramMessage | boolean;
|
|
69
|
+
description?: string;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type TelegramSendChatActionResponse = {
|
|
73
|
+
ok: boolean;
|
|
74
|
+
result: boolean;
|
|
75
|
+
description?: string;
|
|
76
|
+
};
|
|
77
|
+
|
|
66
78
|
export type TelegramSetMyCommandsResponse = {
|
|
67
79
|
ok: boolean;
|
|
68
80
|
result: boolean;
|
package/src/channels/types.ts
CHANGED
|
@@ -30,9 +30,16 @@ export type OutboundMessage = {
|
|
|
30
30
|
|
|
31
31
|
export type MessageHandler = (message: InboundMessage) => Promise<void>;
|
|
32
32
|
|
|
33
|
+
export interface RunStatusHandle {
|
|
34
|
+
start(): Promise<void>;
|
|
35
|
+
complete(message: OutboundMessage): Promise<void>;
|
|
36
|
+
fail(message: OutboundMessage): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
|
|
33
39
|
export interface ChannelAdapter {
|
|
34
40
|
readonly id: ChannelId;
|
|
35
41
|
start(handler: MessageHandler): Promise<void>;
|
|
36
42
|
stop(): Promise<void>;
|
|
37
43
|
send(message: OutboundMessage): Promise<void>;
|
|
44
|
+
createRunStatus?(message: OutboundMessage): RunStatusHandle;
|
|
38
45
|
}
|
package/src/config/skillRefs.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
|
|
4
|
+
export const DEFAULT_ACTIVE_SKILLS = ["task-management"] as const;
|
|
5
|
+
|
|
6
|
+
export function defaultActiveSkills(): string[] {
|
|
7
|
+
return [...DEFAULT_ACTIVE_SKILLS];
|
|
8
|
+
}
|
|
9
|
+
|
|
4
10
|
export function parseSessionSkills(raw: string | null | undefined): string[] {
|
|
5
11
|
if (!raw) return [];
|
|
6
12
|
|
|
@@ -117,18 +117,54 @@ export class AgentDaemon {
|
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
const
|
|
121
|
-
agentId: route.agentId,
|
|
122
|
-
text: route.text,
|
|
123
|
-
message,
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
await this.send({
|
|
120
|
+
const status = this.createRunStatus({
|
|
127
121
|
channel: message.channel,
|
|
128
122
|
chatId: message.chatId,
|
|
129
123
|
threadId: message.threadId,
|
|
130
|
-
text:
|
|
124
|
+
text: "Working…",
|
|
131
125
|
});
|
|
126
|
+
|
|
127
|
+
await status?.start();
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
const response = await this.runner.run({
|
|
131
|
+
agentId: route.agentId,
|
|
132
|
+
text: route.text,
|
|
133
|
+
message,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const outbound = {
|
|
137
|
+
channel: message.channel,
|
|
138
|
+
chatId: message.chatId,
|
|
139
|
+
threadId: message.threadId,
|
|
140
|
+
text: response,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
if (status) {
|
|
144
|
+
await status.complete(outbound);
|
|
145
|
+
} else {
|
|
146
|
+
await this.send(outbound);
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
const failure = {
|
|
150
|
+
channel: message.channel,
|
|
151
|
+
chatId: message.chatId,
|
|
152
|
+
threadId: message.threadId,
|
|
153
|
+
text: "Agent failed to respond. Please try again later.",
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
if (status) {
|
|
157
|
+
await status.fail(failure);
|
|
158
|
+
} else {
|
|
159
|
+
await this.send(failure);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
logger.error("agent run failed", {
|
|
163
|
+
channel: message.channel,
|
|
164
|
+
chatId: message.chatId,
|
|
165
|
+
error: error instanceof Error ? error.message : String(error),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
132
168
|
}
|
|
133
169
|
|
|
134
170
|
private async autoConfigureChat(message: InboundMessage): Promise<void> {
|
|
@@ -142,13 +178,25 @@ export class AgentDaemon {
|
|
|
142
178
|
}
|
|
143
179
|
|
|
144
180
|
private async send(message: OutboundMessage): Promise<void> {
|
|
145
|
-
const adapter = this.
|
|
181
|
+
const adapter = this.findAdapter(message.channel);
|
|
182
|
+
if (!adapter) return;
|
|
183
|
+
|
|
184
|
+
await adapter.send(message);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private createRunStatus(message: OutboundMessage) {
|
|
188
|
+
const adapter = this.findAdapter(message.channel);
|
|
189
|
+
return adapter?.createRunStatus?.(message) ?? null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private findAdapter(channel: OutboundMessage["channel"]): ChannelAdapter | null {
|
|
193
|
+
const adapter = this.adapters.find((candidate) => candidate.id === channel);
|
|
146
194
|
if (!adapter) {
|
|
147
|
-
logger.warn("no adapter available for outbound message", { channel
|
|
148
|
-
return;
|
|
195
|
+
logger.warn("no adapter available for outbound message", { channel });
|
|
196
|
+
return null;
|
|
149
197
|
}
|
|
150
198
|
|
|
151
|
-
|
|
199
|
+
return adapter;
|
|
152
200
|
}
|
|
153
201
|
}
|
|
154
202
|
|
package/src/pi/PiAgentRunner.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { mkdir } from "node:fs/promises";
|
|
11
11
|
import { resolve } from "node:path";
|
|
12
12
|
import type { LoadedAgentConfig, LoadedProfileConfig } from "../config/schemas";
|
|
13
|
-
import { parseSessionSkills } from "../config/skillRefs";
|
|
13
|
+
import { defaultActiveSkills, parseSessionSkills } from "../config/skillRefs";
|
|
14
14
|
import type { AgentSessionRow } from "../db/schema";
|
|
15
15
|
import { resolveModelSelection } from "./PiModelResolver";
|
|
16
16
|
import { loadOrCreatePiSession } from "./PiSessionFactory";
|
|
@@ -118,6 +118,10 @@ export class PiAgentRunner {
|
|
|
118
118
|
function resolveSkillPaths(agent: LoadedAgentConfig, profile: LoadedProfileConfig | null, session: AgentSessionRow): string[] {
|
|
119
119
|
const paths: string[] = [];
|
|
120
120
|
|
|
121
|
+
for (const s of defaultActiveSkills()) {
|
|
122
|
+
paths.push(resolveSkillPath(s, agent.baseDir));
|
|
123
|
+
}
|
|
124
|
+
|
|
121
125
|
if (profile) {
|
|
122
126
|
for (const s of profile.defaultSkills) {
|
|
123
127
|
paths.push(resolveSkillPath(s, profile.baseDir));
|