@agent-native/core 0.164.15 → 0.164.17

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 (52) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/netlify.toml +4 -0
  3. package/corpus/templates/clips/actions/request-transcript.ts +10 -6
  4. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +298 -3
  5. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +3 -0
  6. package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +18 -4
  7. package/corpus/templates/content/app/i18n-data.ts +160 -0
  8. package/corpus/templates/content/docs/solutions/2026-08-18-colored-text-highlighting-shape.md +693 -0
  9. package/corpus/templates/content/package.json +1 -0
  10. package/corpus/templates/content/shared/nfm.ts +14 -3
  11. package/corpus/templates/factory/AGENTS.md +24 -29
  12. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +8 -28
  13. package/corpus/templates/factory/actions/get-triage-config.ts +1 -0
  14. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +67 -59
  15. package/corpus/templates/factory/actions/list-triage-items.ts +6 -1
  16. package/corpus/templates/factory/actions/reconcile-triage-run.ts +7 -1
  17. package/corpus/templates/factory/actions/save-triage-config.ts +27 -7
  18. package/corpus/templates/factory/actions/start-builder-for-item.ts +113 -31
  19. package/corpus/templates/factory/actions/view-screen.ts +12 -0
  20. package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +457 -0
  21. package/corpus/templates/factory/app/components/factory/FactoryWorkspaceActions.tsx +53 -0
  22. package/corpus/templates/factory/app/components/layout/Layout.tsx +2 -0
  23. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +3 -1
  24. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +10 -7
  25. package/corpus/templates/factory/app/i18n/en-US.ts +3 -0
  26. package/corpus/templates/factory/app/routes/agents.tsx +22 -1
  27. package/corpus/templates/factory/app/routes/factory-settings.tsx +34 -0
  28. package/corpus/templates/factory/app/routes/factory.tsx +33 -323
  29. package/corpus/templates/factory/server/connectors/slack.ts +62 -0
  30. package/corpus/templates/factory/server/db/schema.ts +1 -0
  31. package/corpus/templates/factory/server/lib/slack-feedback-prompt.ts +30 -0
  32. package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -8
  33. package/corpus/templates/factory/server/plugins/factory-migrations.ts +7 -0
  34. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +43 -25
  35. package/corpus/templates/factory/server/triage/ai-services-git.ts +2 -0
  36. package/corpus/templates/factory/server/triage/pr-monitor.ts +2 -1
  37. package/corpus/templates/factory/server/triage/pr-policy.ts +197 -19
  38. package/corpus/templates/factory/server/triage/review-skill-alignment.ts +127 -0
  39. package/corpus/templates/factory/server/triage/slack-client.ts +79 -6
  40. package/dist/client/MultiTabAssistantChat.js +28 -1
  41. package/dist/client/use-chat-threads.d.ts +1 -0
  42. package/dist/client/use-chat-threads.js +13 -3
  43. package/dist/collab/awareness.d.ts +2 -2
  44. package/dist/notifications/routes.d.ts +3 -3
  45. package/dist/observability/routes.d.ts +5 -5
  46. package/dist/progress/routes.d.ts +1 -1
  47. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  48. package/dist/server/auth.js +2 -2
  49. package/dist/server/realtime-token.d.ts +1 -1
  50. package/dist/server/transcribe-voice.d.ts +1 -1
  51. package/dist/vite/client.js +2 -0
  52. package/package.json +1 -1
