@cursor/july 0.1.96 → 0.1.97
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 +3 -2
- package/dist/bin/agent-serve.js +14 -3
- package/dist/channels/origin/api.d.ts +15 -4
- package/dist/channels/origin/api.d.ts.map +1 -1
- package/dist/channels/origin/api.js +19 -3
- package/dist/channels/origin/binding.d.ts +11 -0
- package/dist/channels/origin/binding.d.ts.map +1 -1
- package/dist/channels/origin/binding.js +41 -25
- package/dist/channels/origin/index.d.ts +1 -0
- package/dist/channels/origin/index.d.ts.map +1 -1
- package/dist/channels/origin/index.js +1 -0
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +3 -0
- package/dist/channels/origin/reactions.d.ts +56 -0
- package/dist/channels/origin/reactions.d.ts.map +1 -0
- package/dist/channels/origin/reactions.js +67 -0
- package/dist/channels/origin/types.d.ts +11 -0
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/approvals.d.ts +16 -0
- package/dist/channels/slack/approvals.d.ts.map +1 -1
- package/dist/channels/slack/approvals.js +86 -0
- package/dist/channels/slack/cli-project.d.ts +19 -0
- package/dist/channels/slack/cli-project.d.ts.map +1 -0
- package/dist/channels/slack/cli-project.js +234 -0
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +97 -39
- package/dist/channels/slack/init.d.ts +3 -2
- package/dist/channels/slack/init.d.ts.map +1 -1
- package/dist/channels/slack/init.js +5 -5
- package/dist/channels/slack/interactive.d.ts +2 -1
- package/dist/channels/slack/interactive.d.ts.map +1 -1
- package/dist/channels/slack/interactive.js +15 -4
- package/dist/channels/slack/manifest.d.ts +1 -1
- package/dist/channels/slack/manifest.js +1 -1
- package/dist/channels/slack/setup.d.ts +1 -1
- package/dist/channels/slack/setup.d.ts.map +1 -1
- package/dist/channels/slack/setup.js +10 -6
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +1 -0
- package/dist/channels/slack/tool-approval-events.d.ts.map +1 -1
- package/dist/channels/slack/tool-approval-events.js +91 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.jXleCmOc.js → app.B3rWNYE1.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BU9nHdnQ.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.8LhyglIT.js → VPLocalSearchBox.C1lhqJJR.js} +1 -1
- package/dist/docs/assets/chunks/{theme.9ged-pr2.js → theme.B40_SXuv.js} +2 -2
- package/dist/docs/assets/{deployment.md.D9msOFOW.js → deployment.md.MFPKqsqI.js} +2 -2
- package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.js → guides_mcp-oauth.md.CN-6YmTJ.js} +4 -4
- package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.lean.js → guides_mcp-oauth.md.CN-6YmTJ.lean.js} +1 -1
- package/dist/docs/assets/guides_slack.md.VDXQV3ja.js +22 -0
- package/dist/docs/assets/guides_slack.md.VDXQV3ja.lean.js +1 -0
- package/dist/docs/assets/index.md.CVeRUOeZ.js +5 -0
- package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.js → reference_agent-config.md.BHeYMgme.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CCnG-nJx.js → reference_cli.md.RyZf5OTE.js} +9 -6
- package/dist/docs/assets/{reference_cli.md.CCnG-nJx.lean.js → reference_cli.md.RyZf5OTE.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.js → reference_connections.md.DxldvyIB.js} +4 -3
- package/dist/docs/assets/{reference_http-api.md.D89k1mdm.js → reference_http-api.md.5zOAbV86.js} +1 -1
- package/dist/docs/assets/reference_sessions.md.NxFP_CAC.js +1 -0
- package/dist/docs/assets/{reference_tools.md.BHeXn2id.js → reference_tools.md.B84gw9Ii.js} +1 -1
- package/dist/docs/assets/templates_agents-md.md.CXSMZljE.js +2 -0
- package/dist/docs/assets/templates_agents-md.md.CXSMZljE.lean.js +1 -0
- package/dist/docs/assets/troubleshooting.md.DCiPBhYs.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +7 -7
- package/dist/docs/deployment.md +5 -4
- package/dist/docs/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +8 -8
- package/dist/docs/guides/mcp-oauth.md +26 -8
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +17 -33
- package/dist/docs/guides/slack.md +92 -201
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +5 -3
- package/dist/docs/llms-full.txt +299 -653
- package/dist/docs/llms.txt +2 -2
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/agent-config.md +2 -2
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +13 -10
- package/dist/docs/reference/cli.md +38 -16
- package/dist/docs/reference/connections.html +9 -8
- package/dist/docs/reference/connections.md +6 -3
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/http-api.md +2 -1
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/sessions.md +4 -2
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +6 -6
- package/dist/docs/reference/tools.md +9 -2
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +28 -0
- package/dist/docs/templates/agents-md.md +105 -0
- package/dist/docs/templates/code-wiki.html +5 -5
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +5 -5
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +2 -2
- package/dist/evals/run-facts.d.ts.map +1 -1
- package/dist/evals/run-facts.js +27 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +15 -9
- package/dist/internal/approval-gate.d.ts +12 -13
- package/dist/internal/approval-gate.d.ts.map +1 -1
- package/dist/internal/approval-gate.js +16 -21
- package/dist/internal/chat-client.js +10 -0
- package/dist/internal/cli-deploy.d.ts +5 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +50 -17
- package/dist/internal/cli-mcp-oauth.js +8 -18
- package/dist/internal/cli-slack-manual.d.ts +24 -2
- package/dist/internal/cli-slack-manual.d.ts.map +1 -1
- package/dist/internal/cli-slack-manual.js +251 -20
- package/dist/internal/cli-slack.d.ts +9 -2
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +29 -82
- package/dist/internal/cursor/account-mcp.d.ts +1 -0
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +17 -0
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/deploy-client.d.ts +17 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +31 -10
- package/dist/internal/env-file.d.ts +19 -0
- package/dist/internal/env-file.d.ts.map +1 -0
- package/dist/internal/env-file.js +90 -0
- package/dist/internal/framework-file-storage.d.ts +1 -1
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +6 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +7 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +7 -0
- package/dist/internal/hosted-delivery.d.ts +6 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +63 -22
- package/dist/internal/hosted-execution-diag.d.ts +48 -0
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -0
- package/dist/internal/hosted-execution-diag.js +150 -0
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +81 -1
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +2 -0
- package/dist/internal/logs-client.d.ts +5 -0
- package/dist/internal/logs-client.d.ts.map +1 -1
- package/dist/internal/logs-client.js +5 -0
- package/dist/internal/mcp-endpoint.js +2 -3
- package/dist/internal/mcp-host.d.ts +10 -0
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +57 -8
- package/dist/internal/mcp-oauth-on-demand.d.ts +68 -0
- package/dist/internal/mcp-oauth-on-demand.d.ts.map +1 -0
- package/dist/internal/mcp-oauth-on-demand.js +287 -0
- package/dist/internal/mcp-oauth-persist.d.ts +42 -0
- package/dist/internal/mcp-oauth-persist.d.ts.map +1 -0
- package/dist/internal/mcp-oauth-persist.js +92 -0
- package/dist/internal/mcp-oauth.d.ts +1 -0
- package/dist/internal/mcp-oauth.d.ts.map +1 -1
- package/dist/internal/mcp-oauth.js +10 -2
- package/dist/internal/otel/collector.d.ts.map +1 -1
- package/dist/internal/otel/collector.js +22 -9
- package/dist/internal/server.d.ts +3 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +49 -22
- package/dist/internal/session-engine.d.ts +88 -3
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +515 -43
- package/dist/internal/sessions-client.d.ts +9 -7
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +3 -1
- package/dist/internal/storage-coordinator.d.ts +7 -0
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +28 -5
- package/dist/internal/storage-roles.d.ts +5 -0
- package/dist/internal/storage-roles.d.ts.map +1 -1
- package/dist/internal/stream-progress.d.ts.map +1 -1
- package/dist/internal/stream-progress.js +10 -0
- package/dist/internal/tool-policy.d.ts +9 -1
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +13 -0
- package/dist/internal/trajectory.d.ts.map +1 -1
- package/dist/internal/trajectory.js +10 -0
- package/dist/internal/turn-outbox.d.ts +24 -0
- package/dist/internal/turn-outbox.d.ts.map +1 -0
- package/dist/internal/turn-outbox.js +80 -0
- package/dist/playground/assets/{index-Cx9CclK_.js → index-DrkI6y5O.js} +45 -45
- package/dist/playground/assets/index-DzNGwm7q.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +1 -1
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +12 -0
- package/dist/storage.d.ts +8 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/types.d.ts +63 -7
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +5 -3
- package/docs/deployment.md +5 -4
- package/docs/guides/mcp-oauth.md +26 -8
- package/docs/guides/slack.md +93 -202
- package/docs/reference/agent-config.md +2 -2
- package/docs/reference/cli.md +38 -16
- package/docs/reference/connections.md +6 -3
- package/docs/reference/http-api.md +2 -1
- package/docs/reference/sessions.md +4 -2
- package/docs/reference/tools.md +9 -2
- package/docs/templates/agents-md.md +110 -0
- package/docs/troubleshooting.md +2 -2
- package/package.json +1 -1
- package/skills/create-agent/SKILL.md +2 -1
- package/skills/mcp-auth/SKILL.md +6 -3
- package/skills/setup-slack/SKILL.md +23 -13
- package/src/bin/agent-serve.ts +13 -1
- package/src/channels/origin/api.ts +24 -5
- package/src/channels/origin/binding.ts +55 -26
- package/src/channels/origin/index.ts +1 -0
- package/src/channels/origin/origin-channel.ts +4 -0
- package/src/channels/origin/reactions.ts +82 -0
- package/src/channels/origin/types.ts +11 -0
- package/src/channels/slack/approvals.ts +105 -0
- package/src/channels/slack/cli-project.ts +267 -0
- package/src/channels/slack/defaults.ts +109 -46
- package/src/channels/slack/init.ts +10 -5
- package/src/channels/slack/interactive.ts +35 -9
- package/src/channels/slack/manifest.ts +1 -1
- package/src/channels/slack/setup.ts +10 -6
- package/src/channels/slack/slack-channel.ts +1 -0
- package/src/channels/slack/tool-approval-events.ts +93 -0
- package/src/evals/run-facts.ts +32 -0
- package/src/internal/advertise-tools.ts +31 -10
- package/src/internal/approval-gate.ts +20 -29
- package/src/internal/chat-client.ts +19 -0
- package/src/internal/cli-deploy.ts +79 -9
- package/src/internal/cli-mcp-oauth.ts +7 -21
- package/src/internal/cli-slack-manual.ts +350 -18
- package/src/internal/cli-slack.ts +40 -84
- package/src/internal/cursor/account-mcp.ts +21 -0
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/deploy-client.ts +43 -0
- package/src/internal/env-file.ts +84 -0
- package/src/internal/framework-file-storage.ts +7 -1
- package/src/internal/hosted-delivery-protocol.ts +7 -0
- package/src/internal/hosted-delivery.ts +100 -27
- package/src/internal/hosted-execution-diag.ts +207 -0
- package/src/internal/http-channel.ts +99 -0
- package/src/internal/init-project.ts +2 -0
- package/src/internal/logs-client.ts +5 -0
- package/src/internal/mcp-endpoint.ts +13 -4
- package/src/internal/mcp-host.ts +77 -11
- package/src/internal/mcp-oauth-on-demand.ts +352 -0
- package/src/internal/mcp-oauth-persist.ts +127 -0
- package/src/internal/mcp-oauth.ts +17 -1
- package/src/internal/otel/collector.ts +30 -0
- package/src/internal/server.ts +59 -9
- package/src/internal/session-engine.ts +659 -56
- package/src/internal/sessions-client.ts +17 -8
- package/src/internal/storage-coordinator.ts +38 -8
- package/src/internal/storage-roles.ts +7 -0
- package/src/internal/stream-progress.ts +19 -0
- package/src/internal/tool-policy.ts +18 -0
- package/src/internal/trajectory.ts +10 -0
- package/src/internal/turn-outbox.ts +85 -0
- package/src/storage-backends/cursor-hosted.ts +13 -1
- package/src/storage.ts +12 -0
- package/src/types.ts +68 -8
- package/templates/agents-md/README.md +39 -0
- package/templates/agents-md/agent/agent.ts +8 -0
- package/templates/agents-md/agent/channels/github.ts +10 -0
- package/templates/agents-md/agent/channels/queue.ts +28 -0
- package/templates/agents-md/agent/channels/slack.ts +9 -0
- package/templates/agents-md/agent/instructions.md +39 -0
- package/templates/agents-md/agent/lib/collect.ts +439 -0
- package/templates/agents-md/agent/lib/config.ts +8 -0
- package/templates/agents-md/agent/lib/paths.ts +51 -0
- package/templates/agents-md/agent/schedules/weekly.ts +17 -0
- package/templates/agents-md/agent/tools/apply_agents.ts +226 -0
- package/templates/agents-md/evals/agents.eval.ts +135 -0
- package/templates/agents-md/evals/evals.config.ts +5 -0
- package/templates/agents-md/init.json +38 -0
- package/templates/agents-md/package.json +18 -0
- package/templates/agents-md/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +0 -1
- package/dist/docs/assets/guides_slack.md.C32HsdKk.js +0 -38
- package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +0 -1
- package/dist/docs/assets/index.md.CI93Ltlb.js +0 -5
- package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +0 -1
- package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +0 -1
- package/dist/docs/design/agsh.md +0 -406
- package/dist/playground/assets/index-B1DDvBeC.css +0 -1
- package/docs/design/agsh.md +0 -406
- /package/dist/docs/assets/{deployment.md.D9msOFOW.lean.js → deployment.md.MFPKqsqI.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.CI93Ltlb.lean.js → index.md.CVeRUOeZ.lean.js} +0 -0
- /package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.lean.js → reference_agent-config.md.BHeYMgme.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.lean.js → reference_connections.md.DxldvyIB.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.D89k1mdm.lean.js → reference_http-api.md.5zOAbV86.lean.js} +0 -0
- /package/dist/docs/assets/{reference_sessions.md.D0mIh4KK.lean.js → reference_sessions.md.NxFP_CAC.lean.js} +0 -0
- /package/dist/docs/assets/{reference_tools.md.BHeXn2id.lean.js → reference_tools.md.B84gw9Ii.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.Ctv3T8C2.lean.js → troubleshooting.md.DCiPBhYs.lean.js} +0 -0
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `slack init --manual` and `slack manifest` —
|
|
3
|
-
*
|
|
2
|
+
* `slack init --manual` and `slack manifest` — unmanaged Slack app.
|
|
3
|
+
* Slack CLI create+install when `~/.slack/bin/slack` is present;
|
|
4
|
+
* paste-at-api.slack.com is the fallback. Create/destroy/icon stay
|
|
5
|
+
* in `cli-slack.ts`.
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
|
-
import {
|
|
8
|
+
import { execFile } from "node:child_process";
|
|
9
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
7
10
|
import { basename, join, resolve as resolvePath } from "node:path";
|
|
11
|
+
import { promisify } from "node:util";
|
|
12
|
+
import {
|
|
13
|
+
detectSlackCli,
|
|
14
|
+
parseSlackAuthTeams,
|
|
15
|
+
readSlackCliAppId,
|
|
16
|
+
SLACK_CLI_HOME_BIN,
|
|
17
|
+
type SlackCliEnvironment,
|
|
18
|
+
} from "../channels/slack/cli-project.js";
|
|
8
19
|
import {
|
|
9
20
|
buildSlackManifestPair,
|
|
10
21
|
initSlackManual,
|
|
@@ -12,6 +23,9 @@ import {
|
|
|
12
23
|
} from "../channels/slack/index.js";
|
|
13
24
|
import { describeError } from "./describe-error.js";
|
|
14
25
|
import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
|
|
26
|
+
import { ensureEnvLocalGitignored, upsertEnvFile } from "./env-file.js";
|
|
27
|
+
|
|
28
|
+
const execFileAsync = promisify(execFile);
|
|
15
29
|
|
|
16
30
|
export interface SlackManualCliOptions {
|
|
17
31
|
dir: string;
|
|
@@ -23,14 +37,133 @@ export interface SlackManualCliOptions {
|
|
|
23
37
|
channelPosts?: boolean;
|
|
24
38
|
/** Gate for `slack init`; ignored by `slack manifest`. */
|
|
25
39
|
manual?: boolean;
|
|
40
|
+
/** Require Slack CLI install (fail if missing or install fails). */
|
|
41
|
+
install?: boolean;
|
|
42
|
+
/** Skip Slack CLI install even when the CLI is present. */
|
|
43
|
+
noInstall?: boolean;
|
|
44
|
+
slackTeam?: string;
|
|
45
|
+
prod?: boolean;
|
|
46
|
+
detectSlackCli?: () => string | undefined;
|
|
47
|
+
runSlackCli?: SlackCliExec;
|
|
26
48
|
out?: (text: string) => void;
|
|
27
49
|
err?: (text: string) => void;
|
|
28
50
|
}
|
|
29
51
|
|
|
52
|
+
export interface SlackCliExecRequest {
|
|
53
|
+
bin: string;
|
|
54
|
+
argv: string[];
|
|
55
|
+
cwd: string;
|
|
56
|
+
env?: NodeJS.ProcessEnv;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface SlackCliExecResult {
|
|
60
|
+
code: number;
|
|
61
|
+
stdout: string;
|
|
62
|
+
stderr: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type SlackCliExec = (
|
|
66
|
+
request: SlackCliExecRequest
|
|
67
|
+
) => Promise<SlackCliExecResult>;
|
|
68
|
+
|
|
69
|
+
interface SlackCliInstallResult {
|
|
70
|
+
ok: boolean;
|
|
71
|
+
environment: SlackCliEnvironment;
|
|
72
|
+
team?: string;
|
|
73
|
+
appId?: string;
|
|
74
|
+
error?: string;
|
|
75
|
+
tokens: { bot: boolean; app: boolean };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface SlackCliInstallOptions {
|
|
79
|
+
dir: string;
|
|
80
|
+
bin: string;
|
|
81
|
+
envKeys: { bot: string; app: string };
|
|
82
|
+
environment: SlackCliEnvironment;
|
|
83
|
+
team?: string;
|
|
84
|
+
exec?: SlackCliExec;
|
|
85
|
+
}
|
|
86
|
+
|
|
30
87
|
function errStream(options: SlackManualCliOptions): (text: string) => void {
|
|
31
88
|
return options.err ?? ((text: string) => void process.stderr.write(text));
|
|
32
89
|
}
|
|
33
90
|
|
|
91
|
+
function afterDoctor(prefix?: string): string[] {
|
|
92
|
+
return [
|
|
93
|
+
prefix === undefined
|
|
94
|
+
? `${CLI} slack doctor`
|
|
95
|
+
: `${CLI} slack doctor --prefix ${prefix}`,
|
|
96
|
+
`${CLI} serve --dir . --dev`,
|
|
97
|
+
`${CLI} slack setup`,
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function slackCliEnvironment(prod?: boolean): SlackCliEnvironment {
|
|
102
|
+
return prod === true ? "deployed" : "local";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function slackAppSettingsUrl(appId?: string): string {
|
|
106
|
+
return appId === undefined
|
|
107
|
+
? "https://api.slack.com/apps"
|
|
108
|
+
: `https://api.slack.com/apps/${appId}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function pasteNext(
|
|
112
|
+
envKeys: { bot: string; app: string },
|
|
113
|
+
options: { environment: SlackCliEnvironment; prefix?: string }
|
|
114
|
+
): string[] {
|
|
115
|
+
return [
|
|
116
|
+
"Ask the user to install this Slack app on their workspace",
|
|
117
|
+
`Open ${slackAppSettingsUrl()} → Create from manifest`,
|
|
118
|
+
"Import .slack/manifest.dev.json (then prod)",
|
|
119
|
+
`Install apps; set ${envKeys.bot} + ${envKeys.app}`,
|
|
120
|
+
`Or install Slack CLI to ~/${SLACK_CLI_HOME_BIN}, then slack app install --environment ${options.environment} --team <T> --force`,
|
|
121
|
+
...afterDoctor(options.prefix),
|
|
122
|
+
];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function cliNext(
|
|
126
|
+
cli: string,
|
|
127
|
+
envKeys: { bot: string; app: string },
|
|
128
|
+
options: {
|
|
129
|
+
team?: string;
|
|
130
|
+
environment: SlackCliEnvironment;
|
|
131
|
+
prefix?: string;
|
|
132
|
+
}
|
|
133
|
+
): string[] {
|
|
134
|
+
const workspace = options.team ?? "<T>";
|
|
135
|
+
return [
|
|
136
|
+
"Ask the user to install this Slack app on their workspace",
|
|
137
|
+
`${cli} login --no-prompt`,
|
|
138
|
+
`In Slack send /slackauthticket <ticket>; then ${cli} login --ticket <ticket> --challenge <code>`,
|
|
139
|
+
`${cli} app install --environment ${options.environment} --team ${workspace} --force`,
|
|
140
|
+
`Copy xoxb + xapp (connections:write) from ${slackAppSettingsUrl()} into .env.local as ${envKeys.bot} + ${envKeys.app}`,
|
|
141
|
+
`Fallback: paste .slack/manifest.dev.json at ${slackAppSettingsUrl()}`,
|
|
142
|
+
...afterDoctor(options.prefix),
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function installedNext(
|
|
147
|
+
install: SlackCliInstallResult,
|
|
148
|
+
envKeys: { bot: string; app: string },
|
|
149
|
+
prefix?: string
|
|
150
|
+
): string[] {
|
|
151
|
+
const settings = slackAppSettingsUrl(install.appId);
|
|
152
|
+
const next: string[] = [];
|
|
153
|
+
if (!install.tokens.bot) {
|
|
154
|
+
next.push(
|
|
155
|
+
`Copy the bot token (xoxb-...) from ${settings} into ${envKeys.bot}`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
if (!install.tokens.app) {
|
|
159
|
+
next.push(
|
|
160
|
+
`Mint an app-level token with connections:write at ${settings}; set ${envKeys.app}`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
next.push(...afterDoctor(prefix));
|
|
164
|
+
return next;
|
|
165
|
+
}
|
|
166
|
+
|
|
34
167
|
export async function cmdSlackInit(
|
|
35
168
|
options: SlackManualCliOptions
|
|
36
169
|
): Promise<number> {
|
|
@@ -42,7 +175,7 @@ export async function cmdSlackInit(
|
|
|
42
175
|
|
|
43
176
|
That opens the Cursor dashboard wizard.
|
|
44
177
|
|
|
45
|
-
To install a custom Slack app from a manifest (api.slack.com):
|
|
178
|
+
To install a custom Slack app from a manifest (Slack CLI or api.slack.com):
|
|
46
179
|
|
|
47
180
|
${CLI} slack init --manual --dir .
|
|
48
181
|
`
|
|
@@ -53,6 +186,7 @@ To install a custom Slack app from a manifest (api.slack.com):
|
|
|
53
186
|
const dir = resolvePath(options.dir);
|
|
54
187
|
const out =
|
|
55
188
|
options.out ?? ((text: string) => void process.stdout.write(text));
|
|
189
|
+
const err = errStream(options);
|
|
56
190
|
try {
|
|
57
191
|
const result = await initSlackManual({
|
|
58
192
|
dir,
|
|
@@ -60,32 +194,60 @@ To install a custom Slack app from a manifest (api.slack.com):
|
|
|
60
194
|
envPrefix: options.noPrefix === true ? "" : options.prefix,
|
|
61
195
|
channelPosts: options.channelPosts,
|
|
62
196
|
});
|
|
197
|
+
const cli = (options.detectSlackCli ?? detectSlackCli)();
|
|
198
|
+
const skipInstall = options.noInstall === true;
|
|
199
|
+
const requireInstall = options.install === true && !skipInstall;
|
|
200
|
+
let install: SlackCliInstallResult | undefined;
|
|
201
|
+
if (!skipInstall && cli !== undefined) {
|
|
202
|
+
install = await installSlackApp({
|
|
203
|
+
dir: result.rootDir,
|
|
204
|
+
bin: cli,
|
|
205
|
+
envKeys: result.envKeys,
|
|
206
|
+
environment: slackCliEnvironment(options.prod),
|
|
207
|
+
team: options.slackTeam,
|
|
208
|
+
exec: options.runSlackCli,
|
|
209
|
+
});
|
|
210
|
+
if (!install.ok && requireInstall) {
|
|
211
|
+
err(`${install.error ?? "slack app install failed"}\n`);
|
|
212
|
+
}
|
|
213
|
+
} else if (requireInstall) {
|
|
214
|
+
err(
|
|
215
|
+
`Slack CLI not found (~/${SLACK_CLI_HOME_BIN}). Install it or omit --install and paste at api.slack.com.\n`
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
const ok = !requireInstall || install?.ok === true;
|
|
219
|
+
const next =
|
|
220
|
+
install?.ok === true
|
|
221
|
+
? installedNext(install, result.envKeys, result.envPrefix)
|
|
222
|
+
: cli !== undefined
|
|
223
|
+
? cliNext(cli, result.envKeys, {
|
|
224
|
+
team: install?.team ?? options.slackTeam,
|
|
225
|
+
environment: slackCliEnvironment(options.prod),
|
|
226
|
+
prefix: result.envPrefix,
|
|
227
|
+
})
|
|
228
|
+
: pasteNext(result.envKeys, {
|
|
229
|
+
environment: slackCliEnvironment(options.prod),
|
|
230
|
+
prefix: result.envPrefix,
|
|
231
|
+
});
|
|
63
232
|
out(
|
|
64
233
|
`${JSON.stringify(
|
|
65
234
|
{
|
|
66
|
-
ok
|
|
235
|
+
ok,
|
|
67
236
|
directory: result.rootDir,
|
|
68
237
|
created: result.files,
|
|
69
238
|
envPrefix: result.envPrefix ?? null,
|
|
70
239
|
envKeys: result.envKeys,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
`Install apps; set ${result.envKeys.bot} + ${result.envKeys.app}`,
|
|
75
|
-
result.envPrefix === undefined
|
|
76
|
-
? `${CLI} slack doctor`
|
|
77
|
-
: `${CLI} slack doctor --prefix ${result.envPrefix}`,
|
|
78
|
-
`${CLI} serve --dir . --dev`,
|
|
79
|
-
`${CLI} slack setup`,
|
|
80
|
-
],
|
|
240
|
+
cli: cli ?? null,
|
|
241
|
+
install: install ?? null,
|
|
242
|
+
next,
|
|
81
243
|
},
|
|
82
244
|
null,
|
|
83
245
|
2
|
|
84
246
|
)}\n`
|
|
85
247
|
);
|
|
86
|
-
return 0;
|
|
248
|
+
return ok ? 0 : 1;
|
|
87
249
|
} catch (error) {
|
|
88
|
-
|
|
250
|
+
err(`${describeError(error)}\n`);
|
|
89
251
|
return 1;
|
|
90
252
|
}
|
|
91
253
|
}
|
|
@@ -114,7 +276,7 @@ export async function runSlackManifest(
|
|
|
114
276
|
return 0;
|
|
115
277
|
}
|
|
116
278
|
|
|
117
|
-
const outDir = join(dir, ".
|
|
279
|
+
const outDir = join(dir, ".slack");
|
|
118
280
|
await mkdir(outDir, { recursive: true });
|
|
119
281
|
const written: string[] = [];
|
|
120
282
|
for (const file of slackManifestFileEntries(pair, env)) {
|
|
@@ -125,3 +287,173 @@ export async function runSlackManifest(
|
|
|
125
287
|
process.stdout.write(`${JSON.stringify({ ok: true, written }, null, 2)}\n`);
|
|
126
288
|
return 0;
|
|
127
289
|
}
|
|
290
|
+
|
|
291
|
+
function parseEnvAssignments(text: string): Record<string, string> {
|
|
292
|
+
const out: Record<string, string> = {};
|
|
293
|
+
for (const line of text.split(/\r?\n/)) {
|
|
294
|
+
const trimmed = line.trim();
|
|
295
|
+
if (trimmed === "" || trimmed.startsWith("#")) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const raw = trimmed.startsWith("export ") ? trimmed.slice(7) : trimmed;
|
|
299
|
+
const eq = raw.indexOf("=");
|
|
300
|
+
if (eq <= 0) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
out[raw.slice(0, eq)] = raw.slice(eq + 1);
|
|
304
|
+
}
|
|
305
|
+
return out;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function readDotenv(dir: string): Promise<Record<string, string>> {
|
|
309
|
+
return parseEnvAssignments(
|
|
310
|
+
await readFile(join(dir, ".env"), "utf8").catch(() => "")
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function newToken(
|
|
315
|
+
before: string | undefined,
|
|
316
|
+
after: string | undefined,
|
|
317
|
+
prefix: string
|
|
318
|
+
): string | undefined {
|
|
319
|
+
if (after === undefined || !after.startsWith(prefix) || after === before) {
|
|
320
|
+
return undefined;
|
|
321
|
+
}
|
|
322
|
+
return after;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
async function copySlackCliTokensToLocalEnv(options: {
|
|
326
|
+
dir: string;
|
|
327
|
+
envKeys: { bot: string; app: string };
|
|
328
|
+
before: Record<string, string>;
|
|
329
|
+
}): Promise<{ bot: boolean; app: boolean }> {
|
|
330
|
+
const after = await readDotenv(options.dir);
|
|
331
|
+
const bot = newToken(
|
|
332
|
+
options.before.SLACK_BOT_TOKEN,
|
|
333
|
+
after.SLACK_BOT_TOKEN,
|
|
334
|
+
"xoxb-"
|
|
335
|
+
);
|
|
336
|
+
const app = newToken(
|
|
337
|
+
options.before.SLACK_APP_TOKEN,
|
|
338
|
+
after.SLACK_APP_TOKEN,
|
|
339
|
+
"xapp-"
|
|
340
|
+
);
|
|
341
|
+
const entries: Array<{ key: string; value: string }> = [];
|
|
342
|
+
const wrote = { bot: false, app: false };
|
|
343
|
+
if (bot !== undefined) {
|
|
344
|
+
entries.push({ key: options.envKeys.bot, value: bot });
|
|
345
|
+
wrote.bot = true;
|
|
346
|
+
}
|
|
347
|
+
if (app !== undefined) {
|
|
348
|
+
entries.push({ key: options.envKeys.app, value: app });
|
|
349
|
+
wrote.app = true;
|
|
350
|
+
}
|
|
351
|
+
if (entries.length === 0) {
|
|
352
|
+
return wrote;
|
|
353
|
+
}
|
|
354
|
+
await upsertEnvFile(join(options.dir, ".env.local"), entries);
|
|
355
|
+
await ensureEnvLocalGitignored(options.dir);
|
|
356
|
+
return wrote;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function installSlackApp(
|
|
360
|
+
options: SlackCliInstallOptions
|
|
361
|
+
): Promise<SlackCliInstallResult> {
|
|
362
|
+
const exec = options.exec ?? defaultSlackCliExec;
|
|
363
|
+
const auth = await exec({
|
|
364
|
+
bin: options.bin,
|
|
365
|
+
argv: ["auth", "list"],
|
|
366
|
+
cwd: options.dir,
|
|
367
|
+
});
|
|
368
|
+
const teams = parseSlackAuthTeams(`${auth.stdout}\n${auth.stderr}`);
|
|
369
|
+
if (teams.length === 0) {
|
|
370
|
+
return {
|
|
371
|
+
ok: false,
|
|
372
|
+
environment: options.environment,
|
|
373
|
+
error: "Slack CLI is not logged in. Run slack login --no-prompt.",
|
|
374
|
+
tokens: { bot: false, app: false },
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
let team = options.team;
|
|
378
|
+
if (team === undefined) {
|
|
379
|
+
if (teams.length > 1) {
|
|
380
|
+
return {
|
|
381
|
+
ok: false,
|
|
382
|
+
environment: options.environment,
|
|
383
|
+
error: `Multiple Slack CLI teams (${teams.join(", ")}). Pass --slack-team.`,
|
|
384
|
+
tokens: { bot: false, app: false },
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
team = teams[0];
|
|
388
|
+
}
|
|
389
|
+
const before = await readDotenv(options.dir);
|
|
390
|
+
const installed = await exec({
|
|
391
|
+
bin: options.bin,
|
|
392
|
+
argv: [
|
|
393
|
+
"app",
|
|
394
|
+
"install",
|
|
395
|
+
"--environment",
|
|
396
|
+
options.environment,
|
|
397
|
+
"--force",
|
|
398
|
+
"--team",
|
|
399
|
+
team,
|
|
400
|
+
],
|
|
401
|
+
cwd: options.dir,
|
|
402
|
+
env: { ...process.env, SLACK_ENV: options.environment },
|
|
403
|
+
});
|
|
404
|
+
if (installed.code !== 0) {
|
|
405
|
+
const detail = installed.stderr.trim() || installed.stdout.trim();
|
|
406
|
+
return {
|
|
407
|
+
ok: false,
|
|
408
|
+
environment: options.environment,
|
|
409
|
+
team,
|
|
410
|
+
error:
|
|
411
|
+
detail === "" ? `slack app install exited ${installed.code}` : detail,
|
|
412
|
+
tokens: { bot: false, app: false },
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
await writeFile(
|
|
416
|
+
join(options.dir, ".slack/cli-environment"),
|
|
417
|
+
`${options.environment}\n`
|
|
418
|
+
);
|
|
419
|
+
const appId = await readSlackCliAppId(options.dir, options.environment, team);
|
|
420
|
+
const tokens = await copySlackCliTokensToLocalEnv({
|
|
421
|
+
dir: options.dir,
|
|
422
|
+
envKeys: options.envKeys,
|
|
423
|
+
before,
|
|
424
|
+
});
|
|
425
|
+
return {
|
|
426
|
+
ok: true,
|
|
427
|
+
environment: options.environment,
|
|
428
|
+
team,
|
|
429
|
+
appId,
|
|
430
|
+
tokens,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
async function defaultSlackCliExec(
|
|
435
|
+
request: SlackCliExecRequest
|
|
436
|
+
): Promise<SlackCliExecResult> {
|
|
437
|
+
try {
|
|
438
|
+
const { stdout, stderr } = await execFileAsync(request.bin, request.argv, {
|
|
439
|
+
cwd: request.cwd,
|
|
440
|
+
env: request.env,
|
|
441
|
+
timeout: 120_000,
|
|
442
|
+
});
|
|
443
|
+
return { code: 0, stdout, stderr };
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (!(error instanceof Error)) {
|
|
446
|
+
throw error;
|
|
447
|
+
}
|
|
448
|
+
const execError = error as Error & {
|
|
449
|
+
code?: number | string;
|
|
450
|
+
stdout?: string;
|
|
451
|
+
stderr?: string;
|
|
452
|
+
};
|
|
453
|
+
return {
|
|
454
|
+
code: typeof execError.code === "number" ? execError.code : 1,
|
|
455
|
+
stdout: execError.stdout ?? "",
|
|
456
|
+
stderr: execError.stderr ?? execError.message,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `agent-serve slack …` CLI — doctor, destroy/icon, `create` as a
|
|
3
3
|
* dashboard-wizard launcher (`slack-provision-client.ts`), and
|
|
4
|
-
* `init --manual` for
|
|
4
|
+
* `init --manual` for Slack CLI / paste-at-api.slack.com manifests.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { access,
|
|
7
|
+
import { access, readFile } from "node:fs/promises";
|
|
8
8
|
import { basename, extname, join, resolve as resolvePath } from "node:path";
|
|
9
9
|
import {
|
|
10
10
|
envPrefixFromName,
|
|
@@ -15,12 +15,17 @@ import {
|
|
|
15
15
|
slackEnvKeys,
|
|
16
16
|
} from "../channels/slack/index.js";
|
|
17
17
|
import { resolveDeployAuth } from "./cli-deploy.js";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
cmdSlackInit,
|
|
20
|
+
runSlackManifest,
|
|
21
|
+
type SlackCliExec,
|
|
22
|
+
} from "./cli-slack-manual.js";
|
|
19
23
|
import { cursorExternalApiUrl } from "./cursor/credentials.js";
|
|
20
24
|
import { slugFromDirectoryName } from "./deploy-client.js";
|
|
21
25
|
import { inferDeployGitSource } from "./deploy-source.js";
|
|
22
26
|
import { describeError } from "./describe-error.js";
|
|
23
27
|
import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
|
|
28
|
+
import { ensureEnvLocalGitignored, upsertEnvFile } from "./env-file.js";
|
|
24
29
|
import { loadAgentLocalEnv } from "./local-env.js";
|
|
25
30
|
import { openBrowser } from "./open-browser.js";
|
|
26
31
|
import {
|
|
@@ -60,8 +65,14 @@ export interface SlackCliOptions {
|
|
|
60
65
|
icon?: string;
|
|
61
66
|
/** create: accepted for compatibility; live-app updates always overwrite. */
|
|
62
67
|
force?: boolean;
|
|
63
|
-
/** `slack init --manual`:
|
|
68
|
+
/** `slack init --manual`: Slack CLI project + paste fallback. */
|
|
64
69
|
manual?: boolean;
|
|
70
|
+
/** `slack init --manual`: require Slack CLI install. */
|
|
71
|
+
install?: boolean;
|
|
72
|
+
/** `slack init --manual`: skip Slack CLI install. */
|
|
73
|
+
noInstall?: boolean;
|
|
74
|
+
detectSlackCli?: () => string | undefined;
|
|
75
|
+
runSlackCli?: SlackCliExec;
|
|
65
76
|
/** `slack icon <source>` positional (same URL-or-file forms as --icon). */
|
|
66
77
|
iconSource?: string;
|
|
67
78
|
/** doctor: watched channel ids (`C…`) to verify visibility/membership. */
|
|
@@ -90,6 +101,8 @@ Usage:
|
|
|
90
101
|
[--prod] [--team <id>] [--json]
|
|
91
102
|
${CLI} slack init --manual [--dir .] [--name NAME]
|
|
92
103
|
[--prefix PREFIX | --no-prefix] [--channel-posts]
|
|
104
|
+
[--install | --no-install]
|
|
105
|
+
[--slack-team T0123ABCD] [--prod]
|
|
93
106
|
${CLI} slack manifest --env dev|prod|both [--dir .] [--name NAME]
|
|
94
107
|
[--print]
|
|
95
108
|
${CLI} slack doctor [--dir .] [--prefix PREFIX | --no-prefix] [--json]
|
|
@@ -107,8 +120,13 @@ create/destroy/icon — dedicated Socket Mode app via the Cursor dashboard:
|
|
|
107
120
|
png/jpg/gif file (at most 512KB).
|
|
108
121
|
|
|
109
122
|
\`slack init\` without --manual is not the first-run path. Use \`slack create\`.
|
|
110
|
-
\`slack init --manual\` writes the channel file, manifests
|
|
111
|
-
|
|
123
|
+
\`slack init --manual\` writes the channel file, manifests, a Slack CLI
|
|
124
|
+
\`.slack/\` project (get-manifest → those JSON files), env.example, and
|
|
125
|
+
setup-status.json. When \`~/.slack/bin/slack\` is logged in, it installs
|
|
126
|
+
the app. Otherwise \`next\` asks the user to install it. \`--install\`
|
|
127
|
+
requires that install. \`--no-install\` skips it. \`--prod\` selects the
|
|
128
|
+
deployed app. Paste at api.slack.com is the fallback. Do not
|
|
129
|
+
\`slack deploy\`.
|
|
112
130
|
|
|
113
131
|
Env tokens:
|
|
114
132
|
single agent: SLACK_BOT_TOKEN + SLACK_APP_TOKEN
|
|
@@ -140,7 +158,22 @@ export async function cmdSlack(
|
|
|
140
158
|
case "icon":
|
|
141
159
|
return cmdSlackIcon(options);
|
|
142
160
|
case "init":
|
|
143
|
-
return cmdSlackInit(
|
|
161
|
+
return cmdSlackInit({
|
|
162
|
+
dir: options.dir,
|
|
163
|
+
name: options.name,
|
|
164
|
+
prefix: options.prefix,
|
|
165
|
+
noPrefix: options.noPrefix,
|
|
166
|
+
channelPosts: options.channelPosts,
|
|
167
|
+
manual: options.manual,
|
|
168
|
+
install: options.install,
|
|
169
|
+
noInstall: options.noInstall,
|
|
170
|
+
slackTeam: options.slackTeam,
|
|
171
|
+
detectSlackCli: options.detectSlackCli,
|
|
172
|
+
runSlackCli: options.runSlackCli,
|
|
173
|
+
prod: options.prod,
|
|
174
|
+
out: options.out,
|
|
175
|
+
err: options.err,
|
|
176
|
+
});
|
|
144
177
|
case "manifest":
|
|
145
178
|
return runSlackManifest(options);
|
|
146
179
|
case "doctor":
|
|
@@ -812,83 +845,6 @@ async function scaffoldSlackChannelFiles(
|
|
|
812
845
|
}
|
|
813
846
|
}
|
|
814
847
|
|
|
815
|
-
/**
|
|
816
|
-
* Append `KEY=value` lines to an env file, replacing every existing line
|
|
817
|
-
* for the same key instead of appending duplicates. Creates the file when
|
|
818
|
-
* missing.
|
|
819
|
-
*/
|
|
820
|
-
async function upsertEnvFile(
|
|
821
|
-
path: string,
|
|
822
|
-
entries: Array<{ key: string; value: string }>
|
|
823
|
-
): Promise<void> {
|
|
824
|
-
let existing = "";
|
|
825
|
-
try {
|
|
826
|
-
existing = await readFile(path, "utf8");
|
|
827
|
-
} catch (error) {
|
|
828
|
-
if (!isErrnoException(error) || error.code !== "ENOENT") {
|
|
829
|
-
throw error;
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
const lines =
|
|
833
|
-
existing === "" ? [] : existing.replace(/\r?\n$/, "").split(/\r?\n/);
|
|
834
|
-
// A stale `export KEY=…` line would shadow or duplicate the bare line
|
|
835
|
-
// under some loaders; treat both spellings as the same entry.
|
|
836
|
-
const matchesKey = (line: string, key: string): boolean =>
|
|
837
|
-
line.startsWith(`${key}=`) || line.startsWith(`export ${key}=`);
|
|
838
|
-
for (const { key, value } of entries) {
|
|
839
|
-
const next = `${key}=${value}`;
|
|
840
|
-
let replaced = false;
|
|
841
|
-
for (let i = 0; i < lines.length; ) {
|
|
842
|
-
if (!matchesKey(lines[i] ?? "", key)) {
|
|
843
|
-
i += 1;
|
|
844
|
-
continue;
|
|
845
|
-
}
|
|
846
|
-
if (replaced) {
|
|
847
|
-
lines.splice(i, 1);
|
|
848
|
-
continue;
|
|
849
|
-
}
|
|
850
|
-
lines[i] = next;
|
|
851
|
-
replaced = true;
|
|
852
|
-
i += 1;
|
|
853
|
-
}
|
|
854
|
-
if (!replaced) {
|
|
855
|
-
lines.push(next);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
// writeFile's mode only applies on create; clamp pre-existing files too.
|
|
859
|
-
await writeFile(path, `${lines.join("\n")}\n`, { mode: 0o600 });
|
|
860
|
-
await chmod(path, 0o600);
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
/**
|
|
864
|
-
* Ensure the agent directory's .gitignore covers .env.local (create or
|
|
865
|
-
* append). A bare `.env` line does not count — that pattern matches only
|
|
866
|
-
* the file literally named .env.
|
|
867
|
-
*/
|
|
868
|
-
async function ensureEnvLocalGitignored(dir: string): Promise<boolean> {
|
|
869
|
-
const path = join(dir, ".gitignore");
|
|
870
|
-
let existing = "";
|
|
871
|
-
try {
|
|
872
|
-
existing = await readFile(path, "utf8");
|
|
873
|
-
} catch (error) {
|
|
874
|
-
if (!isErrnoException(error) || error.code !== "ENOENT") {
|
|
875
|
-
throw error;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
const covered = existing
|
|
879
|
-
.split(/\r?\n/)
|
|
880
|
-
.some((line) => /^\.env(\.local\*?|\.\*|\*)$/.test(line.trim()));
|
|
881
|
-
if (covered) {
|
|
882
|
-
return false;
|
|
883
|
-
}
|
|
884
|
-
const next =
|
|
885
|
-
existing === "" || existing.endsWith("\n")
|
|
886
|
-
? `${existing}.env.local\n`
|
|
887
|
-
: `${existing}\n.env.local\n`;
|
|
888
|
-
await writeFile(path, next);
|
|
889
|
-
return true;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
848
|
function renderDoctorReport(result: SlackDoctorResult): string {
|
|
893
849
|
let text = `env: ${result.envKeys.bot} / ${result.envKeys.app}\n`;
|
|
894
850
|
for (const check of result.checks) {
|
|
@@ -253,6 +253,27 @@ export class CursorAccountMcpBridge {
|
|
|
253
253
|
* Returns a promise that settles when every ref's log lines are written —
|
|
254
254
|
* callers may ignore it; tests can await it.
|
|
255
255
|
*/
|
|
256
|
+
async probeAuthUrl(
|
|
257
|
+
ref: CursorAccountConnectionRef
|
|
258
|
+
): Promise<string | undefined> {
|
|
259
|
+
const identifiers =
|
|
260
|
+
ref.servers !== undefined && ref.servers.length > 0
|
|
261
|
+
? [...ref.servers]
|
|
262
|
+
: (await this.client.getAvailableMcpServers()).map(
|
|
263
|
+
(server) => server.serverIdentifier ?? server.name
|
|
264
|
+
);
|
|
265
|
+
const urls = await probeConnectorAuthUrls({
|
|
266
|
+
client: this.client,
|
|
267
|
+
identifiers,
|
|
268
|
+
});
|
|
269
|
+
for (const url of urls.values()) {
|
|
270
|
+
if (url !== "") {
|
|
271
|
+
return url;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return undefined;
|
|
275
|
+
}
|
|
276
|
+
|
|
256
277
|
logPreflight(refs: CursorAccountConnectionRef[]): Promise<void> {
|
|
257
278
|
return Promise.all(refs.map((ref) => this.runPreflight(ref))).then(
|
|
258
279
|
() => undefined
|