@cursor/july 0.1.52 → 0.1.53

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 (112) hide show
  1. package/AGENTS.md +1 -0
  2. package/README.md +4 -2
  3. package/dist/bin/agent-serve.js +2 -0
  4. package/dist/channels/slack/init.d.ts +16 -3
  5. package/dist/channels/slack/init.d.ts.map +1 -1
  6. package/dist/channels/slack/init.js +92 -18
  7. package/dist/channels/slack/manifest.d.ts +8 -0
  8. package/dist/channels/slack/manifest.d.ts.map +1 -1
  9. package/dist/channels/slack/manifest.js +17 -0
  10. package/dist/channels/slack/setup.d.ts +26 -1
  11. package/dist/channels/slack/setup.d.ts.map +1 -1
  12. package/dist/channels/slack/setup.js +107 -25
  13. package/dist/docs/404.html +3 -3
  14. package/dist/docs/ab.html +6 -6
  15. package/dist/docs/assets/{app.Cbeq6FOy.js → app.DAKcDclS.js} +1 -1
  16. package/dist/docs/assets/chunks/@localSearchIndexroot.C4uxzYEU.js +1 -0
  17. package/dist/docs/assets/chunks/{VPLocalSearchBox.Bmb8QjCI.js → VPLocalSearchBox.BNIaCSfG.js} +2 -2
  18. package/dist/docs/assets/chunks/{theme.BLNMeCRL.js → theme.B47GzJjc.js} +2 -2
  19. package/dist/docs/assets/{guides_slack.md.D2nTRu9M.js → guides_slack.md.DP4H75WP.js} +8 -6
  20. package/dist/docs/assets/guides_slack.md.DP4H75WP.lean.js +1 -0
  21. package/dist/docs/assets/{reference_cli.md.CGKfz_Yj.js → reference_cli.md.-V6J7Cl8.js} +7 -3
  22. package/dist/docs/assets/{reference_cli.md.CGKfz_Yj.lean.js → reference_cli.md.-V6J7Cl8.lean.js} +1 -1
  23. package/dist/docs/assets/{style.CK3hwt6q.css → style.kTsvp4pE.css} +1 -1
  24. package/dist/docs/assets/{troubleshooting.md.C6n3wCr6.js → troubleshooting.md.CuVztCKs.js} +1 -1
  25. package/dist/docs/building-with-agents.html +6 -6
  26. package/dist/docs/concepts.html +6 -6
  27. package/dist/docs/deployment.html +6 -6
  28. package/dist/docs/evals.html +6 -6
  29. package/dist/docs/example-agents/approval-buddy.html +6 -6
  30. package/dist/docs/example-agents/benny.html +6 -6
  31. package/dist/docs/example-agents/bugbot.html +6 -6
  32. package/dist/docs/example-agents/codebase-wiki.html +6 -6
  33. package/dist/docs/example-agents/codeowners-review.html +6 -6
  34. package/dist/docs/example-agents/concierge.html +6 -6
  35. package/dist/docs/example-agents/fsd.html +6 -6
  36. package/dist/docs/example-agents/index.html +6 -6
  37. package/dist/docs/example-agents/knowledge-base.html +6 -6
  38. package/dist/docs/example-agents/oncall.html +6 -6
  39. package/dist/docs/example-agents/security-reviewer.html +6 -6
  40. package/dist/docs/example-agents/slack-agent.html +6 -6
  41. package/dist/docs/example-agents/weather-agent.html +6 -6
  42. package/dist/docs/guides/agent-to-agent.html +6 -6
  43. package/dist/docs/guides/cloud-runtime.html +6 -6
  44. package/dist/docs/guides/github.html +6 -6
  45. package/dist/docs/guides/human-in-the-loop.html +6 -6
  46. package/dist/docs/guides/mcp-oauth.html +6 -6
  47. package/dist/docs/guides/opentelemetry.html +6 -6
  48. package/dist/docs/guides/slack.html +14 -12
  49. package/dist/docs/guides/webhooks.html +6 -6
  50. package/dist/docs/hashmap.json +1 -1
  51. package/dist/docs/hillclimbing.html +6 -6
  52. package/dist/docs/index.html +6 -6
  53. package/dist/docs/quickstart.html +6 -6
  54. package/dist/docs/reference/agent-config.html +6 -6
  55. package/dist/docs/reference/artifacts.html +6 -6
  56. package/dist/docs/reference/channels.html +6 -6
  57. package/dist/docs/reference/cli.html +13 -9
  58. package/dist/docs/reference/connections.html +6 -6
  59. package/dist/docs/reference/hooks.html +6 -6
  60. package/dist/docs/reference/http-api.html +6 -6
  61. package/dist/docs/reference/instructions.html +6 -6
  62. package/dist/docs/reference/playground.html +5 -5
  63. package/dist/docs/reference/project-layout.html +6 -6
  64. package/dist/docs/reference/prompt.html +6 -6
  65. package/dist/docs/reference/schedules.html +6 -6
  66. package/dist/docs/reference/sessions.html +6 -6
  67. package/dist/docs/reference/skills.html +6 -6
  68. package/dist/docs/reference/subagents.html +6 -6
  69. package/dist/docs/reference/tools.html +6 -6
  70. package/dist/docs/scaffolding-agents.html +5 -5
  71. package/dist/docs/storage.html +6 -6
  72. package/dist/docs/templates/triage.html +6 -6
  73. package/dist/docs/troubleshooting.html +6 -6
  74. package/dist/internal/cli-deploy.d.ts.map +1 -1
  75. package/dist/internal/cli-deploy.js +8 -18
  76. package/dist/internal/cli-slack-manual.d.ts +20 -0
  77. package/dist/internal/cli-slack-manual.d.ts.map +1 -0
  78. package/dist/internal/cli-slack-manual.js +106 -0
  79. package/dist/internal/cli-slack.d.ts +5 -2
  80. package/dist/internal/cli-slack.d.ts.map +1 -1
  81. package/dist/internal/cli-slack.js +18 -69
  82. package/dist/internal/deploy-client.d.ts +7 -10
  83. package/dist/internal/deploy-client.d.ts.map +1 -1
  84. package/dist/internal/deploy-client.js +1 -3
  85. package/dist/internal/deploy-source.d.ts +1 -1
  86. package/dist/internal/deploy-source.js +1 -1
  87. package/dist/internal/process-memory-telemetry.d.ts +3 -4
  88. package/dist/internal/process-memory-telemetry.d.ts.map +1 -1
  89. package/dist/internal/process-memory-telemetry.js +4 -17
  90. package/dist/playground/assets/{index-BKMz70wx.js → index-BHAPd9KT.js} +31 -31
  91. package/dist/playground/assets/index-DpKH0HcT.css +1 -0
  92. package/dist/playground/index.html +2 -2
  93. package/docs/guides/slack.md +52 -7
  94. package/docs/reference/cli.md +29 -6
  95. package/docs/troubleshooting.md +1 -1
  96. package/package.json +1 -1
  97. package/skills/create-agent/SKILL.md +1 -0
  98. package/skills/setup-slack/SKILL.md +99 -7
  99. package/src/bin/agent-serve.ts +2 -0
  100. package/src/channels/slack/init.ts +130 -20
  101. package/src/channels/slack/manifest.ts +27 -0
  102. package/src/channels/slack/setup.ts +124 -23
  103. package/src/internal/cli-deploy.ts +8 -22
  104. package/src/internal/cli-slack-manual.ts +127 -0
  105. package/src/internal/cli-slack.ts +18 -70
  106. package/src/internal/deploy-client.ts +8 -13
  107. package/src/internal/deploy-source.ts +1 -1
  108. package/src/internal/process-memory-telemetry.ts +5 -24
  109. package/dist/docs/assets/chunks/@localSearchIndexroot.TzAgoWLl.js +0 -1
  110. package/dist/docs/assets/guides_slack.md.D2nTRu9M.lean.js +0 -1
  111. package/dist/playground/assets/index-BmMrulSc.css +0 -1
  112. /package/dist/docs/assets/{troubleshooting.md.C6n3wCr6.lean.js → troubleshooting.md.CuVztCKs.lean.js} +0 -0
