Skip to content

Commit 7fc9e79

Browse files
authored
v0.8.48: prewarm, tin pg extensions, knowledge search speedups, ui consolidation, keyword search speedups
2 parents a2c9756 + bc2f641 commit 7fc9e79

776 files changed

Lines changed: 240967 additions & 6864 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/rules/global.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@ Use shared helpers from `@sim/utils` instead of writing inline implementations:
5151
- `structuredClone(value)` — built-in deep clone, no import needed. Never write `JSON.parse(JSON.stringify(obj))`
5252
- `omit(obj, keys)` from `@sim/utils/object` — remove keys from object
5353
- `filterUndefined(obj)` from `@sim/utils/object` — strip undefined-valued keys. Never write `Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined))`
54+
- `isRecordLike(value)` from `@sim/utils/object` — indexable-object guard. Never redeclare `typeof value === 'object' && value !== null && !Array.isArray(value)`
55+
- `toRecord(value)` / `toRecordOrNull(value)` / `toArray(value)` from `@sim/utils/object` — coerce an untyped payload value to a record or array. Never inline `isRecordLike(v) ? v : {}` or `Array.isArray(v) ? v : []`. Where the source is already typed, keep the inline `Array.isArray` check: it narrows, while `toArray` asserts
56+
- `toStringOrNull(value)` / `toNumberOrNull(value)` / `toBooleanOrNull(value)` from `@sim/utils/coerce` — read one scalar out of an untyped payload. Never declare a local one-liner that is byte-identical to one of these (`asString`, `getString`, `nullableString`, …). Keep a local helper that differs: one returning `undefined` rather than `null` changes the wire shape, and one adding `Number.isFinite` or a string parse is a stricter check these deliberately omit
5457
- `truncate(str, maxLength, suffix?)` from `@sim/utils/string` — safe string truncation with ellipsis
58+
- `escapeRegExp(value)` from `@sim/utils/string` — escape regex metacharacters. Never inline `replace(/[.*+?^${}()|[\]\\]/g, '\\$&')`
59+
- `compareStrings(left, right)` from `@sim/utils/string` — code-unit string comparator for hashes, fingerprints, and values compared across processes. Never `localeCompare` there
5560
- `backoffWithJitter(attempt, retryAfterMs, options?)` from `@sim/utils/retry` — exponential backoff with jitter
5661
- `parseRetryAfter(header)` from `@sim/utils/retry` — parse HTTP `Retry-After` header to milliseconds
5762

.claude/rules/sim-imports.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ paths:
1313

1414
```typescript
1515
// ✓ Good
16+
import { Chip } from '@sim/emcn'
1617
import { useWorkflowStore } from '@/stores/workflows/store'
17-
import { Button } from '@/components/ui/button'
1818

1919
// ✗ Bad
2020
import { useWorkflowStore } from '../../../stores/workflows/store'

.cursor/rules/global.mdc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,12 @@ Use shared helpers from `@sim/utils` instead of writing inline implementations:
5454
- `structuredClone(value)` — built-in deep clone, no import needed. Never write `JSON.parse(JSON.stringify(obj))`
5555
- `omit(obj, keys)` from `@sim/utils/object` — remove keys from object
5656
- `filterUndefined(obj)` from `@sim/utils/object` — strip undefined-valued keys. Never write `Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined))`
57+
- `isRecordLike(value)` from `@sim/utils/object` — indexable-object guard. Never redeclare `typeof value === 'object' && value !== null && !Array.isArray(value)`
58+
- `toRecord(value)` / `toRecordOrNull(value)` / `toArray(value)` from `@sim/utils/object` — coerce an untyped payload value to a record or array. Never inline `isRecordLike(v) ? v : {}` or `Array.isArray(v) ? v : []`. Where the source is already typed, keep the inline `Array.isArray` check: it narrows, while `toArray` asserts
59+
- `toStringOrNull(value)` / `toNumberOrNull(value)` / `toBooleanOrNull(value)` from `@sim/utils/coerce` — read one scalar out of an untyped payload. Never declare a local one-liner that is byte-identical to one of these (`asString`, `getString`, `nullableString`, …). Keep a local helper that differs: one returning `undefined` rather than `null` changes the wire shape, and one adding `Number.isFinite` or a string parse is a stricter check these deliberately omit
5760
- `truncate(str, maxLength, suffix?)` from `@sim/utils/string` — safe string truncation with ellipsis
61+
- `escapeRegExp(value)` from `@sim/utils/string` — escape regex metacharacters. Never inline `replace(/[.*+?^${}()|[\]\\]/g, '\\$&')`
62+
- `compareStrings(left, right)` from `@sim/utils/string` — code-unit string comparator for hashes, fingerprints, and values compared across processes. Never `localeCompare` there
5863
- `backoffWithJitter(attempt, retryAfterMs, options?)` from `@sim/utils/retry` — exponential backoff with jitter
5964
- `parseRetryAfter(header)` from `@sim/utils/retry` — parse HTTP `Retry-After` header to milliseconds
6065

.cursor/rules/sim-imports.mdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ globs: ["apps/sim/**/*.ts","apps/sim/**/*.tsx"]
1313

1414
```typescript
1515
// ✓ Good
16+
import { Chip } from '@sim/emcn'
1617
import { useWorkflowStore } from '@/stores/workflows/store'
17-
import { Button } from '@/components/ui/button'
1818

