@urateam/core 0.1.31 → 0.1.33
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/__tests__/agent-stream.test.js +35 -1
- package/dist/__tests__/agent-stream.test.js.map +1 -1
- package/dist/__tests__/audit-immutability.test.js +7 -1
- package/dist/__tests__/audit-immutability.test.js.map +1 -1
- package/dist/__tests__/auth-monitor.test.d.ts +2 -0
- package/dist/__tests__/auth-monitor.test.d.ts.map +1 -0
- package/dist/__tests__/auth-monitor.test.js +253 -0
- package/dist/__tests__/auth-monitor.test.js.map +1 -0
- package/dist/__tests__/bec-186-repro.test.d.ts +16 -0
- package/dist/__tests__/bec-186-repro.test.d.ts.map +1 -0
- package/dist/__tests__/bec-186-repro.test.js +223 -0
- package/dist/__tests__/bec-186-repro.test.js.map +1 -0
- package/dist/__tests__/control-signals.test.d.ts +2 -0
- package/dist/__tests__/control-signals.test.d.ts.map +1 -0
- package/dist/__tests__/control-signals.test.js +77 -0
- package/dist/__tests__/control-signals.test.js.map +1 -0
- package/dist/__tests__/db-migrations.test.d.ts +2 -0
- package/dist/__tests__/db-migrations.test.d.ts.map +1 -0
- package/dist/__tests__/db-migrations.test.js +237 -0
- package/dist/__tests__/db-migrations.test.js.map +1 -0
- package/dist/__tests__/executor-issue-id.test.js +2 -0
- package/dist/__tests__/executor-issue-id.test.js.map +1 -1
- package/dist/__tests__/pm-slack-interface.test.js +45 -0
- package/dist/__tests__/pm-slack-interface.test.js.map +1 -1
- package/dist/__tests__/pm-triage.test.js +101 -0
- package/dist/__tests__/pm-triage.test.js.map +1 -1
- package/dist/__tests__/post-fanout-comments.test.js +36 -0
- package/dist/__tests__/post-fanout-comments.test.js.map +1 -1
- package/dist/__tests__/preflight-claude-auth.test.d.ts +2 -0
- package/dist/__tests__/preflight-claude-auth.test.d.ts.map +1 -0
- package/dist/__tests__/preflight-claude-auth.test.js +36 -0
- package/dist/__tests__/preflight-claude-auth.test.js.map +1 -0
- package/dist/__tests__/resolve-claude-auth.test.d.ts +2 -0
- package/dist/__tests__/resolve-claude-auth.test.d.ts.map +1 -0
- package/dist/__tests__/resolve-claude-auth.test.js +129 -0
- package/dist/__tests__/resolve-claude-auth.test.js.map +1 -0
- package/dist/__tests__/stage-models.test.js +4 -0
- package/dist/__tests__/stage-models.test.js.map +1 -1
- package/dist/__tests__/util-linear.test.d.ts +10 -0
- package/dist/__tests__/util-linear.test.d.ts.map +1 -0
- package/dist/__tests__/util-linear.test.js +244 -0
- package/dist/__tests__/util-linear.test.js.map +1 -0
- package/dist/audit/events.d.ts +37 -0
- package/dist/audit/events.d.ts.map +1 -1
- package/dist/audit/events.js +53 -0
- package/dist/audit/events.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +8 -0
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrations/postgres/014_missing_indexes.sql +28 -0
- package/dist/db/migrations/sqlite/013_missing_indexes.sql +28 -0
- package/dist/executor/agent-stream.d.ts +16 -0
- package/dist/executor/agent-stream.d.ts.map +1 -1
- package/dist/executor/agent-stream.js +43 -1
- package/dist/executor/agent-stream.js.map +1 -1
- package/dist/executor/auth-check.d.ts +39 -0
- package/dist/executor/auth-check.d.ts.map +1 -1
- package/dist/executor/auth-check.js +31 -0
- package/dist/executor/auth-check.js.map +1 -1
- package/dist/executor/auth-monitor.d.ts +40 -0
- package/dist/executor/auth-monitor.d.ts.map +1 -0
- package/dist/executor/auth-monitor.js +114 -0
- package/dist/executor/auth-monitor.js.map +1 -0
- package/dist/executor/executor.d.ts.map +1 -1
- package/dist/executor/executor.js +7 -2
- package/dist/executor/executor.js.map +1 -1
- package/dist/executor/index.d.ts +2 -0
- package/dist/executor/index.d.ts.map +1 -1
- package/dist/executor/index.js +2 -0
- package/dist/executor/index.js.map +1 -1
- package/dist/executor/review/post-fanout-comments.d.ts +8 -0
- package/dist/executor/review/post-fanout-comments.d.ts.map +1 -1
- package/dist/executor/review/post-fanout-comments.js +23 -3
- package/dist/executor/review/post-fanout-comments.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/notifier/composite.d.ts +1 -0
- package/dist/notifier/composite.d.ts.map +1 -1
- package/dist/notifier/composite.js +3 -0
- package/dist/notifier/composite.js.map +1 -1
- package/dist/notifier/linear.d.ts +1 -0
- package/dist/notifier/linear.d.ts.map +1 -1
- package/dist/notifier/linear.js +7 -0
- package/dist/notifier/linear.js.map +1 -1
- package/dist/pipeline/control-signals.d.ts +49 -0
- package/dist/pipeline/control-signals.d.ts.map +1 -0
- package/dist/pipeline/control-signals.js +93 -0
- package/dist/pipeline/control-signals.js.map +1 -0
- package/dist/pipeline/feedback-pipeline.d.ts +140 -0
- package/dist/pipeline/feedback-pipeline.d.ts.map +1 -0
- package/dist/pipeline/feedback-pipeline.js +427 -0
- package/dist/pipeline/feedback-pipeline.js.map +1 -0
- package/dist/pipeline/index.d.ts +1 -0
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +1 -0
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/runner.d.ts +49 -33
- package/dist/pipeline/runner.d.ts.map +1 -1
- package/dist/pipeline/runner.js +143 -350
- package/dist/pipeline/runner.js.map +1 -1
- package/dist/pm/actions/promote.d.ts.map +1 -1
- package/dist/pm/actions/promote.js +15 -11
- package/dist/pm/actions/promote.js.map +1 -1
- package/dist/pm/actions/recover-stuck.d.ts.map +1 -1
- package/dist/pm/actions/recover-stuck.js +9 -5
- package/dist/pm/actions/recover-stuck.js.map +1 -1
- package/dist/pm/actions/triage.d.ts.map +1 -1
- package/dist/pm/actions/triage.js +67 -1
- package/dist/pm/actions/triage.js.map +1 -1
- package/dist/pm/linear-helpers.d.ts +10 -0
- package/dist/pm/linear-helpers.d.ts.map +1 -1
- package/dist/pm/linear-helpers.js +13 -21
- package/dist/pm/linear-helpers.js.map +1 -1
- package/dist/pm/pause-state.d.ts +29 -0
- package/dist/pm/pause-state.d.ts.map +1 -0
- package/dist/pm/pause-state.js +34 -0
- package/dist/pm/pause-state.js.map +1 -0
- package/dist/pm/scheduler.d.ts.map +1 -1
- package/dist/pm/scheduler.js +19 -0
- package/dist/pm/scheduler.js.map +1 -1
- package/dist/pm/slack-bulk.d.ts +34 -0
- package/dist/pm/slack-bulk.d.ts.map +1 -0
- package/dist/pm/slack-bulk.js +110 -0
- package/dist/pm/slack-bulk.js.map +1 -0
- package/dist/pm/slack-commands.d.ts +101 -0
- package/dist/pm/slack-commands.d.ts.map +1 -0
- package/dist/pm/slack-commands.js +309 -0
- package/dist/pm/slack-commands.js.map +1 -0
- package/dist/pm/slack-helpers.d.ts +10 -0
- package/dist/pm/slack-helpers.d.ts.map +1 -1
- package/dist/pm/slack-helpers.js +32 -0
- package/dist/pm/slack-helpers.js.map +1 -1
- package/dist/pm/slack-interface.d.ts +32 -58
- package/dist/pm/slack-interface.d.ts.map +1 -1
- package/dist/pm/slack-interface.js +150 -320
- package/dist/pm/slack-interface.js.map +1 -1
- package/dist/rbac/matrix.d.ts +2 -0
- package/dist/rbac/matrix.d.ts.map +1 -1
- package/dist/rbac/matrix.js +2 -0
- package/dist/rbac/matrix.js.map +1 -1
- package/dist/release-manager/index.d.ts +2 -0
- package/dist/release-manager/index.d.ts.map +1 -1
- package/dist/release-manager/index.js +2 -0
- package/dist/release-manager/index.js.map +1 -1
- package/dist/release-manager/release-helpers.d.ts +112 -0
- package/dist/release-manager/release-helpers.d.ts.map +1 -0
- package/dist/release-manager/release-helpers.js +164 -0
- package/dist/release-manager/release-helpers.js.map +1 -0
- package/dist/release-manager/release-tick.d.ts +101 -0
- package/dist/release-manager/release-tick.d.ts.map +1 -0
- package/dist/release-manager/release-tick.js +374 -0
- package/dist/release-manager/release-tick.js.map +1 -0
- package/dist/release-manager/scheduler.d.ts +28 -3
- package/dist/release-manager/scheduler.d.ts.map +1 -1
- package/dist/release-manager/scheduler.js +41 -417
- package/dist/release-manager/scheduler.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -0
- package/dist/server.js.map +1 -1
- package/dist/sync/gh-linear-sync.d.ts.map +1 -1
- package/dist/sync/gh-linear-sync.js +2 -2
- package/dist/sync/gh-linear-sync.js.map +1 -1
- package/dist/types.d.ts +22 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -1
- package/dist/util/linear.d.ts +70 -0
- package/dist/util/linear.d.ts.map +1 -0
- package/dist/util/linear.js +108 -0
- package/dist/util/linear.js.map +1 -0
- package/dist/webhook/github-handler.d.ts +7 -1
- package/dist/webhook/github-handler.d.ts.map +1 -1
- package/dist/webhook/github-handler.js +82 -38
- package/dist/webhook/github-handler.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PM Agent — Slack command execution.
|
|
3
|
+
*
|
|
4
|
+
* Responsibility: execute a parsed `PmCommand` against the Linear API and return
|
|
5
|
+
* a human-readable response string suitable for posting back to Slack.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from `slack-interface.ts` (BEC-195). The previous implementation
|
|
8
|
+
* accessed `isPmPaused` / `setPmPaused` as module-level closures within
|
|
9
|
+
* `slack-interface.ts`. After the split those functions live in `pause-state.ts`
|
|
10
|
+
* and are imported explicitly here, making the dependency transparent and
|
|
11
|
+
* avoiding a circular import (slack-interface → slack-commands → slack-interface).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Structured representation of a PM command parsed from Slack text.
|
|
15
|
+
* This type lives here (rather than in `slack-interface.ts`) so that
|
|
16
|
+
* `executePmCommand` owns the shape of the data it operates on, and
|
|
17
|
+
* `slack-interface.ts` can import it without creating a circular dependency.
|
|
18
|
+
*/
|
|
19
|
+
export type PmCommand = {
|
|
20
|
+
type: "prioritize";
|
|
21
|
+
issueId: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: "create";
|
|
24
|
+
title: string;
|
|
25
|
+
description: string;
|
|
26
|
+
} | {
|
|
27
|
+
type: "bulk_create";
|
|
28
|
+
request: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: "status";
|
|
31
|
+
} | {
|
|
32
|
+
type: "pause";
|
|
33
|
+
} | {
|
|
34
|
+
type: "resume";
|
|
35
|
+
} | {
|
|
36
|
+
type: "assign";
|
|
37
|
+
issueId: string;
|
|
38
|
+
}
|
|
39
|
+
/** Operator-initiated stop. `runId` is a pipeline_runs row id (nanoid). */
|
|
40
|
+
| {
|
|
41
|
+
type: "cancel";
|
|
42
|
+
runId: string;
|
|
43
|
+
} | {
|
|
44
|
+
type: "stop";
|
|
45
|
+
runId: string;
|
|
46
|
+
} | {
|
|
47
|
+
type: "halt";
|
|
48
|
+
} | {
|
|
49
|
+
type: "unknown";
|
|
50
|
+
original: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* External dependencies injected into `executePmCommand`.
|
|
54
|
+
* All fields are optional so callers can pass a partial object during testing.
|
|
55
|
+
*/
|
|
56
|
+
export interface CommandExecutorDeps {
|
|
57
|
+
/** Linear API key (needed for create / prioritize / assign commands). */
|
|
58
|
+
linearApiKey?: string;
|
|
59
|
+
/** Team IDs for issue creation commands. */
|
|
60
|
+
teamIds?: string[];
|
|
61
|
+
/** Sonnet-model callable required for the `bulk_create` command. */
|
|
62
|
+
callClaudeSonnet?: (prompt: string) => Promise<string>;
|
|
63
|
+
/**
|
|
64
|
+
* Reference to the live pipeline runner. Required for `cancel`/`stop`/`halt`
|
|
65
|
+
* commands; if absent, those commands report a clear configuration error
|
|
66
|
+
* rather than silently succeeding.
|
|
67
|
+
*/
|
|
68
|
+
runner?: {
|
|
69
|
+
requestStop?: (runId: string, mode: "cancel" | "graceful") => {
|
|
70
|
+
issueId: string | null;
|
|
71
|
+
mode: "cancel" | "graceful";
|
|
72
|
+
};
|
|
73
|
+
haltAll?: () => {
|
|
74
|
+
cancelledRunIds: string[];
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
/** DB handle for audit-event writes. */
|
|
78
|
+
db?: any;
|
|
79
|
+
/** Slack user id (e.g. "U123") for audit attribution. */
|
|
80
|
+
slackUserId?: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Executes a parsed `PmCommand` against Linear and returns a human-readable
|
|
84
|
+
* response string suitable for posting back to Slack.
|
|
85
|
+
*
|
|
86
|
+
* Design note — implicit state access: the `pause` / `resume` / `status`
|
|
87
|
+
* command cases call `isPmPaused()` and `setPmPaused()` from `pause-state.ts`.
|
|
88
|
+
* These functions are now explicit imports rather than closures over outer module
|
|
89
|
+
* state (as they were when this logic lived in `slack-interface.ts`). The
|
|
90
|
+
* dependency is intentional and transparent — the pause flag is process-scoped
|
|
91
|
+
* shared state that must be the same instance for both command execution and the
|
|
92
|
+
* scheduler's `isPmPaused()` check.
|
|
93
|
+
*
|
|
94
|
+
* @param cmd - A structured `PmCommand` (output of `parsePmCommand` or
|
|
95
|
+
* `interpretNaturalLanguage`).
|
|
96
|
+
* @param deps - External service dependencies (Linear API key, team IDs,
|
|
97
|
+
* optional Sonnet callable for bulk create).
|
|
98
|
+
* @returns A Slack-formatted response string (may contain mrkdwn markup).
|
|
99
|
+
*/
|
|
100
|
+
export declare function executePmCommand(cmd: PmCommand, deps: CommandExecutorDeps): Promise<string>;
|
|
101
|
+
//# sourceMappingURL=slack-commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-commands.d.ts","sourceRoot":"","sources":["../../src/pm/slack-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwBH;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AACrC,2EAA2E;GACzE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAe1C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD;;;;OAIG;IACH,MAAM,CAAC,EAAE;QACP,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,UAAU,KAAK;YAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;YAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAA;SAAE,CAAC;QACtH,OAAO,CAAC,EAAE,MAAM;YAAE,eAAe,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC;KAC/C,CAAC;IACF,wCAAwC;IACxC,EAAE,CAAC,EAAE,GAAG,CAAC;IACT,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA+BD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,MAAM,CAAC,CA2PjB"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PM Agent — Slack command execution.
|
|
3
|
+
*
|
|
4
|
+
* Responsibility: execute a parsed `PmCommand` against the Linear API and return
|
|
5
|
+
* a human-readable response string suitable for posting back to Slack.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from `slack-interface.ts` (BEC-195). The previous implementation
|
|
8
|
+
* accessed `isPmPaused` / `setPmPaused` as module-level closures within
|
|
9
|
+
* `slack-interface.ts`. After the split those functions live in `pause-state.ts`
|
|
10
|
+
* and are imported explicitly here, making the dependency transparent and
|
|
11
|
+
* avoiding a circular import (slack-interface → slack-commands → slack-interface).
|
|
12
|
+
*/
|
|
13
|
+
import { createLogger } from "../logger.js";
|
|
14
|
+
import { createLazyLinearClient } from "./linear-helpers.js";
|
|
15
|
+
import { analyzeBulkCreateRequest } from "./slack-bulk.js";
|
|
16
|
+
import { isPmPaused, setPmPaused } from "./pause-state.js";
|
|
17
|
+
const log = createLogger({ component: "PmAgent:slack-commands" });
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Constants
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/** Linear workflow state name for the Triage column. */
|
|
22
|
+
const LINEAR_STATE_TRIAGE = "Triage";
|
|
23
|
+
/** Linear workflow state name for the Todo column. */
|
|
24
|
+
const LINEAR_STATE_TODO = "Todo";
|
|
25
|
+
/** Linear label name that triggers the auto-implement pipeline. */
|
|
26
|
+
const LINEAR_LABEL_AUTO_IMPLEMENT = "auto-implement";
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Private validation helpers
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
/**
|
|
31
|
+
* Returns an error message string when `deps.linearApiKey` is missing or empty,
|
|
32
|
+
* or `null` when a key is present. Callers should check and return early:
|
|
33
|
+
* const err = validateLinearApiKey(deps); if (err) return err;
|
|
34
|
+
*/
|
|
35
|
+
function validateLinearApiKey(deps) {
|
|
36
|
+
return deps.linearApiKey
|
|
37
|
+
? null
|
|
38
|
+
: `⚠️ No Linear API key configured — please set \`linearApiKey\` in your PM Agent config.`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns an error message string when `deps.teamIds` is missing or empty,
|
|
42
|
+
* or `null` when team IDs are present.
|
|
43
|
+
*/
|
|
44
|
+
function validateTeamIds(deps) {
|
|
45
|
+
return deps.teamIds && deps.teamIds.length > 0
|
|
46
|
+
? null
|
|
47
|
+
: `⚠️ No team IDs configured — please set \`teamIds\` in your PM Agent config.`;
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Public API
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Executes a parsed `PmCommand` against Linear and returns a human-readable
|
|
54
|
+
* response string suitable for posting back to Slack.
|
|
55
|
+
*
|
|
56
|
+
* Design note — implicit state access: the `pause` / `resume` / `status`
|
|
57
|
+
* command cases call `isPmPaused()` and `setPmPaused()` from `pause-state.ts`.
|
|
58
|
+
* These functions are now explicit imports rather than closures over outer module
|
|
59
|
+
* state (as they were when this logic lived in `slack-interface.ts`). The
|
|
60
|
+
* dependency is intentional and transparent — the pause flag is process-scoped
|
|
61
|
+
* shared state that must be the same instance for both command execution and the
|
|
62
|
+
* scheduler's `isPmPaused()` check.
|
|
63
|
+
*
|
|
64
|
+
* @param cmd - A structured `PmCommand` (output of `parsePmCommand` or
|
|
65
|
+
* `interpretNaturalLanguage`).
|
|
66
|
+
* @param deps - External service dependencies (Linear API key, team IDs,
|
|
67
|
+
* optional Sonnet callable for bulk create).
|
|
68
|
+
* @returns A Slack-formatted response string (may contain mrkdwn markup).
|
|
69
|
+
*/
|
|
70
|
+
export async function executePmCommand(cmd, deps) {
|
|
71
|
+
const { getClient: getLinear } = createLazyLinearClient(deps.linearApiKey);
|
|
72
|
+
/**
|
|
73
|
+
* Searches Linear for an issue by its identifier (e.g. "BEC-25") and returns
|
|
74
|
+
* the first match, or `null` when not found. Shared by prioritize + assign.
|
|
75
|
+
*/
|
|
76
|
+
async function findIssueByIdentifier(linear, issueId) {
|
|
77
|
+
const results = await linear.searchIssues(issueId);
|
|
78
|
+
return results.nodes?.[0] ?? null;
|
|
79
|
+
}
|
|
80
|
+
switch (cmd.type) {
|
|
81
|
+
case "status": {
|
|
82
|
+
const state = isPmPaused() ? "⏸ *Paused*" : "▶️ *Running*";
|
|
83
|
+
return `PM Agent is ${state}.\nUse \`/pm pause\` or \`/pm resume\` to control autonomous assignment.`;
|
|
84
|
+
}
|
|
85
|
+
case "pause": {
|
|
86
|
+
setPmPaused(true);
|
|
87
|
+
log.info("PM Agent paused via Slack");
|
|
88
|
+
return "⏸ PM Agent autonomous assignment has been *paused*. Use `/pm resume` to restart.";
|
|
89
|
+
}
|
|
90
|
+
case "resume": {
|
|
91
|
+
setPmPaused(false);
|
|
92
|
+
log.info("PM Agent resumed via Slack");
|
|
93
|
+
return "▶️ PM Agent autonomous assignment has been *resumed*.";
|
|
94
|
+
}
|
|
95
|
+
case "cancel":
|
|
96
|
+
case "stop": {
|
|
97
|
+
if (!deps.runner?.requestStop) {
|
|
98
|
+
return `⚠️ Runner not configured — cannot ${cmd.type} run *${cmd.runId}*.`;
|
|
99
|
+
}
|
|
100
|
+
const mode = cmd.type === "cancel" ? "cancel" : "graceful";
|
|
101
|
+
const { issueId } = deps.runner.requestStop(cmd.runId, mode);
|
|
102
|
+
if (deps.db) {
|
|
103
|
+
const { logAuditEvent, runCancelledEvent } = await import("../audit/index.js");
|
|
104
|
+
void logAuditEvent(deps.db, runCancelledEvent({
|
|
105
|
+
runId: cmd.runId,
|
|
106
|
+
issueId: issueId ?? "(unknown)",
|
|
107
|
+
actor: `slack:${deps.slackUserId ?? "unknown"}`,
|
|
108
|
+
actorType: "slack",
|
|
109
|
+
mode,
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
log.info({ runId: cmd.runId, mode, slackUserId: deps.slackUserId }, "run stop requested via Slack");
|
|
113
|
+
return mode === "cancel"
|
|
114
|
+
? `🛑 Cancel signal sent to run *${cmd.runId}*. The active stage will abort within a few seconds.`
|
|
115
|
+
: `⏹ Graceful stop requested for run *${cmd.runId}*. The current stage will finish, then the pipeline will stop.`;
|
|
116
|
+
}
|
|
117
|
+
case "halt": {
|
|
118
|
+
if (!deps.runner?.haltAll) {
|
|
119
|
+
return "⚠️ Runner not configured — cannot halt.";
|
|
120
|
+
}
|
|
121
|
+
const { cancelledRunIds } = deps.runner.haltAll();
|
|
122
|
+
if (deps.db) {
|
|
123
|
+
const { logAuditEvent, systemHaltedEvent, runCancelledEvent } = await import("../audit/index.js");
|
|
124
|
+
void logAuditEvent(deps.db, systemHaltedEvent({
|
|
125
|
+
actor: `slack:${deps.slackUserId ?? "unknown"}`,
|
|
126
|
+
actorType: "slack",
|
|
127
|
+
cancelledRunIds,
|
|
128
|
+
}));
|
|
129
|
+
for (const rid of cancelledRunIds) {
|
|
130
|
+
void logAuditEvent(deps.db, runCancelledEvent({
|
|
131
|
+
runId: rid,
|
|
132
|
+
issueId: "(halt)",
|
|
133
|
+
actor: `slack:${deps.slackUserId ?? "unknown"}`,
|
|
134
|
+
actorType: "slack",
|
|
135
|
+
mode: "cancel",
|
|
136
|
+
reason: "system.halt",
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
log.warn({ count: cancelledRunIds.length, slackUserId: deps.slackUserId }, "container halt requested via Slack");
|
|
141
|
+
return `🚨 *Halted.* PM Agent paused; cancelled ${cancelledRunIds.length} active run(s). Use \`/pm resume\` when ready.`;
|
|
142
|
+
}
|
|
143
|
+
case "prioritize": {
|
|
144
|
+
const keyErr = validateLinearApiKey(deps);
|
|
145
|
+
if (keyErr)
|
|
146
|
+
return keyErr;
|
|
147
|
+
try {
|
|
148
|
+
const linear = await getLinear();
|
|
149
|
+
if (!linear)
|
|
150
|
+
return `⚠️ Linear client could not be initialised — cannot prioritize *${cmd.issueId}*.`;
|
|
151
|
+
const issue = await findIssueByIdentifier(linear, cmd.issueId);
|
|
152
|
+
if (!issue)
|
|
153
|
+
return `⚠️ Issue *${cmd.issueId}* not found in Linear.`;
|
|
154
|
+
// updateIssue and createComment are independent — run in parallel
|
|
155
|
+
await Promise.all([
|
|
156
|
+
linear.updateIssue(issue.id, { priority: 1 }),
|
|
157
|
+
linear.createComment({
|
|
158
|
+
issueId: issue.id,
|
|
159
|
+
body: "🤖 **PM Agent** — Bumped to top of queue via Slack command.",
|
|
160
|
+
}),
|
|
161
|
+
]);
|
|
162
|
+
log.info({ issueId: cmd.issueId }, "prioritized via Slack");
|
|
163
|
+
return `✅ *${cmd.issueId}* has been bumped to top priority (Urgent).`;
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
log.error({ err, issueId: cmd.issueId }, "prioritize failed");
|
|
167
|
+
return `❌ Failed to prioritize *${cmd.issueId}*: ${err.message}`;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
case "assign": {
|
|
171
|
+
const keyErr = validateLinearApiKey(deps);
|
|
172
|
+
if (keyErr)
|
|
173
|
+
return keyErr;
|
|
174
|
+
try {
|
|
175
|
+
const linear = await getLinear();
|
|
176
|
+
if (!linear)
|
|
177
|
+
return `⚠️ Linear client could not be initialised — cannot assign *${cmd.issueId}*.`;
|
|
178
|
+
const issue = await findIssueByIdentifier(linear, cmd.issueId);
|
|
179
|
+
if (!issue)
|
|
180
|
+
return `⚠️ Issue *${cmd.issueId}* not found in Linear.`;
|
|
181
|
+
const team = await issue.team;
|
|
182
|
+
const allStates = await linear.workflowStates({
|
|
183
|
+
filter: { team: { id: { eq: team?.id } } },
|
|
184
|
+
first: 50,
|
|
185
|
+
});
|
|
186
|
+
const todoState = allStates.nodes?.find((s) => s.name === LINEAR_STATE_TODO);
|
|
187
|
+
if (!todoState)
|
|
188
|
+
return `⚠️ No "${LINEAR_STATE_TODO}" state found for *${cmd.issueId}*'s team.`;
|
|
189
|
+
await linear.updateIssue(issue.id, { stateId: todoState.id });
|
|
190
|
+
await linear.createComment({
|
|
191
|
+
issueId: issue.id,
|
|
192
|
+
body: "🤖 **PM Agent** — Manually assigned to Todo via Slack command.",
|
|
193
|
+
});
|
|
194
|
+
log.info({ issueId: cmd.issueId }, "manually assigned to Todo via Slack");
|
|
195
|
+
return `✅ *${cmd.issueId}* has been moved to Todo.`;
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
log.error({ err, issueId: cmd.issueId }, "assign failed");
|
|
199
|
+
return `❌ Failed to assign *${cmd.issueId}*: ${err.message}`;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
case "create": {
|
|
203
|
+
const keyErr = validateLinearApiKey(deps);
|
|
204
|
+
if (keyErr)
|
|
205
|
+
return keyErr;
|
|
206
|
+
const teamErr = validateTeamIds(deps);
|
|
207
|
+
if (teamErr)
|
|
208
|
+
return teamErr;
|
|
209
|
+
try {
|
|
210
|
+
const linear = await getLinear();
|
|
211
|
+
if (!linear)
|
|
212
|
+
return `⚠️ Linear client could not be initialised — cannot create issue.`;
|
|
213
|
+
const created = await linear.createIssue({
|
|
214
|
+
// deps.teamIds is guaranteed non-empty by validateTeamIds above.
|
|
215
|
+
teamId: deps.teamIds[0],
|
|
216
|
+
title: cmd.title,
|
|
217
|
+
description: cmd.description || undefined,
|
|
218
|
+
});
|
|
219
|
+
const issue = await created.issue;
|
|
220
|
+
const url = issue?.url ?? "";
|
|
221
|
+
log.info({ title: cmd.title, issueId: issue?.identifier }, "issue created via Slack");
|
|
222
|
+
return `✅ Created <${url}|${issue?.identifier ?? "new issue"}>: *${cmd.title}*`;
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
log.error({ err, title: cmd.title }, "create issue failed");
|
|
226
|
+
return `❌ Failed to create issue: ${err.message}`;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
case "bulk_create": {
|
|
230
|
+
const keyErr = validateLinearApiKey(deps);
|
|
231
|
+
if (keyErr)
|
|
232
|
+
return keyErr;
|
|
233
|
+
const teamErr = validateTeamIds(deps);
|
|
234
|
+
if (teamErr)
|
|
235
|
+
return teamErr;
|
|
236
|
+
if (!deps.callClaudeSonnet) {
|
|
237
|
+
return `⚠️ Bulk create requires a Sonnet model caller — not configured.`;
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
const specs = await analyzeBulkCreateRequest(cmd.request, deps.callClaudeSonnet);
|
|
241
|
+
if (specs.length === 0) {
|
|
242
|
+
return `🤔 Could not generate any issues from your request. Try being more specific.`;
|
|
243
|
+
}
|
|
244
|
+
const linear = await getLinear();
|
|
245
|
+
if (!linear)
|
|
246
|
+
return `⚠️ Linear client could not be initialised — cannot create issues.`;
|
|
247
|
+
// Resolve the Triage state and auto-implement label IDs.
|
|
248
|
+
// deps.teamIds is guaranteed non-empty by validateTeamIds above.
|
|
249
|
+
const teamId = deps.teamIds[0];
|
|
250
|
+
const [allStatesRes, allLabelsRes] = await Promise.all([
|
|
251
|
+
linear.workflowStates({ filter: { team: { id: { eq: teamId } } }, first: 50 }),
|
|
252
|
+
linear.issueLabels({ first: 100 }),
|
|
253
|
+
]);
|
|
254
|
+
const triageState = allStatesRes.nodes?.find((s) => s.name === LINEAR_STATE_TRIAGE);
|
|
255
|
+
const labelMap = new Map();
|
|
256
|
+
for (const label of allLabelsRes.nodes ?? []) {
|
|
257
|
+
labelMap.set(label.name.toLowerCase(), label.id);
|
|
258
|
+
}
|
|
259
|
+
const autoImplementLabelId = labelMap.get(LINEAR_LABEL_AUTO_IMPLEMENT);
|
|
260
|
+
// Build all payloads first, then create all issues in parallel
|
|
261
|
+
const payloads = specs.map((spec) => {
|
|
262
|
+
const descWithCriteria = spec.acceptanceCriteria.length > 0
|
|
263
|
+
? `${spec.description}\n\n**Acceptance Criteria:**\n${spec.acceptanceCriteria.map((c) => `- [ ] ${c}`).join("\n")}`
|
|
264
|
+
: spec.description;
|
|
265
|
+
const payload = {
|
|
266
|
+
teamId,
|
|
267
|
+
title: spec.title,
|
|
268
|
+
description: descWithCriteria || undefined,
|
|
269
|
+
priority: spec.priority,
|
|
270
|
+
};
|
|
271
|
+
if (triageState)
|
|
272
|
+
payload.stateId = triageState.id;
|
|
273
|
+
if (autoImplementLabelId)
|
|
274
|
+
payload.labelIds = [autoImplementLabelId];
|
|
275
|
+
return payload;
|
|
276
|
+
});
|
|
277
|
+
const results = await Promise.all(payloads.map((p) => linear.createIssue(p)));
|
|
278
|
+
const issueObjects = await Promise.all(results.map((r) => r.issue));
|
|
279
|
+
const created = [];
|
|
280
|
+
for (let i = 0; i < issueObjects.length; i++) {
|
|
281
|
+
const issue = issueObjects[i];
|
|
282
|
+
if (issue) {
|
|
283
|
+
const title = specs[i].title;
|
|
284
|
+
created.push({ identifier: issue.identifier ?? "", url: issue.url ?? "", title });
|
|
285
|
+
log.info({ issueId: issue.identifier, title }, "bulk issue created via Slack");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (created.length === 0) {
|
|
289
|
+
return `❌ Failed to create any issues.`;
|
|
290
|
+
}
|
|
291
|
+
const lines = [`✅ Created ${created.length} issue${created.length === 1 ? "" : "s"}:`];
|
|
292
|
+
for (const issue of created) {
|
|
293
|
+
const link = issue.url ? `<${issue.url}|${issue.identifier}>` : `*${issue.identifier}*`;
|
|
294
|
+
lines.push(`• ${link}: *${issue.title}*`);
|
|
295
|
+
}
|
|
296
|
+
return lines.join("\n");
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
log.error({ err, request: cmd.request }, "bulk create failed");
|
|
300
|
+
return `❌ Failed to create issues: ${err.message}`;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
case "unknown":
|
|
304
|
+
return `🤔 I didn't understand that. Try:\n• \`/pm status\`\n• \`/pm prioritize BEC-25\`\n• \`/pm create "title" "description"\`\n• \`/pm assign BEC-13\`\n• \`/pm pause\` / \`/pm resume\`\n• \`/pm cancel <runId>\` (interrupt immediately) / \`/pm stop <runId>\` (graceful)\n• \`/pm halt\` (pause PM + cancel all active runs)`;
|
|
305
|
+
default:
|
|
306
|
+
return `Unknown command.`;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=slack-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-commands.js","sourceRoot":"","sources":["../../src/pm/slack-commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
export declare function postSlackMessage(botToken: string, payload: object): Promise<any>;
|
|
2
|
+
/**
|
|
3
|
+
* React to a Slack message (or any thing that has a channel + ts) with the
|
|
4
|
+
* given emoji name (no surrounding colons). Fire-and-forget — failures are
|
|
5
|
+
* logged at info because they're best-effort UX and we never want a missed
|
|
6
|
+
* reaction to surface as a user-visible error.
|
|
7
|
+
*
|
|
8
|
+
* Slash commands have no `ts` to react to, so for those the caller uses
|
|
9
|
+
* `chat.postEphemeral` instead. See `postSlackEphemeral` below.
|
|
10
|
+
*/
|
|
11
|
+
export declare function reactToSlackMessage(botToken: string, channel: string, ts: string, emoji: string): Promise<void>;
|
|
2
12
|
//# sourceMappingURL=slack-helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-helpers.d.ts","sourceRoot":"","sources":["../../src/pm/slack-helpers.ts"],"names":[],"mappings":"AAGA,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAmBtF"}
|
|
1
|
+
{"version":3,"file":"slack-helpers.d.ts","sourceRoot":"","sources":["../../src/pm/slack-helpers.ts"],"names":[],"mappings":"AAGA,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAmBtF;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAqBf"}
|
package/dist/pm/slack-helpers.js
CHANGED
|
@@ -21,4 +21,36 @@ export async function postSlackMessage(botToken, payload) {
|
|
|
21
21
|
return null;
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* React to a Slack message (or any thing that has a channel + ts) with the
|
|
26
|
+
* given emoji name (no surrounding colons). Fire-and-forget — failures are
|
|
27
|
+
* logged at info because they're best-effort UX and we never want a missed
|
|
28
|
+
* reaction to surface as a user-visible error.
|
|
29
|
+
*
|
|
30
|
+
* Slash commands have no `ts` to react to, so for those the caller uses
|
|
31
|
+
* `chat.postEphemeral` instead. See `postSlackEphemeral` below.
|
|
32
|
+
*/
|
|
33
|
+
export async function reactToSlackMessage(botToken, channel, ts, emoji) {
|
|
34
|
+
try {
|
|
35
|
+
const resp = await fetch("https://slack.com/api/reactions.add", {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
Authorization: `Bearer ${botToken}`,
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify({ channel, timestamp: ts, name: emoji }),
|
|
42
|
+
});
|
|
43
|
+
const data = (await resp.json());
|
|
44
|
+
if (!data?.ok) {
|
|
45
|
+
// `already_reacted` is benign — operator re-mentioned the bot in the
|
|
46
|
+
// same thread. Other errors are worth logging for ops visibility.
|
|
47
|
+
const benign = data?.error === "already_reacted";
|
|
48
|
+
const level = benign ? "info" : "warn";
|
|
49
|
+
log[level]({ error: data?.error, channel, ts, emoji }, "Slack reactions.add returned ok:false");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
log.error({ err, channel, ts, emoji }, "Slack reactions.add failed");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
24
56
|
//# sourceMappingURL=slack-helpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-helpers.js","sourceRoot":"","sources":["../../src/pm/slack-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,OAAe;IACtE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,wCAAwC,EAAE;YACjE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,QAAQ,EAAE;aACpC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAS,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,0CAA0C,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,0BAA0B,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"slack-helpers.js","sourceRoot":"","sources":["../../src/pm/slack-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,OAAe;IACtE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,wCAAwC,EAAE;YACjE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,QAAQ,EAAE;aACpC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAS,CAAC;QACtC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,0CAA0C,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,0BAA0B,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,OAAe,EACf,EAAU,EACV,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,qCAAqC,EAAE;YAC9D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,QAAQ,EAAE;aACpC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAQ,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;YACd,qEAAqE;YACrE,kEAAkE;YAClE,MAAM,MAAM,GAAG,IAAI,EAAE,KAAK,KAAK,iBAAiB,CAAC;YACjD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;YACvC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,uCAAuC,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,4BAA4B,CAAC,CAAC;IACvE,CAAC;AACH,CAAC"}
|
|
@@ -7,8 +7,18 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Outbound helpers (call from PM scheduler):
|
|
9
9
|
* notifyAssigned, notifySkipped, askForClarification, postDailySummary
|
|
10
|
+
*
|
|
11
|
+
* This file retains: types, request parsing, Slack signature verification, the
|
|
12
|
+
* notifier class, and the Hono router factory. Command execution logic was
|
|
13
|
+
* extracted to `slack-commands.ts` (BEC-195) and bulk-create analysis to
|
|
14
|
+
* `slack-bulk.ts` (BEC-195). Both are re-exported here for backward
|
|
15
|
+
* compatibility so existing import sites do not need to change.
|
|
10
16
|
*/
|
|
11
17
|
import { Hono } from "hono";
|
|
18
|
+
import type { PmCommand } from "./slack-commands.js";
|
|
19
|
+
export { isPmPaused, setPmPaused } from "./pause-state.js";
|
|
20
|
+
export { type BulkIssueSpec, analyzeBulkCreateRequest } from "./slack-bulk.js";
|
|
21
|
+
export { type PmCommand, type CommandExecutorDeps, executePmCommand } from "./slack-commands.js";
|
|
12
22
|
export interface SlackInterfaceConfig {
|
|
13
23
|
/** Slack signing secret for request verification */
|
|
14
24
|
signingSecret: string;
|
|
@@ -32,30 +42,23 @@ export interface SlackInterfaceConfig {
|
|
|
32
42
|
text: string;
|
|
33
43
|
responseType: "ephemeral" | "in_channel";
|
|
34
44
|
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Live runner reference. Required for the `cancel`/`stop`/`halt` Slack
|
|
47
|
+
* commands. When absent, those commands report a clear configuration error
|
|
48
|
+
* instead of silently no-op'ing.
|
|
49
|
+
*/
|
|
50
|
+
runner?: {
|
|
51
|
+
requestStop?: (runId: string, mode: "cancel" | "graceful") => {
|
|
52
|
+
issueId: string | null;
|
|
53
|
+
mode: "cancel" | "graceful";
|
|
54
|
+
};
|
|
55
|
+
haltAll?: () => {
|
|
56
|
+
cancelledRunIds: string[];
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/** DB handle for audit-event writes from stop/halt commands. */
|
|
60
|
+
db?: any;
|
|
35
61
|
}
|
|
36
|
-
export type PmCommand = {
|
|
37
|
-
type: "prioritize";
|
|
38
|
-
issueId: string;
|
|
39
|
-
} | {
|
|
40
|
-
type: "create";
|
|
41
|
-
title: string;
|
|
42
|
-
description: string;
|
|
43
|
-
} | {
|
|
44
|
-
type: "bulk_create";
|
|
45
|
-
request: string;
|
|
46
|
-
} | {
|
|
47
|
-
type: "status";
|
|
48
|
-
} | {
|
|
49
|
-
type: "pause";
|
|
50
|
-
} | {
|
|
51
|
-
type: "resume";
|
|
52
|
-
} | {
|
|
53
|
-
type: "assign";
|
|
54
|
-
issueId: string;
|
|
55
|
-
} | {
|
|
56
|
-
type: "unknown";
|
|
57
|
-
original: string;
|
|
58
|
-
};
|
|
59
62
|
export interface AssignedNotification {
|
|
60
63
|
issueId: string;
|
|
61
64
|
issueTitle: string;
|
|
@@ -72,20 +75,6 @@ export interface DailySummaryEntry {
|
|
|
72
75
|
issueTitle: string;
|
|
73
76
|
status: "assigned" | "completed" | "blocked";
|
|
74
77
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Returns `true` if the PM Agent is currently paused.
|
|
77
|
-
*
|
|
78
|
-
* Pause is active when EITHER of the following is true (OR logic):
|
|
79
|
-
* - `process.env.PM_AGENT_PAUSED === "true"` — env-var path for no-Slack incident
|
|
80
|
-
* response. Toggling requires a container restart (env vars are read at each
|
|
81
|
-
* tick invocation, not at module load time).
|
|
82
|
-
* - `setPmPaused(true)` has been called via the Slack `/pm pause` command.
|
|
83
|
-
*
|
|
84
|
-
* The env-var takes priority: setting `PM_AGENT_PAUSED=true` keeps the agent
|
|
85
|
-
* paused even if `setPmPaused(false)` is subsequently called via Slack.
|
|
86
|
-
*/
|
|
87
|
-
export declare function isPmPaused(): boolean;
|
|
88
|
-
export declare function setPmPaused(value: boolean): void;
|
|
89
78
|
/**
|
|
90
79
|
* Verifies the Slack signing secret against the X-Slack-Signature header.
|
|
91
80
|
* Returns `true` if valid, `false` otherwise.
|
|
@@ -99,22 +88,6 @@ export declare function parsePmCommand(text: string): PmCommand;
|
|
|
99
88
|
* Returns `{ type: "unknown", original }` if no actionable intent is found.
|
|
100
89
|
*/
|
|
101
90
|
export declare function interpretNaturalLanguage(message: string, callClaude: (prompt: string) => Promise<string>): Promise<PmCommand>;
|
|
102
|
-
export interface BulkIssueSpec {
|
|
103
|
-
title: string;
|
|
104
|
-
description: string;
|
|
105
|
-
priority: number;
|
|
106
|
-
acceptanceCriteria: string[];
|
|
107
|
-
}
|
|
108
|
-
export interface CommandExecutorDeps {
|
|
109
|
-
linearApiKey?: string;
|
|
110
|
-
teamIds?: string[];
|
|
111
|
-
callClaudeSonnet?: (prompt: string) => Promise<string>;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Executes a parsed `PmCommand` against Linear and returns a human-readable
|
|
115
|
-
* response string suitable for posting back to Slack.
|
|
116
|
-
*/
|
|
117
|
-
export declare function executePmCommand(cmd: PmCommand, deps: CommandExecutorDeps): Promise<string>;
|
|
118
91
|
export declare class SlackInterfaceNotifier {
|
|
119
92
|
private botToken;
|
|
120
93
|
private channelId;
|
|
@@ -127,6 +100,12 @@ export declare class SlackInterfaceNotifier {
|
|
|
127
100
|
askForClarification(question: string): Promise<void>;
|
|
128
101
|
/** Post a daily summary of assigned, completed, and blocked issues. */
|
|
129
102
|
postDailySummary(entries: DailySummaryEntry[], date?: string): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Posts a single Slack Block Kit section containing mrkdwn-formatted `text`
|
|
105
|
+
* to the configured channel. All three simple notification methods delegate
|
|
106
|
+
* here to avoid repeating the identical blocks structure.
|
|
107
|
+
*/
|
|
108
|
+
private postMarkdownMessage;
|
|
130
109
|
private postMessage;
|
|
131
110
|
}
|
|
132
111
|
/**
|
|
@@ -145,9 +124,4 @@ export declare function createSlackInterface(config: SlackInterfaceConfig): {
|
|
|
145
124
|
router: Hono;
|
|
146
125
|
notifier: SlackInterfaceNotifier;
|
|
147
126
|
};
|
|
148
|
-
/**
|
|
149
|
-
* Uses a capable Claude model (Sonnet) to analyze a bulk create request and
|
|
150
|
-
* produce a structured list of issue specifications.
|
|
151
|
-
*/
|
|
152
|
-
export declare function analyzeBulkCreateRequest(request: string, callClaudeSonnet: (prompt: string) => Promise<string>): Promise<BulkIssueSpec[]>;
|
|
153
127
|
//# sourceMappingURL=slack-interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-interface.d.ts","sourceRoot":"","sources":["../../src/pm/slack-interface.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"slack-interface.d.ts","sourceRoot":"","sources":["../../src/pm/slack-interface.ts"],"names":[],"mappings":"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"}
|