@@ -2,32 +2,133 @@
2
2
  * Slack setup guide printed by `agent-serve slack setup`.
3
3
  *
4
4
  * Two products: Cursor-hosted (`cursorAccount`) vs a dedicated Socket
5
- * Mode app via `slack create` (dashboard wizard).
5
+ * Mode app via `slack create` (dashboard wizard). `slack init --manual`
6
+ * is the unmanaged paste-at-api.slack.com path. {@link SLACK_SETUP_PHASES}
7
+ * is that checklist; its ids key `.agent-serve/slack/setup-status.json`.
6
8
  */
7
9
 
8
- export function formatSlackSetupGuide(): string {
9
- return `agent-serve — Slack setup
10
-
11
- Two products. Pick one.
12
-
13
- A) Cursor-hosted (recommended default, zero Slack admin):
14
- slackChannel({ cursorAccount: true, agentName: "MyAgent" })
15
- Sign in (agent-serve login / CURSOR_API_KEY), serve, then mention
16
- "@Cursor MyAgent ..." in the linked workspace. No app, no tokens.
17
-
18
- B) Dedicated Slack app (Socket Mode):
19
- agent-serve slack create --dir .
20
- Opens the signed-in Cursor dashboard wizard. Finish Slack consent
21
- and the bot name there. The CLI writes tokens into .env.local.
22
- Use this when you need your own bot user, channel watching
23
- (engagement.channelPosts), or approval buttons.
10
+ export interface SlackSetupPhase {
11
+ id: string;
12
+ actor: "agent" | "human";
13
+ title: string;
14
+ steps: string[];
15
+ }
24
16
 
25
- Do not paste a manifest at api.slack.com. \`slack init\` is removed.
17
+ export const SLACK_SETUP_PHASES: SlackSetupPhase[] = [
18
+ {
19
+ id: "generate",
20
+ actor: "agent",
21
+ title: "Generate channel + manifests",
22
+ steps: [
23
+ "agent-serve slack init --manual --dir . --name My Agent",
24
+ "Manifests default to Socket Mode (no public Request URL).",
25
+ ],
26
+ },
27
+ {
28
+ id: "createApps",
29
+ actor: "human",
30
+ title: "Create two Slack apps from manifests",
31
+ steps: [
32
+ "Open https://api.slack.com/apps -> Create New App from a manifest",
33
+ "Paste .agent-serve/slack/manifest.dev.json -> create the *dev* app",
34
+ "Repeat with manifest.prod.json for the *prod* app",
35
+ ],
36
+ },
37
+ {
38
+ id: "install",
39
+ actor: "human",
40
+ title: "Install + mint App-Level Token",
41
+ steps: [
42
+ "Install to Workspace; copy Bot User OAuth Token (xoxb-...)",
43
+ "App-Level Tokens: create token with connections:write; copy xapp-...",
44
+ ],
45
+ },
46
+ {
47
+ id: "env",
48
+ actor: "agent",
49
+ title: "Wire environment",
50
+ steps: [
51
+ "Write per-agent tokens into .env.local (see .agent-serve/slack/env.example)",
52
+ "Multi-agent: <PREFIX>_SLACK_BOT_TOKEN + <PREFIX>_SLACK_APP_TOKEN",
53
+ "Single agent: SLACK_BOT_TOKEN + SLACK_APP_TOKEN (--no-prefix)",
54
+ "agent-serve slack doctor --prefix <PREFIX>",
55
+ ],
56
+ },
57
+ {
58
+ id: "serve",
59
+ actor: "agent",
60
+ title: "Serve",
61
+ steps: [
62
+ "agent-serve serve --dir . --dev",
63
+ "Confirm log: [agent-sdk/slack] Socket Mode connected",
64
+ ],
65
+ },
66
+ {
67
+ id: "smoke",
68
+ actor: "human",
69
+ title: "Smoke test",
70
+ steps: [
71
+ "Invite the bot to a channel",
72
+ "@mention it or DM it",
73
+ "Confirm logs: inbound → session start → reply delivered",
74
+ "Confirm streaming reply and rotating status",
75
+ ],
76
+ },
77
+ ];
26
78
 
27
- Then:
28
- - agent-serve serve --dir . --dev
29
- - Invite the bot (Path B) or mention @Cursor <name> (Path A)
79
+ /** Seed `.agent-serve/slack/setup-status.json` after `slack init --manual`. */
80
+ export function initialSlackSetupStatus(options: {
81
+ envPrefix: string | undefined;
82
+ envKeys: { bot: string; app: string };
83
+ }): {
84
+ updatedAt: string;
85
+ envPrefix: string | null;
86
+ envKeys: { bot: string; app: string };
87
+ phases: Record<string, boolean>;
88
+ } {
89
+ const completed = SLACK_SETUP_PHASES[0]?.id;
90
+ return {
91
+ updatedAt: new Date().toISOString(),
92
+ envPrefix: options.envPrefix ?? null,
93
+ envKeys: options.envKeys,
94
+ phases: Object.fromEntries(
95
+ SLACK_SETUP_PHASES.map((phase) => [phase.id, phase.id === completed])
96
+ ),
97
+ };
98
+ }
30
99
 
31
- Skill: packages/agent-serve/skills/setup-slack/SKILL.md
32
- `;
100
+ export function formatSlackSetupGuide(): string {
101
+ const lines: string[] = [
102
+ "agent-serve — Slack setup",
103
+ "",
104
+ "Two products. Pick one.",
105
+ "",
106
+ " A) Cursor-hosted (recommended default, zero Slack admin):",
107
+ ' slackChannel({ cursorAccount: true, agentName: "MyAgent" })',
108
+ " Sign in (agent-serve login / CURSOR_API_KEY), serve, then mention",
109
+ ' "@Cursor MyAgent ..." in the linked workspace. No app, no tokens.',
110
+ " B) Dedicated Slack app (Socket Mode) via the dashboard wizard:",
111
+ " agent-serve slack create --dir .",
112
+ " Finish Slack consent and the bot name there. The CLI writes",
113
+ " tokens into .env.local. Use this when you need your own bot",
114
+ " user, channel watching, or approval buttons.",
115
+ "",
116
+ "Manual Slack app: `slack init --manual`. Phases below.",
117
+ "Goal: importable dev + prod Slack apps over Socket Mode (no public URL).",
118
+ "App-Level Token (xapp-...) + Bot Token (xoxb-...) required.",
119
+ "",
120
+ ];
121
+ for (const [index, phase] of SLACK_SETUP_PHASES.entries()) {
122
+ lines.push(`## Phase ${index} — ${phase.title} (${phase.actor})`);
123
+ for (const step of phase.steps) {
124
+ lines.push(` - ${step}`);
125
+ }
126
+ lines.push("");
127
+ }
128
+ lines.push("Status file: .agent-serve/slack/setup-status.json");
129
+ lines.push(
130
+ "Skill (Cursor): packages/agent-serve/skills/setup-slack/SKILL.md"
131
+ );
132
+ lines.push("");
133
+ return lines.join("\n");
33
134
  }
@@ -405,7 +405,7 @@ async function resolveDeployTargets(
405
405
  );
406
406
  return 1;
407
407
  }