1919
// ✗ Bad
2020
import { useWorkflowStore } from '../../../stores/workflows/store'

.github/workflows/test-build.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ jobs:
149149
KNOWLEDGE_ACL_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim
150150
run: bunx vitest run --mode integration lib/workspace-files/search/dispatcher.integration.ts
151151

152+
- name: Verify workspace file version history on PostgreSQL 17
153+
working-directory: apps/sim
154+
env:
155+
KNOWLEDGE_ACL_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim
156+
run: bunx vitest run --mode integration lib/uploads/contexts/workspace/__integration__/file-versions.integration.ts
157+
158+
- name: Verify file search trigram estimate against pg_trgm
159+
working-directory: apps/sim
160+
env:
161+
KNOWLEDGE_ACL_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim
162+
run: bunx vitest run --mode integration lib/workspace-files/search/index-plan.integration.ts
163+
152164
- name: Verify SCIM and administration over real HTTP
153165
working-directory: apps/sim
154166
env:
@@ -219,6 +231,8 @@ jobs:
219231
bunx vitest run
220232
lib/table/rows/secret-provenance.postgres.test.ts
221233
lib/memory/message-provenance.postgres.test.ts
234+
lib/memory/conversation-store.postgres.test.ts
235+
lib/memory/summary-store.postgres.test.ts
222236
executor/handlers/agent/memory-harness.postgres.test.ts
223237
224238
- name: Verify Search vector projection upgrade in PostgreSQL
@@ -229,6 +243,7 @@ jobs:
229243
bunx vitest run
230244
script-migrations/0016_backfill_search_vectors.postgres.test.ts
231245
script-migrations/0018_repair_workspace_file_content_revision.postgres.test.ts
246+
script-migrations/0019_tin_keyword_projection.postgres.test.ts
232247
233248
- name: Verify Search progress, pagination, and outbox scheduling in PostgreSQL
234249
working-directory: apps/sim
@@ -246,6 +261,8 @@ jobs:
246261
lib/knowledge/__integration__/stored-document-recovery.integration.ts
247262
lib/knowledge/__integration__/connector-partition-work.integration.ts
248263
lib/knowledge/__integration__/listing-continuation.integration.ts
264+
lib/knowledge/__integration__/member-scope-renewal.integration.ts
265+
lib/knowledge/__integration__/slack-empty-threads.integration.ts
249266
lib/knowledge/__integration__/kb-block-search.integration.ts
250267
lib/core/outbox/service.integration.ts
251268
lib/knowledge/__integration__/connector-upload.integration.ts

CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ You are a professional software engineer. All code must follow best practices: a
1616
- `getErrorMessage(e, fallback?)` from `@sim/utils/errors` — extract message string from unknown caught value; never write `e instanceof Error ? e.message : 'fallback'`
1717
- `structuredClone(value)` — built-in deep clone; never `JSON.parse(JSON.stringify(...))`
1818
- `omit(obj, keys)` / `filterUndefined(obj)` from `@sim/utils/object` — object trimming; never `Object.fromEntries(Object.entries(...).filter(...))`
19+
- `isRecordLike(value)` from `@sim/utils/object` — never redeclare `typeof value === 'object' && value !== null && !Array.isArray(value)`
20+
- `toRecord(value)` / `toRecordOrNull(value)` / `toArray(value)` from `@sim/utils/object` — coerce an untyped payload value to a record or array; never inline `isRecordLike(v) ? v : {}` or `Array.isArray(v) ? v : []`. Where the source is already typed, keep the inline `Array.isArray` check: it narrows, while `toArray` asserts
21+
- `toStringOrNull(value)` / `toNumberOrNull(value)` / `toBooleanOrNull(value)` from `@sim/utils/coerce` — read one scalar out of an untyped payload; never declare a local one-liner byte-identical to one of these. Keep a local helper that differs: `undefined` instead of `null` changes the wire shape, and a `Number.isFinite` or string-parse variant is a stricter check these omit
1922
- `truncate(str, maxLength, suffix?)` from `@sim/utils/string` — never inline slice + ellipsis
23+
- `escapeRegExp(value)` from `@sim/utils/string` — never inline `replace(/[.*+?^${}()|[\]\\]/g, '\\$&')`
24+
- `compareStrings(left, right)` from `@sim/utils/string` — code-unit ordering for hashes, fingerprints, and cross-process comparisons; never `localeCompare` there
2025
- `backoffWithJitter(attempt, retryAfterMs, options?)` / `parseRetryAfter(header)` from `@sim/utils/retry` — shared retry pacing; never reimplement exponential backoff inline
2126
- **Deployment flags in the browser**: client code inside a workspace, organization, or standalone settings surface reads `hosted`, `billingEnabled`, `chatEnabled`, and the enterprise feature set through `useDeploymentShape()` (components) or `getDeploymentShape()` (block conditions, stores, helpers) from `@/lib/core/config/deployment-shape`, never `isHosted`/`isBillingEnabled`/... from `env-flags`. The constants freeze at module init from the root layout's `NEXT_PUBLIC_*` transport, which Next's bare 404 shell and `global-error` never emit; the reader is seeded from the server-resolved workspace host context, organization layout, or standalone settings layout instead. Server code keeps reading `env-flags`
2227
- **Package Manager**: Use `bun` and `bunx`, not `npm` and `npx`

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<p align="center">
99
<a href="https://deepwiki.com/simstudioai/sim" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/Ask-DeepWiki-E6E6E6?labelColor=C3C3C3&color=E6E6E6" alt="Ask DeepWiki"></a>
10-
<a href="https://cursor.com/link/prompt?text=Help%20me%20set%20up%20Sim%20locally.%20Follow%20these%20steps%3A%0A%0A1.%20First%2C%20verify%20Docker%20is%20installed%20and%20running%3A%0A%20%20%20docker%20--version%0A%20%20%20docker%20info%0A%0A2.%20Clone%20the%20repository%3A%0A%20%20%20git%20clone%20https%3A%2F%2Fgithub.com%2Fsimstudioai%2Fsim.git%0A%20%20%20cd%20sim%0A%0A3.%20Generate%20required%20secrets%20%28the%20stack%20will%20not%20start%20without%20them%29%3A%0A%20%20%20cat%20%3E%20.env%20%3C%3C%20EOF%0A%20%20%20BETTER_AUTH_SECRET%3D%24%28openssl%20rand%20-hex%2032%29%0A%20%20%20ENCRYPTION_KEY%3D%24%28openssl%20rand%20-hex%2032%29%0A%20%20%20INTERNAL_API_SECRET%3D%24%28openssl%20rand%20-hex%2032%29%0A%20%20%20CRON_SECRET%3D%24%28openssl%20rand%20-hex%2032%29%0A%20%20%20EOF%0A%0A4.%20Start%20the%20services%20with%20Docker%20Compose%3A%0A%20%20%20docker%20compose%20-f%20docker-compose.prod.yml%20up%20-d%0A%0A4.%20Wait%20for%20all%20containers%20to%20be%20healthy%20(this%20may%20take%201-2%20minutes)%3A%0A%20%20%20docker%20compose%20-f%20docker-compose.prod.yml%20ps%0A%0A5.%20Verify%20the%20app%20is%20accessible%20at%20http%3A%2F%2Flocalhost%3A3000%0A%0AIf%20there%20are%20any%20errors%2C%20help%20me%20troubleshoot%20them.%20Common%20issues%3A%0A-%20Port%203000%2C%203002%2C%20or%205432%20already%20in%20use%0A-%20Docker%20not%20running%0A-%20Insufficient%20memory%20(needs%2012GB%2B%20RAM)%0A%0AFor%20local%20AI%20models%20with%20Ollama%2C%20use%20this%20instead%20of%20step%203%3A%0A%20%20%20docker%20compose%20-f%20docker-compose.ollama.yml%20--profile%20setup%20up%20-d"><img src="https://img.shields.io/badge/Set%20Up%20with-Cursor-E6E6E6?logo=cursor&logoColor=1A1A1A&labelColor=C3C3C3&color=E6E6E6" alt="Set Up with Cursor"></a>
10+
<a href="https://cursor.com/link/prompt?text=Help%20me%20set%20up%20Sim%20locally.%20Follow%20these%20steps%3A%0A%0A1.%20First%2C%20verify%20Docker%20is%20installed%20and%20running%3A%0A%20%20%20docker%20--version%0A%20%20%20docker%20info%0A%0A2.%20Clone%20the%20repository%3A%0A%20%20%20git%20clone%20https%3A%2F%2Fgithub.com%2Fsimstudioai%2Fsim.git%0A%20%20%20cd%20sim%0A%0A3.%20Generate%20required%20secrets%20%28the%20stack%20will%20not%20start%20without%20them%29%3A%0A%20%20%20cat%20%3E%20.env%20%3C%3C%20EOF%0A%20%20%20BETTER_AUTH_SECRET%3D%24%28openssl%20rand%20-hex%2032%29%0A%20%20%20ENCRYPTION_KEY%3D%24%28openssl%20rand%20-hex%2032%29%0A%20%20%20INTERNAL_API_SECRET%3D%24%28openssl%20rand%20-hex%2032%29%0A%20%20%20CRON_SECRET%3D%24%28openssl%20rand%20-hex%2032%29%0A%20%20%20POSTGRES_PASSWORD%3D%24%28openssl%20rand%20-hex%2024%29%0A%20%20%20EOF%0A%0A4.%20Start%20the%20services%20with%20Docker%20Compose%3A%0A%20%20%20docker%20compose%20-f%20docker-compose.prod.yml%20up%20-d%0A%0A4.%20Wait%20for%20all%20containers%20to%20be%20healthy%20(this%20may%20take%201-2%20minutes)%3A%0A%20%20%20docker%20compose%20-f%20docker-compose.prod.yml%20ps%0A%0A5.%20Verify%20the%20app%20is%20accessible%20at%20http%3A%2F%2Flocalhost%3A3000%0A%0AIf%20there%20are%20any%20errors%2C%20help%20me%20troubleshoot%20them.%20Common%20issues%3A%0A-%20Port%203000%20or%203002%20already%20in%20use%0A-%20Docker%20not%20running%0A-%20Insufficient%20memory%20(needs%2012GB%2B%20RAM)%0A%0AFor%20local%20AI%20models%20with%20Ollama%2C%20use%20this%20instead%20of%20step%203%3A%0A%20%20%20docker%20compose%20-f%20docker-compose.ollama.yml%20--profile%20setup%20up%20-d"><img src="https://img.shields.io/badge/Set%20Up%20with-Cursor-E6E6E6?logo=cursor&logoColor=1A1A1A&labelColor=C3C3C3&color=E6E6E6" alt="Set Up with Cursor"></a>
1111
</p>
1212

