Skip to content

Commit 75cb92c

Browse files
Merge remote-tracking branch 'origin/staging' into fix/kb-connector-sync-followup
# Conflicts: # apps/sim/background/knowledge-connector-sync.ts # apps/sim/lib/knowledge/connectors/queue.test.ts # apps/sim/lib/knowledge/connectors/queue.ts # apps/sim/lib/knowledge/connectors/sync-engine.ts # apps/sim/lib/knowledge/orchestration/connectors.test.ts # apps/sim/lib/knowledge/orchestration/connectors.ts
2 parents 5d0ac9c + fb8f0d6 commit 75cb92c

497 files changed

Lines changed: 80985 additions & 3868 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.

.agents/skills/ship/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ gh pr create --base staging --title "COMMIT_MESSAGE" --body "PR_BODY"
150150

151151
## Important Notes
152152

153-
- Always confirm the commit message and PR description with the user before executing
153+
- Do not ask the user to confirm the commit message or PR description before executing
154154
- The PR should be created against `staging` branch
155155
- Keep descriptions concise and in active voice
156156
- Match the user's previous PR style: direct, no fluff, bullet points

.claude/rules/sim-list-ordering.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,71 @@ Left-to-right becomes top-to-bottom. A toolbar reading `Filter · Sort · Export
2626

2727
Platform-only entries (desktop **Browser** and **Terminal**) trail the shared set rather than interleaving, so the common prefix is identical on every platform.
2828

29+
## Grouping: one rule, against the consequential group
30+
31+
Order is governed above. **Separators are governed here** — and the answer is: use at most one.
32+
33+
Put a single `DropdownMenuSeparator` against the **consequential group** — the actions that
34+
delete, detach, or change a run — and nowhere else. Everything on the other side of it runs
35+
uninterrupted in toolbar-mirroring order.
36+
37+
That group trails in almost every menu, so in practice the rule reads "one rule immediately
38+
before Delete / Leave / Close / Hide". It leads in exactly one place: the **logs row menu**,
39+
where `Retry` and `Cancel Run` are the primary actions on a failed run and sit at the top, with
40+
the rule beneath them. Ordering follows the surface (see "The rule" above); the separator simply
41+
fences whichever end the consequential group occupies. A menu whose consequential actions are
42+
merely *disabled* still gets no extra rule — `disabled` is not a group.
43+
44+
```tsx
45+
// ✗ Bad — four semantic bands the user meets nowhere else
46+
Open in new tab │─── Rename, Lock │─── Duplicate, Export │─── Delete
47+
48+
// ✓ Good — one rule, isolating the irreversible action
49+
Open in new tab, Rename, Lock, Duplicate, Export │─── Delete
50+
```
51+
52+
**Why one.** No toolbar in this app renders a divider — every header is a flat
53+
`HEADER_ACTION_CLUSTER` (`gap-1`) chip row and every bulk action bar a flat `gap-[5px]` run. A
54+
menu banded into navigation / status / edit / copy / destructive therefore teaches a taxonomy
55+
that appears on no other surface, and because each band is conditional, the same action lands in
56+
a different group depending on which sibling items happen to be visible. The one thing a rule
57+
genuinely buys is a stop before the action you cannot undo.
58+
59+
A second rule is justified only when a menu mixes genuinely different *scopes* — cell-level and
60+
table-level actions in one menu, say — not different verbs.
61+
62+
**The one standing exception: menus that emulate a native menu.** The text-editor menu
63+
(`editor-context-menu.tsx`), the terminal menu (`terminal-context-menu.tsx`), and the browser
64+
page menu (`browser-session.tsx`) each mirror the OS menu the user already knows — clipboard
65+
banding (`Cut · Copy · Paste │ Select all`) is a convention every text field on their machine
66+
teaches them. These keep their native banding, and that is the *same* principle as the ordering
67+
rule above: mirror the surface the user already reads. The test is whether a real menu outside
68+
Sim taught them the grouping. Our own resource, row, and action menus have no such precedent —
69+
the toolbars they mirror are flat — so they take the single rule.
70+
71+
**Both sides of every rule must be guaranteed non-empty.** Write the separator's guard out of
72+
the *exact* render conditions of the items around it, never a looser approximation:
73+
74+
```tsx
75+
// ✗ Bad — `showLeave` alone, while the Leave item needs `showLeave && onLeave`.
76+
// A caller passing showLeave from a permission check with a conditional
77+
// onLeave renders a trailing rule under the last item.
78+
{hasActionsAbove && (showLeave || showDelete) && <DropdownMenuSeparator />}
79+
80+
// ✓ Good — each term is the item's own condition, verbatim
81+
const hasDestructiveSection = (showLeave && onLeave) || showDelete
82+
{hasActionsAboveDestructive && hasDestructiveSection && <DropdownMenuSeparator />}
83+
```
84+
85+
This is the failure that put a dangling rule at the bottom of the logs row menu, where two
86+
unconditional separators sat above conditional items.
87+
88+
**Do not add a prop to move a rule.** The shared workflow context menu grew
89+
`groupNonDestructiveActions` and `separateNavigationAction` for this; between them they moved one
90+
separator for one caller, four of six branches were unreachable, and `separateNavigationAction`
91+
had no observable effect anywhere in the repo. Both are gone. A menu that wants different
92+
grouping wants the standard grouping.
93+
2994
## Encode the order once
3095

3196
An order duplicated across surfaces is an order that will drift. Export **one** constant and sort by it — do not hand-maintain a matching literal per menu.

CLAUDE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@ Co-locate a `search-params.ts` per feature exporting the parser map (single sour
386386

387387
A list orders itself the way the user already reads the same things somewhere else. Resource menus (`+` attach, `@` mention, resource-tab `+`) mirror the **sidebar** top-down; a row or root **context menu** mirrors that surface's **toolbar**, left-to-right becoming top-to-bottom; tab strips mirror their nav. Platform-only entries (desktop Browser, Terminal) trail the shared set.
388388

389-
Encode the order in ONE exported constant and sort by it — never a hand-maintained literal per menu (`RESOURCE_MENU_ORDER` / `byResourceMenuOrder` in `home/components/mothership-view/components/resource-registry`). Render mixed item kinds in a single ordered pass; emitting all submenu-backed families and then all flat ones silently pins every submenu to the top no matter what the constant says. Divergence is allowed only for search ranking, user-controlled ordering, and recency. Full rule in `.claude/rules/sim-list-ordering.md`.
389+
Encode the order in ONE exported constant and sort by it — never a hand-maintained literal per menu (`RESOURCE_MENU_ORDER` / `byResourceMenuOrder` in `home/components/mothership-view/components/resource-registry`). Render mixed item kinds in a single ordered pass; emitting all submenu-backed families and then all flat ones silently pins every submenu to the top no matter what the constant says. Divergence is allowed only for search ranking, user-controlled ordering, and recency.
390+
391+
**Grouping**: at most ONE `DropdownMenuSeparator` per menu, fencing the consequential group — immediately before Delete/Leave/Close/Hide in almost every menu, and immediately after Retry/Cancel Run in the logs row menu, where those lead. No toolbar in the app renders a divider, so multi-band menus teach a taxonomy that exists on no other surface. Build each separator's guard from the EXACT render conditions of the items on both sides — a looser guard is what leaves a dangling rule when its group is conditional. Never add a prop to move a rule. Full rule in `.claude/rules/sim-list-ordering.md`.
390392

391393
## Styling
392394

apps/desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"type": "module",
1010
"main": "dist/main.cjs",
1111
"engines": {
12-
"bun": ">=1.2.13",
12+
"bun": ">=1.3.14",
1313
"node": ">=20.0.0"
1414
},
1515
"scripts": {

apps/docs/content/docs/en/cli/commands.mdx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,29 @@ sim configure [options]
113113
| `--unset <key...>` | No | Remove settings (endpoint, workspace, output). |
114114

115115
</CommandTable>
116+
117+
## Ask Sim and print the reply
118+
119+
```bash
120+
sim chat <message> [options]
121+
```
122+
123+
**Arguments**
124+
125+
<CommandTable>
126+
127+
| Argument | Required | Description |
128+
| --- | --- | --- |
129+
| `message` | Yes | What to ask Sim |
130+
131+
</CommandTable>
132+
133+
**Options**
134+
135+
<CommandTable>
136+
137+
| Option | Required | Description |
138+
| --- | --- | --- |
139+
| `-c, --conversation <id>` | No | Continue the conversation with this ID. |
140+
141+
</CommandTable>

apps/docs/content/docs/en/cli/reference.mdx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,34 @@ sim configure [options]
101101

102102
</CommandTable>
103103

104+
## sim chat
105+
106+
Ask Sim and print the reply
107+
108+
```bash
109+
sim chat <message> [options]
110+
```
111+
112+
**Arguments**
113+
114+
<CommandTable>
115+
116+
| Argument | Required | Description |
117+
| --- | --- | --- |
118+
| `message` | Yes | What to ask Sim |
119+
120+
</CommandTable>
121+
122+
**Options**
123+
124+
<CommandTable>
125+
126+
| Option | Required | Description |
127+
| --- | --- | --- |
128+
| `-c, --conversation <id>` | No | Continue the conversation with this ID. |
129+
130+
</CommandTable>
131+
104132
## sim profiles
105133

106134
Also spelled `sim profile`.

apps/docs/content/docs/en/platform/enterprise/custom-blocks.mdx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,15 @@ Pick which of the workflow's outputs consumers can use, and give each one a name
7474

7575
<Image src="/static/enterprise/custom-blocks-form.png" alt="Create block form filled in: Workspace and Workflow selectors, an uploaded icon, Name and Description fields, an expanded input with a placeholder, and two selected outputs each given a name" width={900} height={570} />
7676

77-
### 6. Save
77+
### 6. Choose whether runs are traced
78+
79+
**Trace runs in consumer logs** is off by default. Leave it off and your block stays a single step in every workflow that uses it: nothing about the run is recorded anywhere a consumer can reach.
80+
81+
Turn it on and the block's steps appear inside the trace of every workflow that runs it, org-wide. That means anyone who can read those workflows' logs sees your workflow's block names, inputs, outputs, and prompts — including people with no access to this workspace. It is the same information curated outputs and redacted errors otherwise keep on your side of the block, so turn it on when you want consumers to be able to debug your block themselves, and leave it off otherwise.
82+
83+
You can change this at any time; it applies to runs from that point on. Failures always return a reference id either way, so you can find a run in your own logs even with tracing off.
84+
85+
### 7. Save
7886

7987
Click **Save changes**. The block is published immediately and becomes available to everyone in your organization in the workflow editor's block toolbar.
8088

@@ -86,7 +94,7 @@ In the workflow editor, open the block toolbar. Published custom blocks appear u
8694

8795
<Image src="/static/enterprise/custom-blocks-toolbar.png" alt="Workflow editor block toolbar with a Custom Blocks section listing two published blocks below Core Blocks" width={400} height={476} />
8896

89-
Consumers don't need any access to the source workflow. The block runs on its own, using only the inputs provided, and returns only the outputs you exposed. Internal steps, models, and intermediate values of the source workflow are never visible.
97+
Consumers don't need any access to the source workflow. The block runs on its own, using only the inputs provided, and returns only the outputs you exposed. Its internal steps, models, and intermediate values stay hidden unless the block's publisher turned on **Trace runs in consumer logs**, in which case they appear under the block in the run's trace.
9098

9199
<Image src="/static/enterprise/custom-blocks-canvas.png" alt="A custom block connected to a Start block on the workflow canvas, with its query input filled in and the run output showing the returned fields" width={900} height={570} />
92100

@@ -96,7 +104,7 @@ Consumers don't need any access to the source workflow. The block runs on its ow
96104

97105
Open a block from **Settings → Enterprise → Custom blocks** to edit or delete it.
98106

99-
- **Editing** changes only the block's presentation and interface — name, description, icon, input placeholders, and exposed outputs. The source workflow can't be re-pointed.
107+
- **Editing** changes only the block's presentation, interface, and trace policy — name, description, icon, input placeholders, exposed outputs, and whether runs are traced in consumer logs. The source workflow can't be re-pointed.
100108
- **Changing what the block does** is done by editing and **redeploying the source workflow**. The block picks up the new deployment automatically; there's nothing to republish.
101109
- **Deleting** a block is permanent. Workflows already using it will have that block removed, so replace it before deleting if it's in active use.
102110

apps/docs/openapi-v2-knowledge.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3450,8 +3450,8 @@
34503450
},
34513451
"status": {
34523452
"type": "string",
3453-
"enum": ["active", "paused", "syncing", "error", "disabled"],
3454-
"description": "Current connector state."
3453+
"enum": ["active", "paused", "pending", "syncing", "error", "disabled"],
3454+
"description": "Current connector state. `pending` means a sync is queued but not yet running."
34553455
},
34563456
"lastSyncAt": {
34573457
"anyOf": [
@@ -3840,8 +3840,8 @@
38403840
},
38413841
"status": {
38423842
"type": "string",
3843-
"enum": ["active", "paused", "syncing", "error", "disabled"],
3844-
"description": "Current connector state."
3843+
"enum": ["active", "paused", "pending", "syncing", "error", "disabled"],
3844+
"description": "Current connector state. `pending` means a sync is queued but not yet running."
38453845
},
38463846
"lastSyncAt": {
38473847
"anyOf": [

apps/realtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"license": "Apache-2.0",
66
"type": "module",
77
"engines": {
8-
"bun": ">=1.2.13",
8+
"bun": ">=1.3.14",
99
"node": ">=20.0.0"
1010
},
1111
"scripts": {

apps/sim/app/api/cron/cleanup-stale-executions/route.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,9 @@ describe('stale execution cleanup deadline grace', () => {
396396
const response = await GET(createRequest())
397397

398398
expect(response.status).toBe(200)
399-
expect(dbChainMockFns.transaction).toHaveBeenCalledTimes(8)
400-
expect(dbChainMockFns.for).toHaveBeenCalledTimes(8)
399+
// Nine batched arms: the connector sync-log retention pass is the newest.
400+
expect(dbChainMockFns.transaction).toHaveBeenCalledTimes(9)
401+
expect(dbChainMockFns.for).toHaveBeenCalledTimes(9)
401402
for (const [strength, options] of dbChainMockFns.for.mock.calls) {
402403
expect(strength).toBe('update')
403404
expect(options).toEqual({ skipLocked: true })
@@ -469,7 +470,7 @@ describe('stale execution cleanup deadline grace', () => {
469470
const limits = dbChainMockFns.limit.mock.calls.map(([limit]) => limit)
470471
expect(limits.filter((limit) => limit === 100)).toHaveLength(20)
471472
expect(limits.filter((limit) => limit === 1000)).toHaveLength(30)
472-
expect(limits.filter((limit) => limit === 2000)).toHaveLength(11)
473+
expect(limits.filter((limit) => limit === 2000)).toHaveLength(12)
473474

474475
const workflowUpdates = dbChainMockFns.update.mock.calls.filter(
475476
([table]) => table === workflowExecutionLogs

0 commit comments

Comments
 (0)