408
- // Static / bare-slug deploy against a non-agent directory.
408
+ // Bare-slug deploy against a non-agent directory (still requires --repo).
409
409
  let slug: string;
410
410
  if (options.slug !== undefined) {
411
411
  slug = options.slug;
@@ -419,9 +419,7 @@ async function resolveDeployTargets(
419
419
  }
420
420
  slug = derived;
421
421
  if (!ctx.json) {
422
- ctx.err(
423
- `Deploying as "${slug}" (static; no agent project at ${dir}).\n`
424
- );
422
+ ctx.err(`Deploying as "${slug}" (no agent project at ${dir}).\n`);
425
423
  }
426
424
  }
427
425
  return [{ slug, dir }];
@@ -586,21 +584,10 @@ async function deployOne(
586
584
  );
587
585
  return 1;
588
586
  }
589
- // Repo-backed fields without a resolvable https origin become a static
590
- // deploy body the control plane rejects. Fail here with a fix hint —
591
- // common when origin is an unrecognized SSH shape (pass --repo).
592
- if (
593
- gitRepoUrl === undefined &&
594
- (gitRef !== undefined ||
595
- agentPath !== undefined ||
596
- (options.cursorEventsRepos !== undefined &&
597
- options.cursorEventsRepos.length > 0) ||
598
- (options.allowDomains !== undefined && options.allowDomains.length > 0))
599
- ) {
587
+ if (gitRepoUrl === undefined) {
600
588
  ctx.err(
601
589
  `Could not resolve an https:// git repository URL for this deploy.\n` +
602
- ` Pass --repo https://github.com/<owner>/<repo> (inferred from origin when possible).\n` +
603
- ` Or omit --ref/--path/--cursor-events-repo/--allow-domain for a static engine.\n`
590
+ ` Pass --repo https://github.com/<owner>/<repo> (inferred from origin when possible).\n`
604
591
  );
605
592
  return 1;
606
593
  }
@@ -633,8 +620,7 @@ async function deployOne(
633
620
 
634
621
  // The package manifest (`defineAgent({ hosting })`) is the source of
635
622
  // truth for egress domains and expected secret names; flags override or
636
- // augment it. Directories without an agent project (static placeholder
637
- // deploys) simply have no manifest. The same load supplies the
623
+ // augment it. Directories without an agent project have no manifest. The same load supplies the
638
624
  // cursorAccount connection refs for the post-deploy connector auth and
639
625
  // the channels declared public via `publicEndpoint()`.
640
626
  const manifest = isAgent ? await readDeployManifest(dir) : undefined;
@@ -661,11 +647,11 @@ async function deployOne(
661
647
  );
662
648
  }
663
649
 
664
- // Today's only source shape: the control plane builds from a git ref (or
665
- // serves the static placeholder). See DeploySource for the artifact seam.
650
+ // Today's only source shape: the control plane builds from a git ref.
651
+ // See DeploySource for the artifact seam.
666
652
  const source: DeploySource = {
667
653
  kind: "git-ref",
668
- ...(gitRepoUrl === undefined ? {} : { gitRepoUrl }),
654
+ gitRepoUrl,
669
655
  ...(gitRef === undefined ? {} : { gitRef }),
670
656
  ...(agentPath === undefined ? {} : { agentPath }),
671
657
  ...(options.cursorEventsRepos === undefined ||
@@ -0,0 +1,127 @@
1
+ /**
2
+ * `slack init --manual` and `slack manifest` — DIY paste-at-api.slack.com.
3
+ * Create/destroy/icon stay in `cli-slack.ts`.
4
+ */
5
+
6
+ import { mkdir, writeFile } from "node:fs/promises";
7
+ import { basename, join, resolve as resolvePath } from "node:path";
8
+ import {
9
+ buildSlackManifestPair,
10
+ initSlackManual,
11
+ slackManifestFileEntries,
12
+ } from "../channels/slack/index.js";
13
+ import { describeError } from "./describe-error.js";
14
+ import { CLI_COMMAND_NAME as CLI } from "./distribution.js";
15
+
16
+ export interface SlackManualCliOptions {
17
+ dir: string;
18
+ name?: string;
19
+ env?: "dev" | "prod" | "both";
20
+ print?: boolean;
21
+ prefix?: string;
22
+ noPrefix?: boolean;
23
+ channelPosts?: boolean;
24
+ /** Gate for `slack init`; ignored by `slack manifest`. */
25
+ manual?: boolean;
26
+ out?: (text: string) => void;
27
+ err?: (text: string) => void;
28
+ }
29
+
30
+ function errStream(options: SlackManualCliOptions): (text: string) => void {
31
+ return options.err ?? ((text: string) => void process.stderr.write(text));
32
+ }
33
+
34
+ export async function cmdSlackInit(
35
+ options: SlackManualCliOptions
36
+ ): Promise<number> {
37
+ if (options.manual !== true) {
38
+ errStream(options)(
39
+ `\`slack init\` without --manual is not the first-run path. Socket Mode apps are created with:
40
+
41
+ ${CLI} slack create --dir .
42
+
43
+ That opens the Cursor dashboard wizard.
44
+
45
+ To install a custom Slack app from a manifest (api.slack.com):
46
+
47
+ ${CLI} slack init --manual --dir .
48
+ `
49
+ );
50
+ return 1;
51
+ }
52
+
53
+ const dir = resolvePath(options.dir);
54
+ const out =
55
+ options.out ?? ((text: string) => void process.stdout.write(text));
56
+ try {
57
+ const result = await initSlackManual({
58
+ dir,
59
+ name: options.name,
60
+ envPrefix: options.noPrefix === true ? "" : options.prefix,
61
+ channelPosts: options.channelPosts,
62
+ });
63
+ out(
64
+ `${JSON.stringify(
65
+ {
66
+ ok: true,
67
+ directory: result.rootDir,
68
+ created: result.files,
69
+ envPrefix: result.envPrefix ?? null,
70
+ envKeys: result.envKeys,
71
+ next: [
72
+ "Open https://api.slack.com/apps → Create from manifest",
73
+ "Import .agent-serve/slack/manifest.dev.json (then prod)",
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
+ ],
81
+ },
82
+ null,
83
+ 2
84
+ )}\n`
85
+ );
86
+ return 0;
87
+ } catch (error) {
88
+ errStream(options)(`${describeError(error)}\n`);
89
+ return 1;
90
+ }
91
+ }
92
+
93
+ export async function runSlackManifest(
94
+ options: SlackManualCliOptions
95
+ ): Promise<number> {
96
+ const env = options.env ?? "both";
97
+ const dir = resolvePath(options.dir);
98
+ const pair = buildSlackManifestPair({
99
+ name: options.name ?? basename(dir),
100
+ managedByCursor: false,
101
+ channelPosts: options.channelPosts === true ? true : undefined,
102
+ });
103
+
104
+ if (options.print) {
105
+ if (env === "dev" || env === "both") {
106
+ process.stdout.write(`${JSON.stringify(pair.dev, null, 2)}\n`);
107
+ }
108
+ if (env === "prod" || env === "both") {
109
+ if (env === "both") {
110
+ process.stdout.write("--- prod ---\n");
111
+ }
112
+ process.stdout.write(`${JSON.stringify(pair.prod, null, 2)}\n`);
113
+ }
114
+ return 0;
115
+ }
116
+
117
+ const outDir = join(dir, ".agent-serve/slack");
118
+ await mkdir(outDir, { recursive: true });
119
+ const written: string[] = [];
120
+ for (const file of slackManifestFileEntries(pair, env)) {
121
+ const path = join(outDir, file.name);
122
+ await writeFile(path, file.contents);
123
+ written.push(path);
124
+ }
125
+ process.stdout.write(`${JSON.stringify({ ok: true, written }, null, 2)}\n`);
126
+ return 0;
127
+ }
@@ -1,12 +1,12 @@
1
1
  /**
2
- * `agent-serve slack …` CLI — doctor, destroy/icon, and `create` as a
3
- * dashboard-wizard launcher (`slack-provision-client.ts`).
2
+ * `agent-serve slack …` CLI — doctor, destroy/icon, `create` as a
3
+ * dashboard-wizard launcher (`slack-provision-client.ts`), and
4
+ * `init --manual` for hand-imported manifests.
4
5
  */
5
6
 
6
- import { access, chmod, mkdir, readFile, writeFile } from "node:fs/promises";
7
+ import { access, chmod, readFile, writeFile } from "node:fs/promises";
7
8
  import { basename, extname, join, resolve as resolvePath } from "node:path";
8
9
  import {
9
- buildSlackManifestPair,
10
10
  envPrefixFromName,
11
11
  formatSlackSetupGuide,
12
12
  initSlackChannel,
@@ -15,6 +15,7 @@ import {
15
15
  slackEnvKeys,
16
16
  } from "../channels/slack/index.js";
17
17
  import { resolveDeployAuth } from "./cli-deploy.js";
18
+ import { cmdSlackInit, runSlackManifest } from "./cli-slack-manual.js";
18
19
  import { cursorExternalApiUrl } from "./cursor/credentials.js";
19
20
  import { slugFromDirectoryName } from "./deploy-client.js";
20
21
  import { inferDeployGitSource } from "./deploy-source.js";
@@ -58,6 +59,8 @@ export interface SlackCliOptions {
58
59
  icon?: string;
59
60
  /** create: accepted for compatibility; live-app updates always overwrite. */
60
61
  force?: boolean;
62
+ /** `slack init --manual`: manifests for paste at api.slack.com. */
63
+ manual?: boolean;
61
64
  /** `slack icon <source>` positional (same URL-or-file forms as --icon). */
62
65
  iconSource?: string;
63
66
  /** Test seams. */
@@ -81,6 +84,10 @@ Usage:
81
84
  [--team <id>] [--json]
82
85
  ${CLI} slack icon <URL-or-FILE> [--dir .] [--slack-team T0123ABCD]
83
86
  [--prod] [--team <id>] [--json]
87
+ ${CLI} slack init --manual [--dir .] [--name NAME]
88
+ [--prefix PREFIX | --no-prefix] [--channel-posts]
89
+ ${CLI} slack manifest --env dev|prod|both [--dir .] [--name NAME]
90
+ [--print]
84
91
  ${CLI} slack doctor [--dir .] [--prefix PREFIX | --no-prefix] [--json]
85
92
 
86
93
  create/destroy/icon — dedicated Socket Mode app via the Cursor dashboard:
@@ -94,13 +101,14 @@ create/destroy/icon — dedicated Socket Mode app via the Cursor dashboard:
94
101
  icon Set the provisioned app's icon: an https image URL or a local
95
102
  png/jpg/gif file (at most 512KB).
96
103
 
97
- \`slack init\` is removed. Use \`slack create\`. Do not paste a manifest
98
- at api.slack.com.
104
+ \`slack init\` without --manual is not the first-run path. Use \`slack create\`.
105
+ \`slack init --manual\` writes the channel file, manifests to paste at
106
+ api.slack.com, env.example, and setup-status.json.
99
107
 
100
108
  Env tokens:
101
109
  single agent: SLACK_BOT_TOKEN + SLACK_APP_TOKEN
102
110
  multi-agent: <PREFIX>_SLACK_BOT_TOKEN + <PREFIX>_SLACK_APP_TOKEN
103
- (create default PREFIX from the directory name;
111
+ (create / init --manual default PREFIX from the directory name;
104
112
  doctor defaults to it too when those keys are set)
105
113
 
106
114
  See also: skills/setup-slack/SKILL.md
@@ -129,7 +137,7 @@ export async function cmdSlack(
129
137
  case "init":
130
138
  return cmdSlackInit(options);
131
139
  case "manifest":
132
- return runManifest(options);
140
+ return runSlackManifest(options);
133
141
  case "doctor":
134
142
  return runDoctor(options);
135
143
  default:
@@ -139,58 +147,6 @@ export async function cmdSlack(
139
147
  }
140
148
  }
141
149
 
142
- async function cmdSlackInit(options: SlackCliOptions): Promise<number> {
143
- errStream(options)(
144
- `\`slack init\` is removed. Socket Mode apps are created with:
145
-
146
- ${CLI} slack create --dir .
147
-
148
- That opens the Cursor dashboard wizard. Do not paste a manifest at api.slack.com.
149
- `
150
- );
151
- return 1;
152
- }
153
-
154
- async function runManifest(options: SlackCliOptions): Promise<number> {
155
- const env = options.env ?? "both";
156
- const dir = resolvePath(options.dir);
157
- const name = options.name ?? basename(dir);
158
- const pair = buildSlackManifestPair({
159
- name,
160
- managedByCursor: false,
161
- channelPosts: options.channelPosts === true ? true : undefined,
162
- });
163
-
164
- if (options.print) {
165
- if (env === "dev" || env === "both") {
166
- process.stdout.write(`${JSON.stringify(pair.dev, null, 2)}\n`);
167
- }
168
- if (env === "prod" || env === "both") {
169
- if (env === "both") {
170
- process.stdout.write("--- prod ---\n");
171
- }
172
- process.stdout.write(`${JSON.stringify(pair.prod, null, 2)}\n`);
173
- }
174
- return 0;
175
- }
176
-
177
- const outDir = join(dir, ".agent-serve/slack");
178
- await mkdir(outDir, { recursive: true });
179
- const written: string[] = [];
180
- if (env === "dev" || env === "both") {
181
- const path = join(outDir, "manifest.dev.json");
182
- await writeFile(path, `${JSON.stringify(pair.dev, null, 2)}\n`);
183
- written.push(path);
184
- }
185
- if (env === "prod" || env === "both") {
186
- const path = join(outDir, "manifest.prod.json");
187
- await writeFile(path, `${JSON.stringify(pair.prod, null, 2)}\n`);
188
- written.push(path);
189
- }
190
- process.stdout.write(`${JSON.stringify({ ok: true, written }, null, 2)}\n`);
191
- return 0;
192
- }
193
-
194
150
  async function runDoctor(options: SlackCliOptions): Promise<number> {
195
151
  const dir = resolvePath(options.dir);
196
152
  // Tokens usually live in the agent's .env.local; real env still wins.
@@ -450,7 +406,7 @@ export async function cmdSlackCreate(
450
406
 
451
407
  let wrote: string[];
452
408
  try {
453
- wrote = await scaffoldSlackChannelFiles(options, target);
409
+ wrote = await scaffoldSlackChannelFiles(target);
454
410
  } catch (error) {
455
411
  ctx.err(`${describeError(error)}\n`);
456
412
  return 1;
@@ -780,7 +736,6 @@ function formatAppList(
780
736
  * never overwritten: initSlackChannel writes with `wx`.
781
737
  */
782
738
  async function scaffoldSlackChannelFiles(
783
- options: SlackCliOptions,
784
739
  target: SlackAppTarget
785
740
  ): Promise<string[]> {
786
741
  const channelFile = "agent/channels/slack.ts";
@@ -788,22 +743,15 @@ async function scaffoldSlackChannelFiles(
788
743
  return [];
789
744
  }
790
745
  try {
791
- // Pass the resolved name/prefix so the channel file and the env keys
792
- // share one derivation.
793
746
  const result = await initSlackChannel({
794
747
  dir: target.dir,
795
748
  name: target.name,
796
749
  envPrefix: target.envPrefix ?? "",
797
- channelPosts: options.channelPosts,
798
750
  });
799
751
  return result.files;
800
752
  } catch (error) {
801
753
  if (isErrnoException(error) && error.code === "EEXIST") {
802
- // The channel file is written first, so it exists by the time a
803
- // later pre-existing file aborts the scaffold.
804
- return (await fileExists(join(target.dir, channelFile)))
805
- ? [channelFile]
806
- : [];
754
+ return [channelFile];
807
755
  }
808
756
  throw error;
809
757
  }
@@ -52,29 +52,26 @@ export const TERMINAL_DEPLOY_STATUSES: ReadonlySet<DeploymentStatus> = new Set([
52
52
 
53
53
  /**
54
54
  * What gets deployed. Today the control plane builds the engine itself from
55
- * a git ref (or serves the static placeholder when no repo is given), so the
56
- * only member is the slug/git-ref shape. When artifact-based deploys ship
57
- * ("build locally + upload"), add an `{ kind: "artifact", ... }` member here
58
- * and a branch in {@link AgentServeDeployClient.deploy} — the command
59
- * surface and everything downstream stays unchanged.
55
+ * a git ref, so the only member is the slug/git-ref shape. When
56
+ * artifact-based deploys ship ("build locally + upload"), add an
57
+ * `{ kind: "artifact", ... }` member here and a branch in
58
+ * {@link AgentServeDeployClient.deploy} — the command surface and everything
59
+ * downstream stays unchanged.
60
60
  */
61
61
  export type DeploySource = {
62
62
  kind: "git-ref";
63
- /** Omit for the control-plane static engine (`static-http-200`). */
64
- gitRepoUrl?: string;
63
+ gitRepoUrl: string;
65
64
  gitRef?: string;
66
65
  agentPath?: string;
67
66
  /** Repos whose SCM events the deployed engine pulls (`owner/name`). */
68
67
  cursorEventRepos?: string[];
69
68
  /**
70
- * Egress allowlist for the engine pod. Only valid on repo-backed
71
- * deploys — the backend 400s when set on a static deploy.
69
+ * Egress allowlist for the engine pod.
72
70
  */
73
71
  egressAllowedDomains?: string[];
74
72
  /**
75
73
  * `/v1/channels/…` subtrees the stable alias serves WITHOUT
76
74
  * `X-Agent-Alias-Token` (channels authored with `publicEndpoint()`).
77
- * Only valid on repo-backed deploys.
78
75
  */
79
76
  publicRoutePaths?: string[];
80
77
  };
@@ -441,9 +438,7 @@ export class AgentServeDeployClient {
441
438
  const body: Record<string, unknown> = {
442
439
  teamId: args.teamId,
443
440
  slug: args.slug,
444
- ...(args.source.gitRepoUrl === undefined
445
- ? {}
446
- : { gitRepoUrl: args.source.gitRepoUrl }),
441
+ gitRepoUrl: args.source.gitRepoUrl,
447
442
  ...(args.source.gitRef === undefined
448
443
  ? {}
449
444
  : { gitRef: args.source.gitRef }),
@@ -113,7 +113,7 @@ export function agentPathRelativeToGitRoot(
113
113
 
114
114
  /**
115
115
  * Probe the git checkout containing `dir` for deploy source fields.
116
- * Missing pieces stay undefined (static deploy / server defaults).
116
+ * Missing pieces stay undefined.
117
117
  */
118
118
  export async function inferDeployGitSource(
119
119
  dir: string,
@@ -8,9 +8,8 @@
8
8
  * An optional in-process sampler (`AGENT_SDK_MEMORY_METRICS=1`) still logs
9
9
  * and, if a Datadog key happens to be in the pod, posts directly.
10
10
  *
11
- * `event_log.events_retained` is the in-process cache size (the OOM
12
- * suspect). `event_log.events_total` is the durable recorded count. They
13
- * are equal today; a later consume-and-drop change should split them.
11
+ * Event-log residency is `event_log.resident_sessions` (open session
12
+ * map). Transcripts live on disk; unflushed tails are not a scrape gauge.
14
13
  */
15
14
 
16
15
  import { getHeapStatistics } from "node:v8";
@@ -102,7 +101,7 @@ export function sampleProcessMemory(
102
101
 
103
102
  export type MemoryHealthFields = {
104
103
  memory: ProcessMemorySample & { heapUsedRatio: number };
105
- eventLog: EventLogMemoryStats;
104
+ eventLog: Pick<EventLogMemoryStats, "residentSessions">;
106
105
  };
107
106
 
108
107
  export function heapUsedRatio(memory: ProcessMemorySample): number {
@@ -132,7 +131,7 @@ export function buildMemoryHealthFields(
132
131
  ): MemoryHealthFields {
133
132
  return {
134
133
  memory: { ...sample, heapUsedRatio: heapUsedRatio(sample) },
135
- eventLog,
134
+ eventLog: { residentSessions: eventLog.residentSessions },
136
135
  };
137
136
  }
138
137
 
@@ -167,9 +166,7 @@ export function formatMemoryLogLine(args: {
167
166
  ` heap_limit_mb=${mb(args.memory.heapLimitBytes)}` +
168
167
  ` heap_used_ratio=${ratio.toFixed(3)}` +
169
168
  ` rss_mb=${mb(args.memory.rssBytes)}` +
170
- ` event_log.sessions=${args.eventLog.residentSessions}` +
171
- ` event_log.retained=${args.eventLog.eventsRetained}` +
172
- ` event_log.total=${args.eventLog.eventsTotal}`
169
+ ` event_log.sessions=${args.eventLog.residentSessions}`
173
170
  );
174
171
  }
175
172
 
@@ -209,14 +206,6 @@ export function buildDatadogGaugeSeries(args: {
209
206
  name: `${EVENT_LOG_METRIC_PREFIX}.resident_sessions`,
210
207
  value: args.eventLog.residentSessions,
211
208
  },
212
- {
213
- name: `${EVENT_LOG_METRIC_PREFIX}.events_retained`,
214
- value: args.eventLog.eventsRetained,
215
- },
216
- {
217
- name: `${EVENT_LOG_METRIC_PREFIX}.events_total`,
218
- value: args.eventLog.eventsTotal,
219
- },
220
209
  ];
221
210
  return points.map((point) => ({
222
211
  metric: point.name,
@@ -300,14 +289,6 @@ function recordOtel(
300
289
  memory.rssBytes,
301
290
  attributes
302
291
  );
303
- histogram(meter, `${EVENT_LOG_METRIC_PREFIX}.events_retained`).record(
304
- eventLog.eventsRetained,
305
- attributes
306
- );
307
- histogram(meter, `${EVENT_LOG_METRIC_PREFIX}.events_total`).record(
308
- eventLog.eventsTotal,
309
- attributes
310
- );
311
292
  histogram(meter, `${EVENT_LOG_METRIC_PREFIX}.resident_sessions`).record(
312
293
  eventLog.residentSessions,
313
294
  attributes