@codeworksh/harness 0.3.0-dev.20261013131320 → 0.3.0-dev.20261019181702
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/{daytona-D4sNwzSr.mjs → daytona-BqRoRhe7.mjs} +5 -8
- package/daytona-BqRoRhe7.mjs.map +1 -0
- package/effect.d.mts +897 -828
- package/effect.mjs +373 -57
- package/effect.mjs.map +1 -1
- package/package.json +10 -7
- package/sandboxes/daytona/index.mjs +1 -1
- package/daytona-D4sNwzSr.mjs.map +0 -1
package/effect.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as __reExport, t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
|
|
2
2
|
import { a as io_exports, i as errors_exports, n as shell_exports, o as instance_exports, r as filesystem_exports, s as posix } from "./resource-DFZh0e-s.mjs";
|
|
3
3
|
import { a as decode, c as importModule, d as share, l as lendResolve, n as dimensionNote, o as load$5, r as resize, s as load$4, u as resolveModule } from "./resize-D34zcVQl.mjs";
|
|
4
|
-
import "./daytona-
|
|
4
|
+
import "./daytona-BqRoRhe7.mjs";
|
|
5
5
|
import "./vercel-3GouQSJI.mjs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { Cause, Clock, Config, Context, Crypto, Data, DateTime, Deferred, Duration, Effect, Exit, Fiber, FiberSet, FileSystem, Layer, LayerMap, Metric, Option, Path, Predicate, PubSub, Queue, Random, Ref, Result, Schedule, Schema, SchemaIssue, Scope, Semaphore, Stream, String as String$1 } from "effect";
|
|
@@ -21,11 +21,13 @@ import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
|
21
21
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
22
22
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
23
23
|
import { DirectoryNotFoundError, DirectoryNotFoundError as DirectoryNotFoundError$1, Info, Info as Info$1, NotDirectoryError, NotDirectoryError as NotDirectoryError$1, Service, Service as Service$8 } from "@codeworksh/plugin/location";
|
|
24
|
-
import {
|
|
24
|
+
import { downloadCatalog } from "@codeworksh/aikit/modelgen";
|
|
25
25
|
import { JsonGitHubCopilotAuthStorage, getGitHubCopilotApiKey } from "@codeworksh/aikit/oauth/github/copilot";
|
|
26
26
|
import { JsonOpenAICodexAuthStorage, getOpenAICodexApiKey } from "@codeworksh/aikit/oauth/openai/codex";
|
|
27
27
|
import { parse, printParseErrorCode } from "jsonc-parser";
|
|
28
28
|
import * as Section from "@codeworksh/plugin/plugin/section";
|
|
29
|
+
import ignore from "ignore";
|
|
30
|
+
import { parse as parse$1 } from "yaml";
|
|
29
31
|
import * as Diff from "diff";
|
|
30
32
|
import { FetchHttpClient, HttpClient } from "effect/http";
|
|
31
33
|
import npa from "npm-package-arg";
|
|
@@ -134,10 +136,10 @@ var global_exports = /* @__PURE__ */ __exportAll({
|
|
|
134
136
|
app: () => app,
|
|
135
137
|
appConfigDir: () => appConfigDir,
|
|
136
138
|
authFile: () => authFile,
|
|
137
|
-
defaultLayer: () => defaultLayer$
|
|
139
|
+
defaultLayer: () => defaultLayer$4,
|
|
138
140
|
homeConfig: () => homeConfig,
|
|
139
141
|
layer: () => layer$27,
|
|
140
|
-
layerWith: () => layerWith,
|
|
142
|
+
layerWith: () => layerWith$1,
|
|
141
143
|
make: () => make$18,
|
|
142
144
|
resolve: () => resolve$4
|
|
143
145
|
});
|
|
@@ -184,8 +186,8 @@ const build = (input) => Effect.gen(function* () {
|
|
|
184
186
|
return Service$17.of(paths);
|
|
185
187
|
});
|
|
186
188
|
const layer$27 = Layer.effect(Service$17, build({}));
|
|
187
|
-
const defaultLayer$
|
|
188
|
-
const layerWith = (input) => Layer.effect(Service$17, build(input));
|
|
189
|
+
const defaultLayer$4 = layer$27;
|
|
190
|
+
const layerWith$1 = (input) => Layer.effect(Service$17, build(input));
|
|
189
191
|
//#endregion
|
|
190
192
|
//#region src/db/migrations.ts
|
|
191
193
|
const migrations = {
|
|
@@ -374,7 +376,7 @@ var db_exports = /* @__PURE__ */ __exportAll({
|
|
|
374
376
|
Database: () => db_exports,
|
|
375
377
|
SqlClient: () => SqlClient$1,
|
|
376
378
|
SqlSchema: () => SqlSchema$1,
|
|
377
|
-
defaultLayer: () => defaultLayer$
|
|
379
|
+
defaultLayer: () => defaultLayer$3,
|
|
378
380
|
layer: () => layer$26,
|
|
379
381
|
locationConfig: () => locationConfig,
|
|
380
382
|
path: () => path$1,
|
|
@@ -408,7 +410,7 @@ const path$1 = Effect.fn("Database.path")(function* (data) {
|
|
|
408
410
|
const directory = data ?? (yield* resolve$4()).data;
|
|
409
411
|
return resolveDatabaseLocation(yield* locationConfig, directory);
|
|
410
412
|
});
|
|
411
|
-
const defaultLayer$
|
|
413
|
+
const defaultLayer$3 = Layer.unwrap(path$1().pipe(Effect.map(layer$26)));
|
|
412
414
|
//#endregion
|
|
413
415
|
//#region src/event/schema.ts
|
|
414
416
|
var schema_exports$7 = /* @__PURE__ */ __exportAll({});
|
|
@@ -1579,7 +1581,7 @@ var session_exports$1 = /* @__PURE__ */ __exportAll({
|
|
|
1579
1581
|
SessionNotLinkedError: () => SessionNotLinkedError,
|
|
1580
1582
|
SessionRow: () => SessionRow,
|
|
1581
1583
|
ToolCallNotFoundError: () => ToolCallNotFoundError,
|
|
1582
|
-
defaultLayer: () => defaultLayer,
|
|
1584
|
+
defaultLayer: () => defaultLayer$2,
|
|
1583
1585
|
entryStates: () => entryStates,
|
|
1584
1586
|
entryTypes: () => entryTypes,
|
|
1585
1587
|
layer: () => layer$23,
|
|
@@ -1663,6 +1665,16 @@ const layer$23 = Layer.effect(Service$14, Effect.gen(function* () {
|
|
|
1663
1665
|
SELECT p.* FROM space p JOIN session s ON s.space_id = p.id WHERE s.id = ${sessionId}
|
|
1664
1666
|
`
|
|
1665
1667
|
});
|
|
1668
|
+
const findProject = SqlSchema.findOneOption({
|
|
1669
|
+
Request: Schema.String,
|
|
1670
|
+
Result: ProjectRow,
|
|
1671
|
+
execute: (sessionId) => sql`
|
|
1672
|
+
SELECT p.* FROM project p
|
|
1673
|
+
JOIN space sp ON sp.project_id = p.id
|
|
1674
|
+
JOIN session s ON s.space_id = sp.id
|
|
1675
|
+
WHERE s.id = ${sessionId}
|
|
1676
|
+
`
|
|
1677
|
+
});
|
|
1666
1678
|
const findSpaceById = SqlSchema.findOneOption({
|
|
1667
1679
|
Request: Schema.String,
|
|
1668
1680
|
Result: SpaceRow,
|
|
@@ -1811,6 +1823,13 @@ const layer$23 = Layer.effect(Service$14, Effect.gen(function* () {
|
|
|
1811
1823
|
const space = Effect.fn("Session.space")(function* (sessionId) {
|
|
1812
1824
|
return Option.map(yield* findSpace(sessionId).pipe(Effect.orDie), fromRow$1);
|
|
1813
1825
|
});
|
|
1826
|
+
const project = Effect.fn("Session.project")(function* (sessionId) {
|
|
1827
|
+
return Option.map(yield* findProject(sessionId).pipe(Effect.orDie), (row) => new schema_exports$6.ProjectSchema.Info({
|
|
1828
|
+
id: schema_exports$6.ProjectSchema.ID.make(row.id),
|
|
1829
|
+
name: row.name,
|
|
1830
|
+
status: row.status
|
|
1831
|
+
}));
|
|
1832
|
+
});
|
|
1814
1833
|
const list = Effect.fn("Session.list")(function* (input) {
|
|
1815
1834
|
return yield* (input === void 0 ? selectAll() : "spaceId" in input ? selectBySpace(input.spaceId) : selectByProject(input.projectId)).pipe(Effect.orDie);
|
|
1816
1835
|
});
|
|
@@ -2313,6 +2332,7 @@ const layer$23 = Layer.effect(Service$14, Effect.gen(function* () {
|
|
|
2313
2332
|
configure,
|
|
2314
2333
|
get,
|
|
2315
2334
|
space,
|
|
2335
|
+
project,
|
|
2316
2336
|
list,
|
|
2317
2337
|
entry,
|
|
2318
2338
|
path,
|
|
@@ -2329,7 +2349,7 @@ const layer$23 = Layer.effect(Service$14, Effect.gen(function* () {
|
|
|
2329
2349
|
setLabel
|
|
2330
2350
|
});
|
|
2331
2351
|
}));
|
|
2332
|
-
const defaultLayer = layer$23.pipe(Layer.provide(defaultLayer$
|
|
2352
|
+
const defaultLayer$2 = layer$23.pipe(Layer.provide(defaultLayer$3));
|
|
2333
2353
|
//#endregion
|
|
2334
2354
|
//#region src/context/errors.ts
|
|
2335
2355
|
var ContextDecodeError = class extends Schema.TaggedError()("ContextDecodeError", {
|
|
@@ -4274,6 +4294,17 @@ const make$9 = () => {
|
|
|
4274
4294
|
}) };
|
|
4275
4295
|
};
|
|
4276
4296
|
//#endregion
|
|
4297
|
+
//#region src/sandbox/sandbox.ts
|
|
4298
|
+
/**
|
|
4299
|
+
* Assemble a local backend into a sandbox with a **real host shell** — the
|
|
4300
|
+
* right choice whenever commands must invoke actual binaries (`git`, package
|
|
4301
|
+
* managers). For a sandbox whose shell should stay inside the VFS, use
|
|
4302
|
+
* `EnvBash.services` instead, which wires just-bash over the same tree.
|
|
4303
|
+
*/
|
|
4304
|
+
const services = (backend, identity) => Layer.provideMerge(io_exports.SandboxIO.mount(identity), Layer.provideMerge(Layer.merge(layer$21, layer$18()), backend));
|
|
4305
|
+
/** Default sandbox: the real OS filesystem and processes, mounted at `cwd`. */
|
|
4306
|
+
const defaultLayer$1 = (cwd) => services(layer$20(), io_exports.SandboxIO.host(cwd));
|
|
4307
|
+
//#endregion
|
|
4277
4308
|
//#region src/git/git.ts
|
|
4278
4309
|
var AppProcessError = class extends Schema.TaggedError()("AppProcessError", {
|
|
4279
4310
|
command: Schema.String,
|
|
@@ -4464,7 +4495,8 @@ const up = Effect.fn("SandboxFileSystem.up")(function* (fs, options) {
|
|
|
4464
4495
|
const isDirectory$1 = Effect.fn("SandboxFileSystem.isDirectory")(function* (fs, path) {
|
|
4465
4496
|
return yield* fs.stat(path).pipe(Effect.map((stat) => stat.isDirectory), Effect.orElseSucceed(() => false));
|
|
4466
4497
|
});
|
|
4467
|
-
|
|
4498
|
+
/** True when `path` exists and is a regular file; false when it is absent or unreadable. */
|
|
4499
|
+
const isFile = Effect.fn("SandboxFileSystem.isFile")(function* (fs, path) {
|
|
4468
4500
|
return yield* fs.stat(path).pipe(Effect.map((stat) => stat.isFile), Effect.orElseSucceed(() => false));
|
|
4469
4501
|
});
|
|
4470
4502
|
/** Read a file, or `undefined` when it is missing or unreadable. */
|
|
@@ -4611,6 +4643,16 @@ const layer$13 = Layer.effect(Service$10, Effect.gen(function* () {
|
|
|
4611
4643
|
}));
|
|
4612
4644
|
//#endregion
|
|
4613
4645
|
//#region src/project/project.ts
|
|
4646
|
+
var project_exports = /* @__PURE__ */ __exportAll({
|
|
4647
|
+
Project: () => project_exports,
|
|
4648
|
+
ProjectNotFoundError: () => ProjectNotFoundError,
|
|
4649
|
+
Service: () => Service$9,
|
|
4650
|
+
defaultLayer: () => defaultLayer,
|
|
4651
|
+
layer: () => layer$12,
|
|
4652
|
+
layerWith: () => layerWith,
|
|
4653
|
+
provisional: () => provisional,
|
|
4654
|
+
rename: () => rename
|
|
4655
|
+
});
|
|
4614
4656
|
/** Deterministic, env-local id for a directory without a portable identity. Never written to a marker. */
|
|
4615
4657
|
const provisional = (env, location) => schema_exports$6.ProjectSchema.ID.make(fast(JSON.stringify([
|
|
4616
4658
|
"dir",
|
|
@@ -4664,7 +4706,7 @@ const layer$12 = Layer.effect(Service$9, Effect.gen(function* () {
|
|
|
4664
4706
|
main: repo.gitDir === repo.store
|
|
4665
4707
|
}]).toSorted((a, b) => Number(b.main) - Number(a.main));
|
|
4666
4708
|
});
|
|
4667
|
-
const resolveOrCreate = Effect.fn("Project.resolveOrCreate")(function* (cwd) {
|
|
4709
|
+
const resolveOrCreate = Effect.fn("Project.resolveOrCreate")(function* (cwd, options) {
|
|
4668
4710
|
if (!(yield* fs.exists(cwd).pipe(Effect.orDie))) return yield* new DirectoryNotFoundError$1({
|
|
4669
4711
|
directory: cwd,
|
|
4670
4712
|
sandboxInstanceId: env
|
|
@@ -4678,7 +4720,7 @@ const layer$12 = Layer.effect(Service$9, Effect.gen(function* () {
|
|
|
4678
4720
|
const ident = repo === void 0 ? void 0 : yield* repos.identity(repo);
|
|
4679
4721
|
const worktree = repo?.directory ?? location;
|
|
4680
4722
|
const projectId = ident?.id === void 0 ? provisional(env, worktree) : schema_exports$6.ProjectSchema.ID.make(ident.id);
|
|
4681
|
-
const name = ident?.name ?? posix.basename(worktree);
|
|
4723
|
+
const name = options?.name ?? ident?.name ?? posix.basename(worktree);
|
|
4682
4724
|
const vcs = repo === void 0 ? void 0 : {
|
|
4683
4725
|
type: "git",
|
|
4684
4726
|
store: repo.store
|
|
@@ -4750,6 +4792,32 @@ const layer$12 = Layer.effect(Service$9, Effect.gen(function* () {
|
|
|
4750
4792
|
list
|
|
4751
4793
|
});
|
|
4752
4794
|
}));
|
|
4795
|
+
var ProjectNotFoundError = class extends Schema.TaggedError()("ProjectNotFoundError", { projectId: Schema.String }) {};
|
|
4796
|
+
/** Renames a project. Needs only the database, not a mount: a name is the same in every env. */
|
|
4797
|
+
const rename = Effect.fn("Project.rename")(function* (input) {
|
|
4798
|
+
const sql = yield* SqlClient.SqlClient;
|
|
4799
|
+
const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
|
|
4800
|
+
const row = yield* SqlSchema.findOneOption({
|
|
4801
|
+
Request: Schema.Struct({
|
|
4802
|
+
id: Schema.String,
|
|
4803
|
+
name: Schema.String
|
|
4804
|
+
}),
|
|
4805
|
+
Result: ProjectRow,
|
|
4806
|
+
execute: ({ id, name }) => sql`UPDATE project SET name = ${name}, updated_at = ${now} WHERE id = ${id} RETURNING *`
|
|
4807
|
+
})({
|
|
4808
|
+
id: input.projectId,
|
|
4809
|
+
name: input.name
|
|
4810
|
+
}).pipe(Effect.orDie);
|
|
4811
|
+
if (Option.isNone(row)) return yield* new ProjectNotFoundError({ projectId: input.projectId });
|
|
4812
|
+
return new schema_exports$6.ProjectSchema.Info({
|
|
4813
|
+
id: schema_exports$6.ProjectSchema.ID.make(row.value.id),
|
|
4814
|
+
name: row.value.name,
|
|
4815
|
+
status: row.value.status
|
|
4816
|
+
});
|
|
4817
|
+
});
|
|
4818
|
+
/** Takes an assembled sandbox — local or remote — not a local backend. */
|
|
4819
|
+
const layerWith = (sandbox) => layer$12.pipe(Layer.provide(Layer.mergeAll(layer$14, layer$13, layer$24)), Layer.provide(layer$15), Layer.provide(sandbox), Layer.provide(defaultLayer$3));
|
|
4820
|
+
const defaultLayer = (path) => layerWith(defaultLayer$1(path));
|
|
4753
4821
|
//#endregion
|
|
4754
4822
|
//#region src/location/location.ts
|
|
4755
4823
|
var location_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -4761,10 +4829,10 @@ var location_exports = /* @__PURE__ */ __exportAll({
|
|
|
4761
4829
|
layer: () => layer$11,
|
|
4762
4830
|
layerMounted: () => layerMounted
|
|
4763
4831
|
});
|
|
4764
|
-
const layer$11 = () => Layer.effect(Service, Effect.gen(function* () {
|
|
4832
|
+
const layer$11 = (options) => Layer.effect(Service, Effect.gen(function* () {
|
|
4765
4833
|
const instance = yield* io_exports.SandboxIO.Current;
|
|
4766
4834
|
const directory = schema_exports$9.AbsolutePath.make(instance.cwd);
|
|
4767
|
-
const resolved = yield* (yield* Service$9).resolveOrCreate(directory);
|
|
4835
|
+
const resolved = yield* (yield* Service$9).resolveOrCreate(directory, options);
|
|
4768
4836
|
return Service.of(new Info({
|
|
4769
4837
|
directory: resolved.directory,
|
|
4770
4838
|
space: resolved.space,
|
|
@@ -4776,7 +4844,7 @@ const layer$11 = () => Layer.effect(Service, Effect.gen(function* () {
|
|
|
4776
4844
|
* folded in. What remains is exactly the mount and the database — for callers
|
|
4777
4845
|
* that already hold both, such as the runner and `Session.create`.
|
|
4778
4846
|
*/
|
|
4779
|
-
const layerMounted = () => layer$11().pipe(Layer.provide(layer$12.pipe(Layer.provide(Layer.mergeAll(layer$14, layer$13, layer$24)), Layer.provide(layer$15))));
|
|
4847
|
+
const layerMounted = (options) => layer$11(options).pipe(Layer.provide(layer$12.pipe(Layer.provide(Layer.mergeAll(layer$14, layer$13, layer$24)), Layer.provide(layer$15))));
|
|
4780
4848
|
//#endregion
|
|
4781
4849
|
//#region src/runner/run.ts
|
|
4782
4850
|
var run_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -4871,7 +4939,6 @@ var ProviderError = class extends Schema.TaggedError()("Runner.ProviderError", {
|
|
|
4871
4939
|
var ModelCatalogError = class extends Schema.TaggedError()("Runner.ModelCatalogError", {
|
|
4872
4940
|
path: Schema.String,
|
|
4873
4941
|
reason: Schema.Literals([
|
|
4874
|
-
"missing",
|
|
4875
4942
|
"unreadable",
|
|
4876
4943
|
"empty",
|
|
4877
4944
|
"invalid"
|
|
@@ -5312,7 +5379,7 @@ var settings_exports = /* @__PURE__ */ __exportAll({
|
|
|
5312
5379
|
layer: () => layer$8,
|
|
5313
5380
|
load: () => load$3,
|
|
5314
5381
|
modules: () => modules,
|
|
5315
|
-
parse: () => parse$
|
|
5382
|
+
parse: () => parse$5,
|
|
5316
5383
|
paths: () => paths,
|
|
5317
5384
|
projectRoot: () => projectRoot,
|
|
5318
5385
|
userConfigDir: () => userConfigDir
|
|
@@ -5401,7 +5468,7 @@ const decodeFormatter = SchemaIssue.makeFormatterStandardSchemaV1({ leafHook: (i
|
|
|
5401
5468
|
const message = "annotations" in issue ? issue.annotations?.message : void 0;
|
|
5402
5469
|
return typeof message === "string" ? message.replaceAll(/\s*\n\s*/g, " ") : "invalid value";
|
|
5403
5470
|
} });
|
|
5404
|
-
const parse$
|
|
5471
|
+
const parse$5 = Effect.fn("Settings.parse")(function* (path, source) {
|
|
5405
5472
|
const errors = [];
|
|
5406
5473
|
const json = parse(source, errors, {
|
|
5407
5474
|
allowTrailingComma: true,
|
|
@@ -5449,7 +5516,7 @@ const attempt = (path) => fileSystem.readFileString(path).pipe(Effect.mapError((
|
|
|
5449
5516
|
path,
|
|
5450
5517
|
reason: "read",
|
|
5451
5518
|
detail: error.reason._tag
|
|
5452
|
-
})), Effect.flatMap((source) => parse$
|
|
5519
|
+
})), Effect.flatMap((source) => parse$5(path, source)));
|
|
5453
5520
|
/**
|
|
5454
5521
|
* One read of every layer. Exported for the harness constructor, which needs the plugin
|
|
5455
5522
|
* selection before any layer is built; everything else goes through `Service`.
|
|
@@ -5563,8 +5630,13 @@ const stale = Effect.fn("ModelCatalog.stale")(function* (path) {
|
|
|
5563
5630
|
const ttl = yield* ttlConfig;
|
|
5564
5631
|
return (yield* Clock.currentTimeMillis) - mtime.value >= Duration.toMillis(ttl);
|
|
5565
5632
|
});
|
|
5633
|
+
/** OpenRouter's catalog is narrowed to what the host's key may use, when one is set. */
|
|
5634
|
+
const openRouterKey = () => getEnvApiKey({ env: ["OPENROUTER_API_KEY"] });
|
|
5566
5635
|
const download$1 = (path) => Effect.tryPromise({
|
|
5567
|
-
try: () =>
|
|
5636
|
+
try: () => downloadCatalog({
|
|
5637
|
+
path,
|
|
5638
|
+
openRouterKey: openRouterKey()
|
|
5639
|
+
}),
|
|
5568
5640
|
catch: (cause) => new RefreshError({
|
|
5569
5641
|
path,
|
|
5570
5642
|
detail: cause instanceof Error ? cause.message : String(cause)
|
|
@@ -5585,8 +5657,7 @@ const refresh$1 = Effect.fn("ModelCatalog.refresh")(function* (home, options = {
|
|
|
5585
5657
|
});
|
|
5586
5658
|
/**
|
|
5587
5659
|
* The automatic check: refresh a stale catalog unless it is pinned, and never fail. A failed
|
|
5588
|
-
* download leaves the old file in place;
|
|
5589
|
-
* `Runner.ModelCatalogError` from whatever needed it.
|
|
5660
|
+
* download leaves the old file in place; without one, aikit's bundled baseline is read.
|
|
5590
5661
|
*/
|
|
5591
5662
|
const check$1 = Effect.fn("ModelCatalog.check")(function* ({ path, pinned }) {
|
|
5592
5663
|
if (pinned || !(yield* stale(path))) return;
|
|
@@ -5622,7 +5693,7 @@ const loadError = (cause) => {
|
|
|
5622
5693
|
if (typeof cause !== "object" || cause === null || !("name" in cause) || cause.name !== "ModelCatalogLoadError") return;
|
|
5623
5694
|
if (!("data" in cause) || typeof cause.data !== "object" || cause.data === null) return void 0;
|
|
5624
5695
|
const data = cause.data;
|
|
5625
|
-
if (!("path" in data) || typeof data.path !== "string" || !("message" in data) || typeof data.message !== "string" || !("reason" in data) || data.reason !== "
|
|
5696
|
+
if (!("path" in data) || typeof data.path !== "string" || !("message" in data) || typeof data.message !== "string" || !("reason" in data) || data.reason !== "unreadable" && data.reason !== "empty" && data.reason !== "invalid") return;
|
|
5626
5697
|
return new ModelCatalogError({
|
|
5627
5698
|
path: data.path,
|
|
5628
5699
|
reason: data.reason,
|
|
@@ -5755,6 +5826,22 @@ const defaultPromptPlugin = (0, plugin_exports$1.define)({
|
|
|
5755
5826
|
})
|
|
5756
5827
|
});
|
|
5757
5828
|
//#endregion
|
|
5829
|
+
//#region src/plugin/builtin/prompt/walk.ts
|
|
5830
|
+
const stripBom$1 = (raw) => raw.charCodeAt(0) === 65279 ? raw.slice(1) : raw;
|
|
5831
|
+
/** `directory` and every ancestor up to the sandbox root, closest first. */
|
|
5832
|
+
const ancestors = (directory) => {
|
|
5833
|
+
const chain = [];
|
|
5834
|
+
for (let current = directory;; current = posix.dirname(current)) {
|
|
5835
|
+
chain.push(current);
|
|
5836
|
+
if (posix.dirname(current) === current) return chain;
|
|
5837
|
+
}
|
|
5838
|
+
};
|
|
5839
|
+
/**
|
|
5840
|
+
* Which of `paths` exist as the requested kind (`entry` takes either). Absence stays silent; any other failure
|
|
5841
|
+
* (permissions, a remote blip) is logged so a dropped entry is not a mystery, then counts as absent.
|
|
5842
|
+
*/
|
|
5843
|
+
const present$1 = (fs, paths, kind, label) => Effect.forEach(paths, (path) => fs.exists(path).pipe(Effect.filterOrElse((exists) => !exists || kind === "entry", () => fs.stat(path).pipe(Effect.map((stat) => kind === "file" ? stat.isFile : stat.isDirectory))), Effect.catch((error) => filesystem_exports.SandboxFileSystem.isNotFoundError(error.cause) ? Effect.succeed(false) : Effect.logWarning(`could not stat ${label} ${path}`, error.cause).pipe(Effect.as(false)))), { concurrency: "unbounded" }).pipe(Effect.map((hits) => new Set(paths.filter((_, index) => hits[index]))));
|
|
5844
|
+
//#endregion
|
|
5758
5845
|
//#region src/plugin/builtin/prompt/instruction.ts
|
|
5759
5846
|
/** First readable match per directory wins. */
|
|
5760
5847
|
const names = [
|
|
@@ -5766,22 +5853,9 @@ const names = [
|
|
|
5766
5853
|
"CLAUDE.MD"
|
|
5767
5854
|
];
|
|
5768
5855
|
const content = (raw) => {
|
|
5769
|
-
const text =
|
|
5856
|
+
const text = stripBom$1(raw);
|
|
5770
5857
|
return text.trim().length === 0 ? void 0 : text;
|
|
5771
5858
|
};
|
|
5772
|
-
/** `directory` and every ancestor up to the sandbox root, closest first. */
|
|
5773
|
-
const ancestors = (directory) => {
|
|
5774
|
-
const chain = [];
|
|
5775
|
-
for (let current = directory;; current = posix.dirname(current)) {
|
|
5776
|
-
chain.push(current);
|
|
5777
|
-
if (posix.dirname(current) === current) return chain;
|
|
5778
|
-
}
|
|
5779
|
-
};
|
|
5780
|
-
/**
|
|
5781
|
-
* Which of `paths` are files. Absence is the expected answer and stays silent; any other failure
|
|
5782
|
-
* (permissions, a remote blip) is logged so a dropped file is not a mystery, then counts as absent.
|
|
5783
|
-
*/
|
|
5784
|
-
const present$1 = (fs, paths) => Effect.forEach(paths, (path) => fs.exists(path).pipe(Effect.flatMap((exists) => exists ? fs.stat(path).pipe(Effect.map((stat) => stat.isFile)) : Effect.succeed(false)), Effect.catch((error) => filesystem_exports.SandboxFileSystem.isNotFoundError(error.cause) ? Effect.succeed(false) : Effect.logWarning(`could not stat instruction file ${path}`, error.cause).pipe(Effect.as(false)))), { concurrency: "unbounded" }).pipe(Effect.map((hits) => new Set(paths.filter((_, index) => hits[index]))));
|
|
5785
5859
|
/** A file that stats but does not read falls through to the next candidate. */
|
|
5786
5860
|
const first = Effect.fnUntraced(function* (fs, directory, files) {
|
|
5787
5861
|
for (const name of names) {
|
|
@@ -5809,9 +5883,9 @@ const shadowing = (location) => {
|
|
|
5809
5883
|
return location.space.location.startsWith(`${main}/`) ? main : void 0;
|
|
5810
5884
|
};
|
|
5811
5885
|
/** One file per directory from the sandbox root down to the cwd, closest last so it has the final word. */
|
|
5812
|
-
const discover = Effect.fnUntraced(function* (fs, location) {
|
|
5886
|
+
const discover$1 = Effect.fnUntraced(function* (fs, location) {
|
|
5813
5887
|
const chain = ancestors(location.directory);
|
|
5814
|
-
const files = yield* present$1(fs, chain.flatMap((directory) => names.map((name) => posix.join(directory, name))));
|
|
5888
|
+
const files = yield* present$1(fs, chain.flatMap((directory) => names.map((name) => posix.join(directory, name))), "file", "instruction file");
|
|
5815
5889
|
const found = yield* Effect.forEach(chain, (directory) => first(fs, directory, files), { concurrency: "unbounded" });
|
|
5816
5890
|
const main = shadowing(location);
|
|
5817
5891
|
const worktree = main === void 0 ? void 0 : found[chain.indexOf(location.space.location)];
|
|
@@ -5827,7 +5901,7 @@ const instructionPlugin = (0, plugin_exports$1.define)({
|
|
|
5827
5901
|
kind: "prompt",
|
|
5828
5902
|
setup: Effect.fn("InstructionPlugin.setup")(function* (ctx) {
|
|
5829
5903
|
const fs = yield* io_exports.SandboxIO.FileSystem;
|
|
5830
|
-
const files = (yield* discover(fs, ctx.location)).filter((file) => file.content !== void 0);
|
|
5904
|
+
const files = (yield* discover$1(fs, ctx.location)).filter((file) => file.content !== void 0);
|
|
5831
5905
|
if (files.length === 0) return;
|
|
5832
5906
|
const prompt = ctx.plugin.prompt;
|
|
5833
5907
|
prompt.sections.append(Section.ProjectContext, "Project-Specific Instructions & Guidelines:");
|
|
@@ -5835,6 +5909,236 @@ const instructionPlugin = (0, plugin_exports$1.define)({
|
|
|
5835
5909
|
})
|
|
5836
5910
|
});
|
|
5837
5911
|
//#endregion
|
|
5912
|
+
//#region src/plugin/builtin/prompt/skill.ts
|
|
5913
|
+
/** Max name length per Agent Skills spec. */
|
|
5914
|
+
const MAX_NAME_LENGTH = 64;
|
|
5915
|
+
/** Max description length per Agent Skills spec. */
|
|
5916
|
+
const MAX_DESCRIPTION_LENGTH = 1024;
|
|
5917
|
+
const IGNORE_FILE_NAMES = [
|
|
5918
|
+
".gitignore",
|
|
5919
|
+
".ignore",
|
|
5920
|
+
".fdignore"
|
|
5921
|
+
];
|
|
5922
|
+
const normalizeNewlines = (value) => value.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
|
|
5923
|
+
const extractFrontmatter = (content) => {
|
|
5924
|
+
const normalized = normalizeNewlines(stripBom$1(content));
|
|
5925
|
+
if (!normalized.startsWith("---")) return void 0;
|
|
5926
|
+
const endIndex = normalized.indexOf("\n---", 3);
|
|
5927
|
+
if (endIndex === -1) return void 0;
|
|
5928
|
+
return normalized.slice(4, endIndex);
|
|
5929
|
+
};
|
|
5930
|
+
const parseFrontmatter = (raw) => {
|
|
5931
|
+
const yamlString = extractFrontmatter(raw);
|
|
5932
|
+
if (yamlString === void 0) return { frontmatter: {} };
|
|
5933
|
+
try {
|
|
5934
|
+
const parsed = parse$1(yamlString);
|
|
5935
|
+
return { frontmatter: typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {} };
|
|
5936
|
+
} catch (error) {
|
|
5937
|
+
return {
|
|
5938
|
+
frontmatter: {},
|
|
5939
|
+
error
|
|
5940
|
+
};
|
|
5941
|
+
}
|
|
5942
|
+
};
|
|
5943
|
+
const validateName = (name) => {
|
|
5944
|
+
const errors = [];
|
|
5945
|
+
if (name.length > MAX_NAME_LENGTH) errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);
|
|
5946
|
+
if (!/^[a-z0-9-]+$/.test(name)) errors.push("name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)");
|
|
5947
|
+
if (name.startsWith("-") || name.endsWith("-")) errors.push("name must not start or end with a hyphen");
|
|
5948
|
+
if (name.includes("--")) errors.push("name must not contain consecutive hyphens");
|
|
5949
|
+
return errors;
|
|
5950
|
+
};
|
|
5951
|
+
const validateDescription = (description) => {
|
|
5952
|
+
const errors = [];
|
|
5953
|
+
if (typeof description !== "string" || description.trim() === "") errors.push("description is required");
|
|
5954
|
+
else if (description.length > MAX_DESCRIPTION_LENGTH) errors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);
|
|
5955
|
+
return errors;
|
|
5956
|
+
};
|
|
5957
|
+
const prefixIgnorePattern = (line, prefix) => {
|
|
5958
|
+
const trimmed = line.trim();
|
|
5959
|
+
if (!trimmed) return void 0;
|
|
5960
|
+
if (trimmed.startsWith("#") && !trimmed.startsWith("\\#")) return void 0;
|
|
5961
|
+
let pattern = line;
|
|
5962
|
+
let negated = false;
|
|
5963
|
+
if (pattern.startsWith("!")) {
|
|
5964
|
+
negated = true;
|
|
5965
|
+
pattern = pattern.slice(1);
|
|
5966
|
+
} else if (pattern.startsWith("\\!")) pattern = pattern.slice(1);
|
|
5967
|
+
if (pattern.startsWith("/")) pattern = pattern.slice(1);
|
|
5968
|
+
const prefixed = prefix ? `${prefix}${pattern}` : pattern;
|
|
5969
|
+
return negated ? `!${prefixed}` : prefixed;
|
|
5970
|
+
};
|
|
5971
|
+
const addIgnoreRules = Effect.fnUntraced(function* (fs, ig, dir, root, entryNames) {
|
|
5972
|
+
const relativeDir = posix.relative(root, dir);
|
|
5973
|
+
const prefix = relativeDir && relativeDir !== "." ? `${relativeDir}/` : "";
|
|
5974
|
+
const presentIgnoreFiles = IGNORE_FILE_NAMES.filter((name) => entryNames.has(name));
|
|
5975
|
+
if (presentIgnoreFiles.length === 0) return;
|
|
5976
|
+
const contents = yield* Effect.forEach(presentIgnoreFiles, (filename) => fs.readFile(posix.join(dir, filename)).pipe(Effect.option), { concurrency: "unbounded" });
|
|
5977
|
+
for (const content of contents) {
|
|
5978
|
+
if (Option.isNone(content)) continue;
|
|
5979
|
+
const patterns = content.value.split(/\r?\n/).map((line) => prefixIgnorePattern(line, prefix)).filter((line) => line !== void 0);
|
|
5980
|
+
if (patterns.length > 0) ig.add(patterns);
|
|
5981
|
+
}
|
|
5982
|
+
});
|
|
5983
|
+
const loadSkillFromFile = Effect.fnUntraced(function* (fs, filePath) {
|
|
5984
|
+
const isDeclaredSkill = posix.basename(filePath) === "SKILL.md";
|
|
5985
|
+
const raw = yield* fs.readFile(filePath).pipe(Effect.tapError((error) => Effect.logWarning(`could not read skill file ${filePath}`, error.cause)), Effect.option);
|
|
5986
|
+
if (Option.isNone(raw)) return void 0;
|
|
5987
|
+
const { frontmatter, error } = parseFrontmatter(raw.value);
|
|
5988
|
+
if (error !== void 0) {
|
|
5989
|
+
if (isDeclaredSkill) yield* Effect.logWarning(`could not parse skill file ${filePath}`, error);
|
|
5990
|
+
return;
|
|
5991
|
+
}
|
|
5992
|
+
const description = frontmatter.description;
|
|
5993
|
+
const hasDescription = typeof description === "string" && description.trim() !== "";
|
|
5994
|
+
if (!isDeclaredSkill && !hasDescription) return void 0;
|
|
5995
|
+
const skillDir = posix.dirname(filePath);
|
|
5996
|
+
const parentDirName = posix.basename(skillDir);
|
|
5997
|
+
for (const error of validateDescription(description)) yield* Effect.logWarning(`skill ${filePath}: ${error}`);
|
|
5998
|
+
const name = (typeof frontmatter.name === "string" ? frontmatter.name : void 0) || parentDirName;
|
|
5999
|
+
for (const error of validateName(name)) yield* Effect.logWarning(`skill ${filePath}: ${error}`);
|
|
6000
|
+
if (!hasDescription) return void 0;
|
|
6001
|
+
return {
|
|
6002
|
+
name,
|
|
6003
|
+
description,
|
|
6004
|
+
filePath,
|
|
6005
|
+
baseDir: skillDir,
|
|
6006
|
+
disableModelInvocation: frontmatter["disable-model-invocation"] === true
|
|
6007
|
+
};
|
|
6008
|
+
});
|
|
6009
|
+
const scanDir = (fs, dir, mode, root, ig, visited) => Effect.gen(function* () {
|
|
6010
|
+
const realDir = yield* realpath(fs, dir);
|
|
6011
|
+
if (visited.has(realDir)) return [];
|
|
6012
|
+
const nextVisited = /* @__PURE__ */ new Set([...visited, realDir]);
|
|
6013
|
+
const listed = yield* fs.readdir(dir).pipe(Effect.tapError((error) => filesystem_exports.SandboxFileSystem.isNotFoundError(error.cause) ? Effect.void : Effect.logWarning(`could not read skill directory ${dir}`, error.cause)), Effect.option);
|
|
6014
|
+
if (Option.isNone(listed)) return [];
|
|
6015
|
+
const entries = [...listed.value].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
6016
|
+
const entrySet = new Set(entries);
|
|
6017
|
+
yield* addIgnoreRules(fs, ig, dir, root, entrySet);
|
|
6018
|
+
if (entrySet.has("SKILL.md")) {
|
|
6019
|
+
const fullPath = posix.join(dir, "SKILL.md");
|
|
6020
|
+
const relPath = posix.relative(root, fullPath);
|
|
6021
|
+
if ((yield* isFile(fs, fullPath)) && !ig.ignores(relPath)) {
|
|
6022
|
+
const skill = yield* loadSkillFromFile(fs, fullPath);
|
|
6023
|
+
return skill === void 0 ? [] : [skill];
|
|
6024
|
+
}
|
|
6025
|
+
}
|
|
6026
|
+
const visible = entries.filter((name) => !name.startsWith(".") && name !== "node_modules");
|
|
6027
|
+
const statted = yield* Effect.forEach(visible, (name) => {
|
|
6028
|
+
const fullPath = posix.join(dir, name);
|
|
6029
|
+
return fs.stat(fullPath).pipe(Effect.map((stat) => ({
|
|
6030
|
+
name,
|
|
6031
|
+
fullPath,
|
|
6032
|
+
stat
|
|
6033
|
+
})), Effect.option);
|
|
6034
|
+
}, { concurrency: "unbounded" });
|
|
6035
|
+
const skills = [];
|
|
6036
|
+
for (const item of statted) {
|
|
6037
|
+
if (Option.isNone(item)) continue;
|
|
6038
|
+
const { name, fullPath, stat } = item.value;
|
|
6039
|
+
const relPath = posix.relative(root, fullPath);
|
|
6040
|
+
if (ig.ignores(stat.isDirectory ? `${relPath}/` : relPath)) continue;
|
|
6041
|
+
if (stat.isDirectory) {
|
|
6042
|
+
const nested = yield* scanDir(fs, fullPath, mode, root, ig, nextVisited);
|
|
6043
|
+
skills.push(...nested);
|
|
6044
|
+
continue;
|
|
6045
|
+
}
|
|
6046
|
+
if (stat.isFile && name.endsWith(".md") && (mode === "codework" && dir === root || mode === "agents" && dir !== root)) {
|
|
6047
|
+
const skill = yield* loadSkillFromFile(fs, fullPath);
|
|
6048
|
+
if (skill !== void 0) skills.push(skill);
|
|
6049
|
+
}
|
|
6050
|
+
}
|
|
6051
|
+
return skills;
|
|
6052
|
+
});
|
|
6053
|
+
/**
|
|
6054
|
+
* Load skills from a single directory in the sandbox.
|
|
6055
|
+
*
|
|
6056
|
+
* Discovery rules:
|
|
6057
|
+
* - If a directory contains `SKILL.md`, treat it as a skill root and do not recurse further.
|
|
6058
|
+
* - In `"codework"` mode, direct `.md` children in the root are also loaded; in `"agents"` mode,
|
|
6059
|
+
* `.md` files in subdirectories are loaded while root `.md` files are ignored.
|
|
6060
|
+
* - Recurse into subdirectories (skipping dotfiles, `node_modules`, and ignored paths).
|
|
6061
|
+
*/
|
|
6062
|
+
const loadSkillsFromDir = (fs, dir, mode) => scanDir(fs, dir, mode, dir, ignore(), /* @__PURE__ */ new Set());
|
|
6063
|
+
/**
|
|
6064
|
+
* Discover skills inside the sandbox: `.codework/skills` at the cwd, then
|
|
6065
|
+
* `.agents/skills` from the cwd up to the git root (the closest ancestor holding `.git`), or up to
|
|
6066
|
+
* the sandbox root outside a repository. Earlier skills win name collisions.
|
|
6067
|
+
*/
|
|
6068
|
+
const discover = Effect.fnUntraced(function* (fs, location) {
|
|
6069
|
+
const chain = ancestors(location.directory);
|
|
6070
|
+
const own = posix.join(location.directory, appConfigDir, "skills");
|
|
6071
|
+
const agents = chain.map((directory) => posix.join(directory, ".agents", "skills"));
|
|
6072
|
+
const [dirs, gits] = yield* Effect.all([present$1(fs, [own, ...agents], "directory", "skill directory"), present$1(fs, chain.map((directory) => posix.join(directory, ".git")), "entry", "git marker")], { concurrency: "unbounded" });
|
|
6073
|
+
const root = chain.findIndex((directory) => gits.has(posix.join(directory, ".git")));
|
|
6074
|
+
const walked = root === -1 ? agents : agents.slice(0, root + 1);
|
|
6075
|
+
const sources = [{
|
|
6076
|
+
dir: own,
|
|
6077
|
+
mode: "codework"
|
|
6078
|
+
}, ...walked.map((dir) => ({
|
|
6079
|
+
dir,
|
|
6080
|
+
mode: "agents"
|
|
6081
|
+
}))].filter(({ dir }) => dirs.has(dir));
|
|
6082
|
+
const found = yield* Effect.forEach(sources, ({ dir, mode }) => loadSkillsFromDir(fs, dir, mode), { concurrency: "unbounded" });
|
|
6083
|
+
const skillMap = /* @__PURE__ */ new Map();
|
|
6084
|
+
const realPathSet = /* @__PURE__ */ new Set();
|
|
6085
|
+
for (const skill of found.flat()) {
|
|
6086
|
+
const realPath = yield* realpath(fs, skill.filePath);
|
|
6087
|
+
if (realPathSet.has(realPath)) continue;
|
|
6088
|
+
const existing = skillMap.get(skill.name);
|
|
6089
|
+
if (existing !== void 0) yield* Effect.logWarning(`skill ${skill.filePath}: name "${skill.name}" collision with ${existing.filePath}`);
|
|
6090
|
+
else {
|
|
6091
|
+
skillMap.set(skill.name, skill);
|
|
6092
|
+
realPathSet.add(realPath);
|
|
6093
|
+
}
|
|
6094
|
+
}
|
|
6095
|
+
return Array.from(skillMap.values());
|
|
6096
|
+
});
|
|
6097
|
+
const escapeXml = (str) => str.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
6098
|
+
/**
|
|
6099
|
+
* Format skills for inclusion in `Section.Skills` per the Agent Skills specification.
|
|
6100
|
+
* Skills with `disableModelInvocation: true` are excluded from the prompt.
|
|
6101
|
+
*/
|
|
6102
|
+
const formatSkillsForPrompt = (skills, fileReadTool = "read") => {
|
|
6103
|
+
const visibleSkills = skills.filter((s) => !s.disableModelInvocation);
|
|
6104
|
+
if (visibleSkills.length === 0) return "";
|
|
6105
|
+
const lines = [
|
|
6106
|
+
"The following skills provide specialized instructions for specific tasks.",
|
|
6107
|
+
fileReadTool === "read" ? "Use the read tool to load a skill's file when the task matches its description." : fileReadTool === "bash" ? "Use bash to load a skill's file when the task matches its description." : "Load a skill's file when the task matches its description.",
|
|
6108
|
+
"When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.",
|
|
6109
|
+
"",
|
|
6110
|
+
"<available_skills>"
|
|
6111
|
+
];
|
|
6112
|
+
for (const skill of visibleSkills) {
|
|
6113
|
+
lines.push(" <skill>");
|
|
6114
|
+
lines.push(` <name>${escapeXml(skill.name)}</name>`);
|
|
6115
|
+
lines.push(` <description>${escapeXml(skill.description)}</description>`);
|
|
6116
|
+
lines.push(` <location>${escapeXml(skill.filePath)}</location>`);
|
|
6117
|
+
lines.push(" </skill>");
|
|
6118
|
+
}
|
|
6119
|
+
lines.push("</available_skills>");
|
|
6120
|
+
return lines.join("\n");
|
|
6121
|
+
};
|
|
6122
|
+
const readers = ["read", "bash"];
|
|
6123
|
+
const skillPlugin = (0, plugin_exports$1.define)({
|
|
6124
|
+
id: "codework.prompt.skill",
|
|
6125
|
+
kind: "prompt",
|
|
6126
|
+
setup: Effect.fn("SkillPlugin.setup")(function* (ctx) {
|
|
6127
|
+
const tools = ctx.plugin.tools;
|
|
6128
|
+
const visible = (name) => {
|
|
6129
|
+
const tool = tools.get(name);
|
|
6130
|
+
return tool !== void 0 && tool.promptSnippet !== void 0 && tool.promptSnippet.length > 0;
|
|
6131
|
+
};
|
|
6132
|
+
const fileReadTool = readers.find(visible) ?? (readers.some((name) => tools.has(name)) ? "indirect" : void 0);
|
|
6133
|
+
if (fileReadTool === void 0) return;
|
|
6134
|
+
const fs = yield* io_exports.SandboxIO.FileSystem;
|
|
6135
|
+
const skills = yield* discover(fs, ctx.location);
|
|
6136
|
+
const formatted = formatSkillsForPrompt(skills, fileReadTool);
|
|
6137
|
+
if (formatted.length === 0) return;
|
|
6138
|
+
ctx.plugin.prompt.sections.append(Section.Skills, formatted);
|
|
6139
|
+
})
|
|
6140
|
+
});
|
|
6141
|
+
//#endregion
|
|
5838
6142
|
//#region src/tool/truncate.ts
|
|
5839
6143
|
/**
|
|
5840
6144
|
* Shared truncation utilities for tool outputs.
|
|
@@ -6165,7 +6469,7 @@ const script = (command, file, limits, pipeline, report) => [
|
|
|
6165
6469
|
"run 2>&1"
|
|
6166
6470
|
].join("\n");
|
|
6167
6471
|
const header = new RegExp(`^${HEADER} (\\d+) (\\d+) ([01])(?: (\\d+))?$`, "m");
|
|
6168
|
-
const parse$
|
|
6472
|
+
const parse$4 = (match) => ({
|
|
6169
6473
|
bytes: Number(match[1]),
|
|
6170
6474
|
newlines: Number(match[2]),
|
|
6171
6475
|
kept: match[3] === "1"
|
|
@@ -6184,7 +6488,7 @@ const report = (stderr) => {
|
|
|
6184
6488
|
rest: stderr
|
|
6185
6489
|
};
|
|
6186
6490
|
return {
|
|
6187
|
-
report: parse$
|
|
6491
|
+
report: parse$4(match),
|
|
6188
6492
|
rest: stderr.slice(0, match.index) + stderr.slice(match.index + match[0].length).replace(/^\n/, "")
|
|
6189
6493
|
};
|
|
6190
6494
|
};
|
|
@@ -6207,7 +6511,7 @@ const window = (stdout) => {
|
|
|
6207
6511
|
const match = header.exec(newline === -1 ? stdout : stdout.slice(0, newline));
|
|
6208
6512
|
if (match === null || match[4] === void 0) return void 0;
|
|
6209
6513
|
return {
|
|
6210
|
-
...parse$
|
|
6514
|
+
...parse$4(match),
|
|
6211
6515
|
text: stdout.slice(newline + 1),
|
|
6212
6516
|
textBytes: Number(match[4])
|
|
6213
6517
|
};
|
|
@@ -7282,7 +7586,7 @@ const pipeline = (argv, limit, errors) => [
|
|
|
7282
7586
|
].join("; ");
|
|
7283
7587
|
const STATUS = /^\{"type":"rc","code":(\d+)\}$/;
|
|
7284
7588
|
/** The pipeline's output: match events, ripgrep's status, and anything else, which is its stderr. */
|
|
7285
|
-
const parse$
|
|
7589
|
+
const parse$3 = (stdout, stderr) => {
|
|
7286
7590
|
const matches = [];
|
|
7287
7591
|
const errors = [];
|
|
7288
7592
|
let status;
|
|
@@ -7366,7 +7670,7 @@ const grepHandler = (params) => Effect.gen(function* () {
|
|
|
7366
7670
|
if (params.glob) argv.push("--glob", params.glob);
|
|
7367
7671
|
argv.push("-e", params.pattern, searchPath);
|
|
7368
7672
|
const result = yield* shell.exec(pipeline(argv, limit, errors));
|
|
7369
|
-
const parsed = parse$
|
|
7673
|
+
const parsed = parse$3(result.stdout, result.stderr);
|
|
7370
7674
|
return {
|
|
7371
7675
|
...parsed,
|
|
7372
7676
|
exitCode: parsed.status ?? result.exitCode
|
|
@@ -7931,7 +8235,8 @@ const builtins = Object.freeze([
|
|
|
7931
8235
|
findPlugin,
|
|
7932
8236
|
lsPlugin,
|
|
7933
8237
|
defaultPromptPlugin,
|
|
7934
|
-
instructionPlugin
|
|
8238
|
+
instructionPlugin,
|
|
8239
|
+
skillPlugin
|
|
7935
8240
|
]);
|
|
7936
8241
|
//#endregion
|
|
7937
8242
|
//#region src/plugin/error.ts
|
|
@@ -8371,7 +8676,7 @@ const isPath = (reference) => reference.startsWith("file:") || reference.startsW
|
|
|
8371
8676
|
* - a **CLI argument** anchors to the process's startup directory, because that is where the
|
|
8372
8677
|
* person typed it.
|
|
8373
8678
|
*/
|
|
8374
|
-
const parse$
|
|
8679
|
+
const parse$2 = (reference, from) => Effect.gen(function* () {
|
|
8375
8680
|
const fail = (reason, message) => new SourceError({
|
|
8376
8681
|
reason,
|
|
8377
8682
|
reference,
|
|
@@ -9047,7 +9352,7 @@ const inspect = Effect.fn("PluginLoader.inspect")(function* (reference, options)
|
|
|
9047
9352
|
reference,
|
|
9048
9353
|
file: options.file
|
|
9049
9354
|
};
|
|
9050
|
-
const target = yield* parse$
|
|
9355
|
+
const target = yield* parse$2(reference, options.hostDir);
|
|
9051
9356
|
const loaded = yield* load$2(target, origin, options);
|
|
9052
9357
|
return {
|
|
9053
9358
|
id: loaded.plugin.id,
|
|
@@ -9073,7 +9378,7 @@ const load$2 = Effect.fn("PluginLoader.load")(function* (target, origin, options
|
|
|
9073
9378
|
* are one package, and `./plugins/x.ts` is the file it resolves to from the directory that
|
|
9074
9379
|
* declared it. Pure -- nothing is installed, imported or read.
|
|
9075
9380
|
*/
|
|
9076
|
-
const canonical = (reference, hostDir) => Effect.map(parse$
|
|
9381
|
+
const canonical = (reference, hostDir) => Effect.map(parse$2(reference, hostDir), canonical$1);
|
|
9077
9382
|
//#endregion
|
|
9078
9383
|
//#region src/plugin/catalog.ts
|
|
9079
9384
|
/**
|
|
@@ -9135,7 +9440,7 @@ const load$1 = Effect.fn("PluginCatalog.load")(function* (references, options) {
|
|
|
9135
9440
|
remember(plugin, []);
|
|
9136
9441
|
continue;
|
|
9137
9442
|
}
|
|
9138
|
-
const target = yield* parse$
|
|
9443
|
+
const target = yield* parse$2(reference, options.hostDir);
|
|
9139
9444
|
const key = target.kind === "local" ? target.path : target.spec;
|
|
9140
9445
|
const already = seen.get(key);
|
|
9141
9446
|
if (already !== void 0) {
|
|
@@ -11318,7 +11623,7 @@ var harness_exports = /* @__PURE__ */ __exportAll({
|
|
|
11318
11623
|
const layer = (options = {}) => Layer.unwrap(Effect.gen(function* () {
|
|
11319
11624
|
const hostCwd = options.hostCwd ?? process.cwd();
|
|
11320
11625
|
const paths = yield* resolve$4(options.home === void 0 ? {} : { home: hostPath.resolve(hostCwd, expandTilde(options.home, hostPath)) });
|
|
11321
|
-
const global = layerWith(paths);
|
|
11626
|
+
const global = layerWith$1(paths);
|
|
11322
11627
|
const settingsOptions = options.userConfigDir === void 0 ? {} : { userConfigDir: userConfigDir(options.userConfigDir, hostCwd) };
|
|
11323
11628
|
const config = yield* load$3({
|
|
11324
11629
|
...settingsOptions,
|
|
@@ -11337,7 +11642,7 @@ const layer = (options = {}) => Layer.unwrap(Effect.gen(function* () {
|
|
|
11337
11642
|
* `hostDir` led to; only the process view falls back to `hostCwd`.
|
|
11338
11643
|
*/
|
|
11339
11644
|
const hostDirOf = (root) => root ?? hostCwd;
|
|
11340
|
-
const filed = (reference, from) => parse$
|
|
11645
|
+
const filed = (reference, from) => parse$2(reference, from).pipe(Effect.flatMap((target) => target.kind === "local" ? fileSystem.exists(target.path).pipe(Effect.map((there) => there ? Option.some({}) : Option.none())) : resolve$2(target, paths.cache, from).pipe(Effect.map((entry) => Option.fromUndefinedOr(entry)))), Effect.orElseSucceed(() => Option.none()));
|
|
11341
11646
|
const resolveOnly = {
|
|
11342
11647
|
...catalogOptions,
|
|
11343
11648
|
install: required
|
|
@@ -11579,13 +11884,24 @@ const makeHandle = Effect.fn("Session.makeHandle")(function* (id) {
|
|
|
11579
11884
|
const space = Option.getOrUndefined(yield* sessions.space(id));
|
|
11580
11885
|
const sandbox = space === void 0 || space.env === instance_exports.SandboxInstance.ID.local ? void 0 : Option.getOrUndefined(yield* sandboxes.get(space.env));
|
|
11581
11886
|
const hostDir = Option.getOrUndefined(row.hostDir);
|
|
11887
|
+
const project = Option.getOrUndefined(yield* sessions.project(id));
|
|
11888
|
+
const config = Option.getOrUndefined(row.config);
|
|
11889
|
+
const model = config?.model;
|
|
11890
|
+
const thinkingLevel = config?.thinkingLevel;
|
|
11582
11891
|
return {
|
|
11583
11892
|
id,
|
|
11584
11893
|
title: row.title,
|
|
11585
11894
|
directory: row.directory,
|
|
11586
11895
|
...hostDir === void 0 ? {} : { hostDir },
|
|
11587
11896
|
hasHostLink: hostDir !== void 0,
|
|
11588
|
-
...sandbox === void 0 ? {} : { sandbox }
|
|
11897
|
+
...sandbox === void 0 ? {} : { sandbox },
|
|
11898
|
+
...project === void 0 ? {} : { project: {
|
|
11899
|
+
id: project.id,
|
|
11900
|
+
name: project.name
|
|
11901
|
+
} },
|
|
11902
|
+
updatedAt: DateTime.toEpochMillis(row.updatedAt),
|
|
11903
|
+
...model === void 0 ? {} : { model },
|
|
11904
|
+
...thinkingLevel === void 0 ? {} : { thinkingLevel }
|
|
11589
11905
|
};
|
|
11590
11906
|
}).pipe(Effect.withSpan("Session.info"));
|
|
11591
11907
|
return {
|
|
@@ -11613,7 +11929,7 @@ const create$1 = Effect.fn("Session.create")(function* (input = {}) {
|
|
|
11613
11929
|
const sandboxes = yield* Controller;
|
|
11614
11930
|
const id = ID$1.create();
|
|
11615
11931
|
const sandboxId = input.sandbox?.id ?? instance_exports.SandboxInstance.ID.local;
|
|
11616
|
-
const location = yield* sandboxes.withMount(sandboxId, Effect.provide(Service$8.use(Effect.succeed), layerMounted()), input.directory === void 0 ? void 0 : { cwd: input.directory });
|
|
11932
|
+
const location = yield* sandboxes.withMount(sandboxId, Effect.provide(Service$8.use(Effect.succeed), layerMounted(input.project === void 0 ? void 0 : { name: input.project.name })), input.directory === void 0 ? void 0 : { cwd: input.directory });
|
|
11617
11933
|
yield* sessions.create({
|
|
11618
11934
|
id,
|
|
11619
11935
|
spaceId: location.space.id,
|
|
@@ -11727,7 +12043,7 @@ var plugin_exports = /* @__PURE__ */ __exportAll({
|
|
|
11727
12043
|
inspect: () => inspect,
|
|
11728
12044
|
lendResolve: () => lendResolve,
|
|
11729
12045
|
localName: () => localName,
|
|
11730
|
-
parse: () => parse$
|
|
12046
|
+
parse: () => parse$2,
|
|
11731
12047
|
probe: () => probe,
|
|
11732
12048
|
resolve: () => resolve$2,
|
|
11733
12049
|
resolveCached: () => required,
|
|
@@ -11740,6 +12056,6 @@ var DateTimeUtcFromMillis = schema_exports$9.DateTimeUtcFromMillis;
|
|
|
11740
12056
|
var EventSchema = schema_exports$7.EventSchema;
|
|
11741
12057
|
var SandboxError = errors_exports.SandboxError;
|
|
11742
12058
|
var optional = schema_exports$9.optional;
|
|
11743
|
-
export { control_exports as Control, db_exports as Database, DateTimeUtcFromMillis, event_exports as Event, list_exports as EventList, registry_exports as EventRegistry, EventSchema, global_exports as Global, harness_exports as Harness, location_exports as Location, catalog_exports as ModelCatalog, plugin_exports as Plugin, schema_exports as PromptSchema, run_exports as Runner, sandbox_exports as Sandbox, SandboxError, session_exports as Session, session_exports$1 as SessionStore, settings_exports as Settings, state_exports as State, tool_exports as Tool, optional };
|
|
12059
|
+
export { control_exports as Control, db_exports as Database, DateTimeUtcFromMillis, event_exports as Event, list_exports as EventList, registry_exports as EventRegistry, EventSchema, global_exports as Global, harness_exports as Harness, location_exports as Location, catalog_exports as ModelCatalog, plugin_exports as Plugin, project_exports as Project, schema_exports as PromptSchema, run_exports as Runner, sandbox_exports as Sandbox, SandboxError, session_exports as Session, session_exports$1 as SessionStore, settings_exports as Settings, state_exports as State, tool_exports as Tool, optional };
|
|
11744
12060
|
|
|
11745
12061
|
//# sourceMappingURL=effect.mjs.map
|