From d69eb7228e920bce5c0fc566ca88f8e7398065e2 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Thu, 10 Sep 2026 13:54:42 -0700 Subject: [PATCH 01/25] feat(library): AI Coding Agents vs. AI Workflow Agents: What's the Difference? (#7736) * feat(library): AI Coding Agents vs. AI Workflow Agents: What's the Difference? * Pi Babysit: address PR #7736 feedback --------- Co-authored-by: Sim Pi Agent --- .../index.mdx | 103 ++++++++++++++++++ .../cover.jpg | Bin 0 -> 32333 bytes 2 files changed, 103 insertions(+) create mode 100644 apps/sim/content/library/ai-coding-agents-vs-ai-workflow-agents/index.mdx create mode 100644 apps/sim/public/library/ai-coding-agents-vs-ai-workflow-agents/cover.jpg diff --git a/apps/sim/content/library/ai-coding-agents-vs-ai-workflow-agents/index.mdx b/apps/sim/content/library/ai-coding-agents-vs-ai-workflow-agents/index.mdx new file mode 100644 index 00000000000..7bf5af022ac --- /dev/null +++ b/apps/sim/content/library/ai-coding-agents-vs-ai-workflow-agents/index.mdx @@ -0,0 +1,103 @@ +--- +slug: ai-coding-agents-vs-ai-workflow-agents +title: 'AI Coding Agents vs. AI Workflow Agents: What''s the Difference?' +description: 'Compare AI coding agents like Cursor, GitHub Copilot, Augment Code, and Devin with AI workflow agents like Sim, Zapier, Make, and n8n across context, task scope, integrations, setup, pricing, and oversight.' +date: 2026-09-10 +updated: 2026-09-10 +authors: + - andrew +readingTime: 7 +tags: [AI Agents, Coding Agents, Workflow Automation, Sim] +ogImage: /library/ai-coding-agents-vs-ai-workflow-agents/cover.jpg +canonical: https://www.sim.ai/library/ai-coding-agents-vs-ai-workflow-agents +draft: false +faq: + - q: "Can a coding agent replace a workflow agent?" + a: "A coding agent edits and tests software inside a codebase. Sim coordinates actions, data, approvals, and integrations across business systems. Choose a coding agent when the deliverable is code and a workflow agent when the deliverable is a completed business process." + - q: "Can a workflow agent write code?" + a: "A workflow agent can execute code as one step within a larger process. Sim places code beside model calls, conditions, integrations, and human approvals in the same graph. You can use custom logic without turning the entire workflow into a software project." + - q: "Which category has a bigger context window?" + a: "A context window measures how much information a model can process in one request. Coding agents emphasize repository context, while Sim draws context from connected files, tables, knowledge bases, and applications. Compare the information each agent can access rather than relying on token limits alone." + - q: "Do I need both types of agent?" + a: "Coding agents modify software, while workflow agents coordinate processes across systems. Sim can execute code within workflows and receive outputs produced by coding agents. You may need both when software changes must trigger or support wider business operations." +--- + +## TL;DR + +- AI coding agents write and modify code inside a codebase, while AI workflow agents orchestrate tasks and data across business systems. +- Cursor, GitHub Copilot, Augment Code, and Devin belong primarily to the coding-agent category. Sim, Zapier, Make, and n8n belong primarily to the workflow-agent category. +- Use the expected output as the test. Choose a coding agent when you need code changes, tests, or a pull request. Choose a workflow agent when you need actions coordinated across applications, APIs, and data stores. + +## Why these two categories keep getting conflated + +These tools are often grouped together because both use language models to plan actions, call tools, and complete multistep tasks. Product descriptions also use shared terms such as agents, automation, and orchestration, even when the tools operate on different objects and serve different jobs. Our guide to [agentic AI coding tools](https://www.sim.ai/library/agentic-ai-coding-tools-what-they-are-and-how-the-top-options-compare) examines the coding side of this distinction in more detail. + +[Microsoft's architecture framework](https://techcommunity.microsoft.com/blog/azurearchitectureblog/building-ai-agents-workflow-first-vs-code-first-vs-hybrid/4466788) provides a useful precedent. It separates workflow-first platforms from code-first frameworks, then identifies hybrid designs that combine visual orchestration with custom code. Hybrid products make labels especially unreliable because either category can borrow capabilities from the other. + +A useful comparison examines the context each agent receives, the systems it can act on, and the evidence you use to verify completion. Context, available actions, and completion evidence provide a more useful classification than interface or branding. + +## 1. Context window vs. context surface + +A context window measures how much text a model can process in one request, usually in tokens. A context surface covers the material an agent can search and retrieve before filling that window. The surface may include an indexed repository, documentation, commit history, and relationships between files. Retrieved excerpts still consume context-window space. + +Cursor expands its context surface by finding relevant code and letting developers reference repository materials. Its [official documentation](https://docs.cursor.com/context/%40-symbols/overview) describes tools for understanding a codebase, tracing how a repository fits together, and finding the right places to make a change. The agent retrieves relevant material instead of treating every file as equally important. + +Augment Code applies a similar retrieval model through its Context Engine. Augment's [Context Connectors documentation](https://docs.augmentcode.com/context-services/context-connectors/how-it-works) describes a pipeline that filters, chunks, embeds, stores, and semantically searches repository content. This describes a searchable context surface, not an unlimited context window. + +[Cognition describes Devin](https://www.cognition.ai/) as planning, writing, testing, and shipping code while working inside a codebase and its development tools. Cognition does not publish a context-window size on that overview, so compare documented repository coverage separately from token limits rather than inferring one measure from the other. + +## 2. Task scope: single repo vs. cross-system process + +A coding agent completes a task by changing a codebase and producing a verifiable software result. The endpoint may be a pull request, a resolved issue, or a passing test suite. For example, the [GitHub Copilot cloud agent](https://code.visualstudio.com/docs/copilot/copilot-cloud-agent) can take a GitHub issue, explore a repository, change multiple files, and run builds, tests, and checks in an isolated environment. + +A workflow agent completes a task when a business process reaches its intended state across connected systems. For example, an agent might classify a support request, update the customer record, and pause for approval before issuing a refund. The task ends when those actions finish or reach a defined exception path. This broader coordination is the focus of [AI agent orchestration](https://www.sim.ai/library/ai-agent-orchestration-frameworks-explained). + +The expected output provides the clearest distinction between the categories. Choose a coding agent when you need software work inside a repository. Choose a workflow agent when you need data and actions coordinated across applications, APIs, or internal services. + +## 3. Integration and action surface + +A coding agent's action surface centers on the development environment. [VS Code's Copilot cloud agent](https://code.visualstudio.com/docs/copilot/copilot-cloud-agent) can inspect a codebase, edit files, and run development checks in its own environment. The sources cited here do not document numerical tool-call limits for GitHub Copilot or Cursor, so this article does not compare those limits. + +A workflow agent's action surface spans external applications and APIs. [Sim's pricing page](https://www.sim.ai/pricing) describes access to more than 1,000 integrations. [Zapier publishes its app directory](https://zapier.com/apps), while [Make publishes its integration catalog](https://www.make.com/en/integrations). n8n provides both built-in connectors and a documented [Code node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code) for custom JavaScript or Python within a workflow. + +Catalog totals require careful interpretation. One integration may expose dozens of actions, such as creating a Salesforce record or sending a Slack message. A first-party block, app connector, and individual tool action therefore represent different units. Coding agents suit work performed through editors, repositories, terminals, and test runners. Workflow agents suit processes that must read or change data across several business systems. + +## 4. Setup time and deployment target + +Coding agents usually start inside a development environment. Cursor's [product documentation](https://docs.cursor.com/context/%40-symbols/overview) centers setup and use on understanding, editing, and reviewing a codebase with the developer's existing tools. The work required to prepare a coding agent depends on repository access, project instructions, dependencies, and development permissions. + +Devin uses a different operating model. [Cognition presents Devin](https://www.cognition.ai/) as an autonomous software engineer that works inside a team's codebase and tools. Evaluators should verify current access, repository permissions, and environment requirements instead of treating a product's launch conditions as a present limit. + +The workflow agents compared here use managed services, self-hosted services, or both. Zapier and Make provide web-based automation products through their [pricing](https://zapier.com/pricing) and [product](https://www.make.com/en/product) pages. n8n documents both [n8n Cloud and self-hosted deployment](https://docs.n8n.io/choose-how-to-use-n8n). Sim offers a hosted service and an Apache 2.0-licensed core alongside separately licensed enterprise features; its [self-hosting documentation](https://docs.sim.ai/platform/self-hosting) covers Docker and Kubernetes deployments. + +Fixed setup-time comparisons can mislead because the work varies with repository size, system credentials, and deployment choices. Compare the required starting environment instead. Coding agents need codebase access, while workflow agents need connections to the business systems they will operate. Teams considering deployment tradeoffs can also compare [open-source AI agent frameworks](https://www.sim.ai/library/best-open-source-ai-agent-frameworks). + +## 5. Pricing model + +The coding agents discussed here commonly combine developer access with usage limits or metering. [Cursor's official pricing page](https://cursor.com/pricing) lists a free Hobby plan, an Individual plan at $20 per month, a Teams plan at $40 per user per month, and custom Enterprise pricing. Because software pricing changes, readers should confirm current rates before comparing costs. Model choice and request volume can affect usage. + +Augment Code illustrates why message counts can misrepresent coding work. A short question and a multi-file refactor may each begin with one message but require very different amounts of computing. Augment's [official pricing announcement](https://www.augmentcode.com/blog/augment-codes-pricing-is-changing) explains its move from per-message billing to credits because tasks differ in scope, work, time, and cost. + +The workflow agents compared here meter different units associated with workflow activity. Vendors describe those units on their current pricing pages: [Zapier](https://zapier.com/pricing), [Make](https://www.make.com/en/pricing), [n8n](https://n8n.io/pricing/), and [Sim](https://docs.sim.ai/platform/costs). Make counts module actions as credits, n8n bases pricing on monthly workflow executions, and Sim uses credits for workflow usage. These units are vendor-specific and do not represent the same amount of work. Estimate costs by testing a representative workflow that includes expected loops, agent calls, and retries. + +## 6. Verification and human oversight + +Coding agents usually present code changes for developer review. Cursor's documentation emphasizes inspecting diffs and running checks, while [BugBot reviews pull requests](https://cursor.com/docs/bugbot) for bugs, security issues, and code-quality problems. Neither activity removes the developer's responsibility to verify acceptance criteria through review and tests. + +Workflow agents can place approval and evaluation steps inside the execution path. Sim provides separate Human in the Loop, Guardrails, and Evaluator blocks. The [Human in the Loop documentation](https://docs.sim.ai/workflows/blocks/human-in-the-loop) explains that the block pauses a run without a timeout until someone responds through the approval portal, API, or webhook. Sim's workflow definitions also support notifications to alert approvers. + +Each category places oversight at a different stage of execution. Cursor focuses review on code changes before merge. Sim can require approval while a cross-system workflow is still running, while Guardrails and Evaluator blocks support validation and scoring within the graph. For a broader production perspective, see [AI agent observability](https://www.sim.ai/library/ai-agent-observability). + +## Where the categories overlap + +The categories overlap when an agent crosses the boundary between codebase work and external orchestration. A coding agent may receive work through an issue, modify a repository, and hand the result to another process as a pull request. GitHub Copilot supports this pattern through [cloud agents that work on GitHub issues](https://code.visualstudio.com/docs/copilot/copilot-cloud-agent). Repository events can then trigger testing, review, or deployment workflows. + +A workflow agent can include code execution within a process whose final outcome spans other systems. Sim's Function block executes JavaScript without imports locally, while JavaScript with imports, Python, and shell code require a configured remote sandbox. These modes can run within a larger graph that also contains model reasoning and deterministic steps such as conditions or API calls. The code block serves one stage of a cross-system process rather than treating the repository change as the final output. + +The primary completion target still identifies the category. Coding agents usually finish with validated code or a pull request. Workflow agents finish when the broader business process reaches its defined outcome. + +## Choosing the right category for the job + +Choose according to the artifact you need to change. If the job ends with source files, tests, or a pull request, choose a coding agent. If success requires moving data and triggering actions across applications, APIs, or approval steps, choose a workflow agent. + +For mixed jobs, assign each tool the part it handles directly. A coding agent can modify a service and open a pull request, while a workflow agent can route that pull request, request approval, update a ticket, and notify an operator. Evaluate how the tools exchange work and report failures, including the permissions and interfaces required for the handoff. When coding and workflow agents handle adjacent stages of one process, evaluate their permissions, handoff interfaces, status reporting, and failure handling rather than treating them as substitutes. diff --git a/apps/sim/public/library/ai-coding-agents-vs-ai-workflow-agents/cover.jpg b/apps/sim/public/library/ai-coding-agents-vs-ai-workflow-agents/cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..21dd96f933707ca2765fbeeaeabe8c266e32389c GIT binary patch literal 32333 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 Date: Thu, 10 Sep 2026 14:00:17 -0700 Subject: [PATCH 02/25] fix(knowledge): skip verified empty Slack threads (#7734) * fix(knowledge): skip verified empty Slack threads * chore(knowledge): format Slack sync integration fixture --- apps/sim/connectors/slack/slack.test.ts | 60 +++++ apps/sim/connectors/slack/slack.ts | 30 ++- .../slack-empty-threads.integration.ts | 233 ++++++++++++++++++ 3 files changed, 312 insertions(+), 11 deletions(-) create mode 100644 apps/sim/lib/knowledge/__integration__/slack-empty-threads.integration.ts diff --git a/apps/sim/connectors/slack/slack.test.ts b/apps/sim/connectors/slack/slack.test.ts index 84a4f8ee54d..1bf8f9b18b4 100644 --- a/apps/sim/connectors/slack/slack.test.ts +++ b/apps/sim/connectors/slack/slack.test.ts @@ -410,6 +410,66 @@ describe('Slack thread indexing through provider APIs', () => { }) }) +describe('Slack threads without indexable text', () => { + beforeEach(() => { + pageSize = 1 + channels = [ + { + channel: GENERAL, + readers: ['alice'], + messages: [{ ...root(''), thread_ts: ROOT }], + replies: { [ROOT]: [{ ...root(''), thread_ts: ROOT }, reply('')] }, + }, + ] + }) + + it('explicitly skips a listed thread only after reading all its reply pages', async () => { + const listed = await listAll('alice') + expect(listed.documents).toHaveLength(1) + const document = await slackConnector.getDocument('alice', {}, id(GENERAL.id), listed.context) + expect(document).toMatchObject({ + externalId: listed.documents[0].externalId, + content: '', + contentDeferred: false, + skippedReason: 'Document contains no extractable text', + skippedExistingDisposition: 'replace', + metadata: { messageCount: 0, rootTs: ROOT, channelId: GENERAL.id, teamId: TEAM }, + }) + expect(calls.filter((call) => call.method === 'conversations.replies')).toHaveLength(2) + expect(calls.some((call) => call.method === 'chat.getPermalink')).toBe(false) + }) + + it('indexes a later reply edit even when the root and reply count have not changed', async () => { + const empty = await slackConnector.getDocument('alice', {}, id(GENERAL.id)) + channels[0].replies[ROOT][1] = reply('Orion has a launch date') + const document = await slackConnector.getDocument('alice', {}, id(GENERAL.id)) + expect(document?.externalId).toBe(empty?.externalId) + expect(document?.content).toContain('Orion has a launch date') + expect(document?.contentHash).not.toBe(empty?.contentHash) + expect(document?.skippedReason).toBeUndefined() + }) + + it('does not classify a missing root as verified empty content', async () => { + replacement = (call) => + call.method === 'conversations.replies' ? { ok: true, messages: [] } : undefined + expect(await slackConnector.getDocument('alice', {}, id(GENERAL.id))).toBeNull() + }) + + it.each([ + [{ ok: true, messages: [reply('')], is_limited: true }, 'only part'], + [{ ok: true, messages: [reply('')], has_more: true }, 'continuation cursor'], + [{ ok: false, error: 'missing_scope' }, 'missing_scope'], + [{ ok: true }, 'invalid message page'], + ])( + 'does not skip an empty thread when a later page is incomplete: %j', + async (response, error) => { + replacement = (call) => + call.method === 'conversations.replies' && call.params.has('cursor') ? response : undefined + await expect(slackConnector.getDocument('alice', {}, id(GENERAL.id))).rejects.toThrow(error) + } + ) +}) + describe('Slack incomplete and unsafe provider responses', () => { it('does not complete a member observation when channel access disappears between history pages', async () => { pageSize = 1 diff --git a/apps/sim/connectors/slack/slack.ts b/apps/sim/connectors/slack/slack.ts index 32d3128e181..0f99b9ed2a1 100644 --- a/apps/sim/connectors/slack/slack.ts +++ b/apps/sim/connectors/slack/slack.ts @@ -20,6 +20,7 @@ import { BoundedLines, CONNECTOR_TEXT_DOCUMENT_MAX_BYTES, ConnectorFileTooLargeError, + markSkipped, parseDefaultedUnlimitedSafeInteger, parseMultiValue, parseTagDate, @@ -693,22 +694,14 @@ async function getDocument( cursor = continuation } if (!exhausted) throw new Error(`Slack thread exceeds ${MAX_THREAD_PAGES} reply pages`) - if (!root || lines.count === 0) return null - const link = await slackApiGet('chat.getPermalink', accessToken, { - channel: channelId, - message_ts: rootTs, - }) - if (typeof link.permalink !== 'string' || !link.permalink.startsWith('https://')) { - throw new Error('Slack did not return a message permalink') - } - const content = lines.join() - return { + if (!root) return null + const content = lines.count > 0 ? lines.join() : '' + const document: ExternalDocument = { externalId, title: messageTitle(channel, root), content, contentDeferred: false, mimeType: 'text/plain', - sourceUrl: link.permalink, contentHash: `slack-content:v4:${createHash('sha256').update(content).digest('hex')}`, metadata: { channelName: channel.name, @@ -720,6 +713,21 @@ async function getDocument( lastActivity: new Date(Number(lastActivity) * 1000).toISOString(), }, } + /** Only a fully read thread can authoritatively replace previously indexed text with a skip. */ + if (lines.count === 0) { + return { + ...markSkipped(document, 'Document contains no extractable text'), + skippedExistingDisposition: 'replace', + } + } + const link = await slackApiGet('chat.getPermalink', accessToken, { + channel: channelId, + message_ts: rootTs, + }) + if (typeof link.permalink !== 'string' || !link.permalink.startsWith('https://')) { + throw new Error('Slack did not return a message permalink') + } + return { ...document, sourceUrl: link.permalink } } catch (error) { if ( error instanceof SlackApiError && diff --git a/apps/sim/lib/knowledge/__integration__/slack-empty-threads.integration.ts b/apps/sim/lib/knowledge/__integration__/slack-empty-threads.integration.ts new file mode 100644 index 00000000000..2ec84a824a7 --- /dev/null +++ b/apps/sim/lib/knowledge/__integration__/slack-empty-threads.integration.ts @@ -0,0 +1,233 @@ +/** Real sync jobs, PostgreSQL, storage, indexing and authorized search; Slack and embedding responses are synthetic. */ +import { mkdtempSync } from 'node:fs' +import { rm } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import path from 'node:path' +import { db } from '@sim/db' +import { + document, + embedding, + knowledgeConnector, + organization, + user, + workspace, +} from '@sim/db/schema' +import { generateId } from '@sim/utils/id' +import { and, eq, inArray } from 'drizzle-orm' +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' + +const fixture = vi.hoisted(() => ({ storageRoot: '', embeddingCalls: 0 })) +vi.mock('@/lib/uploads/core/setup.server', () => ({ + get UPLOAD_DIR_SERVER() { + return fixture.storageRoot + }, +})) +vi.mock('@/lib/embeddings', async () => ({ + ...(await import('@/lib/embeddings/client')), + assertKnowledgeEmbeddingCapacity: async () => {}, + embedKnowledge: async (texts: string[]) => { + fixture.embeddingCalls++ + return { + embeddings: texts.map(() => [1, ...Array(1535).fill(0)]), + totalTokens: texts.length, + billableTokens: 0, + isBYOK: true, + modelName: 'text-embedding-3-small', + pricingId: 'text-embedding-3-small', + } + }, +})) + +import { resolveBillingAttribution } from '@/lib/billing/core/billing-attribution' +import { + createKnowledgeAclFixtureIds, + seedKnowledgeAclFixture, +} from '@/lib/knowledge/__integration__/seed-source-access-fixture' +import { searchKnowledge } from '@/lib/knowledge/application/search' +import * as connectorTokens from '@/lib/knowledge/connectors/access-token' +import { executeConnectorSyncJob } from '@/background/knowledge-connector-sync' + +const TEAM = 'T0FIXTURE' +const CHANNEL = 'C0GENERAL' +const ROOT = '1700000100.000100' +const REPLY = '1700000200.000100' +const EXTERNAL_ID = `slack:v4:${TEAM}:${CHANNEL}:${ROOT}` +const EMPTY_REASON = 'Document contains no extractable text' + +describe('Slack empty threads through sync jobs, indexing and search', () => { + const ids = createKnowledgeAclFixtureIds() + const documentId = generateId() + let billing: Awaited> + let replyText = '' + let incomplete = false + let missingRoot = false + const channel = { id: CHANNEL, name: 'general', is_archived: false } + const root = () => ({ type: 'message', ts: ROOT, thread_ts: ROOT, text: '', reply_count: 1 }) + + async function providerFetch(input: string | URL | Request, init?: RequestInit) { + const url = new URL( + typeof input === 'string' ? input : input instanceof URL ? input.href : input.url + ) + expect(url.origin).toBe('https://slack.com') + expect(new Headers(init?.headers).get('Authorization')).toBe('Bearer fixture-slack-token') + const method = url.pathname.split('/').at(-1) + switch (method) { + case 'auth.test': + return Response.json({ ok: true, team_id: TEAM }) + case 'conversations.list': + return Response.json({ ok: true, channels: [channel] }) + case 'conversations.info': + return Response.json({ ok: true, channel }) + case 'conversations.history': + return Response.json({ ok: true, messages: [root()] }) + case 'conversations.replies': + if (missingRoot) return Response.json({ ok: true, messages: [] }) + if (!url.searchParams.has('cursor')) { + return Response.json({ + ok: true, + messages: [root()], + has_more: true, + response_metadata: { next_cursor: 'reply' }, + }) + } + return Response.json({ + ok: true, + messages: [{ type: 'message', ts: REPLY, thread_ts: ROOT, text: replyText }], + is_limited: incomplete, + }) + case 'chat.getPermalink': + return Response.json({ + ok: true, + permalink: `https://fixture.slack.com/archives/${CHANNEL}/p${ROOT.replace('.', '')}`, + }) + default: + throw new Error('Unexpected fixture Slack endpoint') + } + } + async function sync() { + return executeConnectorSyncJob({ + connectorId: ids.connectorId, + requestId: 'slack-empty-fixture', + fullSync: true, + billingAttribution: billing, + }) + } + async function row() { + const [stored] = await db + .select() + .from(document) + .where(and(eq(document.connectorId, ids.connectorId), eq(document.externalId, EXTERNAL_ID))) + expect(stored?.id).toBe(documentId) + return stored! + } + async function vectors() { + return db + .select({ content: embedding.content }) + .from(embedding) + .where(eq(embedding.documentId, documentId)) + } + async function search() { + const result = await searchKnowledge.execute({ + principal: { kind: 'session', userId: ids.aliceId, sessionId: 'slack-empty-fixture' }, + input: { + workspaceId: ids.workspaceId, + knowledgeBaseIds: [ids.knowledgeBaseId], + query: 'Orion', + searchMode: 'hybrid', + topK: 10, + }, + }) + return result.results.map((result) => result.documentId) + } + beforeAll(async () => { + fixture.storageRoot = mkdtempSync(path.join(tmpdir(), 'sim-slack-empty-')) + await seedKnowledgeAclFixture(ids) + billing = await resolveBillingAttribution({ + actorUserId: ids.aliceId, + workspaceId: ids.workspaceId, + }) + await db + .update(knowledgeConnector) + .set({ + connectorType: 'slack', + sourceConfig: { channel: CHANNEL, maxMessages: 0 }, + accessMode: 'workspace', + status: 'active', + syncLockToken: null, + }) + .where(eq(knowledgeConnector.id, ids.connectorId)) + vi.spyOn(connectorTokens, 'resolveConnectorAccessToken').mockResolvedValue({ + accessToken: 'fixture-slack-token', + }) + vi.stubGlobal('fetch', providerFetch) + await db.insert(document).values({ + id: documentId, + knowledgeBaseId: ids.knowledgeBaseId, + connectorId: ids.connectorId, + externalId: EXTERNAL_ID, + filename: 'Thread.txt', + mimeType: 'text/plain', + fileUrl: '', + fileSize: 0, + processingStatus: 'failed', + processingError: 'Synthetic previous source failure', + }) + }) + afterAll(async () => { + await db.delete(workspace).where(eq(workspace.id, ids.workspaceId)) + await db.delete(organization).where(eq(organization.id, ids.organizationId)) + await db.delete(user).where(inArray(user.id, [ids.aliceId, ids.bobId])) + await rm(fixture.storageRoot, { recursive: true, force: true }) + vi.restoreAllMocks() + vi.unstubAllGlobals() + await db.$client.end() + }) + + it('completes empty-thread syncs, recovers reply edits and removes stale searchable text', async () => { + expect(await sync()).toMatchObject({ + outcome: 'completed', + docsFailed: 0, + docsSkipped: 1, + processingDispatch: { requested: 0, failed: 0 }, + }) + expect(await row()).toMatchObject({ + processingStatus: 'failed', + processingError: EMPTY_REASON, + storageKey: null, + }) + expect(await vectors()).toEqual([]) + expect(fixture.embeddingCalls).toBe(0) + expect(await sync()).toMatchObject({ outcome: 'completed', docsFailed: 0 }) + expect(fixture.embeddingCalls).toBe(0) + + replyText = 'Orion launch is scheduled for Friday.' + expect(await sync()).toMatchObject({ outcome: 'completed', docsFailed: 0, docsUpdated: 1 }) + expect(await row()).toMatchObject({ processingStatus: 'completed', processingError: null }) + expect((await vectors()).map((row) => row.content).join(' ')).toContain(replyText) + expect(await search()).toContain(documentId) + const embedded = fixture.embeddingCalls + expect(await sync()).toMatchObject({ outcome: 'completed', docsUnchanged: 1 }) + expect(fixture.embeddingCalls).toBe(embedded) + + replyText = '' + expect(await sync()).toMatchObject({ outcome: 'completed', docsFailed: 0, docsSkipped: 1 }) + expect(await row()).toMatchObject({ processingError: EMPTY_REASON, storageKey: null }) + expect(await vectors()).toEqual([]) + expect(fixture.embeddingCalls).toBe(embedded) + expect(await search()).not.toContain(documentId) + + replyText = 'Orion launch moved to Monday.' + expect(await sync()).toMatchObject({ outcome: 'completed', docsUpdated: 1 }) + expect(await search()).toContain(documentId) + const restored = await vectors() + incomplete = true + replyText = '' + await expect(sync()).rejects.toThrow('1 source failures') + expect(await vectors()).toEqual(restored) + expect((await row()).storageKey).not.toBeNull() + incomplete = false + missingRoot = true + await expect(sync()).rejects.toThrow('1 source failures') + expect(await vectors()).toEqual(restored) + }, 60000) +}) From 2ac7faadd43fa43f8f816b2c8f4127891d5b5449 Mon Sep 17 00:00:00 2001 From: Waleed Date: Thu, 10 Sep 2026 15:25:01 -0700 Subject: [PATCH 03/25] fix(knowledge): stop connector sync failures on download-restricted Drive files and macro-only Confluence pages (#7739) * fix(knowledge): stop connector sync failures on download-restricted Drive files and macro-only Confluence pages * fix(knowledge): drop raw error message from hydration failure logs --- .../connectors/confluence/confluence.test.ts | 106 ++++++++++++++++- apps/sim/connectors/confluence/confluence.ts | 110 +++++++++++++++--- .../google-drive/google-drive-errors.ts | 13 ++- .../google-drive/google-drive.test.ts | 75 +++++++++++- .../connectors/google-drive/google-drive.ts | 33 +++++- apps/sim/connectors/slack/slack.test.ts | 25 ++++ apps/sim/connectors/slack/slack.ts | 80 +++++++++++-- .../organization-search-overview.test.ts | 35 ++++++ .../organization-search-overview.ts | 8 +- .../connectors/sync-content-pass.test.ts | 4 +- 10 files changed, 456 insertions(+), 33 deletions(-) diff --git a/apps/sim/connectors/confluence/confluence.test.ts b/apps/sim/connectors/confluence/confluence.test.ts index d1e5b0b7945..f4c3601b9a9 100644 --- a/apps/sim/connectors/confluence/confluence.test.ts +++ b/apps/sim/connectors/confluence/confluence.test.ts @@ -10,7 +10,9 @@ import { buildLastModifiedClause, confluenceConnector, confluenceStorageToPlainText, + DYNAMIC_CONTENT_SKIP_REASON, escapeCql, + extractConfluenceStorageText, isCurrentContent, preserveConfluenceCallouts, readIncludedLabels, @@ -770,6 +772,77 @@ describe('confluenceStorageToPlainText', () => { expect(confluenceStorageToPlainText(storage)).toBe('Public body') }) + it('keeps text authored inside legacy section and column layouts', () => { + const storage = + '' + + '50%' + + '

Linux Patching

Run the playbook.

' + + '
' + + '

Second column

' + + '
' + + expect(confluenceStorageToPlainText(storage)).toBe( + 'Linux Patching Run the playbook. Second column' + ) + }) + + it('keeps page properties tables, table-macro bodies, and status labels', () => { + const storage = + '' + + '
OwnerPlatform team
' + + '
' + + 'Name' + + '
Filtered row
' + + '
' + + '

State: Green' + + 'Approved

' + + expect(confluenceStorageToPlainText(storage)).toBe( + 'Owner Platform team Filtered row State: Approved' + ) + }) + + it('keeps new-editor panel and decision text while dropping app extensions', () => { + const storage = + '' + + 'custom' + + '

Rotate the key quarterly.

' + + '

Rotate the key quarterly.

' + + '' + + 'abc' + + 'DECIDED' + + 'Use Vault' + + '' + + 'remote' + + '

Rendered by an app

' + + expect(confluenceStorageToPlainText(storage)).toBe( + '[CALLOUT] Rotate the key quarterly. Use Vault' + ) + }) + + it('drops template placeholders and task bookkeeping but keeps task text intact', () => { + const storage = + '

Type your summary here

' + + '1u' + + 'incompleteShip it' + + '

Unbelievable

' + + expect(confluenceStorageToPlainText(storage)).toBe('Ship it Unbelievable') + }) + + it('reports whether dynamic content was removed', () => { + expect(extractConfluenceStorageText('

Local

')).toEqual({ + text: 'Local', + droppedDynamicContent: false, + }) + expect( + extractConfluenceStorageText( + '1' + ) + ).toEqual({ text: '', droppedDynamicContent: true }) + }) + it.each(['expand', 'excerpt', 'noformat'])( 'retains the authored content of the %s macro', (name) => { @@ -902,7 +975,36 @@ describe('Confluence permission-scoped content', () => { cloudId: 'cloud-1', mirrorsSourceAcls: true, }) - ).resolves.toMatchObject({ content: '', skippedExistingDisposition: 'replace' }) + ).resolves.toMatchObject({ + content: '', + skippedReason: DYNAMIC_CONTENT_SKIP_REASON, + skippedExistingDisposition: 'replace', + }) + }) + + it('names dynamic-only hub pages distinctly from genuinely empty ones', async () => { + vi.mocked(fetch).mockResolvedValueOnce( + new Response( + JSON.stringify({ + id: 'hub', + version: { number: 2 }, + body: { + storage: { + value: + '' + + 'project = X', + }, + }, + }) + ) + ) + const document = await confluenceConnector.getDocument('token', config, 'hub', { + cloudId: 'cloud-1', + perMemberListing: true, + memberId: 'member-1', + }) + expect(document?.skippedReason).toBe(DYNAMIC_CONTENT_SKIP_REASON) + expect(document?.skippedRetryPolicy).toBe('source-change') }) it('keeps skipped pages retryable when no usable source version is available', async () => { @@ -1015,7 +1117,7 @@ describe('Confluence permission-scoped content', () => { ) const expectedHash = 'mirrorsSourceAcls' in mode || 'perMemberListing' in mode - ? 'confluence:storage-local-body-v1:shared-page:1' + ? 'confluence:storage-local-body-v2:shared-page:1' : 'confluence:view-callouts:shared-page:1' expect(v2.documents[0].contentHash).toBe(expectedHash) diff --git a/apps/sim/connectors/confluence/confluence.ts b/apps/sim/connectors/confluence/confluence.ts index 1b4bb94e446..87986332c5e 100644 --- a/apps/sim/connectors/confluence/confluence.ts +++ b/apps/sim/connectors/confluence/confluence.ts @@ -93,6 +93,7 @@ const INLINE_FORMATTING_TAGS = new Set([ 'var', 'samp', 'time', + 'ac:inline-comment-marker', ]) /** @@ -204,33 +205,98 @@ export function preserveConfluenceCallouts(html: string): string { } const STORAGE_MACRO_SELECTOR = 'ac\\:structured-macro, ac\\:macro' +const ADF_NODE_SELECTOR = 'ac\\:adf-node' +/** Callout macros whose body is prefixed with a semantic label, as on the view path. */ +const LOCAL_CALLOUT_MACROS = new Set(['info', 'note', 'warning', 'tip', 'panel']) +/** + * Macros whose text is authored on the page itself: callouts, expand/excerpt/code + * bodies, legacy `section`/`column` layouts (which wrap the entire body of pages + * built in the old editor), Page Properties (`details`), table-wrapping macros, + * and `status` lozenges. Everything else either resolves another resource + * (include, jira, children, page tree, label reports) or is an app macro, and + * may render differently for each reader. + */ const LOCAL_STORAGE_MACROS = new Set([ - 'info', - 'note', - 'warning', - 'tip', - 'panel', + ...LOCAL_CALLOUT_MACROS, 'expand', 'excerpt', 'code', 'noformat', + 'section', + 'column', + 'details', + 'toc-zone', + 'chart', + 'table-filter', + 'table-chart', + 'table-pivot', + 'table-transformer', + 'table-excerpt', + 'table-plus', + 'status', ]) +/** New-editor nodes stored as ADF whose content is authored on the page. */ +const LOCAL_ADF_NODE_TYPES = new Set(['panel', 'decision-list', 'decision-item']) +/** ADF nodes rendered by a Forge or Connect app; their output is resolved elsewhere. */ +const APP_ADF_NODE_TYPES = new Set(['extension', 'bodiedExtension', 'inlineExtension']) +/** Storage-format bookkeeping that is never page prose. */ +const STORAGE_NOISE_SELECTOR = [ + 'ac\\:parameter', + 'ac\\:default-parameter', + 'ac\\:adf-attribute', + 'ac\\:adf-fallback', + 'ac\\:placeholder', + 'ac\\:task-id', + 'ac\\:task-uuid', + 'ac\\:task-status', + 'script', + 'style', +].join(', ') + +/** Recorded when a scoped page holds nothing but content resolved from elsewhere. */ +export const DYNAMIC_CONTENT_SKIP_REASON = + 'Page only contains dynamic content (child lists, includes, or app macros) that Search cannot index' + +export interface ConfluenceStorageText { + text: string + /** True when at least one non-local macro or app node was removed. */ + droppedDynamicContent: boolean +} /** * Search authorizes the containing page, not content expanded from another * resource. Read authored storage text and known local macro bodies only; * inclusion and third-party macros may render differently for each reader. */ -export function confluenceStorageToPlainText(storage: string): string { +export function extractConfluenceStorageText(storage: string): ConfluenceStorageText { const $ = cheerio.load( storage, { xml: { xmlMode: false, recognizeCDATA: true, recognizeSelfClosing: true } }, false ) - $('ac\\:adf-extension').remove() + let droppedDynamicContent = false + + for (const element of $(ADF_NODE_SELECTOR).toArray().reverse()) { + const node = $(element) + const type = node.attr('type') ?? '' + if (!LOCAL_ADF_NODE_TYPES.has(type)) { + if (APP_ADF_NODE_TYPES.has(type)) droppedDynamicContent = true + node.remove() + continue + } + const panelType = node.children('ac\\:adf-attribute[key="panel-type"]').text().trim() + node.children('ac\\:adf-attribute, ac\\:adf-fallback').remove() + const body = extractBlockJoinedText($, node) + const label = + type === 'panel' + ? (CALLOUT_LABELS[panelType === 'info' ? 'information' : panelType] ?? '[CALLOUT]') + : '' + node.replaceWith($('

').text([label, body].filter(Boolean).join(' '))) + } $(STORAGE_MACRO_SELECTOR).each((_, element) => { if (!LOCAL_STORAGE_MACROS.has($(element).attr('ac:name') ?? '')) { + droppedDynamicContent = true $(element).remove() } }) @@ -248,13 +314,23 @@ export function confluenceStorageToPlainText(storage: string): string { ? title ? `[CALLOUT: ${title}]` : '[CALLOUT]' - : CALLOUT_LABELS[name === 'info' ? 'information' : name] + : LOCAL_CALLOUT_MACROS.has(name) + ? CALLOUT_LABELS[name === 'info' ? 'information' : name] + : '' const text = [label, name === 'panel' ? '' : title, body].filter(Boolean).join(' ') macro.replaceWith($('

').text(text)) } - $('ac\\:parameter, ac\\:default-parameter, script, style').remove() - return extractBlockJoinedText($, $.root()).replace(/\s+/g, ' ').trim() + $(STORAGE_NOISE_SELECTOR).remove() + return { + text: extractBlockJoinedText($, $.root()).replace(/\s+/g, ' ').trim(), + droppedDynamicContent, + } +} + +/** Plain text of a storage-format body; see {@link extractConfluenceStorageText}. */ +export function confluenceStorageToPlainText(storage: string): string { + return extractConfluenceStorageText(storage).text } function usesPermissionScopedContent(syncContext?: Record): boolean { @@ -313,7 +389,7 @@ export function readIncludedLabels(page: Record): string[] { * ordinary knowledge bases retain their existing rendered representation. */ const CONTENT_REPRESENTATION = 'view-callouts' -const SCOPED_CONTENT_REPRESENTATION = 'storage-local-body-v1' +const SCOPED_CONTENT_REPRESENTATION = 'storage-local-body-v2' /** * Produces a canonical metadata stub with a deterministic contentHash that @@ -690,9 +766,8 @@ export const confluenceConnector: ConnectorConfig = { throw new Error(`Confluence content is missing its ${bodyFormat} body`) } const rawContent = representation.value - const plainText = scopedContent - ? confluenceStorageToPlainText(rawContent) - : htmlToPlainText(preserveConfluenceCallouts(rawContent)) + const scoped = scopedContent ? extractConfluenceStorageText(rawContent) : null + const plainText = scoped ? scoped.text : htmlToPlainText(preserveConfluenceCallouts(rawContent)) const links = page._links as Record | undefined const stub = pageToStub( @@ -707,7 +782,12 @@ export const confluenceConnector: ConnectorConfig = { if (!plainText.trim()) { return { - ...markSkipped(stub, 'Document contains no extractable text'), + ...markSkipped( + stub, + scoped?.droppedDynamicContent + ? DYNAMIC_CONTENT_SKIP_REASON + : 'Document contains no extractable text' + ), skippedExistingDisposition: 'replace', } } diff --git a/apps/sim/connectors/google-drive/google-drive-errors.ts b/apps/sim/connectors/google-drive/google-drive-errors.ts index b57cd059b27..db9c993b5e5 100644 --- a/apps/sim/connectors/google-drive/google-drive-errors.ts +++ b/apps/sim/connectors/google-drive/google-drive-errors.ts @@ -20,7 +20,18 @@ const PERMISSION_REASONS = new Set([ 'insufficientFilePermissions', 'teamDriveMembershipRequired', ]) -const POLICY_REASONS = new Set(['domainPolicy', 'download_restricted_for_revision']) +/** + * Owner- or admin-imposed restrictions on an otherwise readable file. The + * credential is valid, so these are not authorization failures; `cannotExportFile` + * and `cannotDownloadFile` are what Drive returns when the owner disabled + * download, print, and copy for viewers. + */ +const POLICY_REASONS = new Set([ + 'domainPolicy', + 'download_restricted_for_revision', + 'cannotDownloadFile', + 'cannotExportFile', +]) const UNSUPPORTED_EXPORT_REASONS = new Set(['fileNotDownloadable', 'fileNotExportable']) const QUOTA_REASONS = new Set(['dailyLimitExceeded', 'quotaExceeded']) const RATE_LIMIT_REASONS = new Set([ diff --git a/apps/sim/connectors/google-drive/google-drive.test.ts b/apps/sim/connectors/google-drive/google-drive.test.ts index f538e5b81bd..06444b02cf4 100644 --- a/apps/sim/connectors/google-drive/google-drive.test.ts +++ b/apps/sim/connectors/google-drive/google-drive.test.ts @@ -41,7 +41,10 @@ afterEach(() => { vi.unstubAllGlobals() }) -import { googleDriveConnector } from '@/connectors/google-drive/google-drive' +import { + DOWNLOAD_RESTRICTED_SKIP_REASON, + googleDriveConnector, +} from '@/connectors/google-drive/google-drive' import { GoogleDriveApiError, readGoogleDriveApiError, @@ -458,6 +461,8 @@ describe('Google Drive API error parsing', () => { ['insufficientFilePermissions', 'permission'], ['appNotAuthorizedToFile', 'permission'], ['domainPolicy', 'policy'], + ['cannotDownloadFile', 'policy'], + ['cannotExportFile', 'policy'], ['fileNotExportable', 'unsupported_export'], ['dailyLimitExceeded', 'quota'], ['rateLimitExceeded', 'transient'], @@ -564,6 +569,72 @@ describe('Google Drive API error parsing', () => { }) }) +describe('Google Drive download-restricted files', () => { + beforeEach(() => { + vi.clearAllMocks() + vi.stubGlobal('fetch', mockFetch) + }) + + const restricted = () => fileMetadata({ capabilities: { canDownload: false } }) + + it('always asks Drive whether the file can be downloaded', async () => { + mockFetch.mockResolvedValueOnce(jsonResponse({ files: [] })) + await googleDriveConnector.listDocuments('token', {}, undefined, {}) + + const fields = decodeURIComponent(String(mockFetch.mock.calls[0][0])) + expect(fields).toContain('capabilities(canDownload)') + expect(fields).not.toContain('permissions(') + }) + + it.each([ + ['a workspace crawl', {}], + ['a per-member listing', { perMemberListing: true }], + ])('skips a restricted file at listing time in %s', async (_label, syncContext) => { + mockFetch.mockResolvedValueOnce(jsonResponse({ files: [restricted()] })) + const page = await googleDriveConnector.listDocuments('token', {}, undefined, syncContext) + + expect(page.documents).toHaveLength(1) + expect(page.documents[0].skippedReason).toBe(DOWNLOAD_RESTRICTED_SKIP_REASON) + expect(mockFetch).toHaveBeenCalledTimes(1) + }) + + it('lists a downloadable file as an ordinary deferred stub', async () => { + mockFetch.mockResolvedValueOnce( + jsonResponse({ files: [fileMetadata({ capabilities: { canDownload: true } })] }) + ) + const page = await googleDriveConnector.listDocuments('token', {}, undefined, {}) + + expect(page.documents[0].skippedReason).toBeUndefined() + expect(page.documents[0].contentDeferred).toBe(true) + }) + + it('skips hydration without calling export when metadata says the file is restricted', async () => { + mockFetch.mockResolvedValueOnce(jsonResponse(restricted())) + const document = await googleDriveConnector.getDocument('token', {}, FILE_ID) + + expect(document?.skippedReason).toBe(DOWNLOAD_RESTRICTED_SKIP_REASON) + expect(document?.contentDeferred).toBe(false) + expect(mockFetch).toHaveBeenCalledTimes(1) + }) + + it('reports a restricted file from the change feed as a skipped upsert', async () => { + mockFetch.mockResolvedValueOnce( + jsonResponse({ + changes: [{ changeType: 'file', fileId: FILE_ID, file: restricted() }], + newStartPageToken: '2', + }) + ) + const page = await googleDriveConnector.listChanges?.('token', {}, '1', {}) + + expect(page?.changes).toHaveLength(1) + const change = page?.changes[0] + expect(change?.kind).toBe('upsert') + if (change?.kind === 'upsert') { + expect(change.document.skippedReason).toBe(DOWNLOAD_RESTRICTED_SKIP_REASON) + } + }) +}) + describe('Google Drive metadata hydration', () => { beforeEach(() => { vi.clearAllMocks() @@ -606,6 +677,8 @@ describe('Google Drive export failures', () => { 403, ], ['domainPolicy', 'The domain administrators have disabled Drive apps.', 403], + ['cannotExportFile', 'This file cannot be exported by the user.', 403], + ['cannotDownloadFile', 'This file cannot be downloaded by the user.', 403], ['fileNotExportable', 'This file cannot be exported.', 403], ])( 'propagates recoverable %s failures instead of persisting a sticky same-hash skip', diff --git a/apps/sim/connectors/google-drive/google-drive.ts b/apps/sim/connectors/google-drive/google-drive.ts index fdca1d94b87..88d9413f5a4 100644 --- a/apps/sim/connectors/google-drive/google-drive.ts +++ b/apps/sim/connectors/google-drive/google-drive.ts @@ -73,7 +73,21 @@ const SHORTCUT_FETCH_CONCURRENCY = 8 const DRIVE_METADATA_MAX_BYTES = 1024 * 1024 const DRIVE_PAGE_MAX_BYTES = 16 * 1024 * 1024 const DRIVE_FILE_FIELDS = - 'id,name,mimeType,modifiedTime,createdTime,webViewLink,owners,size,starred,trashed,parents,shortcutDetails(targetId,targetMimeType,targetResourceKey)' + 'id,name,mimeType,modifiedTime,createdTime,webViewLink,owners,size,starred,trashed,parents,shortcutDetails(targetId,targetMimeType,targetResourceKey),capabilities(canDownload)' + +/** + * Recorded on a listed file whose owner disabled download, print, and copy for + * viewers. Drive rejects both `files.export` and `files.get?alt=media` for such a + * file (`cannotExportFile` / `cannotDownloadFile`), so the crawl skips the fetch + * and surfaces the restriction instead of failing hydration on every sync. + */ +export const DOWNLOAD_RESTRICTED_SKIP_REASON = + 'The file owner has disabled downloading for viewers, so its content cannot be indexed' + +/** True when the file's metadata says the acting credential cannot read its bytes. */ +function isDownloadRestricted(file: DriveFile): boolean { + return file.capabilities?.canDownload === false +} const FOLDER_MIME_TYPE = 'application/vnd.google-apps.folder' @@ -427,6 +441,13 @@ function driveChangeToExternal( if (change.removed || !file || !isFileInScope(file, sourceConfig)) { return { kind: 'removed', externalId } } + if (isDownloadRestricted(file)) { + return { + kind: 'upsert', + externalId, + document: markSkipped(fileToStub(file), DOWNLOAD_RESTRICTED_SKIP_REASON), + } + } return { kind: 'upsert', externalId, @@ -731,7 +752,7 @@ async function readDriveFile( resourceKey?: string, permissions = false ): Promise { - const fields = `${DRIVE_FILE_FIELDS}${permissions ? `,permissions(${DRIVE_PERMISSION_FIELDS}),capabilities(canDownload)` : ''}` + const fields = `${DRIVE_FILE_FIELDS}${permissions ? `,permissions(${DRIVE_PERMISSION_FIELDS})` : ''}` const response = await fetchGoogleDriveWithRetry( `https://www.googleapis.com/drive/v3/files/${encodeURIComponent(fileId)}?fields=${encodeURIComponent(fields)}&supportsAllDrives=true`, { method: 'GET', headers: driveRequestHeaders(accessToken, fileId, resourceKey) } @@ -860,6 +881,8 @@ async function listedFileToDocument( } const contentFile = target ?? file if (!matchesFileType((sourceConfig.fileType as string) || 'all', contentFile)) return null + if (isDownloadRestricted(contentFile)) + return markSkipped(fileToStub(file, acl, target), DOWNLOAD_RESTRICTED_SKIP_REASON) return stubOrSkipBySize( fileToStub(file, acl, target), Number(contentFile.size) || undefined, @@ -1069,7 +1092,7 @@ const listGoogleDriveDocuments: ConnectorConfig['listDocuments'] = async ( * crawl would pull a permission array per file and discard it. */ fields: `kind,nextPageToken,incompleteSearch,files(${DRIVE_FILE_FIELDS}${ - aclContext ? `,permissions(${DRIVE_PERMISSION_FIELDS}),capabilities(canDownload)` : '' + aclContext ? `,permissions(${DRIVE_PERMISSION_FIELDS})` : '' })`, supportsAllDrives: 'true', includeItemsFromAllDrives: 'true', @@ -1252,6 +1275,10 @@ export const googleDriveConnector: ConnectorConfig = { } } + if (isDownloadRestricted(contentFile)) { + return markSkipped(stub, DOWNLOAD_RESTRICTED_SKIP_REASON) + } + try { const payload = await fetchFilePayload(accessToken, contentFile, resourceKey) if (!payload.content.trim() && !payload.sourceFile?.bytes.length) { diff --git a/apps/sim/connectors/slack/slack.test.ts b/apps/sim/connectors/slack/slack.test.ts index 1bf8f9b18b4..3353e691137 100644 --- a/apps/sim/connectors/slack/slack.test.ts +++ b/apps/sim/connectors/slack/slack.test.ts @@ -550,6 +550,31 @@ describe('Slack incomplete and unsafe provider responses', () => { } ) + it.each([ + { code: 'ratelimited', status: 429, category: 'rate_limit' }, + { code: 'token_revoked', status: 401, category: 'authorization' }, + { code: 'missing_scope', status: 403, category: 'authorization' }, + { code: 'internal_error', status: 503, category: 'provider_unavailable' }, + { code: 'invalid_arguments', status: 400, category: 'request_rejected' }, + ])('classifies the $code envelope as HTTP $status $category', async ({ code, ...expected }) => { + failure = (call) => + call.method === 'conversations.replies' ? { ok: false, error: code } : undefined + await expect(slackConnector.getDocument('alice', {}, id(GENERAL.id))).rejects.toMatchObject({ + name: 'SlackApiError', + code, + ...expected, + }) + }) + + it('keeps the HTTP status of a non-OK response for failure classification', async () => { + fetchMock.mockImplementationOnce(async () => new Response('forbidden', { status: 403 })) + await expect(slackConnector.getDocument('alice', {}, id(GENERAL.id))).rejects.toMatchObject({ + name: 'ConnectorSourceError', + status: 403, + message: expect.stringMatching(/^Slack [a-z.]+ failed with HTTP 403$/), + }) + }) + it('propagates Slack envelope throttling so the sync scheduler can cool down', async () => { failure = (call) => call.method === 'conversations.replies' ? { ok: false, error: 'ratelimited' } : undefined diff --git a/apps/sim/connectors/slack/slack.ts b/apps/sim/connectors/slack/slack.ts index 0f99b9ed2a1..22c2ace4b29 100644 --- a/apps/sim/connectors/slack/slack.ts +++ b/apps/sim/connectors/slack/slack.ts @@ -15,6 +15,10 @@ import { readSlackConversationSetting as readConversationSetting, } from '@/connectors/slack/config' import { DEFAULT_MAX_MESSAGES, slackConnectorMeta } from '@/connectors/slack/meta' +import { + ConnectorSourceError, + type ConnectorSourceFailureCategory, +} from '@/connectors/source-error' import type { ConnectorConfig, ExternalDocument, ExternalDocumentList } from '@/connectors/types' import { BoundedLines, @@ -95,16 +99,70 @@ interface SlackListingCursor { scanned: number } +interface SlackCodeClassification { + /** The HTTP status Slack would have used had it not answered 200 with an error envelope. */ + status: number + category: ConnectorSourceFailureCategory +} + +/** + * Slack answers HTTP 200 with `ok: false` and a machine-readable code. Mapping + * the known codes onto the shared failure categories lets the sync engine and + * the stored document error tell a revoked token from a missing thread from a + * throttle, instead of every envelope error reading as an unknown failure. + */ +const SLACK_CODE_CLASSIFICATIONS: ReadonlyArray<[ReadonlySet, SlackCodeClassification]> = [ + [new Set(['ratelimited']), { status: 429, category: 'rate_limit' }], + [ + new Set(['invalid_auth', 'token_revoked', 'token_expired', 'account_inactive', 'not_authed']), + { status: 401, category: 'authorization' }, + ], + [ + new Set(['missing_scope', 'access_denied', 'restricted_action', 'ekm_access_denied']), + { status: 403, category: 'authorization' }, + ], + [ + new Set([ + 'channel_not_found', + 'not_in_channel', + 'channel_is_limited_access', + 'thread_not_found', + 'message_not_found', + ]), + { status: 404, category: 'source_unavailable' }, + ], + [ + new Set(['service_unavailable', 'internal_error', 'fatal_error', 'request_timeout']), + { status: 503, category: 'provider_unavailable' }, + ], +] + +/** Unknown codes are treated as a rejected request; the status alone drives the diagnostic. */ +const UNCLASSIFIED_SLACK_CODE: SlackCodeClassification = { + status: 400, + category: 'request_rejected', +} + +function classifySlackCode(code: string): SlackCodeClassification { + for (const [codes, classification] of SLACK_CODE_CLASSIFICATIONS) { + if (codes.has(code)) return classification + } + return UNCLASSIFIED_SLACK_CODE +} + /** Slack's HTTP-200 errors still retain their machine-readable provider code. */ -class SlackApiError extends Error { +class SlackApiError extends ConnectorSourceError { + readonly code: string + readonly method: string + readonly headers?: Headers readonly rateLimited: boolean - constructor( - readonly code: string, - readonly method: string, - readonly headers?: Headers - ) { - super(`Slack ${method} failed: ${code}`) + constructor(code: string, method: string, headers?: Headers) { + const { status, category } = classifySlackCode(code) + super(`Slack ${method} failed: ${code}`, status, category) this.name = 'SlackApiError' + this.code = code + this.method = method + this.headers = headers this.rateLimited = code === 'ratelimited' } } @@ -120,7 +178,13 @@ async function slackApiGet( { headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json' } }, retryOptions ) - if (!response.ok) throw new Error(`Slack ${method} failed with HTTP ${response.status}`) + /** Retries are exhausted by now; the status must survive so the failure can be classified. */ + if (!response.ok) { + throw new ConnectorSourceError( + `Slack ${method} failed with HTTP ${response.status}`, + response.status + ) + } const data = await readResponseJsonWithLimit(response, { maxBytes: MAX_RESPONSE_BYTES, label: `Slack ${method} response`, diff --git a/apps/sim/lib/knowledge/application/organization-search-overview.test.ts b/apps/sim/lib/knowledge/application/organization-search-overview.test.ts index 043fe0f5f8d..6bb20aa3796 100644 --- a/apps/sim/lib/knowledge/application/organization-search-overview.test.ts +++ b/apps/sim/lib/knowledge/application/organization-search-overview.test.ts @@ -29,6 +29,31 @@ vi.mock('@/lib/sim-search/connectors', () => ({ import { organizationSearchOverviewSchema } from '@/lib/api/contracts/knowledge/connectors' import { knowledgeOperations } from '@/lib/knowledge/application/operations' import { readOrganizationSearchOverview } from '@/lib/knowledge/application/organization-search-overview' +import { SOURCE_CONTENT_ERROR } from '@/lib/knowledge/connectors/sync-limits' + +/** The global drizzle mock nests fragments as params; flatten one for inspection. */ +function renderFragment(fragment: unknown): { sql: string; params: unknown[] } { + if (!fragment || typeof fragment !== 'object') return { sql: '', params: [] } + if ('conditions' in fragment && Array.isArray(fragment.conditions)) { + const parts = fragment.conditions.map(renderFragment) + return { + sql: parts.map((part) => part.sql).join(' '), + params: parts.flatMap((part) => part.params), + } + } + const rendered = (fragment as { toSQL?: () => { sql: string; params: unknown[] } }).toSQL?.() + if (!rendered) return { sql: '', params: [] } + const params: unknown[] = [] + let sqlText = rendered.sql + for (const param of rendered.params) { + if (param && typeof param === 'object' && 'toSQL' in param) { + const nested = renderFragment(param) + sqlText += ` ${nested.sql}` + params.push(...nested.params) + } else params.push(param) + } + return { sql: sqlText, params } +} const principal = { kind: 'session', userId: 'admin', sessionId: 'session' } as const const input = { organizationId: 'organization' } @@ -82,6 +107,16 @@ describe('organization Search administration overview', () => { expect(result.providers[0]).toMatchObject({ status: 'needs_attention', issue }) expect(JSON.stringify(result)).not.toContain('private provider response') }) + it('does not count the per-document relisting marker as a member account error', async () => { + queueTableRows(member, [{ role: 'admin' }]) + queueTableRows(knowledgeConnector, [{ ...health }]) + await readOrganizationSearchOverview.execute({ principal, input }) + const rendered = dbChainMockFns.where.mock.calls.flatMap((call) => call.map(renderFragment)) + const memberErrorClause = rendered.find((fragment) => fragment.sql.includes("'suspended'")) + expect(memberErrorClause).toBeDefined() + expect(memberErrorClause?.sql).toContain('IS NOT NULL AND ? <> ?') + expect(memberErrorClause?.params).toContain(SOURCE_CONTENT_ERROR) + }) it('keeps recovery observable while a previous error remains visible', async () => { queueTableRows(member, [{ role: 'admin' }]) queueTableRows(knowledgeConnector, [{ ...health, hasError: true, hasIndexing: true }]) diff --git a/apps/sim/lib/knowledge/application/organization-search-overview.ts b/apps/sim/lib/knowledge/application/organization-search-overview.ts index 70025fc809b..eb58334a776 100644 --- a/apps/sim/lib/knowledge/application/organization-search-overview.ts +++ b/apps/sim/lib/knowledge/application/organization-search-overview.ts @@ -15,6 +15,7 @@ import { SOURCE_ACL_MAX_AGE_MS } from '@/lib/knowledge/access/freshness' import { defineAuthorizedKnowledgeUseCase } from '@/lib/knowledge/application/authorized-knowledge-use-case' import { resolveKnowledgeOwnerContext } from '@/lib/knowledge/application/contexts' import { knowledgeOperations } from '@/lib/knowledge/application/operations' +import { SOURCE_CONTENT_ERROR } from '@/lib/knowledge/connectors/sync-limits' import { MAX_SEARCH_SOURCE_PROVIDER_TYPES } from '@/lib/knowledge/constants' import { canConnectWithDefaults, SEARCH_SOURCE_TYPES } from '@/lib/sim-search/connectors' @@ -100,6 +101,11 @@ export const readOrganizationSearchOverview = defineAuthorizedKnowledgeUseCase({ )) )` const cutoff = sql`statement_timestamp() - (${SOURCE_ACL_MAX_AGE_MS} * interval '1 millisecond')` + /** + * A member whose last run only had per-document content failures carries + * {@link SOURCE_CONTENT_ERROR} as a marker so its next run lists fully; the + * member itself is healthy and the documents are reported separately. + */ const hasMemberError = exists( db .select({ id: knowledgeConnectorMember.id }) @@ -110,7 +116,7 @@ export const readOrganizationSearchOverview = defineAuthorizedKnowledgeUseCase({ sql`( ${knowledgeConnectorMember.status} = 'suspended' OR (${knowledgeConnectorMember.status} = 'active' AND ( - ${knowledgeConnectorMember.lastError} IS NOT NULL + (${knowledgeConnectorMember.lastError} IS NOT NULL AND ${knowledgeConnectorMember.lastError} <> ${SOURCE_CONTENT_ERROR}) OR ${knowledgeConnectorMember.consecutiveFailures} > 0 OR coalesce(${knowledgeConnectorMember.memberSyncedThrough}, ${knowledgeConnectorMember.lastCompleteListingAt}, ${knowledgeConnectorMember.createdAt}) < ${cutoff} )) diff --git a/apps/sim/lib/knowledge/connectors/sync-content-pass.test.ts b/apps/sim/lib/knowledge/connectors/sync-content-pass.test.ts index cec28ccf473..de2d738b106 100644 --- a/apps/sim/lib/knowledge/connectors/sync-content-pass.test.ts +++ b/apps/sim/lib/knowledge/connectors/sync-content-pass.test.ts @@ -655,7 +655,7 @@ describe('Confluence empty content through the shared content pass', () => { it('explicitly rehydrates a skipped source whose version is unchanged', async () => { sourceBody = { value: '

Local content is rechecked

' } const { result, hydrate } = await runPass({ - existing: { ...EXISTING, contentHash: 'confluence:storage-local-body-v1:page:3' }, + existing: { ...EXISTING, contentHash: 'confluence:storage-local-body-v2:page:3' }, access: 'admin', readCurrent: true, forceRehydrate: true, @@ -669,7 +669,7 @@ describe('Confluence empty content through the shared content pass', () => { hydrationVersion = 3 await runPass({ existing: EXISTING, readCurrent: true, access: 'admin' }) const skipped = contentWrite() - expect(skipped.contentHash).toBe('confluence:storage-local-body-v1:page:3') + expect(skipped.contentHash).toBe('confluence:storage-local-body-v2:page:3') hydrationVersion = undefined sourceBody = { value: '

Current version content

' } From 8d9875c822053e8296f366d21d6ff2fcf4a2864c Mon Sep 17 00:00:00 2001 From: Waleed Date: Thu, 10 Sep 2026 15:35:58 -0700 Subject: [PATCH 04/25] improvement(voice): add dictation to organization chat and search (#7737) * improvement(voice): add dictation to organization chat and search * fix(voice): preserve manual edits during dictation --- apps/sim/app/api/speech/token/route.test.ts | 339 +++++++++++++----- apps/sim/app/api/speech/token/route.ts | 218 ++++------- .../components/composer/composer.test.tsx | 111 ++++++ .../home/components/composer/composer.tsx | 33 +- .../o/[organizationId]/search/search.test.tsx | 48 ++- .../app/o/[organizationId]/search/search.tsx | 48 ++- .../components/mic-button/mic-button.tsx | 5 +- .../home/components/user-input/user-input.tsx | 70 +--- apps/sim/hooks/use-speech-to-text.ts | 9 +- apps/sim/hooks/use-voice-input.test.tsx | 144 ++++++++ apps/sim/hooks/use-voice-input.ts | 160 +++++++++ apps/sim/lib/api/contracts/media/speech.ts | 10 +- .../lib/speech/application/create-token.ts | 155 ++++++++ apps/sim/package.json | 1 + bun.lock | 1 + 15 files changed, 1024 insertions(+), 328 deletions(-) create mode 100644 apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx create mode 100644 apps/sim/hooks/use-voice-input.test.tsx create mode 100644 apps/sim/hooks/use-voice-input.ts create mode 100644 apps/sim/lib/speech/application/create-token.ts diff --git a/apps/sim/app/api/speech/token/route.test.ts b/apps/sim/app/api/speech/token/route.test.ts index 2042c24ec22..1e0a602b067 100644 --- a/apps/sim/app/api/speech/token/route.test.ts +++ b/apps/sim/app/api/speech/token/route.test.ts @@ -1,129 +1,296 @@ -/** - * @vitest-environment node - */ +/** @vitest-environment node */ +import * as workspaceAuthz from '@sim/platform-authz/workspace' import { authMockFns, createMockRequest, + dbChainMockFns, + envFlagsMockFns, resetDbChainMock, + resetEnvFlagsMock, resetEnvMock, setEnv, + setEnvFlags, } from '@sim/testing' -import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest' - -const { - mockRecordUsage, - mockVerifyWorkspaceMembership, - mockResolveBillingAttribution, - mockCheckAttributedUsageLimits, - mockToBillingContext, - mockCheckAndBillPayerOverageThreshold, -} = vi.hoisted(() => ({ - mockRecordUsage: vi.fn(), - mockVerifyWorkspaceMembership: vi.fn(), - mockResolveBillingAttribution: vi.fn(), - mockCheckAttributedUsageLimits: vi.fn(), - mockToBillingContext: vi.fn(), - mockCheckAndBillPayerOverageThreshold: vi.fn(), -})) +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -vi.mock('@/lib/billing/core/usage-log', () => ({ recordUsage: mockRecordUsage })) +const mocks = vi.hoisted(() => ({ + recordUsage: vi.fn(), + resolveBilling: vi.fn(), + resolveOrganizationBilling: vi.fn(), + checkUsage: vi.fn(), + toBillingContext: vi.fn(), + billOverage: vi.fn(), + rateCheck: vi.fn(), + organizationConfig: vi.fn(), + workspaceContext: vi.fn(), +})) +vi.mock('@/lib/billing/core/usage-log', () => ({ recordUsage: mocks.recordUsage })) vi.mock('@/lib/billing/core/billing-attribution', () => ({ - resolveBillingAttribution: mockResolveBillingAttribution, - checkAttributedUsageLimits: mockCheckAttributedUsageLimits, - toBillingContext: mockToBillingContext, + resolveBillingAttribution: mocks.resolveBilling, + resolveOrganizationBillingAttribution: mocks.resolveOrganizationBilling, + checkAttributedUsageLimits: mocks.checkUsage, + toBillingContext: mocks.toBillingContext, })) - vi.mock('@/lib/billing/threshold-billing', () => ({ - checkAndBillPayerOverageThreshold: mockCheckAndBillPayerOverageThreshold, -})) - -vi.mock('@/app/api/workflows/utils', () => ({ - verifyWorkspaceMembership: mockVerifyWorkspaceMembership, + checkAndBillPayerOverageThreshold: mocks.billOverage, })) - vi.mock('@/lib/core/rate-limiter', () => ({ RateLimiter: class { - checkRateLimitDirect = vi.fn().mockResolvedValue({ allowed: true }) + checkRateLimitDirect = mocks.rateCheck }, })) +vi.mock('@/lib/permission-groups/resolve.server', () => ({ + getUserPermissionConfigForOrganization: mocks.organizationConfig, +})) +vi.mock('@/lib/workspaces/application/workspace-context', () => ({ + resolveActiveWorkspaceApplicationContext: mocks.workspaceContext, +})) +import { OrchestrationError } from '@/lib/core/orchestration/types' +import { createSpeechToken } from '@/lib/speech/application/create-token' import { POST } from '@/app/api/speech/token/route' -const mockGetSession = authMockFns.mockGetSession +const permission = vi.spyOn(workspaceAuthz, 'resolveEffectiveWorkspacePermission') +const principal = { kind: 'session', userId: 'member-1', sessionId: 'session-1' } as const +const billingEntity = { type: 'organization', id: 'org-1' } as const +const billingPeriod = { start: new Date('2026-07-01'), end: new Date('2026-08-01') } beforeEach(() => { vi.clearAllMocks() resetDbChainMock() setEnv({ ELEVENLABS_API_KEY: 'test-key' }) - mockGetSession.mockResolvedValue({ user: { id: 'member-1' } }) - mockRecordUsage.mockResolvedValue(undefined) - mockCheckAttributedUsageLimits.mockResolvedValue({ isExceeded: false }) - mockResolveBillingAttribution.mockImplementation( - ({ actorUserId, workspaceId }: { actorUserId: string; workspaceId: string }) => ({ - actorUserId, - workspaceId, - billingEntity: { type: 'organization', id: 'org-1' }, - }) - ) - mockToBillingContext.mockImplementation( - (attribution: { billingEntity: { type: 'organization' | 'user'; id: string } }) => ({ - billingEntity: attribution.billingEntity, - billingPeriod: { - start: new Date('2026-07-01T00:00:00.000Z'), - end: new Date('2026-08-01T00:00:00.000Z'), - }, - }) - ) - mockVerifyWorkspaceMembership.mockResolvedValue('admin') - global.fetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => ({ token: 'tok-123' }), - // double-cast-allowed: minimal fetch stub for the ElevenLabs token call - }) as unknown as typeof fetch + setEnvFlags({ isBillingEnabled: true }) + authMockFns.mockGetSession.mockResolvedValue({ + user: { id: principal.userId }, + session: { id: principal.sessionId }, + }) + permission.mockResolvedValue('read') + mocks.workspaceContext.mockImplementation(async (workspaceId: string) => ({ + workspaceId, + workspaceOrganizationId: null, + allowPersonalApiKeys: true, + billedAccountUserId: 'owner-1', + })) + mocks.organizationConfig.mockResolvedValue(null) + dbChainMockFns.limit.mockResolvedValue([{ role: 'member' }]) + mocks.recordUsage.mockResolvedValue(undefined) + mocks.billOverage.mockResolvedValue(undefined) + mocks.rateCheck.mockResolvedValue({ allowed: true }) + mocks.checkUsage.mockResolvedValue({ isExceeded: false }) + mocks.resolveBilling.mockImplementation(async (input) => ({ ...input, billingEntity })) + mocks.resolveOrganizationBilling.mockImplementation(async (input) => ({ + ...input, + workspaceId: null, + billedAccountUserId: 'owner-1', + billingEntity, + })) + mocks.toBillingContext.mockReturnValue({ billingEntity, billingPeriod }) + vi.stubGlobal('fetch', vi.fn().mockResolvedValue(Response.json({ token: 'tok-123' }))) }) -afterAll(() => { +afterEach(() => { + vi.unstubAllGlobals() resetDbChainMock() resetEnvMock() + resetEnvFlagsMock() }) -describe('POST /api/speech/token — usage attribution', () => { - it('editor voice: bills the session user and stamps the verified workspace', async () => { - const res = await POST(createMockRequest('POST', { workspaceId: 'ws-1' })) +describe('POST /api/speech/token', () => { + it.each(['read', 'write', 'admin'] as const)( + 'allows workspace %s members and bills the acting user', + async (role) => { + permission.mockResolvedValue(role) + envFlagsMockFns.getCostMultiplier.mockReturnValue(2) + const response = await POST(createMockRequest('POST', { workspaceId: 'ws-1' })) - expect(res.status).toBe(200) - expect(mockVerifyWorkspaceMembership).toHaveBeenCalledWith('member-1', 'ws-1') - expect(mockRecordUsage).toHaveBeenCalledTimes(1) - expect(mockRecordUsage.mock.calls[0][0]).toMatchObject({ - userId: 'member-1', - workspaceId: 'ws-1', - }) - expect(mockResolveBillingAttribution).toHaveBeenCalledWith({ - actorUserId: 'member-1', - workspaceId: 'ws-1', + expect(response.status).toBe(200) + expect(await response.json()).toEqual({ token: 'tok-123' }) + expect(permission).toHaveBeenCalledWith('member-1', 'ws-1', null, undefined, { + forUpdate: undefined, + }) + expect(mocks.resolveBilling).toHaveBeenCalledWith({ + actorUserId: 'member-1', + workspaceId: 'ws-1', + }) + expect(mocks.recordUsage).toHaveBeenCalledWith({ + userId: 'member-1', + workspaceId: 'ws-1', + billingEntity, + billingPeriod, + entries: [ + { + category: 'fixed', + source: 'voice-input', + description: 'Voice input session (3 min)', + cost: 0.048, + sourceReference: expect.stringMatching(/^voice-input:[a-f0-9]{64}$/), + }, + ], + }) + expect(mocks.billOverage).toHaveBeenCalledWith(billingEntity) + } + ) + + it.each(['member', 'admin', 'owner'])( + 'allows organization %s members without inventing a workspace', + async (role) => { + dbChainMockFns.limit.mockResolvedValue([{ role }]) + const response = await POST(createMockRequest('POST', { organizationId: 'org-1' })) + + expect(response.status).toBe(200) + expect(mocks.resolveOrganizationBilling).toHaveBeenCalledWith({ + actorUserId: 'member-1', + organizationId: 'org-1', + }) + expect(mocks.resolveBilling).not.toHaveBeenCalled() + expect(mocks.workspaceContext).not.toHaveBeenCalled() + expect(mocks.recordUsage.mock.calls[0][0]).toMatchObject({ + userId: 'member-1', + billingEntity, + billingPeriod, + }) + expect(mocks.recordUsage.mock.calls[0][0]).not.toHaveProperty('workspaceId') + } + ) + + it('authenticates before reading an oversized body', async () => { + authMockFns.mockGetSession.mockResolvedValue(null) + const response = await POST(createMockRequest('POST', { workspaceId: 'x'.repeat(64 * 1024) })) + expect(response.status).toBe(401) + expect(mocks.rateCheck).not.toHaveBeenCalled() + expect(mocks.workspaceContext).not.toHaveBeenCalled() + }) + + it('caps authenticated bodies before protected loading', async () => { + const response = await POST(createMockRequest('POST', { workspaceId: 'x'.repeat(64 * 1024) })) + expect(response.status).toBe(413) + expect(mocks.workspaceContext).not.toHaveBeenCalled() + expect(mocks.recordUsage).not.toHaveBeenCalled() + }) + + it.each([ + {}, + { workspaceId: 'ws-1', organizationId: 'org-1' }, + { organizationId: '' }, + { workspaceId: 1 }, + ])('rejects absent, ambiguous or invalid scope %j', async (body) => { + const response = await POST(createMockRequest('POST', body)) + expect(response.status).toBe(400) + expect(mocks.workspaceContext).not.toHaveBeenCalled() + expect(mocks.resolveOrganizationBilling).not.toHaveBeenCalled() + expect(fetch).not.toHaveBeenCalled() + }) + + it('conceals a workspace the caller cannot access', async () => { + permission.mockResolvedValue(null) + const response = await POST(createMockRequest('POST', { workspaceId: 'ws-other' })) + expect(response.status).toBe(400) + expect(await response.json()).toMatchObject({ + error: 'Workspace or organization context is required.', }) - expect(mockCheckAndBillPayerOverageThreshold).toHaveBeenCalledWith({ - type: 'organization', - id: 'org-1', + expect(mocks.resolveBilling).not.toHaveBeenCalled() + expect(fetch).not.toHaveBeenCalled() + }) + + it('rejects removed organization members before billing or token creation', async () => { + dbChainMockFns.limit.mockResolvedValue([]) + const response = await POST(createMockRequest('POST', { organizationId: 'org-other' })) + expect(response.status).toBe(400) + expect(mocks.resolveOrganizationBilling).not.toHaveBeenCalled() + expect(fetch).not.toHaveBeenCalled() + }) + + it('rejects inactive workspaces before billing', async () => { + mocks.workspaceContext.mockRejectedValue( + new OrchestrationError('not_found', 'Workspace not found') + ) + const response = await POST(createMockRequest('POST', { workspaceId: 'ws-archived' })) + expect(response.status).toBe(400) + expect(mocks.resolveBilling).not.toHaveBeenCalled() + }) + + it('rates by actor with the existing bucket and retry header before parsing', async () => { + mocks.rateCheck.mockResolvedValue({ allowed: false, retryAfterMs: 1501 }) + const response = await POST(createMockRequest('POST', {})) + expect(response.status).toBe(429) + expect(response.headers.get('Retry-After')).toBe('2') + expect(mocks.rateCheck).toHaveBeenCalledWith('stt-token:user:member-1', { + maxTokens: 30, + refillRate: 3, + refillIntervalMs: 72000, }) + expect(mocks.resolveOrganizationBilling).not.toHaveBeenCalled() }) - it('editor voice: rejects an unverified workspace id (requires an attributable workspace)', async () => { - mockVerifyWorkspaceMembership.mockResolvedValue(null) + it('preserves the rate exemption when billing is disabled', async () => { + setEnvFlags({ isBillingEnabled: false }) + const response = await POST(createMockRequest('POST', { organizationId: 'org-1' })) + expect(response.status).toBe(200) + expect(mocks.rateCheck).not.toHaveBeenCalled() + }) - const res = await POST(createMockRequest('POST', { workspaceId: 'ws-not-mine' })) + it.each(['actor', 'payer', 'member'])( + 'enforces the %s usage cap before contacting the provider', + async (scope) => { + mocks.checkUsage.mockResolvedValue({ isExceeded: true, message: 'Usage cap reached', scope }) + const response = await POST(createMockRequest('POST', { organizationId: 'org-1' })) + expect(response.status).toBe(402) + expect(await response.json()).toMatchObject({ error: 'Usage cap reached', scope }) + expect(fetch).not.toHaveBeenCalled() + expect(mocks.recordUsage).not.toHaveBeenCalled() + } + ) - expect(res.status).toBe(400) - expect(mockRecordUsage).not.toHaveBeenCalled() + it('does not conceal membership infrastructure failures as missing membership', async () => { + dbChainMockFns.limit.mockRejectedValue(new Error('database unavailable')) + const response = await POST(createMockRequest('POST', { organizationId: 'org-1' })) + expect(response.status).toBe(500) + expect(mocks.resolveOrganizationBilling).not.toHaveBeenCalled() }) - it('rejects an oversized body before any auth/billing work runs', async () => { - const oversizedBody = { workspaceId: 'x'.repeat(64 * 1024) } - const res = await POST(createMockRequest('POST', oversizedBody)) + it('does not issue tokens after billing attribution fails', async () => { + mocks.resolveOrganizationBilling.mockRejectedValue(new Error('billing unavailable')) + const response = await POST(createMockRequest('POST', { organizationId: 'org-1' })) + expect(response.status).toBe(500) + expect(fetch).not.toHaveBeenCalled() + }) + + it('preserves service-not-configured and upstream errors', async () => { + setEnv({ ELEVENLABS_API_KEY: '' }) + expect((await POST(createMockRequest('POST', { organizationId: 'org-1' }))).status).toBe(503) + setEnv({ ELEVENLABS_API_KEY: 'key' }) + vi.mocked(fetch).mockResolvedValue( + Response.json({ detail: 'Provider unavailable' }, { status: 503 }) + ) + const response = await POST(createMockRequest('POST', { organizationId: 'org-1' })) + expect(response.status).toBe(502) + expect(await response.json()).toMatchObject({ error: 'Provider unavailable' }) + expect(mocks.recordUsage).not.toHaveBeenCalled() + }) + + it.each(['recordUsage', 'billOverage'] as const)( + 'keeps an issued token available when %s fails', + async (failure) => { + mocks[failure].mockRejectedValue(new Error('billing write failed')) + const response = await POST(createMockRequest('POST', { organizationId: 'org-1' })) + expect(response.status).toBe(200) + expect(await response.json()).toEqual({ token: 'tok-123' }) + if (failure === 'recordUsage') expect(mocks.billOverage).not.toHaveBeenCalled() + } + ) - expect(res.status).toBe(413) - expect(mockGetSession).not.toHaveBeenCalled() - expect(mockRecordUsage).not.toHaveBeenCalled() + it('rejects non-session principals before any protected loading', async () => { + for (const input of [{ workspaceId: 'ws-1' }, { organizationId: 'org-1' }]) { + await expect( + createSpeechToken.execute({ + principal: { kind: 'personal_api_key', userId: 'member-1', keyId: 'key-1' }, + input, + }) + ).rejects.toThrow('cannot perform operation speech.token.create') + } + expect(mocks.workspaceContext).not.toHaveBeenCalled() + expect(dbChainMockFns.limit).not.toHaveBeenCalled() + expect(fetch).not.toHaveBeenCalled() }) }) diff --git a/apps/sim/app/api/speech/token/route.ts b/apps/sim/app/api/speech/token/route.ts index 6955d97b2c8..b290967287d 100644 --- a/apps/sim/app/api/speech/token/route.ts +++ b/apps/sim/app/api/speech/token/route.ts @@ -1,172 +1,80 @@ -import { createHash } from 'node:crypto' -import { createLogger } from '@sim/logger' -import { getErrorMessage } from '@sim/utils/errors' -import { type NextRequest, NextResponse } from 'next/server' -import { speechTokenBodySchema } from '@/lib/api/contracts/media/speech' -import { parseOptionalJsonBody } from '@/lib/api/server' -import { getSession } from '@/lib/auth' +import { requirePrincipalSubjectUserId } from '@sim/auth/principal' +import { NextResponse } from 'next/server' +import { speechTokenContract } from '@/lib/api/contracts/media/speech' import { - checkAttributedUsageLimits, - resolveBillingAttribution, - toBillingContext, -} from '@/lib/billing/core/billing-attribution' -import { recordUsage } from '@/lib/billing/core/usage-log' -import { checkAndBillPayerOverageThreshold } from '@/lib/billing/threshold-billing' -import { env } from '@/lib/core/config/env' -import { getCostMultiplier, isBillingEnabled } from '@/lib/core/config/env-flags' + defineInternalJsonRoute, + internalErrorResponse, + internalSessionAuth, +} from '@/lib/api/server/routes' +import { NoWorkspaceAccessError } from '@/lib/core/application/workspace-authorization' +import { isBillingEnabled } from '@/lib/core/config/env-flags' +import { asOrchestrationError } from '@/lib/core/orchestration/types' import { RateLimiter } from '@/lib/core/rate-limiter' -import { withRouteHandler } from '@/lib/core/utils/with-route-handler' -import { verifyWorkspaceMembership } from '@/app/api/workflows/utils' - -const logger = createLogger('SpeechTokenAPI') +import { + createSpeechToken, + SpeechTokenError, + speechTokenOperation, +} from '@/lib/speech/application/create-token' export const dynamic = 'force-dynamic' -const ELEVENLABS_TOKEN_URL = 'https://api.elevenlabs.io/v1/single-use-token/realtime_scribe' - -const VOICE_SESSION_COST_PER_MIN = 0.008 -const WORKSPACE_SESSION_MAX_MINUTES = 3 - const STT_TOKEN_RATE_LIMIT = { maxTokens: 30, refillRate: 3, refillIntervalMs: 72 * 1000, } as const - -/** - * This body only ever carries an optional workspaceId string, so a - * tight cap keeps an unauthenticated caller from forcing a large in-memory - * allocation before the auth checks below run. - */ -const MAX_SPEECH_TOKEN_BODY_BYTES = 16 * 1024 - -function hashVoiceToken(token: string): string { - return createHash('sha256').update(token).digest('hex') -} - const rateLimiter = new RateLimiter() -export const POST = withRouteHandler(async (request: NextRequest) => { - try { - const parsedBody = await parseOptionalJsonBody(request, MAX_SPEECH_TOKEN_BODY_BYTES) - if (!parsedBody.success) return parsedBody.response - const body = speechTokenBodySchema.safeParse(parsedBody.data ?? {}) - - let workspaceId: string | undefined - - const session = await getSession() - if (!session?.user?.id) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) - } - const actorUserId = session.user.id - /** - * Accepts only a workspace the caller belongs to, preventing client-supplied - * IDs from misattributing or bypassing member usage. - */ - const requestedWorkspaceId = - body.success && typeof body.data.workspaceId === 'string' ? body.data.workspaceId : undefined - if (requestedWorkspaceId) { - const permission = await verifyWorkspaceMembership(session.user.id, requestedWorkspaceId) - if (permission) workspaceId = requestedWorkspaceId - } - /** - * Workspace-scoped so every charge has a payer and member cap attribution. - */ - if (!workspaceId) { - return NextResponse.json({ error: 'Workspace context is required.' }, { status: 400 }) - } - - const billingAttribution = await resolveBillingAttribution({ actorUserId, workspaceId }) - - if (isBillingEnabled) { +export const POST = defineInternalJsonRoute({ + contract: speechTokenContract, + auth: internalSessionAuth, + operation: speechTokenOperation, + rateLimit: { + kind: 'user', + bucketName: 'stt-token', + async enforce(_request, principal) { + if (!isBillingEnabled) return null const rateCheck = await rateLimiter.checkRateLimitDirect( - `stt-token:user:${actorUserId}`, + `stt-token:user:${requirePrincipalSubjectUserId(principal)}`, STT_TOKEN_RATE_LIMIT ) - if (!rateCheck.allowed) { - return NextResponse.json( - { error: 'Voice input rate limit exceeded. Please try again later.' }, - { - status: 429, - headers: { - 'Retry-After': String(Math.ceil((rateCheck.retryAfterMs ?? 60000) / 1000)), - }, - } - ) + return rateCheck.allowed + ? null + : NextResponse.json( + { error: 'Voice input rate limit exceeded. Please try again later.' }, + { + status: 429, + headers: { + 'Retry-After': String(Math.ceil((rateCheck.retryAfterMs ?? 60000) / 1000)), + }, + } + ) + }, + }, + parseOptions: { + maxBodyBytes: 16 * 1024, + validationErrorResponse: () => + NextResponse.json( + { error: 'Workspace or organization context is required.' }, + { status: 400 } + ), + }, + errorPolicy: { + project(error) { + if (error instanceof SpeechTokenError) { + const status = { usage_limit: 402, unconfigured: 503, provider_failed: 502 }[error.reason] + return internalErrorResponse(status, { error: error.message, scope: error.scope }) } - } - - /** - * Read-then-act, as every metered route in the repo does: concurrent calls - * can pass against the same balance and overshoot the payer's limit. Making - * this atomic needs a reservation primitive in `lib/billing` that fixes the - * class everywhere, not a one-off here. - * - * Accepted as bounded rather than eliminated: this route is session-gated - * and rate limited per user, so the overshoot is a knowable ceiling against - * an identified payer. - */ - const usageCheck = await checkAttributedUsageLimits(billingAttribution) - if (usageCheck.isExceeded) { - return NextResponse.json( - { - error: - usageCheck.message || 'Usage limit exceeded. Please upgrade your plan to continue.', - scope: usageCheck.scope, - }, - { status: 402 } - ) - } - - const apiKey = env.ELEVENLABS_API_KEY - if (!apiKey?.trim()) { - return NextResponse.json( - { error: 'Speech-to-text service is not configured' }, - { status: 503 } - ) - } - - const response = await fetch(ELEVENLABS_TOKEN_URL, { - method: 'POST', - headers: { 'xi-api-key': apiKey }, - }) - - if (!response.ok) { - const errBody = await response.json().catch(() => ({})) - const message = - errBody.detail || errBody.message || `Token request failed (${response.status})` - logger.error('ElevenLabs token request failed', { status: response.status, message }) - return NextResponse.json({ error: message }, { status: 502 }) - } - - const data = await response.json() - - const sessionCost = VOICE_SESSION_COST_PER_MIN * WORKSPACE_SESSION_MAX_MINUTES - - try { - await recordUsage({ - userId: actorUserId, - workspaceId, - ...toBillingContext(billingAttribution), - entries: [ - { - category: 'fixed', - source: 'voice-input', - description: `Voice input session (${WORKSPACE_SESSION_MAX_MINUTES} min)`, - cost: sessionCost * getCostMultiplier(), - sourceReference: `voice-input:${hashVoiceToken(data.token)}`, - }, - ], - }) - await checkAndBillPayerOverageThreshold(billingAttribution.billingEntity) - } catch (err) { - logger.warn('Failed to record voice input usage, continuing:', err) - } - - return NextResponse.json({ token: data.token }) - } catch (error) { - const message = getErrorMessage(error, 'Failed to generate speech token') - logger.error('Speech token error:', error) - return NextResponse.json({ error: message }, { status: 500 }) - } + const classified = asOrchestrationError(error) + if (error instanceof NoWorkspaceAccessError || classified?.code === 'not_found') { + return internalErrorResponse(400, { + error: 'Workspace or organization context is required.', + }) + } + return null + }, + unhandled: () => internalErrorResponse(500, { error: 'Failed to generate speech token' }), + }, + mapInput: ({ body }) => body, + useCase: createSpeechToken, }) diff --git a/apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx b/apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx new file mode 100644 index 00000000000..b8e873529b2 --- /dev/null +++ b/apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx @@ -0,0 +1,111 @@ +/** @vitest-environment jsdom */ +import { act, useState } from 'react' +import { createRoot, type Root } from 'react-dom/client' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type { useSpeechToText } from '@/hooks/use-speech-to-text' + +const mocks = vi.hoisted(() => ({ + speech: vi.fn(), + toggleListening: vi.fn(), + resetTranscript: vi.fn(), + submit: vi.fn(), +})) + +vi.mock('@/hooks/use-speech-to-text', () => ({ useSpeechToText: mocks.speech })) +vi.mock('@/hooks/use-animated-placeholder', () => ({ useAnimatedPlaceholder: () => 'Ask Sim to' })) +vi.mock('@/hooks/use-chat-input-focus', () => ({ useChatInputFocus: vi.fn() })) +vi.mock('@/app/o/[organizationId]/providers/organization-provider', () => ({ + useOrganizationContext: () => ({ organization: { id: 'organization-a' } }), +})) + +import { Composer } from '@/app/o/[organizationId]/home/components/composer/composer' + +let root: Root +let container: HTMLDivElement + +beforeEach(() => { + vi.clearAllMocks() + vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true) + vi.stubGlobal( + 'matchMedia', + vi.fn(() => ({ + matches: false, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + })) + ) + mocks.speech.mockReturnValue({ + isSupported: true, + isListening: false, + audioLevelsRef: { current: new Float32Array(5) }, + toggleListening: mocks.toggleListening, + resetTranscript: mocks.resetTranscript, + }) + container = document.createElement('div') + document.body.appendChild(container) + root = createRoot(container) +}) + +afterEach(async () => { + await act(async () => root.unmount()) + container.remove() + vi.unstubAllGlobals() +}) + +async function render(isInitialView: boolean) { + function Harness() { + const [value, setValue] = useState('Summarize') + return ( + { + mocks.submit(value) + setValue('') + }} + /> + ) + } + await act(async () => root.render()) +} + +describe('organization voice composer', () => { + it.each([true, false])( + 'appends dictation and clears its prefix on send (initial: %s)', + async (isInitialView) => { + await render(isInitialView) + const mic = container.querySelector('button[aria-label="Voice input"]')! + expect(mic.nextElementSibling?.getAttribute('aria-label')).toBe('Send') + await act(async () => mic.click()) + expect(mocks.toggleListening).toHaveBeenCalledOnce() + const speech = mocks.speech.mock.calls.at(-1)![0] + expect(speech.organizationId).toBe('organization-a') + await act(async () => speech.onTranscript('the')) + await act(async () => speech.onTranscript('the release')) + expect(container.querySelector('textarea')!.value).toBe('Summarize the release') + expect(mocks.submit).not.toHaveBeenCalled() + await act(async () => { + container.querySelector('button[aria-label="Send"]')!.click() + }) + expect(mocks.submit).toHaveBeenCalledWith('Summarize the release') + expect(mocks.resetTranscript).toHaveBeenCalledOnce() + await act(async () => mocks.speech.mock.calls.at(-1)![0].onTranscript('Next question')) + expect(container.querySelector('textarea')!.value).toBe('Next question') + } + ) + + it('hides voice input when unavailable', async () => { + mocks.speech.mockImplementation(() => ({ + isSupported: false, + isListening: false, + audioLevelsRef: { current: new Float32Array(5) }, + toggleListening: mocks.toggleListening, + resetTranscript: mocks.resetTranscript, + })) + await render(true) + expect(container.querySelector('button[aria-label="Voice input"]')).toBeNull() + }) +}) diff --git a/apps/sim/app/o/[organizationId]/home/components/composer/composer.tsx b/apps/sim/app/o/[organizationId]/home/components/composer/composer.tsx index 9189db61670..1c897d4d532 100644 --- a/apps/sim/app/o/[organizationId]/home/components/composer/composer.tsx +++ b/apps/sim/app/o/[organizationId]/home/components/composer/composer.tsx @@ -3,8 +3,12 @@ import { useRef } from 'react' import { Button, cn } from '@sim/emcn' import { ArrowUp } from '@sim/emcn/icons' +import { useOrganizationContext } from '@/app/o/[organizationId]/providers/organization-provider' +import { MicButton } from '@/app/workspace/[workspaceId]/home/components/user-input/components/mic-button/mic-button' +import { MicrophonePermissionHelp } from '@/app/workspace/[workspaceId]/home/components/user-input/components/microphone-permission-help/microphone-permission-help' import { useAnimatedPlaceholder } from '@/hooks/use-animated-placeholder' import { useChatInputFocus } from '@/hooks/use-chat-input-focus' +import { useVoiceInput } from '@/hooks/use-voice-input' const SEND_BUTTON_BASE = 'size-[28px] rounded-full border-0 p-0 transition-colors' const SEND_BUTTON_ACTIVE = @@ -35,11 +39,23 @@ export function Composer({ onStop, }: ComposerProps) { const textareaRef = useRef(null) + const { organization } = useOrganizationContext() useChatInputFocus({ textareaRef }) + const voice = useVoiceInput({ + organizationId: organization.id, + getValue: () => value, + onChange, + }) const canSubmit = value.trim().length > 0 const animatedPlaceholder = useAnimatedPlaceholder(isInitialView) const placeholder = isInitialView ? animatedPlaceholder : 'Send message to Sim' + const submit = () => { + if (!canSubmit) return + voice.resetTranscript() + onSubmit() + } + return (
{ if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) { event.preventDefault() - onSubmit() + submit() } }} placeholder={placeholder} @@ -70,7 +86,14 @@ export function Composer({ />
-
+
+ {voice.isSupported && ( + + )} {isSending ? (
+
) } diff --git a/apps/sim/app/o/[organizationId]/search/search.test.tsx b/apps/sim/app/o/[organizationId]/search/search.test.tsx index 24ef1c21007..41db4871567 100644 --- a/apps/sim/app/o/[organizationId]/search/search.test.tsx +++ b/apps/sim/app/o/[organizationId]/search/search.test.tsx @@ -6,14 +6,21 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import type { WorkspaceKnowledgeSearchResult } from '@/lib/api/contracts/knowledge' import type { ResourceScope } from '@/lib/core/resource-scope' import type { SourceTagData } from '@/app/workspace/[workspaceId]/home/components/message-content/components/special-tags' +import type { useSpeechToText } from '@/hooks/use-speech-to-text' const mocks = vi.hoisted(() => ({ search: vi.fn(), urlUpdate: vi.fn(), push: vi.fn(), + speech: vi.fn(), + toggleListening: vi.fn(), })) -vi.mock('next/navigation', () => ({ useRouter: () => ({ push: mocks.push }) })) +vi.mock('@/hooks/use-speech-to-text', () => ({ useSpeechToText: mocks.speech })) +vi.mock('next/navigation', () => ({ + useRouter: () => ({ push: mocks.push }), + usePathname: () => '/o/organization-a/search', +})) vi.mock('@/app/o/[organizationId]/providers/organization-provider', () => ({ useOrganizationContext: () => ({ organization: { id: 'organization-a', name: 'Acme' }, @@ -54,6 +61,21 @@ let container: HTMLDivElement beforeEach(() => { vi.clearAllMocks() vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true) + vi.stubGlobal( + 'matchMedia', + vi.fn(() => ({ + matches: false, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + })) + ) + mocks.speech.mockReturnValue({ + isSupported: true, + isListening: false, + audioLevelsRef: { current: new Float32Array(5) }, + toggleListening: mocks.toggleListening, + resetTranscript: vi.fn(), + }) mocks.search.mockImplementation((_scope: ResourceScope, query: string) => { const result: WorkspaceKnowledgeSearchResult = { documentId: `document-${query}`, @@ -113,6 +135,30 @@ function expectVisibleQuery(query: string) { } describe('organization Search query navigation', () => { + it.each(['', '?q=Orion'])( + 'dictates into the draft without searching until submit (%s)', + async (params) => { + await render(params) + await editDraft('Find') + const searchCalls = mocks.search.mock.calls.length + const mic = container.querySelector('button[aria-label="Voice input"]')! + expect(mic.nextElementSibling?.getAttribute('aria-label')).toBe('Search') + await act(async () => mic.click()) + expect(mocks.toggleListening).toHaveBeenCalledOnce() + const speech = mocks.speech.mock.calls.at(-1)![0] + expect(speech.organizationId).toBe('organization-a') + await act(async () => speech.onTranscript('release')) + await act(async () => speech.onTranscript('release notes')) + expect(searchInput().value).toBe('Find release notes') + expect(mocks.search).toHaveBeenCalledTimes(searchCalls) + expect(mocks.urlUpdate).not.toHaveBeenCalled() + await act(async () => { + container.querySelector('button[aria-label="Search"]')!.click() + }) + expectVisibleQuery('Find release notes') + } + ) + it('replaces the field draft and results when the committed URL query changes without remounting the page', async () => { await render('?q=Orion') expectVisibleQuery('Orion') diff --git a/apps/sim/app/o/[organizationId]/search/search.tsx b/apps/sim/app/o/[organizationId]/search/search.tsx index 581fcee0c2e..7ab8ac1173d 100644 --- a/apps/sim/app/o/[organizationId]/search/search.tsx +++ b/apps/sim/app/o/[organizationId]/search/search.tsx @@ -17,10 +17,13 @@ import { organizationSearchUrlKeys, } from '@/app/o/[organizationId]/search/search-params' import { KnowledgeSearchResults } from '@/app/workspace/[workspaceId]/home/components/knowledge-search-results' +import { MicButton } from '@/app/workspace/[workspaceId]/home/components/user-input/components/mic-button/mic-button' +import { MicrophonePermissionHelp } from '@/app/workspace/[workspaceId]/home/components/user-input/components/microphone-permission-help/microphone-permission-help' import { SIDEBAR_DIVIDER_PAD_ABOVE_CLASS, SIDEBAR_DIVIDER_PAD_BELOW_CLASS, } from '@/app/workspace/[workspaceId]/w/components/sidebar/constants' +import { useVoiceInput } from '@/hooks/use-voice-input' const SUBMIT_BUTTON_BASE = 'size-[28px] shrink-0 rounded-full border-0 p-0 transition-colors' const SUBMIT_BUTTON_ACTIVE = @@ -49,7 +52,13 @@ function SearchField({ docked = false, }: SearchFieldProps) { const inputRef = useRef(null) + const { organization } = useOrganizationContext() const [value, setValue] = useState(initialValue) + const voice = useVoiceInput({ + organizationId: organization.id, + getValue: () => value, + onChange: setValue, + }) const canSubmit = value.trim().length > 0 useEffect(() => { @@ -79,21 +88,34 @@ function SearchField({ aria-label='Search your sources' autoComplete='off' spellCheck={false} - className='h-full w-full bg-transparent font-body text-[14px] text-[var(--text-primary)] tracking-[-0.015em] outline-hidden placeholder:text-[var(--text-muted)] [&::-webkit-search-cancel-button]:hidden' + className='h-full min-w-0 flex-1 bg-transparent font-body text-[14px] text-[var(--text-primary)] tracking-[-0.015em] outline-hidden placeholder:text-[var(--text-muted)] [&::-webkit-search-cancel-button]:hidden' /> - + + + ) } diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/mic-button/mic-button.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/mic-button/mic-button.tsx index 8b78f27fe03..2e2b6a51cae 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/mic-button/mic-button.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/mic-button/mic-button.tsx @@ -5,7 +5,7 @@ import { Button, cn, Tooltip, usePrefersReducedMotion } from '@sim/emcn' import { Mic } from '@sim/emcn/icons' const WAVEFORM_BAR_COUNT = 5 -const WAVEFORM_MIN_HEIGHT = 3 +const WAVEFORM_MIN_HEIGHT = 1 const WAVEFORM_MAX_HEIGHT = 14 const WAVEFORM_CENTER = 9 const WAVEFORM_EASING = 0.24 @@ -71,7 +71,7 @@ function VoiceWaveform({ audioLevelsRef, isListening }: VoiceWaveformProps) { y2={WAVEFORM_CENTER + WAVEFORM_MIN_HEIGHT / 2} stroke='currentColor' strokeLinecap='round' - strokeWidth='1.7' + strokeWidth='1.5' /> ) })} @@ -108,6 +108,7 @@ export const MicButton = memo(function MicButton({ (function UserI const contextsEnabled = !canSearch || mode === 'build' const contextsEnabledRef = useRef(contextsEnabled) contextsEnabledRef.current = contextsEnabled - const [microphonePermissionHelpOpen, setMicrophonePermissionHelpOpen] = useState(false) const [initialValue] = useState(() => { if (defaultValue) return defaultValue @@ -332,14 +330,6 @@ const UserInputImpl = forwardRef(function UserI if (defaultValue) editorRef.current.setValue(defaultValue) }, [defaultValue]) - const sttPrefixRef = useRef('') - - function handleTranscript(text: string) { - const prefix = sttPrefixRef.current - const newVal = prefix ? `${prefix} ${text}` : text - editorRef.current.setValue(newVal) - } - function handleUsageLimitExceeded(message?: string, isMemberLimit?: boolean) { // A per-member cap can only be raised by an org admin, so don't offer Upgrade // (the member can't act on it) — the message already tells them to ask an admin. @@ -356,59 +346,21 @@ const UserInputImpl = forwardRef(function UserI ) } - function handleSpeechError(error: SpeechToTextError) { - if (error === 'microphone-blocked') { - const desktopBridge = getDesktopBridge() - if (desktopBridge) { - const { openMicrophoneSettings } = desktopBridge - toast.error( - 'Microphone access is blocked. Allow Sim to use the microphone in your system privacy settings.', - openMicrophoneSettings - ? { - action: { - label: 'Open Settings', - onClick: () => void openMicrophoneSettings(), - }, - } - : undefined - ) - } else { - toast.error('Microphone access is blocked. Allow it for this site and try again.', { - action: { - label: 'Show steps', - onClick: () => setMicrophonePermissionHelpOpen(true), - }, - }) - } - return - } - if (error === 'microphone-unavailable') { - toast.error('No microphone found. Connect one and try again.') - return - } - toast.error('Could not start voice input. Try again.') - } - const { audioLevelsRef, isListening, isSupported: isSttSupported, - toggleListening: rawToggle, + toggleListening, resetTranscript, - } = useSpeechToText({ - onTranscript: handleTranscript, - onUsageLimitExceeded: handleUsageLimitExceeded, - onError: handleSpeechError, + permissionHelpOpen, + setPermissionHelpOpen, + } = useVoiceInput({ workspaceId, + getValue: () => editorRef.current.getValue(), + onChange: (value) => editorRef.current.setValue(value), + onUsageLimitExceeded: handleUsageLimitExceeded, }) - const toggleListening = useCallback(() => { - if (!isListening) { - sttPrefixRef.current = editorRef.current.getValue() - } - rawToggle() - }, [isListening, rawToggle]) - const onSendQueuedHeadRef = useRef(onSendQueuedHead) onSendQueuedHeadRef.current = onSendQueuedHead const onEditQueuedTailRef = useRef(onEditQueuedTail) @@ -553,7 +505,6 @@ const UserInputImpl = forwardRef(function UserI /** Empties the text, chips, attachments, transcript, and the saved draft in one step. */ const clearComposer = useCallback(() => { editorRef.current.clear() - sttPrefixRef.current = '' if (draftSaveTimerRef.current !== null) { window.clearTimeout(draftSaveTimerRef.current) draftSaveTimerRef.current = null @@ -758,10 +709,7 @@ const UserInputImpl = forwardRef(function UserI {files.isDragging && } - + ) }) diff --git a/apps/sim/hooks/use-speech-to-text.ts b/apps/sim/hooks/use-speech-to-text.ts index f1a1d8986c8..cf7e3bf90fd 100644 --- a/apps/sim/hooks/use-speech-to-text.ts +++ b/apps/sim/hooks/use-speech-to-text.ts @@ -50,6 +50,8 @@ interface UseSpeechToTextProps { onError?: (error: SpeechToTextError) => void /** Attributes the voice-input cost to this workspace for per-member usage. */ workspaceId?: string + /** Attributes organization chat and search voice input to the organization. */ + organizationId?: string } interface UseSpeechToTextReturn { @@ -89,6 +91,7 @@ export function useSpeechToText({ onUsageLimitExceeded, onError, workspaceId, + organizationId, }: UseSpeechToTextProps): UseSpeechToTextReturn { const [isListening, setIsListening] = useState(false) /** @@ -108,6 +111,7 @@ export function useSpeechToText({ const onUsageLimitExceededRef = useRef(onUsageLimitExceeded) const onErrorRef = useRef(onError) const workspaceIdRef = useRef(workspaceId) + const organizationIdRef = useRef(organizationId) const mountedRef = useRef(true) const startingRef = useRef(false) @@ -128,6 +132,7 @@ export function useSpeechToText({ onUsageLimitExceededRef.current = onUsageLimitExceeded onErrorRef.current = onError workspaceIdRef.current = workspaceId + organizationIdRef.current = organizationId const flushAudioBuffer = useCallback(() => { const ws = wsRef.current @@ -213,7 +218,9 @@ export function useSpeechToText({ let tokenData: Awaited>> try { tokenData = await requestJson(speechTokenContract, { - body: workspaceIdRef.current ? { workspaceId: workspaceIdRef.current } : {}, + body: organizationIdRef.current + ? { organizationId: organizationIdRef.current } + : { workspaceId: workspaceIdRef.current }, }) } catch (err) { if (isApiClientError(err) && err.status === 402) { diff --git a/apps/sim/hooks/use-voice-input.test.tsx b/apps/sim/hooks/use-voice-input.test.tsx new file mode 100644 index 00000000000..f3b40a6528b --- /dev/null +++ b/apps/sim/hooks/use-voice-input.test.tsx @@ -0,0 +1,144 @@ +/** @vitest-environment jsdom */ +import { act } from 'react' +import { createRoot, type Root } from 'react-dom/client' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type { useSpeechToText } from '@/hooks/use-speech-to-text' + +const mocks = vi.hoisted(() => ({ speech: vi.fn() })) +vi.mock('@/hooks/use-speech-to-text', () => ({ useSpeechToText: mocks.speech })) + +import { useVoiceInput } from '@/hooks/use-voice-input' + +let root: Root +let container: HTMLDivElement +let value: string +let voice: ReturnType + +function Harness() { + voice = useVoiceInput({ + organizationId: 'organization-a', + getValue: () => value, + onChange: (next) => { + value = next + }, + }) + return null +} + +function transcript(text: string) { + act(() => mocks.speech.mock.calls.at(-1)![0].onTranscript(text)) +} + +beforeEach(() => { + vi.clearAllMocks() + vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true) + mocks.speech.mockReturnValue({ + isListening: false, + isSupported: true, + audioLevelsRef: { current: new Float32Array(5) }, + toggleListening: vi.fn(), + resetTranscript: vi.fn(), + }) + value = 'Find' + container = document.createElement('div') + document.body.appendChild(container) + root = createRoot(container) + act(() => root.render()) + act(() => voice.toggleListening()) +}) + +afterEach(() => { + act(() => root.unmount()) + container.remove() + vi.unstubAllGlobals() +}) + +describe('voice input manual edits', () => { + it('preserves edits made before the first transcript arrives', () => { + value = 'Summarize' + transcript('the report') + expect(value).toBe('Summarize the report') + }) + + it('preserves a changed prefix while updating partial speech', () => { + transcript('the repor') + value = 'Summarize the repor' + transcript('the report') + expect(value).toBe('Summarize the report') + transcript('the report from June') + expect(value).toBe('Summarize the report from June') + }) + + it.each(['Replacement draft', ''])( + 'preserves a replaced or cleared draft (%s)', + (replacement) => { + transcript('the report') + value = replacement + transcript('the report') + expect(value).toBe(replacement) + transcript('the report from June') + expect(value).toBe(replacement ? `${replacement} from June` : 'from June') + } + ) + + it('preserves corrections inside dictated text across later partial updates', () => { + transcript('the red report') + value = 'Find the blue report' + transcript('the red report from June') + expect(value).toBe('Find the blue report from June') + transcript('the red report from July') + expect(value).toBe('Find the blue report from July') + }) + + it('keeps manual suffixes after speech revisions and before new speech', () => { + transcript('the red report') + value += ' and notes' + transcript('the blue report') + expect(value).toBe('Find the blue report and notes') + transcript('the blue report from June') + expect(value).toBe('Find the blue report and notes from June') + }) + + it('prefers the manual correction when speech revises the same word', () => { + value = '' + act(() => voice.toggleListening()) + transcript('hel') + value = 'help' + transcript('hello') + expect(value).toBe('help') + transcript('hello again') + expect(value).toBe('help again') + }) + + it('keeps appended speech when another revision conflicts with a manual correction', () => { + transcript('the red report') + value = 'Find the blue report' + transcript('the green report from June') + expect(value).toBe('Find the blue report from June') + transcript('the green report from June and July') + expect(value).toBe('Find the blue report from June and July') + }) + + it('preserves separate manual edits around an independently revised word', () => { + transcript('the red report') + value = 'Summarize the red report and notes' + transcript('the green report from June') + expect(value).toBe('Summarize the green report and notes from June') + }) + + it('starts fresh after the draft and transcript are cleared on submit', () => { + transcript('the report') + value = '' + act(() => voice.resetTranscript()) + transcript('Next question') + expect(value).toBe('Next question') + }) + + it('continues dictation after a large draft is manually replaced', () => { + const longTranscript = Array.from({ length: 300 }, (_, index) => `word${index}`).join(' ') + transcript(longTranscript) + value = 'New draft' + transcript(`${longTranscript} next question`) + expect(value).toBe('New draft next question') + }) +}) diff --git a/apps/sim/hooks/use-voice-input.ts b/apps/sim/hooks/use-voice-input.ts new file mode 100644 index 00000000000..694490d45db --- /dev/null +++ b/apps/sim/hooks/use-voice-input.ts @@ -0,0 +1,160 @@ +'use client' + +import { useCallback, useRef, useState } from 'react' +import { toast } from '@sim/emcn' +import { diffWordsWithSpace } from 'diff' +import { getDesktopBridge } from '@/lib/desktop' +import { type SpeechToTextError, useSpeechToText } from '@/hooks/use-speech-to-text' + +interface UseVoiceInputProps { + workspaceId?: string + organizationId?: string + getValue: () => string + onChange: (value: string) => void + onUsageLimitExceeded?: (message?: string, isMemberLimit?: boolean) => void +} + +interface TextEdit { + from: number + to: number + insert: string +} + +function textChanges(before: string, after: string): TextEdit[] { + const parts = diffWordsWithSpace(before, after, { maxEditLength: 256 }) + if (!parts) return [{ from: 0, to: before.length, insert: after }] + const edits: TextEdit[] = [] + let position = 0 + let edit: TextEdit | undefined + for (const part of parts) { + if (part.added || part.removed) { + edit ??= { from: position, to: position, insert: '' } + if (part.added) edit.insert += part.value + if (part.removed) { + position += part.value.length + edit.to = position + } + } else { + if (edit) edits.push(edit) + edit = undefined + position += part.value.length + } + } + if (edit) edits.push(edit) + return edits +} + +/** Rebase independent speech updates around manual edits; the user's text wins conflicts. */ +function mergeTranscript(previous: string, next: string, current: string): string { + if (current === previous) return next + if (next === previous) return current + + const speechEdits = textChanges(previous, next) + const manualEdits = textChanges(previous, current) + let result = current + for (const speech of speechEdits.reverse()) { + let offset = 0 + let conflict = false + for (const edit of manualEdits) { + if (speech.to <= edit.from && speech.from < edit.from) continue + if (speech.from >= edit.to && (speech.from > edit.from || /^\s/.test(speech.insert))) { + offset += edit.insert.length - (edit.to - edit.from) + } else { + conflict = true + break + } + } + if (!conflict) { + result = + result.slice(0, speech.from + offset) + speech.insert + result.slice(speech.to + offset) + } + } + return current ? result : result.trimStart() +} + +/** Shares draft appending and microphone recovery across chat and search inputs. */ +export function useVoiceInput({ + workspaceId, + organizationId, + getValue, + onChange, + onUsageLimitExceeded = (message) => toast.error(message || 'You are out of credits.'), +}: UseVoiceInputProps) { + const prefixRef = useRef('') + const previousTranscriptValueRef = useRef('') + const getValueRef = useRef(getValue) + getValueRef.current = getValue + const [permissionHelpOpen, setPermissionHelpOpen] = useState(false) + + function handleSpeechError(error: SpeechToTextError) { + if (error === 'microphone-blocked') { + const desktopBridge = getDesktopBridge() + if (desktopBridge) { + const { openMicrophoneSettings } = desktopBridge + toast.error( + 'Microphone access is blocked. Allow Sim to use the microphone in your system privacy settings.', + openMicrophoneSettings + ? { + action: { + label: 'Open Settings', + onClick: () => void openMicrophoneSettings(), + }, + } + : undefined + ) + } else { + toast.error('Microphone access is blocked. Allow it for this site and try again.', { + action: { + label: 'Show steps', + onClick: () => setPermissionHelpOpen(true), + }, + }) + } + return + } + if (error === 'microphone-unavailable') { + toast.error('No microphone found. Connect one and try again.') + return + } + toast.error('Could not start voice input. Try again.') + } + + const { + toggleListening: rawToggle, + resetTranscript: rawReset, + ...speech + } = useSpeechToText({ + workspaceId, + organizationId, + onTranscript: (text) => { + const next = prefixRef.current ? `${prefixRef.current} ${text}` : text + const value = mergeTranscript(previousTranscriptValueRef.current, next, getValueRef.current()) + previousTranscriptValueRef.current = next + onChange(value) + }, + onUsageLimitExceeded, + onError: handleSpeechError, + }) + + const toggleListening = useCallback(() => { + if (!speech.isListening) { + prefixRef.current = getValueRef.current() + previousTranscriptValueRef.current = prefixRef.current + } + rawToggle() + }, [speech.isListening, rawToggle]) + + const resetTranscript = useCallback(() => { + prefixRef.current = '' + previousTranscriptValueRef.current = '' + rawReset() + }, [rawReset]) + + return { + ...speech, + toggleListening, + resetTranscript, + permissionHelpOpen, + setPermissionHelpOpen, + } +} diff --git a/apps/sim/lib/api/contracts/media/speech.ts b/apps/sim/lib/api/contracts/media/speech.ts index 79c2918ad6b..cfde9a08a64 100644 --- a/apps/sim/lib/api/contracts/media/speech.ts +++ b/apps/sim/lib/api/contracts/media/speech.ts @@ -1,16 +1,14 @@ import { z } from 'zod' +import { resourceOwnerSchema } from '@/lib/api/contracts/primitives' import { defineRouteContract } from '@/lib/api/contracts/types' -export const speechTokenBodySchema = z - .object({ - /** Workspace the session user is recording in. */ - workspaceId: z.string().optional(), - }) - .passthrough() +export const speechTokenBodySchema = resourceOwnerSchema +export type SpeechTokenBody = z.input export const speechTokenResponseSchema = z.object({ token: z.string(), }) +export type SpeechTokenResponse = z.output export const speechTokenContract = defineRouteContract({ method: 'POST', diff --git a/apps/sim/lib/speech/application/create-token.ts b/apps/sim/lib/speech/application/create-token.ts new file mode 100644 index 00000000000..a9f09027186 --- /dev/null +++ b/apps/sim/lib/speech/application/create-token.ts @@ -0,0 +1,155 @@ +import { createHash } from 'node:crypto' +import type { Principal } from '@sim/auth/principal' +import { createLogger } from '@sim/logger' +import { z } from 'zod' +import { + type BillingAttributionSnapshot, + checkAttributedUsageLimits, + resolveBillingAttribution, + resolveOrganizationBillingAttribution, + toBillingContext, +} from '@/lib/billing/core/billing-attribution' +import { recordUsage } from '@/lib/billing/core/usage-log' +import { checkAndBillPayerOverageThreshold } from '@/lib/billing/threshold-billing' +import { defineAuthorizedWorkspaceUseCase } from '@/lib/core/application/authorized-workspace-use-case' +import { authorizeOrganizationOperation } from '@/lib/core/application/organization-authorization' +import { defineOrganizationOperation } from '@/lib/core/application/organization-operation' +import { requireAllowedWorkspacePrincipal } from '@/lib/core/application/workspace-authorization' +import { defineWorkspaceOperation } from '@/lib/core/application/workspace-operation' +import { env } from '@/lib/core/config/env' +import { getCostMultiplier } from '@/lib/core/config/env-flags' +import { type ResourceOwner, resourceScopeFromOwner } from '@/lib/core/resource-scope' +import { resolveActiveWorkspaceApplicationContext } from '@/lib/workspaces/application/workspace-context' + +const logger = createLogger('SpeechToken') +const ELEVENLABS_TOKEN_URL = 'https://api.elevenlabs.io/v1/single-use-token/realtime_scribe' +const VOICE_SESSION_COST_PER_MIN = 0.008 +const VOICE_SESSION_MAX_MINUTES = 3 +const providerTokenSchema = z.object({ token: z.string().min(1) }) +const providerErrorSchema = z.object({ + detail: z.string().optional(), + message: z.string().optional(), +}) + +/** + * permission-group-exempt: Voice dictation is an input aid shared across product surfaces. + */ +export const speechTokenOperation = defineWorkspaceOperation({ + id: 'speech.token.create', + minimumRole: 'read', + workspaceApiKey: 'deny', + principalKinds: ['session'], + capability: 'none', +}) + +/** + * permission-group-exempt: Voice dictation is an input aid shared across product surfaces. + */ +const organizationSpeechTokenOperation = defineOrganizationOperation({ + id: 'speech.token.create', + minimumRole: 'member', + principalKinds: ['session'], + capability: 'none', +}) + +export class SpeechTokenError extends Error { + constructor( + readonly reason: 'usage_limit' | 'unconfigured' | 'provider_failed', + message: string, + readonly scope?: 'actor' | 'payer' | 'member' + ) { + super(message) + this.name = 'SpeechTokenError' + } +} + +async function issueSpeechToken( + actorUserId: string, + billingAttribution: BillingAttributionSnapshot +) { + /** Admission remains bounded by the per-user token bucket; billing has no reservation primitive. */ + const usageCheck = await checkAttributedUsageLimits(billingAttribution) + if (usageCheck.isExceeded) { + throw new SpeechTokenError( + 'usage_limit', + usageCheck.message || 'Usage limit exceeded. Please upgrade your plan to continue.', + usageCheck.scope + ) + } + + const apiKey = env.ELEVENLABS_API_KEY + if (!apiKey?.trim()) { + throw new SpeechTokenError('unconfigured', 'Speech-to-text service is not configured') + } + + const response = await fetch(ELEVENLABS_TOKEN_URL, { + method: 'POST', + headers: { 'xi-api-key': apiKey }, + }) + if (!response.ok) { + const error = providerErrorSchema.safeParse(await response.json().catch(() => ({}))) + const message = + (error.success && (error.data.detail || error.data.message)) || + `Token request failed (${response.status})` + logger.error('ElevenLabs token request failed', { status: response.status, message }) + throw new SpeechTokenError('provider_failed', message) + } + + const { token } = providerTokenSchema.parse(await response.json()) + try { + await recordUsage({ + userId: actorUserId, + ...(billingAttribution.workspaceId ? { workspaceId: billingAttribution.workspaceId } : {}), + ...toBillingContext(billingAttribution), + entries: [ + { + category: 'fixed', + source: 'voice-input', + description: `Voice input session (${VOICE_SESSION_MAX_MINUTES} min)`, + cost: VOICE_SESSION_COST_PER_MIN * VOICE_SESSION_MAX_MINUTES * getCostMultiplier(), + sourceReference: `voice-input:${createHash('sha256').update(token).digest('hex')}`, + }, + ], + }) + await checkAndBillPayerOverageThreshold(billingAttribution.billingEntity) + } catch (error) { + logger.warn('Failed to record voice input usage, continuing:', error) + } + return { token } +} + +const createWorkspaceSpeechToken = defineAuthorizedWorkspaceUseCase({ + operation: speechTokenOperation, + resolveContext: ({ input }: { input: { workspaceId: string } }) => + resolveActiveWorkspaceApplicationContext(input.workspaceId), + authorizationOptions: {}, + async execute({ principal, context }) { + const attribution = await resolveBillingAttribution({ + actorUserId: principal.userId, + workspaceId: context.workspaceId, + }) + return issueSpeechToken(principal.userId, attribution) + }, +}) + +/** Issues a metered token under the caller's current workspace or organization membership. */ +export const createSpeechToken = { + operation: speechTokenOperation, + async execute({ principal, input }: { principal: Principal; input: ResourceOwner }) { + requireAllowedWorkspacePrincipal(principal, speechTokenOperation) + const scope = resourceScopeFromOwner(input) + if (scope.kind === 'workspace') { + return createWorkspaceSpeechToken.execute({ principal, input: scope }) + } + const context = await authorizeOrganizationOperation( + principal, + organizationSpeechTokenOperation, + scope + ) + const attribution = await resolveOrganizationBillingAttribution({ + actorUserId: context.userId, + organizationId: context.organizationId, + }) + return issueSpeechToken(context.userId, attribution) + }, +} diff --git a/apps/sim/package.json b/apps/sim/package.json index 35600921107..ec558e036bc 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -175,6 +175,7 @@ "csv-parse": "7.0.2", "date-fns": "4.1.0", "decimal.js": "10.6.0", + "diff": "8.0.4", "docx-preview": "^0.3.7", "docx": "^9.6.1", "drizzle-orm": "^0.45.2", diff --git a/bun.lock b/bun.lock index 3b63e4d5571..848b03f4155 100644 --- a/bun.lock +++ b/bun.lock @@ -290,6 +290,7 @@ "csv-parse": "7.0.2", "date-fns": "4.1.0", "decimal.js": "10.6.0", + "diff": "8.0.4", "docx": "^9.6.1", "docx-preview": "^0.3.7", "drizzle-orm": "^0.45.2", From 3601f58de402bc173f5226fbee40eb89a3dcd000 Mon Sep 17 00:00:00 2001 From: Waleed Date: Thu, 10 Sep 2026 16:09:51 -0700 Subject: [PATCH 05/25] feat(search): unify source setup and organization usage (#7735) * fix(search): streamline Atlassian source setup * fix(search): validate Atlassian keys beyond discovery limits * fix(search): preserve partial Confluence lookup failures * fix(search): remove redundant source account banner * feat(search): unify source setup and organization usage --- apps/docs/content/docs/search/confluence.mdx | 38 +- .../docs/search/connect-your-account.mdx | 8 +- apps/docs/content/docs/search/github.mdx | 20 +- apps/docs/content/docs/search/gitlab.mdx | 10 +- apps/docs/content/docs/search/gmail.mdx | 24 +- .../content/docs/search/google-calendar.mdx | 22 +- .../docs/content/docs/search/google-drive.mdx | 26 +- apps/docs/content/docs/search/index.mdx | 46 +- apps/docs/content/docs/search/jira.mdx | 40 +- apps/docs/content/docs/search/slack.mdx | 12 +- .../search/confluence-personal-setup.png | Bin 0 -> 68053 bytes .../public/static/search/confluence-setup.png | Bin 45456 -> 0 bytes .../static/search/github-indexing-options.jpg | Bin 17946 -> 0 bytes .../public/static/search/github-setup.jpg | Bin 31061 -> 0 bytes .../public/static/search/gitlab-options.jpg | Bin 47941 -> 0 bytes .../public/static/search/gitlab-setup.jpg | Bin 35088 -> 0 bytes .../static/search/google-drive-setup.jpg | Bin 22911 -> 0 bytes .../static/search/google-drive-setup.png | Bin 0 -> 59707 bytes .../static/search/integration-provider.jpg | Bin 21510 -> 0 bytes .../static/search/integration-provider.png | Bin 0 -> 37791 bytes .../static/search/integration-settings.jpg | Bin 32832 -> 0 bytes .../static/search/integration-settings.png | Bin 0 -> 118870 bytes .../static/search/jira-personal-setup.png | Bin 0 -> 66834 bytes apps/docs/public/static/search/jira-setup.png | Bin 58681 -> 0 bytes .../public/static/search/source-settings.jpg | Bin 37543 -> 0 bytes .../sim-search/personal-source-setup/route.ts | 70 + .../api/knowledge/sim-search/stats/route.ts | 24 + .../integrations/connect-account-options.tsx | 1 + .../integrations/integrations.test.tsx | 5 +- .../add-organization-source-modal.tsx | 106 + ...rganization-integrations-settings.test.tsx | 166 +- .../organization-integrations-settings.tsx | 94 +- .../organization-integrations-setup.test.tsx | 351 +- .../organization-integrations-setup.tsx | 260 +- .../organization-search-stats-period.test.tsx | 127 + .../organization-search-stats-period.tsx | 89 + .../organization-search-status.test.ts | 6 +- .../organization-search-status.ts | 6 +- .../organization-source-people.tsx | 79 + .../organization-source-stats.test.tsx | 152 + .../organization-source-stats.tsx | 227 + .../components/integrations/search-params.ts | 17 +- .../integrations/slack-account-removal.tsx | 4 +- .../integrations/slack-account-setup.test.tsx | 53 +- .../integrations/slack-account-setup.tsx | 39 +- .../providers/[connectorType]/page.test.tsx | 146 +- .../providers/[connectorType]/page.tsx | 28 +- .../[connectorType]/provider-detail.test.tsx | 262 +- .../[connectorType]/provider-detail.tsx | 180 +- .../[connectorId]/source-detail.test.tsx | 40 +- .../sources/[connectorId]/source-detail.tsx | 37 +- .../search-integration-connection.tsx | 13 +- .../atlassian-source-setup-modal.test.tsx | 172 + .../atlassian-source-setup-modal.tsx | 241 + .../search-sources/source-setup-modal.tsx | 24 +- .../add-connector-modal.test.tsx | 114 +- .../add-connector-modal.tsx | 52 +- .../connector-access-field.test.tsx | 2 +- .../connector-access-field.tsx | 2 +- .../connector-selector-field.queries.test.tsx | 175 +- .../connector-selector-field.test.tsx | 60 +- .../connector-selector-field.tsx | 175 +- .../connector-selector-field.ui.test.tsx | 179 + .../connectors-section/connector-actions.tsx | 6 +- .../connector-settings-fields.test.tsx | 2 +- .../connector-settings-fields.tsx | 16 +- .../use-connector-config-fields.test.tsx | 34 + .../[id]/hooks/use-connector-config-fields.ts | 34 +- .../components/search-source-pagination.tsx | 2 +- .../components/search-source-setup.test.tsx | 140 +- .../search/components/search-source-setup.tsx | 26 +- apps/sim/components/charts/bar-chart.tsx | 7 +- apps/sim/components/charts/chart-format.ts | 7 +- .../components/charts/chart-geometry.test.ts | 6 + apps/sim/components/charts/chart-geometry.ts | 13 +- .../components/charts/chart-layout.test.tsx | 21 + .../connectors/confluence/bulk-spaces.test.ts | 234 + apps/sim/connectors/confluence/confluence.ts | 189 +- apps/sim/connectors/confluence/meta.ts | 4 +- apps/sim/connectors/jira/meta.ts | 4 +- apps/sim/connectors/types.ts | 4 + .../organization-account-people.tsx | 37 +- .../organization-person-connections.tsx | 86 + .../components/slack-managed-users-modal.tsx | 2 +- .../search-params.ts | 22 + .../queries/organization-accounts.test.tsx | 86 + .../hooks/queries/organization-accounts.ts | 7 +- .../queries/organization-search-stats.ts | 28 + .../hooks/queries/personal-source-setup.ts | 69 + apps/sim/hooks/queries/selectors.test.tsx | 287 +- apps/sim/hooks/queries/selectors.ts | 236 +- .../use-personal-source-account.test.tsx | 153 + apps/sim/hooks/use-personal-source-account.ts | 135 + ...use-search-integration-connection.test.tsx | 14 + .../use-search-integration-connection.ts | 14 + .../knowledge/personal-source-setup.test.ts | 47 + .../knowledge/personal-source-setup.ts | 86 + .../api/contracts/knowledge/search-stats.ts | 76 + .../lib/copilot/request/lifecycle/run.test.ts | 29 + apps/sim/lib/copilot/request/lifecycle/run.ts | 3 + apps/sim/lib/copilot/tool-executor/types.ts | 2 + .../registry/server-tool-adapter.test.ts | 20 + .../tools/registry/server-tool-adapter.ts | 1 + .../sim/lib/copilot/tools/server/base-tool.ts | 2 + .../server/knowledge/knowledge-base.test.ts | 16 + .../tools/server/knowledge/knowledge-base.ts | 2 +- .../server/knowledge/workspace-search.test.ts | 25 + .../server/knowledge/workspace-search.ts | 2 +- apps/sim/lib/credential-groups/service.ts | 2 +- .../knowledge/application/operations.test.ts | 17 + .../lib/knowledge/application/operations.ts | 27 + .../organization-search-stats.test.ts | 82 + .../application/organization-search-stats.ts | 21 + .../personal-search-account.test.ts | 133 + .../application/personal-search-account.ts | 68 + .../application/personal-source-setup.test.ts | 480 + .../application/personal-source-setup.ts | 298 + .../lib/knowledge/application/search.test.ts | 23 + apps/sim/lib/knowledge/application/search.ts | 12 +- .../knowledge/application/sim-search.test.ts | 48 + .../lib/knowledge/application/sim-search.ts | 32 +- .../slack-search/assistant.test.ts | 1 + .../application/slack-search/assistant.ts | 1 + .../workspace-search.activity.test.ts | 144 + .../knowledge/application/workspace-search.ts | 38 +- .../lib/knowledge/search/activity-stats.ts | 100 + .../sim/lib/knowledge/search/activity.test.ts | 98 + apps/sim/lib/knowledge/search/activity.ts | 38 + apps/sim/lib/knowledge/search/stats.test.ts | 97 + apps/sim/lib/knowledge/search/stats.ts | 74 + .../application/execute-selector.test.ts | 108 + .../selectors/application/execute-selector.ts | 41 +- .../lib/selectors/server/credentials.test.ts | 86 + apps/sim/lib/selectors/server/credentials.ts | 54 + .../server/providers/confluence.test.ts | 148 +- .../selectors/server/providers/confluence.ts | 16 +- .../providers/credential-bundle.test.ts | 45 + .../server/providers/credential-bundle.ts | 15 +- .../selectors/server/providers/jira.test.ts | 14 +- .../lib/selectors/server/providers/jira.ts | 5 +- apps/sim/lib/selectors/server/types.ts | 5 + apps/sim/lib/selectors/types.ts | 7 + apps/sim/lib/sim-search/connection-labels.ts | 71 + .../lib/sim-search/personal-source-setup.ts | 2 + .../0338_organization_search_activity.sql | 16 + .../db/migrations/meta/0338_snapshot.json | 26162 ++++++++++++++++ packages/db/migrations/meta/_journal.json | 7 + packages/db/schema.ts | 31 + .../components/combobox/combobox.dom.test.tsx | 22 + .../emcn/src/components/combobox/combobox.tsx | 35 +- packages/emcn/src/components/index.ts | 1 + packages/testing/src/mocks/schema.mock.ts | 9 + 152 files changed, 33702 insertions(+), 1292 deletions(-) create mode 100644 apps/docs/public/static/search/confluence-personal-setup.png delete mode 100644 apps/docs/public/static/search/confluence-setup.png delete mode 100644 apps/docs/public/static/search/github-indexing-options.jpg delete mode 100644 apps/docs/public/static/search/github-setup.jpg delete mode 100644 apps/docs/public/static/search/gitlab-options.jpg delete mode 100644 apps/docs/public/static/search/gitlab-setup.jpg delete mode 100644 apps/docs/public/static/search/google-drive-setup.jpg create mode 100644 apps/docs/public/static/search/google-drive-setup.png delete mode 100644 apps/docs/public/static/search/integration-provider.jpg create mode 100644 apps/docs/public/static/search/integration-provider.png delete mode 100644 apps/docs/public/static/search/integration-settings.jpg create mode 100644 apps/docs/public/static/search/integration-settings.png create mode 100644 apps/docs/public/static/search/jira-personal-setup.png delete mode 100644 apps/docs/public/static/search/jira-setup.png delete mode 100644 apps/docs/public/static/search/source-settings.jpg create mode 100644 apps/sim/app/api/knowledge/sim-search/personal-source-setup/route.ts create mode 100644 apps/sim/app/api/knowledge/sim-search/stats/route.ts create mode 100644 apps/sim/app/o/[organizationId]/settings/components/integrations/add-organization-source-modal.tsx create mode 100644 apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period.test.tsx create mode 100644 apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period.tsx create mode 100644 apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-people.tsx create mode 100644 apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-stats.test.tsx create mode 100644 apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-stats.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal.test.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connector-selector-field/connector-selector-field.ui.test.tsx create mode 100644 apps/sim/connectors/confluence/bulk-spaces.test.ts create mode 100644 apps/sim/ee/credential-groups/components/organization-person-connections.tsx create mode 100644 apps/sim/ee/organization-search-stats/search-params.ts create mode 100644 apps/sim/hooks/queries/organization-search-stats.ts create mode 100644 apps/sim/hooks/queries/personal-source-setup.ts create mode 100644 apps/sim/hooks/use-personal-source-account.test.tsx create mode 100644 apps/sim/hooks/use-personal-source-account.ts create mode 100644 apps/sim/lib/api/contracts/knowledge/personal-source-setup.test.ts create mode 100644 apps/sim/lib/api/contracts/knowledge/personal-source-setup.ts create mode 100644 apps/sim/lib/api/contracts/knowledge/search-stats.ts create mode 100644 apps/sim/lib/knowledge/application/organization-search-stats.test.ts create mode 100644 apps/sim/lib/knowledge/application/organization-search-stats.ts create mode 100644 apps/sim/lib/knowledge/application/personal-search-account.test.ts create mode 100644 apps/sim/lib/knowledge/application/personal-search-account.ts create mode 100644 apps/sim/lib/knowledge/application/personal-source-setup.test.ts create mode 100644 apps/sim/lib/knowledge/application/personal-source-setup.ts create mode 100644 apps/sim/lib/knowledge/application/workspace-search.activity.test.ts create mode 100644 apps/sim/lib/knowledge/search/activity-stats.ts create mode 100644 apps/sim/lib/knowledge/search/activity.test.ts create mode 100644 apps/sim/lib/knowledge/search/activity.ts create mode 100644 apps/sim/lib/knowledge/search/stats.test.ts create mode 100644 apps/sim/lib/knowledge/search/stats.ts create mode 100644 apps/sim/lib/sim-search/connection-labels.ts create mode 100644 apps/sim/lib/sim-search/personal-source-setup.ts create mode 100644 packages/db/migrations/0338_organization_search_activity.sql create mode 100644 packages/db/migrations/meta/0338_snapshot.json diff --git a/apps/docs/content/docs/search/confluence.mdx b/apps/docs/content/docs/search/confluence.mdx index f818dcba9de..8943a97d197 100644 --- a/apps/docs/content/docs/search/confluence.mdx +++ b/apps/docs/content/docs/search/confluence.mdx @@ -31,21 +31,16 @@ Teammates authorize Sim's shared Confluence app, which also requests workflow pe ### Choose Confluence -Open your organization's **Settings → Sources**, turn on **Confluence**, then select **Set up** (or **Manage**) → **Add source**. This opens service-account setup. +Open **Settings → Sources → Add source** and select **Confluence**. This opens **Connect Confluence site** with service-account authentication. To connect another site later, open **Confluence** from the Sources list and select **Add Confluence site**. ### Choose the account and spaces -Under **Indexing account**, select a service account or [add one](#using-a-service-account). Enter the same **Confluence Domain** as the credential, then choose **Spaces**. To enter comma-separated keys such as `ENG, PRODUCT`, use the switch beside the Spaces field. +Under **Service account**, select a service account or [add one](#using-a-service-account). Enter the same **Confluence site** as the credential, then choose **Spaces**. **All** in the dropdown selects every space the account can currently browse; newly created spaces are not added automatically. Clear the picker search before selecting all. -Confluence source setup with a service account, site domain, and spaces +To enter comma-separated keys such as `ENG, PRODUCT`, use the switch beside **Spaces**. Switching between the picker and manual entry keeps your selection. Open **More options** for content type, labels, and metadata tags. The default is **Pages only**; choose **All content** to include blog posts. @@ -65,9 +60,22 @@ For workspace Search, start from **Search → Add source**. Available methods de ## Connect member accounts -After an admin allows Confluence, open **Integrations → Connect**. If no source exists, enter **Confluence Domain** and **Space Keys**, then connect your account. To use another site or space scope, choose the row labeled **Connect a different site or content scope**. +After an admin allows Confluence, open **Integrations → Connect**. For an existing source, authorize your account; you do not choose its spaces again. + +If no source exists, or you choose **Connect a different site or content scope**: + +1. Under **Your account**, select a saved account or choose **Connect account**. Authorize using the Atlassian email matching your verified Sim email. +2. Enter the hostname under **Atlassian site**, then choose **Spaces**. Use **All** in the dropdown for the complete current list, or **Enter keys manually** for comma-separated keys. You can select up to 1,000 spaces in this form. +3. Select **Connect & Sync**. Sim saves the selected scope and starts indexing with your account. + +Confluence personal source setup with a saved account, Atlassian site, and selected spaces -Admins manage these sources under **Settings → Sources → Confluence → Manage**. An **Account for browsing** populates the space picker; it does not enroll that account for Search. Manual space keys work without a browsing account. +Admins manage these sources under **Settings → Sources → Confluence**. When configuring a member-account connection, an **Account for browsing** populates the space picker; a saved personal Search account can be reused here. Choosing a browsing account does not enroll it for Search. Manual space keys work without a browsing account. ## Using a service account @@ -95,7 +103,7 @@ read:group:confluence Use all 12 scopes for account validation, pickers, content, permissions, and directory reads. Central indexing does not need write scopes. 4. Review and create the token, then copy it. Atlassian shows it only once. -5. In Sim's source form, use **Indexing account** to add a service account. Paste the **API token**, enter **Site domain** (hostname only), and select **Add service account**. Continue in the source form with the same domain. +5. In Sim's source form, use **Service account** to add a service account. Paste the **API token**, enter **Site domain** (hostname only), and select **Add service account**. Continue in the source form with the same domain. -See Atlassian's [account setup](https://support.atlassian.com/user-management/docs/manage-your-service-accounts/) and [token instructions](https://support.atlassian.com/user-management/docs/manage-api-tokens-for-service-accounts/). Scopes do not grant space or page access. To replace an expiring token or change scopes, add a new credential in the source's **Settings**, select **Change indexing account**, and verify a sync before revoking the old token. +See Atlassian's [account setup](https://support.atlassian.com/user-management/docs/manage-your-service-accounts/) and [token instructions](https://support.atlassian.com/user-management/docs/manage-api-tokens-for-service-accounts/). Scopes do not grant space or page access. To replace an expiring token or change scopes, add a new credential in the source's **Settings**, select **Change service account**, and verify a sync before revoking the old token. ## Configuration and indexed content | Setting | What it controls | | --- | --- | -| **Confluence Domain** | Cloud hostname only, such as `your-team.atlassian.net`; omit page URLs and `/wiki`. | +| **Confluence site** | Cloud hostname only, such as `your-team.atlassian.net`; omit page URLs and `/wiki`. | | **Spaces / Space Keys** | Required spaces. The picker and manual input set the same scope. | | **Content Type** | **Pages only** (default), **Blog posts only**, or **All content** for both. | | **Filter by Label** | Optional comma-separated labels; content can match any listed label. | @@ -122,7 +130,7 @@ Search manages the schedule and hides item limits. It indexes published/current Central sources combine space permissions, page and ancestor restrictions, and group membership. Before returning central content, Sim uses your personal connection to check that you still have access to the configured Confluence site. If Atlassian cannot confirm that access, the content is hidden. Member sources use each person's provider listing. Sim admin status does not grant access to all pages, and permission changes take effect after syncing and processing. -Open **Settings → Sources → Confluence → Manage**, then a source's **Documents**, **Settings**, or **Sync history**. Invite teammates through **Settings → Members → Invite** or SSO, then have them connect through **Integrations**. **Accounts → Request connections** only requests a provider connection; it does not invite people to the organization. +Open **Settings → Sources → Confluence**, then a source's **Documents**, **Settings**, or **Sync history**. Invite teammates through **Settings → Members → Invite** or SSO, then have them connect through **Integrations**. **People → Request connections** only requests a provider connection; it does not invite people to the organization. ## Troubleshooting @@ -147,6 +155,6 @@ Configure one shared Confluence OAuth app for teammates' connections: 2. Under **Authorization → OAuth 2.0 (3LO)**, add `https:///api/auth/oauth2/callback/confluence` as a callback. 3. Under **Permissions**, add the Confluence API and its full `confluence` scope list from [Sim's OAuth configuration](https://github.com/simstudioai/sim/blob/staging/apps/sim/lib/oauth/oauth.ts), including `read:group:confluence`. Add **User Identity API → read:me**. Sim requests `offline_access` for refresh tokens; the service-account list above does not replace this shared OAuth scope set. 4. Enable sharing under **Distribution**. Set `CONFLUENCE_CLIENT_ID` and `CONFLUENCE_CLIENT_SECRET` from the app's **Settings**, verify `NEXT_PUBLIC_APP_URL`, and restart Sim. -5. Connect from **Integrations** and select the configured site. After changing the OAuth client or requested scopes, use **Settings → Sources → More → Refresh connection settings**, then have affected teammates reconnect. +5. Connect from **Integrations** and select the configured site. After changing the OAuth client or requested scopes, use **Settings → Sources → More → Update sign-in settings**, then have affected teammates reconnect. The callback must match Sim's scheme, hostname, port, and path exactly. If only the app owner can connect, check **Distribution**. See the [Atlassian OAuth guide](https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/) and [Sim deployment reference](/platform/self-hosting/integrations-oauth). diff --git a/apps/docs/content/docs/search/connect-your-account.mdx b/apps/docs/content/docs/search/connect-your-account.mdx index 7b031e1cf82..bfe41deae8f 100644 --- a/apps/docs/content/docs/search/connect-your-account.mdx +++ b/apps/docs/content/docs/search/connect-your-account.mdx @@ -23,7 +23,7 @@ For a central Google source, use your primary Workspace email and open **Search* ## Open Integrations -Open **Integrations** in the main sidebar, find the provider or source, and select **Connect**. Your first connection may ask for a GitHub repository, Confluence domain and space keys, or Jira domain and project keys. Enter the required fields and select **Connect**. If the provider is missing, ask an organization admin to turn it on under **Settings → Sources**. +Open **Integrations** in the main sidebar, find the provider or source, and select **Connect**. First-time setup can also ask which content to index. For [Confluence](/search/confluence) and [Jira](/search/jira), connect your Atlassian account first, then choose the site and spaces or projects and select **Connect & Sync**. [GitHub](/search/github) asks for a repository. If the provider is missing, ask an organization admin to add it under **Settings → Sources → Add source**. To connect another supported repository, site, or project scope, find the provider row labeled **Connect a different site or content scope** and select **Connect**. Connecting an existing source does not ask you to configure it again. @@ -36,7 +36,7 @@ To connect another supported repository, site, or project scope, find the provid Complete the provider's authorization in the new tab. Choose the account associated with your verified Sim email. The provider may require your organization's SSO or app approval. -The authorization tab closes when the connection completes and Integrations updates. If the tab stays open, return to Integrations. Your account is saved when authorization completes; there is no separate submit step. If the popup was blocked or closed, allow popups and select **Connect** again. While authorization is pending, use **Open again**. +The authorization tab closes when the connection completes and Integrations updates. If the tab stays open, return to Integrations. For an existing source, your account is saved when authorization completes. For first-time Atlassian setup, return to the form, choose your content, and select **Connect & Sync**. If the popup was blocked or closed, allow popups and select **Connect** again. While authorization is pending, use **Open again**. @@ -74,7 +74,7 @@ An account connection request does not invite you into the Sim organization. You On the main **Integrations** page, use **Reconnect** beside an expired connection to renew it. To withdraw an account, open its row's actions menu and select **Disconnect**, then confirm. If several accounts are connected, choose the account to disconnect. Disconnecting stops that account from being used for organization indexing and workflows, and removes Search access that depends on it. -Admins manage setup from **Settings → Sources**. Select **Manage** beside the integration. Providers with personal connections have **Accounts** and a source list under **Advanced** (Google) or **Sources**. Without personal connections, the source list opens directly. This does not grant the admin access to every document. +Admins manage setup from **Settings → Sources**. Open an integration, then its connection to see **Documents**, **Settings**, and **Sync history**. **People** shows account contributors across integrations and supports filtering by integration. This does not grant the admin access to every document. ## If you get stuck @@ -87,7 +87,7 @@ Admins manage setup from **Settings → Sources**. Select **Manage** beside the | **Verify email** | Verify your Sim email to return to the connection page. Reopen the original link if you are not redirected. | | Expired or cancelled authorization | Return to the original connection page and start again. If the invitation itself expired, ask the admin for a new request. | | Access revoked | Ask the organization admin to restore your account contribution access before reconnecting. | -| Needs admin attention | Ask your admin to open **Settings → Sources**, select **Manage** beside the integration, and open its source or sync configuration to inspect the error. | +| Needs admin attention | Ask your admin to open **Settings → Sources**, select the integration, and open its connection to inspect the error. | Your Sim role does not override document access at the source. Connecting a different account or receiving a Search link does not share someone else's mailbox, private calendar, or restricted documents with you. diff --git a/apps/docs/content/docs/search/github.mdx b/apps/docs/content/docs/search/github.mdx index 9a69063e165..8c3da90651a 100644 --- a/apps/docs/content/docs/search/github.mdx +++ b/apps/docs/content/docs/search/github.mdx @@ -9,7 +9,7 @@ import { Image } from '@/components/ui/image' GitHub Search indexes text files from repositories on `github.com`. An organization admin can install the GitHub App once and use it to index selected repositories. Each person connects their own GitHub account once to search the repositories they can access. Installing the App does not connect teammates or give them the installer's permissions. -Admin setup uses your organization's **Settings → Sources** page. Teammates connect from **Integrations** in the main sidebar. Installation indexing is available for organization Search. For workspace Search, use **Search → Add source** with member accounts or a dedicated user account; **Create & Invite** is the workspace equivalent of **Add source**. +Admin setup uses your organization's **Settings → Sources** page. Teammates connect from **Integrations** in the main sidebar. Installation indexing is available for organization Search. For workspace Search, use **Search → Add source** with member accounts or a dedicated user account. ## Before you start @@ -26,7 +26,7 @@ To connect an installation for central indexing, you must be a Sim organization ### Open GitHub setup -Open **Settings → Sources** and turn on **GitHub**. Select **Set up** (or **Manage** if sources already exist), then **Add source**. +Open **Settings → Sources → Add source** and select **GitHub**. This opens **Add GitHub repository**. Add one repository per connection; to add another, open **GitHub** from the Sources list and select **Add repository**. @@ -35,8 +35,6 @@ Open **Settings → Sources** and turn on **GitHub**. Select **Set up** (or **Ma In **Sync documents with**, choose **Connect GitHub App** to index through an installation: -GitHub source setup with indexing choices for connected members, a GitHub account, or a GitHub App - 1. Select **Connect your GitHub account** if prompted. Finish authorization in the new tab, then return and select **Refresh**. Connect GitHub App dialog requiring a personal GitHub connection to verify manageable installations @@ -55,20 +53,18 @@ Alternatively, leave **Connected members** selected to use members' accounts for ### Choose what to index -Enter **Repository** as `owner/repo`. For installation indexing, it must belong to the installation's account and be included in the repositories granted to the App. Add one source per repository; installing on all repositories does not automatically create sources for them. +Enter **Repository** as `owner/repo`. For installation indexing, it must belong to the installation's account and be included in the repositories granted to the App. Add one connection per repository; installing on all repositories does not automatically add them to Search. Open **More options** if you need a different branch, path or extension filters, or metadata tags. -GitHub repository configuration with branch, path filter, file extensions, and metadata tags - | Field | What to enter | |---|---| -| Repository | `owner/repo`. Add another source for another repository. | +| Repository | `owner/repo`. Use **Add repository** for another repository. | | Branch | Optional. Leave blank to follow the repository's default branch. | | Path Filter | Optional prefix such as `docs/`. | | File Extensions | Optional comma-separated list, such as `.md, .txt, .mdx`. | -**Metadata tags** controls the metadata stored with results. Its defaults are suitable for most sources. Select **Add source** to save the source. +**Metadata tags** controls the metadata stored with results. Its defaults are suitable for most sources. Select **Add repository** to save the connection. @@ -79,9 +75,9 @@ Open **Integrations** in the main sidebar, select **Connect** on the GitHub sour An App installation or dedicated indexing account can start syncing after the source is saved. With **Connected members**, indexing begins after someone connects. Each teammate still connects before searching. An existing GitHub connection in the same Sim organization is reused across its GitHub sources. -Open **Settings → Sources**, select **Manage** beside **GitHub**, then open the source to inspect **Documents**, edit **Settings**, or review **Sync history**. +Open **Settings → Sources**, open **GitHub**, then open the source to inspect **Documents**, edit **Settings**, or review **Sync history**. -Use **GitHub → Accounts → Request connections** to send provider-specific connection requests. These requests do not grant organization membership. For another repository, add another source; members can also select **Connect** beside the GitHub row labeled **Connect a different site or content scope** in Integrations. +Use **Settings → Sources → People**, filter by **GitHub**, then select **Request connections** to send provider-specific connection requests. These requests do not grant organization membership. For another repository, add another source; members can also select **Connect** beside the GitHub row labeled **Connect a different site or content scope** in Integrations. @@ -106,7 +102,7 @@ This is an installation plus personal authorization flow. GitHub Search does not | Identity verification fails | Verify the email used by your Sim account in GitHub's email settings, then reconnect. A public profile email alone is insufficient. | | Authorization fails after installation | Return to Sim and start **Connect** there. Do not enable authorization during installation. | | Account authorization did not complete | Start the connection again from Sim. If it repeats, contact your organization admin or Sim support. For self-hosted Sim, check the [App callback and credentials](/platform/self-hosting/integrations-oauth#github-search). | -| GitHub asks for a provider configuration update | An organization admin selects **Settings → Sources → More → Refresh connection settings**, then affected users reconnect GitHub. | +| GitHub asks for a provider configuration update | An organization admin selects **Settings → Sources → More → Update sign-in settings**, then affected users reconnect GitHub. | | Indexed files no longer appear | Confirm your own repository access, App repository selection, and connection status. Installation-indexed content is also withheld when GitHub cannot verify current access; retry once GitHub is available. | | Sync is incomplete | Review the source status. Very large Git trees, file size limits, and unreadable files can limit indexing. | | Empty repository returns an error | Add an initial commit, then sync again. GitHub does not return a file tree for an uninitialized repository. | diff --git a/apps/docs/content/docs/search/gitlab.mdx b/apps/docs/content/docs/search/gitlab.mdx index 39fb464de65..45f91816db9 100644 --- a/apps/docs/content/docs/search/gitlab.mdx +++ b/apps/docs/content/docs/search/gitlab.mdx @@ -9,8 +9,6 @@ import { Image } from '@/components/ui/image' GitLab Search uses an administrator connection to sync a project's content and permissions. Teammates do not connect individual GitLab accounts. They sign in to the Sim organization with a verified email matching their confirmed primary GitLab email. -GitLab source setup in Sim Search - Admin setup uses your organization's **Settings → Sources** page. Teammates do not need a personal GitLab connection. For workspace Search, use **Search → Add source** instead. ## Before you start @@ -49,12 +47,12 @@ The token must read the project, users, inherited project membership, instance s ### Configure the source in Sim -Open **Settings → Sources** and turn on **GitLab**. Select **Set up** (or **Manage** if sources already exist), then **Add source**. Paste the **Personal Access Token**, enter your **Host** and **Project**, and choose the content to index. +Open **Settings → Sources → Add source** and select **GitLab**. This opens **Add GitLab project**. Add one project per connection; to add another, open **GitLab** from the Sources list and select **Add project**. Paste the **Personal Access Token**, enter your **Host** and **Project**, and choose the content to index. | Field | What to enter | |---|---| | Host | Your self-managed domain, such as `gitlab.example.com`. | -| Project | `group/project` or the numeric project ID. Add another source for another project. | +| Project | `group/project` or the numeric project ID. Use **Add project** for another project. | | Content | Defaults to **Wiki & Issues**. Choose **Code, Wiki, Issues & Merge Requests** to include all supported types. | | Branch | Optional branch or tag for repository files; blank uses the project's default branch. | | Path Filter / File Extensions | Optional limits for repository files. | @@ -63,8 +61,6 @@ Open **Settings → Sources** and turn on **GitLab**. Select **Set up** (or **Ma **More options** contains the repository and issue filters, **Max Items**, and **Metadata tags**. Unlike member-account sources, GitLab retains this optional item limit. -GitLab source setup with More options expanded for repository and issue filters, item limit, and metadata tags - Select **Connect & Sync**. Sim validates the token and source policy, then starts indexing. @@ -74,7 +70,7 @@ Select **Connect & Sync**. Sim validates the token and source policy, then start Invite teammates to the Sim organization using their verified work email. Sim matches that email against their confirmed primary GitLab email and applies project, feature, and confidential-issue permissions. Confirmed secondary addresses are not matched. No GitLab **Connect** step is required. -Admins open **Settings → Sources**, select **Manage** beside **GitLab**, then open the source to inspect **Documents**, edit **Settings**, or review **Sync history**. GitLab has no personal **Accounts** tab. Permission and membership changes are picked up during background refreshes. +Admins open **Settings → Sources**, open **GitLab**, then open the source to inspect **Documents**, edit **Settings**, or review **Sync history**. Permission and membership changes are picked up during background refreshes. diff --git a/apps/docs/content/docs/search/gmail.mdx b/apps/docs/content/docs/search/gmail.mdx index b4ce9e2e53f..990e806d51f 100644 --- a/apps/docs/content/docs/search/gmail.mdx +++ b/apps/docs/content/docs/search/gmail.mdx @@ -9,7 +9,7 @@ import { Image } from '@/components/ui/image' Search email threads from your Gmail account. Members can connect their own accounts, or an administrator can index Google Workspace mailboxes with a service account. In either case, each mailbox stays private to its owner. -Admin setup uses your organization's **Settings → Sources** page. Teammates connect from **Integrations** in the main sidebar. For workspace Search, use **Search → Add source** instead; **Create & Invite** is the workspace equivalent of **Add source**. +Admin setup uses your organization's **Settings → Sources** page. Teammates connect from **Integrations** in the main sidebar. For workspace Search, use **Search → Add source** instead. ## Choose your setup @@ -29,34 +29,34 @@ Central indexing does not make email searchable by the administrator, other reci ### Allow Gmail -Open **Settings → Sources** and turn on **Gmail**. This allows personal connections; it does not connect anyone's account. +An admin selects **Settings → Sources → Add source → Gmail**, chooses **Sync using → Member accounts**, sets any filters, and selects **Set up member accounts**. ### Connect your account -Join the Sim organization, then open **Integrations** and select **Connect** beside Gmail. Authorize the Google account matching your verified Sim email. The first connection creates the default sync configuration: the last 6 months across all labels, excluding Promotions, Social, Spam, and Trash. Return to Integrations to see indexing status and your searchable document count. +Join the Sim organization, then open **Integrations** and select **Connect** beside Gmail. Authorize the Google account matching your verified Sim email. The default filters cover the last 6 months across all labels, excluding Promotions, Social, Spam, and Trash. Return to Integrations to see indexing status and your searchable document count. ### Adjust filters if needed -An admin selects **Manage** beside Gmail in **Settings → Sources**, opens **Advanced**, then selects the configuration's **Settings** tab. Change **Labels**, **Date Range**, or other filters and save. +An admin opens **Settings → Sources → Gmail**, selects the connection, then selects the connection's **Settings** tab. Change **Labels**, **Date Range**, or other filters and save. -One member-account configuration is usually enough. Its filters apply to all active Gmail connections, including accounts connected later. It does not assign different filters to selected people or let teammates search each other's mail. **Add sync configuration** opens the [central service-account setup](#set-up-a-central-service-account); it does not edit this member configuration. +One member-account connection is usually enough. Its filters apply to all active Gmail connections, including accounts connected later. It does not assign different filters to selected people or let teammates search each other's mail. **Connect service account** opens the [central service-account setup](#set-up-a-central-service-account); it does not edit this member connection. -Configurations are additive: a narrower one does not restrict an existing broader one, and overlapping configurations can index the same thread more than once. For one organization-wide policy, edit the existing configuration. +Connections are additive: a narrower one does not restrict an existing broader one, and overlapping connections can index the same thread more than once. For one organization-wide policy, edit the existing connection. -Admins can request member connections from **Manage → Accounts → Request connections**. These requests do not invite recipients to the Sim organization. See [Connect your account](/search/connect-your-account) for the shared connection and recovery steps. +Admins can request member connections from **Settings → Sources → People → Request connections** (filter by the integration first). These requests do not invite recipients to the Sim organization. See [Connect your account](/search/connect-your-account) for the shared connection and recovery steps. ## Set up a central service account -Open **Settings → Sources**, enable **Gmail**, and select **Manage → Advanced → Add sync configuration**. If personal connections are disabled for your organization, select **Add source** from the provider page instead. +Open **Settings → Sources → Add source** and select **Gmail**. This opens **Connect Gmail service account**. To add another connection later, open **Gmail** from the Sources list and select **Connect service account**. This requires Google Workspace and a Workspace super administrator to authorize delegation. Consumer Gmail accounts cannot use this path. Each selected user must have Gmail enabled. @@ -91,7 +91,7 @@ If your organization requires multi-party approval, another super administrator ### Configure Gmail in Sim -Under **Indexing account**, select **Add service account** and paste the JSON key into **Add Google Service Account**, or select an existing service account. Set **Directory administrator email** to an active Workspace administrator who can read users in the Directory API. This account supplies directory access; each mailbox is read using that mailbox owner's delegated identity. +Under **Service account**, select **Add service account** and paste the JSON key into **Add Google Service Account**, or select an existing service account. Set **Directory administrator email** to an active Workspace administrator who can read users in the Directory API. This account supplies directory access; each mailbox is read using that mailbox owner's delegated identity. Keep the default **Date Range** of **Last 6 months**, or adjust it and **Labels**. Use label names or system IDs such as `INBOX`; custom `Label_…` IDs are mailbox-specific. A label that does not exist in one mailbox simply matches no threads there. @@ -104,9 +104,9 @@ Teammates join the Sim organization with their matching verified primary email. ## Source options -An admin opens **Settings → Sources** and selects **Manage** beside **Gmail** to open its configuration list. Each row shows **Member accounts** or **Service account** beside its sync status. Open a configuration's **Settings** tab to edit its filters, then select **Save**. Filters apply separately to each mailbox in the source. **Documents** shows indexed threads and **Sync history** shows recent runs. +An admin opens **Settings → Sources → Gmail** to open its configuration list. Each row shows **Member accounts** or **Service account** beside its sync status. Open a connection's **Settings** tab to edit its filters, then select **Save**. Filters apply separately to each mailbox in the connection. **Documents** shows indexed threads and **Sync history** shows recent runs. -**Sync using** identifies the configuration's fixed connection method. To replace a central credential, choose another **Indexing account** and select **Change indexing account**. +**Sync using** identifies the configuration's fixed connection method. To replace a central credential, choose another **Service account** and select **Change service account**. | Option | Behavior | | --- | --- | @@ -155,7 +155,7 @@ Member-account connections use the deployment's Google OAuth client below. Centr 1. In [Google Cloud Console](https://console.cloud.google.com/), select your project. Open **APIs & Services → Library**, find **Gmail API**, and enable it. 2. Open **Google Auth platform → Branding**. Select **Get started** if needed, then enter the app name, support email, and contact email. Under **Audience**, use **Internal** only for an app limited to your Google Workspace organization; otherwise use **External** and add test users while testing. Review the app's permissions under **Data Access → Add or remove scopes**, using the current Sim scopes below. Follow Google's [consent and verification guidance](https://developers.google.com/workspace/guides/configure-oauth-consent) for your audience. 3. Open **Google Auth platform → Clients → Create client**. Choose **Web application**, give the client a name, and add the URI below under **Authorized redirect URIs**. If this instance already has a Google client, add this URI to that client instead. See [Google's credential setup](https://developers.google.com/workspace/guides/create-credentials#web-application). -4. Save the client ID and secret as `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`. Set `NEXT_PUBLIC_APP_URL` to the same Sim origin used in the callback, then restart Sim. See [Integrations & OAuth](/platform/self-hosting/integrations-oauth). If you change an existing deployment's OAuth client or scopes, an organization admin selects **Settings → Sources → More → Refresh connection settings**, then affected teammates reconnect. +4. Save the client ID and secret as `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`. Set `NEXT_PUBLIC_APP_URL` to the same Sim origin used in the callback, then restart Sim. See [Integrations & OAuth](/platform/self-hosting/integrations-oauth). If you change an existing deployment's OAuth client or scopes, an organization admin selects **Settings → Sources → More → Update sign-in settings**, then affected teammates reconnect. ```text https:///api/auth/oauth2/callback/google-email diff --git a/apps/docs/content/docs/search/google-calendar.mdx b/apps/docs/content/docs/search/google-calendar.mdx index 37f427a369e..e9ff7efbbf6 100644 --- a/apps/docs/content/docs/search/google-calendar.mdx +++ b/apps/docs/content/docs/search/google-calendar.mdx @@ -9,7 +9,7 @@ import { Image } from '@/components/ui/image' Search meetings and event details available to your Google account. Members can connect personal accounts, or a Google Workspace administrator can configure a central service-account crawl. Both paths keep each person's own view of events separate. -Admin setup uses your organization's **Settings → Sources** page. Teammates connect from **Integrations** in the main sidebar. For workspace Search, use **Search → Add source** instead; **Create & Invite** is the workspace equivalent of **Add source**. +Admin setup uses your organization's **Settings → Sources** page. Teammates connect from **Integrations** in the main sidebar. For workspace Search, use **Search → Add source** instead. ## Choose your setup @@ -29,28 +29,28 @@ These are alternative setup paths. When only a central Calendar source is config ### Allow and connect Google Calendar -An admin opens **Settings → Sources** and turns on **Google Calendar**. Each person joins the Sim organization, opens **Integrations**, selects **Connect** beside Google Calendar, and authorizes the Google account matching their verified Sim email. The first connection creates the default member-account sync configuration. Return to Integrations to see indexing status and your searchable document count. +An admin selects **Settings → Sources → Add source → Google Calendar**, chooses **Sync using → Member accounts**, sets any filters, and selects **Set up member accounts**. Each person joins the Sim organization, opens **Integrations**, selects **Connect** beside Google Calendar, and authorizes the Google account matching their verified Sim email. Return to Integrations to see indexing status and your searchable document count. ### Choose calendars if needed -An admin selects **Manage** beside Google Calendar in **Settings → Sources**, opens **Advanced**, and selects the configuration's **Settings** tab. Leave **Calendars** empty to search each person's primary calendar. To include specific shared calendars, select an **Account for browsing** and choose calendars, or switch to **Calendar IDs** and enter their IDs. +An admin opens **Settings → Sources → Google Calendar**, selects the connection, then opens **Settings**. Leave **Calendars** empty to search each person's primary calendar. To include specific shared calendars, select an **Account for browsing** and choose calendars, or switch to **Calendar IDs** and enter their IDs. **Account for browsing** only helps you choose calendars. It does not connect your account for Search or grant teammates access. -### Save the configuration +### Save the connection -The default date range covers the previous and next 30 days. Save any changes to the existing configuration. Its calendar and date filters apply separately to each connected member's access. **Add sync configuration** opens the [central service-account setup](#set-up-a-central-service-account); it does not edit this member configuration. +The default date range covers the previous and next 30 days. Save any changes to the existing connection. Its calendar and date filters apply separately to each connected member's access. **Connect service account** opens the [central service-account setup](#set-up-a-central-service-account); it does not edit this member connection. -Admins can request member connections from **Manage → Accounts → Request connections**. These requests do not grant organization membership. Connecting Gmail or Drive does not replace the Calendar connection. See [Connect your account](/search/connect-your-account) for the shared connection and recovery steps. +Admins can request member connections from **Settings → Sources → People → Request connections** (filter by the integration first). These requests do not grant organization membership. Connecting Gmail or Drive does not replace the Calendar connection. See [Connect your account](/search/connect-your-account) for the shared connection and recovery steps. `primary` means the connected or impersonated person's main calendar. A calendar selected from the list is a specific calendar ID, even when it is your main calendar. That same ID applies to every selected user, and only users with access to it can search its events. @@ -58,7 +58,7 @@ Admins can request member connections from **Manage → Accounts → Request con ## Set up a central service account -Open **Settings → Sources** and turn on **Google Calendar**. Select **Manage → Advanced → Add sync configuration** to open the central service-account form. If personal connections are disabled for your organization, select **Add source** from the provider page instead. +Open **Settings → Sources → Add source** and select **Google Calendar**. This opens **Connect Google Calendar service account**. To add another connection later, open **Google Calendar** from the Sources list and select **Connect service account**. This requires a Google Workspace customer and a super administrator to authorize domain-wide delegation. Consumer Gmail accounts cannot use this path. @@ -93,7 +93,7 @@ The **Directory administrator email** must be an active Workspace administrator ### Add the credential and choose users -Under **Indexing account**, select **Add service account** or an existing service account. In **Add Google Service Account**, give the credential a name and paste its JSON key. Back in the source form, enter the **Directory administrator email**. +Under **Service account**, select **Add service account** or an existing service account. In **Add Google Service Account**, give the credential a name and paste its JSON key. Back in the source form, enter the **Directory administrator email**. Leave **Calendar IDs** empty for each user's `primary` calendar. To include shared calendars, enter their IDs, optionally alongside `primary`. IDs apply to each selected user who can read that calendar; this does not share calendars or expand anyone's Google access. Central setup uses manual IDs because an administrator's calendar picker would not represent every user's calendars. @@ -106,9 +106,9 @@ Sim verifies Directory access and selected users, then probes one selected user' ## Source options -An admin opens **Settings → Sources** and selects **Manage** beside **Google Calendar** to open its configuration list. Each row shows **Member accounts** or **Service account** beside its sync status. Open a configuration's **Settings** tab to edit its filters, then select **Save**. **Documents** shows indexed events and **Sync history** shows recent runs. +An admin opens **Settings → Sources → Google Calendar** to open its configuration list. Each row shows **Member accounts** or **Service account** beside its sync status. Open a connection's **Settings** tab to edit its filters, then select **Save**. **Documents** shows indexed events and **Sync history** shows recent runs. -**Sync using** identifies the configuration's fixed connection method. To replace a central credential, choose another **Indexing account** and select **Change indexing account**. +**Sync using** identifies the configuration's fixed connection method. To replace a central credential, choose another **Service account** and select **Change service account**. | Option | Behavior | | --- | --- | @@ -153,7 +153,7 @@ The deployment operator configures Google OAuth for member accounts and the memb 1. In [Google Cloud Console](https://console.cloud.google.com/), select your project. Open **APIs & Services → Library**, find **Google Calendar API**, and enable it. 2. Open **Google Auth platform → Branding** and configure the app name and contact details. Under **Audience**, choose **Internal** for your Google Workspace organization only, or **External** for other users. Add test users while an external app is testing. Review **Data Access → Add or remove scopes** using the current Sim scopes below. See Google's [consent and verification guidance](https://developers.google.com/workspace/guides/configure-oauth-consent). 3. Open **Google Auth platform → Clients → Create client**, choose **Web application**, and add the URI below under **Authorized redirect URIs**. Add it to the existing Google client if the instance already uses one. See [Google's credential setup](https://developers.google.com/workspace/guides/create-credentials#web-application). -4. Save the client ID and secret as `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`. Set `NEXT_PUBLIC_APP_URL` to the same Sim origin used in the callback, then restart Sim. See [Integrations & OAuth](/platform/self-hosting/integrations-oauth). If you change an existing deployment's OAuth client or scopes, an organization admin selects **Settings → Sources → More → Refresh connection settings**, then affected teammates reconnect. +4. Save the client ID and secret as `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`. Set `NEXT_PUBLIC_APP_URL` to the same Sim origin used in the callback, then restart Sim. See [Integrations & OAuth](/platform/self-hosting/integrations-oauth). If you change an existing deployment's OAuth client or scopes, an organization admin selects **Settings → Sources → More → Update sign-in settings**, then affected teammates reconnect. ```text https:///api/auth/oauth2/callback/google-calendar diff --git a/apps/docs/content/docs/search/google-drive.mdx b/apps/docs/content/docs/search/google-drive.mdx index 52ecfc4864b..0ba9cb742a2 100644 --- a/apps/docs/content/docs/search/google-drive.mdx +++ b/apps/docs/content/docs/search/google-drive.mdx @@ -9,7 +9,7 @@ import { Image } from '@/components/ui/image' Search Google Docs, Sheets, Slides, and supported files in Drive. Members can connect their own accounts after an admin allows Google Drive, or an admin can configure a central service-account crawl. -Admin setup uses your organization's **Settings → Sources** page. Teammates connect from **Integrations** in the main sidebar. For workspace Search, use **Search → Add source** instead; **Create & Invite** is the workspace equivalent of **Add source**. +Admin setup uses your organization's **Settings → Sources** page. Teammates connect from **Integrations** in the main sidebar. For workspace Search, use **Search → Add source** instead. ## Choose your setup @@ -31,36 +31,36 @@ These are alternative setup paths. When only a central Drive source is configure ### Allow Google Drive -An organization admin opens **Settings → Sources** and turns on **Google Drive**. This allows personal connections; it does not create a source or connect anyone's account. +An admin selects **Settings → Sources → Add source → Google Drive**, chooses **Sync using → Member accounts**, sets any filters, and selects **Set up member accounts**. ### Connect your account -Join the Sim organization, then open **Integrations** and select **Connect** beside Google Drive. Use the Google account matching your verified Sim email. The first personal connection can create a source with default filters. Return to Integrations to see indexing status and your searchable document count. +Join the Sim organization, then open **Integrations** and select **Connect** beside Google Drive. Use the Google account matching your verified Sim email. Return to Integrations to see indexing status and your searchable document count. ### Adjust filters if needed -An admin opens **Settings → Sources**, selects **Manage** beside **Google Drive**, opens **Advanced**, and selects the sync configuration's **Settings** tab. Leave **Folders** empty to include supported files each member can access, or narrow the source to folders. **Account for browsing** helps select folders; manual **Folder IDs** work without it. Browsing does not connect that account to Search. +An admin opens **Settings → Sources → Google Drive**, selects the connection, then opens **Settings**. Leave **Folders** empty to include supported files each member can access, or narrow the source to folders. **Account for browsing** helps select folders; manual **Folder IDs** work without it. Browsing does not connect that account to Search. Keep **Sync documents with → Connected members** unless a dedicated account should fetch content. Members still connect to establish access. If the dedicated account is a delegated service account, **Crawl as** selects the Google Workspace user whose files it fetches. Save the source settings when finished. -Admins can request member connections from **Manage → Accounts → Request connections**. These requests do not grant organization membership. See [Connect your account](/search/connect-your-account) for the shared connection and recovery steps. +Admins can request member connections from **Settings → Sources → People → Request connections** (filter by the integration first). These requests do not grant organization membership. See [Connect your account](/search/connect-your-account) for the shared connection and recovery steps. ## Set up a central service account -Open **Settings → Sources** and turn on **Google Drive**. Select **Manage → Advanced → Add sync configuration** to open the central service-account form directly. If personal connections are disabled for your organization, select **Add source** from the provider page instead. Teammates do not need a personal Drive connection for this source. +Open **Settings → Sources → Add source** and select **Google Drive**. This opens **Connect Google Drive service account**. To add another connection later, open **Google Drive** from the Sources list and select **Connect service account**. This requires a Google Workspace domain and a Workspace super administrator to authorize domain-wide delegation. Consumer Gmail accounts cannot use this path. -Google Drive central source setup with a service account, Directory administrator email, sharing policy, and optional folders +Google Drive setup with member and service-account methods, account selection, and folders @@ -101,7 +101,7 @@ Group permissions require groups and memberships that this administrator can rea ### Add the credential in Sim -Under **Indexing account**, choose **Add service account**, or select an existing service account. Paste the JSON key into **Add Google Service Account**, give it a name, and add it. Sim returns you to the source form with that credential selected. +Under **Service account**, choose **Add service account**, or select an existing service account. Paste the JSON key into **Add Google Service Account**, give it a name, and add it. Sim returns you to the source form with that credential selected. Add Google Service Account credential modal in Sim @@ -112,7 +112,7 @@ Under **Indexing account**, choose **Add service account**, or select an existin Set **Directory administrator email** to the Workspace administrator described above. Under **More options**, leave **Users** blank for everyone, or enter up to 100 primary Workspace email addresses separated by commas. Suspended, archived, and guest accounts are excluded. -Leave **Folders** empty to include supported files each selected user can access. To narrow the source, select folders visible to the Directory administrator or enter **Folder IDs** manually. The same folder filter applies to each selected user and does not grant access. Choose **Connect & Sync**. Sim validates the administrator and any selected users, and probes Drive access for an active user, before accepting the source. +Leave **Folders** empty to include supported files each selected user can access. To narrow the source, select folders visible to the Directory administrator or enter **Folder IDs** manually. The same folder filter applies to each selected user and does not grant access. Choose **Connect & Sync**. Sim validates the administrator and any selected users, and probes Drive access for an active user, before accepting the connection. The crawl pages through each user’s files and shared drives, including shared-drive files the user has never opened. It resumes unfinished work and indexes a shared file once even when several users can access it. A file must be downloadable by at least one selected user to be indexed; the same requirement applies to a shortcut’s target. Sim must also verify its permissions before showing it in Search. Google can let a reader download a file while refusing to list its permissions; include an owner or another user who can read those permissions. Externally owned files can remain hidden when no selected user can verify their permissions. @@ -123,9 +123,9 @@ Teammates join the Sim organization with their matching verified email; they do ## Source options -An admin opens **Settings → Sources** and selects **Manage** beside **Google Drive** to open its configuration list. Each row shows **Member accounts** or **Service account** beside its sync status. Open a configuration's **Settings** tab to edit its filters, then select **Save**. **Documents** shows indexed files and **Sync history** shows recent runs. +An admin opens **Settings → Sources → Google Drive** to open its configuration list. Each row shows **Member accounts** or **Service account** beside its sync status. Open a connection's **Settings** tab to edit its filters, then select **Save**. **Documents** shows indexed files and **Sync history** shows recent runs. -**Sync using** identifies the configuration's fixed connection method. To replace a central credential, choose another **Indexing account** and select **Change indexing account**. +**Sync using** identifies the configuration's fixed connection method. To replace a central credential, choose another **Service account** and select **Change service account**. | Option | Behavior | | --- | --- | @@ -139,7 +139,7 @@ An admin opens **Settings → Sources** and selects **Manage** beside **Google D Sim exports Docs and Slides as text and Sheets as XLSX spreadsheets. Supported uploaded files use the knowledge-base document pipeline, including PDF and Office formats. Unsupported files and oversized exports cannot be indexed; Google limits Workspace exports to 10 MB. See [Drive export formats](https://developers.google.com/workspace/drive/api/guides/ref-export-formats) and [download limits](https://developers.google.com/workspace/drive/api/guides/manage-downloads). -Search schedules syncs hourly. Central crawls revisit the selected users' files and permissions, including unchanged files, so permission changes and a new employee's older files are included. Unfinished crawls resume before deletion reconciliation. Content, deletions, and permissions refresh in the background; results are not a live read from Drive. **Accounts** on the provider page shows personal account connections where configured; it does not list the central service-account credential. +Search schedules syncs hourly. Central crawls revisit the selected users' files and permissions, including unchanged files, so permission changes and a new employee's older files are included. Unfinished crawls resume before deletion reconciliation. Content, deletions, and permissions refresh in the background; results are not a live read from Drive. **People** on the Sources settings page shows personal account connections; it does not list the central service-account credential. ## Troubleshooting @@ -168,7 +168,7 @@ https:///api/auth/oauth2/callback/google-drive This Google Cloud example uses one client for all three services. Replace `https://sim.example.com` with your Sim origin and add only the callbacks for services you enable. -Save the client ID and secret as `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`. Set `NEXT_PUBLIC_APP_URL` to the same Sim origin used in the callback, then restart Sim. See [Integrations & OAuth](/platform/self-hosting/integrations-oauth). If you change an existing deployment's OAuth client or scopes, an organization admin selects **Settings → Sources → More → Refresh connection settings**, then affected teammates reconnect. +Save the client ID and secret as `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`. Set `NEXT_PUBLIC_APP_URL` to the same Sim origin used in the callback, then restart Sim. See [Integrations & OAuth](/platform/self-hosting/integrations-oauth). If you change an existing deployment's OAuth client or scopes, an organization admin selects **Settings → Sources → More → Update sign-in settings**, then affected teammates reconnect. The current Sim Drive OAuth connection uses these scopes: diff --git a/apps/docs/content/docs/search/index.mdx b/apps/docs/content/docs/search/index.mdx index b3b9aa797be..f9203ead4e1 100644 --- a/apps/docs/content/docs/search/index.mdx +++ b/apps/docs/content/docs/search/index.mdx @@ -14,22 +14,18 @@ Search brings your connected sources into one place. An organization admin allow -### Allow an integration +### Choose an integration -As an organization admin, open **Settings → Sources** and turn on the integration. It stays in the list; no setup page opens automatically. - -The switch saves immediately and permits the integration in your organization. It does not connect an account, grant document access, or start indexing. Teammates connect from **Integrations** in the main sidebar; only admins manage these switches. +Open **Settings → Sources → Add source** and choose an integration. Unavailable integrations need deployment configuration before they can be connected. -### Connect or configure the source - -For personal Gmail, Calendar, or Drive, teammates can connect immediately from **Integrations**. The first account creates the default sync configuration. Admins can adjust it later under **Manage → Advanced** on the provider page. +### Connect the content -For other sources, select **Set up** or **Manage**, then **Add source**. For a central Gmail, Calendar, or Drive service account, use **Manage → Advanced → Add sync configuration**. For Slack, complete **Set up Slack app** first. Follow the provider's **Setup guide** to configure its connection and content. **More options** contains secondary filters and **Metadata tags**. +Follow the integration's **Setup guide**. Confluence connects a site and selected spaces; Jira adds projects; GitHub adds a repository; GitLab adds a project; Slack configures its app, then channels or DMs. Google service-account setup connects Drive, Gmail, or Calendar with the selected users and filters. -In the source form, select **Connect & Sync** for a central account or **Add source** for member accounts. Creating a source does not invite people or authorize their accounts. +Select **Connect & Sync** for a central account, or the form’s **Add** or **Set up member accounts** action for member accounts. **More options** contains additional filters. Saving a connection does not invite teammates or authorize their accounts. @@ -41,9 +37,9 @@ For member-account sources, open **Integrations** in the main sidebar and select -Organization Sources settings with provider switches and Set up or Manage actions +Organization Sources with Add source, connection status, People, and Stats -Source availability depends on the deployment and organization policy. An unavailable source needs operator configuration before setup can continue. If an existing provider asks for a configuration update after a deployment change, an admin selects **More → Refresh connection settings** on this page, then affected teammates reconnect. +Source availability depends on the deployment and organization policy. An unavailable source needs operator configuration before setup can continue. If an existing provider asks for a configuration update after a deployment change, an admin selects **More → Update sign-in settings** on this page, then affected teammates reconnect. ## Choose the right connection method @@ -57,7 +53,9 @@ Sources can use member accounts or a central connection. Gmail, Google Calendar, | **Confluence service account** | Connects an account that can read the selected content and its permissions. | Join the organization and connect Confluence to establish identity. | | **Administrator token** (GitLab) | Connects a self-managed instance administrator token and selects projects to index. | Join the organization with a verified Sim email matching GitLab. No personal connection is needed. | -Adding a Google or Confluence source from the admin page opens its central setup form directly. Google providers use **Manage → Advanced → Add sync configuration**; Confluence uses **Set up/Manage → Add source**. For personal connections, use **Integrations → Connect** in the main sidebar. An approved provider can create its first member source there; required repository, site, or project fields are collected before authorization. Admins can edit that source's filters afterward in its **Settings** tab. When personal connections are disabled for the organization, Google providers use **Add source** on the provider page instead of **Advanced**. +Open an integration from the Sources list to manage its connections. Use **Connect service account** for Google, **Add Confluence site**, **Add projects** for Jira, **Add repository** for GitHub, **Add project** for GitLab, or **Add channels or DMs** for Slack. + +For personal connections, teammates use **Integrations → Connect** in the main sidebar after the admin adds the provider. First-time setup may ask you to select content after connecting your account. Admins can edit those connections' filters afterward in **Settings**. Some member sources offer **Sync documents with**, either directly in setup or under **More options**. **Connected members** uses members' accounts for both content and access checks. Selecting a dedicated account uses it to fetch content; members still connect to establish which documents they may search. For GitHub organization sources, choose **Connect GitHub App** in this field to [connect an installation](/search/github#add-a-repository). **Account for browsing** only helps an admin pick source options—it does not enroll that account for Search. @@ -82,9 +80,9 @@ Some member sources offer **Sync documents with**, either directly in setup or u Invite people through the organization's **Settings → Members**, or use your organization's [SSO provisioning](/platform/enterprise/sso). Share the organization's **Home** or **Integrations** URL. People need their own Sim account and organization membership; they do not need access to a workspace. Connecting an external account alone does not grant organization membership. -To request a particular account connection, open **Settings → Sources**, select **Manage** beside the integration (or **Set up** if no sources exist), then **Accounts → Request connections**. This tab is available for providers that support personal connections. If setup is missing, complete the source or Slack app setup shown there first. The list shows organization account contributors and their connection status for that provider. +Open **Settings → Sources → People** to view account contributors and their connection status. Choose an integration in the filter to inspect its connections or send a targeted **Request connections** invitation. **All integrations** shows each person's connected providers and accounts needing reconnection. -These requests are separate from organization invitations. They let recipients contribute an external account; they do not grant Sim organization membership or Search access. **People** on the Sources settings page shows account contributors across providers. See [Connect your account](/search/connect-your-account) for the teammate walkthrough. +Connection requests do not grant organization membership. See [Connect your account](/search/connect-your-account) for the teammate walkthrough. **Revoke all account access** withdraws every account that person contributed to the organization, including other providers. It does not remove their organization membership. @@ -92,26 +90,28 @@ These requests are separate from organization invitations. They let recipients c ## Manage sources and documents -Open **Settings → Sources** and select **Manage** beside the integration. When personal connections are enabled, Gmail, Calendar, and Drive list their sync configurations under **Advanced** and connections under **Accounts**. Other providers with personal connections use **Sources** and **Accounts**. Providers without personal connections open directly to the source list. Select a source or sync configuration to manage it. Multiple sources can have different folder, repository, space, or project scopes. +Open **Settings → Sources**, choose the integration, then select its site, project, repository, or account connection. Each row identifies **Member accounts**, **Service account**, or **Admin account** and shows its sync status. -For Gmail, one configuration is usually enough. **Add sync configuration** creates another source; editing **Settings** updates the selected source. A member configuration applies to all connected Gmail accounts, including accounts connected later. A central configuration applies to the selected Workspace **Users**, or all active users when that field is blank. Its labels and filters are evaluated separately in each mailbox. +Edit **Settings** to change an existing connection's filters. Adding another connection creates a separate selection. For Gmail, one member-account connection is usually enough: its filters apply separately to each connected mailbox, including accounts connected later. A central Google connection applies to its selected **Users**, or all active users when that field is blank. -Gmail Advanced tab with a sync configuration, search, and Add sync configuration action +Gmail connections with the Connect service account action -| Source tab | What you can do | +| Connection tab | What you can do | | --- | --- | | **Documents** | Find indexed documents, inspect processing status, retry failed indexing, or exclude and restore documents. | | **Settings** | Edit the source's scope, filters, and supported indexing credentials. Select **Save** to apply changes or **Discard** to undo them. | | **Sync history** | Review run dates, document changes, and any sync or account errors. | -**Sync using** shows the method selected when the source was created. Create a new source to change that method. To replace a supported indexing credential, select its replacement and use **Change indexing account**. +**Sync using** shows the method selected when the source was created. Add a new connection to change that method. To replace a supported indexing credential, select its replacement and use **Change service account** or **Change account**, as shown. -Use the source header to sync, pause, resume, or remove that source. The back link returns to its integration. To disable an entire integration, turn off its switch in **Settings → Sources**. If it has sources, confirm **Deactivate**. Its content becomes unavailable in Search, Assistant, and MCP; sources and connected accounts are preserved. Turn the switch back on to allow it again. - -Gmail Settings with the read-only Sync using method and editable label, date range, and search filters +Use the connection header to sync, pause, resume, or remove it. To deactivate an entire integration, open it from **Settings → Sources**, select **Deactivate**, and confirm. Its content becomes unavailable in Search, Assistant, and MCP; saved connections remain. Select **Activate** on that integration to enable it again. Gmail Sync history showing run dates and document additions, deletions, or no changes +## Usage stats + +**Settings → Sources → Stats** shows successful Search invocations, active people, and results returned. Filter by entry point and a preset or custom date range of up to 90 days. Dates use UTC. Source usage counts requests that returned content from each integration; it is not a click or citation count. Tracking starts when enabled and does not backfill earlier activity. + ## Search, Assistant, and MCP **Search** in the organization sidebar finds documents directly. The assistant on **Home** can search and read the same sources to answer questions with citations. Conversations are private to their author, including when another organization member is an admin. @@ -135,7 +135,7 @@ Search runs background syncs on an hourly schedule. Large sources, provider limi A completed sync means the source was checked; some documents may still be indexing. Integrations lists personal connections; a central Google source can be searchable without appearing there. In the main **Integrations** page, each connected source row shows how many documents you can search and whether indexing failed for any documents you can access. -As an admin, open **Settings → Sources**, select **Manage** beside the integration, then open its source or sync configuration. In **Documents**, select **Failed** from the status dropdown to inspect those files. Use the search field to find a document by name. Select **Retry indexing** beside a file to try again. **Exclude** removes a file from search; select **Excluded** and then **Restore** to include it again. Fix a disconnected account or source configuration before retrying a sync that needs attention. +As an admin, open **Settings → Sources**, select the integration, then open its connection. In **Documents**, select **Failed** from the status dropdown to inspect those files. Use the search field to find a document by name. Select **Retry indexing** beside a file to try again. **Exclude** removes a file from search; select **Excluded** and then **Restore** to include it again. Fix a disconnected account or source configuration before retrying a sync that needs attention. Empty source Documents tab with search and an Included status filter diff --git a/apps/docs/content/docs/search/jira.mdx b/apps/docs/content/docs/search/jira.mdx index b793135c408..a50a7d6ffac 100644 --- a/apps/docs/content/docs/search/jira.mdx +++ b/apps/docs/content/docs/search/jira.mdx @@ -30,23 +30,18 @@ Search uses `read:jira-work`, `read:me`, and `offline_access` for issues, identi ### Choose Jira -Open your organization's **Settings → Sources**, turn on **Jira**, then select **Set up** (or **Manage**) → **Add source**. +Open **Settings → Sources → Add source** and select **Jira**. This opens **Add Jira projects**. To add another project selection later, open **Jira** from the Sources list and select **Add projects**. ### Choose the projects -Enter **Jira Domain**. Under **Account for browsing**, select an account or choose **Connect Jira account**, then select **Projects**. To enter keys such as `ENG, SUPPORT` manually, use the switch beside Projects; this works without a browsing account. +Under **Account for browsing**, select a saved account (including your personal Search account) or choose **Connect Jira account**. Enter **Jira site**, then choose **Projects**. **All** in the dropdown selects every project the account can currently browse; newly created projects are not added automatically. Clear the picker search before selecting all. -**Account for browsing** only loads the project picker, using OAuth or **Add service account**. It does not enroll anyone for Search. A service account needs Jira access and the [Jira read scopes](/integrations/atlassian-service-account#jira-and-jira-service-management); Confluence-only tokens do not work here. +To enter keys such as `ENG, SUPPORT` manually, use the switch beside **Projects**; this works without a browsing account. Switching between the picker and manual entry keeps your selection. -Jira source setup with an account for browsing, site domain, and projects +**Account for browsing** only loads the project picker, using OAuth or **Add service account**. It does not enroll anyone for Search. A service account needs Jira access and the [Jira read scopes](/integrations/atlassian-service-account#jira-and-jira-service-management); Confluence-only tokens do not work here. @@ -55,7 +50,7 @@ Enter **Jira Domain**. Under **Account for browsing**, select an account or choo Under **More options**, optionally set a **JQL Filter**, such as `status = "Done"`, and choose **Metadata tags**. Leave JQL empty for all accessible issues in the selected projects. Enter conditions only; omit `ORDER BY` because Sim supplies sorting. -Select **Add source**. This saves the shared scope; it does not authorize accounts or send invitations. +Select **Add projects**. This saves the shared scope; it does not authorize accounts or send invitations. @@ -71,13 +66,28 @@ Each teammate follows this step. Existing authorized accounts may already be con For workspace Search, start from **Search → Add source**; its source-creation button is **Create & Invite**. Search manages the sync schedule and hides item limits. -## Manage the source +## Connect before a source exists + +After an admin approves Jira, a teammate can start from **Integrations → Connect**. The same setup opens when you choose **Connect a different site or content scope**: + +1. Under **Your account**, select a saved account or choose **Connect account**. Authorize using the Atlassian email matching your verified Sim email. +2. Enter the hostname under **Atlassian site**, then choose **Projects**. Use **All** in the dropdown for the complete current list, or **Enter keys manually** for comma-separated keys. You can select up to 1,000 projects in this form. +3. Select **Connect & Sync**. Sim saves the selected scope and starts indexing with your account. + +Jira personal source setup with a saved account, Atlassian site, and selected projects + +## Manage project connections -Admins open **Settings → Sources → Jira → Manage**, then a source's **Documents**, **Settings**, or **Sync history**. Metadata tags include issue type, status, priority, labels, assignee, and last updated. +Admins open **Settings → Sources → Jira**, then a connection’s **Documents**, **Settings**, or **Sync history**. Metadata tags include issue type, status, priority, labels, assignee, and last updated. -Teammates share the configured scope and do not choose projects again. For another site or scope, add another source, or use **Connect** beside **Connect a different site or content scope** in Integrations. +Teammates share the configured scope and do not choose projects again. For another site or scope, select **Add projects**, or use **Connect** beside **Connect a different site or content scope** in Integrations. -Invite teammates through **Settings → Members → Invite** or SSO, then have them connect Jira through **Integrations**. **Jira → Accounts → Request connections** only requests a provider connection; it does not invite people to the organization. +Invite teammates through **Settings → Members → Invite** or SSO, then have them connect Jira through **Integrations**. **Settings → Sources → People**, filter by **Jira**, then select **Request connections** only requests a provider connection; it does not invite people to the organization. Sim checks Jira separately for each connected person. Content becomes searchable as indexing finishes; issue changes and lost access are reflected after later syncs. @@ -104,6 +114,6 @@ Configure one shared Jira OAuth app for the deployment: 2. Under **Authorization → OAuth 2.0 (3LO)**, add `https:///api/auth/oauth2/callback/jira` as a callback. 3. Under **Permissions**, add **Jira API** and configure the full `jira` scope list from [Sim's OAuth configuration](https://github.com/simstudioai/sim/blob/staging/apps/sim/lib/oauth/oauth.ts), including its Jira Service Management and Assets scopes. Add **User Identity API → read:me**. Sim requests `offline_access` for refresh tokens; Search's three scopes above are only a subset of this shared app's permissions. 4. Enable sharing under **Distribution**. Set `JIRA_CLIENT_ID` and `JIRA_CLIENT_SECRET` from the app's **Settings**, verify `NEXT_PUBLIC_APP_URL`, and restart Sim. -5. Connect from **Integrations** and select the configured site. After changing the OAuth client or requested scopes, use **Settings → Sources → More → Refresh connection settings**, then have affected teammates reconnect. +5. Connect from **Integrations** and select the configured site. After changing the OAuth client or requested scopes, use **Settings → Sources → More → Update sign-in settings**, then have affected teammates reconnect. The callback must match Sim's scheme, hostname, port, and path exactly. If only the app owner can connect, check **Distribution**. See the [Atlassian OAuth guide](https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/) and [Sim deployment reference](/platform/self-hosting/integrations-oauth). diff --git a/apps/docs/content/docs/search/slack.mdx b/apps/docs/content/docs/search/slack.mdx index 2b63bb88e82..11f17e1b687 100644 --- a/apps/docs/content/docs/search/slack.mdx +++ b/apps/docs/content/docs/search/slack.mdx @@ -23,7 +23,7 @@ Skip to **Connect the source** if the organization already has a verified Slack ### Open provider settings -Open **Settings → Sources** and turn on **Slack**. Select **Set up** (or **Manage** if sources already exist), then **Set up Slack app**. Allowing Slack does not configure the app or start indexing. +Open **Settings → Sources → Add source** and select **Slack**. Complete **Set up Slack app** before choosing messages to index. If Slack is already listed, open it and select **Set up Slack app**. @@ -53,14 +53,14 @@ Return to **Settings → Sources → Slack → Set up Slack app**. Select **Veri Member connections use one configured Slack app and workspace per organization. Installing another bot does not change that configuration. Changing the verified app requires members to reconnect. -After verification, open **Sources → Add source** on Slack’s provider page to choose what to index. A connected bot alone does not mean Slack messages have been indexed. +After verification, select **Add channels or DMs** on Slack’s provider page to choose what to index. A connected bot alone does not mean Slack messages have been indexed. ## Connect the source -Open **Sources → Add source** on Slack's provider page. Choose **Channel Messages**, **Direct Messages**, **Channels**, and **Earliest Message Date**. Open **More options** for exclusions, archived channels, metadata tags, and **Sync documents with**. Keep **Connected members** for the usual setup. +Open **Add channels or DMs** on Slack's provider page. Choose **Channel Messages**, **Direct Messages**, **Channels**, and **Earliest Message Date**. Open **More options** for exclusions, archived channels, metadata tags, and **Sync documents with**. Keep **Connected members** for the usual setup. | Field | Behavior | |---|---| @@ -71,15 +71,15 @@ Open **Sources → Add source** on Slack's provider page. Choose **Channel Messa | Archived Channels | Included by default. The picker lists active channels; use manual names/IDs to select archived channels. | | Earliest Message Date | Optional UTC date (`YYYY-MM-DD`). Applies to the thread's first message; replies are included with that thread. | -Select **Add source**. Each person opens **Integrations** in the main sidebar, selects **Connect** on the Slack source, and approves the configured app. Creating the source or verifying the Slack app does not authorize teammates automatically. +Select **Add channels or DMs**. Each person opens **Integrations** in the main sidebar, selects **Connect** on the Slack source, and approves the configured app. Creating the source or verifying the Slack app does not authorize teammates automatically. The Slack app's **Home → Connect sources** opens this same Integrations page. -To send a Slack connection request, open **Slack → Accounts → Request connections**. This requests an external account connection; it does not invite the recipient to the Sim organization. +To send a Slack connection request, open **Settings → Sources → People**, filter by **Slack**, then select **Request connections**. This requests an external account connection; it does not invite the recipient to the Sim organization. You can instead select an existing account under **Sync documents with** to supply message content centrally. Members still connect their own accounts to establish access. The selected account must itself be able to read the selected channels. -Admins open **Settings → Sources**, select **Manage** beside **Slack**, then open the source to inspect **Documents**, edit **Settings**, or review **Sync history**. Search reads indexed content, so source changes appear after background syncing. Slack retention and API limits determine how much history is available. +Admins open **Settings → Sources**, open **Slack**, then open the source to inspect **Documents**, edit **Settings**, or review **Sync history**. Search reads indexed content, so source changes appear after background syncing. Slack retention and API limits determine how much history is available. ## Permissions reference diff --git a/apps/docs/public/static/search/confluence-personal-setup.png b/apps/docs/public/static/search/confluence-personal-setup.png new file mode 100644 index 0000000000000000000000000000000000000000..f8c4119d62cecac66dd452f21c0aadaa4157095e GIT binary patch literal 68053 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

%$$bDD%!YfOq&;NmatiK>9S?DY35VA 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

K~^ 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 diff --git a/apps/docs/public/static/search/github-setup.jpg b/apps/docs/public/static/search/github-setup.jpg deleted file mode 100644 index 454bd18b10e60764164c26ea5ded4ed597630970..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31061 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 diff --git a/apps/docs/public/static/search/gitlab-options.jpg b/apps/docs/public/static/search/gitlab-options.jpg deleted file mode 100644 index c2ab696601f9e1e0b2c2dc4b39b482faeb6e6168..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47941 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 diff --git a/apps/docs/public/static/search/google-drive-setup.jpg b/apps/docs/public/static/search/google-drive-setup.jpg deleted file mode 100644 index a61673d34957a2c96436cf60f6288bf04baac9c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22911 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

q?3hA_f~I&Sj+5q`s~t?yZ$zA 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 b7QdmbQ7|7_Sn+7yfj>vJ4YlrT*hTywh`nV2 literal 0 HcmV?d00001 diff --git a/apps/docs/public/static/search/integration-provider.jpg b/apps/docs/public/static/search/integration-provider.jpg deleted file mode 100644 index bf655343f517151e7bc2e65f75dad1a64786bf82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21510 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 diff --git a/apps/docs/public/static/search/integration-provider.png b/apps/docs/public/static/search/integration-provider.png new file mode 100644 index 0000000000000000000000000000000000000000..535a5860a03afd3f069f65c8b5f1202d42ee6ae1 GIT binary patch literal 37791 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 literal 0 HcmV?d00001 diff --git a/apps/docs/public/static/search/integration-settings.jpg b/apps/docs/public/static/search/integration-settings.jpg deleted file mode 100644 index f4e517c06560e8d6eb21e668805d82c344d2c20b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32832 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 Xo1Z|d#7;@xRN4oeG1+}w9L)X?Ik_n9 diff --git a/apps/docs/public/static/search/integration-settings.png b/apps/docs/public/static/search/integration-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..8dcffb533364e8df7e65804458a83f579d31302f GIT binary patch literal 118870 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 )?-3Oae;Ny~jc@M;3WA>jSMe|1T5WtbUONrP|% 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�`6wdJp2y6|ViSHq# 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 literal 0 HcmV?d00001 diff --git a/apps/docs/public/static/search/jira-personal-setup.png b/apps/docs/public/static/search/jira-personal-setup.png new file mode 100644 index 0000000000000000000000000000000000000000..9530eb542d2aa9c77b84dbdf63e15ee44bb00a45 GIT binary patch literal 66834 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

Q9>J5K{Jd$bCS1xT5iXk8rh@Hzc zwg)Bg{H!Q6`njB+4~A=HYsYKP&8S%+O61NFve#s)r?9ZFS?RYY#macZXGw8&a(cqk zrw_@58xjkK$S+!BTE@oAd|*f^L%%{X_@4Og5z~AZ8QN}1-X81sw*mCg+3;E5TJlLj z5tT#VZ%@h5C`yyXvg@{d<#2JLCUwtMUtU*MzVG7`FJ{6VR#jAFZ)HW#TiQ7(>;C&| zSC^JV((Kff0;{SVls4q91J z=pUeSefxH$x9AQWPC)?}mRRK0UzC)TfZ7N$EPNPJ4Pe*o%*@vBS0(&~CILGuppb$+ zMMuYPZ)fdEi}~4So4}rfkUG7zfl#{SG5hV=x!ch^va2S0D<-L_RIy+Hp7#Fzdr*2D z9mNWl;Gsav`)#c@G&ID<#{T&6BPT}~7Y8O8W?pQf>dR|*-!Ch)H2Wh@(Jxr&|ETtK zym#;3*=N6}r-6wC2E%Cqlz(YV3kdb_v_RKl=#J{^`J`;z+?Ic}Jb_kkZGJca-d6aD zeudLW=cYJNfcJ<=);G1ap)-`IA9j3eaQ@ZD$nT&^^!C;P%(Z;G$Cy7KC*%hzME*^&apTdY3W22A*#Ru61jT1+)n-8Ry`a4{8058=*fWj zsCw)D`}c3(zOApXkH>c}jy0F{&q6210e^5@MX0{)NV{AO@Des2 zv@@s*P+}E{5EU8u z9NrKlIS^dIF`$+pdW0?*;C@PCqKfbnIByx}(GPIgg0U4YFZ-*VVMX2#n>XZoUa$8@I#@N1(W z|2dSOIFk!+31H=m`{jf-a5HeSDT3z>JP)8&0t*0p1!~`*V|`TaCvyqdlZ7C_E0Bo( zy+}1D%2A z>TEw`r<+VIz%2!Sr;Wek*96&^!=xO(OT%C2?e!S_5bpZK5a=&3Yv?h8L>(ZSQ0+Ny zEX{pg!{_$xJ}5NM?^%|C!AFuQ>)ku*svYZhJe-{ufBrNDXAYLPQ{&6PfDa&F5WRm? zx!X>5q$cNp8m|<=aq4u^<@=Hn%fQ|2ix~%o6-0PmZf>me=)>X}_{y}z#P?O8zIOxm zhx~ioIsiV9p&=e7I^d$JtE=IEFGXLqX@__NR{^*T<#v`S<`UCuTj_3>GqfK4vo@-! z9U*_REKB#_JW~)5n;-r;$z0+v-{GvCx3+zdd~i#4>1k^RS6>zvcN+b0xbSQJQim+a z%JOSu(0S5$RH7)DBWmHF=nPBEnnI79;6Up=_$pgg`-kzd{F0ELXZ28RZ7l>G7(vDs zYv8l}cCe?q_@_|8+7iUFUM{S!uS1bJ!5miFTI0Lng5VG_u91#aF|70THZwB=FGqz5 z1S0Sr1%q>SP9s-@pHu>w^YiCV_#m)V)a=p71wU;Y>FU+1fSh|VM^4efd0O=zjcB6! zrG|&)rKP>r{ul`rQ{7bwZG?A_k>Jk=Sf1*JbKPEF1mDCh0jN6QWTLV>pEfF?*24wm zW&{+B&%#ftf5`M@d#Y@CZtgv(o8VxZ|52NCgU+!<(>Mm*=3if5SonFwX{stZAxmS_ zr4p*>tvh#Ykssk~ps+vw4VO6F1-^@;N@VfgVxyE6bGRKMxzlc)b>H3gHg64B?p7A^ zKh2uPXsLF5N;a;MJhA{sKDJmfU76xuAXZTKs$gJf=rZJ~O-})=Zm7cfF6>gyh!AG?Ag%;)!1MaZ(_`Lsv1{NDBwxJ97I z*nh8B9BqoIG%T*HJTBY=;gFl|Z*cpz=kKriH-yW8)B;7VGktF?MqXD}S2Zphr3&s7 zXs@)Em;3Lfv+boSc!~0>A764regehQhDX1f6^C$`mu|NVc-U3?Fj#Sw&nmoug`P%Gkb1SQ<-#q{s>1YC>e&pQD2Ul`T zGoPIAx4ymvja)Iv2uVqgpYQi4s=#ECnVE~i4Ppy&v*hl4W8=^yO&TSeNppRI1CP`2ysPa3LUea7bgJx zO>6~(`xTQV(f}KXKSX#}p%@Ilma|WX1i2N=UjCB`j~rgu-^jCNFaHHVPJny=t$o*K z^i)HRnD)L(;b;d$M_)TapSAXYfXw^x6%&UR>Di#eG`|IAigkB(>hj|Or6`M0IBt9Y+2l@&;mNH7_ zygA%0MQ5?BWmCcW*x=KvOStp*ZEN@Jf!2VI1!mnA} zOfiXkVx&D02r=&UZv6hydM&Kup|618;#SO{f%5w1B^3OKz+ql z6VF}K=0fFPdY-6*m%c=Idil`xyAp;-H;#{O(CHO(-(~;E6o~EC z2L3ium&5iaaVA6INR(AtWXko;14rpQ4|;W2#zp2&SZ+CgFn*lH`9j`_pY?&-!uqR5 z`s@FAvInn`(MP`1Oi{fXr3Nj|+#b_+VTk47u)%QY4dP3+DOv2p+&LVTRHGg1cHu8D zW}PN)FL+^rCs>_z?e+9(2bN5iPLxyozgdWbZ%!%SbBXkvx^=*oGsTuM$kYG>_UQ{C zNlL+7NWg)^zV$^j)bA7H-8PTo-Hf{0pVe)JpMV|gYy*&RfABG*g zyT=wr&Oo(--5fmbolE~lB#io$@ZhFnB2QI0lz~CGSU4}l_Mv@M%OfM{+0hNv1 zAw1!6`kz#fi*wQ_)0gvaBNYnaFzO&x0t0>Yk|b|~_LzxLpLd#+)CcfBmeg&YRi_X$ zUrfujkqQb7&>YlBgbQnVaTZBq6`*Zx$6M%Ao&7q9kTL03JvPSj#Ys8Sp2L2gASE)9 zt$@-Wz{E6PuxLf7Q=C#^OoN-*PTk=Lw>rftdDW*Ds2r#sGb=Kw8lV8K_$*NeAl?%= zB9!omf8!jp9@UvBubX6Xt7Lc-D{VxRATEwF4PM(m_u1S}|KtA!TgaF+F_U-raohJh z3OYKVYI;<+jRWeDmp6&G0LOis#Kps_d%!LcGo`ti@rcFj^?g4V@2yk{veI{&41)_2 z=%&te`Sj#}zUcQP4H!n0`FqEqxP{ zm_S9=hk=2CW6d#lige>GfRAps)Yj>7C|8TSrKR;C7xi!80x+p~Bs@xy^*OaSUGS+z zW`f$>xupB5XL4zLe7qDrv*?9Tg1MlO5Dcx2@7q4~Mxxss`bjU}z2lg4mPz$u z1aoVxpKkg&;3cd;6Q2jqa=shdBsl0}SPECOo}T(@81>H$lH0eI|He(QRI( z6&g$i+|8hfo?M0Ll{W@OiCLz|6> z#WOH=6!f4Eg=077;Z^+B;r#vS8SMq;-&H?`hljhn74e8PM%R-yxnL@In4mfgSnnH! zLizTM-bmra0ARxLR)__*A(J}a4QO7$-U^!-B&ZhW2Ea{IZo?d0!obl%^90}qXnpOR z8<$|S;l>9MPzDeH2IICog;%HW4}*{jF4kAC&OKA*x$NTx2M-u&W<~e*ZIenD3ooyV zva+QV$2#Xq!#JV0<>k~K-OEcF016PKtmqF#Ok|jLGX__Isi~=#*E#@e7)fKL@4^5^ z_y+Ob-@gH7S3u?EZ{C=4WX@~?TNM@-MwxcIe}4-YRXa&ACLp=FxsM-*$rYe!fGb$u z@CA$x(jj!^J3Bi7s6dodw9}w0gPA))MF{$Opeo$mFV5zZ!&pGk-T4%IQhs}Z3`iHo zubRiY-FdEl1*ti%#T?Aez^8bv{MNZffuaMdB($z`Gc&+BL1$N0%!xoiu>y@6mI%Dp zJ&7c+7|_McR7E#GY54_&BWxPXJHdJ@4S^BdgYlp90bej8NjDq@-?iJk_1~P%1z-tK z0m;Y5heQHB5!yUP&|ig48Ws-A2cIyoD32EHB~yBAF5bHYP28#OwctZ6{=j`ccEKYc zSjgf5yG!Yd!*U3QahFOMK%kCoz&r}LhpT)yBxq_6vG4-H0EYcPgXLmRTHHK6FEEX* z_}o8T3DZ1)OF>(ZNsYdq1t%Q~RjEaYo!UuH0aMM(!vil0ydq3iCEc);NTU8eFr0u7 zfGR>L6&bw!4Y2~_5V9V#dZlIuGcA*IMwFl(odo;{T_4;u!6bSS!k8Pqz{8(u#sV-jz4NHA(>?U+3TUzHwN1|bkRvTn!pDr zB9(jqiUPPu2nKMh|NP0ny`w3=vkb8e>qrmS1(KtUEfiYIa1|gh00P4}i|14q%w@RF zemk#(2V*GM(_zR1=(A|j#*@*fR4edUkP3if|1K>7P=)Qzov9MSK{-yz6nXv&pblg@cQYV)2P-Qpa9I&EA7xemEd=tsnf($Bf5AI?RP(51MdNA@7`=Y#u$q4x+Td8`819A;)_&?0JHym&CV0qw#X>yeJrSSswylSX*6vza{Pz zAjqT}5G%LiEh3uOndmgru$LqyS6k1)Igykx88wt7!s4`7N7`1*=UJmXZ zgT56o8I})TmXII;DXC6j=9BwAG!zwLh>L?ja+&EB`LGU00J(W_;wr45OD)d)twDOv zBsBEc06%%CN&x}#H40LNlcTyVV?{(F{$V2kc58V(u3MR?Z)*xrU!36f9v*b zAm>Z;O0VFb8j7xg5lkQ!YOv4D zudy&QLwrJRrpgEGLS3DkgPB7|7#B71-xz=Ye&5Z|MBL|#-<+hea&rF-i_n>zO1kj{ zvooGx0#j-F@$i!jTsYi~?ja|je7BfGcZ7>$Rh_BoAkA(pO&+476TkGr+6QJm;fO%? zVGe_Y+WruJG)@TUtL^P=5JlF81JVhJun2cg&sPORfh8zXE#~aOyp;wtK!O z4rURUHh00<>AN=MNo8$)Z7R5dv2qyf)!IK+6atG}Bt5blo>Y-4y4GlkwM`ogc<^*ONmgKiJ zR}NwsDDjU=%fY+^?eEEm(zkEjot#*Mk9<5~9ujsX1LQ5ZN)Uv35WpzYn9e0VQ>fu$ zzo=7e!1@A7C+I&naM3)m3*!gu>8sl%f)}VdC7eA{NiUuU`^>xN*B~@7Kyq+! z$iY?8CRYDJ`WpV0yZhVbF*c<|pfMq`5*HN`&P#$D9V#?Tz}@TM&ZV?0`I@oETM%9& zjvXTu+%ho<0LHAOuNvyKn~af;PDq9`qz6QsLwWVfmlo#c+1c5&O|)R^;zAPuO2}?|A6OR8|ZqX^UsQ(&~YmhUv>DvsjDc@yxT*zI2b%G(R7w8L^;v z=2E>!FOXkp`>nyNA1b<&{H*T@ASG?UB}7=cks{gdP#zN# zLnWM%bb#4O{j-pr7W%uto@fdS3)ew{0PzpC3a0tiAb|m(7?-TUQy_GqwyJ!eg;_g~ zS>)Lm=mpL`8z{Z2ERMvwO###01;r7nRX->w5)xpf%tp1surM@@=kGrt2Yce<$3K4j zNZlr={qTT#uSG#!i`*MYHw_G+x9%Gnss(loW|F0M!FkQiJn3?&Fl1C0lz{$eH;!Y+ zpo9YS0-s{}u>XlmDtheDiGWbtkaqb#+zkW0y{pjh!cC_d=LWpLn+(k6p@p6V3A*iVpV_eWZ$aQfc%y_n`F?UwSp z>vt7d0sep;^ZUlg$OueygRk>xWJmJF83=o5o3DC$dJ4wE)Sq&3dGQRKA~z2Yj4=wi zESw=GOIX141#s+|LhS!B%78@@6BAjL@H#!FJCxr+D1GCBQG>}1uoHl+2mQLIhXcJIR@)4Rd`-Ci2+g z^71m&Y9?l8stN|h@rkA!8|?^n09S~89h+a^10**{%ZpffNECs*7OBR1jceYL9y8vkLgFsKcPu$==k`+Nb{S2fV~IFEz{W z;_--IEiW{V-L@(p#J5Ha1NP+uzlvJsyq+%THQ)`jECXxRqL&sbJv}|f;;P%3z^hT0 zEIXrY@)){Y6Fck;n3BH_T39HQnd}i(EA>I zRYAwZ0yGMu37C&%$=7;lq_x&ca4GHO16Ik`%Mak<;6ulh8gyW$^No#S52`mQ_6Cmf zrpYWYF|#(3pMHw_!S)ryvo!WKddvRj?>8kT5RGLXTS~83vF)Efahymc)I>ruVr0(L z_=b@KX-^wIt3*1)mu0rmd>QGkY%nZpTD0m5p14rqsMmF!=GfvrnAlStjwLsXGu>jr z1AL%2!fRf`Kc!4RoP02i&1P7w1=|ckVRu2S0Movz!`-Zpjt65y27x0;-&{t}N~u%q zIcu|Ra_B*?>0_0l6D56&0&1+Zctq@z0u)1y7wWbb%KUx9Se{sD_j{w0Um}{rPI1!o zz3|@_J$SImzHuH{>_dqMBivHja|+IWzj@R4AT4b#`3HAGTS%*jibY^Su#N5`sUXzQ z)`P8ZbNh&+id@;+=|ndx2a_-FkoeVM8hXgPQ07LCW=#zBUq?C>Z(t4U3lKy9bS?j|ap) z7&hE%E^26Yw6z7I-~)$XsWL)o{iifnBBvUv@ZoFb2bu7bkCuHd=lh1QFr3l4E0KiZ zI>K=WDQI5NC`VAIGiZLNGdi$WpL`pEKn!25zsq;hKQ!gAO)wW@49o1kIGSfKEIGD) zSY@u++#E`%m|Wm14Lo|N+Y0mT48tLA1M!Lzjr7}YtNHIhxwSPbDnaOy+_xc}uPuCj93?zA}bX_*(DP7-Z5|K$C zdeF%1sgpL6`{uFZzENf@dOG~d^lQ;?>3d~lQkivn6qd8C#9L2hIUTXPAjE@})4Pb~ ze^E(TcH)SX)CjYpEo|I-<*lTsxVU#{ZXQ@SMd$lLe`SFvY??dVIu9?1C_jy=*VfX~ z`kwY;TjT%lzfhsS9bL?3#UJ)V!D?4wH~gL4)c%L@JX0B}{+#NvI7Vhnh(d}M=B>gL zhBs%G%7ngH(HKc|%^WKd>Jq2tnN=}id-F*lLC{STNMyR;{W~h%P90X5%wYCpsf?jR z$wx=DtZoNsa8{gk&91rwev)0YCwOeTZ!k1pJ0SeV{0gJvo4)`%r%w0u_J+bwAv=81Q5@N&$I!mr z)pU60vePN6u%LIvQ&&Q4!N_EFAtFrxsOg=w1={Wo*1KlnNM>&72WdlaMj}q#EsW%# z^UYdWi)fj!pMMst#3QZVMZXirc8*;#GahM6beUocW&8N~0}~tVeyK;jkyb=o$&@2> z2Yeolr8aO^*9|gRUr;mNADIipWti2OU;)9Rql=nMoD&B=a%l3^eqCHXe?-OA6eda> zE>vLO_zEm>6dlD4D%EIL{4d(x{GaM~{T`3ZbCM~vNm412kSTL`sZd18Op@3nA(@BF zQ>J82LNcWkij0L&37MxP6++1LS=)KM|A6lg-}5++^Lia=@8@ve*L_{&uSKw)Ah9P zRMjoRcg0sxQ5U{u{(rUcH3O$=qd+CDQlufj0X@~A`(*0(k>CW)hf%`Z>0m~ft>y$c%Kif-Mjyow1xa3CN@eSAL zM-YoO+qdm618+IarIE;1n`4GOR^lTu2SWYm)&CQEKzV^uD9|0k!~JgyGaDqYjx+j` zWk>!Fs(%X3HMqjmzOJQi5#<*PYt4Y-e;1$+W7_Srm&C`0gbU6kiV|>&GaQPH1gjxz z{%vbCRe)H6o5Y#iol9Z88r(axS~xRvpFfuzeUj06qIpMsfKh-uK7&rEG3}X9(_W!; z)1g`(ULL1Y%P(_s)JPO*@WeW45*LmH?+Xg^_W~(aCiMftA?U{rJH4-!Ut~G*gzbnw zCmiOY5*kneM+vcqWk$(;J!@gF8T_9Mvrrn@H!JuW2(yu!TJm(94mVH2)rm>l9C#vb zLdPN{w+rk<=a;j3btZ2;q0G3jffI()q{?UWlF7fQKX zMmIv12xg}M*$c{kUnxd5_wLKL%m;@VmHN7HZ`$1VN*jUcDWT*-J zrb!I`GO`R*!SVX_hWPAvhaF4@gF9^leyNTrc1W?S)Qe{p?rm~HzB=K|75s5}kuQq+ zwHm~0j*j~iwo8%U_zuE+p4FNYSHQJl?&(DjN#Vx~+iOLpfJ{?TEoPGnJnI zDq1Vdisym3;`Dozn~S93f`I{eP>&ux8g3e&U(w1D(A4|yKl(48-|PRgQF!Sky~-(& zBpjjs>FZamuc@+sM_en-BWBse$c7DV%P&^R5=CZ-5SB>u*l-Gw?4mT~44&{K7feeO z)GQUro)+{P*wQkmv?a7mpn^RrkCmTxpvkGt=F{Z-h;>r|j5zIo+ zAqzEmZ@4ecn!>1A&y#u$oe`9Q0Ep96h2na9dbSOSh=_nQSJj?W>!yo{EF6kP_=K~0 zCZh~`(ojIMz!p$tjZMzJDtgv?PQg;rQg8HhO{`ABgmPv_R~Ka#*Ony*zaHcbwSAOy z{!0(L>@@uyb++03s;^hg?o7IWU*NsAOzP9~2fud!5QN|a*thu}WGSNhxu53bn3rZ&5=ZBy`&M=_sQPGKRV7vqs|=|aQ!x|NSpE{4{12EK)}v18p316*hb%E6b2PI!S2_tV@l ztRB&c9=jV#qcTdAW>fQ3BwN=h>dxMKLVNFLK9SSI`orviLLawHx%lnjABuVO8g>pB z3q9ocurFOJ|I5(>=vHOF5V+rqs-IkhZT7_PFyf(pf-c)WO@Z??mE=QjaK9huIJpwh zG?eE%d+E|{?p`pe(%Y|;UnC)9`4C^b$V7De+DhYO3A3*-w#s9Cao;?tvs1Uq+Kk=h zjAXJlHkueKr+PtGC|96SKsjZ=>1FhUKY%r4e56W5jCM7C{SZ#u=0Gphh#naoRQrb{{+DnElVxyqgJa+6@yq2}6C(k@z8oa(9ciG|dxFc}j z7>XposiI{fAu*AIon0@F?HM|XuqguPANUx^Um1fn^7uGZ=}~fjG)fGA{`jHCmhrMKT(UEqGF9}*X=MR>@dPTR#cnboIOJB3H zun^#jy1^rL^5o3?3evup%X)bdN00idA=yk#PBy~j8XA6|p7!7IjY?ab5N*N5J~t7p$hf9E*e(;E(Z!1#N;+mQ2l#8}0|PsqyB2Z3C* z;>ovGSzIiJCwKg~enA)D5)^w^u1vmt`}WS#091_MoL>$X`%{n2xhbTlCnsN(Ou=E0 zFrl6u(>~eM*mz!FZJt!O<8q+3r3-v^5xml(E<2n7iypjXIk~yH#z)X4ZT;{8jB@Yg zU~gz<+H8)cw6Vi}G=~+^3n8?)pjF=img1B12j}PKf#IuK0~Me*ycS%AfDY@i#yZecCogYcbx4E7jT<*A=K2)?-~pTu>E{o% z5M~3{+t1-G_yjHZ#}B_94WVG+I=Q+&@3e&vk)pF^?kC8;L3$<< zi2!U^Xex}Kf@cr-rl6~|_lZf-*&IFG7M>~mA76hyxiNOK(V_&{Z&5eo4WOS|y#gc9 zt~_*p^mP3t%{kuL+mb1iGdyx`v*-?qtr}{4Xm3Az=8SrFCmR za1sT-4%ba`q=h+^v$wZ5o+b|utXpB+x8;k(K}Q)m2KWrn2O^_%B%TLe4G5hU7Fh-b zN@2mG9e}9l0?|L-8A8#Y1%7RBZ!bC_ssbfgT@n&jFZ!xY9P`eDM2!>7)fKVTY*)xG zs(bI<Vt+YnV;5@-&Bn(>+!DnIv(aH)oXI5#81SN8UH`3b zcvKJe_2F6(=U*B}HdtWQ;7!`ww@$efa7(*J&rX5TC3iQG(NiNXrosk!4Q>k!}rRvfmd( z*wNSrIzH*%T#V>}UKt3++!5ywg7`(1i8X~l?&jup^Ct9rG}5@XQf8RA<>+0x0@qeN z=q|fm1@E+S#Kpy7fQ%^P{1Rsc;Xdpk+}KFP?m%2XK&TUQyD-NJ zy`mBef;&w7M&Wh*_+p`e>UQ$CKS~V>kXU|CTJcm!Y#F%@JT^5wy?e?9ooy&$rx!;d9y)^jY!x<3{K}}W){xar=+QWD7*R$_so+#6;5J1mtVv;Vn-tfG;+1Ec?6Hwu?oCKY)Kjl&LI49 z@sW##&kG8!UA?Nw5`bopR*v7&LDrBbPo5Nu0C>fcLerSN6ERK0A2w?_FPRd^oss_oZGrRpfsQn^8f*5cjqQ+q z^En#(w|yPci%78z3f`55_vn}PYUh5kDSHWdfQ=2+TY7ui4}rS_-s4zBy0bUtZmk)y za-jTT+su+IPbA`UUfu!KV*Ut=2XlUwPQV&6Hb_ZUTKnX&WQLGGzAYIy?`h@e2vdwW zTUo(7lanC``0JTmP$pU?WY8rO-p<5r@E+?6s|p=};RT#1$iuX9$b(__dktPbH*YSY z8#3YSe(hSz%#zBheMZ-2KV-1NcCzLQ@O?DhG78nR(Zh>}b7yyV%fz23?={QEj}0Z2 z?fSod%|Cw-Jv&1YJ_S$CYwqdo7Ye#G7z#UWp@1pqg3yF)is}#f5kyO5J&0Lf?8>dg zLpmG|#si?lf>xH8dR{1;&V*KIh;f2O;+6r=)s9S+yDcL|J-=MT_y43baO_~fdpV+>Frk%` zB}~`YVJo2=p9a%5F0LIEnFa+f2OLt*yeKX8D^b4qUs-Scs`$y1QJpYRj@P1OQp(YT zN&H>sIL_mvWGr{VWRd1^kR;K5z<5zWNN_^uS!0rsMJvg$Z3 zJ^F{v=)_?ss01@9egFRRXMh8hAH;Q*mfQcD=-#_n7}RtWyP(kETKQKvZ&aH!jT;*o z`F=ZB&;>ik!E?kH4HhW9F2V^OJNM#68P8?09j^)O$!#`IPPnCsve97|iyahcvC#M3 zjffXG{HeS9MM(*)BuP=q`DGPaw+vK_R4T}HUK$4ljqxTO{XZ@M6d5s<_$2rv{`==~ z_AGNhNB$e{D{F(FK9yBe&}?#Kl6WX)V$Dv*u{?kr8JYdU0(uk44;}4ltcMCrF{|{;0B8wQLMT~!c;gbaS3Ku1V!KalAI`) zC6cv|h>E6YKT;L&mFl&ZeDUH%x7~5Ew+N)~gfE+#p7Oc`%}!#AMwN=(HZGB2g=OoG z4B|)ZYz@KD`4veiscI9^dq&Dcw7+xoXp^TP)>n31pls;-Cw?ZoLXpYWw4cj=J?jF zy%pR@A`J|Xol9^Rc276cY6_v7c`myX%e1RY|IN@@&+DvL4D`#Zt5e4+wo^0Vsp6oJ zmp|O%EEHG!<2lZH9bvNrK`z@wG=YgoaH}OSQ8n30AT`I<4R~~vfE^B1Mt1i0oo?5! zGb)63PeYrhRDrO?6_nn?iVUvBN`f09`u1(vtbPp_a3HaAiRaL7J%4bEC5Z=#K#Eqe zE*tohrlxyZO3|M7@VIZ?i>576I^33y{WTsxO(Aj{kLpN`T|%_(V`c{mx_-QWAL_bC z<6}hA7#0~~=dFGx>R7*7*E%7k2LUCSW)5~6x3PznA?H%udFro5`NatJY~rsSr;%{N zR`~qEm31%VlF(ww%eT!}fvDEs&j5P_W`l#f>iZ#5t*P$=FCE z(Cz;Hi{9b;Fhe=hXMHbnv+8QzzfGu48pW59CKs%zz~WQgcsFPkVcYdzT9hoPlm`5kla{{Q%A*;JdeiwOPm>cg5YA+esozs+z?w#h z1y>DDUCcG;rBE;jJ!wLsfK&pZ2WP;;Y5`uF|G0?X*Vg2e*@)FBOXgQlh?e*Lq7f<) zp-;rN7Y>cZIr!yEMmy3Y9C8m|D}MLc^c7ad+WKSiZF2Hl9-GiEgJ<~O7A;R{T+L}K zY;`id*mSy~=VfI;)le0q1jOdH6v(BQqGSd=Y{r31hz}Y z#;P(i(7H7@-+gEG56NUeyaCGJr#n<#JQaqPm!-)U@vKphr<>ItZu#@`Ck7n|vQ8n* z7w2td8n!!-l+rWo&Q zV{_=ep;aNmj=}(VO6r*_sHjh!qGp{zN*W#PzipfIKCBm%xrgH4qxOWf8li^oJ)SG_ zNF=8SfYBeG2)_sIrrIR+4}faG#wmJ_wiFUfONg1d468Y<)%(bK)3KKX|e)O7!>$myj(dXCd{dhs8~UkJYS zPP%OT^k#G<$lcz4ZMo^>hspU8!|<^Rpsd>mw$IHXs3U!i zi9*e#VTCZyB%N@FIBy=n(l*%BqgWMO@f3OR&6~T*9+#KvCrp5Xjl%&LXM79(-QCLW zLtC5DuKKS`Ek^ZmLi_idpND2OU|Ftpb9fk)zu2Z>Bq$ae8(#Kl%@fXs$+asrkN>TE ziL2mVh_6tn$;e>D3!!7LC6uJ??d|h&0NFBpCH^99FiZdsqL~IQ>AUT5r@wKsKRgUz z3u&)%=C-pZVYygTwD$z{To(?H=F)yl5ztNnwr5r;9Ev4`Q!Pe=LcpBB(mXj&a*Rjz zM_Usf8Ts_d6N!}5oMotSTBDJYQ=E*R3G1m4X%VXv((Uo{PA}b*va+r@SytRebL55 zfq*|OqLeRf|0?}$iW5F0!BsEDAEHbdq@dy&TKl~A&fcjIni@Jk63Hury^ ztrJ!aX442NTzf2z2I!MN7qJ)#x3}gA7W}z4NZqwBuJEtmCn#y`uQVmXHng4Qzz?@a zJ<+sk=!TT`Qcu3M;CY+qu%~A#l#!iN;K_@Ooo}0(sK9aqB8Xa{!2%T>b%^O3DeB~5 zoKy(bhTgMsoBn&&wsl^pZ{LyddCJA?y71WDUcy-_DSCHqmynt0>(|`wV~M!kW!W|N zd$>45Ijq62*Sd##$AWv>mhijt`(pV~u|DsG>^-%#H9U&nWL;@2UCrg@j>XbM8=)rE z*WVW&vTDuw4SgV@OlmWC%^awy!UQVyCHVmtFKUkA$Q7n=&q6ZWdva+qOd75mYyDO9w;W&dX8U>7eLcqy4=-&f?Mui@7BCjKgos%vg-& zesuY?=$s;(c9`Wz_(;QC!xnR`PEg2(>fFvE#&6c}dC2P~Q*W$@`6{H5`uepo?Zf@e z#sukb+Ft6g+WHM4k&j2extW{oI4yJzpgSkE0;ZoRW2DS)vl|^dmm|gKV^7cVDDjA0 ztzdmXKXcM6?7WZ&0;S-6 zy2&-~uGQ3~r{Pfl>piMQxSd;ajkz`O*RpD-z{ItTjXJy09V*2^jS=e(vpK|d&V7c` z_8|fjEW=^L>u(Q_9nH+39OTwB8T~g&c`l%z|7XeD!*#JE14`0t(>ACm#FLAo!u!QT zu8s^eRhUn2Kk!NQ$Eh7>6pbmoI87w%cMIOmJo+{1#O9^fuP!_7Tq;5-{qtV!;7K`2 zIYFIwi?wI@av%_ohbv3e)m_RaE+ zA2cIsbaDTD+q4-w63AF{*x0l_;-^Khc^#Fqe=TXp=~>bb9;M~2>!fNJ_9*^_RxXLU zWj@)gpr7T;$}S|OEP2+Ct@+WZ4hkNLx6hYFHQqgJrKcfhP}A}^=SAsS`;9=)Lc#Zb z(fZ{!1_Bogt7lzD?c+EP6M!*mqDL_0;=}HV8B}IpSY>>4RJ5)k$<6MBTw{a9@qh`l-sCn%rh7)8PmpyE z4-nFrc+}a}3HCHz{Hp2#%5DYk)?)?utxnPAB~eYX$(?bdOFJ&S>trqCPA>CiyPd>Z{K{^A2sH zPl)-mmo)y{7s?W&sTA{&{lJ=OY+qy(WJ8)adEHKMmQ0&+WhF=FKX~|T&w+EkU0sW} zA}akAgD>qZ*U)t5>EC-bT!kV-t(x*+`M1n&eX@A}xE6*52{%LB_gY8}A z>ngIjpc-_RllHO3?7e1ar5+bs*73SFq<)n^d6|}XES6|$HAKg?uQ@R~cO)}=R zyW;?o9oSEt*9ktVLbw9AqPI*V;nLD)P90%g{oG7t`Q*XfV`2FsZo*~~0#-ZQqD7L3 z<8K6v3k|{!rm(zz7w@B|S;~kxdG~$0L+ywBy949*g;U2kHSde*UA&+rmCP5tNTf49 zIajL5yW2unOtqdVhVoEeNW_a2)wH{M-qo3JMPqZAojio?r9y@dKz1qo`jU=UE@tgi z$SbX+f}uJ3mtx`;v?-x|JMV4%hQrzaKYn2;h3-&G(rmDK8^g8dB?dt&?T_S0R4Z@q zwaC~1@ib)~B7bF)F@ExuOvV*T51Nc|Z>-I)+HvgvbxVyZo#pv>?5;#4f2u!`_<-Xu zeaGh@2}yy0nc3t0CoXOd8{0Z5zG})mPIgfWPB$4GWFCxJm&mVrsdGWu$(N+ zx@`Gkz4^nQ&r{wtvf4Ih+W#07dKJw}UmKg9oZer1aj7?*^f11ByY+F9a^1skRnebc ztiq(|R5rUrS7DbO=oZy(9c4)_n!6}`pV8)2AE8oEA>0 z1&e*;=T5z*k@(-Uy8`P6J5L2I@WKOlS4?YhG8DDlZ%j?`r(bB}sZqm+lXB-lKo` zBp-?UbqQ|h-kwGL?xUWvM57d9Sq|Q`(?XwWY810OQ8UL1f~KGeWr-(BFpIk|INrUR^i2uS@`|+B z7HLWFfVpK-{arCCp>lS5B&2TXl&Nc}mQMnC(H`xH!OG!V3%2{^PjRyN;z$pa8h!J8t^Td-*S0Fc>$CV2px@&pp}~6X^XKfVD3XiHUk?TbhQ-; zW)j>5T^MU4MJmX(&zu1(OgXa{MoUELXBQ8*luo(Gq_@L09QL95`Y;LXwEa0VgAN}` zz+U?=V{_13Ly{pSwLcVi+&TSn9pQd7ve90BXZ4XJE++NigxOGN6+gVIDv)toN6vHB zObpOmC7eazhNzW;ciBE47Z-2PIP-~D^#Fh zfrHZzKrF!;b!u2cR{P|Q$^pRf=o@AUqfcp9PIuE59WT(hV>BM;1I*zIYrttUK5hl{ zE*Kp$*uJ2vm8~TEg#tyZ!;1?Cv68d5Tx!yKZACKg@_Cj;6J z7Yjl2XJlfEjEI<+cUOf|sDHQpOVKZLs<*o>FZ(aK{$--ex|F>GZ>pu?(vsY*wUUz7 zG~+s>!#t#z7 zC}WChMTIoz7t+^30bvi*phG(xy+ck06vGkfV~II;yTrzw8K~vFQff21dm=nKZH`_m zXQIFI!nx{t`;8YR;mMW^t_8IY<-Y=RNT-CuuQjfR+4c?&gAh*washq-R0T`T;YG?= z1>R^#2(1zeOWl)h(lj;<#*#||0E@~Qy;*EKK#3yvQIcDfRKQTL&;SfT;u_3z(2KH{ zghV|*pP^1wAjbJ+xONJRwJ{3;UVPYZ=)oeJPq0RD1_Ud5`t7`Dp~1XIwI6{H7&Pe) zG@5}5^q)TpvzMR^!#*!7+ey}gmJ^^LSkRXBqU{LGPBI0UCAJxQJWucZY~X8^!Pv;> z{SEXUWrb}ci#cQ zLSB9V>F#s?>wua;88Ikes6(6Fqnc@Z85&COtiWd)a40e;K;$z#+uGK~|B?Q}z|2xh zX}H)E7y@6rb^}Zc5``4)X{;etf!cXFi+qiDz?A@QYs}=GKZt*32@9O@u>visibKZc zut%`c-X9WKN_+1=V~VSFkemqCKl>uwSD3vehiv7W&}w9dbL`czj656|zdt>L})4wxy$ z2w9Dp7@_*3!wXEIv?zgtBpN^B$*q&~Bxm1eU}T^(T68j{jft5VE%rTY!_;_Kq@Kuq zbYmdmgE=sltWCi?TdC*d-d~0oTgu?KR>|gAF=nqjgVn1#$85 zJ?*l?=WBdHV8thbX$O@)@JAJI$2&E1vAqZJa0-&G|9No# zL^uLu=J=Tc!+CQ*j;-q$ zc3^vaEAw=?>BXU@o83v!r|L7(3`wevSY7Q?zzGJLFokc=Hv2n%uRtTz7K-cp)woZF zhY74aWeM=?vOAksx8=qi&K9OuiM_%=wY|ydag0yhsCe=EdyLnS-KAWio{gzFo{Se6 zg;VZn*9?iYyfQu_NE35M&+5&QVd77HLdSr6N0Fs6w|du&(yOB8jg3T`-`AY?Z>%mV zGj5#)Z~WI!Z`ry0H0v54~nYW!NoSNeDE6bNn{- zR2xPb48n2j%NHt39|~}aXe<5dT|d{=&dpV3cr__Rzo(6CWR6ZMzRA9tf^`9{JCUde zAXXfsHUv%u?Nc;q8)U8Le;NLuuSQeogL&_v<7F>0ucr5weeefT5%z_Va(S%B8y!3AC0(L;I@J;x>p=(JHC-wg|^;uTk0?*eD*1I zx@{;EoxeT9K8tOH(Cpo`gHWHX$LYm;a=1ID1FrwgPcH}`6Vt6Y-VY+0#fi$~^4-ft zo181v_bCM3)g?BsY~bKn_*;Ea;$$q627}346TcUQeD)Alv0DNyW{$>fshSp|SYW$LB`Z!ra!5<%? zdEH!Nvv?;OuDm`o=yI*GKYicWSMGYdpzi68pBH_PtsVB-kG1W)6|{%mZRktCeaO!E z(5`QZ)&S>+;m*pXrmCg+!Tq;`>Jbb2Hd9Js9XBR9NJUV4@y3N{fshw;Z&X@@{!soc z6_C-|l7eg}%yExvy4cX{dO`6fF1v1-z)NW%191pt1EY`fbK(2sqRDqZ;?KtH%)*{B zt8JJX3y}VBiEhp7G3&OM{!5OT>jkPef`2~ko(3-OXjMk4x`cb=H+fm5{^$%h4=Jxj zda|>q5cc*deLq$R~x}S3uLo;xc7e4sEk35a&`jW)x>j}=!-{hEU zNok%zpyi7~t^)6B*Gk>}tkt4hSNEDWLkkw;JF`u&%}>2kQIY-y@Y9HFzw*k!U7 zF)xIRfXym+S1dC3xB~ngUCxqwitZ^{=Cr& zy(NuwvKL zlS%c0mHW;RRgmEXX-(0J$CO*yj^+=PYPwr?S=L5sx!mR&Ry3my>u!2)%1CDFv= zDi}Nd^HNP@Tv{}?x8?YZ5@4H};@ppE+ch6(G-L7jh1oF52yTaLYW?C?5}L8iY97@l z7=b{P7At_7Esd}Nju?i$XTQ|MdcKh%tOdo=wQP^Qc_zgFW@X#wA$GwmK7Dwquda7Y z)cS{Jp;a4A|9bm#)K7i{blE^!dmqGYO`7%ExN(^%!~IliCIl(D7+cVL$ivmqwqH1CaK z3xkCp{EyM%g1a)Rs1uQ>SC;*ik>jaVx&&VGkmu;76EQ@#iv*<-H1bynh({z~?zhNYP-ALk#GNyDdY z5saa%KDqwspHf$UL#MiSXI^&g8r;0alTl}Nlu2+h_+6>Rlz<(L zC4Ij%b}3tSp_e*S6UIgX0ZNHTm^Vm!kOJJ=y*`gg0d-<`V{Q1 z?g{6REQn-Bx)DQ^SkO!qWc8)=^Je5wh}S9+>Fex-^Dp{CQW4vYZ}&^9Z@bSa@Kdh6 zrL&{lGcmS$8fvBC4fC+#)?iX$twz6 zO87_MrUl})YRSBZeW_s->kXYbe!54-h2{Zi;Pma^FHf-qIC2M{;&Zpc#fI!ptAOzY zrp>~-=CV-&#Lr(OkRwlLa+tV{V8+*N_+h{SW^pPvU16@CWX5Aayng)`>_xywITghR z`~`swPy+mLA#SgL2NDK>-#?Sfe|?Jw1Ao#$<)Ob-k1{fd1Ao?j&#z#Qke=TI>A9Ni z%slcQ3vg`$1ss7~>di_UY_3rpz&rsi=w2%=rlEWW3%MunKyQMt!CJ$} zaU@ER*kc+I$#tAG`Wr3@BrobBuf+n~AVs}ZiQ##D%yI6AI)4%F9&&$sEb%l*rV~dJ z$D|$X?0)l1U3QU3-`gL%>L#qb<&j)Ca^fy~W()QfyCws-_QP3Xw;!BPrw^k0Lh z*BllH$-N!~3r+@w*&33;uNP+B|Hir^jSk&%mjx|~fr{jWv(^nH2t-?0u2Q$HgFOpB zf^mO%y!Kc|;pLNtOv|;mfB29Fr<9yTlUJK?P3M#U2Oktyl5L3xygsP+cy`Pzd4H0Y zn{Pda+v!53z0{$?d|D;+}z2u+rLlT`L_UHw3YevO`clXCsz>*T1s{P;&^*)-Tz~a zkAaHh=mmo|u0hg>1^hNXeHUFIo^N#&yi7o8yNxMq%9&7pq)Vp2~tYtUHr3&@3shQi03D1vx!bHC1(F%=VEZRZyBwlBJCO2%9BQ`V4=g(m4^xRMUv0h z|IAyWhiemu@B#V*wj9U|StQGHtciNSwg^kIp^)zTa99iJ}0(4hj#&`;8* ztatNB!w6p-v_syTcY^C6>w;$_9zYb&3Doa+ zBBGaHEsy{!L=J4yTKK~K!9;rW=#*IC6}3>m^DM<*vWr(RC0?zE;onnT9naN@t`!ik zRQ7pK#9tt-vo~vhTCfiXaR3C$KZUSncnPx5oCm2Yg$3GZ+3NPa|1CQPKJUM z3vl5&d-m+!UMjCcZj4%#e`rYF+t`9kRbLR;G4c%NbCAgZ))RfbYyq_e4-?6e1q(p5 zYW6LLr7t6rRUtwEP13N1-1*;4^b`>RNy`ln^Y!dodeZK9^j^IbWIk+h5)aFx`Zf5= z@H2#m2*Mp-)MQ?68pe}p-Ng*)(Zuk0oto{{-TRP)!@jq>uuj>01 z^fOZ8%Z!=bIUUcL%zlA2R5+1>a^oQ_rP|MBt1+mALT=rXVx`8>xPrqL zkrh+lLGyxZ$DbD5z(k^k1$dWuE$%P`0|E#NV7K>r_u!z3)eOAD)(~IRFSdZ|h~o!z zkNkX?SN(%qQFO^(&5uoZLLX#jV0Q|f5{_;M;{`Qe;q=5Sxm!^{putHkC`*|az))9( zi^7*E{W%MFAsqS(q#eKtbh-p5+2?a-eWgH?I*BLYsSwp3wdZ6cMVd$T#^lM(6Y1@T zLj7_=V5RZ=2If$}4I2Bmgp;)$j4A|192p?dlETc{&4sg}S)>P#r*g)zo5Uk*ll|9#y5uEpf4cS_4T!gX^U}I z;n-|Pga^lSh`f;6UkS$4`GKg>F9l@@13H5Qj&=w-JbOuR>ct_j_SnoTMs(_8-hsic zfHiQz#C>0SJFL~0G0{}CdI1A0qvZegAaxUpOHRke-B`meLBq-9_OEhg~adV_8m8NI&#_g!NAq_vKhfFFIDszO#lnxC^}jA#P$FgVt%BN>3<6IhyX z#pC7T(q)?N}cWQdt>&+%k zS;X|zloZV9MXsiR2@)bL?Fy?uIS|WW3x%OGavRHI*cDLQ#R`%_B9em}GO0rnOmEhI zIU*mRP`cYR7AshdEsH$^@+|c5q>~hz{pe4cECHjq$raKr!%{&`3s)pONW8xG31{RE z!|+z}-dx2{w1c6eNSqW_#^aKcxypLOAMiYB)al*qOY24ry9zC4-G)AD?DC7cqvP3JxX7h@AmIRX+skTh(B&h<@zRK z544k+R$bu6HExzSlfquTLoEZ4$X)X1_RRt zLR_Nv95(SyPCbcHdXgHtzzwYYZDG&QX<9)fyZs2>`k_qk-vA3j!5pFP#E699y*~!2 zC!G2DQScRo@GiB>qjS<;yjgKgW4^TeZp%X8>5=j{pUwcrP*X0hE-pUWnz|e>`ck18 z%H)UDyD80;7pRV9gb!i|181x|tj?Mp>PIJhn+5r<{)jZerC&sy`D-;&1VfRYe_>s+ROWheM&{&&dz@ zKGfOfGbZiU|9FTstO20P&`i@L&7eitBZR`Vvv8`d=oy=n!)||R%v2v>aY=f|T|PdU z2M&U_PA&QNP#y^Jf1v!6QjLzqYaeR}kq63Y0*m7P6F+x8WH?_8skd-MjTpm0iW=E( z?h33SG=3d$DPWaqZV0eEmJ!qYmyV`jw;J#!05HuAB-B0i^bx8RYnDMx5 zP_-0`gzbCN_X~>9*?mg;RPO`Qco8i3-*UX+PK{WsQfLFNQ-F1 zane=}FnwiJgA1J7#A6%nyD3A|27I%gG2M6R#4te6ob%&Z`UOUHz+uHQ!aJ#ycx;$= z*L=fLK;z3!h59y& zW3#u8RUQz2J%rI?hG#Kg7R@Q5Gy_%Lt(qA#O_$z{L)=+_OEN0Rn%UK)^JY~c%*xVu zn}4_F4)tn^&iOCXi^_Kz17qo4kU&tjA&Q4=0zatOF}~Ec#Xsqw)zVD(Q0MY4J*ZyL zrjE}1KhWCvHkqUyo>V1X>$C9Cg~d1StwPF863qCTt~s zEcxEIAohgJZ}85_PW_4~d}gI&o4B=q=9r$t!3)Y(sL z!LL%j%Tx9Hg_u?s(`4r+-dy*BH1p7E0sYoruOQpd>faEOsWy4MVz9+^@*AzB{QpdL z@*G-8E&sJXQncCkene%hH+b>Y$*rg8=yj^@gy0A!2i((9e0h}Z;IR9ky=3+Z4Y#3b zdQH^BJ8K+Y^$JkyF@vDv$DZ^yCfh$r){`T37*dDeX6LodI@`EdP;*%{r7b8jW7tVd zq4(PAg&bE5S%9KJnx~#2sqNe5-=`fz6l)u&|N4|4Ws00Q%$`UPS1*g>DD)^Bcz;y= zkmJN_*KsZ|vberHYnpiw^1mJmy+hU}Q||7_s;z)Wd<^H{0}(+M^y=Aj9xr$s?1)aY zO`U&tdS`2VlS<`~Z!njemGYW)9Fn_s+)3zg_6yCbMmw_yOuUvQv{fyCVWD{c`z{9|s)Rv%G6VAzw|tl+@EdDSanLAPBOcO`)7E}q=-n_*}2;$a*lng z^VqMXe#27yP~e?exgudLFgN8KSdQdR`V8^ct0?oA|KRUNhS)=WAW)l5Z%{G4Hb(Pu z+HT;CNxYJ&qhh5A>`G!>t%a`puMD4-`B2q96Q0~RKgwlu_VLK(-fjP(H!)ZJ?G}{( zU3NwZa2Un`2ol7Ev+q!5Bg-VWi#B<_&IrKq|9X+V86}{8B~66iku$#8x17J_z#Sdp zknu+LiOsFP%et2TB{o+u9u93Y`}Cs6y`aHH;)cPorQ>hS0)@9ngtSpd$oz`HBG^UdYjE}?rk>sF=!ip zgc?E5oo_bx{2i2#%RhK|bHm%c=$PB9K*8g`zs~F2&dh0vp_KkVhIG#C5ZL@U+ z;=cHYcE2t+RHxl6x*{JnG{QNu*!FqhHXXf?tsU3tg3W(L_gnZqyyp7lKMxtZaWuG9 zg?HDvdGGMRB$MxZjB7W(%C+a}nPOTSX>@ zHZs;@rB=c+$LBUq5An~@jEgQBkVd7He{0uai`Ni*bS5=4Xh`BTMpi-V`mpZoeTl2^ zOoh4##jlN#LBa$KC*UXn3|`5fYJgbB_~Vf%R#|(mKtBR7JwVt*7^19|{#9H8T#0icU&@m~s(kh|>^+ z*ZB_rvoN&Ay!R4AkodyG!+{*3$P$OqLUt#v+`KMm#O!m@QOnsE{#1G$5_-JL01OSWC4asRnDf~_px7zem;4VOEF$Hk_$i-QAC zBM(L~d{N9?;#PpNRe~5sq$3|q!Cx06;EB7^RYii-bLAkL@`R?LbLOd%%02 zk__jKYt4$EKK(%A@X1;>hC7Wlo=y@o2hs)HZq^-_3g6?zm=7N;~mZMvAM=aw*S)#PL&G7rCo7 z9aRhB-7%Y1A0j5L?>z$(bU@F^$KdeznOR5wCZ;cD35!D?p(Vn;`-HRL=}#j>H&|?g z%aHY$G@kU+Rkt~5eo(J&emX66I!%tNuTbMbuCP{ub=u_q)At{epj{Vf9w@r~d=~5B zst;EV=h-_96OU5)23LxVq=+)!*;4)nfn@jU4$Y5y?!;c6F|Pd=1Cd68^>Il_=o_Oa z-4m=~l&>z>F2-=|+82?uNvBrGt%8E645jk(zkL22zFR8Nobz%w-u6fi!yX0F5ZW&{ z5%$m&z`U{XK8%`#ArfZ&=;(;u_@;fi`$S~6a6XtaphAvG8zq1vgM6>0^wCuyjZgt! zUX6VBrg&8FrC@_FxGkb7PG;9^2Xa{XOhE7%_)rB_$`Xz+Tn~TN02uucUpFNK1k>+!No9a7oxk=jXGj z!CzZAR-}|+dQO93^2RG`gM|~-at)3I z*eKhha(Ttfwiz&MGy`Et-ae-byE$}s&<D{dwx(k-zjGX#ki)?u_kUiV*M`U=s4~=WPEk1s%@0cs>SSMS}76gD&dHti{3w%o^08b!ab|IR5> zgG-eq1EJ5j`eIJ~VPMxKAhS7cA5On+C%YEd z`c=N5=s5<3S>{Sw)HBp&G;{p#SNyy(-<#T+^^9&*PRV}#2`jH>XT?t+gCAfX4G4c7 z^q>Oo-@l(dOzEEPjeROCvt<9r1vqr5WiTpWVY6s8247uPTDmnjE65z=NLvXzBLgwc zdyqo=b{zV)iO1wuYerz{xCx42b}9QSy}o~g^!QuXosfV8nG1*d37A%!?jl{%V+WO# zNq5cIHLo|ML5d9)M-BU*zwV>+Dql>UbU*zG_{P)eEMaG!ruixY&Hrvxt@~#E%>752 z1Bw$jFP~ar|1SG;c}Qt!vNR1LQXGjx3dRCv1rm0aFC3NbaCwVtw2)Y;A_GoG+YHkiJ zfCJ5OKhhUXXKf`nmfMtUYKT~xtpAUuD*=bPZNDW+w$RXIi&9NBF`^P8%P2)mAu4;y z6os-SM4}X;B9yI?B+ImrWSdGQ*(ziw$`-Qk|MTnpe_h}8UA<)dmgl*j`@YY)&+$d% zp@jTSUctu&J0l!Z<<3rO6?XLj0y5~pY}PCx%uM}vEilYrij}d@f+hye(L1w@z@D{H zGSFV85oOP~K#n8d*$B$TI$1Nl*c1gm7}#eiN6LOwGSC#vVqD+WK6m<N(Q304{nuA1L5buURh;KCr)I12mw|DB4na1udbZ}@X?!(G=)y>Ir!d6x7o2TFo7hk>?0G8dcK8WF zPE8Y&d@J8VD+Wm~^2*u0(lh51jbHB3x^TXVpU!~c^W}Hd{SPM8lR!qTQsQ^IEej3q zU5Ehdjmb@zp1pjmb;@S6wOt{p4aR6Px)a)W7gxGjFi0O%DuxB2IroSe%Z#nG`n)`u zg6>dw=^DbH4CFZ_13T@yf$@EWTxeyvh|kfr(AHV_&Y46= z>Q$!0X?)9nbG5XGB&GpLUh{TFw#*eWahx1!X|`QOnKn1-%%WvK_Pg7?z&D_xe~isa zCu|+kDOu3b*jiupL=nMypH#*NsG`tPXNT3-I_XvoF%X%Tuk8lV704JXsew9 zoRlg+7zO<>BM$YXv$FHSM1ufn<$L>Ulw@+p3giOpQ#Hz1SHgzw7N0&gd8XmJa>zr< zUMK*pj<{$B7r*?yt0QnRZ8XtHqZ6qz>qPPm-{fcB+2{~!N`hFIjoO{ft0TChR)FD& zy>~eY>l zYZ@h_{o=w!f{}K@@2=U3vA+SR-6Ol2TkH7ob?eCSzkmsJA=VCV^4GHUNoR^_nO&%o zAC(+Z{tExiHMwD>V9Tea^$dBEgEW7NU)2%(wfaxcRO?DeHQ8P;sFCve836~`w5HaF z+DU@(-#cB4EiZ1=j88mgv|V2$ONWm=IC)`D^>%~hZP2R#nFbAX;IA@sqQzTbu(!AM zF0|e?YLy@|iUylSEtJ}}Ny+ha?ZBRh#*<0X!Q^~nr|V)4|8pw*uY$9tE~uw_4kq6? ze)JYI7Eo}EvP-gLmfh3?rkG#AW9|*6$&|xUi?Fqq$b7@%cgta-aCBX9#av?lCa-15zS66ck zffy8JuW9Z)D01kX%iX6BZXD-)hI|HSFObr^#DS`L)p`v=LHsY=gC$8wF4?tF-Mb^8 zLzy!k!D7pjgW^`0YJmIq1)%-d3w8_4p*FxEJxl{&`;aLnzi^mySa4&?=!kkYRTaiw zV1M{Qg&$ZMewBxF4^#nPu-{??gkT!&rgd3YQ75GeJ%>M+L zD~bcXqng{4kU>jul?+`Zikt7l+ZC;AG`5!ov(*y}Npw7pQd*MjHI8eWO-xWx*7k<# ztWKst3`sXb z;#+AOn}SJO?(pB@ejLxp?$3O*K1EsUMIzOIJFM1j<@l}rIDNH{qncK&V6avxBcQH% z$MZ)94R4AEcmoy$-%IJNtq6}<+u^~&ovVQgKBmTQAw>48KbWI##S?eAGs zsL>BuuhVYc`0_;d!4T_(%=G2!^y^-nI%ICX(o}|8*8WXl)Ykt16nM@eWvMb%bt*9wE$)VW`uA%m`E5*F-m;2WG|3zVgl%zvq3v z*D&~Bk{*p!)zvIC;GsXez2(9%aSwke1~n*I2#5zUi*BST|#tyH%hP&W!?WGnE(AO0= z42Y!#UWC9rGAW<3Y}oKX0cG(8{tdtyNQ<6pE%FaZe%mqhE5Q%*GCueb0v3Tg1RxO5 zwShka@POS{sLBxv53m{j4OaomSxMd8$ftqlbKBw}lJgyeyF&=GIRrcv7 zmAWA~!ayVU_&d3ATy28ioR{hg-N*->Wzhuila_`C{O7wnhK1FCaF)1*+nYmb0q6M8 z%C~P;^@8|JyhJR8{rmUR$cQ3^T;mt8>zv6_VCBF{1R4FX+A5yQ#D4;KgKb40ST4k? zz{@F@RCOQmx8=vP-3Up^ZryfY%`2 z4xTze&H_Z0jcMxKK?wJOx`jAFz*>YQyM0*{qV4G4?uV2fz|D;XKB{38t7$FZM8N(I z0>aNK)UPSXo3oAq*n~z5yvlJSmd_okaIQ6$TEK$sG?Tef)!ot3vKe41MskQp z`QyjobXR0jq6Y|;*hPc5ZBLKB5;oU=nfZ?8=@rn(#a! zKN8Snb@*_|^Kp?)rU;Hl1OxBhy^Gg_7`dYRHau4v-*|g4nV4AU@98=G;-rZ1KIO0@ zS=Pn)c(bT)N=`UZHkqauNp%pH(cB!LkRZ=pl4kP6{ZHf4ZwE>CO?hsxdJ632zlMAU z!XpjtFQvJ28eR9Hhd366ozV=-JnUpR5dF@Z1Mm;x+!~0js;b7>+(8(0b9YB(Rvh66 zfD;cGQb=238nF`zHp$B87<0mU!0TO3cY%*3VI!ln+U&6!_#Dug)7?(IqSL3}t29bXzrZ3_~D>+gAvl@)@! z%%kq@f0V+6j~Z5-2t6CqD;T>`GJu0!S78Xy_dfapKoo(paS9tpzQadr?tcA-;0q}M}NDjq+w9XzQE@Fc6vv?_#i8`@xY zbDnrqP?^6y4|WbDX02ak;mW|tToZA;F_(}^#(skGB#fxw$%Q(DK?<@FrJ7~=&HJiO zat3i#$7kta#vSD~-Z|n0V>0BJeHdSQwjP<=J)_YACXwCuZjWvE$;r6qA1``Aw+#B2l6DeCP}s9* zBz>57=4e}`+5FPy@H6;pu~@?1!F%?~Q7Ct?j1x64ZBbP8{;2q;cj|QP@q-76*?UM^ z^xfL6YM2cI7F0uaeSxp+!jYX3dx$gv>(b4EJLAone<@e`x@5M1Eub;^emwkxlwF=}({T1cwWDf{3iI9>t$OSmBos*ugAP9JObCON0CZ| zG`zGb2k^?_e8Q`v%kxr~85?By0=!HtkMet}co!?q!UWzBbR*E6A~xSo>j9;SkcNMH zh_qH!bs8Ks^jF>^l4M`Z;vYiVvlGmuDEqdL5IwIBjQ8q_!MkUf4nYq^)0psef{q46cd+sEL6h>H zIx5UvtLQjhf9Am!D4XXdCD}klImkvjK|Dqb+*>e_LD8Qr@*B`=L8w>vnZku9NspPY z|M><>sTF#vT2p&%Y}y*m6z)9vmBJul3Ir=YTyZacy5-pkLkOsF^x&d(?h~XKbgTM~ zX}%rcV-w@Q$TG2O*vvUddAt7H14YThhx4#Uk=#RFYmJ>GQ!OO9ukqC|?q~PjwWTgN z!H+?*>A)%Xfo3pckDAFr&7==62Je7^ZyN|1V2z;N@KUn@2rR>H%8 zmYHFKfFIYRYv|P()O?686@NQCL-a%CEJC!iP?- zudWkQuzibQdLt&(Of;mF_Ss;2lQDx)6+Y{sDfkDcEz%Q^%$g9d%Rmwbffk-=0g4ad zQApf~;6nj4oe}l$7FN)+lat$F^h{(NIEG-Iy6sH!^}r|``jE@`61Uw@Fc5SR;w*+N z*^w78=7RabLrNMVDl#W(39Py|rf=a~1CGSL8d3=z^V& z_D9hem}^Zhoy3pcw|MQ|gw!N2;~>f8zyS<};o+iV**-KeHQGClhl-#Dwc7{JL9REC z0>NYs`*6t;&He*4Y8gQiBdn=)R#zJRytw+|U*cn5oLW)c?_w)Dwg-{Y$7dGR2hzFV z)eEtXu%IC_OHg(qJVp@2AV>#K>Avx>RT{o9e#2To$^f^gHs=YXJ9y_-tYdnJdx+_T zBAtar=++JdQ-Vf=er7Xz_>}pJBopqPqGtP|<=#m%W8XWYe`?vHS3mBWGP*&7zucyQl)BEAbO35bo=SmIVDoO#Xux0@_-$dxH~7I7~Sf zZ+MD)G5zoho&o;90uiOIWt($wnGZ2!x;D=b`;qk-X+xFZ`>XM)v;mv4W2nsTw*svf$SXN zEYjUNQm8lIRUsYMcyEhj%VaYS%})Ga8m8e1+gYejj+U<0G$R1v5@O znBP&ksD`6TxZuU9`5%i#r(I^g(D*EumMy=#;>ES)t*zk}?p(+7q`3*gACb9ugEsW? zbW`5RZ)q4Za#qgj(G*$Hm<}adb0Hzh`=VjBjK%d^KWxk{mndUpiF{;HgZvlWrO-Bn zBxm$O690s9|0QFI(l!d3k%UVo9I1h(D3v2!aBO(V-#OWWBo~{d-B~oA=f%Rot(Kce zJoRgNj3Q-_SS3^LY8^1SZA0!eYc=@v;lsuH%RkRCNG|bZa?dUuIhnbX90a@e)Dx|) zub}RITHs4#Y|7PN#o6oFG@5Lnh}n^>ChH|=Zr<&>%-B=&9BwM59S<~C_&YO>%B|qZ zFd~V-CLjrZffFqu^Y1FBc1bVL>&~1Kc&rs5y-tBT*7g$vHGvO9lF@FP`(9g%(At1i zft(cU${ID3m)8yfN}GvM!h&Z3ApFgia6RsqUh^ra2YujM&YBV-du>wFdG+4y<#~M5 zOwYzP>r{T*+CKdh(D!qi&p*L>^xlr8OAMK`|3Nv0#_t*bWZeLZbh9Y?TR-1j%wBeB zm-za9Ldte)NFBj~c6F$f7umG%rw{abhiy@&{ZW`VkGc)VgYcH-WAd zf7w6_u0JdO_~w4J&5KX}^$A8vDJ;UcaH#;&b1w{(AC~^s=%`N$%_wqq!ZiV+L*sLh);X@Aqp-&yHFK*LLqeDCKl67;E20#ntX z2EbCPZ{5D(Z<|sFDAm_?a_&(pFqIc-Sm5u+f2j1O>6Czbgk}ED+>>?VMqWQ(vgtBt zSzBJbSoc)S5kr#p=D$Dx8a*GOHLLntHO!%8@5|*E9q)J5+Ie(oM^O&*7GM2y&{`_s z)v_|F6n?5>zF{tpW7vFi2S5y;XkH7kBb_cA7mrGO z4njQd?6>dZpFiv0y$j&UeRb2BO8dZ`T(ySFyG<^sUv5ejdnGp(wW!)v`nPkl-l~&; z1XNdW{oS(#Oo}~eQb2TmT){;1oq!hbc|Z8xDy?XF$V0#_h{tY zO-NW3s*B30eaKT!PjBPxsW+v7b*AKu@*xO&_pSu#;Lzj+Oyd0$uV#=yJgMo%yyHec zKo!XpOp9W8@D1iTM>JgF{>_neD6#CNV~G$%KW;eYH1H4K>*?}PZVB9M>bMQwo)D=7 z?2YHR>K`)m&TAp!PmpS<%L<-xdSSudsXxxjfLOX#1=*NI(eE$)IRadQBWb;+$xR8Zw`|Ge6ja6Nln`5TkiB`81L+2-_*RXB+;+qA+74gl|3`iTDWHYs(0l$rmGIV zZrk|pLjwxQ0n*1#oVfo@Oqc{zMY7Dw#0L!FI{|{v8t$b|lr0GhN`536b}(stF@E6a zP40jjdmqZ_dk25Ax-=Dk`!A~4XTgRbXqwf!~cbajK6u@a^Auem+# zDjh|e=4g&TFSYlvC?RB#_~nK0F|8^SFMr@{nmm4XIqur3$mOV|r4&!mu1*Fu5m>6M zo{^beq;i;@x#+i2uq22~8GkU2R}PoC*zYxN@yaeGZO)vRilN2}BdqS{DNOjV+Ac9K zO=w69T~u&K3j@o~b{*N(ecJg8JSnheUg;bxLW%C2)yjpWVGzkI6;CmvlLCB z+88!p;1gX*bv1`mI}x-Wjkx&)$7}g`#v|rqGobVBTiC)%harva+bfvARwnKBV4!k+ z-QG^n-M@gC0xmk57Z~KCmaR?=PHgCoT=Bg(TicE5Oe1tD+JGM=*7c6=jl2Z_+*=7l zcZ6>@_4K9(=7OBYRz<_mPKgfs4sJY~R%sw4AKLXKK)P-paLVieL@Kn(!*y0)sadQE z(N!gbhMT4!GV?y)(3IPRz#tJ`3byyv`VRx+ihQ7f0&2@3J>u-!dQg7+CU%+6R9?aT zKjgH;$=NwjX+SK!B56D3prnEhFKmGXb0782O!a1>Er5Cp3kd*(!C8>u5fn@BS=$1j zEs~hyTkX(rD2c)&vqK7K0AX9VKe}x3Li(vQvbOMN&|NL0Dahf!Al9B8= z>qaug4Nwf&#}>Vs5S{UKkoQU=y*Zyis(t7AJ-} zfDB-%1_?-pxZpEPOifKej5u_N5c18lG&57qjsuGTbSGnnIAxdi-&Oa~{yuf`B*8sm z9yT=xY z@d0~MNpgEYuT1S-}aek$71{{Z;s@hS>)fjx`W8>om z?Lqev2=>w4AQlSLX3gLJZk2FJRea!9@IYj=g95c=5-PyZpq3?5dQ##}r=_M+Hg1Fx z2+mBq_nA_^oreHpJQV&3JfewyT_^=wREp}fgD>zgp zno+mm|CcUbM-H-y1^T8K%r7n)UW(^Ib1HHw?b=xC5@lb0cgNWeH)Nm^gf#}zl=wEj zt8wW5VO|D|Aq@Jl+Ykl>q}1wI>DYq!G(1#rsjgiE2?vt-{A_q`uiD{y3_W>x2ca4= zH;+LTIX#QNf=%@SzBdmKV6ygeSy_j2Mrx`97+2_|Tp7pDgSf@dCT~573SFp2(T*#b z89SlKsa2S=>bI)!w^?653P}tUn9`1=m$hiugqVk;Okm19{_0V$noB$9S0^<8aH#+V zHf-2{HLa+47GEJ+BkCuBGeC4(nj4IkN;k;T;mNnmM3SrvnSh2dB{VZxx z%nr%IvZy3*sk61Q3B;-;wjATW>!W|8PJ8V98*15@tHx4Jt(Hfby{g7>Hsp|GJ~mmy zH-GaKi7w-P3~vnqvrf3LTLp9GOUAjLaf~Q|(!{t09eB)BqnN|+s0&swarsq0F(d+W zlI>f!0*=|Apf1T=~ar~4))Q*i0%20x_m#3gfAFk|Dlo&v2T@T!%iC8oQay^F|x z;QJ{th5rt%)eF&CeRG{byRsZq<}xw_3i2UweL`@zT^d={o$4;R&M^M-@CEF0w2i?x zM2qDFumGEqKrplnYFfo?YHQ;U9V1L45XJe}4zXRXudvtG>EEgR`c=tyX2N)*{d$46 z_mRU^#8N;zIxX$P-xSIxrE=^^XnaG@pYtr6rhA>tz&XgrvW&)dJGY5 zZ#s7~nS#54;M#URPz9ww!fp~~VR$Tvz_Nr8m9sLHTMLVhBx(zL9ZLpd;i?21GP&Ki z&<_m0x?#*;0Ks&ZsUz6hYkgQL?R6GJKAg^$=ogP+nifXZ$(9Y|MsnZ z=`Dm11OyzuwhF(!;r0NsqD04n6#+w$k&)OyJ$Zjdu_!Q3jvE;m|Mm0d*Kgls7)z!X z-myav#DuM*K@FFH#1(y`!j^FQqL&c{HRoP8p|8}Cb!hw`_%s=GpYh2H5RbbiQBQ@U zF^;KK_2uQ;Thy=;AoiD^uO=Hfa_$}`gAclGzq5#kmzXZIIB-C#X5@y9HkLUCw}BPF zMGa;)Nd1v&q925jZ>~$=gyRT;^MqOj+cEo@Fh{T*gkV4o#|;i>-1cFR z`izY^c^B(ZL8!((q-AEJM|L{rHMp(MpOX}}xGx6Oiuk2~CTdZyvx8o$NQR4p?hI{^+${;$KIC+VrWXDIS^(!f1W#ND;9!Fy= z7IGLEywAVAqaK zUXUmSOb;wsWmRbe&B2VKto#F+q=sKJjW4ry6F0|El5Bo&-hRd{D3_>(4e$Q&;j5cu z6Eot;rE-0&VcJmwg~7rEQ%m>$759j!{S1=Itu_4?wQglB+RCCTQO=~StgNJ@h0WZ; z{(^nT%HFT3bIV$;?G?Y9qZ7dUVoi*);DU2yAl&)Zx-|=F%{or zP({bMAi0MV&66WLl{3$*H?>W=$RR)YssEPn*NwZ}q^@&jVs6!0isxI9dDLaold(Z_ zGN~%o3HwXRt|pTOf*%>gafx&KUHdI%epR_DWD}D4i6i;igIBNy5SaWMAe}yQE;a?8 zB-An#$I;egl+4b}Hi;dU@D=be*2xO>)JMnqlap3CxX5Ll0cAQpUCX&=0}3(*KK#^{ z4!=WMAKABy?62ngXoZi4-<(?5d9Cj<0TU5EqN_?mZce!mE%?k+Y45$K@{}xl*K)7; z(yOL0l5}YS4d&j&eqAsmr2Ia_&+5 z)M_1|V6YsNxHKE`4c8fUI^&MO&_SKv+)%SvX-RJ0HPbT-j~`6mcLlxMf7dpaSL4)*wvcZiU4=o zG!6Ujx||a#=HnD!((Y?ByXSS?0}E3=DeiUT&&S5J7K&#Hx_sVA7V!!ZEowu`awr zlTEvE&*_lKbHAsLdUf))r!S>QUKa{%GxB<%mW+mzu!w|A`(P)-LEpq=M#h-z&cosK zI&DRl?9nS0wY3F;YL9BV-(G;9kI-H_H`}tjoig?9ye}?ya>%@ov6o)0pAdqdyy>45V6@a1uo#bC>Ub(s~;Y7lN&F)F!8%VP5_Ka{(i zS_6rX)@^)IXD>RPTwr&MoSniXEB&kWIi5-zEf^|c$@v(!C>SLZ*EYCm)S^a7=l#nY zV-`NUXXXm2`-nSeosTQf-Z7m~&@j76R<9)F64A1FbMd9%SnW%CP0onqqSez+h#&9O z^axgeI^aGS<}N{&d&x^fnPp5=yRf1-w3b^7Ehklw?JN71&Zbx0F8OocXK79dK5R-h zFGIT$^D22IC@zn?zvNxE^SL*3gz2;0pvDxw$Z}<_&>ho0c`l!Q%szJAlnQp{m|jRS zoRl4_=bFzD6xE|#vU+gbb}u{-n}PxEh`r4q$Vqndv5T(klrn^WQlZfvWR=NG6%r3< zPDfv2G?kO%_m&XjeKQ1;cvdW|gIX4_&!4f)$*H~PS4Yqc6cLNG*rVR_G=Lgs!9u|twytew;rw(Vkc8>Hj7{k7a7jEV zb2&pSk8$K5U}!g3)Q&=MMt>b<5B$E3qb%jQ>>0nEZ;kNPLA63~et=&ksCuAffBlX< z@T=N*RSzhAA_c^twq5)$C|KIBtXD4Vjl=8Uj$RmLk3LDouV>UJ4kI%I0ZdZccBsv8WFPS^dq;cnPRFJsQ$UPS_4<1Z@Eq*C!T-^2IOYd= z7=T!($hy$Q0{Mv;$L8Z2a{O?6=1t2AVn6VurcFUWXD8HmC}g2r1D!2k%LZO#u4Y%noFOS1qk5tt(};sZJdo_+_gHxarJXB+0;@x1|sizo>S zF#iAH3WO~gq=brb??NkLBb@@(77W?tZU7iTKr1=j0}_xo&`a~EwR#6=WD;jFE8X(% z2|Rrigli)9u;Pq2qOgtIBYVEOZI7&N>~VBcX=FHRVQ1XiZ>7^B|03Mja4M|aBsOJ7 znDXzQ%&VOr zaj>X8ly2rS)@NSE0@b0pn=4yGF7ECbEVfzhC{)?U$WXyGi|T~Z%RuuibY0MY(G*Oa zzOz7Z;rIh^Mny=ZU3T@St^bZZU=N-Ev}RDF^QZk?hsPh`?zI{ROunHrjNuys8wYgy z?kZ~ZMgBzu7Y>yYRF0sYg72Y41|>NB144%h^iVIY$bZYI%aO_UH}p3AMPkONXF5Z%R3R`!45yOV2lJd((;2LHE6i?c82MLPf4U85A% zfuWz5CN3%9prcoYT1(?qDkdQ=H5uteBGbwnI{#*8H*N1A)L1cI&~&uXukh$pSmss( zZMt0<3x>!rEtZ$o10T>qDUHHY>ayn=3~D+9va2IxyAQRPVf#%YYAIAeZFl%<%c;B{dcHd!_1=iT32WIn}rMr4#r5JC(N*X%Eivt6J^<9mb6R zzOePG7BOds-ZtsqndxkhEcpND`9t|$Z}f-mS%j}vMqh60(tqcyW{nc*VYZ=A{R#T? z-GYYorxZxI8|jgNr*|pBS9ebxoe5jfr7ZA`>Md`gkC4nc$6+6wJHCVHySuw^gmuX3 zwJV3+qTpMB^CHH#{WTVu=a>{2{#KoP+q^vMnhq2oIg&go-wVV&iImk$!OZEksj#qY za4mBYOLqNUeB`&2Pfq_0j0&LD$jkHlbuuOO{7j+#5q#UZX^qGBKNsoHySeK7faYGV2G-d>+A6Z{~bm$7j2+CysK z{u;2>Fm55dRDZu(MTgM24+LVcPm4r1k3taoxxd!!`LUkNsXy+oMd(Qsc$(HIRo&Uk zAYmF}WbiB+u*_IY;ys!UxB*GGp1d%16VIjdogF2kLM$VLnzxuTxgru|Lv|4HUTGDL z{9-+K0N#$Zb>c!u#9daXlpozG$c+P$O+!Og_v-1u-}jx!Tvbw$BigI-CxgVSYdvo&6#|V_mAq_+970s6Z}P%m|>4hWs1eJ#t!+EUUJ{= zq8Et|EpbjaRWbmj;Yuem8t*)L2wq;&)L-Tx&pXiU7gJPMxulVH9k!q>>WoiV2d%hT zDU_T*tltTKa!}ilCs;ixOtjpT40f*;3hS79QUGxv&p!ge5U{qJvL)+A%6`DS;s>5& zX5RQ3#y_2q!j=K|*JoaJMj>~wZGKJN6G;ly6`>b51>b^rQ}4kP{o=hFD??M5N(NTV z4;SHF-cOY623K;~Z76kuH2uDLpo3w7=0cUj2$Z1IL58lig6tB6z92ydffx|(RsaAj zb>WWj9%_NAhe3_=ernkdL^gC-B0v7@%p1skDmZ0EU03!O`q_lO6FTP|b3IKTSo#cO zS>ablGm*1ptU`sUvzm_$<{nNNKJB;HkP#?oeq?=iX~c*CDAn7U)ejKW5jg>!N8P$L z)1m&Cp2Sp%(O>=4vUb#nVr*pOymFX?i=Z<=MXOQj zU9VS`#46DE-6WnyOUC`U-CBE*YiyrS>AEy&?${LQ{kY>yRWj(!3o|%IRt7(19;!eD z-0#=ipqYIf;pjw}6v6koO7{V2tFV3qfU&=4XCs_~Bd*vKdtKL*E?Ks7~Db zFUX*|w7*41?caEpHTn4D-%gbLgy;=~hZx}D5Cl#D@Z*p(B2r6;tmVPMIcs~C?Yj^{ zqYX4hsPWX}X=o=^Ld)kB_;tn`MvhbT&=!PPGz5)6Jvc=e`O(U1`BqFR220 z;a8748_DCuv(L0j*dvRXt97dFQ^buyl}-iyKE(>PXCOkNONk!!ZqhppbK>t3Xgs2* zya1AG0rb{DrfC6nCO|qL%THr|=2^wB8l`?PxskS9n@Yxc>nRlK+?hpYYX%wL9PM)JT0y3=T9^+eL*=Q6jE!t`+9n&ppJybG+G99 z1|BVD&a0K2kbtf?jHhncfD_zoA)3mzC{!SZ1&Kg)jM<_KTgE~g50}v0)5D@Z$<3WW zs(J)eF_n9m{6ni!1KN>TdNu>ZF_~dV4)R}zxv7H(wQJ6S1df6znF3C_*>eY>Eo-v7 z>p<7b7AJ4TFP(u(BnzVvAi4blS2YibvO&!)`$?=r)D90yJHYD+NzTW*1r@GDYQB8gI>Ucng5)AV%omII`L#bUK$-a^{Osz%AvNO>Ebh-7tt zxOS&7L8BT)F3mQd1p&9g3Rc`Kst&8L2UvIN&P2*5r07r$MCY4PhAcY25tSLSah;Vv z)2=5|2EcN}ZVM=G1!EB$xkaBBLQW2d#o!6g_?BFk4us**r(du*2sz4FqzWdMmcGD; z&~}6#0eY~Yi#~Yv>@40okw)YBfNi@nXcE$nh&b4tEPNFNVS-KvGJI^xQ>(%`=MQLXQ`(8uca^s865v zqgTA=^Z4{E0XR^p_&Mw>#LP>S5S;HZqfnlOeyW$WU>)8DBGiTut*TiG|(FNR4V{25Y#s(y#101$$|QTSue~zAA(dj0qAas(eKG?{_$f9vl0N(jVnvc zXF-jbIgXRo#H1?KFshS?&k(|kMY9l7A;e(-vFgTiH3sPK<3$nTgm*I2dI&L4C^5D< z^n$GJ3;jEJ2wLL2AYw6A{Ne#jv{+6;hI3_5g#9FnXkthTW}gOUaizc%oKBt;=4?Z8 z^-q-I+mrP`ZmO&Q5-0n=;g{23TM`0rV7?g`lqb`#5z3NquD2l0f4BS$p9|eTKi-5? z8+?9_fK`kjAF)T)NU{wrUzFx0eA&h14KiU0vj8y~PX&rt_U1%O zr9=@~nAvdFM_D};=T@S`1VRMzlycZ~O~Tw)n4zGJ!?>?23B-?}(JP`q7}&e~&1=5Z z2V@!9dr?qmYDR3j+ZL{S-#z;#SZ-3`02~%%6xy337Ed_+SvA2wH7EXMC71}H!X_st zgZT_EdLhFX$ID|A{N{GZ%P(t5{$yrYap`!_9-FsxoArs0O6A?|dREBl{Xp|2a_v5_ z2)zojvxjh)f-QQ2LMoBmRo(kgeFrkWW+ORz%gUhQoC(PbHsf7#8#h8iH|zdNv*$qG;6lp)$%Xnn*(I0L$U*dF2ny7hGN z^ChQeLt++0@y;Y%Q}=y*>3JCm#MQg_S05tQ0P|AETEH;~*cIas3`??rNWB$u{x`!7 z?H*C~F{cyjDtq7v{Z*cqlLJNWd}+V?ug*@H2be{EY#d^5p1ach5oKof_ID4*wY&2) zU0x6hpO{$yU9A9%4lflNpcXN2qLCRdU@7)@+#l4Jo0>Rt>Rmu=G}b}`hTC9c6@THc zp7AC2Rj#iQ^ZXSk*)q1@+E?ZAy!_%8^sSwxZU=kC%TuZU#vL&b3m)5ihwCfht2)oc z*);Sn0_D*1pS| z)PPd@S}B-bGh=C|Z%lEl;IKU}G9r0f4B76s#E8s*h0+^$H}EUb`sgiAZ7(Gwc?)Mt zOXWq_H0Mp|V7@ehfL{s|h+}FR*C>XAOFjJ9`%q-{F6lflBI%-{HqPrt?ruW4cH+dT z*r2bUtwx|9Krq%lY2@crUM+dO$fk4M1M$Ckx`B+ot6n64gN#Hk-orZLc3=07z4@C7 zMeYiD(z&0{M@A;jcq%&k{c}A={9GIezo3xE^|~4#{m?EyMDZCyi6&u6W?;Bm!Dm1|O zzlNHQXdd_Y#hRceXpTDt*;s!q>PTiDCecaJ(xZWB-FJ?*I8{irw5O`Ma-h8@E379g zd?nnkYMhV)rMz40RdNRMh{k71e^&0}_IovgnfhY|+Ko<(mq#v3FX7_<;C=PAP<(?> z-YnnFopa*vud1zz|CPNii^}V*i)iT-O0P}bXG z_-SR(2DpBKbKgV~5$S{gcMbCbRB*ruyZP~$yZg5NiZ;7}+M;UJi^R(<>zs-!fLc;) zO2i}z9>Jdb0c%SpVch%&bKE{Q0sPc^yd4fiyW%M6sW|6AmR{mRiBg%flKWxiu!V0? zan94vD=lFek?51hpG}-AwG5r+le1r4Oq@48X-hS)%Z_Y5{nh5CZ8PZKnwS zb;K4@lNwm-iRoy+M+0W&Bk`^T?!j3weJ9e%x5%V4hvEu!VB@8>4^TiXIu5OXf2}n% z2GJee|0r7D_B%JPjhbFRX3EEasMf4&**~xAea29jI@(XCKH+I{_Th% z0LDKaV*&BS5EfWA7)MH8W(SVTuJ@8n5C*oI@i@}rbT!AXYsixl0=8i0ufB!t6}Tp> zBIH~Ej0uxGslIU31F{oB~!f#o4wUPnj zR#_+P)FtW+pg@59`1O(xa|Au}X!EQIoq+%X8m_77cgO{Rp{{gqYTh=u|Avd<_W46C zHtaRlORjtpD)g2w`nE_`BNB}&xih{Gq`8MY@1`*Sd2LWaShwpaqP@LF3mxh|}ux?Ab5xYOCrlF(`^?fJ^_ zYkTvlWfG+}!3)--H7vb(E1;%%tyl4*v&omGOibwhda_-;dC1vh^&TW(KK-{9MWg{0fBS9mGD==vdq{wEh#c$U74Fp=-t`GTJs?CWBA0C7 zCT|t|vg6K<<6(O1WHh~&8a7Rux|tjHm#bI!yxui9H50MdI;EzjY0|Q=*W+{O_3Lnj z?<0fO5BANSM?HjI|FV$KX`uxRMt?&HWvy4axplvWp%Wj>RzT}Q zbs)c{-+f=?E&X*U(q;4_GkUjABQ566Sr)HgaOnl6ST=HNQAmg$chn$Z!Kqo7b0(p- z_qII%{h_o0TBuDBB>#N@RA8l9_#g#?qa_d|NNK@e4IL(!Y4mk>$Edi0*M_vRzq@+_ z+!LFc(1Hn`{WIh#<=vN!IbcZKM?^$mI2g(%D6jTKo&#|NAp?r#1NO6Hg^i^k6*hX+6ZH@Xmt>nO4@Po13o z#)cfR=O@zK0O_yazeB+vZhatyT)<_&I+_6o%#?1Tn7X|emv1vWH45I!tNIF}gXd#y zzDLL)Y?qg1jS~4WAtZsii2tmV$#{oJ3nVOxgn-qAmwNR7FtM=cA3aaZ z&T1vmXtaxc@1ejmqDU~Kes63%%3utka3cCK(6N?QX+-AyzGDa% zQ?68wz8r=PW7oYu3jyutIXPu4LjT*}-~U9s7uv6E8ZqPk>_mlF5U8psRDls*bNc$f zr?1xKR$SM+m{-(@v=wa=m;eq>q85MS(xFRWo!K)LxbQ0e_lURsW3XuH{B#>z4{i^W z7gk3QO$Rm&-Oz-JfyP(M&)&z;dnaI$Gt5Ru4+%~5l7-&RS zwDrL5ynS-f4Oupj>IE1CJ|G{T#QU3N` z%<3PA>cp5a_*7*#zcn@abbVeK%&z+S_14~p#wH+CnGchl0h!?s%n<^6eV?s@YN7LV zVy_CA6rQmu;OY|I5_rB6@RYf<&&ISwQzNV&(sw(;*vDl>ufeifi-qwb`<0X0z}R>$ zqgE*G9mTK-gY>N45womg@)D&FYr4_%U{R;hNWgq3R0YlzfIT~akh+iDJj)jG!K@G;!%~=oN{Cemm#+EU=86Yj~MjUOvLgb(-HzZU! z4NkEs(%k4mfpLmy06}i)@?|D5o}HfGJfh1U_Nu7sZi}N|fXi(BueKZ^I-_=UZjKm} zhp1FYvaH?|gu-tyhA{<+8CED@pe}{D6Us-(*TRnmO(-lqD8G*jI+=dO0pFV}_2X;I3<~@6#=1fgbBj_>A&5?RQT0Xw46XhZ7Qv70G z6N#JUK*f<;c4oV29@%DR6xxje3ghUAe}*WrP6H{mJuQEYzf>NMcSTtJ>b&& z{P#-2uCJK$oua|8dkvPsh7cg9{qAtk3Q0El(la~>)8QG^qq|K^IPH?Y;*)56i&R&T zrvZ4<`0_CiL1#dU5qiSxn;*- zQF5&b@ZaE*QjMtoFD?@2k0m{yoANr3ZSC?tHbusZA;=kIbIe?K(MmewnEA_kNBr_y zH`3w{tiJJSnSu{W?aBfcJRm!|?pdn`Ld7*%{keY~VM^JSzxqjC6Li>gwF!Kc%%YYJ ztBI1S;)PR7u)1b!_e65W1Y~lFdCuls-{-SCjED+-qz$uIHh{60uLplCi&`cAY}2p~ z{N9Fs401TW1l+SdOcpe0>9brZIo}$JlnhSYd%M6jt~@1eO3vR|FqhBR;aJ{afSK{jxtQ@z@S3`s6ZT2>XjY{}%PatVL_D1ODZVDW=zPxVN2X|)8+0RqB6 z!y-|~c86YE!Uvp|91++8$-`49z@k&A%|yoZ()NRKqXl@EB$ zC3ykwO2THsBe%7!Ah?nMVdYCI>?ONp1apuLfZr(SA?vMWlJu8ADRTuhRw?keEIORk zm^XELlupP6mbhgF)tJXi+!@RXDInB0e;h0tg+$7j*nd9}RmmRqkEzZ{Ex;g%l4Wjl z09udSfeN(RrCbUllATldF^J1*whW2vxT0Y=FH3x8A*ZRD+JMIP<})Hb3EP~+zDwK% z+1-ZBWlD$!3T7-yceA#aY1W!ltn}zT3R&MD61a5WBr{eU{r2^$vT0ETYq|*;LGF3U zJzJk|S>q=+n-fU#uu??jD#-Mf`U1~jQy^}e=uPX+#T|e|9fTf2%z|`({^&nWu4V- z79{$JF(JvOLz5M~X#veuWr_DU%p@Q{hV=?@)|J{&tm9o$>>y_>XRX@`lOlyHXhuZY zyWDm*C($P-cgdd;g_UfsLt0vUmS?6k_noa*z9j!PJjTDTc_1 zYBS){9eh18J0mUah9sM27A2WE6;@F+oL|$8PHPHNMIsDj+MRzttZ8!w(dnPPA*x?E zZ3}4qz)aIUx#K77rmi;hZ!=il5hEQSc<`vu73nVR?mSClb7mgul)i4(a2f)1Ze zl9;jf=HaFHnX%BFHdwA`&CiCF<(-<)@J07thz5m(@LXST6qBxihAKJtljzqY4w#5s zN=+X!A+P)5a+gqds#e-uwgpo~=cxPn*k*Q%?ag7}hUvnyMO7xynWN;Ih&yhMB0FG0 z4)Th!dS;8})-0390+w@F&b0v@E80t}`-=FKcBoRZ^Gc36(yOJUl9cH4VS z1q7I?nwpz?AFhtrqjFE(cSiYrmu9P3lnA{F&md*#DalPXE-ng=2lRV`VhRCjq3bFc z!j&yb7di=J30if<=^WkwjQHs0w^xHl%x(c0I6C_NS&S)~1uKWK@0jM3ms?>X&<)}m z5(4OE-DEmBVG3gM!W@C1yt9Qx)caXIlp837nEgUYs;hxd$IEOq4jkI%?K}DtMh0 zxF#=>a&vR@^Ce7QwG1FGYv(P$`WDT5n@eRZ{hD*qf)}StdPi}NmWbHJ_AO8-P3kyR1?FlbCea|0kE@Ewq`A?CWP z9se?87nmz0YeH5B#-}h-x6SNue{B)@08l^jK!GJeZx5`1i|}0Y3p0Tz~u-Di=vLPc(&OZxT)|#EuF{#)lB2_@mzr0aBBakbp1G zf0_nY-`OH}05}vBr_ZBp2t^EYPC?O4|T8Qp_XlVhBL3Uw8@B!6TVFrU@tIZP$ zl~Oq}UWk0%w6Dke1J)Gy%L|+lcWA?QW`k?i!N*@wbAGZ17xs`!C+bFpJlz|Ir(U(AsqW$)?l2NDU&2hb(t zPpHU%1E7OsOzH#-hM^x|zHs3}QxVT{Fb;k+82i2=yIY-LVAI($tZgp%nhF2=)bBE?D=x-jSAF2;5jJ$r+dpfCLu_ zqgv zop@G{!G1L1AJlY1H^^1u5#v4 zKX4zDn&;@{=XPl)!D95%!FB+V(3IJ!B^W7-dxvZ^d=da;B3TF1j<6F0l#i#A08Gg98c&bIEo)802b357LV12O9jo9Q zj~4;64ivWMy}b!WLu^V$FDgV-5rEkt2#0pE9jugxn=XB_5)N*nZPg~hOWs1FQ1+)(ND`&}lk*sIPcfNTa1nb5jeG9F3}_gl+=GghuRHl2 zwM0I~zql0J7~4ZWX*Fs~C;TF!JrNK5tv?*RPH(1+!?zp!ETX zF|4|Yen5#^zsrOHQ)$GrSgh#@CT6C^Yr<}7bs;pTVX_YFnG#Z6RTZ)K;f)g?S$%lM zC?@Ijci<+(eLM!b0pviOyYaPs`>wSNw7m8>0|Y^MlaG1}LJKirr0c)y;sju~IB0ed zrN|Tx4y;O%4Nion3|{`6q>K{hulHa|ZxG*b9aE!^A1~bybVFA5-KkhzhOv4Ax;F$<(;kwylBfo!pVpN-LNNsW+1Eui4aI3B3{3n@zC%H{( z%N#>)#ky8T?lG~kHX0j?q4t0O`+T0y`!PO)Hyqo>_YanEzuT#*8Vmn==3o<%ze{D!+~}F4CalLHPm1h{i8!>5 zQSG5i!9#Hh#4M1>Dq61Q$H0OFK-GgjVSj(j;uI{!Sr6OvUSdDP|M8M#_c-izkAvn~ z?R+|WqI8spTQXt0!CD={It3F7=TE2QTwG;v-G#i*PyiX&n1>aQ!~F{fMOp+fO!%~+ zlF5y(um3o478eex2I@E3J!Dz5bkzsmqr|I|$yeNf%?4J_Pn8ep45}ECH%$t-Z{ECF z17{9cCfqdOLc`bYhAxo^i)|Tqq_vI{Iv_AvUu6RBguKSTA(D%|1dqwJ-IH1N8W0Z& zClu9Cn&T6ns8A>n+$JW-z)>tK1JZ(Un;;Su?iX+GZ@VwUCnKNIj9n<$Sm-VK+!sSd zY%s^d9O_zt!9ZsxRvISRbpHi;vyl0bO7#3=s2HO@2lknfQC0jZt6J#g>S_$8C!_|} z?5X-85p+f{nb%mHR)FOz6GZDad1Bk-w>E};x#@1-Rc-Wi zlve^+oj5oQ4-cbMRYR|V&!e%i5lJCUdgw+P^Xg#VMo?iDY8+I+za|)<;WMZJqU}`{ z;$I+$mlhVdT0mW*F@lj7I60|L5;t>)q~cv~d5azfEGVi^QA*vw?`AOQ?=~$QtLQ!H zatn?q0M$!MY`ZLijA1^Gor*GVEfFkGIgwg7a1ViLgk5Kf{@}Ved&J$lDzz=c2 zLE;U*kEp_!Lx!geSkg5^#C*b*l`H}S8*#S;1`8$P=~Mpr3iKdz`4rMNLN6lh6|flb zjF{c{THNiLfK9{EMJ9~Ihm97&5aV!Yv;`P&JMgu_d@khjU%6Zm$()@r0Lo}1;v`%B zDv{}kqKzcmB1cLbj)~a#pLmAG#1Q$mM_JVP&r!f~?aG2q{tVI?yz6QJ?S1F%?7RRm z{j5O_8geIe;6`EABwHe7F)M33tX#-|Coq}M{VMHtMSw;NA9;u-u1Jl;2NY=;q$aBi zFZCV6#nrZ(Z?OpWB)setZ=2hhgzxk$Tuj&?tEXVrZon(R{J~7T^#0V83L8qQ0UpOA zyOL|Ygn)v`H-h}sDHwxpYy^ft7Hee=2mWcTo&C$8xT(U;LUff|BVOw}j-o0dV#Zi% z@Rw#aBPlDALWW_$JQCSq@!0Q$`Ou`b7Y`pAxVWIboYxs;jc9p2d>Rng%-|C6Z^5Mv z@4-A|duY7qr$oPqdWh*yFK#&PZ~_&)jnzdC)qBernNNwfXN>lfwY@l=cpj zBGYV{H_sk?HyUfHxV14}QCdQ-17cR7++~de;n}{2*-FoYypwpaE_WToi5~;52&mO+eTe;WDL zVb4h1KD)3&Np(`ZS6WJHw4yQaPF)M}Nri$7mPN4K3LZCHpX;!s{`(+# zG5vfH`~i!bi2!pSkdw}RsHzoHqIU0Xs6FRIb52&;^M$8P zBR|z>{}4R83bp7PsbsUAGB`8rI@c1U!89Y;F@R!P-lKtQ?If~kdeEtmRa5=+@7_&a z;|qD|JEBxYGCef~1rod+E-tey*cOi-xx&tAK2snpCy|g@(Y=yrlZ%c=#^4Z zQS>VkwC1yAq}^1%OMNAgcAl(kKW6$mXdtjmS-N&Kpj5zd=f~W(w~;mYGOwhYHZ9)v zIJ9^%qV(XF@iY^RQMf_xbNBC@k}r|%c$n;)Yqss0cG=(&NLEKSrvRK!<1UXuew=Xs zsXi35=LTa|Ls>~z*)pS>&mqEvP`vocuKw1h(|I4O`Cl?Vq=gr_D}&XpDYyQ2J$9H^ zJir`wL+GZ3IOrsbh@VUMwQjBTlW#HYycmbZGNIG`rJg4^O&{8$tD9NHF>KPc+Yq$Y z_hny@av*7asLmIR@rP}8t*b)nTdvkTm2z_Cj)hI=zWCO5+a4oC~y9M+2at0C5qPC=do4|C;A_Vheq{b1|C6m&4V4ieWsCGKWASp{4j+ zw~?2pC+SgL0EzdCb$782AD$Nnt?!7#xf_4oYxw$QEzT2RZ8_{-$-bxpxJcyAffax} zDAsRZj!dtjP|dO|47AaMi;iA|2O8d{!VTH57DM)9IQ^GG^2dUgN}6DZNBmqUY^h;> zrZY}@cnkmlqC@9HI48Mvg(a*C{fJlV$+h@U;}5KaBRz;XX&wgrJvhB2bzUPy}21KuRMlv_veWh3%c{BLRw?XYlZk^)aM--B4ZFC}k z4Jog`H1O^-=n7;CVF?*(G5_PH|6cxm%cF-YzaBJST&UE2X{bC$ zgyPW5l4|iZ*$$6Oi+v5GnGri-#-L?a@wC=GV|qj4GU|FfQT2nN917~swYejk%ntfV zbI>jw6yczuAgf}Q69}Hkt`}zGx+`2t^Ls1{1yr#o9re?Do?Xp4G&~vo=v24bHOcp#=H>+y#BW ziEk9%Qf|00ww}-@Qpe2g`5Bc{u6j!yV+lEK&ZY35yUqkl$Zj989zo)Hd~h|d!~g!4 zmuk?qD52xKqc%xDyPas=L$WRMtTg0_x{}s9?Ig-X{jgMDA?&T@X&H6;|Gh(v&NN?F zMt#;vG*Jzoej>cVQs5{R`AweoNBY@<^Z~d_Asea0XKWO7GA;Z~x!jlkx51I7cV4Cv z{7FlOycCD`?a0#4UJx(ui&x^TCh{`P_$R$+GJBbN#D^&KP4Rzk2p(kcNhEwR;XCC| z8&Z$GGMyARB%s@9)*{iCmV-srF-_^T~@RUdOUJ9u{bF4Od6Y$ zFr#7`_6b;rb%@_XftVBGj@Yrnm>RK|re9hFx}+9!ZhE}CqslnP)iSP_yRo;om#UiJ zj~jx4^;!wWG%eoYi*||=j6X)<*A};{i0KkITWa>FNyti5K(R|EiL7VYBb@KoaLt9+dLx}uS99%Yjq>* zC(JCM7K=_)E0nRB92xNlOH$ijW-btOPasA!(^Q9kh}v4?Ls>yVyK#=4z5T^l6(*^) z);s(!wYgJU%mZbUITUW*yveUD5~~tCm@p}%V9q1{q0{nBz+ptS@4CD_rpZTqTgIrh(3DIZiOArQ zPTeafxl8ClLXk`9IwuLn8}Iz*NO%LkxcGYPq^lgA48w?7o(`Q%tjcX(1}19XHVe45 zc>I3f?-u#i*NGoPzwCp zT+Gdfm*>XrmrU14>IZlhNcEm12<+PADjJ3%uoMTVfO9^}Zn3$N!@(pBz;^N}$vSkZ?Mj5%JI;tNk zJH(ihcD)}XzWCI6<^)ng=Jm|BPkKBQ2X+KmRM3j=L>f`eCin}65Fh;;pmu+TIN$ER z)_z#usd91w7ACE8I^v5jt6O1CPNJ;Z#oz}*Oz?Xp&c!BEor#f=a|~3TYz$Q7{z+5k z8H37}M>E?ju+_IV{F7jiI+4zCBq8cADy{s@Gs3aoM(jrCTo$u96g($uEd?AM9UF6% zT0itnPL7Tu>rx*SDzajq(8|_-MD#w)q41wMKX2PP#tJQs_7_P6w{q6oCRmm_e@qi& zkdLVjlecIE4oG$T!-9f>g~^TeNuurJGf1hbs;V1z52UP2JSgtXnS%qphg?9dr?)tZ^Y75MHf+b}%o2;saN@$Rhm%c$eXC2&?)q7pM||LN66@0; z?u*r|>x=agZVSDR*#_n7UaYH+NlVq$)ugzG6V>}AT<6-f`rJ1j`BqP_&NSb*w7hiH z{a<)|$?Ctx?DF;H-K?%tU3ar@7TKn>j)>0vxaP@b%|x;jzMS}dWwLy7VI{d`_{!PR z*|}`@wef;Jw*kMCuT*X)w>T}2q;1SdY|I1+{#xuVU%PSP$e)lR*QI}_vrCfNEV{?% z^Y6BQHJh28oeerF7#tGP_i(Z_+jZ!)$EE)6zV-RJvG$GezV&hM!}^2>#m{Xy-Q%*! z2aI-Z<_aR`@SID{_<+`vuL+1M4Yg zAB{w4=~oJ?>Sk%)?Af{JDQEZy?AmE8s~|EmQdU;hZMijGzu4hSc*B(FMx(*{zo96D z^`!GIc$fuo!yUdhw|yVqp(%cW`j?5Bb~S7V`E}Y zM<}X_Fa3VdEEd&ZlA4ybF(|QqIj!~B;k-7B(zW?+er41NaEuK&TdYdj)%34lzn0+C zPM$m&#&Ll$sNk2&*y7?M!f$0|C3Xk?^z-LW?9QyqT2)n5%>A;ZpEvGjWn~=-sLghp z%giqMrSqUlsjSTY2EKBB zrkzm+ZcD5i)2#Ody7QXFSH7NaX1ior&>ipkuK~wC=1|;=4O#jV6QQ{4&eOAHivvVr zVy~4u!a}^;@*NX)@x^|x^5wQ{GRZe>7L#QwJgdE&;dkuq=jPfC>J>e(kS|*0%hxS8 z{xzO;UnuUgFYeW5nV+s_bzd5aI$$irC026tbFqY|XouhVj7W@fTv z=37@6Ba`%%D_1UGzWh11ueZ0SW9#d(Lmja$#Qm3o0t8-f& zWWAlIL#7exY0l4hG1%*8pH*Y8RRJmq$6wBftNe5ZiFb6vIQ)}dHvK7{EbDG-^X|Ni zDBR!QkBu(vv|J~-uao3hAJH|0(#fnfmajIpm(5?0q#2lAoOD|#_Ve3ga=i>EYu#vR zWhK5g+qz$D_WSbka;vJun)`b5#sM-TTieaZsg}o;mX?-%vzXK0n45m3chXHzLL$Tq z_Bh__*ta%Sz2CrjD55WZ`o}d@zoe)6S17%u1Y%@zgJhHMJbd^Nn?T*e z2m3JNi`nzc}UruND6xtk*RXP4K@cZeXvPBIk$7v`Qg#44(r0aQ= zc%oM71j}0b`ZlueKRO+)#7E_|l=#e2DCK@;;pMAxa&qn~-F-jD>^Uw}5#JHM+|4eX zZ_9SGzk7EKSxh-cTl(?|h2??6<%BfI!+2y}11z=7gZnMcp1+7G9zMe-A`EQ|YK}_kmg+R>x^0kl1sCT*y zdG*R%m+FF!@<-PZ?VcZRFdL1+l4^&n6*V}|htS_p% z{X6)2{5%y>QA)dkd#|NHc6N68%r_CLYHl8$GPvRk0qm5%%SZ|=+xfwRyz=sL&CF6* zaHu@l$v59jPn_4-Lsq3+@s}fb5QiF7zH0j0Q!csXwAMSa9osv;pwba-t}cIcqn7#3 zG0|px<{m>7fAIo!@}@Uz8b_f4tzS(5e(Lwy|EYK4Bz)(J!7{CD zE8;pXKO|T-z0b#}ia3QZD0tz5x86Tey!-m_@MlBbgaQU;<}-AZMS9eCtEl(yFQ5JI z%GlVLXmfGz#H1@p1Y!CU8%4UtXjZ|mmoHvCGu5H1z3)1Bv{_=KqI;(S4Q z&M}ZQK_e-AQvUGU|3kdUP^D!NGB_UUiJm zzkA0M-<;Mu^32Ey8NQmi92H8qcZ$>-d^L?Ur>hcXS; zMn(FTzGb2i7&F*FyEs2PE4r~dW3W1K*r=$Q*EfnYRz+f==Rv;izVv5EP?Bk_MCbLC zD1Dcq2rY5ZK_rbuB&5>!@B6KV;@p-;;Mk;4ITq*n&f6%zYWp_U7tnV_E0tlb(Msex zenol{>1lDF9LBp~)lIDHQ@+T@8)Y9qrnXt^lKgJY&l5EU8?QxhU&zA}qHo7JBXJ^} z{B?MUio|X0Q>}5j1{aDbpJvi6hB`yu)hSw<*)2HVQ+B= zUFYg4c!{U0HFYx2UbD%7B=jE#3aU9)yJJb;cmvreG9o^G`sCv3x(bVmjf*4ql8hs* zxs^AVj806%#mAQ;n{JwpW@at#*R_Sd`+1$3nwoWWb=$-&9hr>KGVcd%`$k zU%g`6&rG5XsMXE-2|LdBWpOb#G~DKG{{4i5z5PCF>bST#@#W!UR6WeBtmW3k9iO5d zikou(R#a3FiN{70(4xeV78Vv*kq$DoveAC8tvzym%51FP*|d`l$(+SkdSV1((BIXZQ|uT}-g8Hc|-L z>1w2DOw&)KgHyVrtA=FuIbzdA2PvM!Jk~8T%R8d$YiFSlmefMXkV*1n`0>|arAIya zK&V1q=UaM)3OZMYIU$ZZW*VDV67~(fgYR z6qFX{!bKlItf3;`Np)MhY0=L@fZ+(rR!N#?x=&PTMDn${UmOYGGqR}Ulcf1hp8uD( z*aThFZ9-yg()>i2#Gl=NL8?3dW5+~CAa}4NUeZw#Jh0#@ z?!Mb!gvx>JIWbD^gyY*ukLa6IbGN)ybJEfKPu-c0rgN14_)_AX?5P8JwXW(g@5-SO%ts&kh+{!yePt#21#>pTV1`Bh_g(B>?CfMY^o=C0#LRmYDU zklKGze;BKtqsdN0{D!m2e+<8M(crni1xYhM9?Y0T2 z9|WX>T03HrN8w3YKimp?=u>I-B0ZJ- z`CXEi{D`V&$TxfLCo!H~pFG*#{1@9egcQrldF}+Qp9$YZUfu+PKft<8yy^4UoR3r@ z+yAgJjl_8;Q2wGdVUEAe&rcyM+VYJHh$C>*)N>E4U=E zdBfuL0}nP|dwBLxn9}B(pER?Z_-vk3&%=Dv{~=8AGV(;;&0XKSl)2b*PvEF>D}8`W z7zcL=b3iSk;ro~Im4-Aj2TuG()zoQe#!zP|09ez<=!0%nGwD17m1uJ-e~@XCwX|2I zVU9LX4%uX)5OvT28TIV;K|7v}u`61TsOi6OOGlwh>}NuzRnYWmQm|ogI=yKqMhh z*4uPYjdc$2F;bCdwkfJVU%psx!`(Q*(_h{FPv`*fG_9UQuMXx9|5@boaB~BrFigDn zGPPwpvJ3Yt68e~J5n6A}%tK@zsdxO7hR-LIFZ#Dx*ca&m*s&DY>j^Bz<>A8?E&v;i ze6w9d>;HA|n*foR3!{%wU46ZCoFHS6OQ}8`u!i3y6&R0EqJtYmV_n~x)@tVhcjS!jVVRkb9pxWOd1(~_xPau~(+ z@US^h%35Qz81JK+%<`JdVvwz4V(!Ktp!7DhOl=*JO}4SNMm9xsX)*sTq@w;@G3DRq z;~{@1Cy}y|VY4(vgoK26c`If_zY<+aS*U$?dQ_k*{r&s*moHx?CME_3*qdi+jdR*8 zP@$mg<34*f`7S!ljz3dV*6!{SEFl3&fR4`^l(|}4zyI`!tI_uUeXR7RuCA`OcA?$K zRbGagBhgKNP*PjucUcOks;CGE2uLN;$nHUBbN>AKAlc&#RJKflA|el6TwI2}M0k7e z%53AJsOsv{<%|BH&CL^a7p4%?WXp8YADyRBj&@+JF}!U*+RiUu6uBa>BO`X7bhEC~ zMKlg^o;-;|L!EmgOOu=4YlRRh|Mu-$xQXcO_siI%@^aQBR8rO=R)d4mNMHIkC`!Du zqe)8+#Wx9bN}R3p^Yi`vY=0-D65oIPsL2zx)8kUQhVG3U;T)&v11`ig*$Iz36z?V{ zN2w0VghK(wf9uvQ?nch=1~l*K>8CQ=bkj8yQ)mOP75BQ?+0g~mn!gkm6}9ANOxO4_ zI1PZvA|DXlwe%lYq7ajVaP0i~68-FI;u{Svw7FB^o2Gx}OhYbHK<&@=_QUk_+L2A9 znW(b{INZIy)l+|~BivnFba|o>F#0CXMm3`3Fzqztb;9le;?w4?n^|36cFEG5aVfPb zc)i%Y5D-{D^P7qfp&}hk&!zJVgHTT<#ob6sj7k3%sN}Ih3{&D zZ|>XlP3}gvy!b#jX;;t zmeFJeJm}w0Bhr>>Cvf1d@p;5*AEVUNRGdNcOpCeQqenN@>7FYoM3O2x0r;4#Knss zTCS$k@gH`+ARId}HN_jPL{I76+j~=z=KW>Mid@UgHdGuLx0!a7Sxyb)lztu3&A#2~HA z>&3ml+S|3VG*4_Is-A3r|NaG87t>8vLfpVQv`aoXi-?}=VO=c+{IV)M+tMc(M zd+s&Gl&dLM56GO0Py{rGe9z0U>L$T-7BveUB^GVOwj(Asi6BYCbMw;^x6kM`g6dS# zTHD*x2wz%SLX!yOUdIqd7=tdcJ+_qBi3F`75M!$2;Oy*-+i-N$iX2*BUk4@$BFtLo z>x?UbPKxr>02xnIW_I>{d;5sN!mH_IMId-A@~y0_f&)>j=a!cna76&@#Odk2sY|lS zEvzaS^Fuuq@9i>Cpmyj#v%KhUC^WDMjg5^{OI7O6RMN2f%+&Sh2qq@pHIoK~tXy4P zA3YKSeM#%r)YODXo7^JA$CsOvbAXB*6;WoJXYfPOxY*cO;~a|ni=(4l1Cj7lgeBRe z&+F^rRe8d(@6-r@#Mtkap%CLcav^9p=Xig=VUgY+XMMU_>|Ay`Km_5~2M-?1xx^a1 z08;7X1ojK$8;63>;g}`|L@?W;SBfb@!Kb4dZ``;c9^X7RH!(hbOb&z=!0?om6Y6v) z6m)fTJRbBJ=ODHM{C5ImYnE48F=;2vuYB4+_rnMN3m0Ts@j>s}$56gUHD+aJqbB5- zHzd)?VDFKhL+ZhBe7Ox*rP{YoA?$UV1*!#3g6+71cEqK^cHTz=b3H`LXW*^rI%;X8 zQDuPi!42Bk@$>SsDbNl)i{iPdYhZv9w{;BAM@Uf6y?gg=ezHq%9l;fkiN>g;wYRs2 zgoGgDp`;3Lcnz{m$m-UuLHItttQBhpZ3?8z|X4CU`D zVeo7esKuO}i}bT6CnxXUyLXJ#JGmejqio+p6Hp76+~2INtE!lJN0K~$s(W2-xwgmj~~xFEoE7~X69Db!0RO6rrN(B z*`ler`PRE_U5_IV7EpOuXB&NT7F&?#_($?D?zHr&1R_Q7hcjH`2_2zGhVO%2dBC(g zwn~%@HT7P`GUnpm^@^SQ4Rzs|v}Bc}nPXx-#yLnVufz9xK6Xx&pZ#f(KPn2GGwqv4 z)hvNbqxjP&f`8Q$&I>ua-*GGsJQ8P>Q6H_*lB5A7PIRmM1*SKN0IHOU8lG%h^g;KG zo}dL|ahru0YlpPH#Jf0ThT`5~iWb8U+dC($Zy#GQppyaS=1@$$Ek`T1qj8kut!#24 zK~YO9s@LjlgyOhEHy9#2VX_Z4(qSYOww}8$#BFRqAaVJmhds0Z>T{TE`%CZ6*96|j zCO}k@U?6K_1eblKwEu02hlieGd-`N8O)#B2UoX=Wn`bQGPp5yNxgOAnvX z+{w{?7L_jCs?2%Nj#W|}B&COg5R+(gj1s3#W92_hy-)eBd z9ro|vKWNe>>gYNoAg+OS&Wg_Q4F?nTs0Jf4LfAI+hGCB2ceQ)o$F{u|v)rHP%ZQF7 zt<_JBwB&cuEU(jq4^2~JuEp`=wMV;l-#T)^$gniyNFTY^_6YKXqAA78#pmwR%k1TK zq??BY;PAdH4s!>(FiZk;u@tDDkp1uVXph`^4G~7IZKL~RnA4Xjqz9!cM>rb!Qdjt> zcJ|hjopbdz?L>~s(mYD({cmX%RVlKP@wVaPq3@qiEA9KR30^!2Ik0eJswlaKa&_B# z@5Hm#$DKr3p61pXtJCeO%O1V`_{{z_#Fy_EhMDd5**46SR1@EKTIy!e--%jGcc7hW zOUP$9_$GEAWmm;a@;v)!BC)B0itV)olBC`KT<%QM+s|myHHG2iD1M0639q*^Zj+SD zO!z~C1}P-K@0QX1#k}I;qbkQNeH;e(q`n*dyCq@%xJ&g?6VXCW%Y(e4`f?8+Syide z$e-L${#0`{Dpp9kgm!=+}P*Nn*O+g0^JE`mXlroUJ73X5^rbInZe z`;6?=L~xhZeev2LEWVCLF? z%;$5JvG=b;zW0pMwIgp%CPmiC5P2g_iSd=cG)_|KJ`~TRSq^BGuJ<|lDKBGr7M_>?sGr_%;;TwugH4bXeC0z=c zvfspJR*T+vT(&36{^?r!XuwUswRx}DCWf$1%Qj59zW&j__~nUz^|4f&zq9fPDZKo{ z-pMMnFjG=0|I{cI=N7uN!}`gq=8VM-;a~1&;zeu?rw-YVQ~&Q3dEaY?=2nI87PQ%F zJ(~Eer$JXsnmMtB=3H5H1#`{YHobAKXepakt(K^sRy*#n^38fnDHEx7ovy7QVX{CZ zA>)r#KoaQYZBu!_=kKL9ks7|MdJgXvF6<&yUHezy{LVY2yf{7 z?S$2zFqbc`x#>iz9Eq6Z}0Nf#g)D zYhjo@VST@{%Kp)OWrWo@a+)+H1LM&C#UzqV2Ku)#n`mds@sP1HQoHT$7FN4 zZ%Gtb%dkxh3w(RH>H(&EWvxS&`QGPTs`h7HLxtjlugd#}bDpaDTv~j)ZAPO>NdY1Y zsgG2O7f})o^C{W$e|9IQx=rzhLxB)RJ^8V3QsO>m{Kg6T03$8;37N{F#|f9STZ;P+ z&eCf?sK%xPA6a!PA6@XRDHb2BSUAzh_wA;=_M@(Gm=|lvXsVC3Dc=!$nS}0>6K?`y z8ix|vEd~>^v`;pV*!ffw5el` z>}HCr>L3V;v))&FE%IGN>{yqGy-R3Ging#x+NO^t@IrzKN{S zTroDM81}qzNZeuRtEzs_#bCtAC0CX!x|ijkbu#I~El4F!Pfr7haFWgIWMXE<%NGBr z=;|jI^0@c*Jra%uumluyj&zWUymiD5iHF>aB(`Ez5M$a|fzA+Y_|On)Vz=ye5fPDY zbABN3A48&pYG%*(jD=*H?}272G+&$uV4GeC~qa z&bmVGM)CL%(vqdX3P?H?Rn^^Il^R?Z#Kaz<=yVeOW~0X*nm_<7pH9vxx+hxc4^RMF zKejS1iXEF>BwdVTdfNx4IJAh{c(!X;0=+Oc-of+IkoQgM5F1DTw9^ic$L(Wc;^N>} z7{u_Q{33LelG{UNyk4s?$#C{>_sH5XG@2rnbo#|NrObNl4Nd2&6_i_9zjg1 z?60Y*LG4JO%hl%op0KpEl$dzzcOCjR#gxr{N?aV=!GR7Y1_r>29Wey|wY4>LqCh8- zlaq%JB}7CknW6P^aQLXfb*x!}i5dkUGcz;#A7vF4S@r{;*?Eq9xxjXVlZo1()a62W z!_%Y}iYX|A50FiajU5Hw8P$07=uwuCdaDA`%u;A*s71c8sHh%+?pd9e`Fq47ZQOEE zQBh}SC%&r@p47PeR);Ea*4NiV@blw`27BoH?(t{q;C<3H04(+N=m{~^g=Hc7GY0YS z@IY~*s-%Pp`)%FfAlchyX1vUuq#4t^P7jamRAHQ)oVGV zIX>P7*GbR-y^J^-Y2`=a2BIty!ovR2 z?EXng04o{yeJDctfA%bNm>qvQEghVk7z9s+H+<+Gw-m^XyiP&xmCFrdg<+NVou#M( zF*-l*z!?s7ANrN4po)+_s{+7+9-D83Tao?(LP?adk_ox#TL&L|y&ByLje~#1dIm zZ^(@Mw;*(m{ zfB(^P&$^1EYaW|h{`pfAy&cFwd`Ga&*PU|`?X;X99;Ofm00T<}-PF<1fj`LWd=(uH z{V)I>XJ?3I<4EV271}1?5Vl3!6gzsvM=iB|tG71?)(`sC4+8l?^*>}A6cU0aG_eUQ zhdqflXQ}{a2fC@n69p>==8E9Zc4K&E2?AQ5!w`Ihhlj(>AQ;z5ZXJ29ctVn1Q)mtzT)e*Z!iQf4Z(we4i!_v zI1~^eVpUl2=gBQ<1PuZmK6+qUNQKEwjA1=~^cGC>pwPx=C%L-*@88vuTNs#_ps>bW zqf?_Ha|&z=J2u*r0FOT;<8g&-8o3i11gS)jX=0+HuVP~(IQD$=)y?_{3_?P}AiEtW z&qOUJ9Q&)c7n!fpaO(GO6LjSOR>$Uw&imIUb&mt2fY*g_oS@w^%qgm=k~Xur=wxY0 z)q9JV0l{F{3>Oe$q9>E2t2O8UR9+4ZA*>XF5If;Y!|$XS$({q0)Z|_ula=|K z?p>r}3ZyJbN=k3$YI(x|#G4m%1FAs`K?L8V@);PWTuN~?2M-?PT_SqQ@%({Q@RdA= z+KC{Nv%O|Je$wNnN2XgBk&tk=wr2Amz&#cB%9cPI*ZlP>I5A=!aE1L;RBV5lwsiX3 z^fODY4JQB4p`r2azLq)Me*~Gy{e;HK$nm=3zDe*zORm78-2iogBhug^p7DueyCN0q z;w%?{*Xw^Lpis!qzaSK0Xbz#`*XHJxwe>C10Obo3u*^C70Pkv}@;(V6AtzVYzY8le z>OGyE(Q$Er&?#=Bx-xm&42Syrm*CG%fx3I=&Ye&^cOD;icxY>TwW$&60*_0V)So+v z>T^Y~&3a1_k>cqnFERxKsC6g~`U7YPu$QYKt)G&rDnv!MI1UBL!pOwq<@z3L94Wk( z@DcDBP$1!0J)V;kJM_l=lMMg+IXp~Y458T}OpX!-nNywvCJO(ms@h?Eh$SS=!KZx; z$q|(S)cHvS6hv)pZCK~*JP>t?UCDjOd|yd3^6Qvd08!i=GD3)Eg&r1Wswieu%EOk+k`L?K%Kk0JG?t4 z#;e!@SUm75+lz}vKO#}zA^#^PCZb$Ae|}Q|+)*+(I2fz4drtu1T>R7G`jtgMTqcQX z0F{J=gdW#RFi=$`PR=YLZXkt(=GCjaEd=GE<4J9ScB~cB%k)L!@uNBa3CsA>Jemf_p!lI%*`&CiZ zFfvwMex}3;WxQ}KhFVYn!eXthd09e|b8~bP#Bh5hZ1ks(B*G?113SV9UfsciS z9qsMD)b~tGUiVs|z_CZhv#_9y*yAeR2VN|%v&41?cwBUJv|p|9XMWG{Po0)k4PFWF zI1~WH7#R_VhlfE~%(;|ma}SI{iaIxEPj^MzzyMysa0K?K!F4@*6FV#b1Er+}k`P{1 za>=4bD5}v2{Iz9n(ZH!xU!Cq;e@Az>h^S~!M+ZJoj^;WP5){XP%_~`1TE4z|YIY+tGZP5Cv-3rk zkm`%csZ)@^JiJSL4KoY7Y|5RNw&NOKpjN;r46R>+W|SSdahUw#we$5vvr518&h^Uk z&%XNVIk~b353Z8jMLDIeJmdA6{es;tQTjR|*>y_5=d66JDo3L&F9Vpo7fr7tKS(Rz zdOdplkQftn^3`)S8etrTUf-p@+E=wbW@Z-ODbDU1T!%Uzmw0kTAxv8R$wJ-Oobi_k z4uwQD3bzbEQG^|z7VLzBVh7p#zrT3sy|`QV3dp^ze>)ck!?~DzqQz;Hm)t$+Gq;lw z@`X=b$r^pP=KUDfL!fN%}6*)q&mDy+&A<)WnqSwOFTnhzX-)rmw_5(aQ_GX1$i9_TTQK{e)pB zc`gnQ>$8!o%CXZ5XMWoJI+Dcm$kFXc$xP+$wx2%FB>mWwNbSpN3wve^)~>D5f1+RY z{97GD_O_Yz=FN8$b$l8O0{NptS2JVMeXlv%iXXq8MT@!ul894#^0TkT>~`GeBQ#1P zDck>57Gt7%Absn-s{F+-ED4h}1@DE6HaR%$n_8+jM`+feccGKe| zOrGz6PDa3=l1CZ3J@0E0B{OO>QX4W?M9T|l>GrKp%$QnUzpOpi@#f0))f|tvR{O(Q ze{nFZ@OB(1uhV)Tr2Cxw=&cHm=9c|L$KQJ7JGOtl>G?qR%&6z}A{!m?u%8)Le$8zP z?@1DJjW%DV{$$1+6WF$Jz^&fz&7QoemGH1~Ky`&*^|vO^;um*xW>miGYRS0wu50d1 z5;ZCRQyiD({NuKz(9Z3nQjb{AZ5+E-$n^Aj)iz)Ix55v8%vY%HyRqncg{_H{oNF%n z>P!YR0~Dl{^`*NHkH)J4 zlMCpt)w-)~!?bYNZ&R>TKUlyv@#lR1yv&||A;06dR6!fe&$;|$lQ)S_8S}qc0S`ID zi-s(ZSbF`YXJ~Y`Nui!i`PE(-g^=FFK(mD{J$@f0&di+Y(ZVhn9XP&OGI`XBSw@NA4!u5vA$<|6zGo{=E z27>dMt!DBvP(_7GFfX_`kWi#2cK9L9~rq zlX4Gew*EgM^?&1a6gHa@tE!uy>z}WddW$+L8B_XJ=j%2B``7{O`dyoaw%FzDcEtGS zf*?CxN`C>Aqax=fSmbD=A>t_LzwDGrO?D*?4tHcSq- zV6!&ob#615p)_C#IqhFHQ-V`#Jb-d1jsz)&iO$FFakIRlf`Y?)<a zgj@N#V6asrX~+U44Dn{-zXF%VjwBEt?%#^g4 zgJiJ?;#f5<=myP1CJ9^!Go6-}K)h@ zF~`|MH0WT7qISgQK%wL3G&*p?Kq2@kEzMV? z8bhF-ms)3+>Z$hSX>;={=Wz%0zHBlJ9-K;@62;s@(DeqKuCO5UzPi(o_wx9&v&g?p zRd@Je$g9mw?_2G0{=%zc6gwtDb)zW9D^oDz=%3X8(r~AY`j68-^q@25jzM&Icdmc_ z9MxrYI^AI3CKJ9+O96$jDFdCzb3x#2p%959ZE=T(&+6Cg4BV}h-41~P49p^b>d@x! z;0+d968cY@T zJ*^%RgW1_aJ)Wm$S%Pufq6uK9jCYS1Z4Qu1l}uHESbLdzY&+TtQyu7G)-fRSMyuJ7 zmzU}qPgJS?S>;xUDOA!9p1rK98lsYhQo!7(xOd*A6xTV+kU@g90)1_<9?x8Db%2NO z(ffSAge7U%o<7?@YXLb?r0I`WUQ7v15FOuyNJ%B_0r-0oplI+>nwc_bPn!VBTns)a zbHFh=_0DQs;}D$D8m=Y9Xe|gVG_4iTam#tI`i;36!x-Xxv*#U^-9bl~5(<5E5TdW> zWQ>k#lMgE&8}m;>B!pM5?u`ZhxjEHmZOSHw8=c%ad%&M+=Pp&gcPuW(PYd<4(+HH! zqK&y!)%~xhI&NM6jQKtPr0=^1?7o_vhfvM#h!2nzjLsGMsNEJ7EyP@f>-tQ5{doWi zP!5W*?ElN65cXXrF+@%TBhLT+@#(XRmSX>*fC60I(<0H38>scwoL|4tx)PefyB<#w zoyz<6d+of*?C^Ab+lEY$8Dd>jY2jbJj_Kw6#!-Q|>B17eW zFD^2KkbT-MdaN+*J;loMGA6&-Xe#V|ECv%zbu=*-@J})93Cj+-O0TRkFY|2=9PYkn z9qVnZr=u?3Wm6vzrNjx^bNVY$Y)gHGNo%+Y6*)$rMOo@^aQF{={wyyX%W~vMr81n+ zlZ^wNALpR8kcx`RE0vS_T4}8pMMVSOv9p9+gX#dy%h=>3Kyi!h54BH2QwcEuV-WN% zm6ejBG}`(+3{=!qRFH9RO(Ji>THZ;}&{w(8%H)7@J$sow6bvw(3HE}MC;;vybMlpA@xsnihTdS7GMx?NVWDNugu0kL=N_^XZsG;T zf|+}av_~i+00qg0D{&%DDz~D?2igG5T`u?Syw2%qo44<4XIAU#WX0n#D~1*j?X;P# zK+H`&J?Vnq3oFo~RaJR*k3-amS>SwKNgC^wf!n~aC26q2&1}9)P@FLc;r3*D63z`=UwJXp{AK^RTC!O2*mP6rv4~8|D11$wkH}d_U z53y$tttbtyABXUOU#8h15agD1*}9aA`HOM?e#{m6dV zg*VVqdV|(;00I#i6?HeCQ8v?CN;2$qON)9(0MWXzyxiT`*mH|gcWob>#-5;MTE7$_ z@aL^y?Uf+veygEdqeXpPJ36;Ud7%6%F=M!f><9^Xd0(G7KNLJ!n%x~8k5|v|@PI)9 z`~&lVdEui&>d}h=tr-|F&g&Ev7Pb{)a$3S;B0$;$t^;I?2uPso>gswad<)2IRHMD4 zW9G*j(78d&5)*SnUmrM_mzNg`3-q+(8@_9}GU7Jv}wN=6K1?t?X(# z0O5fqJOTjaD)2zD3jwu!!oq-Wxc!rwN!@*YtVfUHQ3-%`^s^5OGFYYHD<~)k^a?~| zD05Ee14xCK4b!72-g2}d1qI3rZy^TaFFQMR;+vt%ghxSdEgp|s>SzWC3C!3mZ5v)#FKXA6W(y?V;W$j8?gv(KOa zNF-8@*tfm60?NwDfcb!uz?L*MDTmZo=l=cv{X47zW`pG0K1Q=Je+1%Q&=OF8F(m3k zP}ODuYeUBVKQT@_aGg?pjNer}@-P78c@KwUW=1Z^P9JccD*_e-3QJTJpd5{ae$bULsA@#M?UKj`6nc4cV>kd{DS z0lT6KfLN=dVw;{37z9it;$aTK!IYlw!3og0 z{HnhNp=SAKN3N91Zg6wQ3%+1=zO$j7gL0kf;(OSnJ4p?&7jClq{HbuoFg^ zq@DH9(NQp_DL4qCrVBnspns`e!F(93nChX+hO+W$02>8%GC+p^;g%3dDRKx7T+rP# z7N8Kno-2K2G_3BZ}oUom6db2Z=f)( ztFzYAyXT(-Y6&)$uR9I_C`RAvdJzOLs{HHf%hX#r9Y2542TCF$ojXUgEmBPR@9S48 zcA6qRtJ}9x9)f#>VooRWVsL;odywqT!9>Jr3NkA4%b1bV(|aQLb!?7>iRnEzh;AljwvUYp?}XVv-?1OWOo_|fC=37vRdKIRDdQ-%Ijn#uVC#rGk37QJ1j3sH{ZlDwUk0YzVcToA= zIvhvBgB!vcUZZx6X@a3Ix&9)}Y$2?35Zm=nkY=2Vd-1pt-)r(U6RD>RIJ8|z+(r)GJ;>b`b zfXsaip<1QP`7J6MPbXqx!p}*BFS+0c5Bia@v%~Ep6lG|hVBRpMDN-d3E46k6n}bWO zs*`(R1UvU?y5a0cXpl48`nxQ)ROhn4p<8`hje%GgWTYtsuz&t=x;Ym2BH(md(!04k zac3>OE$s8WK`vgX!IfWBluqu9=NNq3sQ(q?b|NgRvzql&@u+5GI{OSmU?t7hyuc*B zr~Z^XJlWXT&I_4oYTEa$f6v^QbS#}{YaY-ln0$US`nqZCT4JQBvGqWW-=ny^_&fYv zeSIXMcgQDct&rw64*j-W0!iyCUJiLaCKRZB!8bytF2sa5`s!($#oWwHUhBwfzAF7} z#~kg7%m?o7cs4`gAwagGqM}c#jR-F9Tlk^_r4pSs)=Tl-*?Et*6z>;nzSw3G9>((D zGpR&Wz8;qIaWBY2Xz`(f`?i}g2v70AAl!(Z3x*YfWZ_8lA*`rHP}nv#?Nd40 zq1C?~5x<5!PmkwxguiZ<_{EEz-QCr+zRR$1C}SZ0H0MWba4B7%pZ`gkNpBl%v#6aZ z!8}%9A0(x$ROFCDUQH)Ne8C?3NdskmmBK3S3OFB3FO+&&n&rrjvdJJoqm=+}XSXL` zqYD%=F9u^ratOvID(9gD}sUqHN5dpWp;RG8S1N3-E&g)A{Iw@E0p-Ep^ z!-bfr-4}_zV4U3DfvP_!>Y1KC_k+RmD=cqp4s4vdFYo7BHA|4vfr^V#)?Z0NJhXm2 zy}gyb4z{)f(@y&O`iN3fko)gSn`<#AJ98zu#dUR29i1b&I#&d496<;5)}Rn!XS7nP z9?zhWky~Wr2~E&s;D_)EX$iWasVUSgHUnsNF=&-^8m@u}4Gdo#YUE64i$1Tx^S0mzIwBM^_pONl2XCtZbce@`v#pEXW(+(rgs0 z5^jIzTp(^m0ft8_(fU~m+{kPTlpXx}GZOH;OX<{!)q3|;->c~u`|)IhlOhk}$b)3h z-JeP}$?IHMSwRi%BnkzN(KL5dBYwul#i|(jV<^WztOJi)C@%+Xhxc+t;4g=4m!_uR z%A0&?v~>kUpn!2R+b}CxTkEZ#-3MMlL`w({w%pDX<_w@WcJ*6A!?Ku|;Bel#n@%Z~W+MkF1>1S^~I0f@iS2)7p zBn>7BH^9Q^@$4?3hh){ayFJ z_jP~%_*@rpob!Ia-mlm5`B+c5!jK)s5d*P0A3r}dWtEn3o>o%HkR(nU+H!5kcdh_uss=AG2>NTTN}>^iA=n9wzE7g5(+;YG8-p;r<3Wn8*j%irx}9l`Znt=&K446B$X`2 zs#nr|XxohpiqQIw$vLlkphBO$c=2h%ePjmsfc;5-JpNr1qQ_k%k_yd=2q&=C(Y;9| zJ+;`SYYg|>R}1u}x}t?2C2mDE4w*|OPnQC?Yuov!q|{t;AaGqpUgGYp(%Oaz;yi?e zzka=QmbX_Pw64yFJOQ~+sYSooiQx!%xl(m1y}fyM#YP$tLiIK-xM?`Vju4J2B>;H78(STVLdiC z>%cK}VbjQd0q7_b#aI=!UlKOaQs}kuz<*|6Y{Aw)zvSzZhChxr#F&WfOI#s zm?`o$x`Rvm`M0#gD1|VF{H}>nw@PzKI(mv=YUTDAtt=HQt+a$Y(ERmkK%i>+CMwDst?npeEu~ILB^wtYo(ifQ*n3C> zpt(+RchIO7o1xCw2u+x9=b>aTO@s~zr%c<}b5z7HUcBmD8ylmge>dc^xVi=y&-E^V z?e57^O%&Mk3kx{%>>lBK@RDIDfp{Ubo?y6O|UlhzvvwguCLIvK0Ki%`m=-vk~tY z-y27DMHZwM)A@$f!y}LKBBqHcas<1tJnVIl8k$SE)Xn>-M4esPiJOjYsI!yh`^dxu zq+Ew`-}gGxJ)U3k!{24S3JS|Gk2(tuIhR|yxyBEU^%E>%DE+y%21pb25^!p=03B>S zo&?tY`8oxrW)g6`ym7q?B3Y6HX(4cRLjHG6`eQ~DoV+%y&dTQNhbdn+dsVU z&)UjLnV;EUi`E@9bOE*Twu38_JA05PbKn5FOB~}U^7M0YQX_r>nhQYYsc)sRSi0R6 zYo0wr@YuE+1$|Te{QS=?AO8F2%XI|uinUTNWu{8jI8-w*(SV3qu_cC6ZMX4ix^(d( zia{6EDr|F2c6emVE$Rh=(wj$QH00}l3nzjEhe3YO#@*K!_@L`HIA(CF;+&CBg-Pw9 zxuitW>#8axb&^eHXa`FQ2yIe%a6Z5Ent+_<+^nQ$iw87Lz0R;!qL&S*y;N=?l#bmA z_yBfq2q0QzZ?rN*HbO!GZ=hiwasf>x@G(#awT(SCE1LV~&vlzC$S|+StO&X?LIQ%Q z6s$d~P9?X6tFh7OW8+142t~_KV`OUT)*fpd;Fn~n8URn=#2Xp0ue5ws1xW;CFL;i_ zc3Yk?*8|AX>7)z^=(ZbZz_sqdG>f+fZ{9Hp_KLpP&>XX(G4C~KLzb2*yC+eJIgOEe z;TmqTtC!(st#_73#|}Lf?03V%RODbm;Qw6lC z#ywIvSyvnx$|6P#IwBw-z!`H;noBE3#4iXH0xnHdNYB6kT%yxX_3R9hw#8<^9&mDz z!hp8p`bO>PX~AcBWFB_EvZ|_Ya?WKj+_@YwBmG>Q+U9iku6tBLN;18;NI0DVSKW5+ zfB=35I@A&!F)-bHyR6JFz{~s03bH_(+d$M8`G+h96>$3iCgNt|=TNOV$wfEa(8ami znRg@|k}QN_c1-}igbHrRr3KD$(sb0OP|9aLj%854wU5u@E?N{vgz~tD;^>6P%B|9- z(Bz1ZIth}wbYS`X{LxLqY^9J3UaY{^IMDt6v0fcrTjQsePl00VEKY)4W1OH`!glBP zD=5@?Q{B6|()KSGJw;g&8w0aV57dHNCDCX|1vI%ULgJ!e3iCMHi>?WvYMDkTe3aWqAPIbq zk_9z~zyIn`~{XU%?iG}__*TmP_K<2ScS2YOd!#6ST$UR9z z`*v?!s9TVUQ=P3t+jgf=KCC&j%FHonuWJL>v4{6L%llDS>t8S;vBya}j6OwSdT-qI zTlk>iJJj@4nT<%J;AMJb&TyLht4;s5_E`Y1Gl9zFpt(99|Ak+C9$L@tx$teMSfP=W9m@<#N{LKkmyyza}oDUAB!{;QzODK*WyQ&6JbJ<0O(2>?1u9xB4q zBh~y-YY~K?X<6dmSDZowzIxHp4k7D=FskuAukLqGLR3UDiP!bhin70poYRXHA|V_R z{NI{4Fv~am_avWk^Nz}Byfm`6L4{Xv;h91#F)SoiwwCIT$~F@H=GPIX5;!guKEY3q z_`TD5Uz()@c#Cyi8$Q@Z$oQHw^EL}D8Ir<~ZpOqb{GE zzG3#!JC;*%n%FquZPnOf*!TNuP2>6Z7b`|)6hyZ@o7{1YoifcUIq*{m)1GU(I=tWN z1``I=^l$I{IC;0LcZT_g(JI3UI>p^qLMU)Q#s_BAxx8c-oT5tMTog43aHg=~Ew_l> z6nb-$vWDG}ouW04_sr;t#tmH^;VxcC zYOV+p8`6DQ=R|4q6^ehQMdmtdIh)ZLVVj6Q*IHiGPhlUI+(olv_zsTEMPtjz$CpaQ zIzohAzdGJ!lFdjR+FbVPB*h4Y(w1ER&RFuMKYo@za##F#+~yonR%L<#o1|!m+&sey zUFB=9(}Oiyg%Z8TH*v5Y-Sps!R`bZ|`Zx9k zg8^eD*;)I>mCw~@M`CiJP(N83V~M^8*kbzRi&_PMmNb*nSP9W)FyTuN}y zY6=Y!$J06$lIcW!--m0_s;9{ug72GSbD=xZn4MNfC=QowosyB$@Hr#1wTA&w9}2t? ze469OUBuT&XD+^xxG-;|%Vtxvm=icgB{I-OFqH2>NXPzD)ds+-0E*L4$zp`#~Od#&mdNKQtj=F3GL}A zhvU~DgnbOX63@xHp6h%z%>D-FoyT$zL1KguH@Sj9S8ZY3GalW2dr;bd4U?WSPH zf@-<~89AHi{f&$bhGDc}OPn!HFGIN~toGlGsXwFkEJq_~r|Suyj@u_CA~n{DjnVHo z1hst5J{sr}JgZ+YO`n_D6`Fl{>skVnq97-$-?W~E#iHoX*K=WKoR2@bcJ-T0f?ekI z%;>bMKRza0ICMVZmZFL^PiU|6*Uz7Y?VbG39vx$Nvz4+!`@W*&d1cTG2H|$Pdo0(v zYB(LvbbLc<%NBYa#cDo>`-4+;d$L+HsVN;pnJ&MiHl+=_B|a~|$Q5->*P!uL#8_}( z?u9F>qQL`$vwzKo&kXy27GhhUwIw&*M}C<*=fAqVfk@t{~I> z1p9CqUHgnXI)7P1m|7TKUXqrmjyA6n?Mdv_tqpF~)=@5HPkN9=)SCRn{q>BC7+uh% z;Io>->>ulc9;;hfbFqz9HNP&iC{AFKIUu)mTd|tj{dPtyqpaeIzkh3_zt+=paq-i9 z;S9()7=N-+b9*a42k8r&%IU1LtlGA3hTp!VXrU5gJ+VIad@G&v!LrD!O$;^?-`ghw zWpowfb-m3OhzTFG=|ucHm#4aVqh5p%GZS);+}ieyTbaQH z9`uLO9hr{>wWM5&jH;c(>X!6;lB}m^tXctz4RZLTyrCY~DdaN_RKc#BY=rA$*0Q!ICbgeex&2H9l7l zz9e)b%*y8Rm%68-%Uy0S*#^CIuZ-Bl*SS%Sbg63nquk}+PrFP1x_W@)5lZutQXO6M zyl(avs>)k=_HYY|s$QQttp>o?*?ddFIe{sbpon_l7!zA_&+XT~J-^J{kLPPX% zcoJEB>8yK$h)9s!zLota;ubk9Nkvo#yGp&pucygxzOyuEaV=x30o5-mfmgOv`%}E` zo3~E-DmNA0C^zKHqvlp=p3B}-LwGV3T+q4@HDKhgue_tWI3e`Yk-D27Lc$MkXINps z`cFJgoA&dk0rkf>T6_)cMxGyHC=peS-zw_MawGnL7UNN8-Dm#Qv^VM0WmpQkBXyVG zoNU_t+vwE7xJ|lsh1CwTv~72I&p%m=DkH@ZgQ@7lorR5cOBdB-a*B+cDRz8#a__tU zwqF^SrFPU#zSz66S-*1lg7v=a(!`Zqkr=~;$)a$MSfRf;NQ7*_f}QC z7y53-i4UW_@3WTls2BVhe$IG^^8}~brv-}75;p&WgpbbLzV`S^7N!4|EARCPWi$e^ zOVUo$Pqr4Hd^W0)ae-Z1%FtQ#osp}>=kwhHiq7Yhb&UI_^^BdPgj=(=AM;n~kGXjM zg6zZp(*mT2ROvbj9j4&i-Z*w9gLb`a1XBImQBOG(A~Vj~s0{Yaythrf;r{fOYGz7( ztUZ6rl$Mm`8wt8)PmQJ& z2fOePfQ$KgdEVV#dN%9BB*r@;p)5@nXAj$F8ZCbIS&`iTI^)gtOIzkFgsu+D)X7EY z9m+jFBP%#e+qbnrqUBpdSVsZvw(S$OJqh2F?z11EeYS(g;Y(Mz>-B8*&2~}WNmsRy zM0@^xjIIOzH_BP4bEKW#AUHB=IZ*eFkpJ15{6Ei!^fa5C6TZamOnAV|nxm5RI^%`_ zmkv=mqk`|lo4V1AsRpFND zVMss&m%2}0-iFif-&95Z&)`*x264V6mfCCfyZ=zMzKl4-AR2Qhk?GJT+S{fHJl+2+ zf?P?T4J;&n?#LGy9jy-t)z5>xY24e~D#|Z!&n5;cYAG{<3qzJ^vU*T}b2R(BPr? zAnSYmLUr($#l+AfB7T8)O+eQs>Yp|hQxrvC-K$r0w4ozUT4t5M9${d6pd~Tt)3#Oa zv6`1sVJn!b4&jDV1s|y+B7f7)3|ZHg<iK*OfYmY(t1!+9oNv{%{cWJ~w8jmhdC*OUV4+_Dfleo7)K%aH%BS3YgTzAaxuY?d^h z2j8`mM+>-=+P6Zf;|S*mXM{fOCiBn zS0rbaIP9m(kXuUpGi&rhc#&tE?)E5~UPN5z?OT(R=M$29o#CLV|3pZnxwn(F^RZrL z)-%h8jg6XG*U-D%-AbcwRA7qE3K2M+PJ|E=1KrW%VZwf-FHx^!)YWdEGA^#Kyp_tiv>LGZ3!en}XkN;I5g=TkLOgs$uQO(bkO)EQ9ji>cY{2hJ@MXQ!0bb-Fn^3!> z1o6dfzZYQ2gQPMYA(a%XnM}{{2mY;^6+w2gFG(LS%**7`(d$dgvue|**4qS>2$(GJ zeV$(}f7IHjo}3Al!J08CU|W8O_%d_J2&TOVd1Ac^Sy1CofH=#`Jjae8W8(AxdQWK~ zukS9((M`ihv~hC_Q3{cSn;A;1!oL|t?LZ4Zhk<27s4tAH_k;k$&nxH&n-%S4BO=re z-Mqj5<;##cqH+DOlcX0iYzMS`$OTJo=x354QUO3yU~)-9&h%y36j;{4bb!f&Ml$>8 z2cs}^WG4aj=^Tx6yT{G7MpzUceTaw;v&oT>Y@|O$HX;noDKzA%KH{+W%<(?P#>9B2 zGdFd>xeUOy>=rpHYO}ruo?6qwDsb7=)dr%hz;offqdnC59^w%x4*Cx!f0z8SI|;w~ zXT17>@V@N!^TSVd;omC$GLQg1kNaI`k(fo@3d+;l zyVr+Su_+@#_mMf~$zX}3zJ;LmX0?vW^2G{z?m|-u$PW=_3$g(K9+30pA`nV|QdQHj zba2&8MNGT+80dPuS_%f|d;oyu8dpAhcH1xy3>HQ&q^AR0g(uHhzSCuUiUA;aybHw7 zcvK;v3gEnB8FKi)e+SnAwGx0tJcxg1rlAgd@2dR#*|R!XI7^ZCli#|RKORF!YOH|e z0%9vRgS&GV2XZ>BrIKa(#QURJhnyrrBvSMDf~^6IBA?o14bh5K3G({@@j(@XfNQvx zf*f~Wsv-(fHztdD@=kXq11HW>1154XVe`4#rPVd^-yeWY91zU76SA^W-&#r?7iC3g zIOzqZ(V$ss+j%GO)X6G3RFP=xP9nN8~)=VH`Um#tQwEUX9hJN*b!*8Lyu% z3Z(-XdKFz0cMY~V?F4OZKp)pv=Q=`@D4;g z&mMrBSqeX#ePwiPk2uBbE%HTP<=5Xd10E#z(BTNHT1G3ax`q5 z#Bj5sTqAL;8XOuulj;} z+7eJ*Q*+Qa8bd$Kiq?^2jw=ZmTW(xqKM+H1VmRjF7>WYpQ*IB$0gmNdY=+FYA!G4A z=s!9Nr!W!$)?n~F`S(6ec@)UD_8IOwW3%{pG;Wa;-waYd{@WRtRo%3gR|6zDAe4hl z9haVCp{0fTK3Y;~QJITiT zUSwdrMy*aZi;vhqf4>pc_I!0x7;>CFJtHqR7`b&4^UNi|3>x*gE7Fc+x4m>x$XQbd zxOMmr9;=SSY;l_kOnt6g!SaH-01`l{qz;1J=-%{M3fA&JE0ncRw6l>^O3nS7en0~ zIY|2}CX@Ir2F-UlIV+_Ys0OS=MJQo1$c?Tkk4~)w2^q-O&y{1`6r|KwwXoAR*(ILy z$zb2Sl24F>9STnlKtU_Jt6KQN?$Pb`@znNlmyZB7KP2j?c)CBveugdKnD^29=GmPY zNju&7)7$s)G9~GY@k|`e*nZnqd4v}G??J&W|Ap!py z2QDO3EF)H^Re@fMiwroH4Y@N9?9lxIv5ct%v7uMn=GQT^qjPM!*2$K9Z-G{W+c1pML! zQY12sz(@+--c+9q7`k}7mhjPBWA#8o-LLq7yNX#_LnU4SS#~;eqiqb(ZhXtZyIY}J z$an`XCo*zV+z2)_2sl1bJnznCNBRW#{4f3epxLqPW}$6Bs6L9Uzdn~QH@fy?$U*J2 za=g?XQ2)toLOUqis1K21`J}JqLx%U4&S`h>OeZp#y}U@ zD8zG7GWpO;KB1)boi8jI7%oX!(AjSPUQM0L^^|`R8*rA2k!(uX*2~gd8O;bL14)#m zpBV@urpQzx#ej~epg0Y7&ip0e9cDqTFQu<_P(2hXZo20M)^P9Kojn<4u zL5)LdzrAnY#iiBGMlLD*76qoz8bE$WC7h{~UCY@%OD3{Kokzc9FiJjl&Zp$JSa~yk zIleg?`I@=!q5T1f=l9f!CN#s~$*lI}bh9Gb@WK_M!}8#3=rd7fzSDd1Pkqq7q7MfZ z$dATIX1vQ8X&j{B1;JWa`JT|kqvU2y& z915q7{WzkFObg8=&5ALA?3Y_**i+5=5crPJATIyi%y*77B1CAwFo>YF87H5sj?;*Y z_`QJSq*(37*%kN{z|px?A}$jf>&I6tE+NZ>A3fUpw1(K_cAPZ%xfp2Ut1_XlJXtebP@A!x>R2P5jK2p*=gtn9L@D{f@R zj$E|yIJy9NgB0~?g;-^aEk>RxXhMOk!_V?PlBkBxeF%#9o2 z8rALr0c+q9QB^=09N+AE8(G3pkJO9g@h2WV!rqLLB{fzR=919hpmYO`r7?gQiAqaV z__RNNUY_r}BxE3@$#^jcQR{wwxCFJsZB2F4Pg~GO9PJj>G6#ja0-@8vX@&R4@-67^ z2H&(LQ19o7)$rH;PJfI}=QS&&L0^esOcK`N_vNQABX9q&mxiv=m2tI*ceSg1wZ+G; z4SVzZ$o-<##5O^**Mv_=ycX-EnUI)7q~l36H`!HFk>*|IKmgulY4< zr2SAY!srZ{2Y5%}L_xy$Eg{Og3y0!F1tq$o#l51%a~1h@DWOeK`8b43j=xh;dfgN5 zI2kD?bl+tuK0-r8P99#-l?(p>2_TDUoQ)JY0)cva|^A;JRJIuky5B|Kkk=M@WeB6E3j_IvyMsIa$n z=gJ$n=_3w0?9-4Hm)Rs5Zn5*`vs$Z@T)|T>KRhb|Q<$Qtx7ncBkhg*@x7!56dco6zYu2{u6;luW*BmtYnk-?wGNvrUCzI4k8Ef_X2K>ruY8c-) zx6})wqns2IC98%H%O(^&rx3f}P^NSGSjYQ)iMn;0C{Au2=VCip&v^0DB@;@Yn+Elp zq}|w<)mW5D<-fBQEZwFwkWGpf-7S;rX*{PR?x_1yi(3HHRF;%!YB0|qXwH-mODh~B zr|g9Ysxeyso(*bH==t&K{6Fji`jZFG%1ewzg}tA9Y%Sg1J^9x7pTtjLgL>d(-Jc-aO6nR*WPzQi(A7n*fx$bJLfZil)X=~9y|5uP9HHkAT8Q2$sU+z z7zXI~*4{UPa-I3%fLQ?cmiN6SRru;P%{QkjAj4u)ebe9(?~XHYAY8~EZ0bfQlWZZ+WZ$loV&C3{o6 z$y268+C9T@^BTQ+wCLPgPcf*TTQV z-3c;jVDqEv;Ws*eZ9b{wkA;l%%F|Yr4Yg|f#e}!W*{Pd8DY~F5`nam9ttAc7L_@_V ze!)wasD$8;##G@21Y!U8ea7p)qO7*J{_p!<%4^=`r@6@g1yqef{>(|B;i}vtEiGNW z!wtRO8@DqyHa1@8M_>HEubimlqb_|Sg8WwwC&JZiJNl0N27GBQ=fh?qy)r|LeB{Ip zxpzc`_Aj`6c$xOR{qH>;Y%BdkP0pFU6x$EAsfg$QehBd^=|XLT8jF;>1Um+)_(VH6 z*}jB#v~V5BsG?oF^?3%eh$j~_I7m)(z>)?~;5}vkP)}XM*KvXRLTU#STkN)uTuPOL zoxiAKWjl6;T9jp-r1cR!y65ycZpaEsXOv#UrY4 zAXpq9@w0)>cA_yF^V*PfHSqhm1p8mJrd>AY^5^847-13OiM^#Sb`3*l{nu9)dK~kq zc{kqG&He)-SM_GsLju}eQ5%I^;J>N`3lh|8=(rS^R1Ts_L}j?d{yl3m$18C-?1qLQ z;Q@RK`3B$$MZTWS(t3=>h4;Y6_@tFBP~m<15RS0>Eb7SAFOFrPS^$7(z)2L5S={La z2^&BWbII@LVm-b}zk(u@P3RsJhkigQDk~@Ee4wBB`SZ>1h3uFe@~oetQm_j59sZSm zyq!;C)5AFC%e>>=0=eHyW zX2PL}o1ecm?j5U5_Ddc)0uc^+KuAqd6KQAfS5euup;<zPNgthlM!VYb;`9)8`z$0| zsKk-*G(PLUIGx!w0cS5{uwLOP(km^YbwVt854+8^60;%)*#aYR8ubLS;s~-GM5K&F zl0}9n!3#g0L%+FURYg)528rGq$Cbh4Hq(-Bkwk)4=DBhxXVHh0^^SU@v4x7sqIe!M zWb`qn62R-QKAq*E!40Uz^aJSDrvbzQ?F|xtE?nNH>WFrlD695w2FOnQ+ z(;|T8otEuw|0_=3v)O&mwPH=O(TW zcYJf`aja`gsYt@X>2H`xCd#V7SZ9n}!AeW4LPR4g*g!yQDHZ7Lt)4rKqt;Xc^BJ^+ zaXo;%xK-j_!Fq!Y202Z$OP{CY8KzM_BXPdG{7OK8l_Upt16bw|IV7NlkaWLypgy`L z!t8@a6vCPXAJQ>d-6!wqEBAf#10u%a#IHaUCe0e!pX2i@= zQwiKYKh?;3ROUj}Y9F8$M-ufrJ*~unfq}?ITbgPpyr3rsxQVHZ@y!SP7AZoZErlw6 zSMs6Mw{VDInLTQD;l)B>y&8sG*8)>K?pX(@>`Cl+6sx{G)Xv5ZJNOst)yqqlWfE%K zDG!*x!c5`!gZrrSD)|AJx}o$iO1c?c-H;39RvWrqtXMQ+B$`q`Nsg0J$x&N?lcE7e znpH_Rx+V;s6-v}aY$1jMUj@hxPpCQxoe$uGYs3%-G-tKs3`|7ODIsXw7O?p?sj!~E?Ut7c}x{guTTdj(#!{-2Ml z*`DE0#3ugxvHJX(1f_;e$PL7VP-GQijlvrMs08Z8Z8tEzdcqw5LQE5U!kADkdL_*e zmjU9~apB9$3nnHTHb%p!~})2t6|Y zaBgqN5ka52fM)iuHNI!$Q&}!XMR{3T19oK03&XSbdbV0u^t!Gn+6_p**_qZJQw8@r zP=%`9We?buANYQcMH zTRjp`8dH~e$d@6+%7rukisrFbuv}B|)_3Tcq}bt5_s4otk6eYU6zUn| zQ&Q~QO8J{~Om|H1Jf}nKItU!hC_$!I(cN)x210#!ltS1fyB5O;4~LvPzr-I}kBHAN zpiny+_2<-%0%CciZWeq&Anm>#xWLNWJhYRvqIpa8kK@_tjf$&wg+jsglykj6*0R(h z=SLqF4-FBuyTi|Em=AFuhj2Eb4QK6Z3bnKKv_nHUjrw=u{(kVbq>Q9vxcBg?3SGG0 z4CdDGh(%@A3@%I))l?g}sm3Wr3yi)!U!I=;WVcIy>KuY2ImST=sEJ>;#UW|`pk z-|K|h^|a5j;@8%=Zz+Y;BYzjuHetl59eB0z5+|nrt->M%WhVojL*GieB$BpPxyd9G zRODc>QVfFCg2ug(j|ru_HCNz%zS^I2X@=WZk&M`}J0V~xkb69tYZtD~$q@Jl71O?} zUyx17Z}`}~&2uyZMP}_l`)su!L7Zy#;7qQb35mw^4$?J&2yh~dy0+XE1$MQ{^txsa z-V$y#107_Kb1i(FkNc(or%uk{C5(o;??&y``K1s-C~>JCPJXURz8BWi26{N$=X^jR zLSMg|ayqGn&sGtKA&!wR7vZlcx1d!o4YXakb|%o(t$D7K{nqU?a{thHoPs+U9~#?D z&DYwKmsVmDkf4KkX$g5kr~M-2S5Hzu1?MA1z(s^)$>5N!jm@HB(4b+!3m1iziqQUA zLZ!%aL?&Dp#pYBiTY2NeD!s)gl7oxLr}g?Xi>#lT=fz&NV)L0tiZ}SL{VQ3W-`96& z&Xu*E$~A`mJ!J8&VP31lGV$@7=LG7RmrK#sKbECGQs#A`9t5>W?js^fDAY*^lp(~9 zFTqM1mKu1$4QXhK-}F2%j$AW@zZcm=W2c$uI_ z25gW7ItqTi z+4b*MOBz*!X`b(Ifcv{ZiH-^v_JS)RafspE7+#{9{u@PZuk)~dP7>@GVSj_hR1lsw zgbWidYFR%!tk_m4c=!ft_FE%?V7 z9$UcPr<4yxxI&YiOqwCmB8ThExQ%@gyTLh9d z*)^9Sm5eD;v*@E8b={u0nk*x68)wrA%!&sQizIQhIq}W*kIem4tyR<4C-TzaA5=|8 zF;%*N<2T^n;?#8vtB82SV4-#Im})v$+z`Rh*(JoRqO&8{{gdvB9cpklJu)Bl=D)&@ z#DsDScA88K`*tkDg1uOQ_6QYaW#x|KHaIh3po3|0bq#b(MW25_fGT3e$(CzSl`-1c z_|yZx7p!E+oH53pH0Z%HYFq$2jPGhRgbMENqcdL6G}uUk5yO92)f_P(pIsCXgBIC1 zgeShn3ietUU+^m^HWm;Og7H_Yt14m1VCg64z?)R`os#4z?LxIj9SrIOUMh6XuvYd> zwK`lk%-bJFPAoOphP;43n9t(t?jEK?pZN_T2?#B~JjCi@h%%D&&&u7=6~(8M$weaz zjz7f!fxD>QG4=Hko=cusyGM)XcONJB2nQ;Ggw_s#_CQ~Zbk?p3j1Yt63H|H2azK|p zHNR$;;HZZ48`l5vS;3c>p(V}_nU(@C2F!h*Tec{c=Vc!$#J#>I)pNvMHF?j8U0M`smjYzL1`-DUJAr{A=jxz);}92AeLQ3I`N_{O;sK z$!*Av0jZm5grXrt(9+r(CL45ZyiDZ&C?U67_7uxX`I|ROiIt|>1l2TdU6wn25C>wDE$RbkM3UvrVVPQ)aP7E4N zYjwbyhtm7vmiT5|TTpO#OWB?1TTu<5r>(Jy8+l-M9`*Xdzm8#hB;#X9hd1M|^Z-ZQ^g@0(IL7!xIf~5r? zVkAE5u80T_Fw_X4Qc;0;MS2BKR)MMTfHSU3xdje3Rok*&KR6sOU#4EgL7jg0E)49w zQ}f6U;$naXBfGPucKGK{2Bseq?sxQa`%4y^IoNS7l*A86Rl?^p*)!n|d;?oDHiNb? zfDi5C|Ipzn^GC)3CqUc?{5kEjcxj8`J68B(_q%qu$AkWdpIk0WP0$5fl)K`bkH07@ z&Rsx*$lgyr6t)N00tSGU^&-Iochy}{dWq!=GLnFJz!iM}Ax_YDEL_6FFcc|ZWM76E zqN#`Tx#1yJOhYb@pDG?g*TN|6Y)r#8E5heNCJ(Y-msPtao>)rZikFq`K}Rm1ijI9_ zZUArw2pJ~a8#HtV?+X$dhe)X};YkP0OLYqV)t4LwJLIHF_pfz3mcbxcZv(S#L?b?q z7UTY^FBp%3s4n>Yyp%hjzVI@M2mSO`1{A2#K4hjhA7}R1S$?vrK^Mba{^@? zNo__716&EeTzfmMI=qFoH8rT^2tpUiEfAW=#qeWp8CLl7CFVE}YMDh}g&xHjj!PN! z@3`OsEY*A5wh!=WoB&+1DKr=g1WW`eS0oVxBk~KOt1zGiJjyN#Bq1dGL4%20gQrPivse%;JhE71q|l{a80Yf4O%)a(YvM@JCLnrT6C;-z}okq zAW1=06}UCkd3y3Vg25u-ZD-D$!SY>W$MuEIj|CaqkRmRhlxI~WNFcn5^oY;*=G}qfuG8s>xunaAk1{{XOjlG-1a*)B)>AWH30$XOnb^)xuFGwaa<>mAXZUnI`a@t>}ZO?_8PSC(?6e_j9*LqkQXsC+;AA zRqTp9AqJiNKksp=&~Bc2aq=XiJ|Q88sg=qUkXR-wW@n8KLpl*RQp#8-K!1<+WUyxD!=S&meZ%J<&2ncb zlQo-ZM~}Qqj#|N?pC_LP zsh?<=bEOyO)I8QmTA(_K@+{$%hTGN%t+|HM^1=K0*O)C?%xP{@#%gPh)A{W!BDSJ- zX?RWoPJw2jgfuP%os;i_8%h)Gcng+v*<6l$bp=k<*j8qTNS&5f_YE$NE;J_zxD-h{ zA6?=w(0{G4c=Mca!`JOkbB%9uZGP$LB$!j$C0GzG3Y&UIkU(i-&;z|d6uww+StNJA z79E#>EV|Hv-;tb@%*;;@5E<&~nt4MW2$c!4BrkK~;U@edeX=dobkPZ*pc>lIN3kiS zqH`@Fc!*gS195b=-SEHQ7FotL@n*g=(^TzcXKv4xH@t_ysCN;Z0LBjj%~Yb+LmZI_kTh@578+ZFR}Fs<|AWzJi4!n# zTNK}NnlHNkPZ4-8)!I)F->{8WDWix)h{JlH;y(yvW3{m{%218%#LqOlE?(Y1w*onM zn}Iq=|7drbpG;Je3cD1(W>^c91{)2-idY(JZ-9#1dJ223s_cJgSY7+~zXJ8i#PFO@ z>a~T-PbD_Kyy4Jq|0huzeaonn%}%GSKjSO`kh=5b>m0^ z_Pf!SXlEztihe$hs5_Kro|+{hL&bq;XNZ3C)t<@OS@ooH&ydcE#}UqM_14$b>=9*AlK`S-+P z3L+kH;88e0)k)V|MPImrececbg?=;}ai^Hr09gf)WRD7z5nK!aU^<iavaS zpsTjA0l(Q;gcqh5AX@16LZlUb36V~c9F5cNieDBWYNWjA@Fcy z#tRwa2w?j65B)eYJ$Yi0+lhZg)NibAfhoR#kPIEk>O$c9g54unt%>2oU#dKNZmi80 zZ*;o@lsjHI$ks0ddPfip`3<1oC+BvdmPW5NeqjAS9pD5QX@HQVyX!NKy|v1fmw8c0 z-_*~ow?S+X3NRaKo83Tzk;{a(eq;vk2$0R>9F00ySwxS)xRLr6qGK}Nfr@A~KwumI zi6wbdG=%R!Q&7t1bwPu@n6mi+G05#bV3^l1bAc20&0Y<0j~%~2#tOBBxHH0IMN}xKz2^0B|cA7+^9dt>xwBCfOJwfa?)y8LvbSME*;jKNyy!@ov+`woU3`T$7|mx_*Whp14mDtT@JKeY0LF z&K>Xjm*-L8+SkSS*fCJb{NTigf*U`2e+SH04O~ERE8zdP^PY+?`j!1h7*=o*!Q*vJ zxYU3wf4qGM8*$8<_`W`IJM}@VN{OWCaU{nv?AH*rICZMVb>!8-MB-I`bZ|(P0=m06 zGotH_=TAWv=|~IznE92FG?G{o@Mjd$=L^WYV{zMF)^`c zehiH(qqn8QH8NKw;Z=KSptG%F;P*g{?*bIE*pGZ6_b|yboEoUDef;>(hXRv*m%c*H z4{HM}v21O7?Xb1*FHvzw81NUPvJ;oyNne9P!>2~c<7XYOaE|V;zKTmzpUcmGdeB?r z>j`N+_hsz!Gj0Lc*S7^ zRB+&hKX~=bw~mMgJ$CF^>b^@-l9CVd^I-zozkfe6j&{90FlTsFob7cx#Vy5`X$B^! z%%vX=HSJ-5%i+_*Qzwm#C_*W3XtwgU?^DT${&0mC%@k%a>Do7Eg7wdN3$5@_O9I`^ z^mJ=;^V`56bw#C1EA5)1-=^-fZz$|_e%IEv6KK1*IQqq&*2kyYh(x#oXS<6}j=Lz> z{Do5CjiGGnTO3=z7fMc6Nb$sOW8I9(`K7*PTKZ)XVCZA%40NWpwD?K1Abv}3Z-#N- zfuR9o#kP~54~-f2^wBw?AKTCFxn$a(ND(@smQ8a8;tRyyyb(E8V45$W=8>9`0_{Y? zU5LLAZ!_`sURs`;1YrWjMoWuYAkDU$5FVf0p4@iX%`JgKg!L-a9ahkKbA5MM-q|RP z13Q#b&NO`>t-TRC0<#_-KnO zcs@2ap;N4Hbj0i!cWEz==m_}VOihh(bud>cH33hnPd~_KcgmGFQY$Sy67p?n!x)o| zQ24RYQNff*3}yRDB&pez+UT;LW7@Q}D^xl~U}=YVFV*SDPqk@<2?`gDX&ElCIq>F zZ1YoLeZ$G4SDG%nXOF8{{yvHWeDz*tX16d4Z^E6o`Lv@Wrk(WcC5*e~8nH+!DQ!J` z*Hoe@Tx4(CTJOFXe5AFb(z|seId(sg4(-%;V!NM{<-+mfzRjMOi-e^C!y)OH6VRTF zD7eYx?+<-ng&y)pN!P@nxcYY)0i@XvnGX2=R>5q9yGD1JWjt&Ss=w}hJ>>uXcwO>! zZRUTXhVKseasIb#TyNVdZ9$4`cxg6{bk-HpHCFXATy$%1CdbD*niTOvr#EXfrQt2z z5;X0{rt|;x%k_po)VCjKMSn>k!u1!fv2-F~^NQB-fw*TkzTk{|lX3dQC%mfoO>3Ih zno^c}bGz7>M8?F?O}9NJ4}VZl!Omf{#_7U)Mw&~PTg$j?GB#St3Po;ceci0`%QT3_ z*k13Z8h%HfXi|5M|B|iPHnuFS-rcNEQ8UGnU%Qq7XIF^l&1gS*u|T~keRnZzo&Cai zH<>GTrJqRd?8|FDd~4$|O7qV;ge<%aHr{BZpuUwt^b)iF%mI^r=;i>~DZGPsqW@80 z#Q$DaSN!D{CpkCXNUt3^un0ZI&xHoQ;XGedgQfO>zL%%Xu4Ie*LWm(6AwFx8a zi@RT>$$e;^qxnBAKq?se0$nd;9{o{nmuB!VRDJ9cX}*Uh57AH4dEqtO4^-hNO8DU* zn^O8rFk+{RNvodi@n`iYeu~Wy+;wlf)zvP2arb^M+55439U+Zl;_4;|)Ypzmy12T8 zJoD)Rx7R==^Q^GPd8i<9*VR3`??N;(C20=Gt+48uzI!YwO6aqpUion~44(|C=CUbY z8}tnhZ2N_eK1|!%n0WSEeRN2JGDOjT4&UT+i?6W_S9T(W(H*B8HgqlsPj(y%Ke@P_ zu(P#Wl=G$&uj>s#E3Owo#y8ejK8xP%Y`8_S@2a?@Au%NC)X;pwJw^^5QOypDAMw>9 zf5ZnB2kCbE#U8M|kR0Al<6-#ufTi&JAA?8eQ#Uz>b}LByBwpAq#d)^IMWDaQ900rM69!x(Ow$P)8`2~xa$`bhE8(W{UpUe?V#gA-=df%8r{4(VHe~! zUxgIIJxMiIOQKNywbYoH3HAqL50IslhyC zjxwYWB8p_DBE)|k&-1>Y-Y@@eZy)+KIOp8wzOQRvd#|dam{Id=J`E4g3zproC|R9=A2~Wt`^@n z7sO>KIz``HbPH~d$ubb$VaDoD7II>ThH%T}1cy;RCa;jnI57;w1H%L_Ixbl6p~D(8 z$7n-*k>NaHAMwpR?sDhGF(hRf*WohTv~YC8GtVa@=EyfL1z^!}ifzyK_3zPY=n8$f zr@(~}=*J>+J4I4WW?l#*#?e;RVW*--`*_>zp6wAbdcD+2H|Xe9&!vw;#Nf=!cC&iA zc39r(zPCnx56JrPy23fe<`05Y=*Q7Qa(HA*KBh{p>=noqIz^kjV;ALf0dv9PK3y&Y zn$QLExieuKr3Tz{I_Aq~_zlNKn7nKrr|3SyTqU}2;CN{EB61k`gv_yqg+8eBKh64D z_1A7?)hUotusM^VDHIIb5-}4oPNy7FvOP|gkc$BseNLD_4#r$zEs#5=k@`bGgoIkO z(}?k~;Meu9Nd%|32y$|}`h$UdSsLmqeBVYNj#6qh#DwRlmhmiqP!+uwEk)0t{)6Bv z2O(~T!3`Pv`W&>bfLLOV@~O1IK!W5}pLD1zh!`Oou^8N#LR57Sa0x}F1$d=uV=m*7 zfpFQz(p9tG_VvK<3WGkDa{0a8G3ewn@eNO+G=e*Ebowb0m=y5J!udMpo|=yhuV{s4%I_LB-6HS z+mMZ2qP<|~ItTEZp2~Y1T};H|C=5KydCx1|Z^!InQ!N%Uo1ZSkIagqB{3=d(6EL4V z^e*p$nWIv8d%t{lix&;fU;MBB$NJZs33rqo?%U`SQF$*`7Qxw(s98>_ki(`soeX^13V}o_v4nERkQ#$v0-Y~(0{mfAS zh@%=*i#}^U8o<8#);O=oO+|sstjQIcNn2^&URyIXtS%_-l0bjlQRY*5rt!(i;mwr~ z9zf7Pd>TNhaID^ARL{qb9cz98EjWs5472bM#;h4Js;x$@z+QOhQFJp$WtWt&#vW*2 z1bdF3=;@qY+8(T;LVx3^Dy9A4;;?K;-B+~a*NKaWs7g>=(!vn({^^pv^)isA0hL)I z7h}Hn3x|}ZfQua}`1W=XZr;ig61!$1d8izA$i=p{x8Fo>Xb~r!22|;E)StDZ^X3$n z|1>MIZrdEPOMht#U82B=5xuWcNRJ`xbbOhaUD!XpjJ{uXR56`TFk#$`;v!VcP&xp$ zy8ABdT+KXB98%N(B&Ar_>q6bT-Up)gw2hCK8#zj_a1DRm>dHaEsDxNkc>0-vQ9U+d zDd3$H5%nxgrd7F#%p8lgsCAo)@c#XQ2d=xYIs#+fbUo;CkioK>&#L>%!&^aePaeen z>~J;}-b5QvKi+IY%|Kw@p;a&7kBSQuVkGtPe&-5V*OC%NPXR?JY3FFF#Por=fAJPU zWY)bbh(TUlRPq(O-347XT<+i@bKL|Xuq-Rk(1Gs-+f8$ENH||(6}O|+J_l5o`rS_1 zIQzT@5021N3~bB&h$$b@=MjtYEGpS1$p3g*B|?@ppF(y zK(Go^SSZ2q(2X#3geC6Ch-Z0JWF*+3P6zW+w|%sG(8x`tibq-DcE6p4E*#de~q^l!@bgRMmfO{uz>FjA); z?ZtyCPC4|=g$UBaqV8^(Snx38d2U%RmeFE4R=Qjbh3%*9&2!yTvjf) zh)4+K3oETr&aZ>*qM-``%zq^QNbzbcrQ?FC5{1u(-qvEo~0b3`G z8qO=D^E|V~1qJlevMU@IF&iEjwPluz{Ba2plL4naarUYGKp*eCv;geyaciSx9x&}E z5MVZ}*nU^{5mp(5-A&C{h|?-!ff)NvdpWLx$NXsQsASyro`MWX?=6S8_sg>?1^!+=L#Aaz7iz`a`CHQbB#N~3)-WHs*UJVPnu)I*egSAojn z_z6~lPDqE$nfwoRMs1rB4v0P63lxFD*)#6)7@>p4=*5KvXjtCa^B;%+dEP+_4sBV) zrP10HnVEDob-F@}2k&vZ%u~OF=03VuY2Hzk9roe+D~ZUSs=M+J6S*R6q~W2Is*Fcr zs3;EguFB_K>pLm7Hg7*RM@LT4l6+$YHl{@;b4oLOTxsYae@X<#oy=J%+bGh(X=Zwj zOeo0kg!xh24$Rt7>^h=#;R2~|Ts=N6_$!5xFWLDJ05orR9cjL?!l!8*yfWdRJwm6$ zA|gQ*gh4q(4$Yqei(G|;_+Y;6O0iN}RNQ?+-P=vdd8lk}x7!rfoKkU*;HrD`ncUWd z@zGq(zw0e@*2gRaZ^yRrUpG9uPNPBfonqKNt{|CJnrLaHxg`LiwK=W0hc}ZbSL>-l z%*C5t@>Oo9t*+s2x@~NfdL+jfOq3DRmRNdmPNmRa?9!<_lJB@{4F4HsyR|)vHqhz; zdvY?P2_(M{d&!@Y$NRiVIi1((V3qTgZ=<&ks;}-vWhtuNK}(j|B}Zwrj!ABcq9STk zqO|0W-g=?WVf}>ZAv53BZB4Rsw^`mN1xX#Z_YpIH7TK-JTb$6b<;dQEg6D_aHY%a^|^eZC4>zj;$x3aLEc)LMMan(S5Em zuQWo*jpW1H7KEnheRy2j9`cR8Nqs?dn*vY$ReqQzK{fGV-d1Us4!VqqHzne!1=>Gz ztjQJidzEv{)n^FK+2-OJSyB8NO*cp})ab}vT?c@M&QehdXY+zl&?gPsaJr`+M*VIU z)H>CR%nB(ekh-96+zHgv2A>a!&3Fgi*7#-|_iNW?)o;#h zAHbvFpV3<-=h~EH>tl37fdn)7OWAfF|JGs^k#R_5#ipXy`%|k6d5D=ZMCt z3$9I#3qBncagV_J8we}2q)hGb_$_p7*>c|u2{iDDGC)2ie0v`ilh@|u{eS(}=DT~m zzy*GEG)sb77BDBF73rv7F5HEL88J+iktWG5)yLmSnJvbC^3yYDtbjIIv!dD|O_Ykq zaJ8mU;J@G)QEEOjId5lINC4O1laAIieEV!8)PRMinAz~3&H+rojj;W@@Essvwh{P3 zXhj$zx-lg*A3u+cxXD0*B9mlwb8`c5sVRU#9E$BI$T2Vqtyq^p0f8-e4Wc>BT9HfN z+4(sbJI9w`(>TJkv-wz5Aoi*5t=^>ZFpa&0j?lU}1_1g`|JD8>G<^ZZPSoD;S^|(o zaQ$+x1W4&$MSL{8I%Mu-W@ct-KyqOO3nh0-Q5OA=?&WjzT=z zMB*V@7EC~2P1Z*YmvLZ4=M0@`h5?%9K+P~mp}^D5e%st^WrhR=$uy3GgchKr7=49l zRC5q>F;l4I_efY)nWOa%MWI@eQ=fF~D0~@ssP^vN>tOs~5IWrh2Tt(CW3qD3rz&=(J=n4TCijkn-v`q%4^eCF>+ zLlj!OFc%HC3Rp9b*Xo~XjFy6X8tP011yEfIX?hg1RL=nhV+J3(W;F%gzJ06O3?LG` zFHme8ytol#Xj8p+j|16xk&~WYtS1-#L>ev(XX&8zFIQ*rHA2>UVXz<5VAFnI8RN;o z4{K+;jW)($Sl$m)^scqF=|Y?(or=|wBw>kVf}*;8vE-q_bY30-kvCow_o!pP%6)aP zYu5Mqv4T}ksUAQ6z?Y_)VU&=KF9hfFVCsx`C0rZiiMW&98^2}{A@Wfw!b=HBj?0p+%Db1~|{UxsFAdtjB!r<+@95L8%#|{jCygXR8?f&D+%4>)N85v)34d_VV z_M1cEZCdUL!NU|5%!VSa>gCIqoBZzar>ooj@gs->)ZZu&KRQ~Al9-)L zdash7@ERK>jXur&Xn+3v0op6zmT;p}X0bQ&=WpYqxpA%F)d~v>L0dtY8>%|rz+xF4 z9eq1FIbdnfE7#;1`hjut4tvdTu-!r`h7FXImK_jtRi=Ls5wqyw}RTjU{ws?knY16PIfl7hei`vkLz>c%HPJuZ0IpPXdVB7 zqW#H}A0z@EZ@c5(0+vr$SQx^-o!xib9zP{Gfyuj$)b|yiho=6G=gZT_FTpUa$h4kw zjHI`4kfE)EoFPS$(2D7YVrO2Ng8~G7@pbKD{b6P04ZQBI?4>e{$7^oB!9&H-ggZYC zHV#i0dkmM?|LPKEA5zswQ9!7C`t)gx!P3`n$M-^WfoevH&*E4Vi-fpE#q!5fmTAfX zRj*$C!M8`YjrcCIr!+vxpyyGS6}rxVUXwcU0k4R=YC+H{{A&_ zLWTa#*Et9h0zjMx*Ull*T!YyguE+7EudVGj3=74x&gxwI^SToGF@9q3clC#iq%+Ldp;RG{6*;&nlTD=ZLm5OVbNi ztJ}#gYhLM#fX`|fSbUG4K3M*oblXGV9ucrM--H{|?62ZG z0w0zSJv~D4nvKw?a}Z%)((UM>qoZ@?On*GT#-Hi_rTHdqga$uQmN;m#9`VIL$m@tjNfe4K@@$qr6+o&*q={z?t?fUWs zMB##ve)>JEMvKzTd1+X?gNP+0|2sLk2~rzC9pX6Z-QR0}uT&2~Hi2IOOXWkLp%D;d zWn_3_q=kgS$9>{8f9-IF`PtvzDz1S!mMNPn@%fqr265F#yv189w{@L3GNR5PsITkgLRL?o)$5T5Ww7MkPv zSz8ZZ8EgCTL%2?|V+FMH!h#!^erQ`X9UUF9o;$u25Ky6F7_Eq?s9DlA%tpc@iZ9)O z5sd%e@5#8~7-GaoQ|Ud=$90om;m6xVQOs|}jOS<1o;`jXZVhkPxWvSl_V4Z}|C`VU z!Hpn|aMBzM0gk9iUP^j;ta=u%JPv*myE16EEDInYdl7`rq(Bq1gSm3U9SCFUXHCK6gP7S`Cr1luw%FV9<1>Chq4 z8EqhJY;24m_j|aO9NGpqdOR`&oUVa^=$+^xz|w=X$HauWO9~u3`Vp3}uCQp303ih| zA6$n}pfy{A3k3Mt5wHQ2&O^Orn3o;(GM}7Ek<<}3x^l`A)x`O?M=bA9t1{fgD2Ivp)u5n#i zcZEbnFMfYZ8YLTmx#!qe=)D(_P7t0dEh<)q=%lt8VD8+B{jbNqN41aoZpFh^b|K%zkLIAjDF4W_i1<2 z)BWd18it355%Q%bX)eG*;2X=pR)ms(@Iyi~DPA-a^+b@|n39O)%omUEiQ%4N5VW^= zr{iE5pUCIKeHfLgMk!C}oDFGWF$+fMvF_D9rf{c#3eQ~y8F&5*T9Axk$17<6i zpj<1TtwJ{=z_^c&2u+fQC8cQg+>sQxh%}w#APimlTos0~Dy{tBPqM>My*f#`#o?=H zqkzfWX{dp4{eZp&7$6UXZ--|&teBm=+Khp_BK93P09#vhlUd!m4Jx+YSXwsMK)B%h zMR7W8g^Ez8y|hnM*N4RjXI{}>xnocf%9!f&PJk05zNHVQC`1PDen(!78QZ|aOmgvE z!;B

v&wbX5{KfxY4bcS)4nFo5Do$>BinIe0IQB9^8qK5A>y^twZ9Kmzjx@gI5Ud zsbCjg=pz2%r@@lSDU)sl4;3_XOJA;bTuf*|uMTomthFgm1(7{*R{()@`C#3JaBcJX z<|bE06pmQ@zj2JoD|0YqX;<7FCPqGJ)g19Z{`5XrdJU_E;cb5+Tuoi#*q%R+f`XMNMKx63T$3wY7sVs^QsccxC#aRrp`&8vb8D{C(qL3FbgkD1%rb|hWkV8Ff^^EIzBcA z-yn*=y;KYvug(bK5;NAW@k~;^ogad!*3mPKUtQ2U-Yd=Oe=K;8fAt~hJ_xuTmwy=5Z_u{1~0gS^frXkNH$4-x%=sCsubxe{6zNNzmq?*#-!0KeE3 zk`?lAK)*?7#SN)r2tC8|YlDjPpx)*){E=|s5F){h%oMfA`jaRS#+G{4E)h3;GairV z0sBd$zksGZ+sJHaG?FO>EZ@`dy$)bj!d``DuPUvMLV!(mk{(uvv@b_kwwfrobzwzM}K(={TrNHdgvxUhJ6}EO(VJ z_nLin8ZH20 zZFES4)nHvghEFk`uzW8|VZ(&OJ1w55e)g zzP^qT_AujuIi|NX(jUlVb$XK^xpzQ{=j_bI#)cx}Y5O?8$F_Cx%_p7N=p+l}4B*LQ zp%Bj_(YLf5s;N1G#yi#D>FMckxWVsu@W zigX>WMiAe^NKrvvo@YjFD7iq4bPMp>j*bqz5I#enKR-3faS#zezWfrZWi(tF<$Uu= zw@!gAcnLQC>(}tE|Gl&XV;+nl#GQa~7QBIgy;Q1Ar0UbWVRZu(Ba-+=@zJr}rTEt9 zF&RrNB;bUP`>E#n#3%<{VwC!E?;*63BFBhPP#I}@P`vd~(`ZAy9y`h!=1S7YTIXCw z&7yDp{1lF@u5;)dtJ<;c8&+-Okd#Sqixp%@uyo2c0^;RX>hcK^BK*S}*4Cm;9BZ=~ z0fLRq>|o3XC>@L}h7NZzzOBZzgCNTgoZb{F=*4?xLM%0)P@IG5ThrCmH8g}RcK6O5c?AWmR@{6%1t{_HAV_%~0EC_%Ea0KePBNXx zxw*NR+IUc3M`wp8=Ei>lkOzZ!OaQ*1IXyQgd214{!fSV1qB4P^8e>YmJUm`vEiNs+ ze))1IE$#4}%ZpxGDQ~<1rOv#{FJ+AL29Rc8X?e4Kgp-4dtpF>nXL6362~8_7J1|QE z6$f>z-})LRE4#q)2&@^GbX3Ee#R}Do=9U&fF($c*<37;fCu;MK^xov5Vvaht+5Vf* zQcpt52(1V{Kxqn1U6ioFH@i8&iZMh4)jsg#0#%C#ZIFI%=z+NSzp|9_srmaJxh%VcDX-~MSPXgkB z+5z-h_Ft~XOm@IAq}qJ_-zxas_QejnwNG<&_LW)n;;lurb;xTl^ZDVBtu(qWfsjh4 z!cb#tUg(wY^ZajCfmk4R0k{-T-mpzws1}`3)5jg&{e_R+4cHd&0>{gj!yP<5Ja*F2 zsb;~7cBrds;dhTE&W_8~|6b+iqe0o(-Tejrkdcv5UVarONWeoN2j}GEMD~skfEg4d z+!#2IzoL?(C+$&K9s*!`{#=}PnvRzCNYPbaUs&t{bC|QgdR1ZXZ)l_`WslOvhLHT| z%F5(rRN?=flQU5pyd43@!@~pbMKqIPiaIqAp9pu~u<&qnv!K|c<5En~&K49Dg!uPv zLIUpg{1KRPsnD~Afw6t6t$q+wJ*--7Sf~C=bG3zobioFxBK;G z8_ec-Th+I_Ni9_1&Q74)SU&AJ3J<_zeDR>hyLJuxK&PR9{CHwwA{u&u31yu`53+*} zkmJ@O=(@)(xM{v0f8%;jHKP{@AqpHoWq)Re0)}e>QN+y8&m%28SES&cs`lx}(W4Y- z9Bf~N+C}*cx(r^Po^Z*b;%t#I}8FkDLZTuSohyvfZ`MWEnBe6$P1YR9o zMeX?9vYJkAb)i)P$0cw$gml2?mo7Cl0)NBu?w{D(> z^@V_Y<;vn}A#~!|NwVaiw;7Ke zzZVv|y13Bq)H-v9J@ysMNHQ|WF4bT&H7Q1&9)N&vQ<#qO4Do!kFG!vv7AIXA(e=&v zqV+M%&X}C{rq39Skn^4!uCEV)75k2xOV-zsj)Ei&StF{FjHVU0(l96?R>ErPb${o{ z5L3uF72%Dt)5C`~40S2aE6z|9q;R|b7&e0!;%(jK?;pNua{4sQ2g-TC{7|*Rzp-iM zrbG&o7$(**txb6O_2nUS;Nu>DzBbiM0#lQclF+FQpc1_)p5=xjoYs4`?yuKJzq5nP zraP84*Qy#HFGB>qaYo(FZRpI0osq4y^(b^Wmj=rc-HQUAm+&77qiDGC9jOIwHJX`y zD*;8r+HV#P3X_xkkNj{P0ba}2Nv2SFl9N;WgwRGG@)aNfdNh=q(=IzWTz>$^(dz2z z0Bg5vB8jRFh>%j!(m`HWI&AFhyCZJK#K53rpu%TQcwjF&K3=0FuCC_R+a1lqsf;Z}2!${ZabT+`RA(^O6y6rOr}EeT%?2n-Ns%CKz@fL3 zl1>wnuuZYxF>n*}Cuab&V^q7JpC8@=>0<6jXaMlPfDkXr+`&9=i!yh7Je;xDNcHTq zXQ7Ybx?nXmr&#SgSOx%4S63GWp_8ZQD-0z8*!f|CUn3U1OWvVKAh0K`%>F>q4wMJo zS8x!=MnyUSk9e}B$w9ccY#>nVRQ63MK^4|g@Wc4uP zySDlVm@Y=PWE)ZQLL&nB7H^P3UV5%67MNOeOiU#}(8d_{f>9(oA3Hi+fVSYVEBXF< zQdOlyPgN7Ov9{O_5L{hDGKO}ivS$4c)1MQ^yFl@$0Te5pFVvGQ%bxByB|nAS>qy_Rs;vo zY>(5Gk%fi7W>L9v_i|M#>@NzekAjzxWW|Y!3y}*u0u3SJ99{wH2?M9w z+S&k9Ap=Gv+yM3pV3$3n5fjTGd|gn)tdRA!apj&*pP&`GGXDNB5W-&*A0QJ-)8i(( zY>9=#>V*4Bal6teai%L<2Q)$ukJC`qKY%ueoCm<bu$@RZ z0WoUCa^MVMk+4|1j{ymyr=BBPjDjVC`3RO3n(}cDz_-52eWDAW7R#-?{_|rlr-CQ^ zbjHTUkenX8_zC?cA3uEp)sbgb47LW_#>B+r&5fqs-gYK0VTmcmkTwt#jfVi=77(sZ z^-3|`mqX)EYY{%Y)N}gug$p_GteJ3UH3@yoDewLR05if0`tr~lgHM1tY`8K8P&gO& zIe)3}`TmwEx%DNI17xb85MWGnss9x|f2OY(9mIJ36XaXq=O7mBBjAL6`V_W8Xe$IJ zX+*Lh%fRw_@!|#W&QFdn)0M8RV1wd=EKmjEPU6r;^=M)71%I9$EI(yxiW&~_1|4*! zr%t_o(!e=E>IK9&X`;)6>})h|e7hO2c1|P_O*(Mr0I`6t3b_!p(U|O|r{}-^cbw1) z*2&$`F*3RdH^~oeh>-KVgU!o7AbjX}3a*tre0Z?Cn*!!)udyDi{QMLlu7k|y0(#1D z#*p^S)*2wD_%eX#<KOOrz3V+Aw6-Q7c%g}kwr=^~ zI<_nFB214LnwA%3##xqx0Ao z_vAe=*8^Xi=hiWr0f_>;xRsqBIGoj0R8%Z1xM&j~V$c<|b^v(`L>E~v_OO!wnm52p z%HXdELI)3msu{zbLXuRV0^Jcbmgkg+#2cj#;FwhI`3zVOvM&#aEngu@;vhlNhTnhw zbaWrV21V}i^NYKe*Jw4WFVeRXW<(^teDNYX7Z+L#fwW`2=#b1!gTWkDVxbG&_j|Lr zhDNSCckWn`UtEY$Gag-(4^&P(Yr^0(a$j%Hi$fzi)R%gl)+iK3hJQa@@*(#PIX*z_@0-6}n zfd)DnJCwv)RQMbyV#my$2blkd6+RAD2LB9aF^(o=ul|4f&SUJ0c=8!S5>6v9D@ODo zI?3X=jfkVj#gN+cPkYiP;aJ1pZUSxnps$RG_-}o67W5)Y>qByKe*wYoU=cU4dra_0 zM=-KFiwf^rNm@$1_zWO+a1{bAE0Q={4FYg=31m0Uk9Ca7J6q{{^6>|h)wytN6ARRP zyb6RG*a2dWMU|h=a1B}g5nP7jOCYs?7`_9fC)Mb8?yS^tuS+T^DIGlMG5z@<$TB=# zJg$dlX@cfjDM=m8yfZn*Kk;4heK<)d1T(w%p-`2oqg@h*}W$s8o?Bs(Ln}TF~)rqU@<>?cAUUWnp?oy z3O?`euMhf6G{4gPbMc%qM*T9NyjN)?>d09>_4QTSrU?X^?(3n*-4x% zlaslaKsB>pdJBq0cvE}Lm|wgos^>W$snDp31=0QK6J=tEIcRJWkq-KX4V}PZVhz^? z_77m{365O^0G)@g`A=kLW^Ubk5NA60Ok4$_6|oJ^V7Fl~3?@NMAqBLy=IydKO*#w0 z8Ek}n8W%e|cvdV1=d*RVbvQ5@2wiAxxK*Q|SC1=GJaC_CnL~SN23NBE8GXteD?1vB~e<4ib zE1+$sJ@WVIZ_w!vCByJ_J*m1pp%4@(tuaO9-s=c$gjrP+1+i7Q@4K_xIvZYG@CqMXlN){ zN>XF$hl#e9mcRcg%6VFI!Q;=5HldC6m@PObY|T|@h|@9IsLhz zXbOxPPPpc^T5bisZx!(`_j}F^XgRLg)bEfZNh=7gcv$CbZ6Bf*n+QW4U)1MBdSu1+ zF|FVEs725OjAI9P;rVlT;#@-hgzOTl73&nvWiS);?7|s}h%W0qK&2y;riZ#-fsy9r z>(}t6290^*#NxM>1OPOf!gQ3Bblgf)^WHOGDx+Ru*Z^8lR+naxM%)@LL5L8jS@x^K z-oWaZMxI78Sy0U&`Yq4(SO!4IE-EStJ{V>nRVzP5%LgrhpPf1t9-_%m%wKnY_dA1Q zY)*XfB_J&a2F&HtW?(7(_yeNjyY_ZC_~0$IAAi7!u#N#e;bCDQ=t0AR4#y%mEGzq| ztIKVoYhUarijd#9(Kx3N)&TgSs(D^i1b@@$*jT+y4N7C9y6$lp=)2h43;I&S1rpyG zdk;|7I_e{kvr;1vI(g21i3$9KQxu1nqW{`5GEo>#qJ|`WK781aeW8|KUM5PX;w2jp zdHDV6)Ihw#>4)PN>HFMwlop_*q4hQvq_OJ^n()VY;g9MX*)b3T6nDr=P)8R&Idkk- z19E3%S6+Xn`mo7x;g_raQd*w?zGdPv=Cck30RjswGU0r-tX}j7Sp=fbv?mJ5ejGoz zuOtpv?=kKS&5j)~0mH_DSmH)}aSz3;W}#3*m#ByceGOj>#fRH)&KEyh2F3uHQARor zc|g(-u%K%Lu@Dgyof5EuB8~rWz55Ps1yDrAYiH}FE4CClsi@SVJcFwnIu^mKf7~~FPWS=mBmtO*P7JTWmG;07ISN0 z&H4M+JfVj`rVbIv0xAn24oz%ielq6(rFuv{IHt{oM>|cw} z{d>roysB3R5wo`jZnmEt4WCV51endRqYwyB996Z@)RcH#hRPS+urhrNA$pgFE7gJ1O_90bx zJgbxEB*$;txa`<}R;EKJKGvc-9nb;^`I3!IW?30qaY9`F8%bK(M$HS?Fn*$0lfYaz z{BzcSNkO0;kVlSjq>p}cSp8y1?M`?Ir^RU)WEfbLaenr>onJe@s5t9c?vwsFAqA;M z%HXnDZ34Dn%Ef0N9g#e>k3;#6n9!tK8Ty6FhNU8c8}m3J=YWbMMdXQrFntfipJ16% zQ(G1l1%=+EALC`SHLdWMGcfuxmo4&h2v38q0;#4o($7M;-xv?E(h>bsH^}XnGit}ew zhLt06%k3lZB4Jg52S-XGj1w-rp|y(-Uh#$awODs97C&oB08EOe#gjFXR}#Bf_;U}O zBh&Z(jvqL@Wi8p7^?rM}*zOddjJMdD$J0cwa&uwGFk*e(1 zUC(L;KwO4hg3W;2W}Pl`@F0jYYe&)jE@9SZre0N6a)t-WJ;#l7@US|hQh(<3X)Yzd z-u`|CY3Z$pD02=H^`yy`p+jIc!t$Yt*&V&8h+{FM2Ye?`|J3isg#;)i+2c8o3SQZUNK?<{lVFTk}#MaKFJOc0=WD@fJvu8PJx$8gQm@h9Y z>za_Ei9<|yBcNhr53Um=L&ZAml^=FI_$Cm-8cJVq_!c4F>}LKE_7h-=-hry>?B_Wt z(rGn3+Kc3NckOqZh=KXr@THI!domKVq6YeGM^s$=9u@jI)(q>Ktl&$UdnJC6N&ThL zr~MOLAr7;XnXmR+wooK%si_#perDOB&nh3Q%|h=LtpiSmW7ikp`rfy9zu~85sJ(Ie zncz)@y;OYJjF5}>Ijy%aJR(JR$0#?c<jg0ts zNAd^AmPpf*XU}%N4BAdfX%PD;J9}Fy=MVZCUS304H4X_Yzq-AEs>6B77q_b`yZVEq zE)0m?Ib4iwEo>V`tK+BebZ6a)hSuI&p%H63-MO{?F5b<15zy(LdWg|%wp-la5kgHT zW?%DwsDK26m6wT6YkJ61;_ME!d(mk&AzSSAK;hwOLFCM*M)PsENw?8g6) zmAbJGC>H8h0`n>$@Ll0)-;#I^{Oi%1wfwY7xqKPgDrnen93cr?LXN|8xMlKpm7wU& zO>TZF&cg(T(9+)}PuZgkK{RD8L(o+J+{W-=QDU1dn$0{E+1S`nb6OY}T)#~(;La2E zZFW;sKyWlD*tOT$w6T5K^IRFNyD|qIvWb6i+rgm;UhT`G=y?=ySk_+@Akw{xs*jYy zgP)|OM3D+s_~}2)i}g_TpDHsX-SQ~5hsJzo?u^4}2W{jajMu!nS%C9nV8cYpiltnc zPxFp8R)gG+PX;h2LNbA}*wG?EHL}vMog@!1k~|bDpk~9IfjQ3+Cbu+$Clr-aC90RD z-rpzWh+fZ>S8V6sYy9|w^`9*w(`#<7n3M^L79$PjxHG=rx0;#Yj@}exvy@vR9ty{C zQBlBES%wXrjMbn}fpAT@!|=D;yYB5PhcjOshoB>YD2PU0MtI|bbn2V0E@(^XpT^HQ z$gGFinYAmLZlD9!y3N-*MtxJABCC0j3p%SUhZ$+$NOrTSu4w9VK@mxub#fd6ize3_ zLqmURPv9cH&j$ONKY0=Du^sXi_>p?#4?W=FlNlUe#D^Z?!L$d%`t6Bd@spuNy+0r|+^}Er{9wwV@Cc4l9m6{`q zMVp?VQkXSRcysZMfDvSJ#MnjO%8qpmzF!s8#FxB%ObY`akUAMqRqaU9Z+ZK6WupPq zJQU;*jpRkAYYG6&touq8Ubjrrry4M`Yr3nMl*3k?RSh z_aIo>lpF~I^8}1$8tj`9HrlYU$BQ5-hDKh72xAd6kvw@iwY>WtNyOw@MeVN}UYM7o jn!(exlb!PE`UY8NrAmXoPk-GO{L(t6r}kXcD(HUzx-s_M diff --git a/apps/docs/public/static/search/source-settings.jpg b/apps/docs/public/static/search/source-settings.jpg deleted file mode 100644 index d89c80623807b52f49e4bd2119f4c6b08cfc04ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37543 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 diff --git a/apps/sim/app/api/knowledge/sim-search/personal-source-setup/route.ts b/apps/sim/app/api/knowledge/sim-search/personal-source-setup/route.ts new file mode 100644 index 00000000000..8fff7a8ff6e --- /dev/null +++ b/apps/sim/app/api/knowledge/sim-search/personal-source-setup/route.ts @@ -0,0 +1,70 @@ +import { + listPersonalSourceSetupAccountsContract, + personalSourceSetupContract, +} from '@/lib/api/contracts/knowledge/personal-source-setup' +import { + defineInternalJsonRoute, + extendInternalErrorPolicy, + internalErrorResponse, + internalRateLimits, + internalSessionAuth, +} from '@/lib/api/server/routes' +import { internalKnowledgeErrorPolicies } from '@/lib/knowledge/api/route-policies' +import { knowledgeOperations } from '@/lib/knowledge/application/operations' +import { + listPersonalSourceSetupAccounts, + personalSourceSetup, +} from '@/lib/knowledge/application/personal-source-setup' +import { + SelectorConnectionUnavailableError, + SelectorContextUnavailableError, + SelectorOptionsUnavailableError, +} from '@/lib/selectors/server/errors' +import { IntegrationNotAllowedError } from '@/ee/access-control/utils/permission-check' + +const errorPolicy = extendInternalErrorPolicy( + internalKnowledgeErrorPolicies.connectAccount, + (error) => { + if (error instanceof SelectorConnectionUnavailableError) + return internalErrorResponse(error.status, { + error: 'Reconnect your account to choose projects or spaces', + }) + if (error instanceof SelectorContextUnavailableError) + return internalErrorResponse(400, { + error: 'Enter your Atlassian site to choose projects or spaces', + }) + if (error instanceof SelectorOptionsUnavailableError) + return internalErrorResponse(error.status, { + error: + 'Could not load projects or spaces. Check the site and account access, then try again.', + }) + if (error instanceof IntegrationNotAllowedError) + return internalErrorResponse(403, { error: error.message }) + return null + } +) + +export const GET = defineInternalJsonRoute({ + contract: listPersonalSourceSetupAccountsContract, + auth: internalSessionAuth, + operation: knowledgeOperations.listPersonalSourceSetupAccounts, + rateLimit: internalRateLimits.user({ bucketName: 'knowledge.search.personal-setup.accounts' }), + errorPolicy, + mapInput: ({ query }) => query, + useCase: listPersonalSourceSetupAccounts, + present: (data) => ({ success: true as const, data }), + staticResponseHeaders: { 'Cache-Control': 'private, no-store' }, +}) + +export const POST = defineInternalJsonRoute({ + contract: personalSourceSetupContract, + auth: internalSessionAuth, + operation: knowledgeOperations.personalSourceSetup, + rateLimit: internalRateLimits.user({ bucketName: 'knowledge.search.personal-setup' }), + errorPolicy, + parseOptions: { maxBodyBytes: 384 * 1024 }, + mapInput: ({ body }) => body, + useCase: personalSourceSetup, + present: (data) => ({ success: true as const, data }), + staticResponseHeaders: { 'Cache-Control': 'private, no-store' }, +}) diff --git a/apps/sim/app/api/knowledge/sim-search/stats/route.ts b/apps/sim/app/api/knowledge/sim-search/stats/route.ts new file mode 100644 index 00000000000..e7ae7eb9777 --- /dev/null +++ b/apps/sim/app/api/knowledge/sim-search/stats/route.ts @@ -0,0 +1,24 @@ +import { readOrganizationSearchStatsContract } from '@/lib/api/contracts/knowledge/search-stats' +import { + defineInternalJsonRoute, + internalRateLimits, + internalSessionAuth, +} from '@/lib/api/server/routes' +import { internalKnowledgeErrorPolicies } from '@/lib/knowledge/api/route-policies' +import { knowledgeOperations } from '@/lib/knowledge/application/operations' +import { readOrganizationSearchStats } from '@/lib/knowledge/application/organization-search-stats' + +export const GET = defineInternalJsonRoute({ + contract: readOrganizationSearchStatsContract, + auth: internalSessionAuth, + operation: knowledgeOperations.readOrganizationSearchStats, + rateLimit: internalRateLimits.user({ + bucketName: 'organization-search-stats', + config: { maxTokens: 30, refillRate: 30, refillIntervalMs: 60_000 }, + }), + errorPolicy: internalKnowledgeErrorPolicies.connectors, + mapInput: ({ query }) => query, + useCase: readOrganizationSearchStats, + present: (data) => ({ success: true as const, data }), + staticResponseHeaders: { 'Cache-Control': 'private, no-store' }, +}) diff --git a/apps/sim/app/o/[organizationId]/integrations/connect-account-options.tsx b/apps/sim/app/o/[organizationId]/integrations/connect-account-options.tsx index c5e75a3a749..fe091b7cc4f 100644 --- a/apps/sim/app/o/[organizationId]/integrations/connect-account-options.tsx +++ b/apps/sim/app/o/[organizationId]/integrations/connect-account-options.tsx @@ -210,6 +210,7 @@ export function ConnectAccountOptions({ {enrollment.setupConnector && ( { } ) - it('keeps source setup fields after a failure without duplicating the toast inside the modal', async () => { + it('keeps manual source setup fields after a failure without duplicating the toast inside the modal', async () => { const message = 'Connection unavailable' mocks.enrollmentError = message - mocks.setupConnector = SEARCH_CONNECTORS.find((connector) => connector.type === 'jira') ?? null + mocks.setupConnector = + SEARCH_CONNECTORS.find((connector) => connector.type === 'github') ?? null await render() expect(document.querySelector('[role="dialog"]')).not.toBeNull() expect(document.body.textContent).not.toContain(message) diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/add-organization-source-modal.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/add-organization-source-modal.tsx new file mode 100644 index 00000000000..babcd4f2c91 --- /dev/null +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/add-organization-source-modal.tsx @@ -0,0 +1,106 @@ +'use client' + +import { type ReactNode, useState } from 'react' +import { + ChipInput, + ChipModal, + ChipModalBody, + ChipModalField, + ChipModalFooter, + ChipModalHeader, +} from '@sim/emcn' +import { Search } from '@sim/emcn/icons' +import { IntegrationTile } from '@/app/workspace/[workspaceId]/integrations/components/integrations-showcase' +import { SettingsEmptyState } from '@/app/workspace/[workspaceId]/settings/components/settings-empty-state' +import { + RESOURCE_LIST_STACK, + SettingsResourceRow, +} from '@/app/workspace/[workspaceId]/settings/components/settings-resource-row' +import type { ConnectorMeta } from '@/connectors/types' + +interface AddOrganizationSourceModalProps { + sources: { + type: string + meta: ConnectorMeta + access: { admin: boolean; members: boolean } + }[] + pending: boolean + ready: boolean + feedback: ReactNode + onClose: () => void + onSelect: (type: string, accessMode: 'admin' | 'members') => void +} + +export function AddOrganizationSourceModal({ + sources, + pending, + ready, + feedback, + onClose, + onSelect, +}: AddOrganizationSourceModalProps) { + const [search, setSearch] = useState('') + const query = search.trim().toLowerCase() + const visible = sources.filter(({ meta }) => meta.name.toLowerCase().includes(query)) + + return ( + !open && onClose()} + srTitle='Add source' + > + Add source + + + setSearch(event.target.value)} + disabled={pending} + /> + + + {feedback} +

+ + + + + ) +} diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-settings.test.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-settings.test.tsx index 952880c34ee..45b6307162e 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-settings.test.tsx +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-settings.test.tsx @@ -23,6 +23,14 @@ vi.mock( '@/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup', () => ({ OrganizationIntegrationsSetup: () =>
Provider setup
}) ) +vi.mock( + '@/app/o/[organizationId]/settings/components/integrations/organization-source-stats', + () => ({ + OrganizationSourceStats: ({ organizationId }: { organizationId: string }) => ( +
Stats for {organizationId}
+ ), + }) +) vi.mock('@/hooks/queries/organization-accounts', () => ({ useOrganizationAccounts: mocks.accounts, useUpdateOrganizationAccounts: () => ({ @@ -53,6 +61,7 @@ describe('organization integration invitations', () => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true) mocks.context.mockReturnValue({ organization: { id: 'org-a' }, viewer: { isAdmin: true } }) mocks.accounts.mockReturnValue({ + isSuccess: true, data: { credentialGroup: { id: 'group-a', options: [] } }, error: null, refetch: mocks.refetch, @@ -111,9 +120,9 @@ describe('organization integration invitations', () => { ) ) const item = document.querySelector('[role="menuitem"]') - expect(item?.textContent).toBe('Refresh connection settings') + expect(item?.textContent).toBe('Update sign-in settings') await act(async () => item?.click()) - expect(document.body.textContent).toContain('Affected accounts will need to reconnect.') + expect(document.body.textContent).toContain('People whose settings changed must reconnect.') } it('keeps provider setup as the default and sends manual invitations from People to this org', async () => { @@ -147,6 +156,7 @@ describe('organization integration invitations', () => { it('refreshes saved provider identities only after choosing the maintenance action and confirming', async () => { mocks.accounts.mockReturnValue({ + isSuccess: true, data: { credentialGroup: { id: 'group-a', @@ -173,7 +183,7 @@ describe('organization integration invitations', () => { mocks.update.mockImplementationOnce((_input, { onSuccess }) => onSuccess()) await render() await openRefresh() - await click('Refresh') + await click('Update') expect(mocks.update).toHaveBeenCalledWith( { organizationId: 'org-a', @@ -198,26 +208,27 @@ describe('organization integration invitations', () => { }, expect.any(Object) ) - expect(toast.success).toHaveBeenCalledWith('Connection settings refreshed') + expect(toast.success).toHaveBeenCalledWith('Sign-in settings updated') expect(document.querySelector('[role="dialog"]')).toBeNull() }) it('keeps failed refreshes open for retry and blocks duplicate submissions', async () => { mocks.accounts.mockReturnValue({ + isSuccess: true, data: { credentialGroup: { id: 'group-a', options: [{ provider: 'gmail' }] } }, error: null, }) await render() await openRefresh() - await click('Refresh') + await click('Update') mocks.updateError = new Error('Update denied') await render() expect(document.body.textContent).toContain('Update denied') expect(document.querySelector('[role="dialog"]')).not.toBeNull() mocks.updatePending = true await render() - expect(findButton('Refresh')).toBeDisabled() + expect(findButton('Update')).toBeDisabled() expect(mocks.update).toHaveBeenCalledOnce() }) @@ -233,11 +244,16 @@ describe('organization integration invitations', () => { expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { enabled: true }) }) - it('loads people alongside setup but waits for the pool before allowing invitations', async () => { - mocks.accounts.mockReturnValue({ data: undefined, error: null, isPending: true }) - await render('?tab=people') + it('waits for integration options before loading filtered people or allowing invitations', async () => { + mocks.accounts.mockReturnValue({ + isSuccess: false, + data: undefined, + error: null, + isPending: true, + }) + await render('?tab=people&integration=jira') expect(mocks.accounts).toHaveBeenLastCalledWith('org-a') - expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { enabled: true }) + expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { enabled: false }) expect(container.textContent).toContain('Loading connected accounts') expect(container.textContent).not.toContain('No people invited yet') expect(findButton('Request connections')).toBeDisabled() @@ -245,10 +261,11 @@ describe('organization integration invitations', () => { expect(document.querySelector('[role="dialog"]')).toBeNull() mocks.accounts.mockReturnValue({ + isSuccess: true, data: { credentialGroup: { id: 'group-a', options: [] } }, error: null, }) - await render('?tab=people') + await render('?tab=people&integration=jira') expect(container.textContent).not.toContain('Loading connected accounts') expect(findButton('Request connections')).not.toBeDisabled() await click('Request connections') @@ -257,14 +274,23 @@ describe('organization integration invitations', () => { }) it('stops the people query when setup resolves without a pool and preserves the setup action', async () => { - mocks.accounts.mockReturnValue({ data: undefined, error: null, isPending: true }) + mocks.accounts.mockReturnValue({ + isSuccess: false, + data: undefined, + error: null, + isPending: true, + }) mocks.people.mockReturnValue({ error: new Error('Organization accounts not configured') }) - await render('?tab=people') - expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { enabled: true }) + await render('?tab=people&integration=jira') + expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { enabled: false }) expect(container.textContent).not.toContain('Organization accounts not configured') - mocks.accounts.mockReturnValue({ data: { credentialGroup: null }, error: null }) - await render('?tab=people') + mocks.accounts.mockReturnValue({ + isSuccess: true, + data: { credentialGroup: null }, + error: null, + }) + await render('?tab=people&integration=jira') expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { enabled: false }) expect(container.textContent).toContain('before requesting connections') expect(container.textContent).not.toContain('Organization accounts not configured') @@ -272,7 +298,11 @@ describe('organization integration invitations', () => { }) it('sends an org without a credential group back to provider setup before invitations', async () => { - mocks.accounts.mockReturnValue({ data: { credentialGroup: null }, error: null }) + mocks.accounts.mockReturnValue({ + isSuccess: true, + data: { credentialGroup: null }, + error: null, + }) await render('?tab=people') expect(container.textContent).toContain('before requesting connections') expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { enabled: false }) @@ -284,6 +314,7 @@ describe('organization integration invitations', () => { it('surfaces account lookup errors instead of treating them as missing setup', async () => { mocks.accounts.mockReturnValue({ + isSuccess: true, error: new Error('Account access denied'), refetch: mocks.refetch, }) @@ -304,4 +335,105 @@ describe('organization integration invitations', () => { expect(mocks.people).not.toHaveBeenCalled() expect(mocks.invite).not.toHaveBeenCalled() }) + it('opens organization stats without loading people', async () => { + await render() + await click('Stats') + expect(container.textContent).toContain('Stats for org-a') + expect(mocks.people).not.toHaveBeenCalled() + }) + + it('filters connection summaries and requests to the selected integration, then returns to All', async () => { + mocks.accounts.mockReturnValue({ + isSuccess: true, + data: { + credentialGroup: { + id: 'group-a', + options: [ + { id: 'jira-option', provider: 'jira', status: 'active' }, + { id: 'gmail-option', provider: 'gmail', status: 'active' }, + { id: 'old-option', provider: 'confluence', status: 'revoked' }, + ], + }, + }, + }) + await render('?tab=people&integration=jira&credential-group-people=alex') + expect(mocks.people).toHaveBeenLastCalledWith('org-a', 'alex', { + enabled: true, + optionId: 'jira-option', + }) + expect(findButton('Filter people by integration').textContent).toContain('Jira') + await click('Request connections') + expect(document.querySelector('[role="dialog"]')?.textContent).toContain( + 'Request Jira connections' + ) + await click('Cancel') + await act(async () => + findButton('Filter people by integration').dispatchEvent( + new MouseEvent('pointerdown', { bubbles: true, button: 0 }) + ) + ) + const all = Array.from(document.querySelectorAll('[role="menuitem"]')).find( + (item) => item.textContent === 'All integrations' + ) + expect(all).toBeDefined() + expect(document.querySelector('[role="menu"]')?.textContent).not.toContain('Confluence') + await act(async () => all?.click()) + await vi.waitFor(() => + expect(mocks.people).toHaveBeenLastCalledWith('org-a', 'alex', { enabled: true }) + ) + expect(container.querySelector('input[placeholder="Search people..."]')).toHaveValue('alex') + }) + + it.each(['', '&integration=gmail'])( + 'defaults to All on navigation with one integration and initial filter %s', + async (filter) => { + mocks.accounts.mockReturnValue({ + isSuccess: true, + data: { + credentialGroup: { + id: 'group-a', + options: [{ id: 'gmail-option', provider: 'gmail', status: 'active' }], + }, + }, + }) + await render(`?tab=people${filter}`) + expect(findButton('Filter people by integration').textContent).toContain( + filter ? 'Gmail' : 'All integrations' + ) + expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { + enabled: true, + ...(filter ? { optionId: 'gmail-option' } : {}), + }) + await click('Sources') + await click('People') + expect(findButton('Filter people by integration').textContent).toContain('All integrations') + expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { enabled: true }) + } + ) + + it('preserves Slack setup recovery in People without hiding existing connections', async () => { + mocks.accounts.mockReturnValue({ + isSuccess: true, + data: { + credentialGroup: { + id: 'group-a', + options: [ + { + id: 'slack-option', + provider: 'slack', + status: 'active', + configurationStatus: 'needs_update', + }, + ], + }, + }, + }) + await render('?tab=people&integration=slack') + expect(mocks.people).toHaveBeenLastCalledWith('org-a', '', { + enabled: true, + optionId: 'slack-option', + }) + expect(findButton('Request connections')).toBeDisabled() + expect(container.textContent).toContain('Update the Slack app from Sources') + }) }) diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-settings.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-settings.tsx index 5a88385585a..4753f09eb96 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-settings.tsx +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-settings.tsx @@ -2,17 +2,21 @@ import { useState } from 'react' import { Chip, ChipConfirmModal, ChipModalError, ChipSwitch, toast } from '@sim/emcn' -import { useQueryState } from 'nuqs' +import { useQueryStates } from 'nuqs' import { getOrganizationAccountUpdateOptions } from '@/lib/credential-groups/organization-account-options' import { useOrganizationContext } from '@/app/o/[organizationId]/providers/organization-provider' import { OrganizationIntegrationsSetup } from '@/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup' -import { organizationIntegrationsTabParam } from '@/app/o/[organizationId]/settings/components/integrations/search-params' +import { OrganizationSourcePeople } from '@/app/o/[organizationId]/settings/components/integrations/organization-source-people' +import { OrganizationSourceStats } from '@/app/o/[organizationId]/settings/components/integrations/organization-source-stats' +import { + organizationIntegrationsTabParam, + organizationPeopleIntegrationParam, +} from '@/app/o/[organizationId]/settings/components/integrations/search-params' import { RowActionsMenu } from '@/app/workspace/[workspaceId]/settings/components/row-actions-menu' import { SettingsEmptyState, SettingsQueryErrorState, } from '@/app/workspace/[workspaceId]/settings/components/settings-empty-state' -import { OrganizationAccountPeople } from '@/ee/credential-groups/components/organization-account-people' import { useOrganizationAccounts, useUpdateOrganizationAccounts, @@ -20,10 +24,10 @@ import { export function OrganizationIntegrationsSettings() { const { organization, viewer } = useOrganizationContext() - const [tab, setTab] = useQueryState( - organizationIntegrationsTabParam.key, - organizationIntegrationsTabParam.parser - ) + const [{ tab }, setNavigation] = useQueryStates({ + [organizationIntegrationsTabParam.key]: organizationIntegrationsTabParam.parser, + [organizationPeopleIntegrationParam.key]: organizationPeopleIntegrationParam.parser, + }) const accounts = useOrganizationAccounts(viewer.isAdmin ? organization.id : undefined) const update = useUpdateOrganizationAccounts() const [refreshOpen, setRefreshOpen] = useState(false) @@ -39,58 +43,68 @@ export function OrganizationIntegrationsSettings() { { onSuccess: () => { setRefreshOpen(false) - toast.success('Connection settings refreshed') + toast.success('Sign-in settings updated') }, } ) } if (!viewer.isAdmin) return null + const tabs = ( + void setNavigation({ tab: value, integration: null })} + options={[ + { value: 'providers', label: 'Sources' }, + { value: 'people', label: 'People' }, + { value: 'stats', label: 'Stats' }, + ]} + /> + ) + return (
-
- void setTab(value)} - options={[ - { value: 'providers', label: 'Sources' }, - { value: 'people', label: 'People' }, - ]} - /> - {tab === 'providers' && !accounts.error && group && group.options.length > 0 && ( - { - update.reset() - setRefreshOpen(true) + {tab === 'providers' && ( +
+ {tabs} + {tab === 'providers' && !accounts.error && group && group.options.length > 0 && ( + { + update.reset() + setRefreshOpen(true) + }, }, - }, - ]} - /> - )} -
+ ]} + /> + )} +
+ )} { if (!update.isPending) setRefreshOpen(open) }} - title='Refresh connection settings?' - text='Apply the latest sign-in settings to all integrations. Affected accounts will need to reconnect.' - confirm={{ label: 'Refresh', pending: update.isPending, onClick: refreshConnections }} + title='Update sign-in settings?' + text='Apply Sim’s current OAuth app and permission settings to member connections. People whose settings changed must reconnect. This does not sync content.' + confirm={{ label: 'Update', pending: update.isPending, onClick: refreshConnections }} > {update.error?.message} {tab === 'providers' && } + {tab === 'stats' && } {tab === 'people' && ( - Add a source that uses member accounts before requesting connections. - void setTab('providers')}>View sources + void setNavigation({ tab: 'providers', integration: null })}> + View sources +
) : undefined } diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.test.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.test.tsx index 9c1f75f361e..bb3eab8e511 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.test.tsx +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.test.tsx @@ -8,6 +8,9 @@ import type { OrganizationSearchProviderSummary } from '@/lib/api/contracts/know const mocks = vi.hoisted(() => ({ admin: true, + memberAccess: true, + mirroredAccess: true, + updateUrl: vi.fn(), overview: vi.fn(), push: vi.fn(), add: vi.fn(), @@ -25,7 +28,7 @@ vi.mock('@/app/o/[organizationId]/providers/organization-provider', () => ({ useOrganizationContext: () => ({ organization: { id: 'org-one' }, viewer: { isAdmin: mocks.admin }, - searchAccess: { memberScoped: true, sourceMirrored: true }, + searchAccess: { memberScoped: mocks.memberAccess, sourceMirrored: mocks.mirroredAccess }, }), })) vi.mock('@/hooks/queries/kb/connectors', () => ({ useOrganizationSearchOverview: mocks.overview })) @@ -73,6 +76,8 @@ let container: HTMLDivElement beforeEach(() => { vi.clearAllMocks() mocks.admin = true + mocks.memberAccess = true + mocks.mirroredAccess = true mocks.pending = false mocks.mutationError = null mocks.add.mockReset() @@ -83,6 +88,7 @@ beforeEach(() => { ['confluence', true], ['google-drive', true], ['google-email', true], + ['jira', true], ]), isIntegrationAvailabilityReady: true, refetchIntegrationAvailability: mocks.refetch, @@ -110,7 +116,7 @@ afterEach(async () => { async function render(searchParams = '') { await act(async () => root.render( - + @@ -128,253 +134,280 @@ async function click(label: string) { await act(async () => button!.click()) } -describe('organization integration management entry', () => { - it('uses Sources terminology in search and its empty state', async () => { - await render('?search=not-a-real-source') - expect(container.querySelector('input[placeholder="Search sources..."]')).toHaveValue( - 'not-a-real-source' - ) - expect(container.textContent).toContain('No matching sources') - expect(container.textContent).not.toContain('No matching integrations') - }) - it('offers Drive account management before anyone has connected', async () => { - mocks.overview.mockReturnValue({ - data: { - providers: [ - { - connectorType: 'google_drive', - approved: true, - sourceCount: 0, - status: 'waiting_for_connections', - issue: null, - isSyncing: false, - }, - ], - }, - isPending: false, +async function expectSetup(type: string | null, access: string | null = null) { + await act(async () => { + await vi.waitFor(() => { + const params = mocks.updateUrl.mock.calls.at(-1)?.[0].searchParams + expect(params).toBeDefined() + expect(params.get('addConnector')).toBe(type) + expect(params.get('source-access')).toBe(access) }) - await render() - expect(document.querySelector('a[aria-label="Manage Google Drive"]')).toHaveAttribute( - 'href', - '/o/org-one/settings/integrations/providers/google_drive' - ) - expect(document.querySelector('a[aria-label="Set up Google Drive"]')).toBeNull() - expect(container.textContent).toContain('Waiting for connections') }) - it('shows the stable catalog with switches and separate setup and management links', async () => { +} + +async function fillPicker(value: string) { + const input = document.querySelector('[aria-label="Find a source"]') + expect(input).not.toBeNull() + await act(async () => { + Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set?.call(input, value) + input?.dispatchEvent(new Event('input', { bubbles: true })) + }) +} + +describe('organization integration management entry', () => { + it('uses navigable settings rows for added sources without switches or setup buttons', async () => { await render() - expect(document.querySelector('a[aria-label="Manage Gmail"]')).toHaveAttribute( + expect(container.textContent).toContain('Waiting for connections') + expect(container.textContent).toContain('Deactivated · 2 connections') + expect(container.querySelector('a[aria-label="Manage Gmail"]')).toHaveAttribute( 'href', '/o/org-one/settings/integrations/providers/gmail' ) - expect(document.querySelector('a[aria-label="Manage Google Drive"]')).toHaveAttribute( - 'href', - '/o/org-one/settings/integrations/providers/google_drive' - ) - expect(container.textContent).toContain('Waiting for connections') - expect(container.textContent).not.toContain('Needs setup') - expect(container.textContent).toContain('Disabled') - expect(container.textContent).toContain('Confluence') - expect(container.textContent).not.toContain('Add integration') - expect(document.querySelector('[aria-label="Allow Gmail in Sim Search"]')).toHaveAttribute( - 'aria-checked', - 'true' - ) - expect( - document.querySelector('[aria-label="Allow Google Drive in Sim Search"]') - ).toHaveAttribute('aria-checked', 'false') - expect(document.querySelector('a[aria-label="Set up Confluence"]')).toBeNull() - }) - - it('offers the catalog for a new organization without a modal or writes', async () => { - mocks.overview.mockReturnValue({ data: { providers: [] }, isPending: false }) - await render() - expect(container.textContent).toContain('Confluence') - expect(container.textContent).toContain('Google Drive') - expect(document.querySelector('[role="dialog"]')).toBeNull() + expect(container.querySelector('a[aria-label="Manage Google Drive"]')).not.toBeNull() + expect(container.textContent).not.toContain('Confluence') + expect(container.querySelector('[role="switch"]')).toBeNull() + expect(container.querySelector('a[aria-label="Set up Gmail"]')).toBeNull() expect(mocks.add).not.toHaveBeenCalled() }) - it('enables in place and shows setup after the server confirms approval', async () => { - await render() - const row = document.querySelector('[aria-label="Allow Confluence in Sim Search"]') - await click('Allow Confluence in Sim Search') - expect(mocks.add).toHaveBeenCalledExactlyOnceWith( - { organizationId: 'org-one', connectorType: 'confluence', approved: true }, - expect.any(Object) - ) - expect(row).toHaveAttribute('aria-checked', 'false') + it('keeps approved sources with unfinished setup visible', async () => { mocks.overview.mockReturnValue({ data: { providers: [ - ...providers, { + ...providers[0], connectorType: 'confluence', - approved: true, - sourceCount: 0, status: 'needs_setup', - isSyncing: false, }, ], }, isPending: false, }) await render() - expect(document.querySelector('[aria-label="Allow Confluence in Sim Search"]')).toBe(row) - expect(row).toHaveAttribute('aria-checked', 'true') - expect(document.querySelector('a[aria-label="Set up Confluence"]')).not.toBeNull() - expect(mocks.push).not.toHaveBeenCalled() - expect(document.querySelector('[role="dialog"]')).toBeNull() + expect(container.textContent).toContain('Setup required') + expect(container.querySelector('a[aria-label="Manage Confluence"]')).not.toBeNull() }) - it('requires confirmation before disabling existing sources and lets the admin cancel', async () => { - mocks.overview.mockReturnValue({ - data: { providers: [{ ...providers[1], approved: true }] }, - isPending: false, - }) + it('opens the catalog from the header without changing any approvals', async () => { + mocks.overview.mockReturnValue({ data: { providers: [] }, isPending: false }) await render() - await click('Allow Google Drive in Sim Search') - expect(document.querySelector('[role="dialog"]')).toHaveTextContent( - 'Sources and connected accounts are preserved.' - ) + expect(container.textContent).toContain('No sources yet. Add a source to get started.') + expect(document.querySelector('[role="dialog"]')).toBeNull() + await click('Add source') + expect(document.querySelector('[role="dialog"]')).toHaveTextContent('Confluence') + expect(document.querySelector('[role="dialog"]')).toHaveTextContent('Jira') + expect(document.querySelector('[role="dialog"]')).toHaveTextContent('Connect a service account') + expect(document.querySelector('[role="dialog"]')).toHaveTextContent('Connect member accounts') expect(mocks.add).not.toHaveBeenCalled() await click('Cancel') expect(document.querySelector('[role="dialog"]')).toBeNull() + await expectSetup(null) expect(mocks.add).not.toHaveBeenCalled() - await click('Allow Google Drive in Sim Search') - mocks.add.mockImplementation((_input, options) => options.onSuccess()) - await click('Deactivate') + }) + + it('approves a new source before opening its central configuration form', async () => { + await render('?addConnector=') + await click('Set up Confluence') expect(mocks.add).toHaveBeenCalledExactlyOnceWith( - { organizationId: 'org-one', connectorType: 'google_drive', approved: false }, + { organizationId: 'org-one', connectorType: 'confluence', approved: true }, expect.any(Object) ) + expect(document.querySelector('[role="dialog"]')).not.toBeNull() + await act(async () => mocks.add.mock.calls[0][1].onSuccess()) + await expectSetup('confluence') expect(document.querySelector('[role="dialog"]')).toBeNull() }) - it('allows disabling an integration with no sources in place', async () => { - await render() - await click('Allow Gmail in Sim Search') - expect(mocks.add).toHaveBeenCalledExactlyOnceWith( - { organizationId: 'org-one', connectorType: 'gmail', approved: false }, + it('opens an approved source directly without a duplicate approval', async () => { + await render('?addConnector=&search=retained') + await click('Set up Gmail') + await expectSetup('gmail') + expect(mocks.updateUrl.mock.calls.at(-1)?.[0].searchParams.get('search')).toBe('retained') + expect(mocks.add).not.toHaveBeenCalled() + }) + + it.each(['jira', 'confluence'])( + 'uses member setup for %s when central indexing is unavailable', + async (type) => { + mocks.mirroredAccess = false + mocks.add.mockImplementation((_input, options) => options.onSuccess()) + await render('?addConnector=') + await click(`Set up ${type === 'jira' ? 'Jira' : 'Confluence'}`) + await expectSetup(type, 'members') + } + ) + + it('routes Slack into the existing member setup with its custom-app step', async () => { + mocks.availability.mockReturnValue({ + integrationAvailability: new Map([['slack_v2', { state: 'limited' }]]), + oauthServiceAvailability: new Map(), + isIntegrationAvailabilityReady: true, + }) + mocks.add.mockImplementation((_input, options) => options.onSuccess()) + await render('?addConnector=') + expect(document.querySelector('[role="dialog"]')).toHaveTextContent('Set up your Slack app') + await click('Set up Slack') + await expectSetup('slack', 'members') + }) + + it('reactivates a retained source before opening another configuration', async () => { + mocks.add.mockImplementation((_input, options) => options.onSuccess()) + await render('?addConnector=') + await click('Set up Google Drive') + await expectSetup('google_drive') + expect(mocks.add).toHaveBeenCalledWith( + { organizationId: 'org-one', connectorType: 'google_drive', approved: true }, expect.any(Object) ) - expect(document.querySelector('[role="dialog"]')).toBeNull() }) - it('keeps the confirmed state and reports failed approval changes', async () => { + it('keeps the picker open and toasts a failed approval for retry', async () => { mocks.add.mockImplementation((_input, options) => - options.onError(new Error('Could not update integration')) + options.onError(new Error('Could not add source')) ) - await render() - await click('Allow Confluence in Sim Search') - expect(toast.error).toHaveBeenCalledWith('Could not update integration') - expect(document.querySelector('[aria-label="Allow Confluence in Sim Search"]')).toHaveAttribute( - 'aria-checked', - 'false' - ) - expect(document.querySelector('a[aria-label="Set up Confluence"]')).toBeNull() + await render('?addConnector=') + await click('Set up Confluence') + expect(toast.error).toHaveBeenCalledWith('Could not add source') + expect(document.querySelector('[role="dialog"]')).not.toBeNull() + expect(mocks.updateUrl).not.toHaveBeenCalled() }) - it('keeps a failed deactivation in the confirmation dialog for retry', async () => { - mocks.overview.mockReturnValue({ - data: { providers: [{ ...providers[1], approved: true }] }, - isPending: false, + it('prevents another selection or dismissal while approval is pending', async () => { + mocks.pending = true + await render('?addConnector=') + expect(document.querySelector('button[aria-label="Set up Confluence"]')).toBeNull() + expect(document.querySelector('[aria-label="Find a source"]')).toBeDisabled() + await click('Cancel') + expect(document.querySelector('[role="dialog"]')).not.toBeNull() + expect(mocks.add).not.toHaveBeenCalled() + expect(mocks.updateUrl).not.toHaveBeenCalled() + }) + + it('explains unavailable providers in the picker without allowing setup', async () => { + mocks.availability.mockReturnValue({ + integrationAvailability: new Map(), + oauthServiceAvailability: new Map(), + isIntegrationAvailabilityReady: true, }) - await render() - await click('Allow Google Drive in Sim Search') - await click('Deactivate') - mocks.mutationError = new Error('Could not deactivate integration') - await render() + await render('?addConnector=') expect(document.querySelector('[role="dialog"]')).toHaveTextContent( - 'Could not deactivate integration' + 'Unavailable in this deployment' ) - expect( - document.querySelector('[aria-label="Allow Google Drive in Sim Search"]') - ).toHaveAttribute('aria-checked', 'true') - }) - - it('prevents duplicate changes while a mutation is pending', async () => { - mocks.pending = true - await render() - await click('Allow Confluence in Sim Search') + expect(document.querySelector('button[aria-label="Set up Confluence"]')).toBeNull() expect(mocks.add).not.toHaveBeenCalled() - expect(document.querySelector('[aria-label="Allow Confluence in Sim Search"]')).toBeDisabled() }) - it('blocks unavailable setup while keeping existing sources manageable and deactivatable', async () => { + it('keeps existing unavailable sources manageable', async () => { mocks.availability.mockReturnValue({ integrationAvailability: new Map(), oauthServiceAvailability: new Map(), isIntegrationAvailabilityReady: true, }) + await render() + expect(container.querySelector('a[aria-label="Manage Gmail"]')).not.toBeNull() + expect(container.querySelector('a[aria-label="Manage Google Drive"]')).not.toBeNull() + }) + + it('filters the picker independently from the main source list and resets when reopened', async () => { + await render('?search=gmail') + await click('Add source') + await fillPicker('confluence') + const dialog = document.querySelector('[role="dialog"]') + expect(dialog).toHaveTextContent('Confluence') + expect(dialog).not.toHaveTextContent('Google Drive') + expect(container.querySelector('a[aria-label="Manage Gmail"]')).not.toBeNull() + await fillPicker('no-such-source') + expect(dialog).toHaveTextContent('No matching sources') + await click('Cancel') + await click('Add source') + expect(document.querySelector('[aria-label="Find a source"]')).toHaveValue('') + expect(document.querySelector('[role="dialog"]')).toHaveTextContent('Google Drive') + expect(mocks.add).not.toHaveBeenCalled() + }) + + it('keeps source health visible alongside the configuration count', async () => { mocks.overview.mockReturnValue({ - data: { providers: [{ ...providers[1], approved: true }] }, + data: { + providers: [ + { + ...providers[1], + approved: true, + status: 'needs_attention', + issue: 'sync_failed', + }, + ], + }, isPending: false, }) await render() - expect(document.querySelector('[aria-label="Allow Confluence in Sim Search"]')).toBeDisabled() - expect( - document.querySelector('[aria-label="Allow Google Drive in Sim Search"]') - ).not.toBeDisabled() - expect(document.querySelector('a[aria-label="Manage Google Drive"]')).not.toBeNull() - expect(container.textContent).toContain('Unavailable in this deployment') - await click('Allow Confluence in Sim Search') - expect(mocks.add).not.toHaveBeenCalled() + expect(container.textContent).toContain('Sync failed · 2 connections') }) - it('fails closed while availability loads and offers retry if it fails', async () => { + it('fails closed and offers retry when availability fails inside the picker', async () => { mocks.availability.mockReturnValue({ integrationAvailability: new Map(), oauthServiceAvailability: new Map(), - isIntegrationAvailabilityReady: false, + isIntegrationAvailabilityReady: true, integrationAvailabilityError: new Error('Could not load connection availability'), refetchIntegrationAvailability: mocks.refetch, }) - await render() - expect(document.querySelector('[aria-label="Allow Confluence in Sim Search"]')).toBeDisabled() + await render('?addConnector=') + expect(document.querySelector('[role="dialog"]')).toHaveTextContent( + 'Could not load connection availability' + ) + expect(document.querySelector('button[aria-label="Set up Confluence"]')).toBeNull() await click('Try again') expect(mocks.refetch).toHaveBeenCalledOnce() }) - it('does not hide actionable sync failures behind a source count', async () => { - mocks.overview.mockReturnValue({ - data: { providers: [{ ...providers[1], approved: true, status: 'needs_attention' }] }, - isPending: false, - }) - await render() - expect(container.textContent).toContain('Sync failed') - expect(document.querySelector('a[aria-label="Manage Google Drive"]')).not.toBeNull() - }) - - it('does not turn a failed overview into unapproved switches', async () => { + it('does not turn a failed overview into an empty source list', async () => { mocks.overview.mockReturnValue({ error: new Error('Could not load sources'), isError: true, refetch: mocks.refetch, }) await render() - expect(document.querySelector('[role="switch"]')).toBeNull() + expect(container.textContent).not.toContain('No sources yet') + expect( + Array.from(container.querySelectorAll('button')).find( + (node) => node.textContent === 'Add source' + ) + ).toBeDisabled() await click('Try again') expect(mocks.refetch).toHaveBeenCalledOnce() }) - it('keeps loading distinct from unapproved integrations', async () => { + it('keeps loading distinct from a new organization', async () => { mocks.overview.mockReturnValue({ isPending: true }) await render() expect(container.textContent).toContain('Loading sources') - expect(document.querySelector('[role="switch"]')).toBeNull() + expect(container.textContent).not.toContain('No sources yet') + expect( + Array.from(container.querySelectorAll('button')).find( + (node) => node.textContent === 'Add source' + ) + ).toBeDisabled() }) it('does not expose admin controls or load admin data for members', async () => { mocks.admin = false - await render() + await render('?addConnector=') expect(mocks.overview).toHaveBeenLastCalledWith('org-one', { enabled: false }) expect(container.textContent).toBe('') + expect(document.querySelector('[role="dialog"]')).toBeNull() + }) + + it('does not expose setup when Search is disabled', async () => { + mocks.memberAccess = false + mocks.mirroredAccess = false + await render('?addConnector=') + expect(container.textContent).toContain('Search sources are not enabled') + expect(document.querySelector('[role="dialog"]')).toBeNull() }) - it('filters the whole catalog without changing approvals', async () => { - await render('?search=confluence') - expect(container.textContent).toContain('Confluence') + it('filters added sources without changing approvals', async () => { + await render('?search=gmail') + expect(container.textContent).toContain('Gmail') expect(container.textContent).not.toContain('Google Drive') expect(mocks.add).not.toHaveBeenCalled() }) diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.tsx index a3de964ef15..359388941bd 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.tsx +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.tsx @@ -1,19 +1,21 @@ 'use client' -import { useState } from 'react' -import { ChipConfirmModal, ChipLink, ChipModalError, Switch, toast } from '@sim/emcn' +import { toast } from '@sim/emcn' +import { Plus } from '@sim/emcn/icons' +import { useQueryStates } from 'nuqs' import { SettingsPanel } from '@/components/settings/settings-panel' import { organizationRoutes } from '@/lib/navigation/paths' -import { - canConnectWithDefaults, - getConnectorAccessAvailability, - SEARCH_SOURCE_TYPES, -} from '@/lib/sim-search/connectors' +import { getConnectorAccessAvailability, SEARCH_SOURCE_TYPES } from '@/lib/sim-search/connectors' import { useOrganizationContext } from '@/app/o/[organizationId]/providers/organization-provider' +import { AddOrganizationSourceModal } from '@/app/o/[organizationId]/settings/components/integrations/add-organization-source-modal' import { organizationSearchStatusLabel } from '@/app/o/[organizationId]/settings/components/integrations/organization-search-status' import { OrganizationSlackAccountSetup } from '@/app/o/[organizationId]/settings/components/integrations/slack-account-setup' import { IntegrationTile } from '@/app/workspace/[workspaceId]/integrations/components/integrations-showcase' import { SearchSourceSetup } from '@/app/workspace/[workspaceId]/search/components/search-source-setup' +import { + searchSetupAccessParam, + searchSetupParam, +} from '@/app/workspace/[workspaceId]/search/search-params' import { SettingsEmptyState, SettingsQueryErrorState, @@ -30,25 +32,62 @@ import { usePermissionConfig } from '@/hooks/use-permission-config' export function OrganizationIntegrationsSetup() { const { organization, viewer, searchAccess } = useOrganizationContext() const [search, setSearch] = useSettingsSearch() + const [setup, setSetup] = useQueryStates( + { + [searchSetupParam.key]: searchSetupParam.parser, + [searchSetupAccessParam.key]: searchSetupAccessParam.parser, + }, + { history: 'replace' } + ) const overview = useOrganizationSearchOverview(organization.id, { enabled: viewer.isAdmin }) const availability = usePermissionConfig() const approval = useUpdateSearchIntegration() - const [deactivating, setDeactivating] = useState(null) const providers = new Map( overview.data?.providers.map((provider) => [provider.connectorType, provider]) ) + const sources = SEARCH_SOURCE_TYPES.map(([type, meta]) => ({ + type, + meta, + access: getConnectorAccessAvailability(meta, availability.integrationAvailability, { + memberAccessAvailable: searchAccess.memberScoped, + mirroredAccessAvailable: searchAccess.sourceMirrored, + oauthServiceAvailability: availability.oauthServiceAvailability, + isIntegrationAvailabilityReady: availability.isIntegrationAvailabilityReady, + }), + })) const query = search.trim().toLowerCase() - const visible = SEARCH_SOURCE_TYPES.filter(([, meta]) => meta.name.toLowerCase().includes(query)) - const deactivatingName = SEARCH_SOURCE_TYPES.find(([type]) => type === deactivating)?.[1].name - const changeApproval = (connectorType: string, approved: boolean) => { - approval.reset() - if (!approved && (providers.get(connectorType)?.sourceCount ?? 0) > 0) { - setDeactivating(connectorType) + const visible = sources.flatMap((source) => { + const provider = providers.get(source.type) + return provider && + (provider.approved || provider.sourceCount > 0) && + source.meta.name.toLowerCase().includes(query) + ? [{ ...source, provider }] + : [] + }) + const ready = Boolean( + !overview.isPending && + !overview.isError && + availability.isIntegrationAvailabilityReady && + !availability.integrationAvailabilityError + ) + const closePicker = () => { + if (!approval.isPending) void setSetup({ addConnector: null, 'source-access': null }) + } + const selectSource = (type: string, accessMode: 'admin' | 'members') => { + const selectedType = searchSetupParam.parser.parse(type) + if (!selectedType || !ready || approval.isPending) return + const startSetup = () => + void setSetup({ + addConnector: selectedType, + 'source-access': accessMode === 'members' ? 'members' : null, + }) + if (providers.get(type)?.approved) { + startSetup() return } approval.mutate( - { organizationId: organization.id, connectorType, approved }, - { onError: (error) => toast.error(error.message) } + { organizationId: organization.id, connectorType: type, approved: true }, + { onSuccess: startSetup, onError: (error) => toast.error(error.message) } ) } if (!viewer.isAdmin) return null @@ -59,113 +98,94 @@ export function OrganizationIntegrationsSetup() { ) + const feedback = overview.isError ? ( + void overview.refetch()} + variant='inline' + /> + ) : availability.integrationAvailabilityError ? ( + void availability.refetchIntegrationAvailability()} + variant='inline' + /> + ) : null + return ( - - {availability.integrationAvailabilityError && ( - void availability.refetchIntegrationAvailability()} - variant='inline' - /> - )} -
- {overview.isError ? ( - void overview.refetch()} - variant='inline' - /> - ) : overview.isPending ? ( - Loading sources… - ) : visible.length === 0 ? ( - No matching sources - ) : ( - visible.map(([type, meta]) => { - const provider = providers.get(type) - const approved = provider?.approved === true - const sourceCount = provider?.sourceCount ?? 0 - const access = getConnectorAccessAvailability( - meta, - availability.integrationAvailability, - { - memberAccessAvailable: searchAccess.memberScoped, - mirroredAccessAvailable: searchAccess.sourceMirrored, - oauthServiceAvailability: availability.oauthServiceAvailability, - isIntegrationAvailabilityReady: availability.isIntegrationAvailabilityReady, - } - ) - const available = access.admin || access.members - const hasSources = sourceCount > 0 - const manage = hasSources || canConnectWithDefaults(meta) - let description = provider ? organizationSearchStatusLabel(provider) : undefined - if (!hasSources && availability.isIntegrationAvailabilityReady && !available) - description = 'Unavailable in this deployment' - return ( - } - title={meta.name} - description={description} - trailing={ -
- {(hasSources || (approved && available)) && ( - - {manage ? 'Manage' : 'Set up'} - - )} - changeApproval(type, checked)} - /> -
- } - /> - ) - }) - )} -
- { - if (!open && !approval.isPending) setDeactivating(null) - }} - title={`Deactivate ${deactivatingName ?? 'integration'}?`} - text='Its content will be unavailable in Search, Assistant, and MCP. Sources and connected accounts are preserved.' - confirm={{ - label: 'Deactivate', - variant: 'destructive', - pending: approval.isPending, - onClick: () => { - if (!deactivating) return - approval.mutate( - { organizationId: organization.id, connectorType: deactivating, approved: false }, - { onSuccess: () => setDeactivating(null) } - ) + <> + void setSetup({ addConnector: '', 'source-access': null }), }, - }} + ]} + search={{ value: search, onChange: setSearch, placeholder: 'Search sources...' }} > - {approval.error?.message} - - + {setup.addConnector !== '' && feedback} +
+ {overview.isError ? null : overview.isPending ? ( + Loading sources… + ) : visible.length === 0 ? ( + + {query ? 'No matching sources' : 'No sources yet. Add a source to get started.'} + + ) : ( + visible.map(({ type, meta, access, provider }) => { + const available = access.admin || access.members + const status = + provider.approved && ready && !available + ? 'Unavailable in this deployment' + : organizationSearchStatusLabel(provider) + return ( + } + title={meta.name} + description={[ + status, + provider.sourceCount > 0 + ? `${provider.sourceCount} ${provider.sourceCount === 1 ? 'connection' : 'connections'}` + : undefined, + ] + .filter(Boolean) + .join(' · ')} + href={organizationRoutes(organization.id).searchProvider(type)} + clickLabel={`Manage ${meta.name}`} + navigable + /> + ) + }) + )} +
+
+ {setup.addConnector === '' ? ( + + ) : ( + + )} - + ) } diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period.test.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period.test.tsx new file mode 100644 index 00000000000..c5b62c0626c --- /dev/null +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period.test.tsx @@ -0,0 +1,127 @@ +/** @vitest-environment jsdom */ +import { act } from 'react' +import { createRoot, type Root } from 'react-dom/client' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { OrganizationSearchStatsPeriod } from '@/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period' + +let root: Root +let container: HTMLDivElement +let originalScroll: typeof HTMLElement.prototype.scrollIntoView +const onChange = vi.fn() + +beforeEach(() => { + vi.clearAllMocks() + vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true) + originalScroll = HTMLElement.prototype.scrollIntoView + HTMLElement.prototype.scrollIntoView = vi.fn() + container = document.createElement('div') + document.body.appendChild(container) + root = createRoot(container) +}) +afterEach(async () => { + await act(async () => root.unmount()) + container.remove() + HTMLElement.prototype.scrollIntoView = originalScroll + vi.unstubAllGlobals() +}) + +async function render() { + await act(async () => + root.render( + + ) + ) +} +async function selectPeriod(label: string) { + const trigger = container.querySelector('[role="combobox"]') + expect(trigger).not.toBeNull() + await act(async () => + trigger?.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true })) + ) + const option = Array.from(document.querySelectorAll('[role="option"]')).find( + (item) => item.textContent === label + ) + expect(option).toBeDefined() + await act(async () => option?.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }))) +} +async function click(label: string) { + const button = Array.from(document.querySelectorAll('button')).find( + (item) => item.textContent === label + ) + expect(button).toBeDefined() + await act(async () => button?.click()) +} + +describe('Stats date selection', () => { + it('keeps the existing range when calendar edits are cancelled', async () => { + await render() + await selectPeriod('Custom range') + expect( + document + .querySelector('[data-radix-popper-content-wrapper]') + ?.contains(document.activeElement) + ).toBe(true) + await click('5') + await click('8') + expect(onChange).not.toHaveBeenCalled() + await click('Cancel') + await vi.waitFor(() => + expect(document.activeElement).toBe(container.querySelector('[role="combobox"]')) + ) + expect(onChange).not.toHaveBeenCalled() + expect(document.body.textContent).not.toContain('Apply') + expect(container.textContent).toContain('Sep 1 – Sep 3') + }) + it('applies both date-only boundaries in one update and closes the calendar', async () => { + await render() + await selectPeriod('Custom range') + await click('5') + await click('8') + await click('Apply') + expect(onChange).toHaveBeenCalledExactlyOnceWith({ + period: 'custom', + startDate: '2024-09-05', + endDate: '2024-09-08', + }) + expect(document.body.textContent).not.toContain('Apply') + }) + it('clears custom boundaries when choosing a preset', async () => { + await render() + await selectPeriod('Past 3 days') + expect(onChange).toHaveBeenCalledExactlyOnceWith({ + period: '3d', + startDate: null, + endDate: null, + }) + }) + it('opens the calendar from the keyboard and restores focus on Escape', async () => { + await render() + const trigger = container.querySelector('[role="combobox"]') + await act(async () => { + trigger?.focus() + trigger?.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true })) + }) + for (let index = 0; index < 6; index++) { + await act(async () => + trigger?.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true })) + ) + } + await act(async () => + trigger?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })) + ) + expect(document.body.textContent).toContain('Apply') + expect(document.activeElement).not.toBe(trigger) + await act(async () => + document.activeElement?.dispatchEvent( + new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }) + ) + ) + await vi.waitFor(() => expect(document.activeElement).toBe(trigger)) + expect(onChange).not.toHaveBeenCalled() + }) +}) diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period.tsx new file mode 100644 index 00000000000..cff874b2785 --- /dev/null +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period.tsx @@ -0,0 +1,89 @@ +'use client' + +import { useRef, useState } from 'react' +import { Calendar, ChipCombobox, Popover, PopoverAnchor, PopoverContent, toast } from '@sim/emcn' +import { formatDateShort } from '@/lib/core/utils/date-display' +import { getSearchStatsRangeError, type SEARCH_STATS_PERIODS } from '@/lib/knowledge/search/stats' + +const PERIOD_OPTIONS = [ + { value: 'today', label: 'Today' }, + { value: '3d', label: 'Past 3 days' }, + { value: '7d', label: 'Past 7 days' }, + { value: '14d', label: 'Past 14 days' }, + { value: '30d', label: 'Past 30 days' }, + { value: '90d', label: 'Past 90 days' }, + { value: 'custom', label: 'Custom range' }, +] satisfies { value: (typeof SEARCH_STATS_PERIODS)[number]; label: string }[] + +interface SearchStatsPeriodSelection { + period: (typeof SEARCH_STATS_PERIODS)[number] + startDate: string | null + endDate: string | null +} + +interface OrganizationSearchStatsPeriodProps extends SearchStatsPeriodSelection { + onChange: (selection: SearchStatsPeriodSelection) => void +} + +export function OrganizationSearchStatsPeriod({ + period, + startDate, + endDate, + onChange, +}: OrganizationSearchStatsPeriodProps) { + const triggerContainerRef = useRef(null) + const calendarRef = useRef(null) + const [calendarOpen, setCalendarOpen] = useState(false) + const label = + period === 'custom' && startDate && endDate && !getSearchStatsRangeError({ startDate, endDate }) + ? `${formatDateShort(startDate)} – ${formatDateShort(endDate)}` + : PERIOD_OPTIONS.find((option) => option.value === period)?.label + + return ( +
+ { + const selected = PERIOD_OPTIONS.find((option) => option.value === value) + if (!selected) return + if (selected.value === 'custom') setCalendarOpen(true) + else onChange({ period: selected.value, startDate: null, endDate: null }) + }} + /> + + + calendarRef.current?.focus()} + onCloseAutoFocus={() => + triggerContainerRef.current?.querySelector('[role="combobox"]')?.focus() + } + > + setCalendarOpen(false)} + onRangeChange={(start, end) => { + const error = getSearchStatsRangeError({ startDate: start, endDate: end }) + if (error) { + toast.error(error) + return + } + onChange({ period: 'custom', startDate: start, endDate: end }) + setCalendarOpen(false) + }} + /> + + +
+ ) +} diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-status.test.ts b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-status.test.ts index dc1bfa33cfa..90b069f5f44 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-status.test.ts +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-status.test.ts @@ -16,13 +16,13 @@ describe('organization source status labels', () => { it('describes the next step instead of calling all empty integrations unconfigured', () => { expect(organizationSearchStatusLabel(provider)).toBe('Waiting for connections') expect(organizationSearchStatusLabel({ ...provider, status: 'needs_setup' })).toBe( - 'Source not configured' + 'Setup required' ) expect( organizationSearchStatusLabel({ ...provider, status: 'needs_setup', sourceCount: 1 }) ).toBe('Waiting for first sync') expect(organizationSearchStatusLabel({ ...provider, status: 'active', sourceCount: 1 })).toBe( - 'Enabled' + 'Ready to search' ) }) it.each([ @@ -50,6 +50,6 @@ describe('organization source status labels', () => { status: 'needs_attention', issue: 'sync_failed', }) - ).toBe('Disabled') + ).toBe('Deactivated') }) }) diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-status.ts b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-status.ts index 547f0339812..5988b08ce56 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-status.ts +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-search-status.ts @@ -1,16 +1,16 @@ import type { OrganizationSearchProviderSummary } from '@/lib/api/contracts/knowledge/connectors' const STATUS_LABELS: Record = { - needs_setup: 'Source not configured', + needs_setup: 'Setup required', waiting_for_connections: 'Waiting for connections', indexing: 'Indexing', needs_attention: 'Sync failed', paused: 'Paused', - active: 'Enabled', + active: 'Ready to search', } export function organizationSearchStatusLabel(provider: OrganizationSearchProviderSummary): string { - if (!provider.approved) return 'Disabled' + if (!provider.approved) return 'Deactivated' if (provider.status === 'needs_setup' && provider.sourceCount > 0) return 'Waiting for first sync' if (provider.status === 'needs_attention') { const error = diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-people.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-people.tsx new file mode 100644 index 00000000000..338ba91c5d9 --- /dev/null +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-people.tsx @@ -0,0 +1,79 @@ +'use client' + +import type { ComponentProps, ReactNode } from 'react' +import { ChipSelect } from '@sim/emcn' +import { useQueryState } from 'nuqs' +import type { CredentialGroupOption } from '@/lib/api/contracts/credential-groups' +import { getCredentialGroupIndexingConnector } from '@/lib/credential-groups/indexing' +import { organizationPeopleIntegrationParam } from '@/app/o/[organizationId]/settings/components/integrations/search-params' +import { OrganizationAccountPeople } from '@/ee/credential-groups/components/organization-account-people' + +interface OrganizationSourcePeopleProps + extends Omit, 'searchConnection' | 'filters'> { + options: CredentialGroupOption[] + tabs: ReactNode +} + +export function OrganizationSourcePeople({ + options, + tabs, + ...props +}: OrganizationSourcePeopleProps) { + const [integration, setIntegration] = useQueryState( + organizationPeopleIntegrationParam.key, + organizationPeopleIntegrationParam.parser + ) + const integrations = options + .flatMap((option) => { + const connector = getCredentialGroupIndexingConnector(option.provider) + return option.status === 'active' && connector + ? [ + { + optionId: option.id, + type: connector.type, + name: connector.meta.name, + icon: connector.meta.icon, + needsSetup: option.provider === 'slack' && option.configurationStatus !== 'ready', + }, + ] + : [] + }) + .sort((a, b) => a.name.localeCompare(b.name)) + const selected = integrations.find((item) => item.type === integration) + + return ( + +
+ {tabs} + void setIntegration(value === 'all' ? null : value)} + disabled={props.enabled === false || Boolean(props.setupFallback)} + options={[ + { value: 'all', label: 'All integrations' }, + ...integrations.map((item) => ({ + value: item.type, + label: item.name, + icon: item.icon, + })), + ]} + /> +
+ {selected?.needsSetup && ( +

+ Update the Slack app from Sources before requesting connections. +

+ )} + + } + /> + ) +} diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-stats.test.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-stats.test.tsx new file mode 100644 index 00000000000..11481d6a1f4 --- /dev/null +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-stats.test.tsx @@ -0,0 +1,152 @@ +/** @vitest-environment jsdom */ +import { act } from 'react' +import { NuqsTestingAdapter } from 'nuqs/adapters/testing' +import { createRoot, type Root } from 'react-dom/client' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type { OrganizationSearchStats } from '@/lib/api/contracts/knowledge/search-stats' + +const mocks = vi.hoisted(() => ({ + query: vi.fn(), + chart: vi.fn(), + refetch: vi.fn(), + updateUrl: vi.fn(), +})) +vi.mock('@/hooks/queries/organization-search-stats', () => ({ + useOrganizationSearchStats: mocks.query, +})) +vi.mock('@/components/charts', () => ({ + BarChart: (props: unknown) => { + mocks.chart(props) + return
Daily chart
+ }, +})) +vi.mock('@/connectors/registry', () => ({ + CONNECTOR_META_REGISTRY: { confluence: { name: 'Confluence' }, jira: { name: 'Jira' } }, +})) +vi.mock('next/navigation', () => ({ useRouter: () => ({}) })) + +import { SettingsHeaderProvider } from '@/components/settings/settings-header' +import { OrganizationSourceStats } from '@/app/o/[organizationId]/settings/components/integrations/organization-source-stats' + +const data: OrganizationSearchStats = { + start: '2026-09-04T00:00:00.000Z', + end: '2026-09-10T20:00:00.000Z', + totals: { invocations: 5, activePeople: 2, results: 8 }, + series: [{ timestamp: '2026-09-10T00:00:00.000Z', invocations: 5 }], + sources: [{ sourceType: 'confluence', invocations: 4 }], + surfaces: [ + { surface: 'dashboard', invocations: 3 }, + { surface: 'mcp', invocations: 2 }, + ], + people: [ + { + userId: 'person', + name: 'Alex', + email: 'alex@example.com', + invocations: 5, + sourceTypes: ['confluence', 'jira'], + }, + ], +} +let root: Root +let container: HTMLDivElement + +beforeEach(() => { + vi.clearAllMocks() + vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true) + mocks.query.mockReturnValue({ data, isError: false, refetch: mocks.refetch }) + container = document.createElement('div') + document.body.appendChild(container) + root = createRoot(container) +}) +afterEach(async () => { + await act(async () => root.unmount()) + container.remove() + vi.unstubAllGlobals() +}) +async function render(searchParams = '') { + await act(async () => + root.render( + + + Sources People Stats} /> + + + ) + ) +} + +describe('organization Search stats', () => { + it('renders request metrics, source labels, people and the canonical daily chart', async () => { + await render() + expect(container.textContent).not.toContain('No-result rate') + expect(container.textContent).toContain('Confluence, Jira') + expect(container.textContent).toContain('alex@example.com') + expect(mocks.chart).toHaveBeenCalledWith( + expect.objectContaining({ data: [{ timestamp: data.series[0].timestamp, value: 5 }] }) + ) + expect(container.textContent).not.toMatch(/citations|clicks|agent runs/i) + }) + it('restores filters from the URL and scopes every metric request consistently', async () => { + await render('?stats-period=7d&stats-surface=mcp') + expect(mocks.query).toHaveBeenLastCalledWith({ + organizationId: 'org', + period: '7d', + surface: 'mcp', + }) + expect(container.textContent).not.toContain('Invocations by surface') + const filter = container.querySelector('button[aria-label="Search surface"]') + const toolbar = filter?.parentElement?.parentElement + expect(toolbar?.textContent).toContain('Sources People Stats') + }) + it('restores a custom UTC range with the surface filter', async () => { + await render( + '?stats-period=custom&stats-start=2026-09-01&stats-end=2026-09-03&stats-surface=slack' + ) + expect(mocks.query).toHaveBeenLastCalledWith({ + organizationId: 'org', + period: 'custom', + startDate: '2026-09-01', + endDate: '2026-09-03', + surface: 'slack', + }) + expect(container.textContent).toContain('Sep 1 – Sep 3') + }) + it('keeps the daily chart mounted with zero-valued buckets when there is no activity', async () => { + mocks.query.mockReturnValue({ + data: { + ...data, + totals: { invocations: 0, activePeople: 0, results: 0 }, + series: data.series.map((point) => ({ ...point, invocations: 0 })), + sources: [], + surfaces: [], + people: [], + }, + isError: false, + }) + await render() + expect(container.textContent).not.toContain('No recorded Search activity') + expect(container.querySelectorAll('dd')).toHaveLength(3) + expect(Array.from(container.querySelectorAll('dd'), (metric) => metric.textContent)).toEqual([ + '0', + '0', + '0', + ]) + expect(mocks.chart).toHaveBeenCalledWith( + expect.objectContaining({ + data: [{ timestamp: data.series[0].timestamp, value: 0 }], + }) + ) + }) + it('offers retry instead of displaying stale successful totals on failure', async () => { + mocks.query.mockReturnValue({ data, isError: true, refetch: mocks.refetch }) + await render() + expect(container.textContent).toContain('Couldn’t load Search stats') + expect(container.textContent).not.toContain('Search invocations') + const retry = Array.from(container.querySelectorAll('button')).find( + (button) => button.textContent === 'Try again' + ) + await act(async () => retry?.click()) + expect(mocks.refetch).toHaveBeenCalledOnce() + }) +}) diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-stats.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-stats.tsx new file mode 100644 index 00000000000..1765187b12d --- /dev/null +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/organization-source-stats.tsx @@ -0,0 +1,227 @@ +'use client' + +import { type ReactNode, useMemo } from 'react' +import { Chip, ChipSelect, Tooltip } from '@sim/emcn' +import { CircleInfo } from '@sim/emcn/icons' +import { useQueryStates } from 'nuqs' +import { BarChart } from '@/components/charts' +import { + SEARCH_STATS_PEOPLE_LIMIT, + SEARCH_STATS_SURFACE_LABELS, + SEARCH_STATS_SURFACES, +} from '@/lib/knowledge/search/stats' +import { OrganizationSearchStatsPeriod } from '@/app/o/[organizationId]/settings/components/integrations/organization-search-stats-period' +import { SettingsEmptyState } from '@/app/workspace/[workspaceId]/settings/components/settings-empty-state' +import { SettingsPanel } from '@/app/workspace/[workspaceId]/settings/components/settings-panel' +import { + RESOURCE_LIST_STACK, + SettingsResourceRow, +} from '@/app/workspace/[workspaceId]/settings/components/settings-resource-row' +import { SettingsSection } from '@/app/workspace/[workspaceId]/settings/components/settings-section/settings-section' +import { CONNECTOR_META_REGISTRY } from '@/connectors/registry' +import { + organizationSearchStatsParsers, + organizationSearchStatsUrlOptions, +} from '@/ee/organization-search-stats/search-params' +import { useOrganizationSearchStats } from '@/hooks/queries/organization-search-stats' + +const SURFACE_OPTIONS = [ + { value: 'all', label: 'All surfaces' }, + ...SEARCH_STATS_SURFACES.map((surface) => ({ + value: surface, + label: SEARCH_STATS_SURFACE_LABELS[surface], + })), +] + +interface OrganizationSourceStatsProps { + organizationId: string + tabs?: ReactNode +} + +function sourceLabel(sourceType: string) { + return ( + CONNECTOR_META_REGISTRY[sourceType]?.name ?? (sourceType === 'uploads' ? 'Uploads' : sourceType) + ) +} + +export function OrganizationSourceStats({ organizationId, tabs }: OrganizationSourceStatsProps) { + const [{ period, surface, startDate, endDate }, setFilters] = useQueryStates( + organizationSearchStatsParsers, + organizationSearchStatsUrlOptions + ) + const stats = useOrganizationSearchStats({ + organizationId, + period, + surface: surface ?? undefined, + ...(period === 'custom' + ? { startDate: startDate ?? undefined, endDate: endDate ?? undefined } + : {}), + }) + const series = useMemo( + () => + stats.data?.series.map((point) => ({ + timestamp: point.timestamp, + value: point.invocations, + })) ?? [], + [stats.data?.series] + ) + const data = stats.data + const totals = data?.totals + const metrics = totals + ? [ + { label: 'Search invocations', value: totals.invocations.toLocaleString() }, + { label: 'Active people', value: totals.activePeople.toLocaleString() }, + { label: 'Results returned', value: totals.results.toLocaleString() }, + ] + : [] + + return ( + +
+ {tabs} +
+ + void setFilters({ surface: organizationSearchStatsParsers.surface.parse(value) }) + } + /> + void setFilters(selection)} + /> +
+
+ {stats.isError ? ( + + Couldn’t load Search stats. void stats.refetch()}>Try again + + ) : !data || !totals ? ( + Loading Search stats… + ) : ( + <> +
+ {metrics.map((metric) => ( +
+
{metric.label}
+
{metric.value}
+
+ ))} +
+ + + + + + Successful Search requests since tracking was enabled. Assistant and MCP counts + are Search tool calls. Results count each document once per request. One request + can return multiple sources. + + + } + action={ + + {period === 'custom' ? 'UTC' : 'UTC · Includes today'} + + } + > + + + {!surface && totals.invocations > 0 && ( + +
+ {data.surfaces.map((row) => ( + + {row.invocations.toLocaleString()} + + } + /> + ))} +
+
+ )} + + Invocations returning this source + + } + > + {data.sources.length ? ( +
+ {data.sources.map((row) => { + const Icon = CONNECTOR_META_REGISTRY[row.sourceType]?.icon + return ( + : undefined} + title={sourceLabel(row.sourceType)} + badge={ + + {row.invocations.toLocaleString()} + + } + /> + ) + })} +
+ ) : ( + + No sources returned in this period. + + )} +
+ + Top {SEARCH_STATS_PEOPLE_LIMIT} · Invocations + + } + > + {data.people.length ? ( +
+ {data.people.map((person) => ( + + {person.invocations.toLocaleString()} + + } + /> + ))} +
+ ) : ( + + No active people in this period. + + )} +
+ + )} +
+ ) +} diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/search-params.ts b/apps/sim/app/o/[organizationId]/settings/components/integrations/search-params.ts index 30d5f4c5561..ad97007ca37 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/search-params.ts +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/search-params.ts @@ -1,8 +1,8 @@ -import { parseAsStringLiteral } from 'nuqs/server' +import { createSerializer, parseAsString, parseAsStringLiteral } from 'nuqs/server' export const organizationIntegrationsTabParam = { key: 'tab', - parser: parseAsStringLiteral(['providers', 'people']).withDefault('providers'), + parser: parseAsStringLiteral(['providers', 'people', 'stats']).withDefault('providers'), } as const export const connectedAccountsParam = { @@ -10,7 +10,14 @@ export const connectedAccountsParam = { parser: parseAsStringLiteral(['slack']), } as const -export const organizationProviderTabParam = { - key: 'view', - parser: parseAsStringLiteral(['sources', 'accounts']).withDefault('sources'), +/** An absent integration includes connections from all integrations. */ +export const organizationPeopleIntegrationParam = { + key: 'integration', + parser: parseAsString, } as const + +export const serializeOrganizationPeople = createSerializer({ + tab: organizationIntegrationsTabParam.parser, + integration: organizationPeopleIntegrationParam.parser, + 'credential-group-people': parseAsString, +}) diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-removal.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-removal.tsx index 2dff4d17b5f..10dac1eb1bb 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-removal.tsx +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-removal.tsx @@ -24,8 +24,8 @@ export function OrganizationSlackAccountRemoval({ onOpenChange={(open) => { if (!open && !update.isPending) onClose() }} - title='Remove Slack account setup?' - text='This disconnects your organization’s Slack accounts and clears their saved app configuration. Remove any sources using these accounts first.' + title='Remove Slack app setup?' + text='This disconnects your organization’s Slack accounts and clears their saved app configuration. Remove any connections using these accounts first.' confirm={{ label: 'Remove', variant: 'destructive', diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-setup.test.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-setup.test.tsx index 1cc0c9b77b9..eef37d52a2f 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-setup.test.tsx +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-setup.test.tsx @@ -72,8 +72,57 @@ describe('organization Slack setup continuation', () => { it('prepares a missing container without asking the admin to make an extra choice', async () => { await render() expect(mocks.ensure).toHaveBeenCalledExactlyOnceWith({ organizationId: 'org-a' }) - expect(document.body.textContent).toContain('Loading Slack setup') - expect(document.body.textContent).not.toContain('Continue') + expect(document.querySelector('[role="dialog"]')).toBeNull() + expect(mocks.modal).not.toHaveBeenCalled() + mocks.prepare.mockReturnValue({ mutate: mocks.ensure, isIdle: false, isPending: true }) + await render() + expect(document.querySelector('[role="dialog"]')).toBeNull() + expect(mocks.ensure).toHaveBeenCalledOnce() + mocks.prepare.mockReturnValue({ + mutate: mocks.ensure, + isIdle: false, + isPending: false, + data: { credentialGroup: { id: 'group-a', organizationId: 'org-a', options: [] } }, + }) + await render() + expect(mocks.modal).toHaveBeenCalledWith( + expect.objectContaining({ credentialGroupId: 'group-a' }), + undefined + ) + }) + + it('does not open a temporary modal while discovering accounts', async () => { + mocks.accounts.mockReturnValue({ isSuccess: false, isPending: true }) + await render() + expect(document.querySelector('[role="dialog"]')).toBeNull() + expect(mocks.ensure).not.toHaveBeenCalled() + expect(mocks.modal).not.toHaveBeenCalled() + }) + + it.each(['discovery', 'preparation'])('keeps %s errors recoverable', async (stage) => { + const retry = vi.fn() + if (stage === 'discovery') { + mocks.accounts.mockReturnValue({ + isSuccess: false, + error: new Error('Could not load Slack setup'), + refetch: retry, + }) + } else { + mocks.prepare.mockReturnValue({ + mutate: mocks.ensure, + isIdle: false, + error: new Error('Could not prepare Slack setup'), + }) + } + await render() + expect(document.body.textContent).toContain('Set up Slack app') + const retryButton = Array.from(document.querySelectorAll('button')).find( + (button) => button.textContent === 'Try again' + ) + expect(retryButton).toBeDefined() + await act(async () => retryButton?.click()) + if (stage === 'discovery') expect(retry).toHaveBeenCalledOnce() + else expect(mocks.ensure).toHaveBeenCalledExactlyOnceWith({ organizationId: 'org-a' }) }) it('does not prepare accounts or open admin setup for an ordinary member', async () => { diff --git a/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-setup.tsx b/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-setup.tsx index e5e46838ec2..37d11404811 100644 --- a/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-setup.tsx +++ b/apps/sim/app/o/[organizationId]/settings/components/integrations/slack-account-setup.tsx @@ -15,10 +15,7 @@ import { searchSetupParam, searchSetupReturnParam, } from '@/app/workspace/[workspaceId]/search/search-params' -import { - SettingsEmptyState, - SettingsQueryErrorState, -} from '@/app/workspace/[workspaceId]/settings/components/settings-empty-state' +import { SettingsQueryErrorState } from '@/app/workspace/[workspaceId]/settings/components/settings-empty-state' import { SlackManagedUsersModal } from '@/ee/credential-groups/components/slack-managed-users-modal' import { useEnsureOrganizationAccounts, @@ -83,32 +80,30 @@ export function OrganizationSlackAccountSetup() { }} /> ) + const error = accounts.error ?? setupError + if (!error) return null return ( { if (!next) close() }} - srTitle='Connect Slack accounts' + srTitle='Set up Slack app' > - Connect Slack accounts + Set up Slack app - - {accounts.error || setupError ? ( - - accounts.error - ? void accounts.refetch() - : ensureAccounts({ organizationId: organization.id }) - } - variant='inline' - /> - ) : ( - Loading Slack setup… - )} + + + accounts.error + ? void accounts.refetch() + : ensureAccounts({ organizationId: organization.id }) + } + variant='inline' + /> diff --git a/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page.test.tsx b/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page.test.tsx index 25ff75fb3e8..bf09e5c23f9 100644 --- a/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page.test.tsx +++ b/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page.test.tsx @@ -1,105 +1,81 @@ /** @vitest-environment node */ -import { Suspense } from 'react' -import { beforeEach, describe, expect, it, vi } from 'vitest' +import { beforeEach, expect, it, vi } from 'vitest' -const mocks = vi.hoisted(() => ({ - session: vi.fn(), - authorize: vi.fn(), - redirect: vi.fn(), - notFound: vi.fn(), -})) +const mocks = vi.hoisted(() => ({ session: vi.fn(), authorize: vi.fn(), redirect: vi.fn() })) vi.mock('@/lib/auth', () => ({ getSession: mocks.session })) vi.mock('@/lib/settings/application/organization-section-access', () => ({ authorizeOrganizationSettingsSection: mocks.authorize, })) -vi.mock('@/lib/sim-search/connectors', () => ({ - SEARCH_SOURCE_TYPES: [['google_drive', { name: 'Google Drive' }]], +vi.mock('next/navigation', () => ({ + redirect: (url: string) => { + mocks.redirect(url) + throw new Error('redirect') + }, + notFound: () => { + throw new Error('not found') + }, })) -vi.mock('next/navigation', () => ({ redirect: mocks.redirect, notFound: mocks.notFound })) -vi.mock('@/components/settings/settings-header', () => ({ - SettingsHeaderProvider: 'header-provider', - SettingsHeaderShell: 'header-shell', +vi.mock('@/lib/sim-search/connectors', () => ({ + SEARCH_SOURCE_TYPES: [ + ['jira', { name: 'Jira' }], + ['confluence', { name: 'Confluence' }], + ], })) vi.mock( '@/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail', - () => ({ OrganizationProviderDetail: 'provider-detail' }) + () => ({ OrganizationProviderDetail: () => null }) ) +vi.mock('@/app/workspace/[workspaceId]/settings/components/settings-empty-state', () => ({ + SettingsEmptyState: () => null, +})) -import OrganizationProviderLayout from '@/app/o/[organizationId]/settings/integrations/providers/[connectorType]/layout' -import OrganizationProviderPage, { - generateMetadata, -} from '@/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page' - -const props = { - params: Promise.resolve({ organizationId: 'org-one', connectorType: 'google_drive' }), -} - -describe('organization provider page authorization', () => { - beforeEach(() => { - vi.clearAllMocks() - mocks.session.mockResolvedValue({ user: { id: 'admin-one' } }) - mocks.authorize.mockResolvedValue(true) - mocks.redirect.mockImplementation(() => { - throw new Error('redirect') - }) - mocks.notFound.mockImplementation(() => { - throw new Error('not found') - }) - }) +import OrganizationProviderPage from '@/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page' - it('checks the target organization integration policy before rendering provider management', async () => { - const page = await OrganizationProviderPage(props) - expect(mocks.authorize).toHaveBeenCalledWith({ - organizationId: 'org-one', - userId: 'admin-one', - section: 'integrations', - }) - expect(page.type).toBe(Suspense) - expect(page.props.children).toMatchObject({ - type: 'provider-detail', - props: { connectorType: 'google_drive' }, - }) - }) +beforeEach(() => { + vi.clearAllMocks() + mocks.session.mockResolvedValue({ user: { id: 'admin-1' } }) + mocks.authorize.mockResolvedValue(true) +}) - it('rejects unknown or unsupported providers before loading protected organization state', async () => { +it.each(['jira', 'confluence'])( + 'moves legacy %s Accounts links to filtered People and preserves the search', + async (connectorType) => { await expect( OrganizationProviderPage({ - params: Promise.resolve({ organizationId: 'org-one', connectorType: 'unknown-provider' }), + params: Promise.resolve({ organizationId: 'org-1', connectorType }), + searchParams: Promise.resolve({ + view: 'accounts', + 'credential-group-people': 'alex+qa@example.com', + }), }) - ).rejects.toThrow('not found') - expect(mocks.session).not.toHaveBeenCalled() - expect(mocks.authorize).not.toHaveBeenCalled() - }) - - it('does not render when the admin or feature gate denies access', async () => { - mocks.authorize.mockResolvedValue(false) - await expect(OrganizationProviderPage(props)).rejects.toThrow('not found') - }) - - it('returns signed-out users to the requested provider after login', async () => { - mocks.session.mockResolvedValue(null) - await expect(OrganizationProviderPage(props)).rejects.toThrow('redirect') - const url = new URL(mocks.redirect.mock.calls[0][0], 'https://example.com') - expect(url.pathname).toBe('/login') - expect(url.searchParams.get('callbackUrl')).toBe( - '/o/org-one/settings/integrations/providers/google_drive' - ) - expect(mocks.authorize).not.toHaveBeenCalled() - }) + ).rejects.toThrow('redirect') + const url = new URL(mocks.redirect.mock.lastCall![0], 'https://example.com') + expect(url.pathname).toBe('/o/org-1/settings/integrations') + expect(url.searchParams.get('tab')).toBe('people') + expect(url.searchParams.get('integration')).toBe(connectorType) + expect(url.searchParams.get('credential-group-people')).toBe('alex+qa@example.com') + expect(url.searchParams.has('view')).toBe(false) + } +) - it('keeps the settings header mounted independently of provider authorization', () => { - const layout = OrganizationProviderLayout({ children: Loading integration }) - expect(layout.type).toBe('header-provider') - expect(layout.props.children).toMatchObject({ - type: 'header-shell', - props: { meta: { title: 'Integration' } }, +it('authorizes organization settings before redirecting a legacy link', async () => { + mocks.authorize.mockResolvedValue(false) + await expect( + OrganizationProviderPage({ + params: Promise.resolve({ organizationId: 'org-1', connectorType: 'jira' }), + searchParams: Promise.resolve({ view: 'accounts' }), }) - expect(mocks.authorize).not.toHaveBeenCalled() - }) - - it('uses the supported provider name as page metadata', async () => { - expect(await generateMetadata(props)).toEqual({ title: 'Google Drive' }) - expect(mocks.session).not.toHaveBeenCalled() - expect(mocks.authorize).not.toHaveBeenCalled() - }) + ).rejects.toThrow('not found') + expect(mocks.redirect).not.toHaveBeenCalled() }) + +it.each(['jira', ''])( + 'preserves an active setup in a legacy Accounts link (%s)', + async (addConnector) => { + await OrganizationProviderPage({ + params: Promise.resolve({ organizationId: 'org-1', connectorType: 'jira' }), + searchParams: Promise.resolve({ view: 'accounts', addConnector, 'source-access': 'members' }), + }) + expect(mocks.redirect).not.toHaveBeenCalled() + } +) diff --git a/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page.tsx b/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page.tsx index 8250da53e98..5f0762a0e49 100644 --- a/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page.tsx +++ b/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/page.tsx @@ -6,11 +6,14 @@ import { organizationRoutes } from '@/lib/navigation/paths' import { authorizeOrganizationSettingsSection } from '@/lib/settings/application/organization-section-access' import { SEARCH_SOURCE_TYPES } from '@/lib/sim-search/connectors' import { buildAuthCrossLink } from '@/app/(auth)/auth-redirect' +import { serializeOrganizationPeople } from '@/app/o/[organizationId]/settings/components/integrations/search-params' import { OrganizationProviderDetail } from '@/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail' +import { searchSetupParam } from '@/app/workspace/[workspaceId]/search/search-params' import { SettingsEmptyState } from '@/app/workspace/[workspaceId]/settings/components/settings-empty-state' interface OrganizationProviderPageProps { params: Promise<{ organizationId: string; connectorType: string }> + searchParams: Promise> } export async function generateMetadata({ @@ -22,7 +25,10 @@ export async function generateMetadata({ } } -export default async function OrganizationProviderPage({ params }: OrganizationProviderPageProps) { +export default async function OrganizationProviderPage({ + params, + searchParams, +}: OrganizationProviderPageProps) { const { organizationId, connectorType } = await params if (!SEARCH_SOURCE_TYPES.some(([type]) => type === connectorType)) notFound() const session = await getSession() @@ -41,6 +47,26 @@ export default async function OrganizationProviderPage({ params }: OrganizationP })) ) notFound() + const query = await searchParams + const activeSetup = + typeof query.addConnector === 'string' + ? searchSetupParam.parser.parse(query.addConnector) + : null + if (query.view === 'accounts' && activeSetup === null) { + redirect( + serializeOrganizationPeople( + organizationRoutes(organizationId).settingsSection('integrations'), + { + tab: 'people', + integration: connectorType, + 'credential-group-people': + typeof query['credential-group-people'] === 'string' + ? query['credential-group-people'] + : null, + } + ) + ) + } return ( Loading integration…} diff --git a/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail.test.tsx b/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail.test.tsx index 7dda89df3ff..594914fb52f 100644 --- a/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail.test.tsx +++ b/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail.test.tsx @@ -116,6 +116,7 @@ vi.mock('@/app/o/[organizationId]/settings/components/integrations/slack-account import { SettingsHeaderProvider, SettingsHeaderShell } from '@/components/settings/settings-header' import { OrganizationProviderDetail } from '@/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail' +import { CONNECTOR_META_REGISTRY } from '@/connectors/registry' const provider = { connectorType: 'google_drive', @@ -221,46 +222,21 @@ describe('organization provider management', () => { } it.each(['gmail', 'google_calendar', 'google_drive'])( - 'lets %s wait for connections without requiring source setup', + 'offers configuration setup directly for %s without an Accounts or Advanced tab', async (connectorType) => { mocks.overview.mockReturnValue({ - data: { - providers: [ - { - connectorType, - approved: true, - status: 'waiting_for_connections', - sourceCount: 0, - issue: null, - isSyncing: false, - }, - ], - }, + data: { providers: [{ ...provider, connectorType, status: 'waiting_for_connections' }] }, }) - mocks.accounts.mockReturnValue({ data: { credentialGroup: null }, isPending: false }) mocks.sources.mockReturnValue({ data: [], isPending: false }) - await render(connectorType, '?view=accounts') + await render(connectorType) expect(container.textContent).toContain('Waiting for connections') expect(container.textContent).toContain( - 'Members connect their accounts from Integrations. Indexing starts automatically.' + `No ${CONNECTOR_META_REGISTRY[connectorType]?.name} connections yet.` ) - expect(container.textContent).not.toContain('Add source') - expect(container.textContent).not.toContain('Add sync configuration') - expect(container.querySelector('a[href="/o/org-one/integrations"]')).toBeNull() - expect(container.textContent).not.toContain('Open Integrations') - expect(mocks.sources).toHaveBeenCalledWith( - expect.any(Object), - expect.objectContaining({ enabled: false }) - ) - await click('Advanced') - expect(container.textContent).toContain('No sync configurations yet.') - expect(container.textContent).toContain('Add sync configuration') - await click('Add sync configuration') + expect(container.querySelector('[role="radio"]')).toBeNull() + await click('Connect service account') await vi.waitFor(() => { - expect(mocks.updateUrl).toHaveBeenLastCalledWith( - expect.objectContaining({ searchParams: expect.any(URLSearchParams) }) - ) - expect(mocks.updateUrl.mock.calls.at(-1)![0].searchParams.get('addConnector')).toBe( + expect(mocks.updateUrl.mock.calls.at(-1)?.[0].searchParams.get('addConnector')).toBe( connectorType ) }) @@ -284,7 +260,7 @@ describe('organization provider management', () => { expect(container.textContent).not.toContain( 'Members connect their accounts from Integrations.' ) - await click('Add sync configuration') + await click('Connect service account') await vi.waitFor(() => { const params = mocks.updateUrl.mock.calls.at(-1)![0].searchParams expect(params.get('addConnector')).toBe(connectorType) @@ -320,29 +296,17 @@ describe('organization provider management', () => { ])('opens configurations for the $name setup', async ({ modes }) => { withSources(modes) await render(connectorType) - expect(container.querySelector('[role="radio"][aria-checked="true"]')).toHaveTextContent( - 'Advanced' - ) + expect(container.querySelector('[role="radio"]')).toBeNull() expect(mocks.sources).toHaveBeenLastCalledWith( expect.any(Object), expect.objectContaining({ enabled: true }) ) expect(mocks.accounts).toHaveBeenLastCalledWith(undefined) - expect(container.textContent).toContain('Add sync configuration') + expect(container.textContent).toContain('Connect service account') if (modes.length === 0) - expect(container.textContent).toContain('No sync configurations yet.') - }) - - it.each(['accounts', 'sources'])('honors explicit %s links', async (view) => { - withSources(['admin']) - await render(connectorType, `?view=${view}`) - expect(mocks.sources).toHaveBeenLastCalledWith( - expect.any(Object), - expect.objectContaining({ enabled: view === 'sources' }) - ) - expect(container.querySelector('[role="radio"][aria-checked="true"]')).toHaveTextContent( - view === 'accounts' ? 'Accounts' : 'Advanced' - ) + expect(container.textContent).toContain( + `No ${CONNECTOR_META_REGISTRY[connectorType]?.name} connections yet.` + ) }) it('loads the configuration list in parallel with its overview and retains the default', async () => { @@ -357,9 +321,7 @@ describe('organization provider management', () => { ) withSources(['members']) await render(connectorType) - expect(container.querySelector('[role="radio"][aria-checked="true"]')).toHaveTextContent( - 'Advanced' - ) + expect(container.querySelector('[role="radio"]')).toBeNull() expect(container.textContent).toContain('Engineering handbook') expect(mocks.sources).toHaveBeenLastCalledWith( expect.any(Object), @@ -367,43 +329,6 @@ describe('organization provider management', () => { ) expect(mocks.accounts).toHaveBeenLastCalledWith(undefined) }) - - it('preserves an explicit Accounts choice when the overview changes', async () => { - withSources(['members']) - await render(connectorType) - await click('Accounts') - await vi.waitFor(() => - expect(mocks.updateUrl.mock.calls.at(-1)?.[0].searchParams.get('view')).toBe('accounts') - ) - withSources(['admin']) - await render(connectorType) - expect(container.querySelector('[role="radio"][aria-checked="true"]')).toHaveTextContent( - 'Accounts' - ) - expect(mocks.sources).toHaveBeenLastCalledWith( - expect.any(Object), - expect.objectContaining({ enabled: false }) - ) - }) - - it.each([ - { accessMode: 'admin', method: 'Service account' }, - { accessMode: 'members', method: 'Member accounts' }, - ])( - 'identifies $method configurations without changing their title or destination', - async ({ accessMode, method }) => { - withSources([accessMode]) - mocks.sources.mockReturnValue({ - data: [{ ...source, connectorType, accessMode }], - isPending: false, - }) - await render(connectorType) - expect(container.textContent).toContain(`${method} · Last synced`) - expect( - container.querySelector('a[aria-label="Open Engineering handbook"]') - ).toHaveAttribute('href', '/o/org-one/settings/integrations/sources/source-one') - } - ) } ) @@ -412,7 +337,15 @@ describe('organization provider management', () => { async (status) => { withSlackAccounts(true, status) await render('slack') - await click('Remove account setup') + const headerRemove = Array.from(container.querySelectorAll('button')).find( + (button) => button.textContent === 'Remove app setup' + ) + const deactivate = Array.from(container.querySelectorAll('button')).find( + (button) => button.textContent === 'Deactivate' + ) + expect(headerRemove?.className).toBe(deactivate?.className) + expect(headerRemove?.querySelector('[class*="text-error"]')).toBeNull() + await click('Remove app setup') expect(mocks.removeAccounts).not.toHaveBeenCalled() expect(document.querySelector('[role="dialog"]')).toHaveTextContent('saved app configuration') await click('Remove') @@ -434,7 +367,7 @@ describe('organization provider management', () => { it('offers removal when Slack is deactivated and allows cancelling without a mutation', async () => { withSlackAccounts(false) await render('slack') - await click('Remove account setup') + await click('Remove app setup') await click('Cancel') expect(document.querySelector('[role="dialog"]')).toBeNull() expect(mocks.removeAccounts).not.toHaveBeenCalled() @@ -444,32 +377,19 @@ describe('organization provider management', () => { withSlackAccounts() mocks.accountRemovalError = new Error('Remove the source using these accounts first.') await render('slack') - await click('Remove account setup') + await click('Remove app setup') await click('Remove') expect(document.querySelector('[role="dialog"] [role="alert"]')).toHaveTextContent( 'Remove the source using these accounts first.' ) }) - it('passes the removal action to the Slack Accounts tab header', async () => { - withSlackAccounts() - await render('slack', '?view=accounts') - const actions = mocks.people.mock.calls.at(-1)![0].panel.actions - expect(actions).toEqual([ - expect.objectContaining({ text: 'Remove account setup', onSelect: expect.any(Function) }), - ]) - await act(async () => actions[0].onSelect()) - expect(document.querySelector('[role="dialog"]')).toHaveTextContent( - 'Remove Slack account setup?' - ) - }) - it('keeps Slack cleanup available even when personal source creation is unavailable', async () => { withSlackAccounts() mocks.personal = false await render('slack') expect(mocks.accounts).toHaveBeenCalledWith('org-one') - await click('Remove account setup') + await click('Remove app setup') expect(document.querySelector('[role="dialog"]')).not.toBeNull() }) @@ -538,14 +458,12 @@ describe('organization provider management', () => { expect(container.textContent).not.toContain('Activate this integration') expect(mocks.people).not.toHaveBeenCalled() expect( - container.querySelector( - `input[placeholder="${params === '?view=accounts' ? 'Search people...' : 'Search sync configurations...'}"]` - ) + container.querySelector('input[placeholder="Search Google Drive connections..."]') ).toBeEnabled() } ) - it('hides cached account content and retries when overview access is revoked', async () => { + it('hides cached source content and retries when overview access is revoked', async () => { const refetch = vi.fn() mocks.overview.mockReturnValue({ data: { providers: [provider] }, @@ -553,21 +471,29 @@ describe('organization provider management', () => { error: new ApiClientError({ status: 403, message: 'Access denied', body: null }), refetch, }) - await render('google_drive', '?view=accounts&credential-group-people=alex') + await render('google_drive', '?search=alex') expect(container.textContent).toContain('Access denied') expect(mocks.people).not.toHaveBeenCalled() - expect(container.querySelector('input[placeholder="Search people..."]')).toHaveValue('alex') - expect(container.querySelector('input[placeholder="Search people..."]')).toBeEnabled() + expect( + container.querySelector('input[placeholder="Search Google Drive connections..."]') + ).toHaveValue('alex') + expect( + container.querySelector('input[placeholder="Search Google Drive connections..."]') + ).toBeEnabled() await click('Try again') expect(refetch).toHaveBeenCalledOnce() }) - it('offers activation from the accounts tab when an existing provider is deactivated', async () => { + it('offers activation when an existing provider is deactivated', async () => { mocks.overview.mockReturnValue({ data: { providers: [{ ...provider, approved: false }] } }) - await render('google_drive', '?view=accounts&credential-group-people=alex') + await render('google_drive', '?search=alex') expect(mocks.people).not.toHaveBeenCalled() - expect(container.querySelector('input[placeholder="Search people..."]')).toHaveValue('alex') - expect(container.querySelector('input[placeholder="Search people..."]')).toBeEnabled() + expect( + container.querySelector('input[placeholder="Search Google Drive connections..."]') + ).toHaveValue('alex') + expect( + container.querySelector('input[placeholder="Search Google Drive connections..."]') + ).toBeEnabled() await click('Activate') expect(mocks.activate).toHaveBeenCalledWith({ organizationId: 'org-one', @@ -576,7 +502,7 @@ describe('organization provider management', () => { }) }) - it('shows activation failures on Accounts and keeps activation available for retry', async () => { + it('shows activation failures and keeps activation available for retry', async () => { mocks.overview.mockReturnValue({ data: { providers: [{ ...provider, approved: false }] } }) mocks.approvalError = new Error('Activation could not be saved') await render('google_drive', '?view=accounts') @@ -590,56 +516,6 @@ describe('organization provider management', () => { }) }) - it.each([ - ['loading', 'Loading accounts…'], - ['error', 'Accounts unavailable'], - [ - 'missing group', - 'Members connect their accounts from Integrations. Indexing starts automatically.', - ], - [ - 'missing provider option', - 'Members connect their accounts from Integrations. Indexing starts automatically.', - ], - ])('preserves Accounts search while %s', async (state, message) => { - const refetch = vi.fn() - mocks.accounts.mockReturnValue( - state === 'loading' - ? { isPending: true } - : state === 'error' - ? { isError: true, error: new Error(message), refetch } - : { - data: { - credentialGroup: - state === 'missing group' ? null : { ...credentialGroup, options: [] }, - }, - isPending: false, - } - ) - await render('google_drive', '?view=accounts&credential-group-people=alex&search=handbook') - - expect(container.textContent).toContain(message) - expect(container.querySelector('input[placeholder="Search people..."]')).toHaveValue('alex') - expect(container.querySelector('input[placeholder="Search people..."]')).toBeEnabled() - expect(container.querySelector('input[placeholder="Search sync configurations..."]')).toBeNull() - expect(mocks.people).not.toHaveBeenCalled() - if (state === 'error') { - await click('Try again') - expect(refetch).toHaveBeenCalledOnce() - } - - const sourcesTab = Array.from( - container.querySelectorAll('[role="radio"]') - ).find((item) => item.textContent === 'Advanced') - expect(sourcesTab).toBeDefined() - await act(async () => sourcesTab!.click()) - expect( - container.querySelector('input[placeholder="Search sync configurations..."]') - ).toHaveValue('handbook') - await click('Accounts') - expect(container.querySelector('input[placeholder="Search people..."]')).toHaveValue('alex') - }) - it('preserves source navigation and retries connection availability failures', async () => { mocks.availabilityError = new Error('Connection availability could not be loaded') await render('google_drive', '?view=sources') @@ -655,6 +531,19 @@ describe('organization provider management', () => { expect(mocks.activate).not.toHaveBeenCalled() }) + it('explains unavailable integrations instead of showing an empty setup dead end', async () => { + mocks.access = { admin: false, members: false } + mocks.overview.mockReturnValue({ + data: { providers: [{ ...provider, connectorType: 'gitlab' }] }, + }) + mocks.sources.mockReturnValue({ data: [], isPending: false }) + await render('gitlab') + expect(container.textContent).toContain('Unavailable in this deployment') + expect(container.textContent).toContain('GitLab must be configured for this deployment') + expect(container.textContent).not.toContain('No GitLab projects added') + expect(container.textContent).not.toContain('Add project') + }) + it('explains and retries Slack account lookup failures without hiding its sources', async () => { const refetch = vi.fn() mocks.access = { admin: false, members: true } @@ -677,20 +566,6 @@ describe('organization provider management', () => { expect(refetch).toHaveBeenCalledOnce() }) - it('scopes account management and connection requests to the current provider option', async () => { - await render('google_drive', '?view=accounts') - expect(mocks.sources).toHaveBeenCalledWith( - expect.any(Object), - expect.objectContaining({ enabled: false }) - ) - expect(mocks.people).toHaveBeenCalledWith( - expect.objectContaining({ - organizationId: 'org-one', - searchConnection: { optionId: 'google-option', providerName: 'Google Drive' }, - }) - ) - }) - it.each([ { type: 'google_drive', access: { admin: true, members: true }, memberParam: false }, { type: 'gmail', access: { admin: false, members: true }, memberParam: true }, @@ -702,8 +577,7 @@ describe('organization provider management', () => { data: { providers: [{ ...provider, connectorType: type }] }, }) await render(type) - await click('Advanced') - await click('Add sync configuration') + await click(memberParam ? 'Set up member accounts' : 'Connect service account') await vi.waitFor(() => { expect(mocks.updateUrl).toHaveBeenCalled() const query = new URLSearchParams(mocks.updateUrl.mock.calls.at(-1)![0].queryString) @@ -740,7 +614,7 @@ describe('organization provider management', () => { slackBotCredentialId: 'slack-bot', configurationStatus: 'needs_update', }, - ])('offers Slack Accounts recovery for an active option with $name', async (option) => { + ])('offers Slack app recovery for an active option with $name', async (option) => { mocks.access = { admin: false, members: true } mocks.overview.mockReturnValue({ data: { providers: [{ ...provider, connectorType: 'slack' }] }, @@ -762,24 +636,21 @@ describe('organization provider management', () => { }, isPending: false, }) - await render('slack', '?view=accounts&credential-group-people=alex') + await render('slack') expect(mocks.people).not.toHaveBeenCalled() - expect(container.textContent).toContain('Set up the Slack app to connect accounts.') - expect(container.querySelector('input[placeholder="Search people..."]')).toHaveValue('alex') + expect(container.textContent).toContain('Set up Slack app') await click('Set up Slack app') await act(async () => { await vi.waitFor(() => expect(mocks.updateUrl).toHaveBeenCalled()) }) const query = new URLSearchParams(mocks.updateUrl.mock.calls.at(-1)![0].queryString) expect(query.get('connectedAccounts')).toBe('slack') - expect(query.get('view')).toBe('accounts') - expect(query.get('credential-group-people')).toBe('alex') expect(query.has('addConnector')).toBe(false) }) it.each([undefined, 'slack-bot'])( - 'uses verified configuration for account management with bot credential %s', + 'allows source setup with verified Slack configuration and bot credential %s', async (slackBotCredentialId) => { mocks.access = { admin: false, members: true } mocks.overview.mockReturnValue({ @@ -804,11 +675,8 @@ describe('organization provider management', () => { }) await render('slack', '?view=accounts') - expect(mocks.people).toHaveBeenCalledWith( - expect.objectContaining({ - searchConnection: { optionId: 'slack-option', providerName: 'Slack' }, - }) - ) + expect(container.textContent).toContain('Add channels or DMs') + expect(mocks.people).not.toHaveBeenCalled() expect(container.textContent).not.toContain('Set up the Slack app to connect accounts.') } ) diff --git a/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail.tsx b/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail.tsx index cbf18f2f4e0..05b2e177c68 100644 --- a/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail.tsx +++ b/apps/sim/app/o/[organizationId]/settings/integrations/providers/[connectorType]/provider-detail.tsx @@ -1,28 +1,20 @@ 'use client' import { useState } from 'react' -import { ChipConfirmModal, ChipModalError, ChipSwitch } from '@sim/emcn' +import { ChipConfirmModal, ChipModalError } from '@sim/emcn' import { ArrowLeft, Plus } from '@sim/emcn/icons' import { format } from 'date-fns' import { useRouter } from 'next/navigation' import { useQueryState, useQueryStates } from 'nuqs' import type { SettingsAction } from '@/components/settings/settings-header' import { SettingsPanel } from '@/components/settings/settings-panel' -import { findCredentialGroupProviderFromProviderId } from '@/lib/credential-groups/providers' import { organizationRoutes } from '@/lib/navigation/paths' -import { getServiceConfigByProviderId, getServiceConfigByServiceId } from '@/lib/oauth' -import { - canConnectPersonally, - canConnectWithDefaults, - getConnectorAccessAvailability, -} from '@/lib/sim-search/connectors' +import { getSearchConnectionLabels } from '@/lib/sim-search/connection-labels' +import { getConnectorAccessAvailability } from '@/lib/sim-search/connectors' import { SEARCH_DEBOUNCE_MS } from '@/lib/url-state' import { useOrganizationContext } from '@/app/o/[organizationId]/providers/organization-provider' import { organizationSearchStatusLabel } from '@/app/o/[organizationId]/settings/components/integrations/organization-search-status' -import { - connectedAccountsParam, - organizationProviderTabParam, -} from '@/app/o/[organizationId]/settings/components/integrations/search-params' +import { connectedAccountsParam } from '@/app/o/[organizationId]/settings/components/integrations/search-params' import { OrganizationSlackAccountRemoval } from '@/app/o/[organizationId]/settings/components/integrations/slack-account-removal' import { OrganizationSlackAccountSetup } from '@/app/o/[organizationId]/settings/components/integrations/slack-account-setup' import { SearchSourcePagination } from '@/app/workspace/[workspaceId]/search/components/search-source-pagination' @@ -41,12 +33,10 @@ import { } from '@/app/workspace/[workspaceId]/settings/components/settings-resource-row' import { useSettingsSearch } from '@/app/workspace/[workspaceId]/settings/components/use-settings-search' import { CONNECTOR_META_REGISTRY } from '@/connectors/registry' -import { OrganizationAccountPeople } from '@/ee/credential-groups/components/organization-account-people' import { useOrganizationSearchOverview, useSearchSources } from '@/hooks/queries/kb/connectors' import { useOrganizationAccounts } from '@/hooks/queries/organization-accounts' import { useUpdateSearchIntegration } from '@/hooks/queries/search-integrations' import { useDebounce } from '@/hooks/use-debounce' -import { useOrganizationAccountPeopleSearch } from '@/hooks/use-organization-account-people-search' import { usePermissionConfig } from '@/hooks/use-permission-config' interface OrganizationProviderDetailProps { @@ -57,31 +47,21 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid const { organization, viewer, searchAccess } = useOrganizationContext() const router = useRouter() const meta = CONNECTOR_META_REGISTRY[connectorType] - const automaticSetup = Boolean(meta && canConnectWithDefaults(meta) && searchAccess.memberScoped) - const [view, setView] = useQueryState( - organizationProviderTabParam.key, - organizationProviderTabParam.parser - ) const [search, setSearch] = useSettingsSearch() - const [peopleSearch, setPeopleSearch] = useOrganizationAccountPeopleSearch() const sourceSearch = useDebounce(search.trim(), SEARCH_DEBOUNCE_MS) const [deactivating, setDeactivating] = useState(false) const [removingSlackAccounts, setRemovingSlackAccounts] = useState(false) const scope = { kind: 'organization', organizationId: organization.id } as const - const personal = Boolean(meta && canConnectPersonally(meta) && searchAccess.memberScoped) - const showAccounts = view === 'accounts' && personal const overview = useOrganizationSearchOverview(organization.id, { enabled: viewer.isAdmin }) const sources = useSearchSources(scope, { connectorType, search: sourceSearch, - enabled: viewer.isAdmin && !showAccounts, + enabled: viewer.isAdmin, }) const availability = usePermissionConfig() const approval = useUpdateSearchIntegration() const accounts = useOrganizationAccounts( - viewer.isAdmin && (connectorType === 'slack' || (personal && showAccounts)) - ? organization.id - : undefined + viewer.isAdmin && connectorType === 'slack' ? organization.id : undefined ) const [, setSetup] = useQueryStates( { @@ -103,19 +83,11 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid router.push(organizationRoutes(organization.id).settingsSection('integrations')), } if (!viewer.isAdmin || !meta) return null - const searchField = showAccounts - ? { value: peopleSearch, onChange: setPeopleSearch, placeholder: 'Search people...' } - : { - value: search, - onChange: setSearch, - placeholder: automaticSetup ? 'Search sync configurations...' : 'Search sources...', - } - const panel = { - back, - title: meta.name, - description: provider ? organizationSearchStatusLabel(provider) : undefined, - docsLink: meta.searchDocsUrl, - search: searchField, + const labels = getSearchConnectionLabels(connectorType) + const searchField = { + value: search, + onChange: setSearch, + placeholder: labels.searchPlaceholder, } const access = getConnectorAccessAvailability(meta, availability.integrationAvailability, { memberAccessAvailable: searchAccess.memberScoped, @@ -123,16 +95,22 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid oauthServiceAvailability: availability.oauthServiceAvailability, isIntegrationAvailabilityReady: availability.isIntegrationAvailabilityReady, }) - const service = - meta.auth.mode === 'oauth' - ? (getServiceConfigByServiceId(meta.auth.provider) ?? - getServiceConfigByProviderId(meta.auth.provider)) - : undefined - const credentialProvider = service - ? findCredentialGroupProviderFromProviderId(service.providerId) - : undefined + const unavailable = + availability.isIntegrationAvailabilityReady && !access.admin && !access.members + const panel = { + back, + title: meta.name, + description: + approved && unavailable + ? 'Unavailable in this deployment' + : provider + ? organizationSearchStatusLabel(provider) + : undefined, + docsLink: meta.searchDocsUrl, + search: searchField, + } const option = accounts.data?.credentialGroup?.options.find( - (item) => item.provider === credentialProvider && item.status === 'active' + (item) => item.provider === 'slack' && item.status === 'active' ) const group = accounts.data?.credentialGroup const removalActions: SettingsAction[] = @@ -141,8 +119,8 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid group?.options.some((item) => item.provider === 'slack') ? [ { - text: 'Remove account setup', - textTone: 'error', + id: 'delete', + text: 'Remove app setup', disabled: accounts.isFetching, onSelect: () => setRemovingSlackAccounts(true), }, @@ -165,14 +143,13 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid approval.mutate({ organizationId: organization.id, connectorType, approved: true }) const actions: SettingsAction[] = approved ? [ - ...((access.admin || access.members) && (!automaticSetup || !showAccounts) + ...(access.admin || access.members ? [ { text: needsSlackSetup ? 'Set up Slack app' - : automaticSetup - ? 'Add sync configuration' - : 'Add source', + : getSearchConnectionLabels(connectorType, access.admin ? 'admin' : 'members') + .add, icon: Plus, variant: 'primary' as const, disabled: @@ -196,6 +173,7 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid text: provider ? 'Activate' : 'Add integration', variant: 'primary', disabled: pending || (!access.admin && !access.members), + tooltip: unavailable ? 'This integration is unavailable in this deployment.' : undefined, onSelect: activate, }, ] @@ -247,13 +225,13 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid {sources.isError && !sources.isFetchNextPageError ? ( void sources.refetch()} variant='inline' /> ) : sources.isPending ? ( - Loading sources… + Loading connections… ) : (
{sources.data?.map((source) => ( @@ -291,12 +269,12 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid {!sources.data?.length && !sources.hasNextPage && ( {sourceSearch - ? 'No matching sources' - : !approved - ? 'Activate this integration to set up sources.' - : automaticSetup - ? 'No sync configurations yet.' - : 'No sources yet.'} + ? 'No matching connections' + : unavailable + ? `${meta.name} must be configured for this deployment before you can add a connection.` + : !approved + ? 'Activate this integration to add a connection.' + : labels.empty} )} @@ -306,81 +284,7 @@ export function OrganizationProviderDetail({ connectorType }: OrganizationProvid ) return ( <> -
- {personal && ( -
- void setView(value)} - options={ - automaticSetup - ? [ - { value: 'accounts', label: 'Accounts' }, - { value: 'sources', label: 'Advanced' }, - ] - : [ - { value: 'sources', label: 'Sources' }, - { value: 'accounts', label: 'Accounts' }, - ] - } - /> -
- )} - {showAccounts ? ( - accounts.isError ? ( - - void accounts.refetch()} - variant='inline' - /> - - ) : accounts.isPending ? ( - - Loading accounts… - - ) : option && approved && !needsSlackSetup ? ( - - ) : ( - - {approval.error && ( - - {approval.error.message} - - )} - {availability.integrationAvailabilityError && ( - void availability.refetchIntegrationAvailability()} - variant='inline' - /> - )} - - {approved - ? needsSlackSetup - ? 'Set up the Slack app to connect accounts.' - : automaticSetup - ? provider && provider.sourceCount > 0 - ? 'No connected member accounts.' - : 'Members connect their accounts from Integrations. Indexing starts automatically.' - : 'Add a source to set up account connections.' - : 'Activate this integration to set up account connections.'} - - - ) - ) : ( - renderSources() - )} -
+ {renderSources()} { ) }) - it.each(['members', 'admin'] as const)( - 'links member sources to personal Search connections: %s', - async (accessMode) => { - mocks.detail.mockReturnValue({ data: { ...connector, accessMode } }) - await render() - const link = container.querySelector('a[aria-label="Manage your Search accounts"]') - if (accessMode === 'members') { - expect(link).toHaveAttribute('href', '/o/org-one/integrations') - expect(container.textContent).toContain( - 'Each person connects from Integrations to sync content they can access.' - ) - } else { - expect(link).toBeNull() - } - } - ) it('restores document search and status from the shared URL', async () => { await render('?search=notes&document-filter=excluded') expect(mocks.documents).toHaveBeenLastCalledWith( @@ -239,8 +223,10 @@ describe('organization source detail navigation', () => { }) await render(searchParams) - expect(container.textContent).toContain('Some source updates are incomplete') - expect(container.textContent).toContain('Review the source settings and try syncing again.') + expect(container.textContent).toContain('Some connection updates are incomplete') + expect(container.textContent).toContain( + 'Review the connection settings and try syncing again.' + ) expect(container.textContent).not.toContain('Provider denied') expect(container.textContent).not.toContain('org-private-id') } @@ -248,8 +234,10 @@ describe('organization source detail navigation', () => { it('keeps a healthy active source quiet', async () => { await render() - expect(container.textContent).not.toContain('Some source updates are incomplete') - expect(container.textContent).not.toContain('Review the source settings and try syncing again.') + expect(container.textContent).not.toContain('Some connection updates are incomplete') + expect(container.textContent).not.toContain( + 'Review the connection settings and try syncing again.' + ) }) it.each(['', '?view=settings', '?view=history'])( @@ -293,7 +281,7 @@ describe('organization source detail navigation', () => { async (status) => { mocks.detail.mockReturnValue({ data: { ...connector, status, lastSyncError: 'Old failure' } }) await render() - expect(container.textContent).not.toContain('Some source updates are incomplete') + expect(container.textContent).not.toContain('Some connection updates are incomplete') } ) @@ -319,7 +307,9 @@ describe('organization source detail navigation', () => { }, }) await render() - expect(container.textContent?.includes('Some source updates are incomplete')).toBe(showNotice) + expect(container.textContent?.includes('Some connection updates are incomplete')).toBe( + showNotice + ) expect(container.textContent).not.toContain('private-account-id') } ) @@ -351,7 +341,7 @@ describe('organization source detail navigation', () => { await render() expect(mocks.actions).not.toHaveBeenCalled() expect(mocks.documents).not.toHaveBeenCalled() - expect(container.textContent).toContain('Loading source') + expect(container.textContent).toContain('Loading connection') }) it('does not load protected source data for non-admins', async () => { mocks.admin = false @@ -368,7 +358,7 @@ describe('organization source detail navigation', () => { mocks.index.mockReturnValue({ data: { knowledgeBaseId: null }, isPending: false }) mocks.detail.mockReturnValue({}) await render() - expect(container.textContent).toContain('This source is no longer available') + expect(container.textContent).toContain('This connection is no longer available') expect(mocks.actions).not.toHaveBeenCalled() await click('Sources') expect(mocks.push).toHaveBeenCalledWith('/o/org-one/settings/integrations') @@ -402,7 +392,7 @@ describe('organization source detail navigation', () => { const sync = Array.from(container.querySelectorAll('button')).find( (item) => item.textContent === 'Sync now' ) - const tabs = container.querySelector('[aria-label="Source views"]') + const tabs = container.querySelector('[aria-label="Connection views"]') expect(sync).toBeTruthy() expect(tabs).toBeTruthy() expect(sync!.compareDocumentPosition(tabs!)).toBe(Node.DOCUMENT_POSITION_FOLLOWING) diff --git a/apps/sim/app/o/[organizationId]/settings/integrations/sources/[connectorId]/source-detail.tsx b/apps/sim/app/o/[organizationId]/settings/integrations/sources/[connectorId]/source-detail.tsx index 1439c907041..939dfd52563 100644 --- a/apps/sim/app/o/[organizationId]/settings/integrations/sources/[connectorId]/source-detail.tsx +++ b/apps/sim/app/o/[organizationId]/settings/integrations/sources/[connectorId]/source-detail.tsx @@ -70,7 +70,7 @@ export function OrganizationSourceDetail({ connectorId }: OrganizationSourceDeta if (!viewer.isAdmin) return ( - + Only organization admins can manage sources. @@ -89,17 +89,17 @@ export function OrganizationSourceDetail({ connectorId }: OrganizationSourceDeta ) if (failedQuery && (!hasCanonicalDetail || accessFailure)) return ( - + {isApiClientError(failedQuery.error) && failedQuery.error.status === 404 ? ( - This source is no longer available. + This connection is no longer available. ) : ( void failedQuery.refetch()} - fallback='Could not load source' + fallback='Could not load connection' variant='inline' /> )} @@ -107,9 +107,9 @@ export function OrganizationSourceDetail({ connectorId }: OrganizationSourceDeta ) if (!index.isPending && !knowledgeBaseId) return ( - + - This source is no longer available. + This connection is no longer available. ) @@ -120,8 +120,8 @@ export function OrganizationSourceDetail({ connectorId }: OrganizationSourceDeta detail.data.knowledgeBaseId !== knowledgeBaseId ) return ( - - Loading source… + + Loading connection… ) return ( @@ -137,7 +137,7 @@ export function OrganizationSourceDetail({ connectorId }: OrganizationSourceDeta error={failedQuery.error} isRetrying={failedQuery.isFetching} onRetry={() => void failedQuery.refetch()} - fallback='Could not refresh source' + fallback='Could not refresh connection' variant='inline' /> ) : undefined @@ -184,7 +184,7 @@ function SourceDetailContent({ const meta = CONNECTOR_META_REGISTRY[connector.connectorType] const title = meta ? describeSearchSource(meta, connector.sourceConfig) || meta.name - : 'Search source' + : 'Connection' const { effectiveStatus, lastSyncError } = getConnectorSyncState(connector) const status = effectiveStatus === 'paused' @@ -209,7 +209,7 @@ function SourceDetailContent({ return ( )} - {connector.accessMode === 'members' && ( - - )} ) if (view === 'settings') @@ -279,8 +270,8 @@ function SourceDetailContent({ {effectiveStatus === 'active' && lastSyncError && ( )}
) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/search-integration-connection.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/search-integration-connection.tsx index e1df655f9ce..5428ce8551d 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/search-integration-connection.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/search-integration-connection.tsx @@ -53,7 +53,8 @@ function SearchIntegrationConnectionControl({ }) const name = connector?.meta.name ?? target.provider const action = target.credentialId ? 'Reconnect' : 'Connect' - const label = connection.connected + const connected = connection.connected + const label = connected ? `Connected ${name}` : connection.isLoading ? `Checking ${name} connections…` @@ -76,18 +77,14 @@ function SearchIntegrationConnectionControl({ !connector || connection.isLoading || connection.isStarting || - connection.connected || + connected || (!connection.available && !connection.pending) } onClick={handleConnect} leading={ connector && } - trailing={ - connection.connected ? ( - - ) : undefined - } + trailing={connected ? : undefined} /> {connection.pending && Cancel} {connection.error && ( @@ -100,6 +97,8 @@ function SearchIntegrationConnectionControl({ )} {setupOpen && connector && ( setSetupOpen(false)} isPending={connection.isStarting} diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal.test.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal.test.tsx new file mode 100644 index 00000000000..44e7fe18616 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal.test.tsx @@ -0,0 +1,172 @@ +/** @vitest-environment jsdom */ +import { act } from 'react' +import { createRoot, type Root } from 'react-dom/client' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type { PersonalSourceSetupAccounts } from '@/lib/api/contracts/knowledge/personal-source-setup' +import type { ConnectorConfigField } from '@/connectors/types' + +const m = vi.hoisted(() => ({ + connect: vi.fn(), + authorize: vi.fn(), + close: vi.fn(), + complete: vi.fn(), + accounts: [] as PersonalSourceSetupAccounts['accounts'], + pending: false, +})) +vi.mock('@/hooks/use-personal-source-account', () => ({ + usePersonalSourceAccount: () => ({ + accounts: { + data: { accounts: m.accounts, completedCredentialId: null }, + isPending: false, + isError: false, + }, + connect: m.authorize, + cancel: vi.fn(), + pending: m.pending, + }), +})) +vi.mock('@/hooks/queries/personal-source-setup', () => ({ + useConnectPersonalSourceSetup: () => ({ mutateAsync: m.connect, isPending: false }), +})) +vi.mock( + '@/app/workspace/[workspaceId]/knowledge/[id]/components/connector-selector-field/connector-selector-field', + () => ({ + ConnectorSelectorField: (props: { + field: ConnectorConfigField + value: string[] + onChange: (value: string[]) => void + credentialId: string + selectorSurface: { kind: string } + }) => ( + + ), + }) +) + +import { SEARCH_CONNECTORS } from '@/lib/sim-search/connectors' +import { AtlassianSourceSetupModal } from '@/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal' + +let root: Root +let container: HTMLDivElement +function button(label: string) { + const found = Array.from(document.querySelectorAll('button')).find( + (node) => node.textContent?.trim() === label + ) + if (!found) throw new Error(`Missing button: ${label}`) + return found +} +function input(placeholder: string) { + const found = document.querySelector(`input[placeholder="${placeholder}"]`) + if (!found) throw new Error(`Missing input: ${placeholder}`) + return found +} +function fill(field: HTMLInputElement, value: string) { + act(() => { + Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')!.set!.call(field, value) + field.dispatchEvent(new Event('input', { bubbles: true })) + }) +} +function render(type: 'jira' | 'confluence' = 'jira') { + const connector = SEARCH_CONNECTORS.find((item) => item.type === type)! + act(() => + root.render( + + ) + ) +} +beforeEach(() => { + vi.clearAllMocks() + m.accounts = [] + m.pending = false + m.connect.mockResolvedValue({ + kind: 'connected', + connectorId: 'source-1', + knowledgeBaseId: 'kb-1', + }) + ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true + vi.stubGlobal( + 'ResizeObserver', + class { + observe() {} + unobserve() {} + disconnect() {} + } + ) + container = document.createElement('div') + document.body.appendChild(container) + root = createRoot(container) +}) +afterEach(() => { + act(() => root.unmount()) + container.remove() + vi.unstubAllGlobals() +}) +describe('Atlassian personal source setup', () => { + it('starts with account authorization and hides content fields until an account exists', () => { + render() + expect(document.querySelector('[data-testid="picker"]')).toBeNull() + expect(button('Connect & Sync')).toBeDisabled() + act(() => button('Connect account').click()) + expect(m.authorize).toHaveBeenCalledOnce() + expect(m.connect).not.toHaveBeenCalled() + }) + it.each(['jira', 'confluence'] as const)( + 'reuses an account and preserves selected %s keys through manual mode and submission', + async (type) => { + m.accounts = [ + { id: 'my-account', name: 'My account', provider: type, type: 'managed_oauth', scopes: [] }, + ] + render(type) + fill(input('yoursite.atlassian.net'), 'team.atlassian.net') + const picker = document.querySelector('[data-testid="picker"]')! + expect(picker.dataset.credential).toBe('my-account') + expect(picker.dataset.surface).toBe('personal-search-setup') + act(() => picker.click()) + act(() => button('Enter keys manually').click()) + const manual = document.querySelector( + `input[aria-label="${type === 'jira' ? 'Project Keys' : 'Space Keys'}"]` + )! + expect(manual.value).toBe('ENG, SUPPORT') + fill(manual, 'ENG, PRODUCT') + act(() => button(`Choose ${type === 'jira' ? 'projects' : 'spaces'} from list`).click()) + expect(document.querySelector('[data-testid="picker"]')?.textContent).toBe('ENG,PRODUCT') + await act(async () => button('Connect & Sync').click()) + expect(m.connect).toHaveBeenCalledWith({ + action: 'connect', + organizationId: 'org-1', + connectorType: type, + credentialId: 'my-account', + domain: 'team.atlassian.net', + keys: ['ENG', 'PRODUCT'], + }) + expect(m.authorize).not.toHaveBeenCalled() + expect(m.complete).toHaveBeenCalledWith({ + connectorId: 'source-1', + credentialId: 'my-account', + }) + } + ) + it('clears the selection when the site changes', () => { + m.accounts = [ + { id: 'my-account', name: 'My account', provider: 'jira', type: 'managed_oauth', scopes: [] }, + ] + render() + fill(input('yoursite.atlassian.net'), 'team.atlassian.net') + act(() => document.querySelector('[data-testid="picker"]')!.click()) + fill(input('yoursite.atlassian.net'), 'other.atlassian.net') + expect(button('Connect & Sync')).toBeDisabled() + }) +}) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal.tsx new file mode 100644 index 00000000000..4b60deaa7cb --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal.tsx @@ -0,0 +1,241 @@ +'use client' + +import { useState } from 'react' +import { + Chip, + ChipCombobox, + ChipInput, + ChipModal, + ChipModalBody, + ChipModalField, + ChipModalFooter, + ChipModalHeader, + toast, +} from '@sim/emcn' +import { getErrorMessage } from '@sim/utils/errors' +import type { PersonalSourceSetupQuery } from '@/lib/api/contracts/knowledge/personal-source-setup' +import type { SearchConnector } from '@/lib/sim-search/connectors' +import { MAX_PERSONAL_SOURCE_SETUP_KEYS } from '@/lib/sim-search/personal-source-setup' +import { ConnectorSelectorField } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/connector-selector-field/connector-selector-field' +import { useConnectorConfigFields } from '@/app/workspace/[workspaceId]/knowledge/[id]/hooks/use-connector-config-fields' +import { useConnectPersonalSourceSetup } from '@/hooks/queries/personal-source-setup' +import { usePersonalSourceAccount } from '@/hooks/use-personal-source-account' + +interface AtlassianSourceSetupModalProps { + organizationId: string + connector: SearchConnector + connectorType: PersonalSourceSetupQuery['connectorType'] + onClose: () => void + onConnected?: (connection: { connectorId: string; credentialId: string }) => void +} + +export function AtlassianSourceSetupModal({ + organizationId, + connector, + connectorType, + onClose, + onConnected, +}: AtlassianSourceSetupModalProps) { + const account = usePersonalSourceAccount({ + organizationId, + connectorType, + onConnected: (id) => { + setSelectedAccount(id) + config.setSourceConfig((previous) => ({ domain: previous.domain ?? '' })) + }, + }) + const { mutateAsync: connect, isPending } = useConnectPersonalSourceSetup() + const config = useConnectorConfigFields({ + connectorConfig: connector.meta, + accessMode: 'members', + }) + const [selectedAccount, setSelectedAccount] = useState() + const accounts = account.accounts.data?.accounts ?? [] + const requestedAccount = + selectedAccount ?? + account.accounts.data?.completedCredentialId ?? + (accounts.length === 1 ? accounts[0].id : undefined) + const credentialId = accounts.find((item) => item.id === requestedAccount)?.id ?? null + const canonicalId = connectorType === 'jira' ? 'projectKey' : 'spaceKey' + const picker = connector.meta.configFields.find( + (field) => field.canonicalParamId === canonicalId && field.type === 'selector' + )! + const manual = connector.meta.configFields.find((field) => field.id === canonicalId)! + const advanced = config.canonicalModes[canonicalId] === 'advanced' + const domain = typeof config.sourceConfig.domain === 'string' ? config.sourceConfig.domain : '' + const resolved = config.resolveSourceConfig()[canonicalId] + const manualValue = config.sourceConfig[canonicalId] + const keys = Array.isArray(resolved) + ? resolved + .filter((key): key is string => typeof key === 'string' && Boolean(key.trim())) + .map((key) => key.trim()) + : [] + const pending = isPending || account.pending + const close = () => { + if (!isPending) onClose() + } + const chooseAccount = (id: string) => { + if (id === credentialId) return + setSelectedAccount(id) + config.setSourceConfig({ domain }) + } + const addAccount = () => { + void account.connect() + } + const submit = async () => { + if (!credentialId || !domain.trim() || !keys.length || pending) return + if (keys.length > MAX_PERSONAL_SOURCE_SETUP_KEYS) { + toast.error('Choose no more than 1,000 projects or spaces per source.') + return + } + try { + const result = await connect({ + action: 'connect', + organizationId, + connectorType, + credentialId, + domain: domain.trim(), + keys, + }) + onConnected?.({ connectorId: result.connectorId, credentialId }) + onClose() + } catch (error) { + toast.error(getErrorMessage(error, 'Could not connect the source')) + } + } + + return ( + { + if (!open) close() + }} + srTitle={`Connect ${connector.meta.name}`} + > + Connect {connector.meta.name} + + + {(aria) => ( + <> + {accounts.length > 0 && ( + ({ value: item.id, label: item.name }))} + placeholder='Select your account' + disabled={pending} + /> + )} +
+ + {account.pending + ? 'Waiting for authorization…' + : accounts.length + ? 'Connect another account' + : 'Connect account'} + + {account.pending && Cancel} +
+ {account.accounts.isPending && ( +

Loading accounts…

+ )} + {account.accounts.isError && ( + void account.accounts.refetch()}>Retry loading accounts + )} + + )} +
+ {credentialId && !account.pending && ( + <> + config.handleFieldChange('domain', value)} + placeholder='yoursite.atlassian.net' + autoComplete='off' + required + disabled={isPending} + /> + + {(aria) => ( + <> + {advanced ? ( + + config.handleFieldChange(canonicalId, event.target.value) + } + placeholder={manual.placeholder} + disabled={isPending} + /> + ) : picker.selectorKey ? ( + + config.handleFieldChange(picker.id, value, labels) + } + credentialId={credentialId} + sourceConfig={config.sourceConfig} + configFields={connector.meta.configFields} + canonicalModes={config.canonicalModes} + selectedLabels={config.selectionLabels[canonicalId]} + disabled={isPending} + /> + ) : null} + config.toggleCanonicalMode(canonicalId)} + disabled={isPending} + > + {advanced + ? `Choose ${connectorType === 'jira' ? 'projects' : 'spaces'} from list` + : 'Enter keys manually'} + + + )} + + + )} +
+ + window.open(connector.meta.searchDocsUrl, '_blank', 'noopener,noreferrer'), + }, + ] + : undefined + } + primaryAction={{ + label: isPending ? 'Connecting…' : 'Connect & Sync', + onClick: () => void submit(), + disabled: !credentialId || !domain.trim() || !keys.length || pending, + }} + /> +
+ ) +} diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/source-setup-modal.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/source-setup-modal.tsx index 4b73d5b989c..eb6f15699a4 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/source-setup-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/search-sources/source-setup-modal.tsx @@ -9,8 +9,11 @@ import { ChipModalHeader, } from '@sim/emcn' import type { SearchConnector } from '@/lib/sim-search/connectors' +import { AtlassianSourceSetupModal } from '@/app/workspace/[workspaceId]/home/components/search-sources/atlassian-source-setup-modal' interface SourceSetupModalProps { + organizationId?: string + onConnected?: (connection: { connectorId: string; credentialId: string }) => void connector: SearchConnector onClose: () => void isPending?: boolean @@ -23,7 +26,26 @@ interface SourceSetupModalProps { * The few fields a source needs before its first connect, such as a site and * a space. Everyone after the first person clicks straight through. */ -export function SourceSetupModal({ +export function SourceSetupModal(props: SourceSetupModalProps) { + if ( + props.organizationId && + (props.connector.type === 'jira' || props.connector.type === 'confluence') + ) { + return ( + + ) + } + return +} + +function ManualSourceSetupModal({ connector, onClose, onConnect, diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.test.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.test.tsx index 2dbccfee687..daee1e5c632 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.test.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.test.tsx @@ -13,6 +13,7 @@ import type { ConfigFieldMap } from '@/app/workspace/[workspaceId]/knowledge/[id const mocks = vi.hoisted(() => ({ create: vi.fn(), accountsQuery: vi.fn(), + oauthQuery: vi.fn(), configFields: vi.fn(), resolveSourceConfig: vi.fn((): Record => ({})), sourceConfig: {} as ConfigFieldMap, @@ -130,14 +131,17 @@ vi.mock('@/hooks/queries/source-accounts', () => ({ }, })) vi.mock('@/hooks/queries/oauth/oauth-credentials', () => ({ - useOAuthCredentials: () => ({ - data: mocks.credentials, - isLoading: mocks.credentialsState === 'loading', - isSuccess: mocks.credentialsState === 'ready', - isFetching: mocks.credentialsState === 'loading', - error: mocks.credentialsState === 'error' ? new Error('Could not load accounts') : null, - refetch: mocks.refetchCredentials, - }), + useOAuthCredentials: (...args: unknown[]) => { + mocks.oauthQuery(...args) + return { + data: mocks.credentials, + isLoading: mocks.credentialsState === 'loading', + isSuccess: mocks.credentialsState === 'ready', + isFetching: mocks.credentialsState === 'loading', + error: mocks.credentialsState === 'error' ? new Error('Could not load accounts') : null, + refetch: mocks.refetchCredentials, + } + }, })) vi.mock('@/hooks/use-oauth-return', () => ({ useOAuthReturnForKBConnectors: vi.fn() })) vi.mock('@/hooks/use-credential-refresh-triggers', () => ({ @@ -158,6 +162,7 @@ vi.mock(