@hahnfeld/teams-adapter 1.0.9
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/LICENSE +21 -0
- package/README.md +286 -0
- package/dist/activity.d.ts +23 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +3 -0
- package/dist/activity.js.map +1 -0
- package/dist/adapter.d.ts +174 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +1583 -0
- package/dist/adapter.js.map +1 -0
- package/dist/app-package.d.ts +7 -0
- package/dist/app-package.d.ts.map +1 -0
- package/dist/app-package.js +158 -0
- package/dist/app-package.js.map +1 -0
- package/dist/assistant.d.ts +7 -0
- package/dist/assistant.d.ts.map +1 -0
- package/dist/assistant.js +32 -0
- package/dist/assistant.js.map +1 -0
- package/dist/commands/admin.d.ts +27 -0
- package/dist/commands/admin.d.ts.map +1 -0
- package/dist/commands/admin.js +146 -0
- package/dist/commands/admin.js.map +1 -0
- package/dist/commands/agents.d.ts +13 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +98 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +49 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/index.d.ts +16 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +253 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/integrate.d.ts +8 -0
- package/dist/commands/integrate.d.ts.map +1 -0
- package/dist/commands/integrate.js +45 -0
- package/dist/commands/integrate.js.map +1 -0
- package/dist/commands/menu.d.ts +16 -0
- package/dist/commands/menu.d.ts.map +1 -0
- package/dist/commands/menu.js +92 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/commands/new-session.d.ts +13 -0
- package/dist/commands/new-session.d.ts.map +1 -0
- package/dist/commands/new-session.js +105 -0
- package/dist/commands/new-session.js.map +1 -0
- package/dist/commands/session.d.ts +22 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +110 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/settings.d.ts +8 -0
- package/dist/commands/settings.d.ts.map +1 -0
- package/dist/commands/settings.js +54 -0
- package/dist/commands/settings.js.map +1 -0
- package/dist/conversation-store.d.ts +38 -0
- package/dist/conversation-store.d.ts.map +1 -0
- package/dist/conversation-store.js +101 -0
- package/dist/conversation-store.js.map +1 -0
- package/dist/draft-manager.d.ts +47 -0
- package/dist/draft-manager.d.ts.map +1 -0
- package/dist/draft-manager.js +136 -0
- package/dist/draft-manager.js.map +1 -0
- package/dist/formatting.d.ts +121 -0
- package/dist/formatting.d.ts.map +1 -0
- package/dist/formatting.js +392 -0
- package/dist/formatting.js.map +1 -0
- package/dist/graph.d.ts +59 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +261 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/media.d.ts +29 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +120 -0
- package/dist/media.js.map +1 -0
- package/dist/permissions.d.ts +15 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +221 -0
- package/dist/permissions.js.map +1 -0
- package/dist/plugin.d.ts +13 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +689 -0
- package/dist/plugin.js.map +1 -0
- package/dist/renderer.d.ts +49 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +55 -0
- package/dist/renderer.js.map +1 -0
- package/dist/send-utils.d.ts +15 -0
- package/dist/send-utils.d.ts.map +1 -0
- package/dist/send-utils.js +64 -0
- package/dist/send-utils.js.map +1 -0
- package/dist/task-modules.d.ts +34 -0
- package/dist/task-modules.d.ts.map +1 -0
- package/dist/task-modules.js +136 -0
- package/dist/task-modules.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/validators.d.ts +54 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +142 -0
- package/dist/validators.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CommandContext } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Handle /new [agent] [workspace] — create a new agent session.
|
|
4
|
+
* Mirrors Telegram's createSessionDirect pattern.
|
|
5
|
+
*/
|
|
6
|
+
export declare function handleNew(ctx: CommandContext, args: string[]): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Handle /newchat — start a new chat with the same agent and workspace
|
|
9
|
+
* as the current session. Mirrors Telegram's "same context, fresh start" pattern.
|
|
10
|
+
*/
|
|
11
|
+
export declare function handleNewChat(ctx: CommandContext): Promise<void>;
|
|
12
|
+
export declare function executeNewSession(ctx: CommandContext, agentName?: string, workspace?: string): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=new-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-session.d.ts","sourceRoot":"","sources":["../../src/commands/new-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6DlF;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCtE;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,cAAc,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { log } from "@openacp/plugin-sdk";
|
|
2
|
+
import { sendCard } from "../send-utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* Handle /new [agent] [workspace] — create a new agent session.
|
|
5
|
+
* Mirrors Telegram's createSessionDirect pattern.
|
|
6
|
+
*/
|
|
7
|
+
export async function handleNew(ctx, args) {
|
|
8
|
+
const agentName = args[0];
|
|
9
|
+
const workspace = args[1];
|
|
10
|
+
if (!agentName) {
|
|
11
|
+
// Send the session wizard inline as an Adaptive Card.
|
|
12
|
+
// Task modules (task/fetch popups) don't work reliably for sideloaded apps,
|
|
13
|
+
// so we render the wizard directly in the chat.
|
|
14
|
+
const agents = ctx.adapter.core.agentManager.getAvailableAgents();
|
|
15
|
+
const defaultWorkspace = ctx.adapter.core.configManager.resolveWorkspace?.() ?? process.cwd();
|
|
16
|
+
const agentChoices = agents.map((a) => ({ title: a.name, value: a.name }));
|
|
17
|
+
if (agentChoices.length === 0) {
|
|
18
|
+
agentChoices.push({ title: "openacp", value: "openacp" });
|
|
19
|
+
}
|
|
20
|
+
const card = {
|
|
21
|
+
type: "AdaptiveCard",
|
|
22
|
+
version: "1.4",
|
|
23
|
+
body: [
|
|
24
|
+
{ type: "TextBlock", text: "**New Session**", weight: "Bolder", size: "Large" },
|
|
25
|
+
{ type: "TextBlock", text: "Select an agent and workspace to start a coding session.", wrap: true, isSubtle: true, spacing: "Small" },
|
|
26
|
+
{ type: "TextBlock", text: "Agent", weight: "Bolder", spacing: "Large" },
|
|
27
|
+
{ type: "Input.ChoiceSet", id: "agent", style: "compact", value: agentChoices[0].value, choices: agentChoices },
|
|
28
|
+
{ type: "TextBlock", text: "Workspace (project directory)", weight: "Bolder", spacing: "Large" },
|
|
29
|
+
{ type: "Input.Text", id: "workspace", placeholder: "/path/to/project", value: defaultWorkspace },
|
|
30
|
+
],
|
|
31
|
+
actions: [
|
|
32
|
+
{ type: "Action.Execute", title: "Create Session", verb: "dialog:new-session" },
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
await sendCard(ctx.context, card);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const workDir = workspace ?? ctx.adapter.core.configManager.resolveWorkspace?.() ?? process.cwd();
|
|
39
|
+
try {
|
|
40
|
+
await ctx.reply(`🔄 Creating session with **${agentName}**...`);
|
|
41
|
+
const conversationId = ctx.context.activity?.conversation?.id;
|
|
42
|
+
const session = await ctx.adapter.core.createSession({
|
|
43
|
+
channelId: "teams",
|
|
44
|
+
agentName,
|
|
45
|
+
workingDirectory: workDir,
|
|
46
|
+
threadId: conversationId,
|
|
47
|
+
createThread: !conversationId,
|
|
48
|
+
});
|
|
49
|
+
if (conversationId) {
|
|
50
|
+
session.threadIds.set("teams", conversationId);
|
|
51
|
+
}
|
|
52
|
+
ctx.adapter["_sessionContexts"].set(session.id, { context: ctx.context, isAssistant: false, threadId: conversationId });
|
|
53
|
+
await ctx.reply(`✅ Session created\n\n` +
|
|
54
|
+
`**Agent:** ${agentName}\n\n` +
|
|
55
|
+
`**Workspace:** \`${workDir}\`\n\n` +
|
|
56
|
+
`**Session:** ${session.id.slice(0, 8)}`);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
log.error({ err, agentName }, "[new-session] Failed to create session");
|
|
60
|
+
await ctx.reply(`❌ Failed to create session: ${err instanceof Error ? err.message : String(err)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Handle /newchat — start a new chat with the same agent and workspace
|
|
65
|
+
* as the current session. Mirrors Telegram's "same context, fresh start" pattern.
|
|
66
|
+
*/
|
|
67
|
+
export async function handleNewChat(ctx) {
|
|
68
|
+
if (!ctx.sessionId) {
|
|
69
|
+
await ctx.reply("❌ No active session. Use `/new <agent>` to create one.");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const session = ctx.adapter.core.sessionManager.getSession(ctx.sessionId);
|
|
73
|
+
if (!session) {
|
|
74
|
+
await ctx.reply("❌ Session not found.");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const agentName = session.agentName;
|
|
78
|
+
const workspace = session.workingDirectory;
|
|
79
|
+
try {
|
|
80
|
+
await ctx.reply(`🔄 Starting new chat with **${agentName}**...`);
|
|
81
|
+
const conversationId = ctx.context.activity?.conversation?.id;
|
|
82
|
+
const newSession = await ctx.adapter.core.createSession({
|
|
83
|
+
channelId: "teams",
|
|
84
|
+
agentName,
|
|
85
|
+
workingDirectory: workspace,
|
|
86
|
+
threadId: conversationId,
|
|
87
|
+
createThread: !conversationId,
|
|
88
|
+
});
|
|
89
|
+
if (conversationId) {
|
|
90
|
+
newSession.threadIds.set("teams", conversationId);
|
|
91
|
+
}
|
|
92
|
+
ctx.adapter["_sessionContexts"].set(newSession.id, { context: ctx.context, isAssistant: false, threadId: conversationId });
|
|
93
|
+
await ctx.reply(`✅ New chat started\n\n` +
|
|
94
|
+
`**Agent:** ${agentName}\n\n` +
|
|
95
|
+
`**Session:** ${newSession.id.slice(0, 8)}`);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
log.error({ err }, "[new-session] Failed to create new chat");
|
|
99
|
+
await ctx.reply(`❌ Failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export async function executeNewSession(ctx, agentName, workspace) {
|
|
103
|
+
await handleNew(ctx, [agentName ?? "", workspace ?? ""].filter(Boolean));
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=new-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-session.js","sourceRoot":"","sources":["../../src/commands/new-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CommandContext } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Handle /cancel — abort the current prompt in the active session.
|
|
4
|
+
* Mirrors Telegram's handleCancel pattern: abortPrompt, not destroy.
|
|
5
|
+
*/
|
|
6
|
+
export declare function handleCancel(ctx: CommandContext): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Handle /status — show session info or overall system stats.
|
|
9
|
+
* Mirrors Telegram's handleStatus with both session-level and global views.
|
|
10
|
+
*/
|
|
11
|
+
export declare function handleStatus(ctx: CommandContext): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Handle /sessions — list all sessions with status.
|
|
14
|
+
* Mirrors Telegram's handleTopics with status overview.
|
|
15
|
+
*/
|
|
16
|
+
export declare function handleSessions(ctx: CommandContext): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Handle /handoff — generate a terminal resume command for the current session.
|
|
19
|
+
*/
|
|
20
|
+
export declare function handleHandoff(ctx: CommandContext): Promise<void>;
|
|
21
|
+
export declare function executeCancelSession(ctx: CommandContext): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBrE;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCrE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBvE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAetE;AAED,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { log } from "@openacp/plugin-sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Handle /cancel — abort the current prompt in the active session.
|
|
4
|
+
* Mirrors Telegram's handleCancel pattern: abortPrompt, not destroy.
|
|
5
|
+
*/
|
|
6
|
+
export async function handleCancel(ctx) {
|
|
7
|
+
if (!ctx.sessionId) {
|
|
8
|
+
await ctx.reply("❌ No active session to cancel.");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const session = ctx.adapter.core.sessionManager.getSession(ctx.sessionId);
|
|
12
|
+
if (!session) {
|
|
13
|
+
await ctx.reply("❌ Session not found.");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
await session.abortPrompt();
|
|
18
|
+
await ctx.reply("⛔ Prompt aborted. Session is still active — send a new message to continue.");
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
log.error({ err, sessionId: ctx.sessionId }, "[session] abortPrompt failed");
|
|
22
|
+
// Fallback: destroy the session
|
|
23
|
+
try {
|
|
24
|
+
await session.destroy();
|
|
25
|
+
await ctx.reply("🚫 Session cancelled.");
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
await ctx.reply("❌ Failed to cancel session.");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Handle /status — show session info or overall system stats.
|
|
34
|
+
* Mirrors Telegram's handleStatus with both session-level and global views.
|
|
35
|
+
*/
|
|
36
|
+
export async function handleStatus(ctx) {
|
|
37
|
+
if (ctx.sessionId) {
|
|
38
|
+
const session = ctx.adapter.core.sessionManager.getSession(ctx.sessionId);
|
|
39
|
+
if (session) {
|
|
40
|
+
await ctx.reply(`**Session:** ${session.name || session.id.slice(0, 8)}\n\n` +
|
|
41
|
+
`**Agent:** ${session.agentName}\n\n` +
|
|
42
|
+
`**Status:** ${session.status}\n\n` +
|
|
43
|
+
`**Workspace:** \`${session.workingDirectory}\`\n\n` +
|
|
44
|
+
`**Queue:** ${session.queueDepth} pending`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Fallback to stored record
|
|
48
|
+
const record = ctx.adapter.core.sessionManager.getSessionRecord(ctx.sessionId);
|
|
49
|
+
if (record) {
|
|
50
|
+
await ctx.reply(`**Session:** ${record.name || record.sessionId.slice(0, 8)}\n\n` +
|
|
51
|
+
`**Agent:** ${record.agentName}\n\n` +
|
|
52
|
+
`**Status:** ${record.status} (not loaded)\n\n` +
|
|
53
|
+
`**Workspace:** \`${record.workingDir}\``);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Global status
|
|
58
|
+
const allRecords = ctx.adapter.core.sessionManager.listRecords();
|
|
59
|
+
const active = allRecords.filter((r) => r.status === "active" || r.status === "initializing");
|
|
60
|
+
const errors = allRecords.filter((r) => r.status === "error");
|
|
61
|
+
await ctx.reply(`**OpenACP Status**\n\n` +
|
|
62
|
+
`Active sessions: ${active.length}\n\n` +
|
|
63
|
+
`Error sessions: ${errors.length}\n\n` +
|
|
64
|
+
`Total sessions: ${allRecords.length}`);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Handle /sessions — list all sessions with status.
|
|
68
|
+
* Mirrors Telegram's handleTopics with status overview.
|
|
69
|
+
*/
|
|
70
|
+
export async function handleSessions(ctx) {
|
|
71
|
+
const allRecords = ctx.adapter.core.sessionManager.listRecords();
|
|
72
|
+
if (allRecords.length === 0) {
|
|
73
|
+
await ctx.reply("No sessions found. Use `/new <agent>` to create one.");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const statusEmoji = {
|
|
77
|
+
active: "🟢", initializing: "🟡", finished: "✅", error: "❌", cancelled: "⛔",
|
|
78
|
+
};
|
|
79
|
+
// Sort: active first
|
|
80
|
+
const statusOrder = { active: 0, initializing: 1, error: 2, finished: 3, cancelled: 4 };
|
|
81
|
+
allRecords.sort((a, b) => (statusOrder[a.status] ?? 5) - (statusOrder[b.status] ?? 5));
|
|
82
|
+
const lines = allRecords.slice(0, 20).map((r) => {
|
|
83
|
+
const emoji = statusEmoji[r.status] || "⚪";
|
|
84
|
+
const name = r.name?.trim() || `${r.agentName} session`;
|
|
85
|
+
return `${emoji} **${name}** — ${r.status}`;
|
|
86
|
+
});
|
|
87
|
+
const truncated = allRecords.length > 20 ? `\n\n...and ${allRecords.length - 20} more` : "";
|
|
88
|
+
await ctx.reply(`**Sessions: ${allRecords.length}**\n\n${lines.join("\n\n")}${truncated}`);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Handle /handoff — generate a terminal resume command for the current session.
|
|
92
|
+
*/
|
|
93
|
+
export async function handleHandoff(ctx) {
|
|
94
|
+
if (!ctx.sessionId) {
|
|
95
|
+
await ctx.reply("❌ No active session.");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const session = ctx.adapter.core.sessionManager.getSession(ctx.sessionId);
|
|
99
|
+
if (!session) {
|
|
100
|
+
await ctx.reply("❌ Session not found.");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
await ctx.reply(`**Handoff to terminal:**\n\n` +
|
|
104
|
+
`\`openacp adopt ${ctx.sessionId}\`\n\n` +
|
|
105
|
+
`Run this command in a terminal to take over this session.`);
|
|
106
|
+
}
|
|
107
|
+
export async function executeCancelSession(ctx) {
|
|
108
|
+
await handleCancel(ctx);
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAmB;IACpD,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,GAAG,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1E,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,GAAG,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;QAC5B,MAAM,GAAG,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjG,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,EAAE,8BAA8B,CAAC,CAAC;QAC7E,gCAAgC;QAChC,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YACxB,MAAM,GAAG,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAmB;IACpD,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1E,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,GAAG,CAAC,KAAK,CACb,gBAAgB,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM;gBAC5D,cAAc,OAAO,CAAC,SAAS,MAAM;gBACrC,eAAe,OAAO,CAAC,MAAM,MAAM;gBACnC,oBAAoB,OAAO,CAAC,gBAAgB,QAAQ;gBACpD,cAAc,OAAO,CAAC,UAAU,UAAU,CAC3C,CAAC;YACF,OAAO;QACT,CAAC;QAED,4BAA4B;QAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/E,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,GAAG,CAAC,KAAK,CACb,gBAAgB,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM;gBACjE,cAAc,MAAM,CAAC,SAAS,MAAM;gBACpC,eAAe,MAAM,CAAC,MAAM,mBAAmB;gBAC/C,oBAAoB,MAAM,CAAC,UAAU,IAAI,CAC1C,CAAC;YACF,OAAO;QACT,CAAC;IACH,CAAC;IAED,gBAAgB;IAChB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC;IACjE,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,cAAc,CAAC,CAAC;IAC9F,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;IAE9D,MAAM,GAAG,CAAC,KAAK,CACb,wBAAwB;QACxB,oBAAoB,MAAM,CAAC,MAAM,MAAM;QACvC,mBAAmB,MAAM,CAAC,MAAM,MAAM;QACtC,mBAAmB,UAAU,CAAC,MAAM,EAAE,CACvC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAmB;IACtD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC;IAEjE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,GAAG,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAA2B;QAC1C,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG;KAC5E,CAAC;IAEF,qBAAqB;IACrB,MAAM,WAAW,GAA2B,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAChH,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEvF,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC9C,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;QAC3C,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,SAAS,UAAU,CAAC;QACxD,OAAO,GAAG,KAAK,MAAM,IAAI,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,cAAc,UAAU,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAE5F,MAAM,GAAG,CAAC,KAAK,CAAC,eAAe,UAAU,CAAC,MAAM,SAAS,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC;AAC7F,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAmB;IACrD,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,GAAG,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1E,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,GAAG,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IACD,MAAM,GAAG,CAAC,KAAK,CACb,8BAA8B;QAC9B,mBAAmB,GAAG,CAAC,SAAS,QAAQ;QACxC,2DAA2D,CAC5D,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAmB;IAC5D,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CommandContext } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Handle /settings — show current configuration.
|
|
4
|
+
* Delegates to core settings command if available, otherwise shows adapter config.
|
|
5
|
+
*/
|
|
6
|
+
export declare function handleSettings(ctx: CommandContext): Promise<void>;
|
|
7
|
+
export declare function handleSettingsButton(ctx: CommandContext): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/commands/settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDvE;AAED,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handle /settings — show current configuration.
|
|
3
|
+
* Delegates to core settings command if available, otherwise shows adapter config.
|
|
4
|
+
*/
|
|
5
|
+
export async function handleSettings(ctx) {
|
|
6
|
+
const registry = ctx.adapter.core.lifecycleManager?.serviceRegistry?.get("command-registry");
|
|
7
|
+
if (registry) {
|
|
8
|
+
const def = registry.get("settings");
|
|
9
|
+
if (def) {
|
|
10
|
+
try {
|
|
11
|
+
const response = await registry.execute("/settings", {
|
|
12
|
+
raw: "",
|
|
13
|
+
sessionId: ctx.sessionId,
|
|
14
|
+
channelId: "teams",
|
|
15
|
+
userId: ctx.userId,
|
|
16
|
+
reply: async (content) => { await ctx.reply(content); },
|
|
17
|
+
});
|
|
18
|
+
if (response.type === "text") {
|
|
19
|
+
await ctx.reply(response.text);
|
|
20
|
+
}
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
catch { /* fall through */ }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Show adapter-level config
|
|
27
|
+
const config = ctx.adapter.core.configManager.get();
|
|
28
|
+
const defaultAgent = config.defaultAgent ?? "not set";
|
|
29
|
+
const workspace = ctx.adapter.core.configManager.resolveWorkspace?.() ?? "not set";
|
|
30
|
+
let sessionInfo = "";
|
|
31
|
+
if (ctx.sessionId) {
|
|
32
|
+
const session = ctx.adapter.core.sessionManager.getSession(ctx.sessionId);
|
|
33
|
+
if (session) {
|
|
34
|
+
sessionInfo = `\n\n---\n\n**Session Settings:**\n\n` +
|
|
35
|
+
`- Agent: ${session.agentName}\n\n` +
|
|
36
|
+
`- Mode: ${session.getConfigByCategory?.("mode")?.currentValue ?? "default"}\n\n` +
|
|
37
|
+
`- Model: ${session.getConfigByCategory?.("model")?.currentValue ?? "default"}\n\n` +
|
|
38
|
+
`- Bypass: ${session.clientOverrides?.bypassPermissions ? "on" : "off"}\n\n` +
|
|
39
|
+
`- TTS: ${session.voiceMode ?? "off"}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
await ctx.reply(`**⚙️ Configuration**\n\n` +
|
|
43
|
+
`**Global:**\n\n` +
|
|
44
|
+
`- Default agent: ${defaultAgent}\n\n` +
|
|
45
|
+
`- Workspace: \`${workspace}\`\n\n` +
|
|
46
|
+
`- Teams channel: ${ctx.adapter.getChannelId() || "not set"}\n\n` +
|
|
47
|
+
`- Notification channel: ${ctx.adapter.getAssistantThreadId() ? "configured" : "not set"}\n\n` +
|
|
48
|
+
`- Graph API: ${ctx.adapter.getTeamId() ? "configured" : "not configured"}` +
|
|
49
|
+
sessionInfo);
|
|
50
|
+
}
|
|
51
|
+
export async function handleSettingsButton(ctx) {
|
|
52
|
+
await handleSettings(ctx);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/commands/settings.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAmB;IACtD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,eAAe,EAAE,GAAG,CAAkB,kBAAkB,CAAC,CAAC;IAC9G,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE;oBACnD,GAAG,EAAE,EAAE;oBACP,SAAS,EAAE,GAAG,CAAC,SAAS;oBACxB,SAAS,EAAE,OAAO;oBAClB,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,KAAK,EAAE,KAAK,EAAE,OAAe,EAAE,EAAE,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;iBAChE,CAAC,CAAC;gBACH,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC7B,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACjC,CAAC;gBACD,OAAO;YACT,CAAC;YAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,4BAA4B;IAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;IACpD,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,SAAS,CAAC;IACtD,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,EAAE,IAAI,SAAS,CAAC;IAEnF,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1E,IAAI,OAAO,EAAE,CAAC;YACZ,WAAW,GAAG,sCAAsC;gBAClD,YAAY,OAAO,CAAC,SAAS,MAAM;gBACnC,WAAW,OAAO,CAAC,mBAAmB,EAAE,CAAC,MAAM,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM;gBACjF,YAAY,OAAO,CAAC,mBAAmB,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM;gBACnF,aAAa,OAAO,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM;gBAC5E,UAAU,OAAO,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,MAAM,GAAG,CAAC,KAAK,CACb,0BAA0B;QAC1B,iBAAiB;QACjB,oBAAoB,YAAY,MAAM;QACtC,kBAAkB,SAAS,QAAQ;QACnC,oBAAoB,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,SAAS,MAAM;QACjE,2BAA2B,GAAG,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,MAAM;QAC9F,gBAAgB,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,EAAE;QAC3E,WAAW,CACZ,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAmB;IAC5D,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface StoredConversationReference {
|
|
2
|
+
/** The Teams conversation ID */
|
|
3
|
+
conversationId: string;
|
|
4
|
+
/** Service URL for the bot connector */
|
|
5
|
+
serviceUrl: string;
|
|
6
|
+
/** Tenant ID */
|
|
7
|
+
tenantId: string;
|
|
8
|
+
/** Channel ID (Teams channel within a team) */
|
|
9
|
+
channelId?: string;
|
|
10
|
+
/** The bot's own ID in this conversation */
|
|
11
|
+
botId: string;
|
|
12
|
+
/** The bot's name */
|
|
13
|
+
botName: string;
|
|
14
|
+
/** Timestamp of last update */
|
|
15
|
+
updatedAt: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class ConversationStore {
|
|
18
|
+
private references;
|
|
19
|
+
private filePath;
|
|
20
|
+
private dirty;
|
|
21
|
+
private saveTimer?;
|
|
22
|
+
constructor(storageDir: string);
|
|
23
|
+
/**
|
|
24
|
+
* Store a conversation reference from an inbound activity.
|
|
25
|
+
* Called on every inbound message to keep references fresh.
|
|
26
|
+
*/
|
|
27
|
+
upsert(ref: StoredConversationReference): void;
|
|
28
|
+
/** Get a stored reference by conversation ID */
|
|
29
|
+
get(conversationId: string): StoredConversationReference | undefined;
|
|
30
|
+
/** Get any stored reference (for proactive messaging when we don't know the conversation) */
|
|
31
|
+
getAny(): StoredConversationReference | undefined;
|
|
32
|
+
/** Get all stored references */
|
|
33
|
+
getAll(): StoredConversationReference[];
|
|
34
|
+
destroy(): void;
|
|
35
|
+
private load;
|
|
36
|
+
private persist;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=conversation-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-store.d.ts","sourceRoot":"","sources":["../src/conversation-store.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,2BAA2B;IAC1C,gCAAgC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAkD;IACpE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAC,CAAiC;gBAEvC,UAAU,EAAE,MAAM;IAW9B;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,2BAA2B,GAAG,IAAI;IAK9C,gDAAgD;IAChD,GAAG,CAAC,cAAc,EAAE,MAAM,GAAG,2BAA2B,GAAG,SAAS;IAIpE,6FAA6F;IAC7F,MAAM,IAAI,2BAA2B,GAAG,SAAS;IASjD,gCAAgC;IAChC,MAAM,IAAI,2BAA2B,EAAE;IAIvC,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,IAAI;IAkBZ,OAAO,CAAC,OAAO;CAahB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent conversation reference store for proactive messaging.
|
|
3
|
+
*
|
|
4
|
+
* Teams bots can only send proactive messages if they have a stored
|
|
5
|
+
* ConversationReference from a prior interaction. This store persists
|
|
6
|
+
* references across bot restarts.
|
|
7
|
+
*
|
|
8
|
+
* References are captured on every inbound message and stored by:
|
|
9
|
+
* - conversationId -> full reference (for replying to existing conversations)
|
|
10
|
+
* - "service" -> the serviceUrl + credentials needed for createConversation
|
|
11
|
+
*
|
|
12
|
+
* @see https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages
|
|
13
|
+
*/
|
|
14
|
+
import { log } from "@openacp/plugin-sdk";
|
|
15
|
+
import * as fs from "node:fs";
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
export class ConversationStore {
|
|
18
|
+
references = new Map();
|
|
19
|
+
filePath;
|
|
20
|
+
dirty = false;
|
|
21
|
+
saveTimer;
|
|
22
|
+
constructor(storageDir) {
|
|
23
|
+
this.filePath = path.join(storageDir, "conversation-refs.json");
|
|
24
|
+
this.load();
|
|
25
|
+
// Auto-save every 30 seconds if dirty
|
|
26
|
+
this.saveTimer = setInterval(() => {
|
|
27
|
+
if (this.dirty)
|
|
28
|
+
this.persist();
|
|
29
|
+
}, 30_000);
|
|
30
|
+
if (this.saveTimer.unref)
|
|
31
|
+
this.saveTimer.unref();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Store a conversation reference from an inbound activity.
|
|
35
|
+
* Called on every inbound message to keep references fresh.
|
|
36
|
+
*/
|
|
37
|
+
upsert(ref) {
|
|
38
|
+
this.references.set(ref.conversationId, { ...ref, updatedAt: Date.now() });
|
|
39
|
+
this.dirty = true;
|
|
40
|
+
}
|
|
41
|
+
/** Get a stored reference by conversation ID */
|
|
42
|
+
get(conversationId) {
|
|
43
|
+
return this.references.get(conversationId);
|
|
44
|
+
}
|
|
45
|
+
/** Get any stored reference (for proactive messaging when we don't know the conversation) */
|
|
46
|
+
getAny() {
|
|
47
|
+
// Return the most recently updated reference
|
|
48
|
+
let best;
|
|
49
|
+
for (const ref of this.references.values()) {
|
|
50
|
+
if (!best || ref.updatedAt > best.updatedAt)
|
|
51
|
+
best = ref;
|
|
52
|
+
}
|
|
53
|
+
return best;
|
|
54
|
+
}
|
|
55
|
+
/** Get all stored references */
|
|
56
|
+
getAll() {
|
|
57
|
+
return Array.from(this.references.values());
|
|
58
|
+
}
|
|
59
|
+
destroy() {
|
|
60
|
+
if (this.saveTimer) {
|
|
61
|
+
clearInterval(this.saveTimer);
|
|
62
|
+
this.saveTimer = undefined;
|
|
63
|
+
}
|
|
64
|
+
if (this.dirty)
|
|
65
|
+
this.persist();
|
|
66
|
+
}
|
|
67
|
+
load() {
|
|
68
|
+
try {
|
|
69
|
+
if (fs.existsSync(this.filePath)) {
|
|
70
|
+
const data = JSON.parse(fs.readFileSync(this.filePath, "utf-8"));
|
|
71
|
+
if (Array.isArray(data)) {
|
|
72
|
+
for (const ref of data) {
|
|
73
|
+
if (ref.conversationId) {
|
|
74
|
+
this.references.set(ref.conversationId, ref);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
log.info({ count: this.references.size }, "[ConversationStore] Loaded conversation references");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
log.warn({ err }, "[ConversationStore] Failed to load references");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
persist() {
|
|
86
|
+
try {
|
|
87
|
+
const dir = path.dirname(this.filePath);
|
|
88
|
+
if (!fs.existsSync(dir))
|
|
89
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
90
|
+
// Atomic write: write to temp file then rename (prevents corruption on crash)
|
|
91
|
+
const tmpPath = `${this.filePath}.tmp`;
|
|
92
|
+
fs.writeFileSync(tmpPath, JSON.stringify(Array.from(this.references.values()), null, 2), { mode: 0o600 });
|
|
93
|
+
fs.renameSync(tmpPath, this.filePath);
|
|
94
|
+
this.dirty = false;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
log.warn({ err }, "[ConversationStore] Failed to persist references");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=conversation-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-store.js","sourceRoot":"","sources":["../src/conversation-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { TurnContext } from "@microsoft/agents-hosting";
|
|
2
|
+
export interface MessageRef {
|
|
3
|
+
activityId?: string;
|
|
4
|
+
conversationId?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class TeamsMessageDraft {
|
|
7
|
+
private context;
|
|
8
|
+
private sendQueue;
|
|
9
|
+
private sessionId;
|
|
10
|
+
private buffer;
|
|
11
|
+
private ref?;
|
|
12
|
+
private flushTimer?;
|
|
13
|
+
private flushPromise;
|
|
14
|
+
private lastSentBuffer;
|
|
15
|
+
private displayTruncated;
|
|
16
|
+
private firstFlushPending;
|
|
17
|
+
private finalizing;
|
|
18
|
+
constructor(context: TurnContext, sendQueue: {
|
|
19
|
+
enqueue<T>(fn: () => Promise<T>, opts?: {
|
|
20
|
+
type?: string;
|
|
21
|
+
}): Promise<T | undefined>;
|
|
22
|
+
}, sessionId: string);
|
|
23
|
+
/** Update the TurnContext to the latest inbound turn (prevents stale context refs) */
|
|
24
|
+
updateContext(context: TurnContext): void;
|
|
25
|
+
append(text: string): void;
|
|
26
|
+
getBuffer(): string;
|
|
27
|
+
private scheduleFlush;
|
|
28
|
+
flush(): Promise<void>;
|
|
29
|
+
stripPattern(pattern: RegExp): Promise<void>;
|
|
30
|
+
finalize(): Promise<void>;
|
|
31
|
+
private _finalizeInner;
|
|
32
|
+
}
|
|
33
|
+
export declare class TeamsDraftManager {
|
|
34
|
+
private sendQueue;
|
|
35
|
+
private drafts;
|
|
36
|
+
constructor(sendQueue: {
|
|
37
|
+
enqueue<T>(fn: () => Promise<T>, opts?: {
|
|
38
|
+
type?: string;
|
|
39
|
+
}): Promise<T | undefined>;
|
|
40
|
+
});
|
|
41
|
+
getOrCreate(sessionId: string, context: TurnContext): TeamsMessageDraft;
|
|
42
|
+
hasDraft(sessionId: string): boolean;
|
|
43
|
+
getDraft(sessionId: string): TeamsMessageDraft | undefined;
|
|
44
|
+
finalize(sessionId: string, _context?: TurnContext, _isAssistant?: boolean): Promise<void>;
|
|
45
|
+
cleanup(sessionId: string): void;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=draft-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-manager.d.ts","sourceRoot":"","sources":["../src/draft-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAW7D,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,iBAAiB;IAW1B,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,SAAS;IAZnB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,GAAG,CAAC,CAAa;IACzB,OAAO,CAAC,UAAU,CAAC,CAAgC;IACnD,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,UAAU,CAAS;gBAGjB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE;QAAE,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;KAAE,EACjG,SAAS,EAAE,MAAM;IAG3B,sFAAsF;IACtF,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIzC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM1B,SAAS,IAAI,MAAM;IAInB,OAAO,CAAC,aAAa;IAUf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAUjB,cAAc;CAyB7B;AAED,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,SAAS;IAF7B,OAAO,CAAC,MAAM,CAAwC;gBAElC,SAAS,EAAE;QAAE,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;KAAE;IAErH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,iBAAiB;IAavE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIpC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAIpD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhG,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAGjC"}
|