allaboard 0.4.0 → 0.6.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 +9 -7
- package/dist/agent/claude/backend.js +73 -2
- package/dist/agent/claude/capabilities.js +4 -0
- package/dist/agent/claude/module.js +55 -0
- package/dist/agent/claude/translate.js +6 -2
- package/dist/agent/claude/trust.js +22 -0
- package/dist/chat/seam.js +3 -0
- package/dist/chat/slack/app/app.js +52 -4
- package/dist/chat/slack/app/delete-thread.js +90 -0
- package/dist/chat/slack/app/guards.js +44 -0
- package/dist/chat/slack/app/home-controls.js +8 -1
- package/dist/chat/slack/channels.js +23 -5
- package/dist/chat/slack/delete-thread.js +37 -0
- package/dist/chat/slack/delete.js +13 -7
- package/dist/chat/slack/home.js +194 -35
- package/dist/chat/slack/module.js +64 -14
- package/dist/chat/slack/onboarding.js +159 -0
- package/dist/chat/slack/reply/blocks.js +27 -11
- package/dist/chat/slack/reply/sinks.js +3 -1
- package/dist/chat/slack/tag.js +317 -0
- package/dist/chat/slack/texts.js +8 -0
- package/dist/chat/slack/thread.js +62 -2
- package/dist/chat/slack/tokens.js +15 -0
- package/dist/cli.js +43 -4
- package/dist/core/cleanup.js +66 -3
- package/dist/core/commands.js +40 -0
- package/dist/core/config.js +19 -11
- package/dist/core/files/listing.js +19 -0
- package/dist/core/flows/bind.js +29 -6
- package/dist/core/flows/flows.js +2 -0
- package/dist/core/flows/gone.js +39 -0
- package/dist/core/flows/inbound.js +3 -0
- package/dist/core/flows/messages.js +4 -2
- package/dist/core/flows/status.js +98 -48
- package/dist/core/flows/words.js +80 -1
- package/dist/core/guide.js +2 -0
- package/dist/core/port/cleanup.js +1 -0
- package/dist/core/port.js +1 -0
- package/dist/core/sessions/directory.js +47 -8
- package/dist/core/sessions/manager.js +32 -17
- package/dist/core/sessions/quote.js +57 -0
- package/dist/core/sessions/session.js +324 -35
- package/dist/core/sessions/title.js +98 -0
- package/dist/core/state.js +25 -0
- package/dist/core/texts.js +58 -3
- package/dist/core/wizard.js +306 -0
- package/dist/daemon.js +23 -11
- package/dist/host/program.js +22 -7
- package/dist/host/prompter.js +61 -0
- package/dist/module-setup.js +6 -0
- package/dist/version.js +4 -0
- package/package.json +5 -2
- package/slack-app-manifest.json +2 -1
package/dist/host/program.js
CHANGED
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
* names the copy it was started from.
|
|
5
5
|
*/
|
|
6
6
|
import { accessSync, constants, realpathSync, statSync } from "node:fs";
|
|
7
|
-
import { delimiter, dirname, join } from "node:path";
|
|
8
|
-
/**
|
|
7
|
+
import { delimiter, dirname, isAbsolute, join } from "node:path";
|
|
8
|
+
/**
|
|
9
|
+
* The first executable file called `name` in the absolute folders of `pathVariable`, or null. A
|
|
10
|
+
* relative folder (`.`) names the caller's working folder, which a service does not share.
|
|
11
|
+
*/
|
|
9
12
|
export function findOnPath(name, pathVariable) {
|
|
10
13
|
for (const folder of pathVariable.split(delimiter)) {
|
|
11
|
-
if (folder
|
|
14
|
+
if (!isAbsolute(folder))
|
|
12
15
|
continue;
|
|
13
16
|
const candidate = join(folder, name);
|
|
14
17
|
try {
|
|
@@ -27,20 +30,32 @@ export function findOnPath(name, pathVariable) {
|
|
|
27
30
|
const GLOBAL_ENTRY = /^(.*)\/lib\/node_modules\/allaboard\/dist\/main\.js$/;
|
|
28
31
|
/**
|
|
29
32
|
* The program of the running command: `entry` is `process.argv[1]` (npm's link in its `bin`
|
|
30
|
-
* folder, resolved here), `pathVariable` the caller's `PATH`, `execPath` the fallback Node
|
|
33
|
+
* folder, resolved here), `pathVariable` the caller's `PATH`, `execPath` the fallback Node,
|
|
34
|
+
* `executables` the agents' own, each kept only when the caller's `PATH` finds it.
|
|
31
35
|
*/
|
|
32
|
-
export function programOf(entry, pathVariable, execPath) {
|
|
36
|
+
export function programOf(entry, pathVariable, execPath, executables = []) {
|
|
33
37
|
const main = realpathSync(entry);
|
|
34
38
|
const prefix = GLOBAL_ENTRY.exec(main)?.[1];
|
|
35
39
|
return {
|
|
36
40
|
node: findOnPath("node", pathVariable) ?? execPath,
|
|
37
41
|
main,
|
|
38
42
|
npmBin: prefix === undefined ? null : join(prefix, "bin"),
|
|
43
|
+
agentExecutables: executables.flatMap((name) => findOnPath(name, pathVariable) ?? []),
|
|
39
44
|
};
|
|
40
45
|
}
|
|
41
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* The folders of the service's `PATH`: Node's own first, then npm's, then the agents' executables'
|
|
48
|
+
* not among the system's, then the system's in their order.
|
|
49
|
+
*/
|
|
42
50
|
export function servicePath(program, system) {
|
|
43
|
-
const folders = [
|
|
51
|
+
const folders = [
|
|
52
|
+
dirname(program.node),
|
|
53
|
+
program.npmBin,
|
|
54
|
+
...program.agentExecutables
|
|
55
|
+
.map((path) => dirname(path))
|
|
56
|
+
.filter((path) => !system.includes(path)),
|
|
57
|
+
...system,
|
|
58
|
+
];
|
|
44
59
|
return [...new Set(folders.filter((folder) => folder !== null))].join(":");
|
|
45
60
|
}
|
|
46
61
|
/** The package folder of the copy whose entry file is `main`: the folder above `dist/`. */
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads one answer from the terminal for `allaboard setup`, with `@inquirer/password` for a secret
|
|
3
|
+
* (it shows an asterisk for each character), `@inquirer/input` for any other answer and
|
|
4
|
+
* `@inquirer/select` for every pick from a list (the chat, the agent, the yes or no). Each prompt clears itself once answered: the wizard
|
|
5
|
+
* prints the answer line, so the terminal holds one line per answer whatever the length of the
|
|
6
|
+
* token. All of them end without an answer when the owner presses Ctrl-C or Ctrl-D, and so does
|
|
7
|
+
* the end of the input.
|
|
8
|
+
*/
|
|
9
|
+
/** The prefix of a question waiting for its answer; the answered question is cleared, not drawn. */
|
|
10
|
+
const THEME = { prefix: { idle: "?", done: "" } };
|
|
11
|
+
/**
|
|
12
|
+
* Runs `prompt` with a signal that aborts on Ctrl-D and on the end of the input, and returns null
|
|
13
|
+
* when it ends that way or by Ctrl-C. The library settles only on Ctrl-C or process exit, which is
|
|
14
|
+
* why the other two are listened for here.
|
|
15
|
+
*/
|
|
16
|
+
async function until(prompt) {
|
|
17
|
+
const ended = new AbortController();
|
|
18
|
+
const onEnd = () => ended.abort();
|
|
19
|
+
const onKey = (_text, key) => {
|
|
20
|
+
if (key?.ctrl === true && key.name === "d")
|
|
21
|
+
ended.abort();
|
|
22
|
+
};
|
|
23
|
+
process.stdin.once("end", onEnd);
|
|
24
|
+
process.stdin.on("keypress", onKey);
|
|
25
|
+
try {
|
|
26
|
+
return await prompt({ signal: ended.signal, clearPromptOnDone: true });
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (error instanceof Error &&
|
|
30
|
+
(error.name === "ExitPromptError" || error.name === "AbortPromptError")) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
process.stdin.off("end", onEnd);
|
|
37
|
+
process.stdin.off("keypress", onKey);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** The line typed after `message`, or null when the owner ended the wizard. */
|
|
41
|
+
export async function askTerminal(message, secret) {
|
|
42
|
+
// Loaded here: the daemon starts through this graph and never needs the prompt library.
|
|
43
|
+
if (secret) {
|
|
44
|
+
const { default: password } = await import("@inquirer/password");
|
|
45
|
+
// A token stays hidden, so the show-it key and its tip go. The mask is a single character
|
|
46
|
+
// per keystroke; the answer line the wizard prints shows a fixed one.
|
|
47
|
+
return until((context) => password({ message, mask: "*", toggleMask: false, theme: THEME }, context));
|
|
48
|
+
}
|
|
49
|
+
const { default: input } = await import("@inquirer/input");
|
|
50
|
+
return until((context) => input({ message, theme: THEME }, context));
|
|
51
|
+
}
|
|
52
|
+
/** The name the owner picks from `names` (arrow keys, Enter), `preselected` first; null when they ended the wizard. */
|
|
53
|
+
export async function chooseTerminal(message, names, preselected) {
|
|
54
|
+
const { default: select } = await import("@inquirer/select");
|
|
55
|
+
return until((context) => select({
|
|
56
|
+
message,
|
|
57
|
+
choices: [preselected, ...names.filter((name) => name !== preselected)],
|
|
58
|
+
default: preselected,
|
|
59
|
+
theme: THEME,
|
|
60
|
+
}, context));
|
|
61
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a module (an agent back end or a chat provider) tells `allaboard setup` to ask of the owner
|
|
3
|
+
* to write its variables into `.env`. The types live here, outside both seams, because both seams
|
|
4
|
+
* use them and a seam imports nothing of the core.
|
|
5
|
+
*/
|
|
6
|
+
export {};
|
package/dist/version.js
CHANGED
|
@@ -48,6 +48,10 @@ export function installedVersion() {
|
|
|
48
48
|
export function changelogOf(version) {
|
|
49
49
|
return `${REPOSITORY}/blob/v${version}/docs/CHANGELOG.md`;
|
|
50
50
|
}
|
|
51
|
+
/** The address of the page of what differs from the terminal, as published with the version that runs. */
|
|
52
|
+
export function limitsPage() {
|
|
53
|
+
return `${REPOSITORY}/blob/v${installedVersion()}/docs/limits.md`;
|
|
54
|
+
}
|
|
51
55
|
/** The address of `section` of the setup guide, as published with the version that runs. */
|
|
52
56
|
export function setupGuide(section) {
|
|
53
57
|
return `${REPOSITORY}/blob/v${installedVersion()}/docs/setup.md#${section}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "allaboard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Your Claude Code workspace in Slack: one channel per project, one thread per session, running on your own Mac.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"slack",
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
"node": ">=22.19.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
26
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.304",
|
|
27
|
+
"@inquirer/input": "5.1.7",
|
|
28
|
+
"@inquirer/password": "5.2.3",
|
|
29
|
+
"@inquirer/select": "5.2.6",
|
|
27
30
|
"@slack/bolt": "5.1.0",
|
|
28
31
|
"@slack/web-api": "8.2.0"
|
|
29
32
|
},
|