blink 1.1.19 → 1.1.20

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 (30) hide show
  1. package/dist/cli/create-slack-app-CyVPwWsG.js +1 -0
  2. package/dist/cli/{dev-BShY-dVP.js → dev-C5PZ-A_f.js} +5 -5
  3. package/dist/cli/index.js +3 -3
  4. package/dist/cli/{init-DoMgv4kU.js → init-CFrylDAP.js} +1 -1
  5. package/dist/cli/{init-templates-MqyReSD9.js → init-templates-CB4tNZfU.js} +249 -263
  6. package/dist/cli/{run-DFYLWiOa.js → run-bKDX6K46.js} +1 -1
  7. package/dist/cli/{setup-slack-app-DQ3iSM5s.js → setup-slack-app-D_iwQuzr.js} +1 -1
  8. package/dist/cli/{util-BQ3TH_Sv.js → util-DDB5k1Go.js} +4 -4
  9. package/dist/node/agent/index.node.cjs +1 -1
  10. package/dist/node/agent/index.node.d.cts +2 -2
  11. package/dist/node/agent/index.node.d.ts +2 -2
  12. package/dist/node/agent/index.node.js +1 -1
  13. package/dist/node/build/index.cjs +1 -1
  14. package/dist/node/build/index.d.cts +1 -1
  15. package/dist/node/build/index.d.ts +1 -1
  16. package/dist/node/build/index.js +1 -1
  17. package/dist/node/{build-D_L0gFGa.js → build-DYI55eX2.js} +1 -1
  18. package/dist/node/{build-BzoNpizh.cjs → build-EgdtUZTI.cjs} +1 -1
  19. package/dist/node/{index-C28Wm0bG.d.ts → index-CnBfy-54.d.ts} +1 -1
  20. package/dist/node/{index-DlWgNLmT.d.cts → index-DYOqnOdZ.d.cts} +1 -1
  21. package/dist/node/{index.node-TFdiI8lm.js → index.node-B6JXREDl.js} +1 -1
  22. package/dist/node/{index.node-D7Cvmag9.cjs → index.node-BrLfthBj.cjs} +1 -1
  23. package/dist/node/{index.node-B6plkLLA.d.cts → index.node-CFw4ITad.d.cts} +1 -21
  24. package/dist/node/{index.node-qJt_7e9E.d.ts → index.node-Dvc-cHCZ.d.ts} +1 -21
  25. package/dist/node/react/index.node.cjs +252 -266
  26. package/dist/node/react/index.node.d.cts +2 -2
  27. package/dist/node/react/index.node.d.ts +2 -2
  28. package/dist/node/react/index.node.js +252 -266
  29. package/package.json +2 -1
  30. package/dist/cli/create-slack-app-CNDXDwfs.js +0 -1
