@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.
- package/README.md +136 -0
- package/dist/commands/agent.d.ts +2 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +91 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/channels.d.ts +2 -0
- package/dist/commands/channels.d.ts.map +1 -0
- package/dist/commands/channels.js +67 -0
- package/dist/commands/channels.js.map +1 -0
- package/dist/commands/dm.d.ts +2 -0
- package/dist/commands/dm.d.ts.map +1 -0
- package/dist/commands/dm.js +86 -0
- package/dist/commands/dm.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +95 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/push.d.ts +7 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +100 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/read.d.ts +4 -0
- package/dist/commands/read.d.ts.map +1 -0
- package/dist/commands/read.js +93 -0
- package/dist/commands/read.js.map +1 -0
- package/dist/commands/send.d.ts +2 -0
- package/dist/commands/send.d.ts.map +1 -0
- package/dist/commands/send.js +49 -0
- package/dist/commands/send.js.map +1 -0
- package/dist/commands/thread.d.ts +3 -0
- package/dist/commands/thread.d.ts.map +1 -0
- package/dist/commands/thread.js +123 -0
- package/dist/commands/thread.js.map +1 -0
- package/dist/commands/unread.d.ts +2 -0
- package/dist/commands/unread.d.ts.map +1 -0
- package/dist/commands/unread.js +91 -0
- package/dist/commands/unread.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +30 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +83 -0
- package/dist/index.js.map +1 -0
- package/dist/stream.d.ts +5 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +55 -0
- package/dist/stream.js.map +1 -0
- package/dist/supabase.d.ts +4 -0
- package/dist/supabase.d.ts.map +1 -0
- package/dist/supabase.js +42 -0
- package/dist/supabase.js.map +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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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"}
|