@agimon-ai/po-git 0.0.0-alpha.7 → 0.0.0-alpha.70
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/LICENSE +149 -21
- package/README.md +16 -4
- package/dist/apiContracts.cjs +4 -1
- package/dist/apiContracts.cjs.map +1 -1
- package/dist/apiContracts.mjs +4 -1
- package/dist/apiContracts.mjs.map +1 -1
- package/dist/extensions/native.mjs +2163 -534
- package/dist/extensions/native.mjs.map +1 -1
- package/dist/extensions/server.cjs +293 -117
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +2 -2
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +290 -114
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +1443 -1292
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.mts +2 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{worktreeOperations-BSeyxUai.mjs → worktreeOperations-B3E4JY4H.mjs} +258 -85
- package/dist/worktreeOperations-B3E4JY4H.mjs.map +1 -0
- package/dist/{worktreeOperations-DGUbUnYU.cjs → worktreeOperations-CD7s0YnO.cjs} +288 -85
- package/dist/worktreeOperations-CD7s0YnO.cjs.map +1 -0
- package/llms.txt +1 -1
- package/package.json +21 -19
- package/src/prompts/{po-use-git → codemode-how-to-git}/SKILL.md +35 -32
- package/dist/worktreeOperations-BSeyxUai.mjs.map +0 -1
- package/dist/worktreeOperations-DGUbUnYU.cjs.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import os from "node:os";
|
|
1
|
+
import { C as READ_TIMEOUT_MS, E as runGit, S as NETWORK_TIMEOUT_MS, T as createWorktreeGit, a as GIT_WORKTREE_LIFECYCLE_EVENT, c as isWorktreeLifecycleEvent, d as registryFile, f as readJson, g as invalidRequest, h as PoGitExpectedError, i as GIT_SESSION_CHANGED_EVENT, l as credentialsFile, m as HubUnavailableError, n as createWorktreeRegistry, o as createWorktreeMessageInbox, p as writeJsonAtomic, r as validRefName, s as isSessionChangedEvent, t as createWorktreeOperations, u as poGitRoot, w as REBASE_TIMEOUT_MS } from "../worktreeOperations-B3E4JY4H.mjs";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
4
3
|
import path from "node:path";
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { composeServerProviderOverrides, defineServerPlugin, packageResourcePath, readPackageResource } from "@agimon-ai/po-core/serverPlugin";
|
|
6
|
+
import { composeRootHooks, composeRootInjects, defineChannel, defineHook, defineResource, defineRoot, defineRoute, defineServerTool } from "@agimon-ai/po-core/extensionFile";
|
|
7
|
+
import { PO_CODEMODE_SERVICE, readPoCodemode } from "@agimon-ai/po-core/codemode";
|
|
7
8
|
import { readPoSessionDelivery } from "@agimon-ai/po-session";
|
|
8
9
|
import { Type } from "typebox";
|
|
9
10
|
//#region src/schemas/runWorktreeTool.ts
|
|
@@ -247,7 +248,8 @@ async function executeRunWorktreeTool(params, operations, context, options = {})
|
|
|
247
248
|
content: text(describe(record, context.sessionId), `Session: ${record.sessionId}`, dirtyFiles.length === 0 ? "Clean." : `${String(dirtyFiles.length)} uncommitted file(s): ${dirtyFiles.slice(0, 20).join(", ")}`),
|
|
248
249
|
details: {
|
|
249
250
|
action: params.action,
|
|
250
|
-
records: [record]
|
|
251
|
+
records: [record],
|
|
252
|
+
dirtyFiles
|
|
251
253
|
}
|
|
252
254
|
};
|
|
253
255
|
}
|
|
@@ -271,7 +273,10 @@ async function executeRunWorktreeTool(params, operations, context, options = {})
|
|
|
271
273
|
const waiting = await operations.messages(context, params.id);
|
|
272
274
|
return {
|
|
273
275
|
content: waiting.length === 0 ? text("No messages.") : text(`${String(waiting.length)} message(s):`, ...waiting.map((entry) => `[${entry.sentAt}] ${entry.from}: ${entry.text}`)),
|
|
274
|
-
details: {
|
|
276
|
+
details: {
|
|
277
|
+
action: params.action,
|
|
278
|
+
messages: waiting
|
|
279
|
+
}
|
|
275
280
|
};
|
|
276
281
|
}
|
|
277
282
|
case WORKTREE_ACTIONS.prune: {
|
|
@@ -286,12 +291,172 @@ async function executeRunWorktreeTool(params, operations, context, options = {})
|
|
|
286
291
|
`Untracked directories, left alone: ${plan.untracked.length === 0 ? "none" : plan.untracked.join(", ")}`,
|
|
287
292
|
...plan.keptBranches.length === 0 ? [] : [`Branches kept, they hold commits: ${plan.keptBranches.join(", ")}`]
|
|
288
293
|
]),
|
|
289
|
-
details: {
|
|
294
|
+
details: {
|
|
295
|
+
action: params.action,
|
|
296
|
+
plan
|
|
297
|
+
}
|
|
290
298
|
};
|
|
291
299
|
}
|
|
292
300
|
}
|
|
293
301
|
}
|
|
294
302
|
//#endregion
|
|
303
|
+
//#region src/services/worktreeNamespace/index.ts
|
|
304
|
+
const DECLARATIONS = `type WorktreeStatus = 'spawning' | 'running' | 'closing' | 'orphaned';
|
|
305
|
+
|
|
306
|
+
interface Worktree {
|
|
307
|
+
id: string;
|
|
308
|
+
branch: string;
|
|
309
|
+
baseRef: string;
|
|
310
|
+
/** Absolute path of the checkout, under ~/.po/git/worktrees. */
|
|
311
|
+
path: string;
|
|
312
|
+
repositoryRoot: string;
|
|
313
|
+
/** The session running inside the worktree. */
|
|
314
|
+
sessionId: string;
|
|
315
|
+
parentSessionId?: string;
|
|
316
|
+
status: WorktreeStatus;
|
|
317
|
+
createdAt: string;
|
|
318
|
+
/** How your session relates to it: 'parent' spawned it, 'child' runs inside it, 'other' is neither. */
|
|
319
|
+
relationship: 'parent' | 'child' | 'other';
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
interface WorktreeMessage {
|
|
323
|
+
worktreeId: string;
|
|
324
|
+
fromSessionId: string;
|
|
325
|
+
from: 'parent' | 'child';
|
|
326
|
+
text: string;
|
|
327
|
+
sentAt: string;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
interface PrunePlan {
|
|
331
|
+
remove: Worktree[];
|
|
332
|
+
forget: Worktree[];
|
|
333
|
+
/** Kept because they hold uncommitted work. */
|
|
334
|
+
keptDirty: Worktree[];
|
|
335
|
+
untracked: string[];
|
|
336
|
+
/** Branches kept because they hold commits. */
|
|
337
|
+
keptBranches: string[];
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
declare const worktrees: {
|
|
341
|
+
/** Every worktree for this repository. */
|
|
342
|
+
list(): Promise<Worktree[]>;
|
|
343
|
+
/** One worktree and its uncommitted files. */
|
|
344
|
+
status(id: string): Promise<{ worktree: Worktree; dirtyFiles: string[] }>;
|
|
345
|
+
/**
|
|
346
|
+
* Create a worktree on a new branch and start a Po session in it, nested under this one. baseRef defaults to
|
|
347
|
+
* the current branch's remote-tracking ref, then the remote default branch; name labels it in the rail; task is
|
|
348
|
+
* the new session's first message. Setup can be slow, so give exec a larger timeoutMs.
|
|
349
|
+
*/
|
|
350
|
+
spawn(request: { branch: string; baseRef?: string; name?: string; task?: string }): Promise<Worktree>;
|
|
351
|
+
/** Stop the worktree's session and delete its checkout. Refused on a dirty tree unless force is true. */
|
|
352
|
+
close(id: string, options?: { force?: boolean }): Promise<Worktree>;
|
|
353
|
+
/** Merge the worktree's branch into this checkout. Refused when this checkout is dirty. */
|
|
354
|
+
merge(id: string, options?: { message?: string }): Promise<Worktree>;
|
|
355
|
+
/** Remove orphaned worktrees. With dryRun, only return the plan. */
|
|
356
|
+
prune(options?: { dryRun?: boolean }): Promise<PrunePlan>;
|
|
357
|
+
/**
|
|
358
|
+
* Message the other side of a worktree. Use the record with relationship 'child' to report to your parent,
|
|
359
|
+
* and 'parent' to reach your own children. 'other' records are not communication edges.
|
|
360
|
+
*/
|
|
361
|
+
send(id: string, message: string): Promise<void>;
|
|
362
|
+
/** Messages waiting for you from a worktree. */
|
|
363
|
+
messages(id: string): Promise<WorktreeMessage[]>;
|
|
364
|
+
};`;
|
|
365
|
+
const json = (value) => JSON.parse(JSON.stringify(value));
|
|
366
|
+
/** Git worktrees for code mode: the actions of `run_worktree` as methods, returning records instead of text. */
|
|
367
|
+
function createWorktreeNamespace(options) {
|
|
368
|
+
return {
|
|
369
|
+
name: "worktrees",
|
|
370
|
+
summary: "Git worktrees, each with its own Po session nested under this one: worktrees.list, status, spawn, close, merge, prune, send and messages.",
|
|
371
|
+
declarations: DECLARATIONS,
|
|
372
|
+
bind(run) {
|
|
373
|
+
if (run.sessionId !== options.execution.sessionId) throw new Error("Worktrees namespace belongs to another session.");
|
|
374
|
+
let disposed = false;
|
|
375
|
+
run.onDispose(() => {
|
|
376
|
+
disposed = true;
|
|
377
|
+
});
|
|
378
|
+
const view = (record) => ({
|
|
379
|
+
...record,
|
|
380
|
+
relationship: record.parentSessionId === options.execution.sessionId ? "parent" : record.sessionId === options.execution.sessionId ? "child" : "other"
|
|
381
|
+
});
|
|
382
|
+
/** One `run_worktree` action through the tool's own code, so the tool and the namespace cannot drift. */
|
|
383
|
+
const act = async (name, action, input) => {
|
|
384
|
+
run.signal.throwIfAborted();
|
|
385
|
+
if (disposed) throw new Error("Worktrees namespace run is disposed.");
|
|
386
|
+
options.assertAvailable();
|
|
387
|
+
const params = validateParams({
|
|
388
|
+
action,
|
|
389
|
+
...typeof input === "object" && input !== null ? input : {}
|
|
390
|
+
});
|
|
391
|
+
const context = {
|
|
392
|
+
cwd: options.execution.cwd,
|
|
393
|
+
sessionId: options.execution.sessionId
|
|
394
|
+
};
|
|
395
|
+
const started = Date.now();
|
|
396
|
+
try {
|
|
397
|
+
const result = await executeRunWorktreeTool(params, options.operations, context, { signal: run.signal });
|
|
398
|
+
options.assertAvailable();
|
|
399
|
+
run.record?.({
|
|
400
|
+
name: `worktrees.${name}`,
|
|
401
|
+
tool: RUN_WORKTREE_TOOL_NAME,
|
|
402
|
+
args: params,
|
|
403
|
+
ok: true,
|
|
404
|
+
ms: Date.now() - started,
|
|
405
|
+
result
|
|
406
|
+
});
|
|
407
|
+
return result;
|
|
408
|
+
} catch (error) {
|
|
409
|
+
run.record?.({
|
|
410
|
+
name: `worktrees.${name}`,
|
|
411
|
+
tool: RUN_WORKTREE_TOOL_NAME,
|
|
412
|
+
args: params,
|
|
413
|
+
ok: false,
|
|
414
|
+
ms: Date.now() - started,
|
|
415
|
+
error: error instanceof Error ? error.message : String(error)
|
|
416
|
+
});
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
const record = (result) => view(result.details.records[0]);
|
|
421
|
+
const members = Object.create(null);
|
|
422
|
+
members.list = async () => json((await act("list", "list", {})).details.records.map(view));
|
|
423
|
+
members.status = async (id) => {
|
|
424
|
+
const { details } = await act("status", "status", { id });
|
|
425
|
+
return json({
|
|
426
|
+
worktree: view(details.records[0]),
|
|
427
|
+
dirtyFiles: details.dirtyFiles ?? []
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
members.spawn = async (request) => json(record(await act("spawn", "spawn_worktree", request)));
|
|
431
|
+
members.close = async (id, settings) => json(record(await act("close", "close_worktree", {
|
|
432
|
+
...settings,
|
|
433
|
+
id
|
|
434
|
+
})));
|
|
435
|
+
members.merge = async (id, settings) => json(record(await act("merge", "merge", {
|
|
436
|
+
...settings,
|
|
437
|
+
id
|
|
438
|
+
})));
|
|
439
|
+
members.prune = async (settings) => {
|
|
440
|
+
const { plan } = (await act("prune", "prune", settings)).details;
|
|
441
|
+
return json({
|
|
442
|
+
...plan,
|
|
443
|
+
remove: plan.remove.map(view),
|
|
444
|
+
forget: plan.forget.map(view),
|
|
445
|
+
keptDirty: plan.keptDirty.map(view)
|
|
446
|
+
});
|
|
447
|
+
};
|
|
448
|
+
members.send = async (id, message) => {
|
|
449
|
+
await act("send", "send", {
|
|
450
|
+
id,
|
|
451
|
+
message
|
|
452
|
+
});
|
|
453
|
+
};
|
|
454
|
+
members.messages = async (id) => json((await act("messages", "messages", { id })).details.messages);
|
|
455
|
+
return members;
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
//#endregion
|
|
295
460
|
//#region src/extensions/workspaces/sessions/(backend)/_lib/root.server.ts
|
|
296
461
|
function progressResult(action, label) {
|
|
297
462
|
return {
|
|
@@ -302,9 +467,9 @@ function progressResult(action, label) {
|
|
|
302
467
|
details: { action }
|
|
303
468
|
};
|
|
304
469
|
}
|
|
305
|
-
function createGitSession({ context, host: serverHost }) {
|
|
306
|
-
if (serverHost.context.directEvents === void 0) throw new Error("Git
|
|
307
|
-
if (serverHost.context.sessionId === void 0) throw new Error("Git
|
|
470
|
+
function createGitSession({ context, host: serverHost, agent, signal }) {
|
|
471
|
+
if (serverHost.context.directEvents === void 0) throw new Error("Git server plugin requires the session direct event bus.");
|
|
472
|
+
if (serverHost.context.sessionId === void 0) throw new Error("Git server plugin requires a session identity.");
|
|
308
473
|
const sessionId = serverHost.context.sessionId;
|
|
309
474
|
const directEvents = serverHost.context.directEvents;
|
|
310
475
|
const messageInbox = createWorktreeMessageInbox(directEvents, sessionId);
|
|
@@ -315,20 +480,12 @@ function createGitSession({ context, host: serverHost }) {
|
|
|
315
480
|
sessionDelivery: () => readPoSessionDelivery(context)
|
|
316
481
|
});
|
|
317
482
|
const resources = [{
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
attribution: {
|
|
321
|
-
kind: "minor",
|
|
322
|
-
mode: "help"
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
name: "po-git",
|
|
326
|
-
kind: "context",
|
|
327
|
-
read: () => readPackageResource(import.meta.url, "llms.txt")
|
|
328
|
-
}, {
|
|
329
|
-
name: "po-use-git",
|
|
483
|
+
name: "codemode-how-to-git",
|
|
484
|
+
description: "Hand a branch of work to a separate session in its own checkout, keeping the current checkout untouched. Use for a long refactor, a risky migration, or parallel features that touch the same files; not for parallel work on one branch.",
|
|
330
485
|
kind: "skill",
|
|
331
|
-
|
|
486
|
+
pinned: true,
|
|
487
|
+
path: packageResourcePath(import.meta.url, "src/prompts/codemode-how-to-git/SKILL.md"),
|
|
488
|
+
read: () => readPackageResource(import.meta.url, "src/prompts/codemode-how-to-git/SKILL.md")
|
|
332
489
|
}];
|
|
333
490
|
const tool = {
|
|
334
491
|
name: RUN_WORKTREE_TOOL_NAME,
|
|
@@ -348,17 +505,37 @@ function createGitSession({ context, host: serverHost }) {
|
|
|
348
505
|
const changed = (_event, execution) => {
|
|
349
506
|
directEvents.publish(GIT_SESSION_CHANGED_EVENT, execution.sessionId, { version: 1 });
|
|
350
507
|
};
|
|
508
|
+
const hooks = [{
|
|
509
|
+
event: "tool_execution_end",
|
|
510
|
+
handle: changed
|
|
511
|
+
}, {
|
|
512
|
+
event: "agent_settled",
|
|
513
|
+
handle: changed
|
|
514
|
+
}];
|
|
515
|
+
if (agent) {
|
|
516
|
+
const namespace = createWorktreeNamespace({
|
|
517
|
+
operations,
|
|
518
|
+
execution: agent.context,
|
|
519
|
+
assertAvailable: () => {
|
|
520
|
+
if (signal?.aborted) throw new Error("Git session is unavailable.");
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
context.inject([PO_CODEMODE_SERVICE], (scoped) => {
|
|
524
|
+
const codemode = readPoCodemode(scoped);
|
|
525
|
+
if (!codemode) return void 0;
|
|
526
|
+
const registration = codemode.register("@agimon-ai/po-git", namespace);
|
|
527
|
+
const restriction = agent.registerToolRestriction({ excludedTools: [RUN_WORKTREE_TOOL_NAME] });
|
|
528
|
+
return () => {
|
|
529
|
+
restriction.dispose();
|
|
530
|
+
registration.dispose();
|
|
531
|
+
};
|
|
532
|
+
});
|
|
533
|
+
}
|
|
351
534
|
return {
|
|
352
535
|
value: {
|
|
353
536
|
resources,
|
|
354
537
|
tool,
|
|
355
|
-
hooks
|
|
356
|
-
event: "tool_execution_end",
|
|
357
|
-
handle: changed
|
|
358
|
-
}, {
|
|
359
|
-
event: "agent_settled",
|
|
360
|
-
handle: changed
|
|
361
|
-
}]
|
|
538
|
+
hooks
|
|
362
539
|
},
|
|
363
540
|
onDispose: () => messageInbox.close()
|
|
364
541
|
};
|
|
@@ -469,11 +646,11 @@ const NAME_STATUS = {
|
|
|
469
646
|
T: "modified"
|
|
470
647
|
};
|
|
471
648
|
/** Line count of a small regular file, or undefined when it is binary, large, or not a regular file. */
|
|
472
|
-
function untrackedLines(root, relPath) {
|
|
649
|
+
async function untrackedLines(root, relPath) {
|
|
473
650
|
const absolute = path.join(root, relPath);
|
|
474
651
|
let stat;
|
|
475
652
|
try {
|
|
476
|
-
stat = fs.
|
|
653
|
+
stat = await fs.lstat(absolute);
|
|
477
654
|
} catch {
|
|
478
655
|
return;
|
|
479
656
|
}
|
|
@@ -482,7 +659,7 @@ function untrackedLines(root, relPath) {
|
|
|
482
659
|
binary: false
|
|
483
660
|
};
|
|
484
661
|
if (!stat.isFile() || stat.size > MAX_FILE_BYTES) return void 0;
|
|
485
|
-
const content = fs.
|
|
662
|
+
const content = await fs.readFile(absolute);
|
|
486
663
|
if (content.subarray(0, BINARY_PROBE_BYTES).includes(0)) return {
|
|
487
664
|
lines: 0,
|
|
488
665
|
binary: true
|
|
@@ -605,8 +782,8 @@ function createBranchDiff() {
|
|
|
605
782
|
"--exclude-standard",
|
|
606
783
|
"-z"
|
|
607
784
|
]));
|
|
608
|
-
untracked.
|
|
609
|
-
const counted = index < MAX_UNTRACKED_COUNTED ? untrackedLines(root, relPath) : void 0;
|
|
785
|
+
for (const [index, relPath] of untracked.entries()) {
|
|
786
|
+
const counted = index < MAX_UNTRACKED_COUNTED ? await untrackedLines(root, relPath) : void 0;
|
|
610
787
|
entries.push({
|
|
611
788
|
path: relPath,
|
|
612
789
|
status: "untracked",
|
|
@@ -614,18 +791,20 @@ function createBranchDiff() {
|
|
|
614
791
|
removed: 0,
|
|
615
792
|
...counted?.binary ? { binary: true } : {}
|
|
616
793
|
});
|
|
617
|
-
}
|
|
794
|
+
}
|
|
618
795
|
entries.sort((left, right) => left.path.localeCompare(right.path));
|
|
619
796
|
const conflicts = [...unmerged];
|
|
620
|
-
const
|
|
797
|
+
const rebaseMerge = await readLine$1(root, [
|
|
621
798
|
"rev-parse",
|
|
622
799
|
"--git-path",
|
|
623
800
|
"rebase-merge"
|
|
624
|
-
])
|
|
801
|
+
]);
|
|
802
|
+
const rebaseApply = await readLine$1(root, [
|
|
625
803
|
"rev-parse",
|
|
626
804
|
"--git-path",
|
|
627
805
|
"rebase-apply"
|
|
628
|
-
])
|
|
806
|
+
]);
|
|
807
|
+
const rebasing = (await Promise.all([rebaseMerge, rebaseApply].map(async (gitPath) => gitPath === void 0 ? false : fs.access(path.resolve(root, gitPath)).then(() => true, () => false)))).some(Boolean);
|
|
629
808
|
const upstreamRef = branch === void 0 ? void 0 : await upstreamOf(root, branch);
|
|
630
809
|
let upstream;
|
|
631
810
|
if (upstreamRef !== void 0) {
|
|
@@ -670,7 +849,7 @@ function createBranchDiff() {
|
|
|
670
849
|
if (entry === void 0) throw new Error("That path is not in this review.");
|
|
671
850
|
if (entry.status === "untracked") {
|
|
672
851
|
const absolute = path.join(review.root, entry.path);
|
|
673
|
-
const stat = fs.
|
|
852
|
+
const stat = await fs.lstat(absolute);
|
|
674
853
|
if (stat.isSymbolicLink()) return {
|
|
675
854
|
path: entry.path,
|
|
676
855
|
hunks: [{
|
|
@@ -678,7 +857,7 @@ function createBranchDiff() {
|
|
|
678
857
|
rows: [{
|
|
679
858
|
marker: "+",
|
|
680
859
|
line: 1,
|
|
681
|
-
content: fs.
|
|
860
|
+
content: await fs.readlink(absolute)
|
|
682
861
|
}]
|
|
683
862
|
}]
|
|
684
863
|
};
|
|
@@ -687,7 +866,7 @@ function createBranchDiff() {
|
|
|
687
866
|
hunks: [],
|
|
688
867
|
tooLarge: true
|
|
689
868
|
};
|
|
690
|
-
const content = fs.
|
|
869
|
+
const content = await fs.readFile(absolute);
|
|
691
870
|
if (content.subarray(0, BINARY_PROBE_BYTES).includes(0)) return {
|
|
692
871
|
path: entry.path,
|
|
693
872
|
hunks: [],
|
|
@@ -804,9 +983,9 @@ function isRecord(value) {
|
|
|
804
983
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
805
984
|
}
|
|
806
985
|
/** The workspace key: the canonical root, so a symlinked path and its target share one entry. */
|
|
807
|
-
function workspaceKey(workspaceRoot) {
|
|
986
|
+
async function workspaceKey(workspaceRoot) {
|
|
808
987
|
try {
|
|
809
|
-
return fs.
|
|
988
|
+
return await fs.realpath(workspaceRoot);
|
|
810
989
|
} catch {
|
|
811
990
|
return path.resolve(workspaceRoot);
|
|
812
991
|
}
|
|
@@ -855,7 +1034,7 @@ function publicView(config) {
|
|
|
855
1034
|
* the saved one, and only for the same host: a token never follows a host it
|
|
856
1035
|
* was not entered for.
|
|
857
1036
|
*/
|
|
858
|
-
function parseGitAuthSave(request, current, homeDir) {
|
|
1037
|
+
async function parseGitAuthSave(request, current, homeDir) {
|
|
859
1038
|
if (!isRecord(request)) throw invalidRequest("The git auth request is not an object.", "Send method none, ssh or https.");
|
|
860
1039
|
if (request.method === "none") return { method: "none" };
|
|
861
1040
|
if (request.method === "ssh") {
|
|
@@ -865,7 +1044,7 @@ function parseGitAuthSave(request, current, homeDir) {
|
|
|
865
1044
|
if (!keyPath.startsWith("/") && !keyPath.startsWith("~/")) throw invalidRequest("The key path is not absolute.", "Give the key as an absolute path or one under ~/.");
|
|
866
1045
|
let isFile = false;
|
|
867
1046
|
try {
|
|
868
|
-
isFile = fs.
|
|
1047
|
+
isFile = (await fs.stat(expandHome(keyPath, homeDir))).isFile();
|
|
869
1048
|
} catch {
|
|
870
1049
|
isFile = false;
|
|
871
1050
|
}
|
|
@@ -900,16 +1079,16 @@ function parseGitAuthSave(request, current, homeDir) {
|
|
|
900
1079
|
throw invalidRequest("The git auth method is unknown.", "Send method none, ssh or https.");
|
|
901
1080
|
}
|
|
902
1081
|
/** Tightens a file or folder something left readable by group or others. */
|
|
903
|
-
function tighten(target, mode) {
|
|
1082
|
+
async function tighten(target, mode) {
|
|
904
1083
|
try {
|
|
905
|
-
if ((fs.
|
|
1084
|
+
if (((await fs.stat(target)).mode & LOOSE_BITS) !== 0) await fs.chmod(target, mode);
|
|
906
1085
|
} catch {}
|
|
907
1086
|
}
|
|
908
1087
|
function createGitAuthStore(homeDir = os.homedir()) {
|
|
909
1088
|
const file = credentialsFile(homeDir);
|
|
910
|
-
const readFile = () => {
|
|
911
|
-
tighten(file, OWNER_ONLY_FILE);
|
|
912
|
-
const raw = readJson(file);
|
|
1089
|
+
const readFile = async () => {
|
|
1090
|
+
await tighten(file, OWNER_ONLY_FILE);
|
|
1091
|
+
const raw = await readJson(file);
|
|
913
1092
|
const workspaces = {};
|
|
914
1093
|
if (isRecord(raw) && raw.version === 1 && isRecord(raw.workspaces)) for (const [key, value] of Object.entries(raw.workspaces)) {
|
|
915
1094
|
const config = parseConfig(value);
|
|
@@ -920,28 +1099,28 @@ function createGitAuthStore(homeDir = os.homedir()) {
|
|
|
920
1099
|
workspaces
|
|
921
1100
|
};
|
|
922
1101
|
};
|
|
923
|
-
const read = (workspaceRoot) => readFile().workspaces[workspaceKey(workspaceRoot)] ?? { method: "none" };
|
|
1102
|
+
const read = async (workspaceRoot) => (await readFile()).workspaces[await workspaceKey(workspaceRoot)] ?? { method: "none" };
|
|
924
1103
|
return {
|
|
925
1104
|
read,
|
|
926
|
-
view: (workspaceRoot) => publicView(read(workspaceRoot)),
|
|
927
|
-
save(workspaceRoot, request) {
|
|
928
|
-
const key = workspaceKey(workspaceRoot);
|
|
929
|
-
const current = readFile();
|
|
930
|
-
const next = parseGitAuthSave(request, current.workspaces[key] ?? { method: "none" }, homeDir);
|
|
1105
|
+
view: async (workspaceRoot) => publicView(await read(workspaceRoot)),
|
|
1106
|
+
async save(workspaceRoot, request) {
|
|
1107
|
+
const key = await workspaceKey(workspaceRoot);
|
|
1108
|
+
const current = await readFile();
|
|
1109
|
+
const next = await parseGitAuthSave(request, current.workspaces[key] ?? { method: "none" }, homeDir);
|
|
931
1110
|
const root = poGitRoot(homeDir);
|
|
932
|
-
fs.
|
|
1111
|
+
await fs.mkdir(root, {
|
|
933
1112
|
recursive: true,
|
|
934
1113
|
mode: OWNER_ONLY_DIRECTORY
|
|
935
1114
|
});
|
|
936
|
-
fs.
|
|
1115
|
+
await fs.chmod(root, OWNER_ONLY_DIRECTORY);
|
|
937
1116
|
const workspaces = { ...current.workspaces };
|
|
938
1117
|
if (next.method === "none") delete workspaces[key];
|
|
939
1118
|
else workspaces[key] = next;
|
|
940
|
-
writeJsonAtomic(file, {
|
|
1119
|
+
await writeJsonAtomic(file, {
|
|
941
1120
|
version: 1,
|
|
942
1121
|
workspaces
|
|
943
1122
|
});
|
|
944
|
-
fs.
|
|
1123
|
+
await fs.chmod(file, OWNER_ONLY_FILE);
|
|
945
1124
|
return publicView(next);
|
|
946
1125
|
}
|
|
947
1126
|
};
|
|
@@ -1187,9 +1366,9 @@ var route_server_default = defineRoute({
|
|
|
1187
1366
|
if (request.method !== "GET" && request.method !== "PUT") return Response.json({ error: "Use GET or PUT." }, { status: 405 });
|
|
1188
1367
|
const root = rootOf(url);
|
|
1189
1368
|
if (root instanceof Response) return root;
|
|
1190
|
-
if (request.method === "GET") return Response.json(gitAuth.view(root));
|
|
1369
|
+
if (request.method === "GET") return Response.json(await gitAuth.view(root));
|
|
1191
1370
|
try {
|
|
1192
|
-
return Response.json(gitAuth.save(root, await request.json().catch(() => void 0)));
|
|
1371
|
+
return Response.json(await gitAuth.save(root, await request.json().catch(() => void 0)));
|
|
1193
1372
|
} catch (error) {
|
|
1194
1373
|
if (error instanceof PoGitExpectedError && error.code === "invalid_request") {
|
|
1195
1374
|
const text = error.message.replace(/^\[[a-z_]+\] /u, "").replace("\nRecovery: ", " ");
|
|
@@ -1213,7 +1392,7 @@ var route_server_default = defineRoute({
|
|
|
1213
1392
|
if (request.method !== "GET") return Response.json({ error: "Use GET." }, { status: 405 });
|
|
1214
1393
|
let recordedBaseRef;
|
|
1215
1394
|
try {
|
|
1216
|
-
recordedBaseRef = createWorktreeRegistry(registryFile(cwd, homeDir)).list().find((record) => record.sessionId === context.sessionId)?.baseRef;
|
|
1395
|
+
recordedBaseRef = (await createWorktreeRegistry(await registryFile(cwd, homeDir)).list()).find((record) => record.sessionId === context.sessionId)?.baseRef;
|
|
1217
1396
|
} catch {
|
|
1218
1397
|
recordedBaseRef = void 0;
|
|
1219
1398
|
}
|
|
@@ -1413,7 +1592,7 @@ async function rebasing(root) {
|
|
|
1413
1592
|
"--git-path",
|
|
1414
1593
|
name
|
|
1415
1594
|
]);
|
|
1416
|
-
if (gitPath !== void 0 && fs.
|
|
1595
|
+
if (gitPath !== void 0 && await fs.access(path.resolve(root, gitPath)).then(() => true, () => false)) return true;
|
|
1417
1596
|
}
|
|
1418
1597
|
return false;
|
|
1419
1598
|
}
|
|
@@ -1583,9 +1762,9 @@ const GIT_CHANGES_TYPE = "git_changes";
|
|
|
1583
1762
|
* DESIGN PATTERNS:
|
|
1584
1763
|
* - Apart from the worktrees channel. Worktrees are repository management;
|
|
1585
1764
|
* this is the session's own code change.
|
|
1586
|
-
* - Push, not poll. The session
|
|
1587
|
-
* tool call and settled turn; recounts are coalesced to one in
|
|
1588
|
-
* one rerun, so a burst of tool calls costs at most two.
|
|
1765
|
+
* - Push, not poll. The session's server plugin publishes a "changed" event
|
|
1766
|
+
* after every tool call and settled turn; recounts are coalesced to one in
|
|
1767
|
+
* flight plus one rerun, so a burst of tool calls costs at most two.
|
|
1589
1768
|
* - One sync command per session. A rebase and a push must never overlap.
|
|
1590
1769
|
* - Auth is read fresh for each command from the session's workspace, and goes
|
|
1591
1770
|
* only into that command's git child.
|
|
@@ -1646,9 +1825,9 @@ function createGitChangesChannel(options = {}) {
|
|
|
1646
1825
|
const rerun = /* @__PURE__ */ new Set();
|
|
1647
1826
|
const busy = /* @__PURE__ */ new Set();
|
|
1648
1827
|
/** The base the session's own worktree was created from, when it has one. */
|
|
1649
|
-
const recordedBaseRef = (scope) => {
|
|
1828
|
+
const recordedBaseRef = async (scope) => {
|
|
1650
1829
|
try {
|
|
1651
|
-
return createWorktreeRegistry(registryFile(scope.cwd, homeDir)).list().find((record) => record.sessionId === scope.sessionId)?.baseRef;
|
|
1830
|
+
return (await createWorktreeRegistry(await registryFile(scope.cwd, homeDir)).list()).find((record) => record.sessionId === scope.sessionId)?.baseRef;
|
|
1652
1831
|
} catch {
|
|
1653
1832
|
return;
|
|
1654
1833
|
}
|
|
@@ -1681,8 +1860,7 @@ function createGitChangesChannel(options = {}) {
|
|
|
1681
1860
|
return;
|
|
1682
1861
|
}
|
|
1683
1862
|
inFlight.add(sessionId);
|
|
1684
|
-
|
|
1685
|
-
diff.review(scope.cwd, base === void 0 ? {} : { recordedBaseRef: base }).then((review) => {
|
|
1863
|
+
recordedBaseRef(scope).then((base) => diff.review(scope.cwd, base === void 0 ? {} : { recordedBaseRef: base })).then((review) => {
|
|
1686
1864
|
if (scopes.has(sessionId)) update(sessionId, { changes: review?.changes });
|
|
1687
1865
|
}).catch((error) => {
|
|
1688
1866
|
host.onNotice(`git diff refresh failed for ${sessionId} (${error instanceof Error ? error.name : "unknown"})`);
|
|
@@ -1691,12 +1869,12 @@ function createGitChangesChannel(options = {}) {
|
|
|
1691
1869
|
if (rerun.delete(sessionId)) refresh(sessionId);
|
|
1692
1870
|
});
|
|
1693
1871
|
};
|
|
1694
|
-
const run = (scope, command) => {
|
|
1872
|
+
const run = async (scope, command) => {
|
|
1695
1873
|
const workspaceRoot = scope.sessionContext?.workspaceRoot ?? scope.cwd;
|
|
1696
|
-
const base = recordedBaseRef(scope);
|
|
1874
|
+
const base = await recordedBaseRef(scope);
|
|
1697
1875
|
const context = {
|
|
1698
1876
|
cwd: scope.cwd,
|
|
1699
|
-
auth: auth.read(workspaceRoot),
|
|
1877
|
+
auth: await auth.read(workspaceRoot),
|
|
1700
1878
|
...base === void 0 ? {} : { recordedBaseRef: base }
|
|
1701
1879
|
};
|
|
1702
1880
|
if (command.action === "pull") return sync.pull(context);
|
|
@@ -1794,9 +1972,9 @@ function payloadOf(state) {
|
|
|
1794
1972
|
};
|
|
1795
1973
|
}
|
|
1796
1974
|
/** Worktrees visible to this session, using the hub's live session table for ownership. */
|
|
1797
|
-
function viewsFor(scope, deps) {
|
|
1975
|
+
async function viewsFor(scope, deps) {
|
|
1798
1976
|
try {
|
|
1799
|
-
return createWorktreeRegistry(registryFile(scope.cwd, deps.homeDir)).list().flatMap((record) => {
|
|
1977
|
+
return (await createWorktreeRegistry(await registryFile(scope.cwd, deps.homeDir)).list()).flatMap((record) => {
|
|
1800
1978
|
if (record.parentSessionId === void 0 && record.sessionId !== scope.sessionId) return [];
|
|
1801
1979
|
const owned = record.parentSessionId === void 0 || record.parentSessionId === scope.sessionId;
|
|
1802
1980
|
const unowned = !owned && !deps.sessionService.isLive(record.parentSessionId);
|
|
@@ -1821,11 +1999,15 @@ function sameList(left, right) {
|
|
|
1821
1999
|
return other !== void 0 && entry.id === other.id && entry.branch === other.branch && entry.sessionId === other.sessionId && entry.orphaned === other.orphaned && entry.unowned === other.unowned;
|
|
1822
2000
|
});
|
|
1823
2001
|
}
|
|
1824
|
-
function errorTargetFor(command) {
|
|
1825
|
-
|
|
2002
|
+
function errorTargetFor(command, error) {
|
|
2003
|
+
if (command.action === "close") return {
|
|
1826
2004
|
action: "close",
|
|
1827
2005
|
id: command.id
|
|
1828
2006
|
};
|
|
2007
|
+
return error instanceof PoGitExpectedError && error.code === "rift_missing" ? {
|
|
2008
|
+
action: "create",
|
|
2009
|
+
riftMissing: true
|
|
2010
|
+
} : { action: "create" };
|
|
1829
2011
|
}
|
|
1830
2012
|
/** A command the page sent, or undefined when the frame was not one. */
|
|
1831
2013
|
function parseCommand(payload) {
|
|
@@ -1853,11 +2035,15 @@ function parseCommand(payload) {
|
|
|
1853
2035
|
/**
|
|
1854
2036
|
* What the reader is told when a command fails.
|
|
1855
2037
|
*
|
|
1856
|
-
* An expected failure explains itself
|
|
1857
|
-
*
|
|
2038
|
+
* An expected failure explains itself, minus the `[code]` tag and recovery line
|
|
2039
|
+
* written for the agent's tool result. A dirty close is said in the person's
|
|
2040
|
+
* terms, because its message tells the agent to pass `force`. Anything else is
|
|
2041
|
+
* summarised, never echoed: a git error can carry a remote URL with a token in it.
|
|
1858
2042
|
*/
|
|
1859
2043
|
function failureText(error) {
|
|
1860
|
-
|
|
2044
|
+
if (!(error instanceof PoGitExpectedError)) return "The worktree operation failed.";
|
|
2045
|
+
if (error.code === "worktree_dirty") return "The worktree has uncommitted changes.";
|
|
2046
|
+
return error.message.replace(/^\[[a-z_]+\] /u, "").split("\nRecovery:")[0] ?? error.message;
|
|
1861
2047
|
}
|
|
1862
2048
|
/** Starts one direct-event subscription per managed session. */
|
|
1863
2049
|
function createWorktreesChannel(options = {}) {
|
|
@@ -1910,10 +2096,13 @@ function createWorktreesChannel(options = {}) {
|
|
|
1910
2096
|
return generation;
|
|
1911
2097
|
};
|
|
1912
2098
|
/** Republishes a session, skipping a frame that would say nothing new. */
|
|
1913
|
-
const publish = (scope, force) => {
|
|
2099
|
+
const publish = async (scope, force) => {
|
|
2100
|
+
const generation = generations.get(scope.sessionId);
|
|
2101
|
+
const worktreeViews = await viewsFor(scope, views);
|
|
2102
|
+
if (generation === void 0 || generations.get(scope.sessionId) !== generation) return;
|
|
1914
2103
|
const previous = latest.get(scope.sessionId);
|
|
1915
2104
|
const next = {
|
|
1916
|
-
worktrees:
|
|
2105
|
+
worktrees: worktreeViews,
|
|
1917
2106
|
pending: previous?.pending,
|
|
1918
2107
|
error: previous?.error,
|
|
1919
2108
|
errorTarget: previous?.errorTarget
|
|
@@ -1925,7 +2114,7 @@ function createWorktreesChannel(options = {}) {
|
|
|
1925
2114
|
const mark = (scope, pending, error, errorTarget) => {
|
|
1926
2115
|
const previous = latest.get(scope.sessionId);
|
|
1927
2116
|
latest.set(scope.sessionId, {
|
|
1928
|
-
worktrees: previous?.worktrees ??
|
|
2117
|
+
worktrees: previous?.worktrees ?? [],
|
|
1929
2118
|
pending,
|
|
1930
2119
|
error,
|
|
1931
2120
|
errorTarget
|
|
@@ -1965,15 +2154,15 @@ function createWorktreesChannel(options = {}) {
|
|
|
1965
2154
|
sessionAdded(scope) {
|
|
1966
2155
|
newGeneration(scope.sessionId);
|
|
1967
2156
|
publish(scope, false);
|
|
1968
|
-
const unsubscribe = host.directEvents.subscribe(GIT_WORKTREE_LIFECYCLE_EVENT, scope.sessionId, (payload) => {
|
|
2157
|
+
const unsubscribe = host.directEvents.subscribe(GIT_WORKTREE_LIFECYCLE_EVENT, scope.sessionId, async (payload) => {
|
|
1969
2158
|
if (!isWorktreeLifecycleEvent(payload)) return;
|
|
1970
2159
|
let sameRepository = false;
|
|
1971
2160
|
try {
|
|
1972
|
-
sameRepository = registryFile(scope.cwd, options.homeDir) === registryFile(payload.repositoryRoot, options.homeDir);
|
|
2161
|
+
sameRepository = await registryFile(scope.cwd, options.homeDir) === await registryFile(payload.repositoryRoot, options.homeDir);
|
|
1973
2162
|
} catch {
|
|
1974
2163
|
sameRepository = false;
|
|
1975
2164
|
}
|
|
1976
|
-
if (sameRepository) publish(scope, false);
|
|
2165
|
+
if (sameRepository) await publish(scope, false);
|
|
1977
2166
|
});
|
|
1978
2167
|
subscriptions.set(scope.sessionId, unsubscribe);
|
|
1979
2168
|
},
|
|
@@ -2006,7 +2195,7 @@ function createWorktreesChannel(options = {}) {
|
|
|
2006
2195
|
}).catch((error) => {
|
|
2007
2196
|
if (generations.get(scope.sessionId) !== generation) return;
|
|
2008
2197
|
host.onNotice(`worktree command failed for ${scope.sessionId} (${failureText(error)})`);
|
|
2009
|
-
mark(scope, void 0, failureText(error), errorTargetFor(command));
|
|
2198
|
+
mark(scope, void 0, failureText(error), errorTargetFor(command, error));
|
|
2010
2199
|
}).finally(() => {
|
|
2011
2200
|
if (generations.get(scope.sessionId) === generation) busy.delete(scope.sessionId);
|
|
2012
2201
|
});
|
|
@@ -2028,20 +2217,8 @@ var agent_settled_server_default = defineHook((context) => context.root.hooks[1]
|
|
|
2028
2217
|
//#region src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.ts
|
|
2029
2218
|
var tool_execution_end_server_default = defineHook((context) => context.root.hooks[0]);
|
|
2030
2219
|
//#endregion
|
|
2031
|
-
//#region src/extensions/workspaces/sessions/(backend)/resource/_lib/poGit.server.ts
|
|
2032
|
-
var poGit_server_default$1 = (context) => context.root.resources[0];
|
|
2033
|
-
//#endregion
|
|
2034
|
-
//#region src/extensions/workspaces/sessions/(backend)/resource/poGit.server.ts
|
|
2035
|
-
var poGit_server_default = defineResource(poGit_server_default$1);
|
|
2036
|
-
//#endregion
|
|
2037
|
-
//#region src/extensions/workspaces/sessions/(backend)/resource/_lib/poGitReadme.server.ts
|
|
2038
|
-
var poGitReadme_server_default$1 = (context) => context.root.resources[2];
|
|
2039
|
-
//#endregion
|
|
2040
|
-
//#region src/extensions/workspaces/sessions/(backend)/resource/poGitReadme.server.ts
|
|
2041
|
-
var poGitReadme_server_default = defineResource(poGitReadme_server_default$1);
|
|
2042
|
-
//#endregion
|
|
2043
2220
|
//#region src/extensions/workspaces/sessions/(backend)/resource/_lib/poUseGit.server.ts
|
|
2044
|
-
var poUseGit_server_default$1 = (context) => context.root.resources[
|
|
2221
|
+
var poUseGit_server_default$1 = (context) => context.root.resources[0];
|
|
2045
2222
|
//#endregion
|
|
2046
2223
|
//#region src/extensions/workspaces/sessions/(backend)/resource/poUseGit.server.ts
|
|
2047
2224
|
var poUseGit_server_default = defineResource(poUseGit_server_default$1);
|
|
@@ -2051,19 +2228,22 @@ var runWorktree_server_default = defineServerTool((context) => context.root.tool
|
|
|
2051
2228
|
//#endregion
|
|
2052
2229
|
//#region generated/server.ts
|
|
2053
2230
|
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
2231
|
+
/* v8 ignore next -- generated normalization branch */
|
|
2232
|
+
const defined = (values) => values.filter((value) => value !== void 0);
|
|
2054
2233
|
const via = (identity, value) => value === void 0 ? void 0 : {
|
|
2055
2234
|
...identity,
|
|
2056
2235
|
...value
|
|
2057
2236
|
};
|
|
2058
|
-
const
|
|
2237
|
+
const serverPlugin = defineServerPlugin({
|
|
2059
2238
|
name: "@agimon-ai/po-git",
|
|
2060
2239
|
providerOverrides: composeServerProviderOverrides(root_server_default),
|
|
2240
|
+
injects: composeRootInjects({ session: [root_server_default] }),
|
|
2061
2241
|
global: (context) => ({
|
|
2062
2242
|
get api() {
|
|
2063
2243
|
return [at(route_server_default, context)];
|
|
2064
2244
|
},
|
|
2065
2245
|
get channels() {
|
|
2066
|
-
return [() => via({ frameType: "git_changes" }, git_changes_server_default
|
|
2246
|
+
return [() => via({ frameType: "git_changes" }, at(git_changes_server_default, context)), () => via({ frameType: "git_worktrees" }, at(git_worktrees_server_default, context))];
|
|
2067
2247
|
}
|
|
2068
2248
|
}),
|
|
2069
2249
|
workspace: (context) => ({
|
|
@@ -2071,11 +2251,11 @@ const facet = defineServerPlugin({
|
|
|
2071
2251
|
return [at(route_server_default, context)];
|
|
2072
2252
|
},
|
|
2073
2253
|
get channels() {
|
|
2074
|
-
return [() => via({ frameType: "git_changes" }, git_changes_server_default
|
|
2254
|
+
return defined([context.hosted("global") ? void 0 : () => via({ frameType: "git_changes" }, at(git_changes_server_default, context)), context.hosted("global") ? void 0 : () => via({ frameType: "git_worktrees" }, at(git_worktrees_server_default, context))]);
|
|
2075
2255
|
}
|
|
2076
2256
|
}),
|
|
2077
2257
|
session: async (context) => {
|
|
2078
|
-
const scopeSession = await root_server_default
|
|
2258
|
+
const scopeSession = await context.scopeRoot("session", root_server_default, context);
|
|
2079
2259
|
const contextSession = {
|
|
2080
2260
|
...context,
|
|
2081
2261
|
root: scopeSession.value
|
|
@@ -2086,17 +2266,13 @@ const facet = defineServerPlugin({
|
|
|
2086
2266
|
return [at(route_server_default, context)];
|
|
2087
2267
|
},
|
|
2088
2268
|
get channels() {
|
|
2089
|
-
return [() => via({ frameType: "git_changes" }, git_changes_server_default
|
|
2269
|
+
return defined([context.hosted("global") ? void 0 : () => via({ frameType: "git_changes" }, at(git_changes_server_default, context)), context.hosted("global") ? void 0 : () => via({ frameType: "git_worktrees" }, at(git_worktrees_server_default, context))]);
|
|
2090
2270
|
},
|
|
2091
2271
|
get hooks() {
|
|
2092
2272
|
return [via({ event: "agent_settled" }, at(agent_settled_server_default, contextSession)), via({ event: "tool_execution_end" }, at(tool_execution_end_server_default, contextSession))];
|
|
2093
2273
|
},
|
|
2094
2274
|
get resources() {
|
|
2095
|
-
return [
|
|
2096
|
-
at(poGit_server_default, contextSession),
|
|
2097
|
-
at(poGitReadme_server_default, contextSession),
|
|
2098
|
-
at(poUseGit_server_default, contextSession)
|
|
2099
|
-
];
|
|
2275
|
+
return [at(poUseGit_server_default, contextSession)];
|
|
2100
2276
|
},
|
|
2101
2277
|
get tools() {
|
|
2102
2278
|
return [via({ name: "run_worktree" }, at(runWorktree_server_default, contextSession))];
|
|
@@ -2109,6 +2285,6 @@ const facet = defineServerPlugin({
|
|
|
2109
2285
|
}
|
|
2110
2286
|
});
|
|
2111
2287
|
//#endregion
|
|
2112
|
-
export {
|
|
2288
|
+
export { serverPlugin as default, serverPlugin };
|
|
2113
2289
|
|
|
2114
2290
|
//# sourceMappingURL=server.mjs.map
|