@geminixiang/mikan 0.5.0 → 0.5.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/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { execFile } from \"child_process\";\nimport { promisify } from \"util\";\n\nconst execFileAsync = promisify(execFile);\ntype ExecFileAsync = typeof execFileAsync;\n\n// ── adapter ───────────────────────────────────────────────────────────────────\n\nexport type ConversationKind = \"direct\" | \"shared\";\n\nexport type PlatformName = \"slack\" | \"discord\" | \"telegram\";\n\nexport interface ConversationMessage {\n id: string;\n sessionKey: string;\n conversationKind: ConversationKind;\n userId: string;\n userName?: string;\n text: string;\n attachments?: { name: string; localPath: string }[];\n threadTs?: string;\n}\n\nexport interface ChatToolResult {\n toolName: string;\n label?: string;\n args?: Record<string, unknown>;\n result: string;\n isError: boolean;\n durationMs: number;\n}\n\nexport interface ChatResponseBlockKit {\n text: string;\n blocks: object[];\n}\n\nexport interface ConversationResponder {\n respond(text: string): Promise<void>;\n appendResponseDelta?(delta: string): Promise<void>;\n finishResponse?(finalText?: string): Promise<void>;\n replaceResponse(text: string, options?: { createOverflowLink?: () => string }): Promise<void>;\n respondDiagnostic(text: string, options?: { style?: \"muted\" | \"error\" }): Promise<void>;\n respondToolResult(result: ChatToolResult): Promise<void>;\n respondBlockKit?(response: ChatResponseBlockKit): Promise<void>;\n setTyping(isTyping: boolean): Promise<void>;\n setWorking(working: boolean): Promise<void>;\n uploadFile(filePath: string, title?: string): Promise<void>;\n deleteResponse(): Promise<void>;\n}\n\nexport interface MessagingInfo {\n name: string;\n formattingGuide: string;\n channels: { id: string; name: string }[];\n users: { id: string; userName: string; displayName: string }[];\n diagnostics?: {\n showUsageSummary?: boolean;\n };\n}\n\nexport interface ChatAdapter {\n start(): Promise<void>;\n stop(): Promise<void>;\n getMessagingInfo(): MessagingInfo;\n}\n\nexport type AgentEventPayload =\n | { kind: \"sessionStart\" }\n | { kind: \"toolStart\"; toolId: string; toolName: string; input?: unknown }\n | { kind: \"toolEnd\"; toolId: string }\n | { kind: \"turnEnd\"; awaitingInput?: boolean }\n | { kind: \"sessionEnd\"; reason?: string };\n\nexport interface AgentEventEnvelope {\n source: \"mikan\";\n sessionId: string;\n actorName: string;\n event: AgentEventPayload;\n}\n\n/**\n * A platform-agnostic event (message/mention) that triggers the agent.\n */\nexport interface ConversationEvent {\n type: string;\n /** Platform-specific raw conversation/channel/chat identifier */\n conversationId: string;\n /** Optional alternate conversation identity used for vault routing. */\n vaultConversationId?: string;\n /** Cross-platform conversation shape: direct message vs shared space */\n conversationKind: ConversationKind;\n /** Message timestamp or ID as string */\n ts: string;\n /** Parent message ID for threaded replies (optional) */\n thread_ts?: string;\n /** User ID */\n user: string;\n /** Message text (already stripped of bot mentions) */\n text: string;\n /** Downloaded attachments */\n attachments?: { name: string; localPath: string }[];\n /** Platform-computed session key; overrides default conversationId:thread_ts computation */\n sessionKey?: string;\n}\n\n/**\n * Minimum interface that every platform bot must implement,\n * used by the central handler in main.ts and by EventsWatcher.\n */\nexport interface MessagingBot {\n start(): Promise<void>;\n postMessage(channel: string, text: string): Promise<string>;\n updateMessage(channel: string, ts: string, text: string): Promise<void>;\n enqueueEvent(event: ConversationEvent): boolean;\n getMessagingInfo(): MessagingInfo;\n postPrivate?(conversationId: string, userId: string, text: string): Promise<void>;\n postPrivateDiagnostic?(\n conversationId: string,\n userId: string,\n text: string,\n options?: { style?: \"muted\" | \"error\" },\n ): Promise<void>;\n}\n\n/** Normalized platform data and reply hook for one event. */\nexport interface ConversationContext {\n message: ConversationMessage;\n responder: ConversationResponder;\n platform: MessagingInfo;\n}\n\nexport interface RunningSession {\n sessionKey: string;\n startedAt: number;\n lastActivityAt?: number;\n currentTool?: string;\n}\n\nexport interface MessagingEventHandler {\n isRunning(sessionKey: string): boolean;\n getRunningSessions(): RunningSession[];\n handleEvent(\n event: ConversationEvent,\n bot: MessagingBot,\n context: ConversationContext,\n ): Promise<void>;\n handleStop(sessionKey: string, conversationId: string, bot: MessagingBot): Promise<void>;\n forceStop(sessionKey: string): void;\n handleNewCommand(sessionKey: string, conversationId: string, bot: MessagingBot): Promise<void>;\n}\n\n// ── agent ─────────────────────────────────────────────────────────────────────\n\nexport interface PiAgentWrapper {\n syncChatHistory(currentMessageId?: string): void;\n run(\n message: ConversationMessage,\n responder: ConversationResponder,\n platform: MessagingInfo,\n ): Promise<{ stopReason: string; errorMessage?: string }>;\n abort(): void;\n getCurrentStep(): { toolName?: string; label?: string } | undefined;\n}\n\n// ── config ────────────────────────────────────────────────────────────────────\n\nexport interface AgentConfig {\n provider: string;\n model: string;\n thinkingLevel: ThinkingLevel;\n sentryDsn?: string;\n sandboxCpus?: string;\n sandboxMemory?: string;\n sandboxBoostCpus?: string;\n sandboxBoostMemory?: string;\n sandboxImageWorkspaceMount?: \"private\" | \"full\";\n defaultSharedVault?: string;\n slack?: {\n replyMode?: \"top-level\" | \"thread\";\n };\n}\n\nexport interface AutoReplyConfig {\n enabled: boolean;\n rules: string[];\n}\n\nexport interface JudgeModelConfig {\n provider: string;\n model: string;\n}\n\n// ── context ───────────────────────────────────────────────────────────────────\n\n/**\n * Platform conversation history entry from log.jsonl.\n */\nexport interface ConversationLogMessage {\n date?: string;\n ts?: string;\n threadTs?: string;\n user?: string;\n userName?: string;\n text?: string;\n isMessagingBot?: boolean;\n}\n\n// ── events ────────────────────────────────────────────────────────────────────\n\nexport interface ImmediateEvent {\n type: \"immediate\";\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n userId?: string;\n text: string;\n}\n\nexport interface OneShotEvent {\n type: \"one-shot\";\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n userId?: string;\n text: string;\n at: string;\n}\n\nexport interface PeriodicEvent {\n type: \"periodic\";\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n userId?: string;\n text: string;\n schedule: string;\n timezone: string;\n}\n\nexport type MikanEvent = ImmediateEvent | OneShotEvent | PeriodicEvent;\n\nexport interface PeriodicEventInfo {\n filename: string;\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n text: string;\n schedule: string;\n timezone: string;\n nextRun: string | null;\n}\n\n// ── execution-resolver ────────────────────────────────────────────────────────\n\nexport interface ActorContext {\n platform: string;\n userId: string;\n conversationId: string;\n}\n\nexport type ImageWorkspaceMountMode = \"private\" | \"full\";\n\n// ── log ───────────────────────────────────────────────────────────────────────\n\nexport interface LogContext {\n conversationId: string;\n userName?: string;\n conversationName?: string;\n sessionId?: string;\n}\n\n// ── portal-shell ──────────────────────────────────────────────────────────────\n\ntype PortalView = \"admin\" | \"session\" | \"vault\";\n\nexport interface PortalShellOptions {\n activeView: PortalView;\n pageTitle: string;\n identity?: {\n primary: string;\n secondary?: string;\n };\n conversationSwitcher?: {\n currentId: string;\n options?: Array<{ id: string; label: string; running?: boolean }>;\n };\n navLinks?: Partial<Record<PortalView, string>>;\n body: string;\n extraStyles?: string;\n inlineScript?: string;\n extraHead?: string;\n bodyAttributes?: Record<string, string>;\n}\n\n// ── provisioner ───────────────────────────────────────────────────────────────\n\nexport interface ContainerMount {\n source: string;\n target: string;\n}\n\nexport interface ResourceLimits {\n cpus?: string;\n memory?: string;\n}\n\nexport interface SandboxLimitStatus {\n limits?: ResourceLimits;\n boosted: boolean;\n}\n\nexport interface ProvisionOptions {\n containerName?: string;\n mounts?: ContainerMount[];\n conversationId?: string;\n}\n\nexport interface DockerContainerManagerOptions {\n limits?: ResourceLimits;\n boostLimits?: ResourceLimits;\n execFileImpl?: ExecFileAsync;\n}\n\n// ── store ─────────────────────────────────────────────────────────────────────\n\nexport interface Attachment {\n original: string;\n localPath: string;\n}\n\nexport interface LoggedMessage {\n date: string;\n ts: string;\n user: string;\n userName?: string;\n displayName?: string;\n text: string;\n attachments: Attachment[];\n isMessagingBot: boolean;\n threadTs?: string;\n}\n\nexport interface ChannelStoreConfig {\n workingDir: string;\n botToken: string;\n}\n\n// ── trigger ───────────────────────────────────────────────────────────────────\n\nexport type TriggerIntent = \"mention\" | \"direct\" | \"thread-continuation\" | \"auto-reply-candidate\";\n\nexport type TriggerResult = { trigger: true; reason: string } | { trigger: false; reason: string };\n\nexport type AutoReplyJudge = (input: {\n event: ConversationEvent;\n rules: string[];\n conversationDir: string;\n}) => Promise<boolean>;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { execFile } from \"child_process\";\nimport { promisify } from \"util\";\n\nconst execFileAsync = promisify(execFile);\ntype ExecFileAsync = typeof execFileAsync;\n\n// ── adapter ───────────────────────────────────────────────────────────────────\n\nexport type ConversationKind = \"direct\" | \"shared\";\n\nexport type PlatformName = \"slack\" | \"discord\" | \"telegram\";\n\nexport interface ConversationMessage {\n id: string;\n sessionKey: string;\n conversationKind: ConversationKind;\n userId: string;\n userName?: string;\n text: string;\n attachments?: { name: string; localPath: string }[];\n threadTs?: string;\n}\n\nexport interface ChatToolResult {\n toolName: string;\n label?: string;\n args?: Record<string, unknown>;\n result: string;\n isError: boolean;\n durationMs: number;\n}\n\nexport interface ConversationResponder {\n respond(text: string): Promise<void>;\n appendResponseDelta?(delta: string): Promise<void>;\n finishResponse?(finalText?: string): Promise<void>;\n replaceResponse(text: string, options?: { createOverflowLink?: () => string }): Promise<void>;\n respondDiagnostic(text: string, options?: { style?: \"muted\" | \"error\" }): Promise<void>;\n respondToolResult(result: ChatToolResult): Promise<void>;\n setTyping(isTyping: boolean): Promise<void>;\n setWorking(working: boolean): Promise<void>;\n uploadFile(filePath: string, title?: string): Promise<void>;\n deleteResponse(): Promise<void>;\n}\n\nexport interface MessagingInfo {\n name: string;\n formattingGuide: string;\n channels: { id: string; name: string }[];\n users: { id: string; userName: string; displayName: string }[];\n diagnostics?: {\n showUsageSummary?: boolean;\n };\n}\n\nexport interface ChatAdapter {\n start(): Promise<void>;\n stop(): Promise<void>;\n getMessagingInfo(): MessagingInfo;\n}\n\nexport type AgentEventPayload =\n | { kind: \"sessionStart\" }\n | { kind: \"toolStart\"; toolId: string; toolName: string; input?: unknown }\n | { kind: \"toolEnd\"; toolId: string }\n | { kind: \"turnEnd\"; awaitingInput?: boolean }\n | { kind: \"sessionEnd\"; reason?: string };\n\nexport interface AgentEventEnvelope {\n source: \"mikan\";\n sessionId: string;\n actorName: string;\n event: AgentEventPayload;\n}\n\n/**\n * A platform-agnostic event (message/mention) that triggers the agent.\n */\nexport interface ConversationEvent {\n type: string;\n /** Platform-specific raw conversation/channel/chat identifier */\n conversationId: string;\n /** Optional alternate conversation identity used for vault routing. */\n vaultConversationId?: string;\n /** Cross-platform conversation shape: direct message vs shared space */\n conversationKind: ConversationKind;\n /** Message timestamp or ID as string */\n ts: string;\n /** Parent message ID for threaded replies (optional) */\n thread_ts?: string;\n /** User ID */\n user: string;\n /** Message text (already stripped of bot mentions) */\n text: string;\n /** Downloaded attachments */\n attachments?: { name: string; localPath: string }[];\n /** Platform-computed session key; overrides default conversationId:thread_ts computation */\n sessionKey?: string;\n}\n\n/**\n * Minimum interface that every platform bot must implement,\n * used by the central handler in main.ts and by EventsWatcher.\n */\nexport interface MessagingBot {\n start(): Promise<void>;\n postMessage(channel: string, text: string): Promise<string>;\n updateMessage(channel: string, ts: string, text: string): Promise<void>;\n enqueueEvent(event: ConversationEvent): boolean;\n getMessagingInfo(): MessagingInfo;\n postPrivate?(conversationId: string, userId: string, text: string): Promise<void>;\n postPrivateDiagnostic?(\n conversationId: string,\n userId: string,\n text: string,\n options?: { style?: \"muted\" | \"error\" },\n ): Promise<void>;\n}\n\n/** Normalized platform data and reply hook for one event. */\nexport interface ConversationContext {\n message: ConversationMessage;\n responder: ConversationResponder;\n platform: MessagingInfo;\n}\n\nexport interface RunningSession {\n sessionKey: string;\n startedAt: number;\n lastActivityAt?: number;\n currentTool?: string;\n}\n\nexport interface MessagingEventHandler {\n isRunning(sessionKey: string): boolean;\n getRunningSessions(): RunningSession[];\n handleEvent(\n event: ConversationEvent,\n bot: MessagingBot,\n context: ConversationContext,\n ): Promise<void>;\n handleStop(sessionKey: string, conversationId: string, bot: MessagingBot): Promise<void>;\n forceStop(sessionKey: string): void;\n handleNewCommand(sessionKey: string, conversationId: string, bot: MessagingBot): Promise<void>;\n}\n\n// ── agent ─────────────────────────────────────────────────────────────────────\n\nexport interface PiAgentWrapper {\n syncChatHistory(currentMessageId?: string): void;\n run(\n message: ConversationMessage,\n responder: ConversationResponder,\n platform: MessagingInfo,\n ): Promise<{ stopReason: string; errorMessage?: string }>;\n abort(): void;\n getCurrentStep(): { toolName?: string; label?: string } | undefined;\n}\n\n// ── config ────────────────────────────────────────────────────────────────────\n\nexport interface AgentConfig {\n provider: string;\n model: string;\n thinkingLevel: ThinkingLevel;\n sentryDsn?: string;\n sandboxCpus?: string;\n sandboxMemory?: string;\n sandboxBoostCpus?: string;\n sandboxBoostMemory?: string;\n sandboxImageWorkspaceMount?: \"private\" | \"full\";\n defaultSharedVault?: string;\n slack?: {\n replyMode?: \"top-level\" | \"thread\";\n };\n}\n\nexport interface AutoReplyConfig {\n enabled: boolean;\n rules: string[];\n}\n\nexport interface JudgeModelConfig {\n provider: string;\n model: string;\n}\n\n// ── context ───────────────────────────────────────────────────────────────────\n\n/**\n * Platform conversation history entry from log.jsonl.\n */\nexport interface ConversationLogMessage {\n date?: string;\n ts?: string;\n threadTs?: string;\n user?: string;\n userName?: string;\n text?: string;\n isMessagingBot?: boolean;\n}\n\n// ── events ────────────────────────────────────────────────────────────────────\n\nexport interface ImmediateEvent {\n type: \"immediate\";\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n userId?: string;\n text: string;\n}\n\nexport interface OneShotEvent {\n type: \"one-shot\";\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n userId?: string;\n text: string;\n at: string;\n}\n\nexport interface PeriodicEvent {\n type: \"periodic\";\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n userId?: string;\n text: string;\n schedule: string;\n timezone: string;\n}\n\nexport type MikanEvent = ImmediateEvent | OneShotEvent | PeriodicEvent;\n\nexport interface PeriodicEventInfo {\n filename: string;\n platform: string;\n conversationId: string;\n conversationKind: ConversationKind;\n text: string;\n schedule: string;\n timezone: string;\n nextRun: string | null;\n}\n\n// ── execution-resolver ────────────────────────────────────────────────────────\n\nexport interface ActorContext {\n platform: string;\n userId: string;\n conversationId: string;\n}\n\nexport type ImageWorkspaceMountMode = \"private\" | \"full\";\n\n// ── log ───────────────────────────────────────────────────────────────────────\n\nexport interface LogContext {\n conversationId: string;\n userName?: string;\n conversationName?: string;\n sessionId?: string;\n}\n\n// ── portal-shell ──────────────────────────────────────────────────────────────\n\ntype PortalView = \"admin\" | \"session\" | \"vault\";\n\nexport interface PortalShellOptions {\n activeView: PortalView;\n pageTitle: string;\n identity?: {\n primary: string;\n secondary?: string;\n };\n conversationSwitcher?: {\n currentId: string;\n options?: Array<{ id: string; label: string; running?: boolean }>;\n };\n navLinks?: Partial<Record<PortalView, string>>;\n body: string;\n extraStyles?: string;\n inlineScript?: string;\n extraHead?: string;\n bodyAttributes?: Record<string, string>;\n}\n\n// ── provisioner ───────────────────────────────────────────────────────────────\n\nexport interface ContainerMount {\n source: string;\n target: string;\n}\n\nexport interface ResourceLimits {\n cpus?: string;\n memory?: string;\n}\n\nexport interface SandboxLimitStatus {\n limits?: ResourceLimits;\n boosted: boolean;\n}\n\nexport interface ProvisionOptions {\n containerName?: string;\n mounts?: ContainerMount[];\n conversationId?: string;\n}\n\nexport interface DockerContainerManagerOptions {\n limits?: ResourceLimits;\n boostLimits?: ResourceLimits;\n execFileImpl?: ExecFileAsync;\n}\n\n// ── store ─────────────────────────────────────────────────────────────────────\n\nexport interface Attachment {\n original: string;\n localPath: string;\n}\n\nexport interface LoggedMessage {\n date: string;\n ts: string;\n user: string;\n userName?: string;\n displayName?: string;\n text: string;\n attachments: Attachment[];\n isMessagingBot: boolean;\n threadTs?: string;\n}\n\nexport interface ChannelStoreConfig {\n workingDir: string;\n botToken: string;\n}\n\n// ── trigger ───────────────────────────────────────────────────────────────────\n\nexport type TriggerIntent = \"mention\" | \"direct\" | \"thread-continuation\" | \"auto-reply-candidate\";\n\nexport type TriggerResult = { trigger: true; reason: string } | { trigger: false; reason: string };\n\nexport type AutoReplyJudge = (input: {\n event: ConversationEvent;\n rules: string[];\n conversationDir: string;\n}) => Promise<boolean>;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geminixiang/mikan",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Multi-platform AI coding agent for Slack, Telegram, and Discord",
5
5
  "keywords": [
6
6
  "agent",
@@ -1,16 +0,0 @@
1
- import type { AgentTool } from "@earendil-works/pi-agent-core";
2
- type SlackBlockKitResponse = {
3
- text: string;
4
- blocks: object[];
5
- };
6
- declare const blockKitSchema: import("@sinclair/typebox").TObject<{
7
- label: import("@sinclair/typebox").TString;
8
- text: import("@sinclair/typebox").TString;
9
- blocks: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnknown>;
10
- }>;
11
- export declare function createSlackBlockKitTool(): {
12
- tool: AgentTool<typeof blockKitSchema>;
13
- setBlockKitResponseFunction: (fn: (response: SlackBlockKitResponse) => Promise<void>) => void;
14
- };
15
- export {};
16
- //# sourceMappingURL=block-kit.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"block-kit.d.ts","sourceRoot":"","sources":["../../../../src/adapters/slack/tools/block-kit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,QAAA,MAAM,cAAc;;;;EAOlB,CAAC;AAkFH,wBAAgB,uBAAuB,IAAI;IACzC,IAAI,EAAE,SAAS,CAAC,OAAO,cAAc,CAAC,CAAC;IACvC,2BAA2B,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;CAC/F,CAgCA"}
@@ -1,105 +0,0 @@
1
- import { Type } from "@sinclair/typebox";
2
- const blockKitSchema = Type.Object({
3
- label: Type.String({ description: "Brief description of the Slack Block Kit response" }),
4
- text: Type.String({ description: "Plain-text fallback for notifications and non-Slack clients" }),
5
- blocks: Type.Array(Type.Unknown(), {
6
- description: "Slack Block Kit blocks. Supports section, context, divider, header, actions; buttons in actions.elements; static_select and multi_static_select in section.accessory.",
7
- }),
8
- });
9
- const ALLOWED_BLOCK_TYPES = new Set(["section", "context", "divider", "header", "actions"]);
10
- const ALLOWED_INTERACTIVE_ELEMENT_TYPES = new Set([
11
- "button",
12
- "static_select",
13
- "multi_static_select",
14
- ]);
15
- function assertPlainObject(value, label) {
16
- if (!value || typeof value !== "object" || Array.isArray(value)) {
17
- throw new Error(`${label} must be an object`);
18
- }
19
- }
20
- function validateInteractiveElement(element, label) {
21
- if (typeof element.type !== "string" || !ALLOWED_INTERACTIVE_ELEMENT_TYPES.has(element.type)) {
22
- return;
23
- }
24
- if (typeof element.action_id !== "string" || !element.action_id) {
25
- throw new Error(`${label}.action_id is required`);
26
- }
27
- if (element.type === "button" && typeof element.value !== "string") {
28
- throw new Error(`${label}.value is required for buttons`);
29
- }
30
- }
31
- function validateInteractiveElements(value, label) {
32
- if (!value || typeof value !== "object")
33
- return;
34
- if (Array.isArray(value)) {
35
- value.forEach((item, index) => validateInteractiveElements(item, `${label}[${index}]`));
36
- return;
37
- }
38
- const obj = value;
39
- validateInteractiveElement(obj, label);
40
- for (const [key, nested] of Object.entries(obj)) {
41
- validateInteractiveElements(nested, `${label}.${key}`);
42
- }
43
- }
44
- function validateBlockPlacement(block, label) {
45
- if (block.type === "actions") {
46
- if (!Array.isArray(block.elements))
47
- throw new Error(`${label}.elements is required`);
48
- block.elements.forEach((element, index) => {
49
- assertPlainObject(element, `${label}.elements[${index}]`);
50
- if (element.type !== "button") {
51
- throw new Error(`${label}.elements[${index}] uses ${String(element.type)}; put static_select and multi_static_select in section.accessory instead`);
52
- }
53
- });
54
- }
55
- if (block.type === "section" && block.accessory !== undefined) {
56
- assertPlainObject(block.accessory, `${label}.accessory`);
57
- const type = String(block.accessory.type);
58
- if (!ALLOWED_INTERACTIVE_ELEMENT_TYPES.has(type)) {
59
- throw new Error(`${label}.accessory has unsupported type: ${type}`);
60
- }
61
- }
62
- }
63
- function validateBlocks(blocks) {
64
- if (blocks.length === 0)
65
- throw new Error("blocks must not be empty");
66
- if (blocks.length > 20)
67
- throw new Error("blocks must contain at most 20 blocks");
68
- return blocks.map((block, index) => {
69
- assertPlainObject(block, `blocks[${index}]`);
70
- const type = block.type;
71
- if (typeof type !== "string" || !ALLOWED_BLOCK_TYPES.has(type)) {
72
- throw new Error(`Unsupported Block Kit block type: ${String(type)}`);
73
- }
74
- validateBlockPlacement(block, `blocks[${index}]`);
75
- validateInteractiveElements(block, `blocks[${index}]`);
76
- return block;
77
- });
78
- }
79
- export function createSlackBlockKitTool() {
80
- let respondFn = null;
81
- const tool = {
82
- name: "slack_blockkit",
83
- label: "slack block kit",
84
- description: "Send a Slack Block Kit response. Use when structured Slack UI helps the user choose or inspect information. Supports buttons, static_select, and multi_static_select. Put buttons in actions.elements. Put static_select and multi_static_select in section.accessory.",
85
- parameters: blockKitSchema,
86
- execute: async (_toolCallId, { text, blocks }, signal) => {
87
- if (!respondFn)
88
- throw new Error("Slack Block Kit response function not configured");
89
- if (signal?.aborted)
90
- throw new Error("Operation aborted");
91
- await respondFn({ text, blocks: validateBlocks(blocks) });
92
- return {
93
- content: [{ type: "text", text: "Sent Slack Block Kit response" }],
94
- details: undefined,
95
- };
96
- },
97
- };
98
- return {
99
- tool,
100
- setBlockKitResponseFunction: (fn) => {
101
- respondFn = fn;
102
- },
103
- };
104
- }
105
- //# sourceMappingURL=block-kit.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"block-kit.js","sourceRoot":"","sources":["../../../../src/adapters/slack/tools/block-kit.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\n\ntype SlackBlockKitResponse = {\n text: string;\n blocks: object[];\n};\n\nconst blockKitSchema = Type.Object({\n label: Type.String({ description: \"Brief description of the Slack Block Kit response\" }),\n text: Type.String({ description: \"Plain-text fallback for notifications and non-Slack clients\" }),\n blocks: Type.Array(Type.Unknown(), {\n description:\n \"Slack Block Kit blocks. Supports section, context, divider, header, actions; buttons in actions.elements; static_select and multi_static_select in section.accessory.\",\n }),\n});\n\nconst ALLOWED_BLOCK_TYPES = new Set([\"section\", \"context\", \"divider\", \"header\", \"actions\"]);\nconst ALLOWED_INTERACTIVE_ELEMENT_TYPES = new Set([\n \"button\",\n \"static_select\",\n \"multi_static_select\",\n]);\n\nfunction assertPlainObject(\n value: unknown,\n label: string,\n): asserts value is Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${label} must be an object`);\n }\n}\n\nfunction validateInteractiveElement(element: Record<string, unknown>, label: string): void {\n if (typeof element.type !== \"string\" || !ALLOWED_INTERACTIVE_ELEMENT_TYPES.has(element.type)) {\n return;\n }\n if (typeof element.action_id !== \"string\" || !element.action_id) {\n throw new Error(`${label}.action_id is required`);\n }\n if (element.type === \"button\" && typeof element.value !== \"string\") {\n throw new Error(`${label}.value is required for buttons`);\n }\n}\n\nfunction validateInteractiveElements(value: unknown, label: string): void {\n if (!value || typeof value !== \"object\") return;\n if (Array.isArray(value)) {\n value.forEach((item, index) => validateInteractiveElements(item, `${label}[${index}]`));\n return;\n }\n\n const obj = value as Record<string, unknown>;\n validateInteractiveElement(obj, label);\n for (const [key, nested] of Object.entries(obj)) {\n validateInteractiveElements(nested, `${label}.${key}`);\n }\n}\n\nfunction validateBlockPlacement(block: Record<string, unknown>, label: string): void {\n if (block.type === \"actions\") {\n if (!Array.isArray(block.elements)) throw new Error(`${label}.elements is required`);\n block.elements.forEach((element, index) => {\n assertPlainObject(element, `${label}.elements[${index}]`);\n if (element.type !== \"button\") {\n throw new Error(\n `${label}.elements[${index}] uses ${String(element.type)}; put static_select and multi_static_select in section.accessory instead`,\n );\n }\n });\n }\n\n if (block.type === \"section\" && block.accessory !== undefined) {\n assertPlainObject(block.accessory, `${label}.accessory`);\n const type = String(block.accessory.type);\n if (!ALLOWED_INTERACTIVE_ELEMENT_TYPES.has(type)) {\n throw new Error(`${label}.accessory has unsupported type: ${type}`);\n }\n }\n}\n\nfunction validateBlocks(blocks: unknown[]): object[] {\n if (blocks.length === 0) throw new Error(\"blocks must not be empty\");\n if (blocks.length > 20) throw new Error(\"blocks must contain at most 20 blocks\");\n\n return blocks.map((block, index) => {\n assertPlainObject(block, `blocks[${index}]`);\n const type = block.type;\n if (typeof type !== \"string\" || !ALLOWED_BLOCK_TYPES.has(type)) {\n throw new Error(`Unsupported Block Kit block type: ${String(type)}`);\n }\n validateBlockPlacement(block, `blocks[${index}]`);\n validateInteractiveElements(block, `blocks[${index}]`);\n return block;\n });\n}\n\nexport function createSlackBlockKitTool(): {\n tool: AgentTool<typeof blockKitSchema>;\n setBlockKitResponseFunction: (fn: (response: SlackBlockKitResponse) => Promise<void>) => void;\n} {\n let respondFn: ((response: SlackBlockKitResponse) => Promise<void>) | null = null;\n\n const tool: AgentTool<typeof blockKitSchema> = {\n name: \"slack_blockkit\",\n label: \"slack block kit\",\n description:\n \"Send a Slack Block Kit response. Use when structured Slack UI helps the user choose or inspect information. Supports buttons, static_select, and multi_static_select. Put buttons in actions.elements. Put static_select and multi_static_select in section.accessory.\",\n parameters: blockKitSchema,\n execute: async (\n _toolCallId: string,\n { text, blocks }: { label: string; text: string; blocks: unknown[] },\n signal?: AbortSignal,\n ) => {\n if (!respondFn) throw new Error(\"Slack Block Kit response function not configured\");\n if (signal?.aborted) throw new Error(\"Operation aborted\");\n\n await respondFn({ text, blocks: validateBlocks(blocks) });\n\n return {\n content: [{ type: \"text\" as const, text: \"Sent Slack Block Kit response\" }],\n details: undefined,\n };\n },\n };\n\n return {\n tool,\n setBlockKitResponseFunction: (fn) => {\n respondFn = fn;\n },\n };\n}\n"]}
@@ -1,2 +0,0 @@
1
- export declare function shouldSurfaceToolDiagnostic(toolName: string): boolean;
2
- //# sourceMappingURL=tool-diagnostics.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool-diagnostics.d.ts","sourceRoot":"","sources":["../src/tool-diagnostics.ts"],"names":[],"mappings":"AAIA,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAErE"}
@@ -1,7 +0,0 @@
1
- // Central policy for what tool diagnostics are posted back to chat surfaces.
2
- // Detailed tool calls/results still remain in the structured session history and session view.
3
- const QUIET_TOOL_DIAGNOSTICS = new Set(["bash", "read", "write", "edit"]);
4
- export function shouldSurfaceToolDiagnostic(toolName) {
5
- return !QUIET_TOOL_DIAGNOSTICS.has(toolName);
6
- }
7
- //# sourceMappingURL=tool-diagnostics.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool-diagnostics.js","sourceRoot":"","sources":["../src/tool-diagnostics.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+FAA+F;AAC/F,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAE1E,MAAM,UAAU,2BAA2B,CAAC,QAAgB;IAC1D,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["// Central policy for what tool diagnostics are posted back to chat surfaces.\n// Detailed tool calls/results still remain in the structured session history and session view.\nconst QUIET_TOOL_DIAGNOSTICS = new Set([\"bash\", \"read\", \"write\", \"edit\"]);\n\nexport function shouldSurfaceToolDiagnostic(toolName: string): boolean {\n return !QUIET_TOOL_DIAGNOSTICS.has(toolName);\n}\n"]}