@getpaseo/server 0.1.97 → 0.1.99
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/server/server/agent/agent-manager.d.ts +11 -3
- package/dist/server/server/agent/agent-manager.js +96 -24
- package/dist/server/server/agent/agent-prompt.d.ts +1 -1
- package/dist/server/server/agent/agent-prompt.js +3 -10
- package/dist/server/server/agent/agent-sdk-types.d.ts +20 -9
- package/dist/server/server/agent/create-agent/create.d.ts +2 -0
- package/dist/server/server/agent/create-agent/create.js +8 -7
- package/dist/server/server/agent/lifecycle-command.d.ts +15 -1
- package/dist/server/server/agent/lifecycle-command.js +9 -2
- package/dist/server/server/agent/mcp-server.js +254 -115
- package/dist/server/server/agent/provider-notices.d.ts +3 -0
- package/dist/server/server/agent/provider-notices.js +5 -0
- package/dist/server/server/agent/provider-registry.d.ts +8 -3
- package/dist/server/server/agent/provider-registry.js +58 -25
- package/dist/server/server/agent/provider-snapshot-manager.d.ts +3 -0
- package/dist/server/server/agent/provider-snapshot-manager.js +37 -16
- package/dist/server/server/agent/providers/acp-agent.d.ts +5 -3
- package/dist/server/server/agent/providers/acp-agent.js +32 -19
- package/dist/server/server/agent/providers/claude/agent.d.ts +2 -2
- package/dist/server/server/agent/providers/claude/agent.js +261 -167
- package/dist/server/server/agent/providers/claude/models.js +7 -3
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +6 -4
- package/dist/server/server/agent/providers/codex-app-server-agent.js +48 -25
- package/dist/server/server/agent/providers/copilot-acp-agent.js +4 -31
- package/dist/server/server/agent/providers/diagnostic-utils.d.ts +9 -0
- package/dist/server/server/agent/providers/diagnostic-utils.js +188 -0
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +0 -1
- package/dist/server/server/agent/providers/generic-acp-agent.js +2 -108
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +2 -3
- package/dist/server/server/agent/providers/mock-load-test-agent.js +5 -5
- package/dist/server/server/agent/providers/mock-slow-provider.d.ts +2 -3
- package/dist/server/server/agent/providers/mock-slow-provider.js +3 -6
- package/dist/server/server/agent/providers/opencode/server-manager.d.ts +29 -2
- package/dist/server/server/agent/providers/opencode/server-manager.js +83 -17
- package/dist/server/server/agent/providers/opencode-agent.d.ts +6 -3
- package/dist/server/server/agent/providers/opencode-agent.js +61 -107
- package/dist/server/server/agent/providers/pi/agent.d.ts +2 -3
- package/dist/server/server/agent/providers/pi/agent.js +11 -63
- package/dist/server/server/agent/providers/pi/cli-runtime.js +2 -2
- package/dist/server/server/agent/providers/pi/runtime.d.ts +1 -1
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +1 -1
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +1 -1
- package/dist/server/server/bootstrap.d.ts +2 -0
- package/dist/server/server/bootstrap.js +32 -2
- package/dist/server/server/managed-processes/managed-processes.d.ts +76 -0
- package/dist/server/server/managed-processes/managed-processes.js +326 -0
- package/dist/server/server/resolve-worktree-creation-intent.d.ts +3 -0
- package/dist/server/server/resolve-worktree-creation-intent.js +3 -3
- package/dist/server/server/session/agent-config/agent-config-session.d.ts +50 -0
- package/dist/server/server/session/agent-config/agent-config-session.js +98 -0
- package/dist/server/server/session/chat/chat-schedule-loop-session.d.ts +120 -0
- package/dist/server/server/session/chat/chat-schedule-loop-session.js +489 -0
- package/dist/server/server/session/checkout/checkout-session.d.ts +142 -0
- package/dist/server/server/session/checkout/checkout-session.js +925 -0
- package/dist/server/server/session/daemon/daemon-session.d.ts +50 -0
- package/dist/server/server/session/daemon/daemon-session.js +98 -0
- package/dist/server/server/session/files/workspace-files-session.d.ts +43 -0
- package/dist/server/server/session/files/workspace-files-session.js +218 -0
- package/dist/server/server/session/project-config/project-config-session.d.ts +34 -0
- package/dist/server/server/session/project-config/project-config-session.js +125 -0
- package/dist/server/server/session/provider/provider-catalog-session.d.ts +74 -0
- package/dist/server/server/session/provider/provider-catalog-session.js +339 -0
- package/dist/server/server/session/voice/voice-session.d.ts +166 -0
- package/dist/server/server/session/voice/voice-session.js +893 -0
- package/dist/server/server/{voice → session/voice}/voice-turn-controller.d.ts +2 -2
- package/dist/server/server/{voice → session/voice}/voice-turn-controller.js +2 -2
- package/dist/server/server/session.d.ts +23 -207
- package/dist/server/server/session.js +2319 -5102
- package/dist/server/server/speech/providers/openai/runtime.js +3 -4
- package/dist/server/server/websocket-server.d.ts +1 -0
- package/dist/server/server/websocket-server.js +11 -0
- package/dist/server/server/workspace-archive-service.js +2 -3
- package/dist/server/server/workspace-directory.js +5 -5
- package/dist/server/server/workspace-reconciliation-service.js +2 -2
- package/dist/server/server/worktree-core.d.ts +1 -0
- package/dist/server/server/worktree-core.js +5 -1
- package/dist/server/services/quota-fetcher/manifest.d.ts +4 -0
- package/dist/server/services/quota-fetcher/manifest.js +47 -0
- package/dist/server/services/quota-fetcher/provider.d.ts +17 -0
- package/dist/server/services/quota-fetcher/provider.js +2 -0
- package/dist/server/services/quota-fetcher/providers/claude.d.ts +26 -0
- package/dist/server/services/quota-fetcher/providers/claude.js +217 -0
- package/dist/server/services/quota-fetcher/providers/codex.d.ts +23 -0
- package/dist/server/services/quota-fetcher/providers/codex.js +211 -0
- package/dist/server/services/quota-fetcher/providers/copilot.d.ts +17 -0
- package/dist/server/services/quota-fetcher/providers/copilot.js +75 -0
- package/dist/server/services/quota-fetcher/providers/cursor.d.ts +17 -0
- package/dist/server/services/quota-fetcher/providers/cursor.js +123 -0
- package/dist/server/services/quota-fetcher/providers/grok.d.ts +18 -0
- package/dist/server/services/quota-fetcher/providers/grok.js +89 -0
- package/dist/server/services/quota-fetcher/providers/kimi.d.ts +20 -0
- package/dist/server/services/quota-fetcher/providers/kimi.js +89 -0
- package/dist/server/services/quota-fetcher/providers/zai.d.ts +17 -0
- package/dist/server/services/quota-fetcher/providers/zai.js +58 -0
- package/dist/server/services/quota-fetcher/service.d.ts +28 -0
- package/dist/server/services/quota-fetcher/service.js +58 -0
- package/dist/server/services/quota-fetcher/usage.d.ts +22 -0
- package/dist/server/services/quota-fetcher/usage.js +49 -0
- package/dist/server/utils/checkout-git.d.ts +6 -0
- package/dist/server/utils/directory-suggestions.js +98 -2
- package/package.json +5 -5
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ApiOptionalStringSchema, fetchProviderApi, unavailableUsage } from "../usage.js";
|
|
3
|
+
const ZaiUsageResponseSchema = z.object({
|
|
4
|
+
data: z
|
|
5
|
+
.array(z.object({
|
|
6
|
+
productName: ApiOptionalStringSchema,
|
|
7
|
+
status: ApiOptionalStringSchema,
|
|
8
|
+
purchaseTime: ApiOptionalStringSchema,
|
|
9
|
+
valid: ApiOptionalStringSchema,
|
|
10
|
+
}))
|
|
11
|
+
.optional(),
|
|
12
|
+
});
|
|
13
|
+
export class ZaiQuotaProvider {
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.providerId = "zai";
|
|
16
|
+
this.displayName = "Z.ai";
|
|
17
|
+
this.logger = options.logger;
|
|
18
|
+
this.fetchApi = options.fetch ?? fetch;
|
|
19
|
+
}
|
|
20
|
+
async fetchUsage() {
|
|
21
|
+
const token = process.env["ZAI_API_KEY"] || process.env["GLM_API_KEY"];
|
|
22
|
+
if (!token)
|
|
23
|
+
return unavailableUsage(this);
|
|
24
|
+
const res = await fetchProviderApi(this.fetchApi, "https://api.z.ai/api/biz/subscription/list", {
|
|
25
|
+
headers: {
|
|
26
|
+
Authorization: `Bearer ${token}`,
|
|
27
|
+
Accept: "application/json",
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
this.logger.debug({ status: res.status }, "Z.ai usage fetch failed");
|
|
32
|
+
return unavailableUsage(this);
|
|
33
|
+
}
|
|
34
|
+
const resp = ZaiUsageResponseSchema.parse(await res.json());
|
|
35
|
+
const sub = resp.data?.[0];
|
|
36
|
+
if (!sub)
|
|
37
|
+
return unavailableUsage(this);
|
|
38
|
+
const details = [];
|
|
39
|
+
if (sub.status)
|
|
40
|
+
details.push({ id: "status", label: "Status", value: sub.status });
|
|
41
|
+
if (sub.valid)
|
|
42
|
+
details.push({ id: "valid", label: "Valid", value: sub.valid });
|
|
43
|
+
if (sub.purchaseTime) {
|
|
44
|
+
details.push({ id: "purchase_time", label: "Purchased", value: sub.purchaseTime });
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
providerId: this.providerId,
|
|
48
|
+
displayName: this.displayName,
|
|
49
|
+
status: "available",
|
|
50
|
+
planLabel: sub.productName || null,
|
|
51
|
+
windows: [],
|
|
52
|
+
balances: [],
|
|
53
|
+
details,
|
|
54
|
+
error: null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=zai.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Logger } from "pino";
|
|
2
|
+
import type { ProviderUsage } from "../../server/messages.js";
|
|
3
|
+
import type { ProviderApiFetch, ProviderUsageFetcher } from "./provider.js";
|
|
4
|
+
export interface ProviderUsageServiceOptions {
|
|
5
|
+
logger: Logger;
|
|
6
|
+
fetchers?: ProviderUsageFetcher[];
|
|
7
|
+
fetch?: ProviderApiFetch;
|
|
8
|
+
cacheTtlMs?: number;
|
|
9
|
+
now?: () => number;
|
|
10
|
+
}
|
|
11
|
+
export interface ProviderUsageListResult {
|
|
12
|
+
fetchedAt: string;
|
|
13
|
+
providers: ProviderUsage[];
|
|
14
|
+
}
|
|
15
|
+
export declare class ProviderUsageService {
|
|
16
|
+
private readonly logger;
|
|
17
|
+
private readonly fetchers;
|
|
18
|
+
private readonly cacheTtlMs;
|
|
19
|
+
private readonly now;
|
|
20
|
+
private cached;
|
|
21
|
+
private inFlight;
|
|
22
|
+
constructor(options: ProviderUsageServiceOptions);
|
|
23
|
+
listUsage(options?: {
|
|
24
|
+
forceRefresh?: boolean;
|
|
25
|
+
}): Promise<ProviderUsageListResult>;
|
|
26
|
+
private fetchFreshUsage;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createProviderUsageFetchers } from "./manifest.js";
|
|
2
|
+
import { unavailableUsage } from "./usage.js";
|
|
3
|
+
const DEFAULT_PROVIDER_USAGE_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
4
|
+
export class ProviderUsageService {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.cached = null;
|
|
7
|
+
this.inFlight = null;
|
|
8
|
+
this.logger = options.logger.child({ module: "provider-usage-service" });
|
|
9
|
+
this.fetchers =
|
|
10
|
+
options.fetchers ??
|
|
11
|
+
createProviderUsageFetchers({
|
|
12
|
+
logger: this.logger,
|
|
13
|
+
fetch: options.fetch,
|
|
14
|
+
});
|
|
15
|
+
this.cacheTtlMs = options.cacheTtlMs ?? DEFAULT_PROVIDER_USAGE_CACHE_TTL_MS;
|
|
16
|
+
this.now = options.now ?? Date.now;
|
|
17
|
+
}
|
|
18
|
+
async listUsage(options) {
|
|
19
|
+
const nowMs = this.now();
|
|
20
|
+
if (!options?.forceRefresh &&
|
|
21
|
+
this.cached &&
|
|
22
|
+
nowMs - this.cached.fetchedAtMs < this.cacheTtlMs) {
|
|
23
|
+
return this.cached.result;
|
|
24
|
+
}
|
|
25
|
+
if (this.inFlight) {
|
|
26
|
+
return this.inFlight;
|
|
27
|
+
}
|
|
28
|
+
const request = this.fetchFreshUsage(nowMs);
|
|
29
|
+
this.inFlight = request;
|
|
30
|
+
try {
|
|
31
|
+
return await request;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
if (this.inFlight === request) {
|
|
35
|
+
this.inFlight = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async fetchFreshUsage(nowMs) {
|
|
40
|
+
const settled = await Promise.allSettled(this.fetchers.map((fetcher) => fetcher.fetchUsage()));
|
|
41
|
+
const providers = settled.map((result, index) => {
|
|
42
|
+
const fetcher = this.fetchers[index];
|
|
43
|
+
if (result.status === "fulfilled") {
|
|
44
|
+
return result.value;
|
|
45
|
+
}
|
|
46
|
+
this.logger.debug({ err: result.reason, providerId: fetcher.providerId }, "Provider usage fetch failed");
|
|
47
|
+
return unavailableUsage({
|
|
48
|
+
providerId: fetcher.providerId,
|
|
49
|
+
displayName: fetcher.displayName,
|
|
50
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
const result = { fetchedAt: new Date(nowMs).toISOString(), providers };
|
|
54
|
+
this.cached = { fetchedAtMs: nowMs, result };
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ProviderUsage, ProviderUsageBalance, ProviderUsageWindow } from "../../server/messages.js";
|
|
3
|
+
import type { ProviderApiFetch } from "./provider.js";
|
|
4
|
+
export declare const ApiNumberSchema: z.ZodCoercedNumber<unknown>;
|
|
5
|
+
export declare const ApiNullableNumberSchema: z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
|
|
6
|
+
export declare const ApiOptionalStringSchema: z.ZodPreprocess<z.ZodOptional<z.ZodCoercedString<unknown>>>;
|
|
7
|
+
export declare function fetchProviderApi(fetchApi: ProviderApiFetch, input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
8
|
+
export declare function unavailableUsage(provider: {
|
|
9
|
+
providerId: string;
|
|
10
|
+
displayName: string;
|
|
11
|
+
error?: string | null;
|
|
12
|
+
}): ProviderUsage;
|
|
13
|
+
export declare function windowFromUsedPct(input: {
|
|
14
|
+
id: string;
|
|
15
|
+
label: string;
|
|
16
|
+
utilizationPct: number | null | undefined;
|
|
17
|
+
resetsAt?: string | null;
|
|
18
|
+
tone?: ProviderUsageWindow["tone"];
|
|
19
|
+
}): ProviderUsageWindow;
|
|
20
|
+
export declare function balanceToneFromRemaining(remaining: number | null | undefined): ProviderUsageBalance["tone"];
|
|
21
|
+
export declare function toIsoStringOrNull(timestampMs: number): string | null;
|
|
22
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const PROVIDER_HTTP_TIMEOUT_MS = 15000;
|
|
3
|
+
export const ApiNumberSchema = z.coerce.number().finite();
|
|
4
|
+
export const ApiNullableNumberSchema = z.preprocess((value) => (value == null ? null : value), ApiNumberSchema.nullable());
|
|
5
|
+
export const ApiOptionalStringSchema = z.preprocess((value) => (value == null ? undefined : value), z.coerce.string().optional());
|
|
6
|
+
export function fetchProviderApi(fetchApi, input, init = {}) {
|
|
7
|
+
return fetchApi(input, {
|
|
8
|
+
...init,
|
|
9
|
+
signal: init.signal ?? AbortSignal.timeout(PROVIDER_HTTP_TIMEOUT_MS),
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export function unavailableUsage(provider) {
|
|
13
|
+
return {
|
|
14
|
+
providerId: provider.providerId,
|
|
15
|
+
displayName: provider.displayName,
|
|
16
|
+
status: provider.error ? "error" : "unavailable",
|
|
17
|
+
planLabel: null,
|
|
18
|
+
windows: [],
|
|
19
|
+
balances: [],
|
|
20
|
+
details: [],
|
|
21
|
+
error: provider.error ?? null,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function windowFromUsedPct(input) {
|
|
25
|
+
const usedPct = typeof input.utilizationPct === "number" ? input.utilizationPct : null;
|
|
26
|
+
const window = {
|
|
27
|
+
id: input.id,
|
|
28
|
+
label: input.label,
|
|
29
|
+
usedPct,
|
|
30
|
+
remainingPct: usedPct === null ? null : Math.max(0, 100 - usedPct),
|
|
31
|
+
resetsAt: input.resetsAt ?? null,
|
|
32
|
+
};
|
|
33
|
+
if (input.tone) {
|
|
34
|
+
window.tone = input.tone;
|
|
35
|
+
}
|
|
36
|
+
return window;
|
|
37
|
+
}
|
|
38
|
+
export function balanceToneFromRemaining(remaining) {
|
|
39
|
+
if (typeof remaining !== "number")
|
|
40
|
+
return "default";
|
|
41
|
+
if (remaining <= 0)
|
|
42
|
+
return "danger";
|
|
43
|
+
return "ok";
|
|
44
|
+
}
|
|
45
|
+
export function toIsoStringOrNull(timestampMs) {
|
|
46
|
+
const date = new Date(timestampMs);
|
|
47
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
2
|
import type { ParsedDiffFile } from "../server/utils/diff-highlighter.js";
|
|
3
3
|
import { type GitHubPullRequestStatusFacts, type GitHubService, type PullRequestMergeable } from "../services/github-service.js";
|
|
4
|
+
/**
|
|
5
|
+
* Why a git mutation is forcing a workspace snapshot refresh. Shared between the
|
|
6
|
+
* Session shell (which owns the refresh primitive) and the checkout subsystem
|
|
7
|
+
* (which triggers most of these reasons after a write).
|
|
8
|
+
*/
|
|
9
|
+
export type GitMutationRefreshReason = "commit-changes" | "pull" | "push" | "merge-to-base" | "merge-from-base" | "merge-pr" | "enable-pr-auto-merge" | "disable-pr-auto-merge" | "create-pr" | "switch-branch" | "rename-branch" | "create-branch" | "stash-push" | "stash-pop" | "create-worktree";
|
|
4
10
|
interface CheckoutReadCacheOptions {
|
|
5
11
|
force?: boolean;
|
|
6
12
|
reason?: string;
|
|
@@ -24,6 +24,15 @@ const IGNORED_SUGGESTION_DIRECTORY_NAMES = new Set([
|
|
|
24
24
|
"coverage",
|
|
25
25
|
"vendor",
|
|
26
26
|
"__pycache__",
|
|
27
|
+
".git",
|
|
28
|
+
]);
|
|
29
|
+
const TRAVERSABLE_HIDDEN_WORKSPACE_DIRECTORY_NAMES = new Set([
|
|
30
|
+
".agents",
|
|
31
|
+
".claude",
|
|
32
|
+
".codex",
|
|
33
|
+
".github",
|
|
34
|
+
".paseo",
|
|
35
|
+
".vscode",
|
|
27
36
|
]);
|
|
28
37
|
export async function searchHomeDirectories(options) {
|
|
29
38
|
const query = options.query.trim();
|
|
@@ -71,6 +80,17 @@ export async function searchWorkspaceEntries(options) {
|
|
|
71
80
|
return [];
|
|
72
81
|
}
|
|
73
82
|
const matchMode = options.matchMode ?? "fuzzy";
|
|
83
|
+
const exactEntry = queryParts.isPathQuery && matchMode === "suffix"
|
|
84
|
+
? await resolveWorkspaceExactEntry({
|
|
85
|
+
workspaceRoot,
|
|
86
|
+
query: options.query,
|
|
87
|
+
includeDirectories,
|
|
88
|
+
includeFiles,
|
|
89
|
+
})
|
|
90
|
+
: null;
|
|
91
|
+
if (exactEntry && limit <= 1) {
|
|
92
|
+
return [exactEntry];
|
|
93
|
+
}
|
|
74
94
|
if (queryParts.isPathQuery && matchMode !== "suffix") {
|
|
75
95
|
return searchWorkspaceWithinParentDirectory({
|
|
76
96
|
workspaceRoot,
|
|
@@ -84,7 +104,7 @@ export async function searchWorkspaceEntries(options) {
|
|
|
84
104
|
const searchTerm = matchMode === "suffix"
|
|
85
105
|
? [queryParts.parentPart, queryParts.searchTerm].filter(Boolean).join("/")
|
|
86
106
|
: queryParts.searchTerm;
|
|
87
|
-
|
|
107
|
+
const entries = await searchWorkspaceAcrossTree({
|
|
88
108
|
workspaceRoot,
|
|
89
109
|
searchTerm,
|
|
90
110
|
limit,
|
|
@@ -94,6 +114,53 @@ export async function searchWorkspaceEntries(options) {
|
|
|
94
114
|
maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,
|
|
95
115
|
maxEntriesScanned: options.maxEntriesScanned ?? DEFAULT_MAX_DIRECTORIES_SCANNED,
|
|
96
116
|
});
|
|
117
|
+
return exactEntry ? prependWorkspaceEntry(exactEntry, entries).slice(0, limit) : entries;
|
|
118
|
+
}
|
|
119
|
+
async function resolveWorkspaceExactEntry(input) {
|
|
120
|
+
const normalized = input.query
|
|
121
|
+
.trim()
|
|
122
|
+
.replace(/\\/g, "/")
|
|
123
|
+
.replace(/^\.\/+/, "")
|
|
124
|
+
.replace(/\/{2,}/g, "/");
|
|
125
|
+
if (!normalized) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const candidatePath = path.isAbsolute(normalized)
|
|
129
|
+
? path.resolve(normalized)
|
|
130
|
+
: path.resolve(input.workspaceRoot, normalized);
|
|
131
|
+
let resolvedPath;
|
|
132
|
+
try {
|
|
133
|
+
resolvedPath = await realpath(candidatePath);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
if (!isPathInsideRoot(input.workspaceRoot, resolvedPath)) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const stats = await stat(resolvedPath).catch(() => null);
|
|
142
|
+
if (!stats) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
if (stats.isFile() && input.includeFiles) {
|
|
146
|
+
return {
|
|
147
|
+
path: normalizeRelativePath(input.workspaceRoot, resolvedPath),
|
|
148
|
+
kind: "file",
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (stats.isDirectory() && input.includeDirectories) {
|
|
152
|
+
return {
|
|
153
|
+
path: normalizeRelativePath(input.workspaceRoot, resolvedPath),
|
|
154
|
+
kind: "directory",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
function prependWorkspaceEntry(entry, entries) {
|
|
160
|
+
return [
|
|
161
|
+
entry,
|
|
162
|
+
...entries.filter((candidate) => candidate.kind !== entry.kind || candidate.path !== entry.path),
|
|
163
|
+
];
|
|
97
164
|
}
|
|
98
165
|
function normalizeLimit(limit) {
|
|
99
166
|
const candidate = limit ?? DEFAULT_LIMIT;
|
|
@@ -185,6 +252,9 @@ async function searchWorkspaceWithinParentDirectory(input) {
|
|
|
185
252
|
if (entry.kind === "file" && !input.includeFiles) {
|
|
186
253
|
continue;
|
|
187
254
|
}
|
|
255
|
+
if (isHiddenWorkspaceSuggestion(entry)) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
188
258
|
const rankedEntry = rankWorkspaceEntry({
|
|
189
259
|
absolutePath: entry.absolutePath,
|
|
190
260
|
kind: entry.kind,
|
|
@@ -230,6 +300,10 @@ async function searchWorkspaceAcrossTree(input) {
|
|
|
230
300
|
if (entry.kind === "directory" && !input.includeDirectories) {
|
|
231
301
|
continue;
|
|
232
302
|
}
|
|
303
|
+
// Hidden directories are traversed, but not offered as suggestions.
|
|
304
|
+
if (isHiddenWorkspaceSuggestion(entry)) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
233
307
|
if (entry.kind === "file" && !input.includeFiles) {
|
|
234
308
|
continue;
|
|
235
309
|
}
|
|
@@ -618,7 +692,23 @@ async function listWorkspaceChildEntries(input) {
|
|
|
618
692
|
return cached.entries;
|
|
619
693
|
}
|
|
620
694
|
const dirents = await readdir(input.directory, { withFileTypes: true }).catch(() => []);
|
|
621
|
-
const candidates = dirents.filter((dirent) =>
|
|
695
|
+
const candidates = dirents.filter((dirent) => {
|
|
696
|
+
if (isIgnoredSuggestionDirectoryName(dirent.name)) {
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
if (isHiddenDirectoryName(dirent.name) &&
|
|
700
|
+
!dirent.isFile() &&
|
|
701
|
+
!isTraversableHiddenWorkspaceDirectoryName(dirent.name)) {
|
|
702
|
+
return false;
|
|
703
|
+
}
|
|
704
|
+
// Allowlisted hidden directories remain traversable so file links like
|
|
705
|
+
// `.claude/settings.local.json` can resolve, but hidden files (e.g.
|
|
706
|
+
// `.DS_Store`) should never be suggested.
|
|
707
|
+
if (dirent.isFile() && isHiddenDirectoryName(dirent.name)) {
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
710
|
+
return true;
|
|
711
|
+
});
|
|
622
712
|
const resolved = await Promise.all(candidates.map(async (dirent) => {
|
|
623
713
|
const candidatePath = path.join(input.directory, dirent.name);
|
|
624
714
|
const entry = await resolveWorkspaceCandidate({
|
|
@@ -687,9 +777,15 @@ async function resolveWorkspaceCandidate(input) {
|
|
|
687
777
|
function isHiddenDirectoryName(name) {
|
|
688
778
|
return name.startsWith(".");
|
|
689
779
|
}
|
|
780
|
+
function isHiddenWorkspaceSuggestion(entry) {
|
|
781
|
+
return isHiddenDirectoryName(entry.name);
|
|
782
|
+
}
|
|
690
783
|
function isIgnoredSuggestionDirectoryName(name) {
|
|
691
784
|
return IGNORED_SUGGESTION_DIRECTORY_NAMES.has(name);
|
|
692
785
|
}
|
|
786
|
+
function isTraversableHiddenWorkspaceDirectoryName(name) {
|
|
787
|
+
return TRAVERSABLE_HIDDEN_WORKSPACE_DIRECTORY_NAMES.has(name);
|
|
788
|
+
}
|
|
693
789
|
function setDirectoryListCache(cacheKey, entry) {
|
|
694
790
|
directoryListCache.set(cacheKey, entry);
|
|
695
791
|
pruneDirectoryListCache();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpaseo/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.99",
|
|
4
4
|
"description": "Paseo backend server",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/server",
|
|
@@ -65,10 +65,10 @@
|
|
|
65
65
|
"@agentclientprotocol/sdk": "^0.17.1",
|
|
66
66
|
"@anthropic-ai/claude-agent-sdk": "^0.3.181",
|
|
67
67
|
"@anthropic-ai/sdk": "^0.104.2",
|
|
68
|
-
"@getpaseo/client": "0.1.
|
|
69
|
-
"@getpaseo/highlight": "0.1.
|
|
70
|
-
"@getpaseo/protocol": "0.1.
|
|
71
|
-
"@getpaseo/relay": "0.1.
|
|
68
|
+
"@getpaseo/client": "0.1.99",
|
|
69
|
+
"@getpaseo/highlight": "0.1.99",
|
|
70
|
+
"@getpaseo/protocol": "0.1.99",
|
|
71
|
+
"@getpaseo/relay": "0.1.99",
|
|
72
72
|
"@isaacs/ttlcache": "^2.1.4",
|
|
73
73
|
"@modelcontextprotocol/sdk": "^1.20.1",
|
|
74
74
|
"@opencode-ai/sdk": "1.14.46",
|