@@ -2,13 +2,18 @@ import { resolveConnectorSecret } from "../connectors/credentials.js";
2
2
  import {
3
3
  getChannelHistory as readChannelHistory,
4
4
  addEyesReaction as writeEyesReaction,
5
+ authTest as readAuthTest,
6
+ getEyesReaction as readEyesReaction,
5
7
  getThread as readThread,
6
8
  getTeamInfo as readTeamInfo,
7
9
  getUserInfo as readUserInfo,
8
10
  postThreadReply as writeThreadReply,
9
11
  type ChannelHistoryResult,
12
+ type SlackAuthTestResult,
13
+ type SlackMessage,
10
14
  type SlackPostMessageResult,
11
15
  type SlackReactionResult,
16
+ type SlackReactionState,
12
17
  type SlackTeamInfo,
13
18
  type SlackUserInfo,
14
19
  type SlackTokenResolver,
@@ -40,14 +45,38 @@ function createTokenResolver({
40
45
 
41
46
  export function createSlackReader(identity: SlackReaderIdentity) {
42
47
  const tokenResolver = createTokenResolver(identity);
48
+ const identities = new Map<Workspace, SlackAuthTestResult>();
49
+
50
+ async function getAgentNativeIdentity(
51
+ workspace: Workspace,
52
+ ): Promise<SlackAuthTestResult> {
53
+ const existing = identities.get(workspace);
54
+ if (existing) return existing;
55
+ const auth = await readAuthTest(workspace, tokenResolver);
56
+ const userName = auth.userName.trim().replace(/^@/, "").toLowerCase();
57
+ if (userName !== "agent-native") {
58
+ throw new Error(
59
+ `Slack credential authenticated as @${auth.userName}, not @agent-native.`,
60
+ );
61
+ }
62
+ identities.set(workspace, auth);
63
+ return auth;
64
+ }
65
+
66
+ async function verifyAgentNativeIdentity(
67
+ workspace: Workspace,
68
+ ): Promise<void> {
69
+ await getAgentNativeIdentity(workspace);
70
+ }
43
71
 
44
72
  return {
45
- getChannelHistory(
73
+ async getChannelHistory(
46
74
  workspace: Workspace,
47
75
  channelId: string,
48
76
  limit?: number,
49
77
  cursor?: string,
50
78
  ): Promise<ChannelHistoryResult> {
79
+ await verifyAgentNativeIdentity(workspace);
51
80
  return readChannelHistory(
52
81
  workspace,
53
82
  channelId,
@@ -56,19 +85,25 @@ export function createSlackReader(identity: SlackReaderIdentity) {
56
85
  tokenResolver,
57
86
  );
58
87
  },
59
- getTeamInfo(workspace: Workspace): Promise<SlackTeamInfo> {
88
+ async getTeamInfo(workspace: Workspace): Promise<SlackTeamInfo> {
89
+ await verifyAgentNativeIdentity(workspace);
60
90
  return readTeamInfo(workspace, tokenResolver);
61
91
  },
62
- getUserInfo(workspace: Workspace, userId: string): Promise<SlackUserInfo> {
92
+ async getUserInfo(
93
+ workspace: Workspace,
94
+ userId: string,
95
+ ): Promise<SlackUserInfo> {
96
+ await verifyAgentNativeIdentity(workspace);
63
97
  return readUserInfo(workspace, userId, tokenResolver);
64
98
  },
65
- getThread(
99
+ async getThread(
66
100
  workspace: Workspace,
67
101
  channelId: string,
68
102
  threadTs: string,
69
103
  limit?: number,
70
104
  cursor?: string,
71
105
  ): Promise<ThreadRepliesResult> {
106
+ await verifyAgentNativeIdentity(workspace);
72
107
  return readThread(
73
108
  workspace,
74
109
  channelId,
@@ -78,19 +113,21 @@ export function createSlackReader(identity: SlackReaderIdentity) {
78
113
  tokenResolver,
79
114
  );
80
115
  },
81
- addEyesReaction(
116
+ async addEyesReaction(
82
117
  workspace: Workspace,
83
118
  channelId: string,
84
119
  timestamp: string,
85
120
  ): Promise<SlackReactionResult> {
121
+ await verifyAgentNativeIdentity(workspace);
86
122
  return writeEyesReaction(workspace, channelId, timestamp, tokenResolver);
87
123
  },
88
- postThreadReply(
124
+ async postThreadReply(
89
125
  workspace: Workspace,
90
126
  channelId: string,
91
127
  threadTs: string,
92
128
  text: string,
93
129
  ): Promise<SlackPostMessageResult> {
130
+ await verifyAgentNativeIdentity(workspace);
94
131
  return writeThreadReply(
95
132
  workspace,
96
133
  channelId,
@@ -99,5 +136,41 @@ export function createSlackReader(identity: SlackReaderIdentity) {
99
136
  tokenResolver,
100
137
  );
101
138
  },
139
+ async getEyesReaction(
140
+ workspace: Workspace,
141
+ channelId: string,
142
+ timestamp: string,
143
+ ): Promise<SlackReactionState> {
144
+ await verifyAgentNativeIdentity(workspace);
145
+ return readEyesReaction(workspace, channelId, timestamp, tokenResolver);
146
+ },
147
+ async getCompleteThread(
148
+ workspace: Workspace,
149
+ channelId: string,
150
+ threadTs: string,
151
+ ): Promise<{ messages: SlackMessage[]; hasMore: boolean }> {
152
+ const messages: SlackMessage[] = [];
153
+ let cursor: string | undefined;
154
+ for (let page = 0; page < 100; page += 1) {
155
+ const result = await this.getThread(
156
+ workspace,
157
+ channelId,
158
+ threadTs,
159
+ 100,
160
+ cursor,
161
+ );
162
+ messages.push(...result.messages);
163
+ if (!result.has_more) return { messages, hasMore: false };
164
+ if (!result.next_cursor) {
165
+ throw new Error(
166
+ "Slack thread pagination is incomplete because the provider omitted its next cursor.",
167
+ );
168
+ }
169
+ cursor = result.next_cursor;
170
+ }
171
+ return { messages, hasMore: true };
172
+ },
173
+ verifyAgentNativeIdentity,
174
+ getAgentNativeIdentity,
102
175
  };
103
176
  }
@@ -515,7 +515,7 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
515
515
  threadUrlParamName,
516
516
  threadUrlSyncEnabled,
517
517
  ]);
518
- const { threads, activeThreadId, isLoading, createThread, switchThread: switchThreadState, forkThread, saveThreadData, generateTitle, searchThreads, loadMoreThreads, refreshThreads, hasMoreThreads, isLoadingMoreThreads, threadsLoadError, isNewThread, pinThread, renameThread, } = useChatThreads(apiUrl, storageKey, scope, {
518
+ const { threads, activeThreadId, isLoading, createThread, switchThread: switchThreadState, forkThread, saveThreadData, generateTitle, searchThreads, loadMoreThreads, refreshThreads, hasMoreThreads, isLoadingMoreThreads, threadsLoadError, restoredThreadIdOnListFailure, isNewThread, pinThread, renameThread, } = useChatThreads(apiUrl, storageKey, scope, {
519
519
  restoreActiveThread,
520
520
  routeThreadId: threadUrlSyncEnabled
521
521
  ? urlThreadId
@@ -1017,7 +1017,34 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
1017
1017
  // optimistic id for a brand-new session); the activeThreadId effect above
1018
1018
  // adds it to openTabIds without spinning up a duplicate thread.
1019
1019
  const autoCreatingRef = useRef(false);
1020
+ const restoreFailureReplacementInFlightRef = useRef(null);
1020
1021
  const lastTabReplacementInFlightRef = useRef(false);
1022
+ useEffect(() => {
1023
+ if (isLoading ||
1024
+ !restoredThreadIdOnListFailure ||
1025
+ activeThreadId !== restoredThreadIdOnListFailure ||
1026
+ restoreFailureReplacementInFlightRef.current ===
1027
+ restoredThreadIdOnListFailure) {
1028
+ return;
1029
+ }
1030
+ restoreFailureReplacementInFlightRef.current =
1031
+ restoredThreadIdOnListFailure;
1032
+ void createThread().then((id) => {
1033
+ if (!id) {
1034
+ restoreFailureReplacementInFlightRef.current = null;
1035
+ return;
1036
+ }
1037
+ newThreadIds.current.add(id);
1038
+ setOpenTabIds([id]);
1039
+ writeThreadUrl(null, { replace: true });
1040
+ });
1041
+ }, [
1042
+ activeThreadId,
1043
+ createThread,
1044
+ isLoading,
1045
+ restoredThreadIdOnListFailure,
1046
+ writeThreadUrl,
1047
+ ]);
1021
1048
  useEffect(() => {
1022
1049
  if (isLoading || autoCreatingRef.current)
1023
1050
  return;
@@ -96,6 +96,7 @@ export declare function useChatThreads(apiUrl?: string, storageKey?: string, sco
96
96
  hasMoreThreads: boolean;
97
97
  isLoadingMoreThreads: boolean;
98
98
  threadsLoadError: string | null;
99
+ restoredThreadIdOnListFailure: string | null;
99
100
  isNewThread: (id: string) => boolean;
100
101
  };
101
102
  export {};
@@ -157,6 +157,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
157
157
  const [hasMoreThreads, setHasMoreThreads] = useState(false);
158
158
  const [isLoadingMoreThreads, setIsLoadingMoreThreads] = useState(false);
159
159
  const [threadsLoadError, setThreadsLoadError] = useState(null);
160
+ const [restoredThreadIdOnListFailure, setRestoredThreadIdOnListFailure] = useState(null);
160
161
  const nextThreadsOffsetRef = useRef(0);
161
162
  const latestFetchRequestRef = useRef(0);
162
163
  const threadsRef = useRef(threads);
@@ -483,12 +484,20 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
483
484
  const loadedThreads = await fetchThreads();
484
485
  const restoredId = activeThreadIdRef.current;
485
486
  if (loadedThreads === undefined) {
486
- // Thread-list fetch failed. Do not reclassify a saved id as a new
487
- // optimistic tab; AssistantChat should still get a chance to restore
488
- // the specific saved thread via /threads/:id.
487
+ // Keep the saved id intact for retry/history, but tell the owning
488
+ // surface to replace the visible tab. A failed list request cannot
489
+ // prove that the saved thread is gone; it only proves that this mount
490
+ // cannot safely restore it.
491
+ if (restoredId &&
492
+ autoCreate &&
493
+ !routeControlsActiveThread &&
494
+ !newlyCreatedRef.current.has(restoredId)) {
495
+ setRestoredThreadIdOnListFailure(restoredId);
496
+ }
489
497
  setIsLoading(false);
490
498
  return;
491
499
  }
500
+ setRestoredThreadIdOnListFailure(null);
492
501
  // Exempts route-owned threads (the URL names what the user asked for) and
493
502
  // ids this client generated, which have never reached the server.
494
503
  const lookupRestored = Boolean(restoredId &&
@@ -1074,6 +1083,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
1074
1083
  hasMoreThreads,
1075
1084
  isLoadingMoreThreads,
1076
1085
  threadsLoadError,
1086
+ restoredThreadIdOnListFailure,
1077
1087
  isNewThread,
1078
1088
  };
1079
1089
  }
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
62
62
  error: string;
63
63
  states?: undefined;
64
64
  } | {
65
- error?: undefined;
66
65
  states: {
67
66
  clientId: number;
68
67
  state: string;
69
68
  }[];
69
+ error?: undefined;
70
70
  }>>;
71
71
  /**
72
72
  * GET /_agent-native/collab/:docId/users
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
77
77
  error: string;
78
78
  users?: undefined;
79
79
  } | {
80
- error?: undefined;
81
80
  users: {
82
81
  clientId: number;
83
82
  lastSeen: number;
84
83
  }[];
84
+ error?: undefined;
85
85
  }>>;
@@ -11,14 +11,14 @@
11
11
  * DELETE /_agent-native/notifications/:id — delete
12
12
  */
13
13
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
14
- error?: undefined;
15
14
  count: number;
16
15
  updated?: undefined;
16
+ error?: undefined;
17
17
  ok?: undefined;
18
18
  } | {
19
- error?: undefined;
20
19
  count?: undefined;
21
20
  updated: number;
21
+ error?: undefined;
22
22
  ok?: undefined;
23
23
  } | {
24
24
  count?: undefined;
@@ -26,8 +26,8 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
26
26
  error: string;
27
27
  ok?: undefined;
28
28
  } | {
29
- error?: undefined;
30
29
  count?: undefined;
31
30
  updated?: undefined;
31
+ error?: undefined;
32
32
  ok: boolean;
33
33
  }>>;
@@ -41,27 +41,27 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
41
41
  thumbsUpRate: number;
42
42
  avgEvalScore: number;
43
43
  } | {
44
- error?: undefined;
45
- ok?: undefined;
46
44
  summary: import("./types.js").TraceSummary;
47
45
  spans: import("./types.js").TraceSpan[];
48
46
  id?: undefined;
49
- } | {
50
47
  error?: undefined;
51
48
  ok?: undefined;
49
+ } | {
52
50
  summary?: undefined;
53
51
  spans?: undefined;
54
52
  id: string;
55
- } | {
53
+ error?: undefined;
56
54
  ok?: undefined;
55
+ } | {
57
56
  summary?: undefined;
58
57
  spans?: undefined;
59
58
  id?: undefined;
60
59
  error: any;
60
+ ok?: undefined;
61
61
  } | {
62
- error?: undefined;
63
62
  summary?: undefined;
64
63
  spans?: undefined;
65
64
  id?: undefined;
65
+ error?: undefined;
66
66
  ok: boolean;
67
67
  }>>;
@@ -15,6 +15,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
15
15
  error: string;
16
16
  ok?: undefined;
17
17
  } | {
18
- error?: undefined;
19
18
  ok: boolean;
19
+ error?: undefined;
20
20
  }>>;
@@ -27,10 +27,10 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
+ error?: undefined;
30
31
  ok: boolean;
31
32
  key: string;
32
33
  baseUrlKey?: string;
33
34
  scope: AgentEngineApiKeyScope;
34
- error?: undefined;
35
35
  }>>;
36
36
  export {};
@@ -1124,8 +1124,8 @@ const DESKTOP_AUTH_TOKEN_BODY_ORIGINS = new Set([
1124
1124
  "https://tauri.localhost",
1125
1125
  "http://localhost:1420",
1126
1126
  ]);
1127
- // 5-minute TTL for exchange entries (short — single-use tokens).
1128
- const DESKTOP_EXCHANGE_TTL_MS = 5 * 60 * 1000;
1127
+ // 10-minute TTL for exchange entries (short — single-use tokens).
1128
+ const DESKTOP_EXCHANGE_TTL_MS = 10 * 60 * 1000;
1129
1129
  function normalizeDesktopFlowId(value) {
1130
1130
  if (typeof value !== "string")
1131
1131
  return null;
@@ -26,8 +26,8 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
26
26
  expiresAt?: undefined;
27
27
  ttlSeconds?: undefined;
28
28
  } | {
29
- error?: undefined;
30
29
  token: string;
31
30
  expiresAt: string;
32
31
  ttlSeconds: number;
32
+ error?: undefined;
33
33
  }>>;
@@ -20,6 +20,6 @@ export declare function createTranscribeVoiceHandler(): import("h3").EventHandle
20
20
  error: string;
21
21
  text?: undefined;
22
22
  } | {
23
- error?: undefined;
24
23
  text: string;
24
+ error?: undefined;
25
25
  }>>;
@@ -2028,6 +2028,8 @@ function ssrStubPlugin(packages) {
2028
2028
  "init",
2029
2029
  "isChangeOrigin",
2030
2030
  "isNodeEmpty",
2031
+ "markInputRule",
2032
+ "markPasteRule",
2031
2033
  "mergeAttributes",
2032
2034
  "renderToString",
2033
2035
  "applyUpdate",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.164.15",
3
+ "version": "0.164.17",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {