@scindo/cli 1.0.0

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 (54) hide show
  1. package/README.md +136 -0
  2. package/dist/commands/agent.d.ts +2 -0
  3. package/dist/commands/agent.d.ts.map +1 -0
  4. package/dist/commands/agent.js +91 -0
  5. package/dist/commands/agent.js.map +1 -0
  6. package/dist/commands/channels.d.ts +2 -0
  7. package/dist/commands/channels.d.ts.map +1 -0
  8. package/dist/commands/channels.js +67 -0
  9. package/dist/commands/channels.js.map +1 -0
  10. package/dist/commands/dm.d.ts +2 -0
  11. package/dist/commands/dm.d.ts.map +1 -0
  12. package/dist/commands/dm.js +86 -0
  13. package/dist/commands/dm.js.map +1 -0
  14. package/dist/commands/login.d.ts +3 -0
  15. package/dist/commands/login.d.ts.map +1 -0
  16. package/dist/commands/login.js +95 -0
  17. package/dist/commands/login.js.map +1 -0
  18. package/dist/commands/push.d.ts +7 -0
  19. package/dist/commands/push.d.ts.map +1 -0
  20. package/dist/commands/push.js +100 -0
  21. package/dist/commands/push.js.map +1 -0
  22. package/dist/commands/read.d.ts +4 -0
  23. package/dist/commands/read.d.ts.map +1 -0
  24. package/dist/commands/read.js +93 -0
  25. package/dist/commands/read.js.map +1 -0
  26. package/dist/commands/send.d.ts +2 -0
  27. package/dist/commands/send.d.ts.map +1 -0
  28. package/dist/commands/send.js +49 -0
  29. package/dist/commands/send.js.map +1 -0
  30. package/dist/commands/thread.d.ts +3 -0
  31. package/dist/commands/thread.d.ts.map +1 -0
  32. package/dist/commands/thread.js +123 -0
  33. package/dist/commands/thread.js.map +1 -0
  34. package/dist/commands/unread.d.ts +2 -0
  35. package/dist/commands/unread.d.ts.map +1 -0
  36. package/dist/commands/unread.js +91 -0
  37. package/dist/commands/unread.js.map +1 -0
  38. package/dist/config.d.ts +16 -0
  39. package/dist/config.d.ts.map +1 -0
  40. package/dist/config.js +30 -0
  41. package/dist/config.js.map +1 -0
  42. package/dist/index.d.ts +3 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +83 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/stream.d.ts +5 -0
  47. package/dist/stream.d.ts.map +1 -0
  48. package/dist/stream.js +55 -0
  49. package/dist/stream.js.map +1 -0
  50. package/dist/supabase.d.ts +4 -0
  51. package/dist/supabase.d.ts.map +1 -0
  52. package/dist/supabase.js +42 -0
  53. package/dist/supabase.js.map +1 -0
  54. package/package.json +48 -0
