@orderful/droid 0.39.1 → 0.40.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/bun.lock +73 -0
  3. package/dist/bin/droid.js +891 -386
  4. package/dist/commands/integrations.d.ts +10 -0
  5. package/dist/commands/integrations.d.ts.map +1 -0
  6. package/dist/commands/tui/components/IntegrationsDetails.d.ts +6 -0
  7. package/dist/commands/tui/components/IntegrationsDetails.d.ts.map +1 -0
  8. package/dist/commands/tui/components/Markdown.d.ts.map +1 -1
  9. package/dist/commands/tui/types.d.ts +1 -1
  10. package/dist/commands/tui/types.d.ts.map +1 -1
  11. package/dist/commands/tui.d.ts.map +1 -1
  12. package/dist/index.js +29 -1
  13. package/dist/integrations/slack/index.d.ts +42 -0
  14. package/dist/integrations/slack/index.d.ts.map +1 -0
  15. package/dist/integrations/slack/index.ts +148 -0
  16. package/dist/integrations/slack/references/setup.md +53 -0
  17. package/dist/lib/config.d.ts.map +1 -1
  18. package/dist/lib/types.d.ts +9 -0
  19. package/dist/lib/types.d.ts.map +1 -1
  20. package/dist/tools/status-update/.claude-plugin/plugin.json +1 -1
  21. package/dist/tools/status-update/TOOL.yaml +2 -6
  22. package/dist/tools/status-update/skills/status-update/SKILL.md +14 -26
  23. package/package.json +2 -1
  24. package/scripts/build.ts +4 -0
  25. package/src/bin/droid.ts +27 -13
  26. package/src/commands/integrations.ts +431 -0
  27. package/src/commands/tui/components/IntegrationsDetails.tsx +95 -0
  28. package/src/commands/tui/components/Markdown.tsx +68 -3
  29. package/src/commands/tui/types.ts +1 -1
  30. package/src/commands/tui.tsx +81 -1
  31. package/src/integrations/slack/index.ts +148 -0
  32. package/src/integrations/slack/references/setup.md +53 -0
  33. package/src/lib/config.ts +49 -1
  34. package/src/lib/types.ts +11 -0
  35. package/src/tools/status-update/.claude-plugin/plugin.json +1 -1
  36. package/src/tools/status-update/TOOL.yaml +2 -6
  37. package/src/tools/status-update/skills/status-update/SKILL.md +14 -26
  38. package/dist/commands/auth.d.ts +0 -3
  39. package/dist/commands/auth.d.ts.map +0 -1
  40. package/dist/lib/secrets.d.ts +0 -7
  41. package/dist/lib/secrets.d.ts.map +0 -1
  42. package/src/commands/auth.ts +0 -150
  43. package/src/lib/secrets.ts +0 -12
