@pinet/slack-bridge 0.2.4 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -1
- package/dist/activity-log.d.ts +10 -3
- package/dist/agent-event-runtime.d.ts +0 -2
- package/dist/agent-event-runtime.js +0 -1
- package/dist/agent-prompt-guidance.d.ts +1 -6
- package/dist/agent-prompt-guidance.js +1 -6
- package/dist/broker/adapters/slack.d.ts +4 -1
- package/dist/broker/adapters/slack.js +16 -9
- package/dist/broker/client.d.ts +21 -4
- package/dist/broker/client.js +65 -25
- package/dist/broker/hibernation-activation-authority.d.ts +22 -0
- package/dist/broker/hibernation-activation-authority.js +51 -0
- package/dist/broker/hibernation-activation.d.ts +75 -0
- package/dist/broker/hibernation-activation.js +95 -0
- package/dist/broker/hibernation-command-router.d.ts +54 -0
- package/dist/broker/hibernation-command-router.js +124 -0
- package/dist/broker/hibernation-runtime-adapters.d.ts +79 -0
- package/dist/broker/hibernation-runtime-adapters.js +473 -0
- package/dist/broker/hibernation-runtime-helpers.d.ts +146 -0
- package/dist/broker/hibernation-runtime-helpers.js +243 -0
- package/dist/broker/index.d.ts +16 -1
- package/dist/broker/index.js +68 -10
- package/dist/broker/lock-conflict.d.ts +109 -0
- package/dist/broker/lock-conflict.js +409 -0
- package/dist/broker/socket-server.d.ts +25 -0
- package/dist/broker/socket-server.js +234 -4
- package/dist/broker-delivery.d.ts +1 -0
- package/dist/broker-delivery.js +10 -1
- package/dist/broker-runtime.d.ts +14 -2
- package/dist/broker-runtime.js +114 -3
- package/dist/canvases.d.ts +12 -2
- package/dist/canvases.js +1 -3
- package/dist/compaction-gate.d.ts +7 -0
- package/dist/compaction-gate.js +35 -0
- package/dist/deploy-manifest.d.ts +8 -2
- package/dist/deploy-manifest.js +9 -7
- package/dist/follower-runtime.d.ts +5 -2
- package/dist/follower-runtime.js +39 -5
- package/dist/git-metadata.d.ts +5 -9
- package/dist/git-metadata.js +23 -42
- package/dist/guardrails.js +5 -0
- package/dist/helpers.d.ts +77 -27
- package/dist/helpers.js +150 -39
- package/dist/hibernation-config.d.ts +13 -0
- package/dist/hibernation-config.js +14 -0
- package/dist/home-tab.d.ts +13 -2
- package/dist/imessage-tools.d.ts +4 -1
- package/dist/inbox-drain-runtime.d.ts +1 -0
- package/dist/inbox-drain-runtime.js +5 -1
- package/dist/index.js +340 -108
- package/dist/pinet-commands.d.ts +14 -1
- package/dist/pinet-commands.js +93 -22
- package/dist/pinet-mesh-ops.d.ts +6 -4
- package/dist/pinet-mesh-ops.js +8 -1
- package/dist/pinet-runtime-composition.d.ts +2 -1
- package/dist/pinet-runtime-composition.js +14 -3
- package/dist/pinet-session-formatting.d.ts +26 -2
- package/dist/pinet-session-formatting.js +2 -0
- package/dist/pinet-tools.d.ts +14 -0
- package/dist/pinet-tools.js +355 -50
- package/dist/prompts/broker/default.md +3 -3
- package/dist/prompts/broker/tmux.md +3 -3
- package/dist/runtime-agent-context.d.ts +3 -3
- package/dist/runtime-agent-context.js +12 -6
- package/dist/runtime-mode.js +4 -0
- package/dist/session-ui-runtime.js +3 -1
- package/dist/single-player-runtime.d.ts +1 -1
- package/dist/single-player-runtime.js +21 -5
- package/dist/slack-access.d.ts +10 -2
- package/dist/slack-access.js +64 -22
- package/dist/slack-block-kit.d.ts +44 -2
- package/dist/slack-block-kit.js +5 -5
- package/dist/slack-file-access.d.ts +12 -1
- package/dist/slack-file-access.js +4 -4
- package/dist/slack-message-context.d.ts +9 -2
- package/dist/slack-modals.d.ts +4 -1
- package/dist/slack-modals.js +5 -5
- package/dist/slack-pinet-runtime-adapter.d.ts +1 -0
- package/dist/slack-pinet-runtime-adapter.js +10 -0
- package/dist/slack-presence.d.ts +5 -4
- package/dist/slack-request-runtime.d.ts +3 -2
- package/dist/slack-scope-diagnostics.d.ts +27 -2
- package/dist/slack-socket-dedup.d.ts +8 -5
- package/dist/slack-tools.d.ts +3 -1
- package/dist/slack-tools.js +26 -16
- package/dist/slack-upload.d.ts +17 -1
- package/dist/subtree-broker-runtime.d.ts +83 -2
- package/dist/subtree-broker-runtime.js +774 -109
- package/dist/tool-output-limits.d.ts +11 -0
- package/dist/tool-output-limits.js +20 -0
- package/dist/tool-registration-runtime.d.ts +3 -0
- package/dist/tool-registration-runtime.js +27 -0
- package/package.json +8 -8
|
@@ -79,6 +79,16 @@ export function createSlackPinetRuntimeAdapterFactory(deps) {
|
|
|
79
79
|
onAppHomeOpened: async ({ userId }) => {
|
|
80
80
|
await deps.onAppHomeOpened(userId, ctx);
|
|
81
81
|
},
|
|
82
|
+
onSocketOpen: () => deps.setExtStatus(ctx, "ok"),
|
|
83
|
+
onSocketReconnectScheduled: () => deps.setExtStatus(ctx, "reconnecting"),
|
|
84
|
+
onSocketError: (message, source) => {
|
|
85
|
+
if (source === "connection") {
|
|
86
|
+
deps.setExtStatus(ctx, "error");
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
ctx.ui.notify(`Slack event failed: ${message}`, "error");
|
|
90
|
+
}
|
|
91
|
+
},
|
|
82
92
|
onSlashCommand: deps.onSlashCommand
|
|
83
93
|
? (event) => deps.onSlashCommand?.(event, ctx) ?? null
|
|
84
94
|
: undefined,
|
package/dist/slack-presence.d.ts
CHANGED
|
@@ -21,11 +21,12 @@ export interface SlackPresenceSnapshot {
|
|
|
21
21
|
lastActivity?: number;
|
|
22
22
|
online?: boolean;
|
|
23
23
|
}
|
|
24
|
+
export type SlackPresenceTimestampValue = string | number | null | undefined;
|
|
24
25
|
export interface SlackDndInfoLike {
|
|
25
|
-
dnd_enabled?:
|
|
26
|
-
next_dnd_end_ts?:
|
|
27
|
-
snooze_enabled?:
|
|
28
|
-
snooze_endtime?:
|
|
26
|
+
dnd_enabled?: boolean | null;
|
|
27
|
+
next_dnd_end_ts?: SlackPresenceTimestampValue;
|
|
28
|
+
snooze_enabled?: boolean | null;
|
|
29
|
+
snooze_endtime?: SlackPresenceTimestampValue;
|
|
29
30
|
}
|
|
30
31
|
export declare function stripSlackUserReference(value: string): string;
|
|
31
32
|
export declare function isSlackUserId(value: string): boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type SlackResult } from "./slack-api.js";
|
|
2
|
-
export type
|
|
1
|
+
import { callSlackApi, type SlackResult } from "./slack-api.js";
|
|
2
|
+
export type SlackRequestBody = NonNullable<Parameters<typeof callSlackApi>[2]>;
|
|
3
|
+
export type SlackRequestCall = (method: string, token: string, body?: SlackRequestBody) => Promise<SlackResult>;
|
|
3
4
|
export interface SlackRequestRuntime {
|
|
4
5
|
slack: SlackRequestCall;
|
|
5
6
|
reset: () => void;
|
|
@@ -1,7 +1,31 @@
|
|
|
1
|
+
export type SlackScopeDiagnosticsSurface = "files" | "bookmarks" | "pins";
|
|
2
|
+
export type SlackScopeProbeBody = Record<string, unknown>;
|
|
3
|
+
interface SlackFileInfoScopeProbeBody extends SlackScopeProbeBody {
|
|
4
|
+
file: string;
|
|
5
|
+
}
|
|
6
|
+
interface SlackCompleteUploadScopeProbeFile {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
}
|
|
10
|
+
interface SlackCompleteUploadScopeProbeBody extends SlackScopeProbeBody {
|
|
11
|
+
files: SlackCompleteUploadScopeProbeFile[];
|
|
12
|
+
channel_id: string;
|
|
13
|
+
}
|
|
14
|
+
interface SlackChannelScopeProbeBody extends SlackScopeProbeBody {
|
|
15
|
+
channel_id: string;
|
|
16
|
+
}
|
|
17
|
+
interface SlackBookmarkRemoveScopeProbeBody extends SlackChannelScopeProbeBody {
|
|
18
|
+
bookmark_id: string;
|
|
19
|
+
}
|
|
20
|
+
interface SlackPinnedItemScopeProbeBody extends SlackScopeProbeBody {
|
|
21
|
+
channel: string;
|
|
22
|
+
timestamp?: string;
|
|
23
|
+
}
|
|
24
|
+
export type SlackScopeProbeRequestBody = SlackFileInfoScopeProbeBody | SlackCompleteUploadScopeProbeBody | SlackChannelScopeProbeBody | SlackBookmarkRemoveScopeProbeBody | SlackPinnedItemScopeProbeBody;
|
|
1
25
|
export type SlackScopeDiagnosticsStatus = "not_checked" | "pending" | "healthy" | "drift" | "unavailable";
|
|
2
26
|
export interface SlackScopeProbeResult {
|
|
3
27
|
key: string;
|
|
4
|
-
surface:
|
|
28
|
+
surface: SlackScopeDiagnosticsSurface;
|
|
5
29
|
method: string;
|
|
6
30
|
expectedScopes: string[];
|
|
7
31
|
status: "ok" | "missing" | "unavailable";
|
|
@@ -14,7 +38,7 @@ export interface SlackScopeDiagnostics {
|
|
|
14
38
|
status: SlackScopeDiagnosticsStatus;
|
|
15
39
|
checkedAt: string | null;
|
|
16
40
|
summary: string;
|
|
17
|
-
surfaces:
|
|
41
|
+
surfaces: SlackScopeDiagnosticsSurface[];
|
|
18
42
|
missingScopes: string[];
|
|
19
43
|
results: SlackScopeProbeResult[];
|
|
20
44
|
error?: string;
|
|
@@ -29,3 +53,4 @@ export declare function createPendingSlackScopeDiagnostics(): SlackScopeDiagnost
|
|
|
29
53
|
export declare function detectSlackScopeDiagnostics(options: DetectSlackScopeDiagnosticsOptions): Promise<SlackScopeDiagnostics>;
|
|
30
54
|
export declare function formatSlackScopeDiagnosticsStatus(diagnostics: SlackScopeDiagnostics): string;
|
|
31
55
|
export declare function buildSlackScopeDriftWarning(diagnostics: SlackScopeDiagnostics): string | null;
|
|
56
|
+
export {};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export declare const SLACK_SOCKET_DELIVERY_DEDUP_TTL_MS: number;
|
|
2
2
|
export declare const SLACK_SOCKET_DELIVERY_DEDUP_MAX_SIZE = 10000;
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
3
|
+
export type SlackDedupEventPayload = Record<string, unknown>;
|
|
4
|
+
export type SlackInteractiveDedupPayload = Record<string, unknown>;
|
|
5
|
+
export type SlackSocketDedupFrame = Record<string, unknown>;
|
|
6
|
+
export declare function extractSlackEventDedupKey(evt: SlackDedupEventPayload): string | null;
|
|
7
|
+
export declare function extractSlackBlockActionDedupKey(payload: SlackInteractiveDedupPayload): string | null;
|
|
8
|
+
export declare function extractSlackViewSubmissionDedupKey(payload: SlackInteractiveDedupPayload): string | null;
|
|
9
|
+
export declare function extractSlackInteractiveDedupKey(payload: SlackInteractiveDedupPayload): string | null;
|
|
10
|
+
export declare function extractSlackSocketDedupKey(frame: SlackSocketDedupFrame): string | null;
|
package/dist/slack-tools.d.ts
CHANGED
|
@@ -31,13 +31,14 @@ export interface SlackPinetDeliveryPort {
|
|
|
31
31
|
* live broker connectivity. When true, threaded Slack replies MUST route
|
|
32
32
|
* through the broker; direct Slack fallback is refused even if the broker
|
|
33
33
|
* is momentarily unavailable, to preserve broker-enforced thread
|
|
34
|
-
* ownership (see gugu91/
|
|
34
|
+
* ownership (see gugu91/pinet#855).
|
|
35
35
|
*/
|
|
36
36
|
isEnabled: () => boolean;
|
|
37
37
|
isAvailable: () => boolean;
|
|
38
38
|
sendSlackMessage: (input: SlackPinetDeliveryInput) => Promise<SlackPinetDeliveryResult>;
|
|
39
39
|
}
|
|
40
40
|
export interface RegisterSlackToolsDeps {
|
|
41
|
+
additionalSendPromptGuidelines?: string[];
|
|
41
42
|
getBotToken: () => string;
|
|
42
43
|
getDefaultChannel: () => string | undefined;
|
|
43
44
|
getSecurityPrompt: () => string;
|
|
@@ -48,6 +49,7 @@ export interface RegisterSlackToolsDeps {
|
|
|
48
49
|
getAgentOwnerToken: () => string;
|
|
49
50
|
getLastDmChannel: () => string | null;
|
|
50
51
|
updateBadge: () => void;
|
|
52
|
+
markSubtreeInboxIdsDelivered: (inboxIds: number[]) => void;
|
|
51
53
|
resolveUser: (userId: string) => Promise<string>;
|
|
52
54
|
threadContext: SlackToolsThreadContextPort;
|
|
53
55
|
resolveChannel: (nameOrId: string) => Promise<string>;
|
package/dist/slack-tools.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
|
+
import { getSubtreeInboxIds } from "./broker-delivery.js";
|
|
3
4
|
import { buildSlackCanvasCreateRequest, buildSlackCanvasEditRequest, buildSlackCanvasSectionsLookupRequest, extractSlackCanvasCommentsPage, extractSlackChannelCanvasId, normalizeSlackCanvasCommentsLimit, normalizeSlackCanvasCreateKind, normalizeSlackCanvasUpdateMode, pickSlackCanvasSectionId, } from "./canvases.js";
|
|
4
5
|
import { normalizeSlackBlocksInput, summarizeSlackBlocksForPolicy } from "./slack-block-kit.js";
|
|
5
6
|
import { encodeSlackModalPrivateMetadata, normalizeSlackModalViewInput } from "./slack-modals.js";
|
|
@@ -146,7 +147,7 @@ const SLACK_DISPATCHER_EXAMPLES = {
|
|
|
146
147
|
},
|
|
147
148
|
],
|
|
148
149
|
};
|
|
149
|
-
function
|
|
150
|
+
function isSlackToolObject(value) {
|
|
150
151
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
151
152
|
}
|
|
152
153
|
function normalizeSlackDispatcherActionName(value) {
|
|
@@ -292,11 +293,11 @@ function classifySlackDispatcherError(error) {
|
|
|
292
293
|
};
|
|
293
294
|
}
|
|
294
295
|
function extractToolResponseText(response) {
|
|
295
|
-
if (!
|
|
296
|
+
if (!isSlackToolObject(response) || !Array.isArray(response.content))
|
|
296
297
|
return undefined;
|
|
297
298
|
const lines = response.content
|
|
298
299
|
.map((item) => {
|
|
299
|
-
if (!
|
|
300
|
+
if (!isSlackToolObject(item))
|
|
300
301
|
return undefined;
|
|
301
302
|
return typeof item.text === "string" ? item.text : undefined;
|
|
302
303
|
})
|
|
@@ -304,18 +305,20 @@ function extractToolResponseText(response) {
|
|
|
304
305
|
return lines.length > 0 ? lines.join("\n") : undefined;
|
|
305
306
|
}
|
|
306
307
|
function extractToolResponseDetails(response) {
|
|
307
|
-
return
|
|
308
|
+
return isSlackToolObject(response) && "details" in response ? response.details : undefined;
|
|
308
309
|
}
|
|
309
310
|
function extractToolResponseFullDetails(response) {
|
|
310
|
-
return
|
|
311
|
+
return isSlackToolObject(response) && "fullDetails" in response
|
|
312
|
+
? response.fullDetails
|
|
313
|
+
: undefined;
|
|
311
314
|
}
|
|
312
315
|
function normalizeSlackOutputOptions(action, args) {
|
|
313
|
-
if (args != null && !
|
|
316
|
+
if (args != null && !isSlackToolObject(args)) {
|
|
314
317
|
throw new Error("slack args must be an object.");
|
|
315
318
|
}
|
|
316
319
|
const ownsFormatArg = SLACK_ACTIONS_WITH_FORMAT_ARG.has(action);
|
|
317
|
-
const rawResponseFormat =
|
|
318
|
-
const rawFormat = rawResponseFormat ?? (
|
|
320
|
+
const rawResponseFormat = isSlackToolObject(args) ? args.response_format : undefined;
|
|
321
|
+
const rawFormat = rawResponseFormat ?? (isSlackToolObject(args) && !ownsFormatArg ? args.format : undefined);
|
|
319
322
|
const normalizedFormat = rawFormat == null ? "cli" : String(rawFormat).trim().toLowerCase();
|
|
320
323
|
if (normalizedFormat !== "cli" && normalizedFormat !== "json") {
|
|
321
324
|
throw new Error(ownsFormatArg
|
|
@@ -323,14 +326,14 @@ function normalizeSlackOutputOptions(action, args) {
|
|
|
323
326
|
: 'format must be "cli" or "json" when provided.');
|
|
324
327
|
}
|
|
325
328
|
const format = normalizedFormat;
|
|
326
|
-
const rawFull =
|
|
329
|
+
const rawFull = isSlackToolObject(args) ? args.full : undefined;
|
|
327
330
|
if (rawFull != null && typeof rawFull !== "boolean") {
|
|
328
331
|
throw new Error("full must be a boolean when provided.");
|
|
329
332
|
}
|
|
330
333
|
return { format, full: rawFull === true };
|
|
331
334
|
}
|
|
332
335
|
function getSlackEnvelopeCliText(envelope) {
|
|
333
|
-
if (envelope.status === "succeeded" &&
|
|
336
|
+
if (envelope.status === "succeeded" && isSlackToolObject(envelope.data)) {
|
|
334
337
|
const text = envelope.data.text;
|
|
335
338
|
if (typeof text === "string" && text.length > 0)
|
|
336
339
|
return text;
|
|
@@ -610,7 +613,7 @@ export function registerSlackTools(pi, deps) {
|
|
|
610
613
|
// Slack when the broker is unavailable or the delivery errors: direct
|
|
611
614
|
// Slack posting bypasses broker thread-ownership enforcement and lets any
|
|
612
615
|
// worker with a valid bot token take over a Slack thread it does not own.
|
|
613
|
-
// See gugu91/
|
|
616
|
+
// See gugu91/pinet#855. Single-player mode (isEnabled === false) and
|
|
614
617
|
// top-level channel posts (no threadTs) remain unaffected.
|
|
615
618
|
if (input.threadTs && pinetDelivery?.isEnabled()) {
|
|
616
619
|
if (!pinetDelivery.isAvailable()) {
|
|
@@ -673,7 +676,7 @@ export function registerSlackTools(pi, deps) {
|
|
|
673
676
|
if (input.threadTs)
|
|
674
677
|
body.thread_ts = input.threadTs;
|
|
675
678
|
const response = await slack("chat.postMessage", getBotToken(), body);
|
|
676
|
-
const message =
|
|
679
|
+
const message = isSlackToolObject(response.message) ? response.message : null;
|
|
677
680
|
const ts = typeof message?.ts === "string" ? message.ts : undefined;
|
|
678
681
|
return {
|
|
679
682
|
...(ts ? { ts } : {}),
|
|
@@ -691,10 +694,10 @@ export function registerSlackTools(pi, deps) {
|
|
|
691
694
|
slackActionRegistry.set(action, definition);
|
|
692
695
|
}
|
|
693
696
|
function buildSlackDispatcherHelpEnvelope(args) {
|
|
694
|
-
if (args != null && !
|
|
697
|
+
if (args != null && !isSlackToolObject(args)) {
|
|
695
698
|
return buildSlackActionFailureEnvelope(new Error("slack help args must be an object."));
|
|
696
699
|
}
|
|
697
|
-
const topic =
|
|
700
|
+
const topic = isSlackToolObject(args) && typeof args.topic === "string" ? args.topic : undefined;
|
|
698
701
|
if (topic) {
|
|
699
702
|
const action = normalizeSlackDispatcherActionName(topic);
|
|
700
703
|
const definition = slackActionRegistry.get(action);
|
|
@@ -769,7 +772,7 @@ export function registerSlackTools(pi, deps) {
|
|
|
769
772
|
if (action === "help") {
|
|
770
773
|
return buildSlackDispatcherResponse(buildSlackDispatcherHelpEnvelope(args), output);
|
|
771
774
|
}
|
|
772
|
-
if (!
|
|
775
|
+
if (!isSlackToolObject(args)) {
|
|
773
776
|
return buildSlackDispatcherResponse(buildSlackActionFailureEnvelope(new Error("slack args must be an object.")), output);
|
|
774
777
|
}
|
|
775
778
|
const definition = slackActionRegistry.get(action);
|
|
@@ -1247,6 +1250,10 @@ export function registerSlackTools(pi, deps) {
|
|
|
1247
1250
|
: "";
|
|
1248
1251
|
lines.push(`${prefix} (${message.timestamp}): ${message.text}${metadataSuffix}`);
|
|
1249
1252
|
}
|
|
1253
|
+
const subtreeInboxIds = getSubtreeInboxIds(pending);
|
|
1254
|
+
if (subtreeInboxIds.length > 0) {
|
|
1255
|
+
deps.markSubtreeInboxIdsDelivered(subtreeInboxIds);
|
|
1256
|
+
}
|
|
1250
1257
|
return {
|
|
1251
1258
|
content: [
|
|
1252
1259
|
{
|
|
@@ -1404,7 +1411,10 @@ export function registerSlackTools(pi, deps) {
|
|
|
1404
1411
|
label: "Slack Send",
|
|
1405
1412
|
description: "Send a message in a Slack assistant thread.",
|
|
1406
1413
|
promptSnippet: "Reply in a Slack assistant thread. When you receive a task: ACK briefly, do the work, report blockers immediately, report the outcome when done. Always reply where the task came from.",
|
|
1407
|
-
promptGuidelines:
|
|
1414
|
+
promptGuidelines: [
|
|
1415
|
+
...buildSlackSendPromptGuidelines(),
|
|
1416
|
+
...(deps.additionalSendPromptGuidelines ?? []),
|
|
1417
|
+
],
|
|
1408
1418
|
parameters: Type.Object({
|
|
1409
1419
|
text: Type.String({ description: "Message text (Slack markdown)" }),
|
|
1410
1420
|
thread_ts: Type.Optional(Type.String({
|
package/dist/slack-upload.d.ts
CHANGED
|
@@ -17,8 +17,24 @@ export interface PreparedSlackUpload {
|
|
|
17
17
|
source: "content" | "path";
|
|
18
18
|
resolvedPath?: string;
|
|
19
19
|
}
|
|
20
|
+
export interface SlackUploadMetadataPayload extends Record<string, unknown> {
|
|
21
|
+
filename: string;
|
|
22
|
+
length: number;
|
|
23
|
+
snippet_type?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SlackCompleteUploadFilePayload {
|
|
26
|
+
id: string;
|
|
27
|
+
title: string;
|
|
28
|
+
}
|
|
29
|
+
export interface SlackCompleteUploadPayload extends Record<string, unknown> {
|
|
30
|
+
files: SlackCompleteUploadFilePayload[];
|
|
31
|
+
channel_id: string;
|
|
32
|
+
thread_ts?: string;
|
|
33
|
+
initial_comment?: string;
|
|
34
|
+
}
|
|
35
|
+
export type SlackUploadApiBody = SlackUploadMetadataPayload | SlackCompleteUploadPayload;
|
|
20
36
|
export interface SlackUploadDeps {
|
|
21
|
-
slack: (method: string, token: string, body?:
|
|
37
|
+
slack: (method: string, token: string, body?: SlackUploadApiBody) => Promise<SlackResult>;
|
|
22
38
|
token: string;
|
|
23
39
|
fetchImpl?: (url: string, init: RequestInit) => Promise<Pick<Response, "ok" | "status" | "statusText" | "text">>;
|
|
24
40
|
}
|
|
@@ -2,21 +2,51 @@ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
|
2
2
|
import type { AgentSessionSummary } from "./broker/types.js";
|
|
3
3
|
import type { PinetReadOptions, PinetReadResult } from "@pinet/pinet-core/pinet-read-formatting";
|
|
4
4
|
import { type InboxMessage, type PinetControlCommand, type PinetRemoteControlRequestResult, type SlackBridgeSettings } from "./helpers.js";
|
|
5
|
+
import type { BrokerDB } from "./broker/schema.js";
|
|
5
6
|
export interface SubtreeBrokerPaths {
|
|
6
7
|
rootDir: string;
|
|
7
8
|
socketPath: string;
|
|
8
9
|
dbPath: string;
|
|
9
10
|
lockPath: string;
|
|
10
11
|
}
|
|
11
|
-
export
|
|
12
|
-
|
|
12
|
+
export type WorkerRuntimeSpec = {
|
|
13
|
+
runtimeKind: "tmux";
|
|
14
|
+
sessionName: string;
|
|
15
|
+
tmuxSocketPath: string | null;
|
|
16
|
+
} | {
|
|
17
|
+
runtimeKind: "herdr";
|
|
13
18
|
sessionName: string;
|
|
19
|
+
herdrSession: string;
|
|
20
|
+
herdrConfigDir: string;
|
|
21
|
+
herdrPaneId: string | null;
|
|
22
|
+
herdrShellPid: number | null;
|
|
23
|
+
};
|
|
24
|
+
type HerdrWorkerRuntimeSpec = Extract<WorkerRuntimeSpec, {
|
|
25
|
+
runtimeKind: "herdr";
|
|
26
|
+
}>;
|
|
27
|
+
export type SubtreeWorkerRecord = WorkerRuntimeSpec & {
|
|
28
|
+
launchId: string;
|
|
14
29
|
repoPath: string;
|
|
15
30
|
role: string;
|
|
16
31
|
laneId: string | null;
|
|
17
32
|
agentId: string | null;
|
|
18
33
|
startedAt: string;
|
|
19
34
|
monitorCommand: string;
|
|
35
|
+
};
|
|
36
|
+
interface WorkerRuntimeController<T extends WorkerRuntimeSpec> {
|
|
37
|
+
createLaunchSpec: (sessionName: string) => T;
|
|
38
|
+
monitorCommand: (spec: T) => string;
|
|
39
|
+
launch: (spec: T, launcherPath: string, launchEnv: Record<string, string>, onRuntimeOwned?: (spec: T) => void) => Promise<void>;
|
|
40
|
+
cleanup: (spec: T) => Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export interface HerdrCommandOptions {
|
|
43
|
+
env: NodeJS.ProcessEnv;
|
|
44
|
+
detached?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export type HerdrCommandRunner = (args: string[], options: HerdrCommandOptions) => Promise<string>;
|
|
47
|
+
export interface HerdrWorkerRuntimeControllerOptions {
|
|
48
|
+
herdrSession: string;
|
|
49
|
+
herdrConfigDir: string;
|
|
20
50
|
}
|
|
21
51
|
export interface SubtreeBrokerStatus {
|
|
22
52
|
active: boolean;
|
|
@@ -50,16 +80,34 @@ export interface SubtreeAgentRecord {
|
|
|
50
80
|
subtreeRole?: string | null;
|
|
51
81
|
laneId?: string | null;
|
|
52
82
|
}
|
|
83
|
+
export interface SubtreeSpawnLaunchHandle {
|
|
84
|
+
launchId: string;
|
|
85
|
+
tmuxSessionName: string;
|
|
86
|
+
socketPath: string;
|
|
87
|
+
state: "launched_unregistered";
|
|
88
|
+
runtimeKind?: WorkerRuntimeSpec["runtimeKind"];
|
|
89
|
+
monitorCommand?: string;
|
|
90
|
+
}
|
|
91
|
+
export declare class SubtreeSpawnRegistrationTimeoutError extends Error {
|
|
92
|
+
readonly handle: SubtreeSpawnLaunchHandle;
|
|
93
|
+
constructor(timeoutMs: number, handle: SubtreeSpawnLaunchHandle);
|
|
94
|
+
}
|
|
95
|
+
export declare class SubtreeSpawnLaunchError extends Error {
|
|
96
|
+
readonly handle: SubtreeSpawnLaunchHandle;
|
|
97
|
+
constructor(error: Error, handle: SubtreeSpawnLaunchHandle, runtimeKind?: WorkerRuntimeSpec["runtimeKind"]);
|
|
98
|
+
}
|
|
53
99
|
export interface SubtreeSpawnInput {
|
|
54
100
|
task: string;
|
|
55
101
|
repo: string;
|
|
56
102
|
role?: string;
|
|
57
103
|
laneId?: string;
|
|
58
104
|
waitForRegistrationMs?: number;
|
|
105
|
+
cleanupHandle?: SubtreeSpawnLaunchHandle;
|
|
59
106
|
}
|
|
60
107
|
export interface SubtreeSpawnResult {
|
|
61
108
|
status: "started";
|
|
62
109
|
launchId: string;
|
|
110
|
+
runtimeKind: WorkerRuntimeSpec["runtimeKind"];
|
|
63
111
|
sessionName: string;
|
|
64
112
|
repoPath: string;
|
|
65
113
|
role: string;
|
|
@@ -85,19 +133,43 @@ export interface SubtreeBrokerRuntimeDeps {
|
|
|
85
133
|
getAgentMetadata: (role: "broker" | "worker") => Promise<Record<string, unknown>>;
|
|
86
134
|
getMeshRoleFromMetadata: (metadata: Record<string, unknown> | undefined, fallback?: "broker" | "worker") => "broker" | "worker";
|
|
87
135
|
pushInboxMessages: (messages: InboxMessage[]) => void;
|
|
136
|
+
discardQueuedInboxMessages: () => void;
|
|
88
137
|
updateBadge: () => void;
|
|
89
138
|
maybeDrainInboxIfIdle: (ctx: ExtensionContext) => boolean;
|
|
139
|
+
deliverSteeringMessage: (text: string, ctx: ExtensionContext) => boolean;
|
|
90
140
|
requestRemoteControl: (command: PinetControlCommand, ctx: ExtensionContext) => PinetRemoteControlRequestResult;
|
|
91
141
|
runRemoteControl: (command: PinetControlCommand, ctx: ExtensionContext) => void;
|
|
92
142
|
formatError: (error: unknown) => string;
|
|
143
|
+
runTmuxCommand?: (args: string[]) => Promise<void>;
|
|
144
|
+
runHerdrCommand?: HerdrCommandRunner;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The authoritative hibernation runtime surface for this process's subtree
|
|
148
|
+
* broker. The subtree broker is the authority that spawns and OWNS its workers
|
|
149
|
+
* and authors their durable runtime specs, so hibernate/wake must resolve the
|
|
150
|
+
* target, read its authz spec, and drive the orchestrator against THIS same
|
|
151
|
+
* authoritative DB end to end. The explicit trust boundary: the operator command
|
|
152
|
+
* may only address workers this subtree broker owns. Null when no subtree broker
|
|
153
|
+
* is running (nothing is command-addressable).
|
|
154
|
+
*/
|
|
155
|
+
export interface SubtreeHibernationRuntimeControl {
|
|
156
|
+
/** The single authoritative DB that owns the spawned workers + their specs. */
|
|
157
|
+
db: BrokerDB;
|
|
158
|
+
/** Broker instance id recorded on lifecycle leases; matches startup recovery. */
|
|
159
|
+
brokerInstanceId: string;
|
|
160
|
+
/** Base PINET_* env re-establishing the mesh connection for a woken worker. */
|
|
161
|
+
baseLaunchEnv: Record<string, string>;
|
|
93
162
|
}
|
|
94
163
|
export interface SubtreeBrokerRuntime {
|
|
95
164
|
start: (ctx: ExtensionContext) => Promise<SubtreeBrokerStatus>;
|
|
165
|
+
getHibernationRuntimeControl: () => SubtreeHibernationRuntimeControl | null;
|
|
96
166
|
stop: (options?: {
|
|
97
167
|
releaseIdentity?: boolean;
|
|
98
168
|
stopChildren?: boolean;
|
|
99
169
|
}) => Promise<void>;
|
|
100
170
|
getStatus: () => SubtreeBrokerStatus;
|
|
171
|
+
drainInbox: (ctx: ExtensionContext) => void;
|
|
172
|
+
markDelivered: (inboxIds: number[]) => void;
|
|
101
173
|
readInbox: (options?: PinetReadOptions) => PinetReadResult | null;
|
|
102
174
|
sendMessage: (target: string, body: string, metadata?: Record<string, unknown>) => Promise<{
|
|
103
175
|
messageId: number;
|
|
@@ -109,4 +181,13 @@ export interface SubtreeBrokerRuntime {
|
|
|
109
181
|
isActive: () => boolean;
|
|
110
182
|
}
|
|
111
183
|
export declare function buildSubtreeBrokerPaths(stableId: string): SubtreeBrokerPaths;
|
|
184
|
+
export declare function createHerdrWorkerRuntimeController(runHerdrCommand: HerdrCommandRunner, options: HerdrWorkerRuntimeControllerOptions): WorkerRuntimeController<HerdrWorkerRuntimeSpec>;
|
|
185
|
+
export declare function getExtensionEntryPath(): string;
|
|
186
|
+
/**
|
|
187
|
+
* Broker env var NAMES (never values) a spawned — or later WOKEN — worker
|
|
188
|
+
* re-exports to re-establish itself. Single source of truth shared by the
|
|
189
|
+
* ordinary spawn launcher and the Phase B wake path so both stay in lockstep.
|
|
190
|
+
*/
|
|
191
|
+
export declare const SUBTREE_INHERITED_ENV_KEYS: string[];
|
|
112
192
|
export declare function createSubtreeBrokerRuntime(deps: SubtreeBrokerRuntimeDeps): SubtreeBrokerRuntime;
|
|
193
|
+
export {};
|