@@ -1,8 +1,15 @@
1
- const e={scratch:{".gitignore":`# dependencies
1
+ const e={scratch:{".env.local":`
2
+ # Store local environment variables here.
3
+ # They will be used by blink dev for development.
4
+ # EXTERNAL_SERVICE_API_KEY=
5
+ `,".env.production":`# Store production environment variables here.
6
+ # They will be upserted as secrets on blink deploy.
7
+ # EXTERNAL_SERVICE_API_KEY=
8
+ `,".gitignore":`# dependencies
2
9
  node_modules
3
10
 
4
11
  # config and build
5
- data
12
+ .blink
6
13
 
7
14
  # dotenv environment variables file
8
15
  .env
@@ -10,103 +17,6 @@ data
10
17
 
11
18
  # Finder (MacOS) folder config
12
19
  .DS_Store
13
- `,"tsconfig.json":`{
14
- "compilerOptions": {
15
- "lib": ["ESNext"],
16
- "target": "ESNext",
17
- "module": "Preserve",
18
- "moduleDetection": "force",
19
-
20
- "moduleResolution": "bundler",
21
- "allowImportingTsExtensions": true,
22
- "verbatimModuleSyntax": true,
23
- "resolveJsonModule": true,
24
- "noEmit": true,
25
-
26
- "strict": true,
27
- "skipLibCheck": true,
28
- "noFallthroughCasesInSwitch": true,
29
- "noUncheckedIndexedAccess": true,
30
- "noImplicitOverride": true,
31
-
32
- "noUnusedLocals": false,
33
- "noUnusedParameters": false,
34
-
35
- "types": ["node"]
36
- }
37
- }
38
- `,".env.local":`
39
- # Store local environment variables here.
40
- # They will be used by blink dev for development.
41
- # EXTERNAL_SERVICE_API_KEY=
42
- `,".env.production":`# Store production environment variables here.
43
- # They will be upserted as secrets on blink deploy.
44
- # EXTERNAL_SERVICE_API_KEY=
45
- `,"agent.ts.hbs":`import { convertToModelMessages, streamText, tool } from "ai";
46
- import * as blink from "blink";
47
- import { z } from "zod";
48
- {{#if (eq aiProvider "anthropic")}}
49
- import { anthropic } from "@ai-sdk/anthropic";
50
- {{else if (eq aiProvider "openai")}}
51
- import { openai } from "@ai-sdk/openai";
52
- {{/if}}
53
-
54
- const agent = new blink.Agent();
55
-
56
- agent.on("chat", async ({ messages }) => {
57
- return streamText({
58
- {{#if (eq aiProvider "anthropic")}}
59
- model: anthropic("claude-sonnet-4-5"),
60
- {{else if (eq aiProvider "openai")}}
61
- model: openai("gpt-5-chat-latest"),
62
- {{else if (eq aiProvider "vercel")}}
63
- model: "anthropic/claude-sonnet-4.5",
64
- {{else}}
65
- // Unknown provider: {{aiProvider}}. Defaulting to Vercel AI Gateway syntax.
66
- model: "anthropic/claude-sonnet-4.5",
67
- {{/if}}
68
- system: \`You are a basic agent the user will customize.
69
-
70
- Suggest the user enters edit mode with Ctrl+T or /edit to customize the agent.
71
- Demonstrate your capabilities with the IP tool.\`,
72
- messages: convertToModelMessages(messages),
73
- tools: {
74
- get_ip_info: tool({
75
- description: "Get IP address information of the computer.",
76
- inputSchema: z.object({}),
77
- execute: async () => {
78
- const response = await fetch("https://ipinfo.io/json");
79
- return response.json();
80
- },
81
- }),
82
- },
83
- });
84
- });
85
-
86
- agent.serve();
87
- `,"package.json.hbs":`{
88
- "name": "{{packageName}}",
89
- "main": "agent.ts",
90
- "type": "module",
91
- "private": true,
92
- "scripts": {
93
- "dev": "blink dev",
94
- "deploy": "blink deploy"
95
- },
96
- "devDependencies": {
97
- "zod": "latest",
98
- "ai": "latest",
99
- {{#if (eq aiProvider "anthropic")}}
100
- "@ai-sdk/anthropic": "latest",
101
- {{else if (eq aiProvider "openai")}}
102
- "@ai-sdk/openai": "latest",
103
- {{/if}}
104
- "blink": "latest",
105
- "esbuild": "latest",
106
- "@types/node": "latest",
107
- "typescript": "latest"
108
- }
109
- }
110
20
  `,"AGENTS.md":`This project is a Blink agent.
111
21
 
112
22
  You are an expert software engineer, which makes you an expert agent developer. You are highly idiomatic, opinionated, concise, and precise. The user prefers accuracy over speed.
@@ -180,7 +90,7 @@ const agent = new blink.Agent();
180
90
 
181
91
  agent.on("chat", async ({ messages, chat, abortSignal }) => {
182
92
  return streamText({
183
- model: blink.model("anthropic/claude-sonnet-4.5"),
93
+ model: "anthropic/claude-sonnet-4.5",
184
94
  system: "You are a helpful assistant.",
185
95
  messages: convertToModelMessages(messages, {
186
96
  ignoreIncompleteToolCalls: true,
@@ -324,17 +234,6 @@ Tool Prefixing to avoid collisions:
324
234
 
325
235
  LLM Models:
326
236
 
327
- **Option 1: Blink Gateway** (Quick Start)
328
-
329
- \`\`\`typescript
330
- model: blink.model("anthropic/claude-sonnet-4.5");
331
- model: blink.model("openai/gpt-5");
332
- \`\`\`
333
-
334
- Requires: \`blink login\` or \`BLINK_TOKEN\` env var
335
-
336
- **Option 2: Direct Provider** (Production Recommended)
337
-
338
237
  \`\`\`typescript
339
238
  import { anthropic } from "@ai-sdk/anthropic";
340
239
  import { openai } from "@ai-sdk/openai";
@@ -349,7 +248,6 @@ model: openai("gpt-5", { apiKey: process.env.OPENAI_API_KEY });
349
248
 
350
249
  1. If \`ANTHROPIC_API_KEY\` is set: uses \`claude-sonnet-4.5\` via \`@ai-sdk/anthropic\`
351
250
  2. If \`OPENAI_API_KEY\` is set: uses \`gpt-5\` via \`@ai-sdk/openai\`
352
- 3. Otherwise: falls back to \`blink.model("anthropic/claude-sonnet-4.5")\`
353
251
 
354
252
  Available SDKs:
355
253
 
@@ -419,7 +317,7 @@ agent.on("request", async (request) => {
419
317
  agent.on("chat", async ({ messages }) => {
420
318
  const tools = slack.createTools({ client: app.client });
421
319
  return streamText({
422
- model: blink.model("anthropic/claude-sonnet-4.5"),
320
+ model: "anthropic/claude-sonnet-4.5",
423
321
  system: "You chatting with users in Slack.",
424
322
  messages: convertToModelMessages(messages, {
425
323
  ignoreIncompleteToolCalls: true,
@@ -443,7 +341,7 @@ Slack App Manifest:
443
341
  - _ALWAYS_ include the "assistant:write" scope unless the user explicitly states otherwise - this allows Slack apps to set their status, which makes for a significantly better user experience. You _MUST_ provide "assistant_view" if you provide this scope.
444
342
  - The user can always edit the manifest after creation, but you'd have to suggest it to them.
445
343
  - "oauth_config" MUST BE PROVIDED - otherwise the app will have NO ACCESS.
446
- - _ALWAYS_ default "token_rotation_enabled" to false unless the user explicitly asks for it. It is a _much_ simpler user-experience to not rotate tokens.
344
+ - _ALWAYS_ default \`token_rotation_enabled\` to false unless the user explicitly asks for it. It is a _much_ simpler user-experience to not rotate tokens.
447
345
  - For the best user experience, default to the following bot scopes (in the "oauth_config" > "scopes" > "bot"):
448
346
  - "app_mentions:read"
449
347
  - "reactions:write"
@@ -536,160 +434,54 @@ The agent process can restart at any time, so all important state must be extern
536
434
 
537
435
  - Never use "as any" type assertions. Always figure out the correct typings.
538
436
  </code_quality>
539
- `},"slack-bot":{".gitignore":`# dependencies
540
- node_modules
541
-
542
- # config and build
543
- data
544
-
545
- # dotenv environment variables file
546
- .env
547
- .env.*
548
-
549
- # Finder (MacOS) folder config
550
- .DS_Store
551
- `,"tsconfig.json":`{
552
- "compilerOptions": {
553
- "lib": ["ESNext"],
554
- "target": "ESNext",
555
- "module": "Preserve",
556
- "moduleDetection": "force",
557
-
558
- "moduleResolution": "bundler",
559
- "allowImportingTsExtensions": true,
560
- "verbatimModuleSyntax": true,
561
- "resolveJsonModule": true,
562
- "noEmit": true,
563
-
564
- "strict": true,
565
- "skipLibCheck": true,
566
- "noFallthroughCasesInSwitch": true,
567
- "noUncheckedIndexedAccess": true,
568
- "noImplicitOverride": true,
569
-
570
- "noUnusedLocals": false,
571
- "noUnusedParameters": false,
572
-
573
- "types": ["node"]
574
- }
575
- }
576
- `,".env.local":`
577
- # Store local environment variables here.
578
- # They will be used by blink dev for development.
579
- SLACK_BOT_TOKEN=xoxb-your-token-here
580
- SLACK_SIGNING_SECRET=your-signing-secret-here
581
- `,".env.production":`# Store production environment variables here.
582
- # They will be upserted as secrets on blink deploy.
583
- # EXTERNAL_SERVICE_API_KEY=
584
- `,"agent.ts.hbs":`import { convertToModelMessages, streamText } from "ai";
437
+ `,"agent.ts.hbs":`import { convertToModelMessages, streamText, tool } from "ai";
585
438
  import * as blink from "blink";
586
- import * as slack from "@blink-sdk/slack";
587
- import { App } from "@slack/bolt";
439
+ import { z } from "zod";
588
440
  {{#if (eq aiProvider "anthropic")}}
589
441
  import { anthropic } from "@ai-sdk/anthropic";
590
442
  {{else if (eq aiProvider "openai")}}
591
443
  import { openai } from "@ai-sdk/openai";
592
444
  {{/if}}
593
445
 
594
- const receiver = new slack.Receiver();
595
- const app = new App({
596
- token: process.env.SLACK_BOT_TOKEN,
597
- signingSecret: process.env.SLACK_SIGNING_SECRET,
598
- receiver,
599
- });
600
-
601
- // Handle messages in channels (only when @mentioned)
602
- app.event("app_mention", async ({ event }) => {
603
- const chat = await agent.chat.upsert([
604
- "slack",
605
- event.channel,
606
- event.thread_ts ?? event.ts,
607
- ]);
608
- const { message } = await slack.createMessageFromEvent({
609
- client: app.client,
610
- event,
611
- });
612
- await agent.chat.sendMessages(chat.id, [message]);
613
- await app.client.assistant.threads.setStatus({
614
- channel_id: event.channel,
615
- status: "is typing...",
616
- thread_ts: event.thread_ts ?? event.ts,
617
- });
618
- });
619
-
620
- // Handle direct messages (always respond)
621
- app.event("message", async ({ event }) => {
622
- // Ignore bot messages and message changes
623
- if (event.subtype || event.bot_id) {
624
- return;
625
- }
626
- // Only handle DMs (channel type is 'im')
627
- const channelInfo = await app.client.conversations.info({
628
- channel: event.channel,
629
- });
630
- if (!channelInfo.channel?.is_im) {
631
- return;
632
- }
633
- const chat = await agent.chat.upsert(["slack", event.channel]);
634
- const { message } = await slack.createMessageFromEvent({
635
- client: app.client,
636
- event,
637
- });
638
- await agent.chat.sendMessages(chat.id, [message]);
639
- await app.client.assistant.threads.setStatus({
640
- channel_id: event.channel,
641
- status: "is typing...",
642
- thread_ts: event.thread_ts ?? event.ts,
643
- });
644
- });
645
-
646
446
  const agent = new blink.Agent();
647
447
 
648
- agent.on("request", async (request) => {
649
- return receiver.handle(app, request);
650
- });
651
-
652
448
  agent.on("chat", async ({ messages }) => {
653
- const tools = slack.createTools({ client: app.client });
654
- const lastMessage = messages[messages.length - 1];
655
- const threadInfo = lastMessage?.metadata as
656
- | { channel?: string; thread_ts?: string }
657
- | undefined;
658
-
659
- // Add instruction to clear status after completion
660
- if (threadInfo?.channel && threadInfo?.thread_ts) {
661
- const clonedMessages = structuredClone(messages);
662
- const lastClonedMessage = clonedMessages[clonedMessages.length - 1];
663
- if (lastClonedMessage) {
664
- lastClonedMessage.parts.push({
665
- type: "text",
666
- text: \`*INTERNAL INSTRUCTION*: Clear the status of this thread after you finish: channel=\${threadInfo.channel} thread_ts=\${threadInfo.thread_ts}\`,
667
- });
668
- }
669
- messages = clonedMessages;
670
- }
671
-
672
449
  return streamText({
673
450
  {{#if (eq aiProvider "anthropic")}}
674
451
  model: anthropic("claude-sonnet-4-5"),
675
452
  {{else if (eq aiProvider "openai")}}
676
- model: openai("gpt-5-chat-latest"),
453
+ model: openai("gpt-5-codex"),
454
+ providerOptions: {
455
+ openai: {
456
+ reasoningSummary: "detailed",
457
+ },
458
+ },
677
459
  {{else if (eq aiProvider "vercel")}}
678
460
  model: "anthropic/claude-sonnet-4.5",
679
461
  {{else}}
680
462
  // Unknown provider: {{aiProvider}}. Defaulting to Vercel AI Gateway syntax.
681
463
  model: "anthropic/claude-sonnet-4.5",
682
464
  {{/if}}
683
- system: "You are a helpful Slack bot assistant.",
684
- messages: convertToModelMessages(messages, {
685
- ignoreIncompleteToolCalls: true,
686
- tools,
687
- }),
688
- tools,
465
+ system: \`You are a basic agent the user will customize.
466
+
467
+ Suggest the user enters edit mode with Ctrl+T or /edit to customize the agent.
468
+ Demonstrate your capabilities with the IP tool.\`,
469
+ messages: convertToModelMessages(messages),
470
+ tools: {
471
+ get_ip_info: tool({
472
+ description: "Get IP address information of the computer.",
473
+ inputSchema: z.object({}),
474
+ execute: async () => {
475
+ const response = await fetch("https://ipinfo.io/json");
476
+ return response.json();
477
+ },
478
+ }),
479
+ },
689
480
  });
690
481
  });
691
482
 
692
- agent.serve();`,"package.json.hbs":`{
483
+ agent.serve();
484
+ `,"package.json.hbs":`{
693
485
  "name": "{{packageName}}",
694
486
  "main": "agent.ts",
695
487
  "type": "module",
@@ -709,11 +501,54 @@ agent.serve();`,"package.json.hbs":`{
709
501
  "blink": "latest",
710
502
  "esbuild": "latest",
711
503
  "@types/node": "latest",
712
- "typescript": "latest",
713
- "@slack/bolt": "latest",
714
- "@blink-sdk/slack": "latest"
504
+ "typescript": "latest"
715
505
  }
716
506
  }
507
+ `,"tsconfig.json":`{
508
+ "compilerOptions": {
509
+ "lib": ["ESNext"],
510
+ "target": "ESNext",
511
+ "module": "Preserve",
512
+ "moduleDetection": "force",
513
+
514
+ "moduleResolution": "bundler",
515
+ "allowImportingTsExtensions": true,
516
+ "verbatimModuleSyntax": true,
517
+ "resolveJsonModule": true,
518
+ "noEmit": true,
519
+
520
+ "strict": true,
521
+ "skipLibCheck": true,
522
+ "noFallthroughCasesInSwitch": true,
523
+ "noUncheckedIndexedAccess": true,
524
+ "noImplicitOverride": true,
525
+
526
+ "noUnusedLocals": false,
527
+ "noUnusedParameters": false,
528
+
529
+ "types": ["node"]
530
+ }
531
+ }
532
+ `},"slack-bot":{".env.local":`
533
+ # Store local environment variables here.
534
+ # They will be used by blink dev for development.
535
+ SLACK_BOT_TOKEN=xoxb-your-token-here
536
+ SLACK_SIGNING_SECRET=your-signing-secret-here
537
+ `,".env.production":`# Store production environment variables here.
538
+ # They will be upserted as secrets on blink deploy.
539
+ # EXTERNAL_SERVICE_API_KEY=
540
+ `,".gitignore":`# dependencies
541
+ node_modules
542
+
543
+ # config and build
544
+ .blink
545
+
546
+ # dotenv environment variables file
547
+ .env
548
+ .env.*
549
+
550
+ # Finder (MacOS) folder config
551
+ .DS_Store
717
552
  `,"AGENTS.md":`This project is a Blink agent.
718
553
 
719
554
  You are an expert software engineer, which makes you an expert agent developer. You are highly idiomatic, opinionated, concise, and precise. The user prefers accuracy over speed.
@@ -787,7 +622,7 @@ const agent = new blink.Agent();
787
622
 
788
623
  agent.on("chat", async ({ messages, chat, abortSignal }) => {
789
624
  return streamText({
790
- model: blink.model("anthropic/claude-sonnet-4.5"),
625
+ model: "anthropic/claude-sonnet-4.5",
791
626
  system: "You are a helpful assistant.",
792
627
  messages: convertToModelMessages(messages, {
793
628
  ignoreIncompleteToolCalls: true,
@@ -931,17 +766,6 @@ Tool Prefixing to avoid collisions:
931
766
 
932
767
  LLM Models:
933
768
 
934
- **Option 1: Blink Gateway** (Quick Start)
935
-
936
- \`\`\`typescript
937
- model: blink.model("anthropic/claude-sonnet-4.5");
938
- model: blink.model("openai/gpt-5");
939
- \`\`\`
940
-
941
- Requires: \`blink login\` or \`BLINK_TOKEN\` env var
942
-
943
- **Option 2: Direct Provider** (Production Recommended)
944
-
945
769
  \`\`\`typescript
946
770
  import { anthropic } from "@ai-sdk/anthropic";
947
771
  import { openai } from "@ai-sdk/openai";
@@ -956,7 +780,6 @@ model: openai("gpt-5", { apiKey: process.env.OPENAI_API_KEY });
956
780
 
957
781
  1. If \`ANTHROPIC_API_KEY\` is set: uses \`claude-sonnet-4.5\` via \`@ai-sdk/anthropic\`
958
782
  2. If \`OPENAI_API_KEY\` is set: uses \`gpt-5\` via \`@ai-sdk/openai\`
959
- 3. Otherwise: falls back to \`blink.model("anthropic/claude-sonnet-4.5")\`
960
783
 
961
784
  Available SDKs:
962
785
 
@@ -1026,7 +849,7 @@ agent.on("request", async (request) => {
1026
849
  agent.on("chat", async ({ messages }) => {
1027
850
  const tools = slack.createTools({ client: app.client });
1028
851
  return streamText({
1029
- model: blink.model("anthropic/claude-sonnet-4.5"),
852
+ model: "anthropic/claude-sonnet-4.5",
1030
853
  system: "You chatting with users in Slack.",
1031
854
  messages: convertToModelMessages(messages, {
1032
855
  ignoreIncompleteToolCalls: true,
@@ -1050,7 +873,7 @@ Slack App Manifest:
1050
873
  - _ALWAYS_ include the "assistant:write" scope unless the user explicitly states otherwise - this allows Slack apps to set their status, which makes for a significantly better user experience. You _MUST_ provide "assistant_view" if you provide this scope.
1051
874
  - The user can always edit the manifest after creation, but you'd have to suggest it to them.
1052
875
  - "oauth_config" MUST BE PROVIDED - otherwise the app will have NO ACCESS.
1053
- - _ALWAYS_ default "token_rotation_enabled" to false unless the user explicitly asks for it. It is a _much_ simpler user-experience to not rotate tokens.
876
+ - _ALWAYS_ default \`token_rotation_enabled\` to false unless the user explicitly asks for it. It is a _much_ simpler user-experience to not rotate tokens.
1054
877
  - For the best user experience, default to the following bot scopes (in the "oauth_config" > "scopes" > "bot"):
1055
878
  - "app_mentions:read"
1056
879
  - "reactions:write"
@@ -1143,4 +966,167 @@ The agent process can restart at any time, so all important state must be extern
1143
966
 
1144
967
  - Never use "as any" type assertions. Always figure out the correct typings.
1145
968
  </code_quality>
969
+ `,"agent.ts.hbs":`import { convertToModelMessages, streamText } from "ai";
970
+ import * as blink from "blink";
971
+ import * as slack from "@blink-sdk/slack";
972
+ import { App } from "@slack/bolt";
973
+ {{#if (eq aiProvider "anthropic")}}
974
+ import { anthropic } from "@ai-sdk/anthropic";
975
+ {{else if (eq aiProvider "openai")}}
976
+ import { openai } from "@ai-sdk/openai";
977
+ {{/if}}
978
+
979
+ const receiver = new slack.Receiver();
980
+ const app = new App({
981
+ token: process.env.SLACK_BOT_TOKEN,
982
+ signingSecret: process.env.SLACK_SIGNING_SECRET,
983
+ receiver,
984
+ });
985
+
986
+ // Handle messages in channels (only when @mentioned)
987
+ app.event("app_mention", async ({ event }) => {
988
+ const chat = await agent.chat.upsert([
989
+ "slack",
990
+ event.channel,
991
+ event.thread_ts ?? event.ts,
992
+ ]);
993
+ const { message } = await slack.createMessageFromEvent({
994
+ client: app.client,
995
+ event,
996
+ });
997
+ await agent.chat.sendMessages(chat.id, [message]);
998
+ await app.client.assistant.threads.setStatus({
999
+ channel_id: event.channel,
1000
+ status: "is typing...",
1001
+ thread_ts: event.thread_ts ?? event.ts,
1002
+ });
1003
+ });
1004
+
1005
+ // Handle direct messages (always respond)
1006
+ app.event("message", async ({ event }) => {
1007
+ // Ignore bot messages and message changes
1008
+ if (event.subtype || event.bot_id) {
1009
+ return;
1010
+ }
1011
+ // Only handle DMs (channel type is 'im')
1012
+ const channelInfo = await app.client.conversations.info({
1013
+ channel: event.channel,
1014
+ });
1015
+ if (!channelInfo.channel?.is_im) {
1016
+ return;
1017
+ }
1018
+ const chat = await agent.chat.upsert(["slack", event.channel]);
1019
+ const { message } = await slack.createMessageFromEvent({
1020
+ client: app.client,
1021
+ event,
1022
+ });
1023
+ await agent.chat.sendMessages(chat.id, [message]);
1024
+ await app.client.assistant.threads.setStatus({
1025
+ channel_id: event.channel,
1026
+ status: "is typing...",
1027
+ thread_ts: event.thread_ts ?? event.ts,
1028
+ });
1029
+ });
1030
+
1031
+ const agent = new blink.Agent();
1032
+
1033
+ agent.on("request", async (request) => {
1034
+ return receiver.handle(app, request);
1035
+ });
1036
+
1037
+ agent.on("chat", async ({ messages }) => {
1038
+ const tools = slack.createTools({ client: app.client });
1039
+ const lastMessage = messages[messages.length - 1];
1040
+ const threadInfo = lastMessage?.metadata as
1041
+ | { channel?: string; thread_ts?: string }
1042
+ | undefined;
1043
+
1044
+ // Add instruction to clear status after completion
1045
+ if (threadInfo?.channel && threadInfo?.thread_ts) {
1046
+ const clonedMessages = structuredClone(messages);
1047
+ const lastClonedMessage = clonedMessages[clonedMessages.length - 1];
1048
+ if (lastClonedMessage) {
1049
+ lastClonedMessage.parts.push({
1050
+ type: "text",
1051
+ text: \`*INTERNAL INSTRUCTION*: Clear the status of this thread after you finish: channel=\${threadInfo.channel} thread_ts=\${threadInfo.thread_ts}\`,
1052
+ });
1053
+ }
1054
+ messages = clonedMessages;
1055
+ }
1056
+
1057
+ return streamText({
1058
+ {{#if (eq aiProvider "anthropic")}}
1059
+ model: anthropic("claude-sonnet-4-5"),
1060
+ {{else if (eq aiProvider "openai")}}
1061
+ model: openai("gpt-5-codex"),
1062
+ providerOptions: {
1063
+ openai: {
1064
+ reasoningSummary: "detailed",
1065
+ },
1066
+ },
1067
+ {{else if (eq aiProvider "vercel")}}
1068
+ model: "anthropic/claude-sonnet-4.5",
1069
+ {{else}}
1070
+ // Unknown provider: {{aiProvider}}. Defaulting to Vercel AI Gateway syntax.
1071
+ model: "anthropic/claude-sonnet-4.5",
1072
+ {{/if}}
1073
+ system: "You are a helpful Slack bot assistant.",
1074
+ messages: convertToModelMessages(messages, {
1075
+ ignoreIncompleteToolCalls: true,
1076
+ tools,
1077
+ }),
1078
+ tools,
1079
+ });
1080
+ });
1081
+
1082
+ agent.serve();`,"package.json.hbs":`{
1083
+ "name": "{{packageName}}",
1084
+ "main": "agent.ts",
1085
+ "type": "module",
1086
+ "private": true,
1087
+ "scripts": {
1088
+ "dev": "blink dev",
1089
+ "deploy": "blink deploy"
1090
+ },
1091
+ "devDependencies": {
1092
+ "zod": "latest",
1093
+ "ai": "latest",
1094
+ {{#if (eq aiProvider "anthropic")}}
1095
+ "@ai-sdk/anthropic": "latest",
1096
+ {{else if (eq aiProvider "openai")}}
1097
+ "@ai-sdk/openai": "latest",
1098
+ {{/if}}
1099
+ "blink": "latest",
1100
+ "esbuild": "latest",
1101
+ "@types/node": "latest",
1102
+ "typescript": "latest",
1103
+ "@slack/bolt": "latest",
1104
+ "@blink-sdk/slack": "latest"
1105
+ }
1106
+ }
1107
+ `,"tsconfig.json":`{
1108
+ "compilerOptions": {
1109
+ "lib": ["ESNext"],
1110
+ "target": "ESNext",
1111
+ "module": "Preserve",
1112
+ "moduleDetection": "force",
1113
+
1114
+ "moduleResolution": "bundler",
1115
+ "allowImportingTsExtensions": true,
1116
+ "verbatimModuleSyntax": true,
1117
+ "resolveJsonModule": true,
1118
+ "noEmit": true,
1119
+
1120
+ "strict": true,
1121
+ "skipLibCheck": true,
1122
+ "noFallthroughCasesInSwitch": true,
1123
+ "noUncheckedIndexedAccess": true,
1124
+ "noImplicitOverride": true,
1125
+
1126
+ "noUnusedLocals": false,
1127
+ "noUnusedParameters": false,
1128
+
1129
+ "types": ["node"]
1130
+ }
1131
+ }
1146
1132
  `}};export{e as templates};
@@ -1 +1 @@
1
- import{__toESM as e}from"./chunk-D9KrCrVq.js";import{findNearestEntry as t,migrateBlinkToData as n,require_main as r,resolveConfig as i}from"./util-BQ3TH_Sv.js";import"./dist-Ceoe3h7v.js";import{getAuthToken as a}from"./auth-CoJASYGP.js";import"./util-BgbIWOFE.js";import{ChatManager as o,Client as s}from"./chat-manager-BRchJngj.js";import{spawn as c}from"node:child_process";import{join as l,resolve as u}from"node:path";import{existsSync as d}from"node:fs";import{readFile as f}from"node:fs/promises";import{createServer as p}from"node:net";async function m(e){let t=e.env?.PORT??await h(),n=e.env?.HOST??`127.0.0.1`,r=`http://${n}:${t}`,i={...e.env??process.env,PORT:t.toString(),HOST:n},a=c(e.command,e.args,{stdio:`pipe`,env:i});e.signal?.addEventListener(`abort`,()=>{try{a.kill()}catch{}},{once:!0});let o=new AbortController,l=[o.signal];e.signal&&l.push(e.signal);let u=AbortSignal.any(l);a.stdout.on(`data`,t=>{e.onStdout?.(Buffer.from(t).toString(`utf-8`))});let d=``;a.stderr.on(`data`,t=>{o.signal.aborted||(d+=Buffer.from(t).toString(`utf-8`)),e.onStderr?.(Buffer.from(t).toString(`utf-8`))}),a.on(`error`,e=>{o.abort(e)}),a.on(`exit`,(t,n)=>{o.signal.aborted?e.onExit?.(t,n):o.abort()});let f=new s({baseUrl:r}),p=0;for(;!u.aborted;){try{await f.health();break}catch{}if(await new Promise(e=>setTimeout(e,p*5)),p++,p>100)throw Error(`Health endpoint timed out`)}if(u.aborted)throw u.reason;return o.abort(),{client:f,dispose:()=>{a.kill()}}}async function h(){let e=p();return new Promise((t,n)=>{e.listen(0,()=>{let n=e.address().port;t(n)}).on(`error`,e=>{n(e)})}).finally(()=>{e.close()})}var g=e(r(),1);async function _(e,r={}){if(!r.directory){let e=process.cwd();try{i(e),r.directory=e}catch{let n=await t(e,`.blink`);n&&d(l(n,`build`))&&(n=void 0),n?r.directory=n:r.directory=e}}await n(r.directory);let s=i(r.directory),c={};try{c=(0,g.parse)(await f(l(r.directory,`.env.local`),`utf-8`))}catch{}let p=await a(),h=await m({command:`node`,args:[`--experimental-strip-types`,`--no-deprecation`,s.entry],env:{...process.env,...c,BLINK_TOKEN:p}});console.log(`Agent spawned`);let _=u(r?.directory??process.cwd(),`data`,`chats`),v=new o({chatId:r?.chat,chatsDirectory:_});v.setAgent(h.client);try{let t=new Promise(e=>{let t=v.subscribe(n=>{(n.status===`idle`||n.status===`error`)&&(t(),e())})});await v.sendMessages([{id:crypto.randomUUID(),created_at:new Date().toISOString(),metadata:void 0,parts:[{type:`text`,text:e.join(` `)}],role:`user`,mode:`run`}]),await t;let n=v.getState();n.error&&console.error(`Error:`,n.error),console.log(`Final state:`,n.messages.pop())}finally{v.dispose(),h.dispose()}}export{_ as default};
1
+ import{__toESM as e}from"./chunk-D9KrCrVq.js";import{findNearestEntry as t,migrateDataToBlink as n,require_main as r,resolveConfig as i}from"./util-DDB5k1Go.js";import"./dist-Ceoe3h7v.js";import{getAuthToken as a}from"./auth-CoJASYGP.js";import"./util-BgbIWOFE.js";import{ChatManager as o,Client as s}from"./chat-manager-BRchJngj.js";import{spawn as c}from"node:child_process";import{join as l,resolve as u}from"node:path";import{existsSync as d}from"node:fs";import{readFile as f}from"node:fs/promises";import{createServer as p}from"node:net";async function m(e){let t=e.env?.PORT??await h(),n=e.env?.HOST??`127.0.0.1`,r=`http://${n}:${t}`,i={...e.env??process.env,PORT:t.toString(),HOST:n},a=c(e.command,e.args,{stdio:`pipe`,env:i});e.signal?.addEventListener(`abort`,()=>{try{a.kill()}catch{}},{once:!0});let o=new AbortController,l=[o.signal];e.signal&&l.push(e.signal);let u=AbortSignal.any(l);a.stdout.on(`data`,t=>{e.onStdout?.(Buffer.from(t).toString(`utf-8`))});let d=``;a.stderr.on(`data`,t=>{o.signal.aborted||(d+=Buffer.from(t).toString(`utf-8`)),e.onStderr?.(Buffer.from(t).toString(`utf-8`))}),a.on(`error`,e=>{o.abort(e)}),a.on(`exit`,(t,n)=>{o.signal.aborted?e.onExit?.(t,n):o.abort()});let f=new s({baseUrl:r}),p=0;for(;!u.aborted;){try{await f.health();break}catch{}if(await new Promise(e=>setTimeout(e,p*5)),p++,p>100)throw Error(`Health endpoint timed out`)}if(u.aborted)throw u.reason;return o.abort(),{client:f,dispose:()=>{a.kill()}}}async function h(){let e=p();return new Promise((t,n)=>{e.listen(0,()=>{let n=e.address().port;t(n)}).on(`error`,e=>{n(e)})}).finally(()=>{e.close()})}var g=e(r(),1);async function _(e,r={}){if(!r.directory){let e=process.cwd();try{i(e),r.directory=e}catch{let n=await t(e,`.blink`);n&&d(l(n,`build`))&&(n=void 0),n?r.directory=n:r.directory=e}}await n(r.directory);let s=i(r.directory),c={};try{c=(0,g.parse)(await f(l(r.directory,`.env.local`),`utf-8`))}catch{}let p=await a(),h=await m({command:`node`,args:[`--experimental-strip-types`,`--no-deprecation`,s.entry],env:{...process.env,...c,BLINK_TOKEN:p}});console.log(`Agent spawned`);let _=u(r?.directory??process.cwd(),`.blink`,`chats`),v=new o({chatId:r?.chat,chatsDirectory:_});v.setAgent(h.client);try{let t=new Promise(e=>{let t=v.subscribe(n=>{(n.status===`idle`||n.status===`error`)&&(t(),e())})});await v.sendMessages([{id:crypto.randomUUID(),created_at:new Date().toISOString(),metadata:void 0,parts:[{type:`text`,text:e.join(` `)}],role:`user`,mode:`run`}]),await t;let n=v.getState();n.error&&console.error(`Error:`,n.error),console.log(`Final state:`,n.messages.pop())}finally{v.dispose(),h.dispose()}}export{_ as default};