package/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # @scindo/cli
2
+
3
+ **Scindo CLI** — team chat with AI agents from the terminal.
4
+
5
+ Interact with your Scindo workspace without leaving the command line. Read channels, send messages, trigger AI agents, and pipe output from any tool directly into your team's conversation.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g @scindo/cli
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # Log in to your workspace
17
+ scindo login
18
+
19
+ # List channels with unread counts
20
+ scindo channels
21
+
22
+ # Read recent messages
23
+ scindo read general
24
+
25
+ # Send a message
26
+ scindo send general "deploying v2 now"
27
+
28
+ # Ask the AI agent a question
29
+ scindo agent general "summarize today's discussion"
30
+ ```
31
+
32
+ ## Commands
33
+
34
+ ### `scindo login`
35
+
36
+ Authenticate with your Scindo workspace via browser-based OAuth.
37
+
38
+ ### `scindo logout`
39
+
40
+ Log out and clear stored credentials.
41
+
42
+ ### `scindo channels`
43
+
44
+ List all channels in your workspace with unread counts.
45
+
46
+ ```bash
47
+ scindo channels
48
+ ```
49
+
50
+ ### `scindo read <channel>`
51
+
52
+ Read recent messages from a channel.
53
+
54
+ ```bash
55
+ scindo read general
56
+ scindo read general -n 50 # show last 50 messages
57
+ ```
58
+
59
+ ### `scindo send <channel> <message>`
60
+
61
+ Send a message to a channel.
62
+
63
+ ```bash
64
+ scindo send general "ship it"
65
+ scindo send dev "PR is up for review"
66
+ ```
67
+
68
+ ### `scindo dm <user> <message>`
69
+
70
+ Send a direct message to a team member.
71
+
72
+ ```bash
73
+ scindo dm @alice "can you review my PR?"
74
+ ```
75
+
76
+ ### `scindo thread <channel>`
77
+
78
+ Read the latest thread in a channel.
79
+
80
+ ```bash
81
+ scindo thread general
82
+ ```
83
+
84
+ ### `scindo reply <message>`
85
+
86
+ Reply to the last viewed thread.
87
+
88
+ ```bash
89
+ scindo reply "looks good, merging now"
90
+ ```
91
+
92
+ ### `scindo unread`
93
+
94
+ Show all unread messages across channels and DMs.
95
+
96
+ ```bash
97
+ scindo unread
98
+ ```
99
+
100
+ ### `scindo agent <channel> <message>`
101
+
102
+ Send a message to the AI agent in a channel and stream the response.
103
+
104
+ ```bash
105
+ scindo agent general "what broke in the last deploy?"
106
+ scindo agent dev "review the latest PR"
107
+ ```
108
+
109
+ ### `scindo push`
110
+
111
+ Push stdin content to a channel. Great for piping output from other tools.
112
+
113
+ ```bash
114
+ # Push git diff to a channel
115
+ git diff | scindo push --channel dev
116
+
117
+ # Push and trigger the AI agent
118
+ git diff | scindo push --channel dev --mention-agent
119
+
120
+ # Push test results
121
+ npm test 2>&1 | scindo push --channel ci
122
+
123
+ # Push a file
124
+ cat report.md | scindo push --channel general
125
+ ```
126
+
127
+ ## Environment Variables
128
+
129
+ | Variable | Description | Default |
130
+ |----------|-------------|---------|
131
+ | `SCINDO_APP_URL` | Scindo API base URL | `https://app.scindo.one` |
132
+ | `SCINDO_AGENT_USER_ID` | Agent user ID for @mentions | — |
133
+
134
+ ## License
135
+
136
+ MIT
@@ -0,0 +1,2 @@
1
+ export declare function agentCommand(channelName: string, message: string): Promise<void>;
2
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AAQA,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiGtF"}
@@ -0,0 +1,91 @@
1
+ import chalk from 'chalk';
2
+ import { getSupabase } from '../supabase.js';
3
+ import { getConfig, setConfig } from '../config.js';
4
+ import { consumeSSEStream } from '../stream.js';
5
+ const AGENT_USER_ID = process.env.SCINDO_AGENT_USER_ID ?? '';
6
+ const APP_URL = process.env.SCINDO_APP_URL ?? 'https://app.scindo.one';
7
+ export async function agentCommand(channelName, message) {
8
+ const supabase = getSupabase();
9
+ const config = getConfig();
10
+ if (!config.userId) {
11
+ console.log(chalk.red('Not logged in. Run: scindo login'));
12
+ return;
13
+ }
14
+ const slug = channelName.replace(/^#/, '');
15
+ let workspaceId = config.lastWorkspaceId;
16
+ if (!workspaceId) {
17
+ const { data: member } = await supabase
18
+ .from('workspace_members')
19
+ .select('workspace_id')
20
+ .limit(1)
21
+ .single();
22
+ if (!member) {
23
+ console.log(chalk.red('No workspaces found'));
24
+ return;
25
+ }
26
+ workspaceId = member.workspace_id;
27
+ setConfig({ lastWorkspaceId: workspaceId });
28
+ }
29
+ // Find channel
30
+ const { data: channel, error: chErr } = await supabase
31
+ .from('channels')
32
+ .select('id, name')
33
+ .eq('workspace_id', workspaceId)
34
+ .eq('slug', slug)
35
+ .single();
36
+ if (chErr || !channel) {
37
+ console.log(chalk.red(`Channel #${slug} not found`));
38
+ return;
39
+ }
40
+ // Auto-prepend @Scindo mention if not already present
41
+ const content = message.includes('@Scindo') ? message : `@Scindo ${message}`;
42
+ const mentions = AGENT_USER_ID ? [AGENT_USER_ID] : [];
43
+ // Send message
44
+ const { error: sendErr } = await supabase.from('messages').insert({
45
+ workspace_id: workspaceId,
46
+ channel_id: channel.id,
47
+ user_id: config.userId,
48
+ content,
49
+ mentions,
50
+ });
51
+ if (sendErr) {
52
+ console.log(chalk.red(`Failed to send: ${sendErr.message}`));
53
+ return;
54
+ }
55
+ console.log(chalk.dim(`> ${content}`));
56
+ console.log();
57
+ // Call agent API with streaming
58
+ try {
59
+ const res = await fetch(`${APP_URL}/api/agent/channel-respond`, {
60
+ method: 'POST',
61
+ headers: {
62
+ 'Content-Type': 'application/json',
63
+ 'Authorization': `Bearer ${config.accessToken}`,
64
+ },
65
+ body: JSON.stringify({
66
+ channelId: channel.id,
67
+ workspaceId,
68
+ stream: true,
69
+ }),
70
+ });
71
+ const contentType = res.headers.get('content-type') ?? '';
72
+ if (contentType.includes('text/event-stream')) {
73
+ // Stream tokens to stdout
74
+ await consumeSSEStream(res, (token) => process.stdout.write(token), () => process.stdout.write('\n'));
75
+ }
76
+ else {
77
+ // Non-streaming response — wait for agent to post via Supabase
78
+ const body = await res.json();
79
+ if (body.error) {
80
+ console.log(chalk.red(`Agent error: ${body.error}`));
81
+ }
82
+ else {
83
+ console.log(chalk.dim('Agent is processing... check the channel for a response.'));
84
+ }
85
+ }
86
+ }
87
+ catch (err) {
88
+ console.log(chalk.red(`Failed to reach agent API: ${err}`));
89
+ }
90
+ }
91
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function channelsCommand(): Promise<void>;
2
+ //# sourceMappingURL=channels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../src/commands/channels.ts"],"names":[],"mappings":"AAIA,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CA2ErD"}
@@ -0,0 +1,67 @@
1
+ import chalk from 'chalk';
2
+ import { getSupabase } from '../supabase.js';
3
+ import { getConfig, setConfig } from '../config.js';
4
+ export async function channelsCommand() {
5
+ const supabase = getSupabase();
6
+ const config = getConfig();
7
+ // Get the user's first workspace if not set
8
+ let workspaceId = config.lastWorkspaceId;
9
+ if (!workspaceId) {
10
+ const { data: member } = await supabase
11
+ .from('workspace_members')
12
+ .select('workspace_id, workspaces(id, name, slug)')
13
+ .limit(1)
14
+ .single();
15
+ if (!member?.workspaces) {
16
+ console.log(chalk.red('No workspaces found'));
17
+ return;
18
+ }
19
+ const ws = member.workspaces;
20
+ workspaceId = ws.id;
21
+ setConfig({ lastWorkspaceId: workspaceId });
22
+ console.log(chalk.dim(`Workspace: ${ws.name}\n`));
23
+ }
24
+ // Fetch channels
25
+ const { data: channels, error } = await supabase
26
+ .from('channels')
27
+ .select('id, name, slug, description, is_private')
28
+ .eq('workspace_id', workspaceId)
29
+ .order('name');
30
+ if (error) {
31
+ console.log(chalk.red(`Error: ${error.message}`));
32
+ return;
33
+ }
34
+ if (!channels || channels.length === 0) {
35
+ console.log(chalk.dim('No channels found'));
36
+ return;
37
+ }
38
+ // Fetch unread counts
39
+ const { data: unreads } = await supabase.rpc('get_unread_counts', {
40
+ p_workspace_id: workspaceId,
41
+ p_user_id: config.userId,
42
+ });
43
+ const unreadMap = new Map();
44
+ if (unreads) {
45
+ for (const u of unreads) {
46
+ unreadMap.set(u.channel_id, { count: u.unread_count, mention: u.has_mention });
47
+ }
48
+ }
49
+ console.log(chalk.bold('Channels'));
50
+ console.log();
51
+ for (const ch of channels) {
52
+ const prefix = ch.is_private ? '🔒' : '#';
53
+ const unread = unreadMap.get(ch.id);
54
+ let line = ` ${prefix} ${ch.name}`;
55
+ if (unread && unread.count > 0) {
56
+ const badge = unread.mention
57
+ ? chalk.red.bold(` (${unread.count} unread, @mention)`)
58
+ : chalk.yellow(` (${unread.count} unread)`);
59
+ line += badge;
60
+ }
61
+ if (ch.description) {
62
+ line += chalk.dim(` — ${ch.description}`);
63
+ }
64
+ console.log(line);
65
+ }
66
+ }
67
+ //# sourceMappingURL=channels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.js","sourceRoot":"","sources":["../../src/commands/channels.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function dmCommand(username: string, message: string): Promise<void>;
2
+ //# sourceMappingURL=dm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dm.d.ts","sourceRoot":"","sources":["../../src/commands/dm.ts"],"names":[],"mappings":"AAIA,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkGhF"}
@@ -0,0 +1,86 @@
1
+ import chalk from 'chalk';
2
+ import { getSupabase } from '../supabase.js';
3
+ import { getConfig, setConfig } from '../config.js';
4
+ export async function dmCommand(username, message) {
5
+ const supabase = getSupabase();
6
+ const config = getConfig();
7
+ if (!config.userId) {
8
+ console.log(chalk.red('Not logged in. Run: scindo login'));
9
+ return;
10
+ }
11
+ const displayName = username.replace(/^@/, '');
12
+ let workspaceId = config.lastWorkspaceId;
13
+ if (!workspaceId) {
14
+ const { data: member } = await supabase
15
+ .from('workspace_members')
16
+ .select('workspace_id')
17
+ .limit(1)
18
+ .single();
19
+ if (!member) {
20
+ console.log(chalk.red('No workspaces found'));
21
+ return;
22
+ }
23
+ workspaceId = member.workspace_id;
24
+ setConfig({ lastWorkspaceId: workspaceId });
25
+ }
26
+ // Find user by display name
27
+ const { data: targetProfile } = await supabase
28
+ .from('profiles')
29
+ .select('id, display_name')
30
+ .ilike('display_name', displayName)
31
+ .single();
32
+ if (!targetProfile) {
33
+ console.log(chalk.red(`User "${displayName}" not found`));
34
+ return;
35
+ }
36
+ // Check for existing DM
37
+ const { data: existing } = await supabase
38
+ .from('conversations')
39
+ .select('id, conversation_members!inner(user_id)')
40
+ .eq('workspace_id', workspaceId)
41
+ .eq('is_group', false);
42
+ let conversationId;
43
+ if (existing) {
44
+ const found = existing.find((conv) => {
45
+ const members = conv.conversation_members;
46
+ return (members.some((m) => m.user_id === config.userId) &&
47
+ members.some((m) => m.user_id === targetProfile.id));
48
+ });
49
+ if (found)
50
+ conversationId = found.id;
51
+ }
52
+ // Create conversation if needed
53
+ if (!conversationId) {
54
+ const { data: conv, error: convErr } = await supabase
55
+ .from('conversations')
56
+ .insert({
57
+ workspace_id: workspaceId,
58
+ is_group: false,
59
+ created_by: config.userId,
60
+ })
61
+ .select('id')
62
+ .single();
63
+ if (convErr || !conv) {
64
+ console.log(chalk.red('Failed to create conversation'));
65
+ return;
66
+ }
67
+ conversationId = conv.id;
68
+ await supabase.from('conversation_members').insert([
69
+ { conversation_id: conversationId, user_id: config.userId },
70
+ { conversation_id: conversationId, user_id: targetProfile.id },
71
+ ]);
72
+ }
73
+ // Send message
74
+ const { error } = await supabase.from('messages').insert({
75
+ workspace_id: workspaceId,
76
+ conversation_id: conversationId,
77
+ user_id: config.userId,
78
+ content: message,
79
+ });
80
+ if (error) {
81
+ console.log(chalk.red(`Failed to send: ${error.message}`));
82
+ return;
83
+ }
84
+ console.log(chalk.green(`DM sent to @${targetProfile.display_name}`));
85
+ }
86
+ //# sourceMappingURL=dm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dm.js","sourceRoot":"","sources":["../../src/commands/dm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function loginCommand(): Promise<void>;
2
+ export declare function logoutCommand(): void;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAkDA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA+ClD;AAED,wBAAgB,aAAa,IAAI,IAAI,CAGpC"}
@@ -0,0 +1,95 @@
1
+ import { createClient } from '@supabase/supabase-js';
2
+ import chalk from 'chalk';
3
+ import { setConfig, clearConfig } from '../config.js';
4
+ import * as readline from 'readline';
5
+ function prompt(question, hidden = false) {
6
+ return new Promise((resolve) => {
7
+ const rl = readline.createInterface({
8
+ input: process.stdin,
9
+ output: process.stdout,
10
+ });
11
+ if (hidden) {
12
+ // For password input, disable echo
13
+ const stdin = process.stdin;
14
+ const wasRaw = stdin.isRaw;
15
+ if (stdin.setRawMode)
16
+ stdin.setRawMode(true);
17
+ let input = '';
18
+ process.stdout.write(question);
19
+ const onData = (char) => {
20
+ const c = char.toString();
21
+ if (c === '\n' || c === '\r') {
22
+ if (stdin.setRawMode)
23
+ stdin.setRawMode(wasRaw ?? false);
24
+ stdin.removeListener('data', onData);
25
+ process.stdout.write('\n');
26
+ rl.close();
27
+ resolve(input);
28
+ }
29
+ else if (c === '\u0003') {
30
+ // Ctrl+C
31
+ process.exit(0);
32
+ }
33
+ else if (c === '\u007F' || c === '\b') {
34
+ // Backspace
35
+ input = input.slice(0, -1);
36
+ }
37
+ else {
38
+ input += c;
39
+ }
40
+ };
41
+ stdin.on('data', onData);
42
+ }
43
+ else {
44
+ rl.question(question, (answer) => {
45
+ rl.close();
46
+ resolve(answer);
47
+ });
48
+ }
49
+ });
50
+ }
51
+ export async function loginCommand() {
52
+ console.log(chalk.bold('Scindo Login\n'));
53
+ const supabaseUrl = await prompt('Supabase URL: ');
54
+ if (!supabaseUrl.trim()) {
55
+ console.log(chalk.red('URL is required'));
56
+ return;
57
+ }
58
+ const supabaseAnonKey = await prompt('Supabase Anon Key: ');
59
+ if (!supabaseAnonKey.trim()) {
60
+ console.log(chalk.red('Anon key is required'));
61
+ return;
62
+ }
63
+ const email = await prompt('Email: ');
64
+ if (!email.trim()) {
65
+ console.log(chalk.red('Email is required'));
66
+ return;
67
+ }
68
+ const password = await prompt('Password: ', true);
69
+ if (!password.trim()) {
70
+ console.log(chalk.red('Password is required'));
71
+ return;
72
+ }
73
+ const supabase = createClient(supabaseUrl.trim(), supabaseAnonKey.trim());
74
+ const { data, error } = await supabase.auth.signInWithPassword({
75
+ email: email.trim(),
76
+ password,
77
+ });
78
+ if (error) {
79
+ console.log(chalk.red(`Login failed: ${error.message}`));
80
+ return;
81
+ }
82
+ setConfig({
83
+ supabaseUrl: supabaseUrl.trim(),
84
+ supabaseAnonKey: supabaseAnonKey.trim(),
85
+ accessToken: data.session.access_token,
86
+ refreshToken: data.session.refresh_token,
87
+ userId: data.user.id,
88
+ });
89
+ console.log(chalk.green(`\nLogged in as ${data.user.email}`));
90
+ }
91
+ export function logoutCommand() {
92
+ clearConfig();
93
+ console.log(chalk.green('Logged out'));
94
+ }
95
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface PushOptions {
2
+ channel: string;
3
+ mentionAgent?: boolean;
4
+ }
5
+ export declare function pushCommand(options: PushOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAQA,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA4GrE"}
@@ -0,0 +1,100 @@
1
+ import chalk from 'chalk';
2
+ import { getSupabase } from '../supabase.js';
3
+ import { getConfig, setConfig } from '../config.js';
4
+ import { consumeSSEStream } from '../stream.js';
5
+ const AGENT_USER_ID = process.env.SCINDO_AGENT_USER_ID ?? '';
6
+ const APP_URL = process.env.SCINDO_APP_URL ?? 'https://app.scindo.one';
7
+ export async function pushCommand(options) {
8
+ const supabase = getSupabase();
9
+ const config = getConfig();
10
+ if (!config.userId) {
11
+ console.log(chalk.red('Not logged in. Run: scindo login'));
12
+ return;
13
+ }
14
+ // Read stdin
15
+ const chunks = [];
16
+ for await (const chunk of process.stdin) {
17
+ chunks.push(chunk);
18
+ }
19
+ let content = Buffer.concat(chunks).toString().trim();
20
+ if (!content) {
21
+ console.log(chalk.red('No input received from stdin'));
22
+ return;
23
+ }
24
+ const slug = options.channel.replace(/^#/, '');
25
+ let workspaceId = config.lastWorkspaceId;
26
+ if (!workspaceId) {
27
+ const { data: member } = await supabase
28
+ .from('workspace_members')
29
+ .select('workspace_id')
30
+ .limit(1)
31
+ .single();
32
+ if (!member) {
33
+ console.log(chalk.red('No workspaces found'));
34
+ return;
35
+ }
36
+ workspaceId = member.workspace_id;
37
+ setConfig({ lastWorkspaceId: workspaceId });
38
+ }
39
+ // Find channel
40
+ const { data: channel, error: chErr } = await supabase
41
+ .from('channels')
42
+ .select('id, name')
43
+ .eq('workspace_id', workspaceId)
44
+ .eq('slug', slug)
45
+ .single();
46
+ if (chErr || !channel) {
47
+ console.log(chalk.red(`Channel #${slug} not found`));
48
+ return;
49
+ }
50
+ // Optionally mention agent
51
+ const mentions = [];
52
+ if (options.mentionAgent && AGENT_USER_ID) {
53
+ content = `@Scindo ${content}`;
54
+ mentions.push(AGENT_USER_ID);
55
+ }
56
+ // Send message
57
+ const { error: sendErr } = await supabase.from('messages').insert({
58
+ workspace_id: workspaceId,
59
+ channel_id: channel.id,
60
+ user_id: config.userId,
61
+ content,
62
+ mentions: mentions.length > 0 ? mentions : undefined,
63
+ });
64
+ if (sendErr) {
65
+ console.log(chalk.red(`Failed to send: ${sendErr.message}`));
66
+ return;
67
+ }
68
+ console.log(chalk.green(`Pushed to #${channel.name}`));
69
+ // If agent mentioned, trigger streaming response
70
+ if (options.mentionAgent && AGENT_USER_ID) {
71
+ try {
72
+ const res = await fetch(`${APP_URL}/api/agent/channel-respond`, {
73
+ method: 'POST',
74
+ headers: {
75
+ 'Content-Type': 'application/json',
76
+ 'Authorization': `Bearer ${config.accessToken}`,
77
+ },
78
+ body: JSON.stringify({
79
+ channelId: channel.id,
80
+ workspaceId,
81
+ stream: true,
82
+ }),
83
+ });
84
+ const contentType = res.headers.get('content-type') ?? '';
85
+ if (contentType.includes('text/event-stream')) {
86
+ await consumeSSEStream(res, (token) => process.stdout.write(token), () => process.stdout.write('\n'));
87
+ }
88
+ else {
89
+ const body = await res.json();
90
+ if (body.error) {
91
+ console.log(chalk.red(`Agent error: ${body.error}`));
92
+ }
93
+ }
94
+ }
95
+ catch (err) {
96
+ console.log(chalk.red(`Failed to reach agent API: ${err}`));
97
+ }
98
+ }
99
+ }
100
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function readCommand(channelName: string, options: {
2
+ limit?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=read.d.ts.map