1313
<p align="center">

apps/desktop/src/main/ipc.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
type TerminalToolArgs,
2828
} from '@sim/terminal-protocol'
2929
import { getErrorMessage } from '@sim/utils/errors'
30-
import { isRecordLike } from '@sim/utils/object'
30+
import { isRecordLike, toRecord } from '@sim/utils/object'
3131
import { PASTE_LIMITS, utf8ByteLength } from '@sim/utils/paste'
3232
import type { BrowserWindow, IpcMainEvent, IpcMainInvokeEvent, WebContents } from 'electron'
3333
import { clipboard, ipcMain, shell } from 'electron'
@@ -856,7 +856,7 @@ export function registerIpcHandlers(deps: IpcDeps): void {
856856
) {
857857
return { ok: false, error: `Unknown browser tool: ${String(tool)}` }
858858
}
859-
const toolParams = isRecordLike(params) ? params : {}
859+
const toolParams = toRecord(params)
860860
return executeTool(
861861
scope,
862862
tool,
@@ -1532,7 +1532,7 @@ export function registerIpcHandlers(deps: IpcDeps): void {
15321532
) {
15331533
return { ok: false, error: `Unknown terminal tool: ${String(tool)}` }
15341534
}
1535-
const call = isRecordLike(params) ? params : {}
1535+
const call = toRecord(params)
15361536
if (!isTerminalOperation(call.operation)) {
15371537
return { ok: false, error: `Unknown terminal operation: ${String(call.operation)}` }
15381538
}

apps/desktop/src/main/local-filesystem.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from '@sim/desktop-bridge/local-filesystem-limits'
2020
import { generateId } from '@sim/utils/id'
2121
import { isRecordLike } from '@sim/utils/object'
22+
import { escapeRegExp } from '@sim/utils/string'
2223
import { app, dialog, shell } from 'electron'
2324
import micromatch from 'micromatch'
2425
import safeRegex from 'safe-regex2'
@@ -1114,7 +1115,7 @@ export class LocalFilesystemService {
11141115
regex =
11151116
rawPattern !== undefined
11161117
? new RegExp(expression, ignoreCase ? 'i' : '')
1117-
: new RegExp(expression.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), ignoreCase ? 'i' : '')
1118+
: new RegExp(escapeRegExp(expression), ignoreCase ? 'i' : '')
11181119
} catch {
11191120
// An empty result set would tell the model the string appears nowhere in
11201121
// the user's files — a factual claim it will act on, when in truth the

0 commit comments

Comments
 (0)