@geminixiang/mikan 1.0.0-beta.73 → 1.0.0-beta.75
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 +21 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +1 -3
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/task-intent.d.ts.map +1 -1
- package/dist/adapters/slack/task-intent.js +1 -1
- package/dist/adapters/slack/task-intent.js.map +1 -1
- package/dist/adapters/slack/tools/blockkit.d.ts +1 -0
- package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -1
- package/dist/adapters/slack/tools/blockkit.js +1 -0
- package/dist/adapters/slack/tools/blockkit.js.map +1 -1
- package/dist/adapters/web/admin/portal.js +33 -17
- package/dist/adapters/web/admin/portal.js.map +1 -1
- package/dist/adapters/web/portal-shell.js +5 -2
- package/dist/adapters/web/portal-shell.js.map +1 -1
- package/dist/harness/execution-env.js +34 -1
- package/dist/harness/execution-env.js.map +1 -1
- package/dist/harness/jev.d.ts +10 -1
- package/dist/harness/jev.d.ts.map +1 -1
- package/dist/harness/jev.js +17 -1
- package/dist/harness/jev.js.map +1 -1
- package/dist/harness/presenter.d.ts.map +1 -1
- package/dist/harness/presenter.js +8 -3
- package/dist/harness/presenter.js.map +1 -1
- package/dist/harness/prompt.js +1 -1
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/tools/generate-image.d.ts +1 -0
- package/dist/harness/tools/generate-image.d.ts.map +1 -1
- package/dist/harness/tools/generate-image.js +1 -0
- package/dist/harness/tools/generate-image.js.map +1 -1
- package/dist/harness/tools/host-fn-tool.d.ts +10 -1
- package/dist/harness/tools/host-fn-tool.d.ts.map +1 -1
- package/dist/harness/tools/host-fn-tool.js +22 -2
- package/dist/harness/tools/host-fn-tool.js.map +1 -1
- package/dist/harness/tools/index.d.ts.map +1 -1
- package/dist/harness/tools/index.js +12 -1
- package/dist/harness/tools/index.js.map +1 -1
- package/dist/harness/tools/jev-browser.d.ts +130 -0
- package/dist/harness/tools/jev-browser.d.ts.map +1 -0
- package/dist/harness/tools/jev-browser.js +434 -0
- package/dist/harness/tools/jev-browser.js.map +1 -0
- package/dist/harness/tools/jev.d.ts.map +1 -1
- package/dist/harness/tools/jev.js +1 -0
- package/dist/harness/tools/jev.js.map +1 -1
- package/dist/harness/tools/sandbox.d.ts +1 -0
- package/dist/harness/tools/sandbox.d.ts.map +1 -1
- package/dist/harness/tools/sandbox.js +1 -0
- package/dist/harness/tools/sandbox.js.map +1 -1
- package/dist/harness/tools/secret-redaction.d.ts +34 -0
- package/dist/harness/tools/secret-redaction.d.ts.map +1 -0
- package/dist/harness/tools/secret-redaction.js +77 -0
- package/dist/harness/tools/secret-redaction.js.map +1 -0
- package/dist/observability/index.d.ts +11 -2
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +30 -0
- package/dist/observability/index.js.map +1 -1
- package/dist/observability/sentry.d.ts +9 -2
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +28 -0
- package/dist/observability/sentry.js.map +1 -1
- package/dist/observability/types.d.ts +15 -0
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/observability/types.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +19 -10
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-intent.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/task-intent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC;AAG1B;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAWxD,uGAAuG;AACvG,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrE,OAAO,EAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GACA,MAAM,CA0BR;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,GACzD,OAAO,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"task-intent.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/task-intent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC;AAG1B;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAWxD,uGAAuG;AACvG,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrE,OAAO,EAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GACA,MAAM,CA0BR;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,GACzD,OAAO,CAAC,UAAU,CAAC,CAqCrB"}
|
|
@@ -48,7 +48,7 @@ export async function classifyTaskIntent(state, text, context) {
|
|
|
48
48
|
instructions: "Given the tasks in play and the recent conversation, what does the NEW message mean?",
|
|
49
49
|
criteria: TASK_INTENT_CRITERIA,
|
|
50
50
|
},
|
|
51
|
-
});
|
|
51
|
+
}, { caller: "task_intent" });
|
|
52
52
|
const choice = result.answers.intent.choice;
|
|
53
53
|
const probabilities = result.answers.intent.probabilities;
|
|
54
54
|
log.logInfo(`[${context.conversationId}] jev task intent: ${choice}${probabilities ? ` ${JSON.stringify(probabilities)}` : ""} text="${text.slice(0, 80)}"`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-intent.js","sourceRoot":"","sources":["../../../src/adapters/slack/task-intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,GAEhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAUxD,MAAM,oBAAoB,GAAG;IAC3B,MAAM,EACJ,yLAAyL;IAC3L,KAAK,EACH,6NAA6N;IAC/N,OAAO,EACL,iIAAiI;CAC3H,CAAC;AAEX,uGAAuG;AACvG,MAAM,UAAU,oBAAoB,CAClC,eAAuB,EACvB,KAAqE,EACrE,OAKC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;IAC9F,MAAM,MAAM,GAAG,eAAe,CAAC,eAAe,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM;QAChC,CAAC,CAAC,OAAO,CAAC,KAAK;aACV,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,eAAe,EAAE,CAChG;aACA,IAAI,CAAC,IAAI,CAAC;QACf,CAAC,CAAC,QAAQ,CAAC;IACb,OAAO;QACL,KAAK,CAAC,SAAS;YACb,CAAC,CAAC,iDAAiD;YACnD,CAAC,CAAC,0DAA0D;QAC9D,EAAE;QACF,uCAAuC;QACvC,KAAK;QACL,EAAE;QACF,+CAA+C;QAC/C,iBAAiB,CAAC,MAAM,CAAC;QACzB,EAAE;QACF,oBAAoB,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG;QACpD,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa,EACb,IAAY,EACZ,OAA0D;IAE1D,MAAM,QAAQ,GAAG,GAAe,EAAE,CAChC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"task-intent.js","sourceRoot":"","sources":["../../../src/adapters/slack/task-intent.ts"],"names":[],"mappings":"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","sourcesContent":["import { evaluateWithJev, JevNotConfiguredError } from \"../../harness/index.js\";\nimport { reportUserFacingError } from \"../../observability/index.js\";\nimport * as log from \"../../log.js\";\nimport type { TaskStatus } from \"../../types.js\";\nimport {\n formatRecentScope,\n humanizeMentions,\n readRecentScope,\n type SlackNameResolver,\n} from \"./jev-context.js\";\nimport { isTaskStatusQuestion } from \"./task-status.js\";\n\n/**\n * What a DM message means while a task is around:\n * - `status`: a pure progress question, answered from observation without a model turn\n * - `steer`: a supplement or correction for the running work, folded into its next step\n * - `request`: anything else, handled as an ordinary conversation turn\n */\nexport type TaskIntent = \"status\" | \"steer\" | \"request\";\n\nconst TASK_INTENT_CRITERIA = {\n status:\n \"Only asks whether the ongoing work is done, how it is going, what step it is on, or how long it will take. Contains no new instruction, constraint, correction, or request for content.\",\n steer:\n \"Adds information, a constraint, a correction, or a change of direction for the ongoing work while it continues (e.g. 先不要部署, also check the staging config, use the other branch). May be combined with a progress question.\",\n request:\n \"A new standalone question or request unrelated to steering the ongoing work, a reaction to a finished result, or anything else.\",\n} as const;\n\n/** The shared `state` Jev scores: the scope's recent lines, the tasks in play, and the new message. */\nexport function buildTaskIntentState(\n conversationDir: string,\n event: { ts: string; thread_ts?: string; user: string; text: string },\n options: {\n speaker?: string;\n tasks: TaskStatus[];\n resolveName?: SlackNameResolver;\n botUserId?: string | null;\n },\n): string {\n const resolve = options.resolveName ?? (() => undefined);\n const humanize = (text: string) => humanizeMentions(text, resolve, options.botUserId ?? null);\n const recent = readRecentScope(conversationDir, event, { humanize });\n const tasks = options.tasks.length\n ? options.tasks\n .map(\n (t) =>\n `- ${t.status}${t.currentTool ? ` (currently: ${t.currentTool})` : \"\"}: ${t.acknowledgement}`,\n )\n .join(\"\\n\")\n : \"(none)\";\n return [\n event.thread_ts\n ? \"Slack DM reply inside a background task thread.\"\n : \"Slack DM top-level message while background tasks exist.\",\n \"\",\n \"Tasks in this DM (most recent first):\",\n tasks,\n \"\",\n \"Recent messages in this scope (oldest first):\",\n formatRecentScope(recent),\n \"\",\n `NEW message from ${options.speaker ?? event.user}:`,\n humanize(event.text),\n ].join(\"\\n\");\n}\n\n/**\n * Classify with Jev. When Jev is unavailable or fails, reproduce the pre-Jev\n * behavior exactly: the regex shortcut decides `status`, and other text is\n * `steer` inside a task thread (where it always targeted that task) or\n * `request` at top level.\n */\nexport async function classifyTaskIntent(\n state: string,\n text: string,\n context: { conversationId: string; inTaskThread: boolean },\n): Promise<TaskIntent> {\n const fallback = (): TaskIntent =>\n isTaskStatusQuestion(text) ? \"status\" : context.inTaskThread ? \"steer\" : \"request\";\n try {\n const result = await evaluateWithJev(\n state,\n {\n intent: {\n type: \"choice\",\n instructions:\n \"Given the tasks in play and the recent conversation, what does the NEW message mean?\",\n criteria: TASK_INTENT_CRITERIA,\n },\n },\n { caller: \"task_intent\" },\n );\n const choice = result.answers.intent.choice;\n const probabilities = result.answers.intent.probabilities;\n log.logInfo(\n `[${context.conversationId}] jev task intent: ${choice}${\n probabilities ? ` ${JSON.stringify(probabilities)}` : \"\"\n } text=\"${text.slice(0, 80)}\"`,\n );\n if (choice === \"status\" || choice === \"steer\" || choice === \"request\") return choice;\n return fallback();\n } catch (err) {\n if (!(err instanceof JevNotConfiguredError)) {\n reportUserFacingError(err, {\n domain: \"chat_platform\",\n surface: \"slack_task_intent_jev\",\n operation: \"evaluate\",\n severity: \"warning\",\n context: { conversationId: context.conversationId },\n });\n }\n return fallback();\n }\n}\n"]}
|
|
@@ -2,6 +2,7 @@ import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
|
2
2
|
export type { SlackBlockKitOps } from "../types.js";
|
|
3
3
|
import type { SlackBlockKitOps } from "../types.js";
|
|
4
4
|
declare const blockkitSchema: import("@sinclair/typebox").TObject<{
|
|
5
|
+
label: import("@sinclair/typebox").TString;
|
|
5
6
|
blocks: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnknown>;
|
|
6
7
|
text: import("@sinclair/typebox").TString;
|
|
7
8
|
thread_ts: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blockkit.d.ts","sourceRoot":"","sources":["../../../../src/adapters/slack/tools/blockkit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,QAAA,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"blockkit.d.ts","sourceRoot":"","sources":["../../../../src/adapters/slack/tools/blockkit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,QAAA,MAAM,cAAc;;;;;;EAqBlB,CAAC;AAyCH,wBAAgB,uBAAuB,IAAI;IACzC,IAAI,EAAE,SAAS,CAAC,OAAO,cAAc,CAAC,CAAC;IACvC,mBAAmB,EAAE,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI,CAAC;CAC7D,CAsEA"}
|
|
@@ -3,6 +3,7 @@ import { Type } from "@sinclair/typebox";
|
|
|
3
3
|
const MAX_BLOCKS = 50;
|
|
4
4
|
const MAX_ARGUMENT_BYTES = 64 * 1024;
|
|
5
5
|
const blockkitSchema = Type.Object({
|
|
6
|
+
label: Type.String({ description: "Brief description of this action (shown to user)" }),
|
|
6
7
|
blocks: Type.Array(Type.Unknown(), {
|
|
7
8
|
maxItems: MAX_BLOCKS,
|
|
8
9
|
description: `Slack Block Kit blocks (max ${MAX_BLOCKS}). Use {type:'markdown', text} for prose, {type:'table'} for tables, and actions/section blocks for buttons and select menus.`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blockkit.js","sourceRoot":"","sources":["../../../../src/adapters/slack/tools/blockkit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAIzC,kFAAkF;AAClF,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,CAAC;AAErC,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE;QACjC,QAAQ,EAAE,UAAU;QACpB,WAAW,EAAE,+BAA+B,UAAU,+HAA+H;KACtL,CAAC;IACF,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;QAChB,WAAW,EAAE,+DAA+D;KAC7E,CAAC;IACF,SAAS,EAAE,IAAI,CAAC,QAAQ,CACtB,IAAI,CAAC,MAAM,CAAC;QACV,WAAW,EACT,6FAA6F;KAChG,CAAC,CACH;IACD,SAAS,EAAE,IAAI,CAAC,QAAQ,CACtB,IAAI,CAAC,MAAM,CAAC;QACV,WAAW,EACT,yGAAyG;KAC5G,CAAC,CACH;CACF,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,SAAS,sBAAsB,CAAC,IAAa;IAC3C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;IACrE,IAAI,KAAK,GAAG,kBAAkB,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,gCAAgC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,gBAAgB,kBAAkB,GAAG,IAAI,YAAY;YAC3G,qEAAqE,CACxE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAI,IAA6B,CAAC,MAAM,CAAC;IACrD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,kCAAkC,UAAU,gBAAgB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAY;IACvC,MAAM,IAAI,GACR,GACD,EAAE,IAAI,CAAC;IACR,IAAI,CAAC,IAAI,EAAE,KAAK;QAAE,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,EAAE,MAAM;QACtD,CAAC,CAAC,KAAK,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACnD,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,IAAI,KAAK,CACd,+BAA+B,IAAI,CAAC,KAAK,GAAG,OAAO,kCAAkC,CACtF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB;IAIrC,IAAI,QAAQ,GAA4B,IAAI,CAAC;IAE7C,MAAM,IAAI,GAAqC;QAC7C,IAAI,EAAE,gBAAgB;QACtB,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,63BAA63B;QAC/3B,UAAU,EAAE,cAAc;QAC1B,gBAAgB,EAAE,sBAAyE;QAC3F,OAAO,EAAE,KAAK,EACZ,WAAmB,EACnB,EACE,MAAM,EACN,IAAI,EACJ,SAAS,EACT,SAAS,
|
|
1
|
+
{"version":3,"file":"blockkit.js","sourceRoot":"","sources":["../../../../src/adapters/slack/tools/blockkit.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nexport type { SlackBlockKitOps } from \"../types.js\";\nimport type { SlackBlockKitOps } from \"../types.js\";\n\n/** Slack's own ceilings: 50 blocks per message, and a payload well under 64KB. */\nconst MAX_BLOCKS = 50;\nconst MAX_ARGUMENT_BYTES = 64 * 1024;\n\nconst blockkitSchema = Type.Object({\n label: Type.String({ description: \"Brief description of this action (shown to user)\" }),\n blocks: Type.Array(Type.Unknown(), {\n maxItems: MAX_BLOCKS,\n description: `Slack Block Kit blocks (max ${MAX_BLOCKS}). Use {type:'markdown', text} for prose, {type:'table'} for tables, and actions/section blocks for buttons and select menus.`,\n }),\n text: Type.String({\n description: \"Plain-text fallback shown in notifications and screen readers\",\n }),\n thread_ts: Type.Optional(\n Type.String({\n description:\n \"Optional active-thread TS. Posts are always constrained to the current conversation thread.\",\n }),\n ),\n update_ts: Type.Optional(\n Type.String({\n description:\n \"Update a message previously posted by slack_blockkit in this conversation instead of posting a new one.\",\n }),\n ),\n});\n\n/**\n * Reject a runaway payload before schema validation sees it.\n *\n * `prepareArguments` runs ahead of validation, which reports a failure by\n * embedding the entire argument object in its message. A malformed multi-\n * hundred-KB `blocks` array therefore lands in the session twice — once as the\n * call, once echoed back as the result — and every later reader pays for it.\n * Only a bounded result belongs there, so the size complaint stays short and\n * never quotes what it rejected.\n */\nfunction guardBlockKitArguments(args: unknown): unknown {\n if (!args || typeof args !== \"object\") return args;\n const bytes = Buffer.byteLength(JSON.stringify(args) ?? \"\", \"utf-8\");\n if (bytes > MAX_ARGUMENT_BYTES) {\n throw new Error(\n `slack_blockkit arguments are ${Math.round(bytes / 1024)}KB, over the ${MAX_ARGUMENT_BYTES / 1024}KB limit. ` +\n \"Post a short message and attach the long content as a file instead.\",\n );\n }\n const blocks = (args as { blocks?: unknown }).blocks;\n if (Array.isArray(blocks) && blocks.length > MAX_BLOCKS) {\n throw new Error(`slack_blockkit accepts at most ${MAX_BLOCKS} blocks, got ${blocks.length}.`);\n }\n return args;\n}\n\nfunction formatSlackApiError(err: unknown): Error {\n const data = (\n err as { data?: { error?: string; response_metadata?: { messages?: string[] } } } | undefined\n )?.data;\n if (!data?.error) return err instanceof Error ? err : new Error(String(err));\n const details = data.response_metadata?.messages?.length\n ? `\\n${data.response_metadata.messages.join(\"\\n\")}`\n : \"\";\n return new Error(\n `Slack rejected the request: ${data.error}${details}\\nFix the blocks JSON and retry.`,\n );\n}\n\nexport function createSlackBlockKitTool(): {\n tool: AgentTool<typeof blockkitSchema>;\n setSlackBlockKitOps: (ops: SlackBlockKitOps | null) => void;\n} {\n let boundOps: SlackBlockKitOps | null = null;\n\n const tool: AgentTool<typeof blockkitSchema> = {\n name: \"slack_blockkit\",\n label: \"slack_blockkit\",\n description:\n \"Post an interactive Slack Block Kit message (buttons, select menus, custom layouts) to the current conversation, or update one previously posted with this tool. Normal replies already render Markdown — use this only when you need interactive elements or a layout Markdown cannot express. When a user clicks a button or picks an option, you receive a new message '[Slack action] <action_id>: <value>' — choose descriptive action_ids and values so the interaction tells you what to do. Returns the message ts; pass it back as update_ts to edit the message later (e.g. refreshing vote tallies). After handling an interaction, update the message via update_ts to replace the buttons with the outcome (e.g. '✅ approved') — buttons stay clickable otherwise and repeated clicks re-trigger the action. If Slack rejects the blocks, the error includes its validation messages — fix the JSON and retry.\",\n parameters: blockkitSchema,\n prepareArguments: guardBlockKitArguments as (args: unknown) => typeof blockkitSchema.static,\n execute: async (\n _toolCallId: string,\n {\n blocks,\n text,\n thread_ts,\n update_ts,\n }: {\n blocks: unknown[];\n text: string;\n thread_ts?: string;\n update_ts?: string;\n label?: string;\n },\n signal?: AbortSignal,\n ) => {\n const ops = boundOps;\n if (!ops) {\n throw new Error(\"slack_blockkit is only available in Slack conversations\");\n }\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n try {\n if (update_ts) {\n await ops.updateBlocks({ ts: update_ts, text, blocks: blocks as object[] });\n return {\n content: [\n { type: \"text\" as const, text: `Updated Block Kit message (ts: ${update_ts}).` },\n ],\n details: undefined,\n };\n }\n const { ts } = await ops.postBlocks({\n text,\n blocks: blocks as object[],\n threadTs: thread_ts,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Posted Block Kit message (ts: ${ts}). Interactive elements will arrive as \"[Slack action] <action_id>: <value>\" messages; pass ts back as update_ts to edit this message.`,\n },\n ],\n details: undefined,\n };\n } catch (err) {\n throw formatSlackApiError(err);\n }\n },\n };\n\n return {\n tool,\n setSlackBlockKitOps: (ops) => {\n boundOps = ops;\n },\n };\n}\n"]}
|
|
@@ -1428,7 +1428,9 @@ const ICONS = {
|
|
|
1428
1428
|
/** One entry in the settings rail: an icon, a label, and the pane id it activates. */
|
|
1429
1429
|
function railLink(id, label, icon, active = false) {
|
|
1430
1430
|
const svg = ICONS[icon];
|
|
1431
|
-
|
|
1431
|
+
// The label span is hidden below 860px, so mirror it into aria-label/title to
|
|
1432
|
+
// keep an accessible name and a hover hint once the text disappears.
|
|
1433
|
+
return `<button class="rail-link${active ? " active" : ""}" type="button" data-pane="${id}" aria-current="${active ? "page" : "false"}" aria-label="${esc(label)}" title="${esc(label)}">${svg}<span>${esc(label)}</span></button>`;
|
|
1432
1434
|
}
|
|
1433
1435
|
/**
|
|
1434
1436
|
* One settings pane: an eyebrow-free header (icon lives in the rail, not
|
|
@@ -1474,33 +1476,33 @@ const adminViewBody = `<div class="settings-shell">
|
|
|
1474
1476
|
|
|
1475
1477
|
<div class="settings-panels">
|
|
1476
1478
|
<div class="tab-panel active" id="panel-conversation">
|
|
1477
|
-
${settingsPane("settings", "Settings", "Model, thinking level, auto-reply, and workspace visibility for this conversation.", '<button class="refresh-btn" onclick="loadSettings()">↻</button>', '<div id="settings-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1479
|
+
${settingsPane("settings", "Settings", "Model, thinking level, auto-reply, and workspace visibility for this conversation.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadSettings()">↻</button>', '<div id="settings-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1478
1480
|
|
|
1479
|
-
${settingsPane("workspace", "Workspace", "Read-only browser for this conversation's files on disk.", '<button class="refresh-btn" onclick="loadWorkspace()">↻</button>', '<div class="workspace-split"><div id="workspace-tree" class="workspace-tree"><div class="loading-msg">Loading…</div></div><div id="workspace-preview" class="workspace-preview"><div class="placeholder-msg">Click a file to preview</div></div></div>')}
|
|
1481
|
+
${settingsPane("workspace", "Workspace", "Read-only browser for this conversation's files on disk.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadWorkspace()">↻</button>', '<div class="workspace-split"><div id="workspace-tree" class="workspace-tree"><div class="loading-msg">Loading…</div></div><div id="workspace-preview" class="workspace-preview"><div class="placeholder-msg">Click a file to preview</div></div></div>')}
|
|
1480
1482
|
|
|
1481
|
-
${settingsPane("skills", "Skills", "Instructions the agent can load for specific tasks in this conversation.", '<button class="primary-action-btn" onclick="openSkillDialog(\'conversation\')">+ New skill</button><button class="refresh-btn" onclick="loadSkills()">↻</button>', '<div class="workspace-split"><div id="skills-content" class="workspace-tree"><div class="loading-msg">Loading…</div></div><div id="skills-preview" class="workspace-preview"><div class="placeholder-msg">Click a skill to preview SKILL.md</div></div></div>')}
|
|
1483
|
+
${settingsPane("skills", "Skills", "Instructions the agent can load for specific tasks in this conversation.", '<button class="primary-action-btn" onclick="openSkillDialog(\'conversation\')">+ New skill</button><button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadSkills()">↻</button>', '<div class="workspace-split"><div id="skills-content" class="workspace-tree"><div class="loading-msg">Loading…</div></div><div id="skills-preview" class="workspace-preview"><div class="placeholder-msg">Click a skill to preview SKILL.md</div></div></div>')}
|
|
1482
1484
|
|
|
1483
|
-
${settingsPane("mcp", "MCP servers", "External tools this conversation can call during a run.", '<button class="refresh-btn" onclick="loadMcpServers()">↻</button>', '<div id="mcp-conv-msg" class="status-msg" style="display:none"></div><div id="mcp-conv-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1485
|
+
${settingsPane("mcp", "MCP servers", "External tools this conversation can call during a run.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadMcpServers()">↻</button>', '<div id="mcp-conv-msg" class="status-msg" style="display:none"></div><div id="mcp-conv-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1484
1486
|
|
|
1485
1487
|
${settingsPane("vault", "Vault", "Credentials scoped to this conversation.", '<button class="primary-action-btn" onclick="openLogin()">Open in new tab ↗</button>', '<div id="vault-link-result" class="link-result" style="display:none"></div><p class="card-desc">Opens the one-time credential form for this conversation\'s vault in a new tab.</p>')}
|
|
1486
1488
|
|
|
1487
|
-
${settingsPane("events", "Events", "Scheduled and one-shot events tied to this conversation.", '<button class="refresh-btn" onclick="loadConversationEvents()">↻</button>', '<div id="events-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1489
|
+
${settingsPane("events", "Events", "Scheduled and one-shot events tied to this conversation.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadConversationEvents()">↻</button>', '<div id="events-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1488
1490
|
|
|
1489
1491
|
${settingsPane("session", "Session view", "The full message and tool-call timeline for this conversation.", '<button class="primary-action-btn" onclick="openSessionView()">Open in new tab ↗</button>', '<div id="session-link-result" class="link-result" style="display:none"></div><p class="card-desc">Opens the session timeline for this conversation in a new tab.</p>')}
|
|
1490
1492
|
</div>
|
|
1491
1493
|
|
|
1492
1494
|
<div class="tab-panel" id="panel-global">
|
|
1493
|
-
${settingsPane("g-overview", "All conversations", "Every registered conversation across every platform.", '<button class="refresh-btn" onclick="loadAllConversations()">↻</button>', '<div id="all-conv-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1495
|
+
${settingsPane("g-overview", "All conversations", "Every registered conversation across every platform.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadAllConversations()">↻</button>', '<div id="all-conv-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1494
1496
|
|
|
1495
|
-
${settingsPane("g-usage", "Token usage", "Spend and volume across every conversation.", '<button class="refresh-btn" onclick="loadTokenUsage()">↻</button>', '<h3 class="card-subtitle">Top 20 sessions</h3><div id="session-usage-content"><div class="loading-msg">Loading…</div></div><h3 class="card-subtitle" style="margin-top:24px">Usage timeline</h3><div class="timeline-controls"><label>Conversation<select id="timeline-conv" onchange="loadUsageTimeline()"></select></label></div><div id="usage-timeline-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1497
|
+
${settingsPane("g-usage", "Token usage", "Spend and volume across every conversation.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadTokenUsage()">↻</button>', '<h3 class="card-subtitle">Top 20 sessions</h3><div id="session-usage-content"><div class="loading-msg">Loading…</div></div><h3 class="card-subtitle" style="margin-top:24px">Usage timeline</h3><div class="timeline-controls"><label>Conversation<select id="timeline-conv" onchange="loadUsageTimeline()"></select></label></div><div id="usage-timeline-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1496
1498
|
|
|
1497
|
-
${settingsPane("g-settings", "Workspace defaults", "The fallback model, sandbox limits, and Slack behavior every conversation inherits.", '<button class="refresh-btn" onclick="loadGlobalSettings()">↻</button>', '<div id="global-settings-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1499
|
+
${settingsPane("g-settings", "Workspace defaults", "The fallback model, sandbox limits, and Slack behavior every conversation inherits.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadGlobalSettings()">↻</button>', '<div id="global-settings-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1498
1500
|
|
|
1499
|
-
${settingsPane("g-mcp", "MCP servers", "External tools available to every conversation in this workspace.", '<button class="refresh-btn" onclick="loadMcpServers()">↻</button>', '<div id="mcp-global-msg" class="status-msg" style="display:none"></div><div id="mcp-global-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1501
|
+
${settingsPane("g-mcp", "MCP servers", "External tools available to every conversation in this workspace.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadMcpServers()">↻</button>', '<div id="mcp-global-msg" class="status-msg" style="display:none"></div><div id="mcp-global-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1500
1502
|
|
|
1501
|
-
${settingsPane("g-skills", "Skills", "Shared instructions available to every conversation in this workspace.", '<button class="primary-action-btn" onclick="openSkillDialog(\'global\')">+ New global skill</button><button class="refresh-btn" onclick="loadGlobalSkills()">↻</button>', '<div class="workspace-split"><div id="global-skills-content" class="workspace-tree"><div class="loading-msg">Loading…</div></div><div id="global-skills-preview" class="workspace-preview"><div class="placeholder-msg">Click a skill to preview SKILL.md</div></div></div>')}
|
|
1503
|
+
${settingsPane("g-skills", "Skills", "Shared instructions available to every conversation in this workspace.", '<button class="primary-action-btn" onclick="openSkillDialog(\'global\')">+ New global skill</button><button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadGlobalSkills()">↻</button>', '<div class="workspace-split"><div id="global-skills-content" class="workspace-tree"><div class="loading-msg">Loading…</div></div><div id="global-skills-preview" class="workspace-preview"><div class="placeholder-msg">Click a skill to preview SKILL.md</div></div></div>')}
|
|
1502
1504
|
|
|
1503
|
-
${settingsPane("g-events", "Global events", "Every scheduled event across the whole workspace.", '<button class="refresh-btn" onclick="loadEvents()">↻</button>', '<div id="global-events-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1505
|
+
${settingsPane("g-events", "Global events", "Every scheduled event across the whole workspace.", '<button class="refresh-btn" type="button" aria-label="Refresh" title="Refresh" onclick="loadEvents()">↻</button>', '<div id="global-events-content"><div class="loading-msg">Loading…</div></div>')}
|
|
1504
1506
|
</div>
|
|
1505
1507
|
</div>
|
|
1506
1508
|
</div>
|
|
@@ -2983,6 +2985,9 @@ const adminViewStyles = `
|
|
|
2983
2985
|
display: grid; grid-template-columns: 1fr 1fr; gap: 18px;
|
|
2984
2986
|
}
|
|
2985
2987
|
.config-block { display: flex; flex-direction: column; gap: 10px; }
|
|
2988
|
+
/* Config blocks are flex columns, so a plain child button stretches to the
|
|
2989
|
+
full column width. Keep the save action a normal-sized button instead. */
|
|
2990
|
+
.config-block .primary-action-btn { align-self: flex-start; min-width: 132px; justify-content: center; }
|
|
2986
2991
|
.config-row { display: grid; grid-template-columns: 110px 1fr; gap: 10px; align-items: center; }
|
|
2987
2992
|
.config-row.config-row-stack { grid-template-columns: 1fr; }
|
|
2988
2993
|
.config-row label { font-size: 0.82rem; color: var(--muted); }
|
|
@@ -3060,14 +3065,14 @@ const adminViewStyles = `
|
|
|
3060
3065
|
.skill-row {
|
|
3061
3066
|
padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
|
|
3062
3067
|
background: rgba(0,0,0,0.02);
|
|
3063
|
-
display: flex;
|
|
3068
|
+
display: flex; flex-direction: column; align-items: stretch; gap: 6px;
|
|
3064
3069
|
}
|
|
3065
3070
|
.skill-row-btn {
|
|
3066
3071
|
flex: 1 1 auto; min-width: 0; text-align: left; cursor: pointer; font-family: inherit;
|
|
3067
3072
|
background: transparent; border: none; padding: 0;
|
|
3068
3073
|
}
|
|
3069
3074
|
.skill-row-btn:hover .skill-name { color: var(--accent); }
|
|
3070
|
-
.skill-row-actions { display: flex; gap: 6px; flex-shrink: 0; }
|
|
3075
|
+
.skill-row-actions { display: flex; gap: 6px; flex-shrink: 0; justify-content: flex-end; }
|
|
3071
3076
|
.skill-name {
|
|
3072
3077
|
font-weight: 650; font-size: 0.9rem; color: var(--text);
|
|
3073
3078
|
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
@@ -3379,9 +3384,20 @@ const adminViewStyles = `
|
|
|
3379
3384
|
@media (max-width: 860px) {
|
|
3380
3385
|
.settings-shell { grid-template-columns: 1fr; }
|
|
3381
3386
|
.settings-rail { position: static; }
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
.rail-
|
|
3387
|
+
/* Keep labels on narrow screens: a scrollable chip row is far easier to
|
|
3388
|
+
scan than a row of bare icons with no text. */
|
|
3389
|
+
.rail-nav {
|
|
3390
|
+
flex-direction: row; flex-wrap: nowrap; gap: 6px;
|
|
3391
|
+
overflow-x: auto; padding-bottom: 6px;
|
|
3392
|
+
/* Without min-width:0 a nowrap flex row refuses to shrink and blows the
|
|
3393
|
+
page width out instead of scrolling. */
|
|
3394
|
+
min-width: 0; max-width: 100%;
|
|
3395
|
+
scrollbar-width: thin; -webkit-overflow-scrolling: touch;
|
|
3396
|
+
}
|
|
3397
|
+
.settings-rail { min-width: 0; }
|
|
3398
|
+
.rail-nav[hidden] { display: none; }
|
|
3399
|
+
.rail-link { flex: 0 0 auto; padding: 7px 11px; }
|
|
3400
|
+
.rail-link span { white-space: nowrap; }
|
|
3385
3401
|
}
|
|
3386
3402
|
|
|
3387
3403
|
@media (max-width: 640px) {
|