@@ -0,0 +1,10 @@
1
+ export declare function integrationsSetupSlackCommand(): Promise<void>;
2
+ export declare function integrationsStatusCommand(): Promise<void>;
3
+ /**
4
+ * Post a message or edit a canvas via Slack SDK.
5
+ * Reads JSON from stdin, outputs JSON result to stdout.
6
+ */
7
+ export declare function slackPostCommand(options: {
8
+ canvas?: boolean;
9
+ }): Promise<void>;
10
+ //# sourceMappingURL=integrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../src/commands/integrations.ts"],"names":[],"mappings":"AAoNA,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAuInE;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqC/D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCnF"}
@@ -0,0 +1,6 @@
1
+ export interface IntegrationsDetailsProps {
2
+ isFocused: boolean;
3
+ selectedAction: number;
4
+ }
5
+ export declare function IntegrationsDetails({ isFocused, selectedAction, }: IntegrationsDetailsProps): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=IntegrationsDetails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrationsDetails.d.ts","sourceRoot":"","sources":["../../../../src/commands/tui/components/IntegrationsDetails.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,cAAc,GACf,EAAE,wBAAwB,2CAmF1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../../../src/commands/tui/components/Markdown.tsx"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,2CA4CzF"}
1
+ {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../../../src/commands/tui/components/Markdown.tsx"],"names":[],"mappings":"AA+DA,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,2CAiDzF"}
@@ -1,4 +1,4 @@
1
- export type Tab = 'tools' | 'settings';
1
+ export type Tab = 'tools' | 'integrations' | 'settings';
2
2
  export type View = 'welcome' | 'tool-updates' | 'setup' | 'menu' | 'detail' | 'configure' | 'readme' | 'explorer' | 'repos' | 'view-repos';
3
3
  export type SetupStep = 'user_mention' | 'auto_update' | 'confirm';
4
4
  export type ComponentType = 'skill' | 'command' | 'agent';
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/tui/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,GAAG,OAAO,GAAG,UAAU,CAAC;AACvC,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,YAAY,CAAC;AAC3I,MAAM,MAAM,SAAS,GAAG,cAAc,GAAG,aAAa,GAAG,SAAS,CAAC;AACnE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/tui/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,GAAG,OAAO,GAAG,cAAc,GAAG,UAAU,CAAC;AACxD,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,YAAY,CAAC;AAC3I,MAAM,MAAM,SAAS,GAAG,cAAc,GAAG,aAAa,GAAG,SAAS,CAAC;AACnE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../src/commands/tui.tsx"],"names":[],"mappings":"AA+lBA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBhD"}
1
+ {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../src/commands/tui.tsx"],"names":[],"mappings":"AAuqBA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAyBhD"}
package/dist/index.js CHANGED
@@ -135,6 +135,33 @@ function migrateToolConfigs(config) {
135
135
  return false;
136
136
  }
137
137
  }
138
+ function migrateIntegrations(config) {
139
+ if (config.migrations?.integrations_consolidated) {
140
+ return false;
141
+ }
142
+ const statusUpdateConfig = config.tools?.["status-update"];
143
+ if (statusUpdateConfig && "default_crosspost_channel" in statusUpdateConfig) {
144
+ const channel = statusUpdateConfig.default_crosspost_channel;
145
+ if (!config.integrations) {
146
+ config.integrations = {};
147
+ }
148
+ if (!config.integrations.slack) {
149
+ config.integrations.slack = {};
150
+ }
151
+ if (!config.integrations.slack.crosspost_channel && channel) {
152
+ config.integrations.slack.crosspost_channel = channel;
153
+ }
154
+ delete statusUpdateConfig.default_crosspost_channel;
155
+ if (Object.keys(statusUpdateConfig).length === 0) {
156
+ delete config.tools["status-update"];
157
+ }
158
+ }
159
+ if (!config.migrations) {
160
+ config.migrations = {};
161
+ }
162
+ config.migrations.integrations_consolidated = true;
163
+ return true;
164
+ }
138
165
  function ensureConfigDir() {
139
166
  if (!existsSync(CONFIG_DIR)) {
140
167
  mkdirSync(CONFIG_DIR, { recursive: true });
@@ -154,7 +181,8 @@ function loadConfig() {
154
181
  const needsLegacyMigration = "ai_tool" in rawConfig && !("platform" in rawConfig);
155
182
  const config = migrateConfig(rawConfig);
156
183
  const needsToolMigration = migrateToolConfigs(config);
157
- if (needsLegacyMigration || needsToolMigration) {
184
+ const needsIntegrationsMigration = migrateIntegrations(config);
185
+ if (needsLegacyMigration || needsToolMigration || needsIntegrationsMigration) {
158
186
  saveConfig(config);
159
187
  }
160
188
  return config;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Slack integration — SDK wrapper + token helpers
3
+ *
4
+ * Uses @slack/web-api for all API calls (postMessage, canvases.edit, OAuth exchange).
5
+ * Each function creates its own WebClient instance (appropriate for CLI — no long-lived connections).
6
+ */
7
+ export declare function getSlackToken(): string | undefined;
8
+ export declare function hasSlackToken(): boolean;
9
+ export interface PostMessageParams {
10
+ channel: string;
11
+ text: string;
12
+ unfurl_links?: boolean;
13
+ }
14
+ export interface PostMessageResult {
15
+ ok: boolean;
16
+ ts?: string;
17
+ channel?: string;
18
+ error?: string;
19
+ }
20
+ export declare function postMessage(params: PostMessageParams): Promise<PostMessageResult>;
21
+ export interface CanvasChange {
22
+ operation: string;
23
+ document_content: {
24
+ type: string;
25
+ markdown: string;
26
+ };
27
+ }
28
+ export interface EditCanvasResult {
29
+ ok: boolean;
30
+ error?: string;
31
+ }
32
+ export declare function editCanvas(params: {
33
+ canvas_id: string;
34
+ changes: CanvasChange[];
35
+ }): Promise<EditCanvasResult>;
36
+ export interface ExchangeOAuthResult {
37
+ ok: boolean;
38
+ token?: string;
39
+ error?: string;
40
+ }
41
+ export declare function exchangeOAuthCode(clientId: string, clientSecret: string, code: string, redirectUri: string): Promise<ExchangeOAuthResult>;
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/slack/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAMD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0BvF;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsB5B;AAMD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CA0B9B"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Slack integration — SDK wrapper + token helpers
3
+ *
4
+ * Uses @slack/web-api for all API calls (postMessage, canvases.edit, OAuth exchange).
5
+ * Each function creates its own WebClient instance (appropriate for CLI — no long-lived connections).
6
+ */
7
+
8
+ import { WebClient } from '@slack/web-api';
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Token helpers (absorbed from secrets.ts)
12
+ // ---------------------------------------------------------------------------
13
+
14
+ export function getSlackToken(): string | undefined {
15
+ return process.env.SLACK_USER_TOKEN;
16
+ }
17
+
18
+ export function hasSlackToken(): boolean {
19
+ return !!process.env.SLACK_USER_TOKEN;
20
+ }
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // API operations
24
+ // ---------------------------------------------------------------------------
25
+
26
+ export interface PostMessageParams {
27
+ channel: string;
28
+ text: string;
29
+ unfurl_links?: boolean;
30
+ }
31
+
32
+ export interface PostMessageResult {
33
+ ok: boolean;
34
+ ts?: string;
35
+ channel?: string;
36
+ error?: string;
37
+ }
38
+
39
+ export async function postMessage(params: PostMessageParams): Promise<PostMessageResult> {
40
+ const token = getSlackToken();
41
+ if (!token) {
42
+ return { ok: false, error: 'SLACK_USER_TOKEN not set. Run: droid integrations setup slack' };
43
+ }
44
+
45
+ const client = new WebClient(token);
46
+
47
+ try {
48
+ const result = await client.chat.postMessage({
49
+ channel: params.channel,
50
+ text: params.text,
51
+ unfurl_links: params.unfurl_links,
52
+ });
53
+
54
+ return {
55
+ ok: result.ok ?? false,
56
+ ts: result.ts,
57
+ channel: result.channel,
58
+ };
59
+ } catch (error) {
60
+ return {
61
+ ok: false,
62
+ error: error instanceof Error ? error.message : 'Unknown error',
63
+ };
64
+ }
65
+ }
66
+
67
+ export interface CanvasChange {
68
+ operation: string;
69
+ document_content: {
70
+ type: string;
71
+ markdown: string;
72
+ };
73
+ }
74
+
75
+ export interface EditCanvasResult {
76
+ ok: boolean;
77
+ error?: string;
78
+ }
79
+
80
+ export async function editCanvas(params: {
81
+ canvas_id: string;
82
+ changes: CanvasChange[];
83
+ }): Promise<EditCanvasResult> {
84
+ const token = getSlackToken();
85
+ if (!token) {
86
+ return { ok: false, error: 'SLACK_USER_TOKEN not set. Run: droid integrations setup slack' };
87
+ }
88
+
89
+ const client = new WebClient(token);
90
+
91
+ try {
92
+ const result = await client.canvases.edit({
93
+ canvas_id: params.canvas_id,
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ changes: params.changes as any,
96
+ });
97
+
98
+ return { ok: result.ok ?? false };
99
+ } catch (error) {
100
+ return {
101
+ ok: false,
102
+ error: error instanceof Error ? error.message : 'Unknown error',
103
+ };
104
+ }
105
+ }
106
+
107
+ // ---------------------------------------------------------------------------
108
+ // OAuth (no token needed for exchange)
109
+ // ---------------------------------------------------------------------------
110
+
111
+ export interface ExchangeOAuthResult {
112
+ ok: boolean;
113
+ token?: string;
114
+ error?: string;
115
+ }
116
+
117
+ export async function exchangeOAuthCode(
118
+ clientId: string,
119
+ clientSecret: string,
120
+ code: string,
121
+ redirectUri: string,
122
+ ): Promise<ExchangeOAuthResult> {
123
+ try {
124
+ const client = new WebClient();
125
+ const result = await client.oauth.v2.access({
126
+ client_id: clientId,
127
+ client_secret: clientSecret,
128
+ code,
129
+ redirect_uri: redirectUri,
130
+ });
131
+
132
+ if (!result.ok) {
133
+ return { ok: false, error: String(result.error ?? 'Unknown error') };
134
+ }
135
+
136
+ const token = result.authed_user?.access_token;
137
+ if (!token) {
138
+ return { ok: false, error: 'No user token in response' };
139
+ }
140
+
141
+ return { ok: true, token };
142
+ } catch (error) {
143
+ return {
144
+ ok: false,
145
+ error: error instanceof Error ? error.message : 'Unknown error',
146
+ };
147
+ }
148
+ }
@@ -0,0 +1,53 @@
1
+ # Slack Integration Setup
2
+
3
+ ## Prerequisites
4
+
5
+ 1. Get the **Client ID** and **Client Secret** from 1Password (search "Droid Slack App")
6
+ 2. Add them to your shell config (e.g. `~/.zshrc`):
7
+
8
+ ```bash
9
+ export SLACK_CLIENT_ID="your-client-id"
10
+ export SLACK_CLIENT_SECRET="your-client-secret"
11
+ ```
12
+
13
+ 3. Reload your shell: `source ~/.zshrc`
14
+
15
+ ## Setup
16
+
17
+ Run the OAuth flow:
18
+
19
+ ```bash
20
+ droid integrations setup slack
21
+ ```
22
+
23
+ Or use the **Run Setup** button in `droid` TUI → Integrations tab.
24
+
25
+ This will:
26
+ - Generate a local HTTPS certificate (stored in `~/.droid/certs/`)
27
+ - Offer to trust it in your macOS Keychain (avoids browser warnings)
28
+ - Open your browser to Slack's authorisation page
29
+ - Catch the redirect on a local callback server (port 9876)
30
+ - Exchange the code for a user token via the Slack SDK
31
+ - Write `SLACK_USER_TOKEN` to your shell rc file
32
+
33
+ ## Verify
34
+
35
+ ```bash
36
+ droid integrations status
37
+ ```
38
+
39
+ You should see all three credentials marked as set and status as "Configured".
40
+
41
+ ## Usage by AI
42
+
43
+ Post a message:
44
+ ```bash
45
+ node -e 'process.stdout.write(JSON.stringify({channel:"#eng",text:"hello"}))' | \
46
+ droid integrations slack post
47
+ ```
48
+
49
+ Edit a canvas:
50
+ ```bash
51
+ node -e 'process.stdout.write(JSON.stringify({canvas_id:"F123",changes:[{operation:"insert_at_end",document_content:{type:"markdown",markdown:"Content here"}}]}))' | \
52
+ droid integrations slack post --canvas
53
+ ```
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,WAAW,EAEhB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,SAAS,CAAC;AA2HjB;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,WAAW,CAgCxC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAKpD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAanD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAiBhE;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAWD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAsBpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,cAAc,GACxB,IAAI,CAWN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAGxD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,IAAI,CAOxE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAI9E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAMtD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAQ5E;AAYD;;GAEG;AACH,wBAAgB,QAAQ,IAAI,UAAU,EAAE,CAGvC;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAG5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM5D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAiB9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAchD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,WAAW,EAEhB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,SAAS,CAAC;AAwKjB;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,WAAW,CAmCxC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAKpD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAanD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAiBhE;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAWD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAsBpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,cAAc,GACxB,IAAI,CAWN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAGxD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,IAAI,CAOxE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAI9E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAMtD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAQ5E;AAYD;;GAEG;AACH,wBAAgB,QAAQ,IAAI,UAAU,EAAE,CAGvC;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAG5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM5D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAiB9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAchD"}
@@ -40,6 +40,13 @@ export interface RepoConfig {
40
40
  description?: string;
41
41
  }
42
42
  export type ToolConfig = Record<string, unknown>;
43
+ export interface IntegrationSlackConfig {
44
+ configured?: boolean;
45
+ crosspost_channel?: string;
46
+ }
47
+ export interface IntegrationsConfig {
48
+ slack?: IntegrationSlackConfig;
49
+ }
43
50
  export interface DroidConfig {
44
51
  platform: Platform;
45
52
  user_mention: string;
@@ -48,12 +55,14 @@ export interface DroidConfig {
48
55
  platforms: Record<string, PlatformConfig>;
49
56
  repos?: RepoConfig[];
50
57
  tools?: Record<string, ToolConfig>;
58
+ integrations?: IntegrationsConfig;
51
59
  auto_update?: AutoUpdateConfig;
52
60
  ignored_platforms?: Platform[];
53
61
  migrations?: {
54
62
  package?: string;
55
63
  tools?: Record<string, string>;
56
64
  tools_consolidated?: boolean;
65
+ integrations_consolidated?: boolean;
57
66
  [key: string]: string | Record<string, string> | boolean | undefined;
58
67
  };
59
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "droid-status-update",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Generate and post project status updates. Aggregates context from codex projects, Jira epics, and manual input. Posts to Slack or prints to terminal.",
5
5
  "author": {
6
6
  "name": "Orderful",
@@ -1,6 +1,6 @@
1
1
  name: status-update
2
2
  description: "Generate and post project status updates. Aggregates context from codex projects, Jira epics, and manual input. Posts to Slack or prints to terminal."
3
- version: 0.1.0
3
+ version: 0.2.1
4
4
  status: beta
5
5
 
6
6
  includes:
@@ -14,8 +14,4 @@ includes:
14
14
 
15
15
  dependencies: []
16
16
 
17
- config_schema:
18
- default_crosspost_channel:
19
- type: string
20
- description: Default channel for cross-posting updates (e.g., rnd-updates)
21
- required: false
17
+ config_schema: {}
@@ -8,7 +8,6 @@ allowed-tools:
8
8
  Glob,
9
9
  Grep,
10
10
  Bash(git:*),
11
- Bash(curl:*),
12
11
  Bash(droid:*),
13
12
  ]
14
13
  ---
@@ -179,14 +178,8 @@ Add ` & :codex:` to footer if codex project was used.
179
178
 
180
179
  **Post to primary channel:**
181
180
  ```bash
182
- curl -s -X POST https://slack.com/api/chat.postMessage \
183
- -H "Authorization: Bearer $SLACK_USER_TOKEN" \
184
- -H "Content-Type: application/json; charset=utf-8" \
185
- -d '{
186
- "channel": "{slack.channel}",
187
- "text": "{formatted_message}",
188
- "unfurl_links": false
189
- }'
181
+ node -e 'process.stdout.write(JSON.stringify({channel:"{slack.channel}",text:`{formatted_message}`,unfurl_links:false}))' | \
182
+ droid integrations slack post
190
183
  ```
191
184
 
192
185
  Check response for `"ok": true`. Save `ts` and `channel` from response.
@@ -207,21 +200,15 @@ Post summary version with link to full update:
207
200
 
208
201
  Message URL format: `https://orderful.slack.com/archives/{channel_id}/p{ts_without_dot}`
209
202
 
203
+ ```bash
204
+ node -e 'process.stdout.write(JSON.stringify({channel:"{crosspost_channel}",text:`{crosspost_message}`,unfurl_links:false}))' | \
205
+ droid integrations slack post
206
+ ```
207
+
210
208
  **Update canvas log (if canvas_id configured):**
211
209
  ```bash
212
- curl -s -X POST https://slack.com/api/canvases.edit \
213
- -H "Authorization: Bearer $SLACK_USER_TOKEN" \
214
- -H "Content-Type: application/json; charset=utf-8" \
215
- -d '{
216
- "canvas_id": "{slack.canvas_id}",
217
- "changes": [{
218
- "operation": "insert_at_start",
219
- "document_content": {
220
- "type": "markdown",
221
- "markdown": "### {date}\n{status} · {current_phase}\n[View update]({message_url})\n\n---"
222
- }
223
- }]
224
- }'
210
+ node -e 'process.stdout.write(JSON.stringify({canvas_id:"{slack.canvas_id}",changes:[{operation:"insert_at_start",document_content:{type:"markdown",markdown:"### {date}\n{status} · {current_phase}\n[View update]({message_url})\n\n---"}}]}))' | \
211
+ droid integrations slack post --canvas
225
212
  ```
226
213
 
227
214
  **Confirm to user:**
@@ -233,21 +220,22 @@ curl -s -X POST https://slack.com/api/canvases.edit \
233
220
 
234
221
  Print the formatted message to terminal.
235
222
 
236
- Tell user: "Slack not configured. To post updates directly, add `slack.channel` to your project's CONTEXT.md and set `SLACK_USER_TOKEN` in your environment."
223
+ Tell user: "Slack not configured. To post updates directly, add `slack.channel` to your project's CONTEXT.md and run `droid integrations setup slack`."
237
224
 
238
225
  ### Error Handling
239
226
 
240
227
  | Error | Action |
241
228
  |-------|--------|
242
- | No SLACK_USER_TOKEN | Print to terminal, suggest setup |
229
+ | No SLACK_USER_TOKEN | Print to terminal, suggest `droid integrations setup slack` |
243
230
  | Slack API error | Show error, offer to print instead |
244
231
  | Jira MCP not available | Skip Jira, continue with other sources |
245
232
  | No codex project found | Continue with manual input |
246
233
 
247
234
  ## Configuration
248
235
 
249
- No required configuration. Optional settings via `droid config`:
236
+ No required configuration. Slack settings are shared via `droid config --get integrations.slack`:
250
237
 
251
238
  | Setting | Description |
252
239
  |---------|-------------|
253
- | `default_crosspost_channel` | Default channel for cross-posts if not in project metadata |
240
+ | `integrations.slack.crosspost_channel` | Default channel for cross-posts if not in project metadata |
241
+ | `integrations.slack.configured` | Whether Slack integration has been set up |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orderful/droid",
3
- "version": "0.39.1",
3
+ "version": "0.40.1",
4
4
  "description": "AI workflow toolkit for sharing skills, commands, and agents across the team",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,6 +45,7 @@
45
45
  "registry": "https://registry.npmjs.org/"
46
46
  },
47
47
  "dependencies": {
48
+ "@slack/web-api": "^7.13.0",
48
49
  "chalk": "^5.3.0",
49
50
  "commander": "^12.1.0",
50
51
  "ink": "^6.5.1",
package/scripts/build.ts CHANGED
@@ -69,6 +69,10 @@ async function main() {
69
69
  console.log('Copying tools...');
70
70
  cpSync('src/tools', 'dist/tools', { recursive: true });
71
71
 
72
+ // Copy integrations directory (references, etc.)
73
+ console.log('Copying integrations...');
74
+ cpSync('src/integrations', 'dist/integrations', { recursive: true });
75
+
72
76
  console.log('Build complete!');
73
77
  }
74
78
 
package/src/bin/droid.ts CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  reposRemoveCommand,
17
17
  reposGetCommand,
18
18
  } from '../commands/repos';
19
- import { authSlackCommand, authStatusCommand } from '../commands/auth';
19
+ import { integrationsSetupSlackCommand, integrationsStatusCommand, slackPostCommand } from '../commands/integrations';
20
20
  import { getVersion } from '../lib/version';
21
21
  import { loadConfig, saveConfig, configExists } from '../lib/config';
22
22
  import { syncNewPlatforms } from '../lib/platforms';
@@ -110,23 +110,37 @@ program
110
110
  .allowUnknownOption()
111
111
  .action(execCommand);
112
112
 
113
- // Auth command with subcommands
114
- const auth = program
115
- .command('auth')
116
- .description('Set up authentication for external services');
113
+ // Integrations command with subcommands
114
+ const integrations = program
115
+ .command('integrations')
116
+ .description('Manage external service integrations');
117
117
 
118
- auth
118
+ const integrationsSetup = integrations
119
+ .command('setup')
120
+ .description('Set up an integration');
121
+
122
+ integrationsSetup
119
123
  .command('slack')
120
- .description('Set up Slack authentication for status updates')
121
- .action(authSlackCommand);
124
+ .description('Set up Slack integration')
125
+ .action(integrationsSetupSlackCommand);
122
126
 
123
- auth
127
+ integrations
124
128
  .command('status')
125
- .description('Show authentication status')
126
- .action(authStatusCommand);
129
+ .description('Show integration status')
130
+ .action(integrationsStatusCommand);
131
+
132
+ const integrationsSlack = integrations
133
+ .command('slack')
134
+ .description('Slack integration commands');
135
+
136
+ integrationsSlack
137
+ .command('post')
138
+ .description('Post a message or edit a canvas (JSON from stdin)')
139
+ .option('--canvas', 'Edit a canvas instead of posting a message')
140
+ .action((options) => slackPostCommand(options));
127
141
 
128
- // Default: show auth status if no subcommand
129
- auth.action(authStatusCommand);
142
+ // Default: show status if no subcommand
143
+ integrations.action(integrationsStatusCommand);
130
144
 
131
145
  // Sync new platforms before running any command
132
146
  // This ensures that newly installed platforms (e.g., Codex) get all existing tools