@mikode13/harness 9.3.1 → 10.0.0
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/README.md +63 -7
- package/dist/agent/domain/agent.d.ts +11 -5
- package/dist/agent/domain/agent.js.map +1 -1
- package/dist/agent/domain/approval.d.ts +2 -1
- package/dist/agent/domain/approval.js +2 -1
- package/dist/agent/domain/approval.js.map +1 -1
- package/dist/agent/domain/question.d.ts +5 -0
- package/dist/agent/domain/question.js +11 -0
- package/dist/agent/domain/question.js.map +1 -1
- package/dist/agent/domain/runContext.d.ts +17 -0
- package/dist/agent/domain/runContext.js +9 -0
- package/dist/agent/domain/runContext.js.map +1 -1
- package/dist/agent/domain/transcript.d.ts +10 -0
- package/dist/agent/domain/transcript.js.map +1 -1
- package/dist/engines/domain/model/askUser.d.ts +0 -5
- package/dist/engines/domain/model/askUser.js +0 -9
- package/dist/engines/domain/model/askUser.js.map +1 -1
- package/dist/engines/domain/model/llmAgent.d.ts +19 -3
- package/dist/engines/domain/model/llmAgent.js +141 -51
- package/dist/engines/domain/model/llmAgent.js.map +1 -1
- package/dist/factory/infrastructure/agentLLMFactory.d.ts +6 -2
- package/dist/factory/infrastructure/agentLLMFactory.js +1 -1
- package/dist/factory/infrastructure/agentLLMFactory.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/domain/preparedCall.d.ts +14 -0
- package/dist/tools/domain/preparedCall.js +12 -0
- package/dist/tools/domain/preparedCall.js.map +1 -1
- package/dist/tools/domain/readRegistry.d.ts +7 -0
- package/dist/tools/domain/readRegistry.js.map +1 -1
- package/dist/tools/infrastructure/agentAsTool.d.ts +61 -0
- package/dist/tools/infrastructure/agentAsTool.js +144 -0
- package/dist/tools/infrastructure/agentAsTool.js.map +1 -0
- package/dist/tools/infrastructure/commandTool.js +6 -2
- package/dist/tools/infrastructure/commandTool.js.map +1 -1
- package/dist/tools/infrastructure/exploreTool.js +9 -22
- package/dist/tools/infrastructure/exploreTool.js.map +1 -1
- package/dist/tools/infrastructure/fileEditor.d.ts +2 -0
- package/dist/tools/infrastructure/fileEditor.js +5 -1
- package/dist/tools/infrastructure/fileEditor.js.map +1 -1
- package/dist/tools/infrastructure/fileFormatter.d.ts +1 -0
- package/dist/tools/infrastructure/fileFormatter.js +5 -1
- package/dist/tools/infrastructure/fileFormatter.js.map +1 -1
- package/dist/tools/infrastructure/subagents.d.ts +19 -0
- package/dist/tools/infrastructure/subagents.js +29 -0
- package/dist/tools/infrastructure/subagents.js.map +1 -0
- package/dist/tools/infrastructure/writeSession.d.ts +8 -0
- package/dist/tools/infrastructure/writeSession.js +37 -0
- package/dist/tools/infrastructure/writeSession.js.map +1 -1
- package/package.json +1 -1
|
@@ -16,6 +16,8 @@ export class WriteSession {
|
|
|
16
16
|
journal;
|
|
17
17
|
changes = 0;
|
|
18
18
|
stopped;
|
|
19
|
+
// The end of the last write waiting or running, which the next one starts after.
|
|
20
|
+
writing = Promise.resolve();
|
|
19
21
|
constructor({ store, maxChanges = defaultMaxChanges, onStart, onDiscard, }) {
|
|
20
22
|
this.store = store;
|
|
21
23
|
this.maxChanges = maxChanges;
|
|
@@ -50,6 +52,28 @@ export class WriteSession {
|
|
|
50
52
|
this.changes++;
|
|
51
53
|
return journal;
|
|
52
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Runs `write` once every write before it has ended, so agents of one run that work at once
|
|
57
|
+
* never change files together: each change is read, recorded and made alone, and a command
|
|
58
|
+
* runs with no other write while the files are captured around it. A cancellation stops the
|
|
59
|
+
* wait.
|
|
60
|
+
*/
|
|
61
|
+
async exclusive(write, signal) {
|
|
62
|
+
const before = this.writing;
|
|
63
|
+
let release;
|
|
64
|
+
this.writing = new Promise(resolve => {
|
|
65
|
+
release = resolve;
|
|
66
|
+
});
|
|
67
|
+
try {
|
|
68
|
+
await untilAborted(before, signal);
|
|
69
|
+
signal.throwIfAborted();
|
|
70
|
+
return await write();
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
// Released even when cancelled while waiting: the writes after it wait for those before.
|
|
74
|
+
void before.then(release, release);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
53
77
|
/** Refuses every further write, for this reason. The first reason given is kept. */
|
|
54
78
|
stop(reason) {
|
|
55
79
|
this.stopped ??= reason;
|
|
@@ -78,4 +102,17 @@ export class WriteSession {
|
|
|
78
102
|
}
|
|
79
103
|
}
|
|
80
104
|
}
|
|
105
|
+
/** Waits for `promise`, settled either way, or until `signal` aborts, whichever comes first. */
|
|
106
|
+
function untilAborted(promise, signal) {
|
|
107
|
+
if (signal.aborted)
|
|
108
|
+
return Promise.resolve();
|
|
109
|
+
return new Promise(resolve => {
|
|
110
|
+
const done = () => {
|
|
111
|
+
signal.removeEventListener('abort', done);
|
|
112
|
+
resolve();
|
|
113
|
+
};
|
|
114
|
+
signal.addEventListener('abort', done, { once: true });
|
|
115
|
+
promise.then(done, done);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
81
118
|
//# sourceMappingURL=writeSession.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeSession.js","sourceRoot":"","sources":["../../../src/tools/infrastructure/writeSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,kBAAkB,GAClB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,iFAAiF;AACjF,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IACP,KAAK,CAAgB;IACrB,UAAU,CAAS;IACnB,OAAO,CAAwC;IAC/C,SAAS,CAA2B;IAC7C,OAAO,CAAkC;IACzC,OAAO,GAAG,CAAC,CAAC;IACZ,OAAO,CAAqB;
|
|
1
|
+
{"version":3,"file":"writeSession.js","sourceRoot":"","sources":["../../../src/tools/infrastructure/writeSession.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype RecoveryStore,\n\ttype RunJournal,\n\ttype RunStatus,\n\tWorkspaceBusyError,\n} from '#src/recovery/domain/recoveryStore';\nimport { EditRefusedError } from '../domain/fileEdits.ts';\n\n// Far more than a task needs; a run past it is more likely looping than working.\nconst defaultMaxChanges = 500;\n\n/**\n * Everything one top-level run writes, across all its roles and rounds. Its journal starts on\n * the first write, so a run that only reads never holds the workspace, and ends with the run.\n * Once a change could not be confirmed, the session refuses every further write: the record of\n * what the run did must stay complete.\n */\nexport class WriteSession {\n\tprivate readonly store: RecoveryStore;\n\tprivate readonly maxChanges: number;\n\tprivate readonly onStart: ((runId: string) => void) | undefined;\n\tprivate readonly onDiscard: (() => void) | undefined;\n\tprivate journal: Promise<RunJournal> | undefined;\n\tprivate changes = 0;\n\tprivate stopped: string | undefined;\n\t// The end of the last write waiting or running, which the next one starts after.\n\tprivate writing: Promise<unknown> = Promise.resolve();\n\n\tconstructor({\n\t\tstore,\n\t\tmaxChanges = defaultMaxChanges,\n\t\tonStart,\n\t\tonDiscard,\n\t}: {\n\t\tstore: RecoveryStore;\n\t\tmaxChanges?: number;\n\t\t/** Told the run's id once its journal has started, before its first change is recorded. */\n\t\tonStart?: (runId: string) => void;\n\t\t/** Told when the run ended having changed nothing, so the history no longer has it. */\n\t\tonDiscard?: () => void;\n\t}) {\n\t\tthis.store = store;\n\t\tthis.maxChanges = maxChanges;\n\t\tthis.onStart = onStart;\n\t\tthis.onDiscard = onDiscard;\n\t}\n\n\t/** The journal for one more change, counted against the run's limit. */\n\tasync journalForChange(): Promise<RunJournal> {\n\t\tif (this.stopped !== undefined) throw new EditRefusedError(this.stopped);\n\t\tif (this.changes >= this.maxChanges) {\n\t\t\tthrow new EditRefusedError(\n\t\t\t\t`This run has made ${String(this.maxChanges)} changes, the most one run may make`,\n\t\t\t);\n\t\t}\n\n\t\tthis.journal ??= this.store.startRun().then(started => {\n\t\t\tthis.onStart?.(started.runId);\n\t\t\treturn started;\n\t\t});\n\t\tlet journal: RunJournal;\n\t\ttry {\n\t\t\tjournal = await this.journal;\n\t\t} catch (error) {\n\t\t\t// A failed start is not kept, so the next change tries again.\n\t\t\tthis.journal = undefined;\n\t\t\tif (error instanceof WorkspaceBusyError) {\n\t\t\t\tthrow new EditRefusedError(\n\t\t\t\t\t'Another run, or a move through its history, holds this workspace, so nothing was changed',\n\t\t\t\t\t{\n\t\t\t\t\t\tcause: error,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new EditRefusedError(\n\t\t\t\t'The harness could not start recording this run, so nothing was changed',\n\t\t\t\t{ cause: error },\n\t\t\t);\n\t\t}\n\t\tthis.changes++;\n\t\treturn journal;\n\t}\n\n\t/**\n\t * Runs `write` once every write before it has ended, so agents of one run that work at once\n\t * never change files together: each change is read, recorded and made alone, and a command\n\t * runs with no other write while the files are captured around it. A cancellation stops the\n\t * wait.\n\t */\n\tasync exclusive<Result>(write: () => Promise<Result>, signal: AbortSignal): Promise<Result> {\n\t\tconst before = this.writing;\n\t\tlet release!: () => void;\n\t\tthis.writing = new Promise<void>(resolve => {\n\t\t\trelease = resolve;\n\t\t});\n\t\ttry {\n\t\t\tawait untilAborted(before, signal);\n\t\t\tsignal.throwIfAborted();\n\t\t\treturn await write();\n\t\t} finally {\n\t\t\t// Released even when cancelled while waiting: the writes after it wait for those before.\n\t\t\tvoid before.then(release, release);\n\t\t}\n\t}\n\n\t/** Refuses every further write, for this reason. The first reason given is kept. */\n\tstop(reason: string): void {\n\t\tthis.stopped ??= reason;\n\t}\n\n\t/** The run's id once it has written, which is what an undo needs. */\n\tasync runId(): Promise<string | undefined> {\n\t\tconst journal = await this.journal?.catch(() => undefined);\n\t\treturn journal?.runId;\n\t}\n\n\t/**\n\t * Ends the run's record and releases the workspace. A run that never wrote has nothing to end,\n\t * and one whose every change was abandoned leaves the history.\n\t */\n\tasync finish(status: Exclude<RunStatus, 'running' | 'interrupted'>): Promise<void> {\n\t\tconst journal = await this.journal?.catch(() => undefined);\n\t\tthis.journal = undefined;\n\t\tif (!journal) return;\n\t\ttry {\n\t\t\tawait journal.finish(status);\n\t\t} finally {\n\t\t\t// Even when finishing failed: a run that changed nothing is out of the history either way.\n\t\t\tif (!journal.changed) this.onDiscard?.();\n\t\t}\n\t}\n}\n\n/** Waits for `promise`, settled either way, or until `signal` aborts, whichever comes first. */\nfunction untilAborted(promise: Promise<unknown>, signal: AbortSignal): Promise<void> {\n\tif (signal.aborted) return Promise.resolve();\n\treturn new Promise(resolve => {\n\t\tconst done = () => {\n\t\t\tsignal.removeEventListener('abort', done);\n\t\t\tresolve();\n\t\t};\n\t\tsignal.addEventListener('abort', done, { once: true });\n\t\tpromise.then(done, done);\n\t});\n}\n"]}
|