@arbidocs/sdk 0.3.65 → 0.3.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{browser-D2dkZnc9.d.cts → browser-B5xRfc7b.d.cts} +143 -17
- package/dist/{browser-D2dkZnc9.d.ts → browser-B5xRfc7b.d.ts} +143 -17
- package/dist/browser.cjs +136 -60
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +136 -60
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +153 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +151 -63
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/browser.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { i as AgentStepEvent, j as Arbi, k as ArbiApiError, l as ArbiError,
|
|
1
|
+
export { i as AgentStepEvent, j as Arbi, k as ArbiApiError, l as ArbiError, aU as ArbiErrorEvent, m as ArbiOptions, n as ArtifactEvent, o as AuthContext, A as AuthHeaders, p as AuthenticatedClient, c as ChatSession, q as CitationSummary, a as CliConfig, b as CliCredentials, C as ConfigStore, r as ConnectOptions, y as MessageMetadataPayload, z as MessageQueuedEvent, O as OutputTokensDetails, Q as QueryOptions, R as ReconnectOptions, B as ReconnectableWsConnection, E as ResolvedCitation, G as ResponseCompletedEvent, H as ResponseContentPartAddedEvent, I as ResponseCreatedEvent, J as ResponseFailedEvent, K as ResponseOutputItemAddedEvent, N as ResponseOutputItemDoneEvent, T as ResponseOutputTextDeltaEvent, V as ResponseOutputTextDoneEvent, W as ResponseUsage, X as SSEEvent, Y as SSEStreamCallbacks, Z as SSEStreamResult, _ as SSEStreamStartData, a0 as UserInfo, a1 as UserInputRequestEvent, a2 as UserMessageEvent, a3 as WorkspaceContext, a4 as WsConnection, a5 as agentconfig, a6 as assistant, a7 as authenticatedFetch, a8 as buildRetrievalChunkTool, a9 as buildRetrievalFullContextTool, aa as buildRetrievalTocTool, ab as connectWebSocket, ac as connectWithReconnect, ad as consumeSSEStream, ae as contacts, af as conversations, ag as countCitations, ah as createAuthenticatedClient, aj as dm, ak as doctags, al as documents, am as files, ao as formatAgentStepLabel, ap as formatFileSize, ar as formatUserName, as as formatWorkspaceChoices, ax as getErrorMessage, ay as getRawWorkspaceKey, az as health, aA as parseSSEEvents, aD as performPasswordLogin, aG as requireData, aH as requireOk, aI as resolveAuth, aJ as resolveCitations, aK as resolveWorkspace, aL as responses, aM as selectWorkspace, aN as selectWorkspaceById, aO as settings, aP as streamSSE, aQ as stripCitationMarkdown, aR as summarizeCitations, aS as tags, aT as workspaces } from './browser-B5xRfc7b.cjs';
|
|
2
2
|
import '@arbidocs/client';
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { i as AgentStepEvent, j as Arbi, k as ArbiApiError, l as ArbiError,
|
|
1
|
+
export { i as AgentStepEvent, j as Arbi, k as ArbiApiError, l as ArbiError, aU as ArbiErrorEvent, m as ArbiOptions, n as ArtifactEvent, o as AuthContext, A as AuthHeaders, p as AuthenticatedClient, c as ChatSession, q as CitationSummary, a as CliConfig, b as CliCredentials, C as ConfigStore, r as ConnectOptions, y as MessageMetadataPayload, z as MessageQueuedEvent, O as OutputTokensDetails, Q as QueryOptions, R as ReconnectOptions, B as ReconnectableWsConnection, E as ResolvedCitation, G as ResponseCompletedEvent, H as ResponseContentPartAddedEvent, I as ResponseCreatedEvent, J as ResponseFailedEvent, K as ResponseOutputItemAddedEvent, N as ResponseOutputItemDoneEvent, T as ResponseOutputTextDeltaEvent, V as ResponseOutputTextDoneEvent, W as ResponseUsage, X as SSEEvent, Y as SSEStreamCallbacks, Z as SSEStreamResult, _ as SSEStreamStartData, a0 as UserInfo, a1 as UserInputRequestEvent, a2 as UserMessageEvent, a3 as WorkspaceContext, a4 as WsConnection, a5 as agentconfig, a6 as assistant, a7 as authenticatedFetch, a8 as buildRetrievalChunkTool, a9 as buildRetrievalFullContextTool, aa as buildRetrievalTocTool, ab as connectWebSocket, ac as connectWithReconnect, ad as consumeSSEStream, ae as contacts, af as conversations, ag as countCitations, ah as createAuthenticatedClient, aj as dm, ak as doctags, al as documents, am as files, ao as formatAgentStepLabel, ap as formatFileSize, ar as formatUserName, as as formatWorkspaceChoices, ax as getErrorMessage, ay as getRawWorkspaceKey, az as health, aA as parseSSEEvents, aD as performPasswordLogin, aG as requireData, aH as requireOk, aI as resolveAuth, aJ as resolveCitations, aK as resolveWorkspace, aL as responses, aM as selectWorkspace, aN as selectWorkspaceById, aO as settings, aP as streamSSE, aQ as stripCitationMarkdown, aR as summarizeCitations, aS as tags, aT as workspaces } from './browser-B5xRfc7b.js';
|
|
2
2
|
import '@arbidocs/client';
|
package/dist/browser.js
CHANGED
|
@@ -3565,6 +3565,7 @@ async function authenticatedFetch(options) {
|
|
|
3565
3565
|
}
|
|
3566
3566
|
|
|
3567
3567
|
// src/auth.ts
|
|
3568
|
+
var TOKEN_MAX_AGE_MS = 50 * 60 * 1e3;
|
|
3568
3569
|
function formatWorkspaceChoices(wsList) {
|
|
3569
3570
|
return wsList.map((ws) => {
|
|
3570
3571
|
const totalDocs = ws.shared_document_count + ws.private_document_count;
|
|
@@ -3595,11 +3596,11 @@ async function createAuthenticatedClient(config, creds, store) {
|
|
|
3595
3596
|
});
|
|
3596
3597
|
store.saveCredentials({
|
|
3597
3598
|
...creds,
|
|
3599
|
+
userExtId: loginResult.userExtId ?? creds.userExtId,
|
|
3598
3600
|
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
|
|
3599
3601
|
accessToken: void 0,
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
tokenTimestamp: void 0
|
|
3602
|
+
tokenTimestamp: void 0,
|
|
3603
|
+
openedWorkspaces: void 0
|
|
3603
3604
|
});
|
|
3604
3605
|
return { arbi, loginResult };
|
|
3605
3606
|
}
|
|
@@ -3609,13 +3610,18 @@ async function performPasswordLogin(config, email, password, store) {
|
|
|
3609
3610
|
const loginResult = await arbi.auth.login({ email, password });
|
|
3610
3611
|
store.saveCredentials({
|
|
3611
3612
|
email,
|
|
3613
|
+
userExtId: loginResult.userExtId,
|
|
3612
3614
|
signingPrivateKeyBase64: arbi.crypto.bytesToBase64(loginResult.signingPrivateKey),
|
|
3613
3615
|
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
|
|
3614
|
-
//
|
|
3616
|
+
// `parent_ext_id` is set for persistent agent accounts (the user is
|
|
3617
|
+
// an Assistant owned by another user). Persisting it makes the CLI's
|
|
3618
|
+
// `arbi listen` work — it requires this to confirm a real agent
|
|
3619
|
+
// identity. Regular users get `null`, which we store as `undefined`.
|
|
3620
|
+
parentExtId: loginResult.parentExtId ?? void 0,
|
|
3621
|
+
// New session = no workspaces deposited yet.
|
|
3615
3622
|
accessToken: void 0,
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
tokenTimestamp: void 0
|
|
3623
|
+
tokenTimestamp: void 0,
|
|
3624
|
+
openedWorkspaces: void 0
|
|
3619
3625
|
});
|
|
3620
3626
|
return { arbi, loginResult, config };
|
|
3621
3627
|
}
|
|
@@ -3631,16 +3637,6 @@ async function selectWorkspace(arbi, workspaceId, wrappedKey, serverSessionKey,
|
|
|
3631
3637
|
arbi.session.setSelectedWorkspace(workspaceId);
|
|
3632
3638
|
return header;
|
|
3633
3639
|
}
|
|
3634
|
-
async function generateEncryptedWorkspaceKey(arbi, wrappedKey, serverSessionKey, signingPrivateKeyBase64) {
|
|
3635
|
-
const signingPrivateKey = base64ToBytes(signingPrivateKeyBase64);
|
|
3636
|
-
const ed25519PublicKey = signingPrivateKey.slice(32, 64);
|
|
3637
|
-
const encryptionKeyPair = deriveEncryptionKeypairFromSigning({
|
|
3638
|
-
publicKey: ed25519PublicKey,
|
|
3639
|
-
secretKey: signingPrivateKey
|
|
3640
|
-
});
|
|
3641
|
-
const workspaceKey = sealedBoxDecrypt(wrappedKey, encryptionKeyPair.secretKey);
|
|
3642
|
-
return sealKeyForSession(workspaceKey, serverSessionKey);
|
|
3643
|
-
}
|
|
3644
3640
|
async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
|
|
3645
3641
|
const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
3646
3642
|
if (error || !workspaces) {
|
|
@@ -3658,38 +3654,79 @@ async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
|
|
|
3658
3654
|
});
|
|
3659
3655
|
return sealedBoxDecrypt(ws.wrapped_key, encryptionKeyPair.secretKey);
|
|
3660
3656
|
}
|
|
3657
|
+
async function openWorkspaceEntry(arbi, ws, serverSessionKey, signingPrivateKeyBase64) {
|
|
3658
|
+
if (ws.wrapped_key) {
|
|
3659
|
+
const sealedKey = await selectWorkspace(
|
|
3660
|
+
arbi,
|
|
3661
|
+
ws.external_id,
|
|
3662
|
+
ws.wrapped_key,
|
|
3663
|
+
serverSessionKey,
|
|
3664
|
+
signingPrivateKeyBase64
|
|
3665
|
+
);
|
|
3666
|
+
const { error: error2 } = await arbi.fetch.POST("/v1/workspace/{workspace_ext_id}/open", {
|
|
3667
|
+
params: { path: { workspace_ext_id: ws.external_id } },
|
|
3668
|
+
body: { workspace_key: sealedKey }
|
|
3669
|
+
});
|
|
3670
|
+
if (error2) {
|
|
3671
|
+
throw new ArbiError(`Workspace open failed for ${ws.external_id}: ${JSON.stringify(error2)}`);
|
|
3672
|
+
}
|
|
3673
|
+
return sealedKey;
|
|
3674
|
+
}
|
|
3675
|
+
arbi.session.setSelectedWorkspace(ws.external_id);
|
|
3676
|
+
const { error } = await arbi.fetch.POST("/v1/workspace/{workspace_ext_id}/open", {
|
|
3677
|
+
params: { path: { workspace_ext_id: ws.external_id } },
|
|
3678
|
+
body: {}
|
|
3679
|
+
});
|
|
3680
|
+
if (error) {
|
|
3681
|
+
throw new ArbiError(`Workspace open failed for ${ws.external_id}: ${JSON.stringify(error)}`);
|
|
3682
|
+
}
|
|
3683
|
+
return null;
|
|
3684
|
+
}
|
|
3661
3685
|
async function selectWorkspaceById(arbi, workspaceId, serverSessionKey, signingPrivateKeyBase64) {
|
|
3662
3686
|
const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
3663
3687
|
if (error || !workspaces) {
|
|
3664
3688
|
throw new ArbiError("Failed to fetch workspaces");
|
|
3665
3689
|
}
|
|
3666
3690
|
const ws = workspaces.find((w2) => w2.external_id === workspaceId);
|
|
3667
|
-
if (!ws
|
|
3668
|
-
throw new ArbiError(`Workspace ${workspaceId} not found
|
|
3691
|
+
if (!ws) {
|
|
3692
|
+
throw new ArbiError(`Workspace ${workspaceId} not found`);
|
|
3669
3693
|
}
|
|
3670
|
-
const sealedKey = await
|
|
3671
|
-
|
|
3672
|
-
ws.external_id,
|
|
3673
|
-
ws.
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3694
|
+
const sealedKey = await openWorkspaceEntry(arbi, ws, serverSessionKey, signingPrivateKeyBase64);
|
|
3695
|
+
return {
|
|
3696
|
+
external_id: ws.external_id,
|
|
3697
|
+
name: ws.name,
|
|
3698
|
+
wrapped_key: ws.wrapped_key ?? null,
|
|
3699
|
+
sealed_key: sealedKey
|
|
3700
|
+
};
|
|
3701
|
+
}
|
|
3702
|
+
function isSessionAlive(creds) {
|
|
3703
|
+
return !!(creds.accessToken && creds.tokenTimestamp && Date.now() - new Date(creds.tokenTimestamp).getTime() < TOKEN_MAX_AGE_MS);
|
|
3704
|
+
}
|
|
3705
|
+
async function buildAuthFromCache(config, creds, store) {
|
|
3706
|
+
const arbi = createArbiClient(buildClientOptions(config, store, creds.email));
|
|
3707
|
+
await arbi.crypto.initSodium();
|
|
3708
|
+
arbi.session.setUser(creds.email, creds.userExtId);
|
|
3709
|
+
arbi.session.setAccessToken(creds.accessToken);
|
|
3710
|
+
const signingPrivateKey = base64ToBytes(creds.signingPrivateKeyBase64);
|
|
3711
|
+
const serverSessionKey = base64ToBytes(creds.serverSessionKeyBase64);
|
|
3712
|
+
const loginResult = {
|
|
3713
|
+
accessToken: creds.accessToken,
|
|
3714
|
+
userExtId: creds.userExtId,
|
|
3715
|
+
signingPrivateKey,
|
|
3716
|
+
serverSessionKey
|
|
3717
|
+
};
|
|
3718
|
+
return { arbi, loginResult };
|
|
3682
3719
|
}
|
|
3683
3720
|
async function resolveAuth(store) {
|
|
3684
3721
|
const config = store.requireConfig();
|
|
3685
3722
|
const creds = store.requireCredentials();
|
|
3723
|
+
if (isSessionAlive(creds)) {
|
|
3724
|
+
const { arbi: arbi2, loginResult: loginResult2 } = await buildAuthFromCache(config, creds, store);
|
|
3725
|
+
return { arbi: arbi2, loginResult: loginResult2, config };
|
|
3726
|
+
}
|
|
3686
3727
|
const { arbi, loginResult } = await createAuthenticatedClient(config, creds, store);
|
|
3687
3728
|
return { arbi, loginResult, config };
|
|
3688
3729
|
}
|
|
3689
|
-
var TOKEN_MAX_AGE_MS = 50 * 60 * 1e3;
|
|
3690
|
-
function isCachedTokenValid(creds, workspaceId) {
|
|
3691
|
-
return !!(creds.accessToken && creds.sealedWorkspaceKey && creds.workspaceId === workspaceId && creds.tokenTimestamp && Date.now() - new Date(creds.tokenTimestamp).getTime() < TOKEN_MAX_AGE_MS);
|
|
3692
|
-
}
|
|
3693
3730
|
async function resolveWorkspace(store, workspaceOpt) {
|
|
3694
3731
|
const config = store.requireConfig();
|
|
3695
3732
|
const creds = store.requireCredentials();
|
|
@@ -3697,53 +3734,52 @@ async function resolveWorkspace(store, workspaceOpt) {
|
|
|
3697
3734
|
if (!workspaceId) {
|
|
3698
3735
|
throw new ArbiError("No workspace selected. Run: arbi workspace select <id>");
|
|
3699
3736
|
}
|
|
3700
|
-
if (
|
|
3701
|
-
const arbi2 =
|
|
3702
|
-
await arbi2.crypto.initSodium();
|
|
3703
|
-
arbi2.session.setUser(creds.email);
|
|
3737
|
+
if (isSessionAlive(creds)) {
|
|
3738
|
+
const { arbi: arbi2, loginResult: loginResult2 } = await buildAuthFromCache(config, creds, store);
|
|
3704
3739
|
arbi2.session.setSelectedWorkspace(workspaceId);
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3740
|
+
await selectWorkspaceById(
|
|
3741
|
+
arbi2,
|
|
3742
|
+
workspaceId,
|
|
3743
|
+
loginResult2.serverSessionKey,
|
|
3744
|
+
creds.signingPrivateKeyBase64
|
|
3745
|
+
);
|
|
3746
|
+
const nextOpened = Array.from(/* @__PURE__ */ new Set([...creds.openedWorkspaces ?? [], workspaceId]));
|
|
3747
|
+
store.saveCredentials({
|
|
3748
|
+
...store.requireCredentials(),
|
|
3749
|
+
openedWorkspaces: nextOpened
|
|
3750
|
+
});
|
|
3713
3751
|
return {
|
|
3714
3752
|
arbi: arbi2,
|
|
3715
3753
|
loginResult: loginResult2,
|
|
3716
3754
|
config,
|
|
3717
3755
|
workspaceId,
|
|
3718
|
-
accessToken: creds.accessToken
|
|
3719
|
-
sealedWorkspaceKey: creds.sealedWorkspaceKey
|
|
3756
|
+
accessToken: creds.accessToken
|
|
3720
3757
|
};
|
|
3721
3758
|
}
|
|
3722
3759
|
const { arbi, loginResult } = await createAuthenticatedClient(config, creds, store);
|
|
3723
|
-
|
|
3760
|
+
await selectWorkspaceById(
|
|
3724
3761
|
arbi,
|
|
3725
3762
|
workspaceId,
|
|
3726
3763
|
loginResult.serverSessionKey,
|
|
3727
3764
|
creds.signingPrivateKeyBase64
|
|
3728
3765
|
);
|
|
3729
3766
|
const accessToken = arbi.session.getState().accessToken;
|
|
3730
|
-
const sealedWorkspaceKey = await generateEncryptedWorkspaceKey(
|
|
3731
|
-
arbi,
|
|
3732
|
-
wsInfo.wrapped_key,
|
|
3733
|
-
loginResult.serverSessionKey,
|
|
3734
|
-
creds.signingPrivateKeyBase64
|
|
3735
|
-
);
|
|
3736
3767
|
if (!accessToken) {
|
|
3737
3768
|
throw new ArbiError("Authentication error \u2014 missing token");
|
|
3738
3769
|
}
|
|
3739
3770
|
store.saveCredentials({
|
|
3740
3771
|
...store.requireCredentials(),
|
|
3741
3772
|
accessToken,
|
|
3742
|
-
|
|
3743
|
-
workspaceId
|
|
3744
|
-
tokenTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3773
|
+
tokenTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3774
|
+
openedWorkspaces: [workspaceId]
|
|
3745
3775
|
});
|
|
3746
|
-
return {
|
|
3776
|
+
return {
|
|
3777
|
+
arbi,
|
|
3778
|
+
loginResult,
|
|
3779
|
+
config,
|
|
3780
|
+
workspaceId,
|
|
3781
|
+
accessToken
|
|
3782
|
+
};
|
|
3747
3783
|
}
|
|
3748
3784
|
|
|
3749
3785
|
// src/sse.ts
|
|
@@ -4307,6 +4343,7 @@ async function uploadFile(auth, fileData, fileName, options) {
|
|
|
4307
4343
|
const params = new URLSearchParams();
|
|
4308
4344
|
if (options?.folder) params.set("folder", sanitizeFolderPath(options.folder));
|
|
4309
4345
|
if (options?.configExtId) params.set("config_ext_id", options.configExtId);
|
|
4346
|
+
if (options?.wpType) params.set("wp_type", options.wpType);
|
|
4310
4347
|
const qs = params.toString();
|
|
4311
4348
|
const res = await authenticatedFetch({
|
|
4312
4349
|
...auth,
|
|
@@ -4322,6 +4359,7 @@ async function uploadFiles(auth, files, options) {
|
|
|
4322
4359
|
const params = new URLSearchParams();
|
|
4323
4360
|
if (options?.folder) params.set("folder", sanitizeFolderPath(options.folder));
|
|
4324
4361
|
if (options?.configExtId) params.set("config_ext_id", options.configExtId);
|
|
4362
|
+
if (options?.wpType) params.set("wp_type", options.wpType);
|
|
4325
4363
|
const qs = params.toString();
|
|
4326
4364
|
const res = await authenticatedFetch({
|
|
4327
4365
|
...auth,
|
|
@@ -4647,6 +4685,10 @@ __export(assistant_exports, {
|
|
|
4647
4685
|
buildRetrievalChunkTool: () => buildRetrievalChunkTool,
|
|
4648
4686
|
buildRetrievalFullContextTool: () => buildRetrievalFullContextTool,
|
|
4649
4687
|
buildRetrievalTocTool: () => buildRetrievalTocTool,
|
|
4688
|
+
filterSkills: () => filterSkills,
|
|
4689
|
+
listSkills: () => listSkills,
|
|
4690
|
+
parseSlashCommand: () => parseSlashCommand,
|
|
4691
|
+
parseSlashTokenInProgress: () => parseSlashTokenInProgress,
|
|
4650
4692
|
queryAssistant: () => queryAssistant,
|
|
4651
4693
|
respondToAgent: () => respondToAgent,
|
|
4652
4694
|
retrieve: () => retrieve
|
|
@@ -4742,6 +4784,40 @@ async function respondToAgent(arbi, assistantMessageExtId, answer) {
|
|
|
4742
4784
|
"Failed to respond to agent"
|
|
4743
4785
|
);
|
|
4744
4786
|
}
|
|
4787
|
+
async function listSkills(arbi, options) {
|
|
4788
|
+
const result = requireData(
|
|
4789
|
+
await arbi.fetch.GET("/v1/assistant/skills", {
|
|
4790
|
+
params: { query: { include_hidden: options?.includeHidden ?? false } }
|
|
4791
|
+
}),
|
|
4792
|
+
"Failed to list skills"
|
|
4793
|
+
);
|
|
4794
|
+
return result.skills;
|
|
4795
|
+
}
|
|
4796
|
+
function parseSlashCommand(input) {
|
|
4797
|
+
const m2 = /^\s*\/([a-zA-Z0-9_-]+)(?:\s+([\s\S]*))?$/.exec(input);
|
|
4798
|
+
if (!m2) return null;
|
|
4799
|
+
return { slug: m2[1].toLowerCase(), args: m2[2] ?? "" };
|
|
4800
|
+
}
|
|
4801
|
+
function parseSlashTokenInProgress(buffer) {
|
|
4802
|
+
const m2 = /^\s*\/([a-zA-Z0-9_-]*)$/.exec(buffer);
|
|
4803
|
+
return m2 ? m2[1].toLowerCase() : null;
|
|
4804
|
+
}
|
|
4805
|
+
function filterSkills(items, query, pinned = []) {
|
|
4806
|
+
const q2 = query.toLowerCase();
|
|
4807
|
+
const pinnedSet = new Set(pinned);
|
|
4808
|
+
const key = (s2) => (s2.slug ?? s2.name).toLowerCase();
|
|
4809
|
+
const matched = q2 ? items.filter((s2) => key(s2).includes(q2)) : items.slice();
|
|
4810
|
+
matched.sort((a2, b2) => {
|
|
4811
|
+
const aPinned = pinnedSet.has(key(a2)) ? 0 : 1;
|
|
4812
|
+
const bPinned = pinnedSet.has(key(b2)) ? 0 : 1;
|
|
4813
|
+
if (aPinned !== bPinned) return aPinned - bPinned;
|
|
4814
|
+
const aPrefix = key(a2).startsWith(q2) ? 0 : 1;
|
|
4815
|
+
const bPrefix = key(b2).startsWith(q2) ? 0 : 1;
|
|
4816
|
+
if (aPrefix !== bPrefix) return aPrefix - bPrefix;
|
|
4817
|
+
return key(a2).localeCompare(key(b2));
|
|
4818
|
+
});
|
|
4819
|
+
return matched;
|
|
4820
|
+
}
|
|
4745
4821
|
|
|
4746
4822
|
// src/operations/tags.ts
|
|
4747
4823
|
var tags_exports = {};
|