copilot-operator 0.1.17 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/api/operator.service.js +23 -2
- package/dist/src/orchestrator/derivedChecks.js +19 -1
- package/dist/src/orchestrator/review.js +2 -2
- package/dist/src/orchestrator/taskRunner.js +81 -8
- package/dist/src/plan/brief.js +26 -0
- package/dist/src/plan/importPlan.js +28 -1
- package/dist/src/plan/schema.js +38 -0
- package/dist/src/plan/systemGuide.js +40 -0
- package/dist/src/protocol/replySchema.js +1 -1
- package/dist/src/protocol/reviewSchema.js +10 -5
- package/dist/src/session/exports.js +44 -13
- package/dist/src/session/model.js +20 -0
- package/dist/src/session/store.js +78 -0
- package/dist/src/vcs/artifacts.js +138 -0
- package/dist/src/vcs/inputs.js +332 -0
- package/dist/src/vcs/snapshot.js +59 -18
- package/dist/src/vcs/taskVcs.js +136 -25
- package/dist/web/404.html +2 -2
- package/dist/web/_next/static/chunks/549-5d7c845fb0a27dbe.js +1 -0
- package/dist/web/_next/static/chunks/867-c078b5b504bf4289.js +1 -0
- package/dist/web/_next/static/chunks/app/history/page-a0bd59986f7c8beb.js +1 -0
- package/dist/web/_next/static/chunks/app/sessions/view/page-27cb2d544b498d92.js +1 -0
- package/dist/web/appearance.html +2 -2
- package/dist/web/appearance.txt +11 -11
- package/dist/web/defaults.html +2 -2
- package/dist/web/defaults.txt +11 -11
- package/dist/web/history.html +2 -2
- package/dist/web/history.txt +11 -11
- package/dist/web/import.html +2 -2
- package/dist/web/import.txt +11 -11
- package/dist/web/index.html +2 -2
- package/dist/web/index.txt +11 -11
- package/dist/web/level1.html +2 -2
- package/dist/web/level1.txt +11 -11
- package/dist/web/presets.html +2 -2
- package/dist/web/presets.txt +11 -11
- package/dist/web/sessions/view.html +2 -2
- package/dist/web/sessions/view.txt +11 -11
- package/dist/web/system.html +2 -2
- package/dist/web/system.txt +11 -11
- package/package.json +7 -3
- package/prompts/level1.md +547 -546
- package/dist/web/_next/static/chunks/549-a13ae394c5e6a837.js +0 -1
- package/dist/web/_next/static/chunks/867-7f27ef819d251cc5.js +0 -1
- package/dist/web/_next/static/chunks/app/history/page-d7314ac22d47a3ab.js +0 -1
- package/dist/web/_next/static/chunks/app/sessions/view/page-d28825430ca280de.js +0 -1
- /package/dist/web/_next/static/{kkxFcGzA9Uo1uRAgcoDti → JPmlfAEvbNkbghoyvY9uC}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{kkxFcGzA9Uo1uRAgcoDti → JPmlfAEvbNkbghoyvY9uC}/_ssgManifest.js +0 -0
package/dist/src/vcs/snapshot.js
CHANGED
|
@@ -22,12 +22,15 @@
|
|
|
22
22
|
* Like the rest of `vcs/`: nothing is reset, stashed, deleted or rewritten. The snapshot adds a
|
|
23
23
|
* branch and a commit.
|
|
24
24
|
*/
|
|
25
|
-
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
25
|
+
import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
26
26
|
import { tmpdir } from 'node:os';
|
|
27
27
|
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
28
28
|
import { looksGenerated } from './commitHygiene.js';
|
|
29
29
|
import { branchNameFrom, freeBranchName, git, gitBytes, isValidBranchName, RUNNER_EMAIL } from './git.js';
|
|
30
30
|
import { repoDirOf, sessionStart } from './taskVcs.js';
|
|
31
|
+
import { inputFilesInTree, inputSettings } from './inputs.js';
|
|
32
|
+
import { artifactPatterns } from './artifacts.js';
|
|
33
|
+
import { inScope } from './scope.js';
|
|
31
34
|
/** The session's dirty-tree policy, absent fields filled in: reject, and asking first. */
|
|
32
35
|
export function dirtyPolicy(vcs) {
|
|
33
36
|
const policy = vcs?.dirtyWorktree?.policy;
|
|
@@ -128,9 +131,10 @@ async function startProblem(session, dir, branch, head, allSessions) {
|
|
|
128
131
|
*/
|
|
129
132
|
export async function planSnapshot(session, allSessions = async () => []) {
|
|
130
133
|
const { policy, requireApproval } = dirtyPolicy(session.vcs);
|
|
134
|
+
const inputs = inputSettings(session.vcs);
|
|
131
135
|
const repoDir = repoDirOf(session);
|
|
132
136
|
const plan = { needed: false, ok: false, policy, requireApproval, repoDir, branch: null, head: null, entries: [] };
|
|
133
|
-
if (!session.vcs?.enabled || policy === 'reject' || session.vcsBaseCommit)
|
|
137
|
+
if (!session.vcs?.enabled || (policy === 'reject' && !inputs) || session.vcsBaseCommit)
|
|
134
138
|
return plan;
|
|
135
139
|
const top = repoDir ? await topOf(repoDir) : null;
|
|
136
140
|
if (!top)
|
|
@@ -142,13 +146,43 @@ export async function planSnapshot(session, allSessions = async () => []) {
|
|
|
142
146
|
const headR = await git(top, ['rev-parse', '--verify', '--quiet', 'HEAD']);
|
|
143
147
|
plan.branch = branchR.ok && branchR.stdout !== 'HEAD' ? branchR.stdout : null;
|
|
144
148
|
plan.head = headR.ok && headR.stdout ? headR.stdout : null;
|
|
145
|
-
if (status.length === 0)
|
|
146
|
-
return plan;
|
|
147
|
-
plan.needed = true;
|
|
148
149
|
// The project folder, when it is a folder inside the repository: a change outside it is not this session's.
|
|
149
150
|
const project = session.projectDir?.trim() ? relative(top, resolve(session.projectDir.trim())).replace(/\\/g, '/') : '';
|
|
150
151
|
const inProject = (p) => !project || project.startsWith('..') || isAbsolute(project) || p.toLowerCase() === project.toLowerCase() || p.toLowerCase().startsWith(`${project.toLowerCase()}/`);
|
|
151
|
-
|
|
152
|
+
const size = async (p) => (await stat(join(top, p)).catch(() => null))?.size;
|
|
153
|
+
/*
|
|
154
|
+
* The operator's input files that are not committed as they are: new, changed, or ignored. They
|
|
155
|
+
* are taken whatever the dirty-tree policy, or the snapshot is not; the rest of the tree is the
|
|
156
|
+
* policy's. A secrets file or one outside the project is never an input.
|
|
157
|
+
*/
|
|
158
|
+
const inputPaths = new Set();
|
|
159
|
+
if (inputs) {
|
|
160
|
+
const dirtyNow = new Set(status.map((s) => s.path));
|
|
161
|
+
for (const f of await inputFilesInTree(top, inputs.patterns)) {
|
|
162
|
+
if (f.kind === 'tracked' && !dirtyNow.has(f.path))
|
|
163
|
+
continue;
|
|
164
|
+
inputPaths.add(f.path);
|
|
165
|
+
const blocked = looksGenerated(f.path)?.reason === 'a secrets file' ? 'a secrets file is never taken as an input' : !inProject(f.path) ? `outside the project folder ${project}` : undefined;
|
|
166
|
+
plan.entries.push({ path: f.path, kind: f.kind, input: true, size: await size(f.path), allowed: blocked ? [] : ['include'], choice: blocked ? null : 'include', reason: blocked ?? 'an input file: committed with the starting snapshot, then read-only' });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const others = status.filter((s) => !inputPaths.has(s.path));
|
|
170
|
+
if (policy === 'reject') {
|
|
171
|
+
if (plan.entries.length === 0)
|
|
172
|
+
return plan;
|
|
173
|
+
plan.needed = true;
|
|
174
|
+
if (others.length > 0) {
|
|
175
|
+
plan.problem =
|
|
176
|
+
`besides the input files there are other uncommitted changes (${someOf(others.map((o) => o.path))}). ` +
|
|
177
|
+
'Commit them yourself, or choose "Take them as a starting snapshot" under "Uncommitted changes".';
|
|
178
|
+
return plan;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (plan.entries.length === 0 && others.length === 0)
|
|
182
|
+
return plan;
|
|
183
|
+
plan.needed = true;
|
|
184
|
+
plan.requireApproval = (others.length > 0 && requireApproval) || (plan.entries.some((e) => e.input) && !!inputs?.requireApproval);
|
|
185
|
+
for (const s of policy === 'reject' ? [] : others) {
|
|
152
186
|
const generated = looksGenerated(s.path);
|
|
153
187
|
const outside = !inProject(s.path);
|
|
154
188
|
if (!s.untracked) {
|
|
@@ -157,15 +191,18 @@ export async function planSnapshot(session, allSessions = async () => []) {
|
|
|
157
191
|
: outside
|
|
158
192
|
? `outside the project folder ${project}; it is tracked, so it cannot be left out. Commit or undo that change yourself`
|
|
159
193
|
: undefined;
|
|
160
|
-
plan.entries.push({ path: s.path, ...(s.from ? { from: s.from } : {}), kind: 'tracked', allowed: blocked ? [] : ['include'], choice: blocked ? null : 'include', ...(blocked ? { reason: blocked } : {}) });
|
|
194
|
+
plan.entries.push({ path: s.path, ...(s.from ? { from: s.from } : {}), kind: 'tracked', size: await size(s.path), allowed: blocked ? [] : ['include'], choice: blocked ? null : 'include', ...(blocked ? { reason: blocked } : {}) });
|
|
161
195
|
continue;
|
|
162
196
|
}
|
|
163
|
-
const
|
|
164
|
-
|
|
197
|
+
const artifact = artifactPatterns(session.vcs).length > 0 && inScope(s.path, artifactPatterns(session.vcs));
|
|
198
|
+
const why = artifact
|
|
199
|
+
? 'an artifact: kept with the run, never committed'
|
|
200
|
+
: generated ? generated.reason : outside ? `outside the project folder ${project}` : policy === 'tracked-only-snapshot' ? 'a new file, and this session takes tracked changes only' : undefined;
|
|
201
|
+
plan.entries.push({ path: s.path, kind: 'untracked', size: await size(s.path), allowed: why ? ['leave-out'] : ['include', 'leave-out'], choice: why ? 'leave-out' : 'include', ...(why ? { reason: why } : {}) });
|
|
165
202
|
}
|
|
166
203
|
if (policy === 'snapshot') {
|
|
167
204
|
for (const path of await scopedIgnored(top, scopedPatterns(session))) {
|
|
168
|
-
if (looksGenerated(path) || !inProject(path))
|
|
205
|
+
if (looksGenerated(path) || !inProject(path) || inputPaths.has(path))
|
|
169
206
|
continue;
|
|
170
207
|
plan.entries.push({ path, kind: 'ignored', allowed: ['include', 'leave-out'], choice: 'leave-out', reason: "ignored by git, and a task's scope names it: taken only when you tick it" });
|
|
171
208
|
}
|
|
@@ -215,16 +252,20 @@ async function leaveOut(top, session, paths) {
|
|
|
215
252
|
return undefined;
|
|
216
253
|
}
|
|
217
254
|
/** The commit message: what was taken, what was left out, from where, and on whose word. */
|
|
218
|
-
function snapshotMessage(session, plan,
|
|
255
|
+
function snapshotMessage(session, plan, taken, leftOut, approved) {
|
|
219
256
|
const list = (paths) => [...paths.slice(0, 200).map((p) => `- ${p}`), ...(paths.length > 200 ? [`- and ${paths.length - 200} more`] : [])].join('\n');
|
|
257
|
+
const inputs = taken.filter((e) => e.input);
|
|
258
|
+
const rest = taken.filter((e) => !e.input).map((e) => e.path);
|
|
259
|
+
const onlyInputs = rest.length === 0;
|
|
220
260
|
return [
|
|
221
|
-
'Capture operator baseline before run',
|
|
261
|
+
onlyInputs ? 'Capture user-provided inputs' : 'Capture operator baseline before run',
|
|
222
262
|
'',
|
|
223
|
-
`The uncommitted changes in the repository when session "${session.name}" was first run, committed so that`,
|
|
263
|
+
`The ${onlyInputs ? "operator's input files" : 'uncommitted changes in the repository'} when session "${session.name}" was first run, committed so that`,
|
|
224
264
|
"the session starts from them and every task's commit shows only that task's work.",
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
265
|
+
...(inputs.length > 0
|
|
266
|
+
? ['', `Input files, read by the work and not changed by it (${inputs.length}):`, list(inputs.map((e) => `${e.path}${e.size !== undefined ? ` (${e.size} bytes, ${e.kind})` : ''}`))]
|
|
267
|
+
: []),
|
|
268
|
+
...(rest.length > 0 ? ['', `Taken (${rest.length}):`, list(rest)] : []),
|
|
228
269
|
...(leftOut.length > 0 ? ['', `Left out, in .git/info/exclude (${leftOut.length}):`, list(leftOut)] : []),
|
|
229
270
|
'',
|
|
230
271
|
`Taken from ${plan.branch ?? 'a detached HEAD'} at ${(plan.head ?? '').slice(0, 8)}, ${approved ? "on the operator's approval of this list" : 'automatically (requireApproval: false)'}.`,
|
|
@@ -240,7 +281,7 @@ function snapshotMessage(session, plan, included, leftOut, approved) {
|
|
|
240
281
|
* `approved`, every file takes its default and anything to be left out refuses (see `DirtyWorktree`).
|
|
241
282
|
*/
|
|
242
283
|
export async function takeSnapshot(session, opts, bus, saveSession, allSessions = async () => []) {
|
|
243
|
-
if (dirtyPolicy(session.vcs).policy === 'reject') {
|
|
284
|
+
if (dirtyPolicy(session.vcs).policy === 'reject' && !inputSettings(session.vcs)) {
|
|
244
285
|
return { ok: false, problem: 'this session does not take uncommitted changes as a snapshot. Choose that under Version control → "Uncommitted changes" first.' };
|
|
245
286
|
}
|
|
246
287
|
if (session.vcsBaseCommit)
|
|
@@ -320,7 +361,7 @@ export async function takeSnapshot(session, opts, bus, saveSession, allSessions
|
|
|
320
361
|
finally {
|
|
321
362
|
await rm(list, { force: true });
|
|
322
363
|
}
|
|
323
|
-
const message = snapshotMessage(session, plan, take
|
|
364
|
+
const message = snapshotMessage(session, plan, take, leftOutAll, opts.approved);
|
|
324
365
|
const commit = await git(top, ['-c', 'user.name=copilot-operator', '-c', `user.email=${RUNNER_EMAIL}`, 'commit', '--no-verify', '-q', '-m', message]);
|
|
325
366
|
if (!commit.ok)
|
|
326
367
|
return await back(`the snapshot could not be committed: ${commit.stderr || commit.stdout}.`);
|
package/dist/src/vcs/taskVcs.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { findSuspicious } from './commitHygiene.js';
|
|
2
2
|
import { dirtyPolicy, planSnapshot, someOf, takeSnapshot } from './snapshot.js';
|
|
3
|
+
import { inputSettings, inputsNote, settleInputs } from './inputs.js';
|
|
4
|
+
import { artifactPatterns, excludeArtifacts } from './artifacts.js';
|
|
5
|
+
import { workingTreePaths } from './git.js';
|
|
6
|
+
import { inScope } from './scope.js';
|
|
3
7
|
import { branchExists, branchNameFrom, describeUpdate, updateFromRemote, localBranches, commitAll, commitFiles, commitsBetween, commitSubject, createBranch, foreignCommits, isAncestor, checkoutExisting, freeBranchName, git, isValidBranchName, plannedBranchName, repoState } from './git.js';
|
|
4
8
|
/** Which repository a session works in: its own setting, else the project it mirrors. */
|
|
5
9
|
export function repoDirOf(session) {
|
|
@@ -38,35 +42,56 @@ allSessions = async () => []) {
|
|
|
38
42
|
message: `version control is on but inactive: ${problem}` });
|
|
39
43
|
return { vcs: { problem }, note: '' };
|
|
40
44
|
}
|
|
45
|
+
const refuse = (why) => {
|
|
46
|
+
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-refused', level: 'error', message: why });
|
|
47
|
+
return { vcs: { problem: why }, note: '', refuse: why };
|
|
48
|
+
};
|
|
49
|
+
/*
|
|
50
|
+
* The session's artifacts are never committed: their patterns go into the repository's own
|
|
51
|
+
* exclude file before anything looks at the tree, so they neither make it dirty nor go into a
|
|
52
|
+
* commit. See `artifacts.ts`.
|
|
53
|
+
*/
|
|
54
|
+
const excluded = await excludeArtifacts(dir, session);
|
|
55
|
+
if (excluded.problem)
|
|
56
|
+
return refuse(`the session's artifacts could not be kept out of git: ${excluded.problem}. Nothing was run.`);
|
|
57
|
+
if (excluded.tracked.length > 0) {
|
|
58
|
+
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-artifacts-tracked', level: 'warn',
|
|
59
|
+
message: `${excluded.tracked.length} artifact file(s) are already tracked by git, so a change to them is still committed: ${someOf(excluded.tracked)}. Take them out of git yourself (git rm --cached) if they should not be.` });
|
|
60
|
+
}
|
|
61
|
+
if (excluded.tracked.length > 0 || artifactPatterns(settings).length > 0)
|
|
62
|
+
state = await repoState(dir);
|
|
41
63
|
if (settings.startFrom === 'existing-branch')
|
|
42
|
-
return await onExistingBranch(session, task, dir, state, bus, saveSession);
|
|
64
|
+
return await onExistingBranch(session, task, dir, state, bus, saveSession, allSessions);
|
|
43
65
|
// The session's base is fixed the first time it runs: every per-task branch is cut from it,
|
|
44
66
|
// which is what makes the tasks independent of each other rather than of the calendar. Where
|
|
45
67
|
// it is taken from is the session's `startFrom`; see `sessionStart`.
|
|
46
68
|
let base = session.vcsBaseCommit;
|
|
47
69
|
let start = session.vcsStart;
|
|
48
70
|
/*
|
|
49
|
-
* The operator's own changes before the session's first task
|
|
50
|
-
* become the commit the session starts from (see `snapshot.ts`). Asked for
|
|
51
|
-
* refused until the list has been approved on the session's page; running
|
|
52
|
-
* control instead would be the one outcome the operator chose against.
|
|
71
|
+
* The operator's own changes before the session's first task — under a snapshot policy, or its
|
|
72
|
+
* input files: they become the commit the session starts from (see `snapshot.ts`). Asked for
|
|
73
|
+
* approval, the run is refused until the list has been approved on the session's page; running
|
|
74
|
+
* without version control instead would be the one outcome the operator chose against.
|
|
53
75
|
*/
|
|
54
76
|
const dirty = dirtyPolicy(settings);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
const inputs = inputSettings(settings);
|
|
78
|
+
// Input files are looked for even in a clean tree: an ignored input does not make it dirty.
|
|
79
|
+
if ((state.dirty || inputs) && !base && (dirty.policy !== 'reject' || inputs)) {
|
|
80
|
+
const plan = await planSnapshot(session, allSessions);
|
|
81
|
+
if (plan.needed) {
|
|
82
|
+
if (!plan.ok)
|
|
83
|
+
return refuse(`the starting snapshot cannot be taken: ${plan.problem} Nothing was run.`);
|
|
84
|
+
if (plan.requireApproval) {
|
|
85
|
+
return refuse(`the repository has uncommitted changes (${someOf(plan.entries.map((e) => e.path))}), and this session takes them as its starting snapshot ` +
|
|
86
|
+
'once you have approved the list: on the session\'s page, Version control → "Uncommitted changes", choose what goes in and take the snapshot. Nothing was run.');
|
|
87
|
+
}
|
|
88
|
+
const taken = await takeSnapshot(session, { approved: false }, bus, saveSession, allSessions);
|
|
89
|
+
if (!taken.ok)
|
|
90
|
+
return refuse(`the starting snapshot of the uncommitted changes was not taken: ${taken.problem} Nothing was run.`);
|
|
91
|
+
base = taken.start.commit;
|
|
92
|
+
start = taken.start;
|
|
93
|
+
state = await repoState(dir);
|
|
63
94
|
}
|
|
64
|
-
const taken = await takeSnapshot(session, { approved: false }, bus, saveSession, allSessions);
|
|
65
|
-
if (!taken.ok)
|
|
66
|
-
return refuse(`the starting snapshot of the uncommitted changes was not taken: ${taken.problem} Nothing was run.`);
|
|
67
|
-
base = taken.start.commit;
|
|
68
|
-
start = taken.start;
|
|
69
|
-
state = await repoState(dir);
|
|
70
95
|
}
|
|
71
96
|
// A dirty tree is the operator's own work in progress. Committing it under the bot's name
|
|
72
97
|
// or moving it to another branch would both be decisions that are not ours to make — unless
|
|
@@ -98,6 +123,24 @@ allSessions = async () => []) {
|
|
|
98
123
|
message: describeStart(chosen), data: { ...chosen } });
|
|
99
124
|
}
|
|
100
125
|
}
|
|
126
|
+
/*
|
|
127
|
+
* The operator's input files, in the commit the session starts from whatever its `startFrom`, with
|
|
128
|
+
* their sums on the record. Once per session: a start that has recorded them has them.
|
|
129
|
+
*/
|
|
130
|
+
if (inputs && start && !start.inputs) {
|
|
131
|
+
const settled = await settleInputs(session, dir, start, allSessions);
|
|
132
|
+
if ('problem' in settled)
|
|
133
|
+
return refuse(`${settled.problem} Nothing was run.`);
|
|
134
|
+
const chosen = settled.start;
|
|
135
|
+
start = chosen;
|
|
136
|
+
base = chosen.commit;
|
|
137
|
+
await saveSession((s) => {
|
|
138
|
+
s.vcsBaseCommit = chosen.commit;
|
|
139
|
+
s.vcsStart = chosen;
|
|
140
|
+
});
|
|
141
|
+
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-inputs', level: 'info',
|
|
142
|
+
message: describeInputs(chosen), data: { files: chosen.inputs?.files.length ?? 0, carried: chosen.inputs?.carried } });
|
|
143
|
+
}
|
|
101
144
|
const attempt = task.attempt ?? 1;
|
|
102
145
|
const prefix = settings.branchPrefix || 'cop/';
|
|
103
146
|
if (settings.branchMode === 'per-session') {
|
|
@@ -149,7 +192,7 @@ export function namedSessionBranch(vcs) {
|
|
|
149
192
|
* refuses the task before a message is sent. The first run records the branch's tip as where the
|
|
150
193
|
* session started, so the record and a restore know what was there before the work.
|
|
151
194
|
*/
|
|
152
|
-
async function onExistingBranch(session, task, dir, state, bus, saveSession) {
|
|
195
|
+
async function onExistingBranch(session, task, dir, state, bus, saveSession, allSessions) {
|
|
153
196
|
const wanted = (session.vcs?.existingBranch ?? '').trim();
|
|
154
197
|
const refuse = (why) => {
|
|
155
198
|
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-refused', level: 'error', message: why });
|
|
@@ -181,6 +224,24 @@ async function onExistingBranch(session, task, dir, state, bus, saveSession) {
|
|
|
181
224
|
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-start', level: updateWarns(chosen) ? 'warn' : 'info', message: describeStart(chosen), data: { ...chosen } });
|
|
182
225
|
}
|
|
183
226
|
}
|
|
227
|
+
/*
|
|
228
|
+
* The input files must already be on the branch, as they are: the runner commits nothing onto a
|
|
229
|
+
* branch the operator named, so one that lacks them, or has them otherwise, is refused.
|
|
230
|
+
*/
|
|
231
|
+
if (inputSettings(session.vcs) && start && !start.inputs) {
|
|
232
|
+
const settled = await settleInputs(session, dir, start, allSessions);
|
|
233
|
+
if ('problem' in settled)
|
|
234
|
+
return refuse(`${settled.problem} Nothing was run.`);
|
|
235
|
+
if (settled.start.commit !== start.commit) {
|
|
236
|
+
return refuse(`the input files are not on "${wanted}" as they were last committed (${settled.start.inputs?.carried?.from ?? 'elsewhere'}), and the runner does not commit onto a branch you named. ` +
|
|
237
|
+
`Commit them on "${wanted}" yourself. Nothing was run.`);
|
|
238
|
+
}
|
|
239
|
+
const chosen = settled.start;
|
|
240
|
+
start = chosen;
|
|
241
|
+
await saveSession((s) => {
|
|
242
|
+
s.vcsStart = chosen;
|
|
243
|
+
});
|
|
244
|
+
}
|
|
184
245
|
const prepared = await switchTo(session, task, dir, wanted, undefined, bus, { reuseExisting: true, mustExist: true, start });
|
|
185
246
|
return prepared.vcs.branch === wanted ? prepared : refuse(`the repository could not be put on "${wanted}": ${prepared.vcs.problem ?? 'unknown reason'}. Nothing was run.`);
|
|
186
247
|
}
|
|
@@ -228,6 +289,31 @@ export async function sessionStart(session, dir, head, allSessions) {
|
|
|
228
289
|
if (!tip) {
|
|
229
290
|
return await fromBranch(`the branch of the previous session "${best.session.name}" (${best.branch}) is no longer in the repository, so it starts from "${baseBranch}"`);
|
|
230
291
|
}
|
|
292
|
+
/*
|
|
293
|
+
* The whole of that session's done work, or nothing. In per-task mode every task has a branch of
|
|
294
|
+
* its own, all cut from one commit, so the branch of the task that finished last holds that task's
|
|
295
|
+
* work only — a chain that started there began without the files the earlier tasks had made,
|
|
296
|
+
* though they were in the repository on other branches. The runner does not merge them; it says
|
|
297
|
+
* which are missing and refuses, rather than start from part of the work as if it were all.
|
|
298
|
+
*/
|
|
299
|
+
const missing = [];
|
|
300
|
+
for (const t of best.session.tasks) {
|
|
301
|
+
if (t.status !== 'done')
|
|
302
|
+
continue;
|
|
303
|
+
const done = [{ vcs: t.vcs, at: t.finishedAt }, ...(t.attempts ?? []).map((a) => ({ vcs: a.vcs, at: a.finishedAt }))]
|
|
304
|
+
.filter((v) => !!v.vcs?.commit && !!v.vcs.branch)
|
|
305
|
+
.sort((a, b) => (b.at ?? '').localeCompare(a.at ?? ''))[0];
|
|
306
|
+
if (done?.vcs?.commit && !(await isAncestor(dir, done.vcs.commit, tip)))
|
|
307
|
+
missing.push(`"${t.title}" (on ${done.vcs.branch})`);
|
|
308
|
+
}
|
|
309
|
+
if (missing.length > 0) {
|
|
310
|
+
return {
|
|
311
|
+
problem: `this session continues the previous session "${best.session.name}", whose done work is not on one branch: ${best.branch} does not have ` +
|
|
312
|
+
`${missing.slice(0, 8).join(', ')}${missing.length > 8 ? `, and ${missing.length - 8} more` : ''}. ` +
|
|
313
|
+
'That session ran per task, so each task\'s work is on its own branch. Merge them into one branch and continue it ("Carry on an existing branch"), ' +
|
|
314
|
+
'or run that session "One branch for the whole session" so the next one can carry on from it.',
|
|
315
|
+
};
|
|
316
|
+
}
|
|
231
317
|
return { start: { kind: 'previous-session', commit: tip, branch: best.branch, fromSession: { id: best.session.id, name: best.session.name } } };
|
|
232
318
|
}
|
|
233
319
|
/**
|
|
@@ -271,6 +357,13 @@ export function describeStart(start) {
|
|
|
271
357
|
const updated = start.update ? ` (${describeUpdate(start.update)})` : '';
|
|
272
358
|
return start.note ? `${said}${updated} — ${start.note}` : `${said}${updated}`;
|
|
273
359
|
}
|
|
360
|
+
/** One line for the log: the session's input files, and whether the runner had to commit them on its start. */
|
|
361
|
+
export function describeInputs(start) {
|
|
362
|
+
const n = start.inputs?.files.length ?? 0;
|
|
363
|
+
const carried = start.inputs?.carried;
|
|
364
|
+
return (`${n} input file(s) in the session's start (${start.commit.slice(0, 8)})${start.inputs?.readOnly ? ', read-only' : ''}` +
|
|
365
|
+
(carried ? `: they were not in ${carried.onto.slice(0, 8)}, so they were committed on top of it as ${carried.branch}, from ${carried.from}` : ''));
|
|
366
|
+
}
|
|
274
367
|
/** Whether the update before a session's start is worth a warning: it did not bring the branch up to date. */
|
|
275
368
|
export function updateWarns(start) {
|
|
276
369
|
return !!start.update && !['updated', 'up-to-date', 'no-remote'].includes(start.update.outcome);
|
|
@@ -346,6 +439,7 @@ opts) {
|
|
|
346
439
|
base: vcs.baseCommit ? { commit: vcs.baseCommit, subject } : undefined,
|
|
347
440
|
earlier,
|
|
348
441
|
start: opts.start,
|
|
442
|
+
artifacts: artifactPatterns(session.vcs),
|
|
349
443
|
});
|
|
350
444
|
return { vcs, note };
|
|
351
445
|
}
|
|
@@ -408,6 +502,14 @@ export function noteFor(repoDir, vcs, ctx = { mode: 'per-task', earlier: [] }) {
|
|
|
408
502
|
'commit instead: `git merge-base --is-ancestor <commit> HEAD` exits 0 when it is.',
|
|
409
503
|
'',
|
|
410
504
|
...(began ? [began, ''] : []),
|
|
505
|
+
...(inputsNote(ctx.start?.inputs) ? [inputsNote(ctx.start?.inputs), ''] : []),
|
|
506
|
+
...((ctx.artifacts?.length ?? 0) > 0
|
|
507
|
+
? [
|
|
508
|
+
`Evidence goes under ${ctx.artifacts?.map((a) => `\`${a}\``).join(', ')}: those files are kept with the run's record and are never committed, ` +
|
|
509
|
+
'so write reports, archives and test results there rather than changing .gitignore for them.',
|
|
510
|
+
'',
|
|
511
|
+
]
|
|
512
|
+
: []),
|
|
411
513
|
standing,
|
|
412
514
|
'',
|
|
413
515
|
'- Do not create branches, switch branches, commit, stash, reset or revert. That is the',
|
|
@@ -699,27 +801,36 @@ export async function vcsPreflight(session, allSessions = async () => []) {
|
|
|
699
801
|
const state = await repoState(repoDir);
|
|
700
802
|
if (!state.isRepo)
|
|
701
803
|
return { ok: false, repoDir, problem: state.problem };
|
|
702
|
-
//
|
|
703
|
-
|
|
804
|
+
// Artifacts do not count: the run keeps them out of git before it looks (see `excludeArtifacts`).
|
|
805
|
+
const artifacts = artifactPatterns(settings);
|
|
806
|
+
const changed = state.dirty && artifacts.length > 0 ? (await workingTreePaths(repoDir)).filter((p) => !inScope(p, artifacts)) : state.changed;
|
|
807
|
+
const dirty = changed.length > 0;
|
|
808
|
+
/*
|
|
809
|
+
* Before the first task, under a snapshot policy or with input files: the list to approve, file by
|
|
810
|
+
* file. Input files are looked for even in a clean tree — an ignored input does not make it dirty.
|
|
811
|
+
*/
|
|
812
|
+
const inputs = !!inputSettings(settings);
|
|
813
|
+
if ((dirty || inputs) && !session.vcsBaseCommit && (dirtyPolicy(settings).policy !== 'reject' || inputs) && settings.startFrom !== 'existing-branch') {
|
|
704
814
|
const snapshot = await planSnapshot(session, allSessions);
|
|
705
815
|
if (snapshot.needed) {
|
|
816
|
+
const listed = snapshot.entries.map((e) => e.path);
|
|
706
817
|
return {
|
|
707
818
|
ok: false,
|
|
708
819
|
repoDir,
|
|
709
820
|
branch: state.branch ?? undefined,
|
|
710
821
|
problem: snapshot.ok
|
|
711
|
-
? `There are uncommitted changes (${someOf(
|
|
822
|
+
? `There are uncommitted changes (${someOf(listed, 3)}). They become the session's starting snapshot ${snapshot.requireApproval ? 'once you approve the list below' : 'when its first task starts'}.`
|
|
712
823
|
: `There are uncommitted changes, and no starting snapshot can be taken: ${snapshot.problem}`,
|
|
713
824
|
snapshot,
|
|
714
825
|
};
|
|
715
826
|
}
|
|
716
827
|
}
|
|
717
|
-
if (
|
|
828
|
+
if (dirty) {
|
|
718
829
|
return {
|
|
719
830
|
ok: false,
|
|
720
831
|
repoDir,
|
|
721
832
|
branch: state.branch ?? undefined,
|
|
722
|
-
problem: `There are uncommitted changes (${
|
|
833
|
+
problem: `There are uncommitted changes (${changed.slice(0, 3).join(', ')}${changed.length > 3 ? '…' : ''}). Commit or stash them first.`,
|
|
723
834
|
};
|
|
724
835
|
}
|
|
725
836
|
return { ok: true, repoDir, branch: state.branch ?? undefined };
|
package/dist/web/404.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--JPmlfAEvbNkbghoyvY9uC--><html lang="en" data-theme="light" data-textsize="normal" data-contrast="normal" data-motion="normal" data-links="plain" data-focus="normal"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/c37978b44194c37b.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-0f31b926d9a9c5a4.js"/><script src="/_next/static/chunks/c7879cf7-b5ab1053c1d9a2e7.js" async=""></script><script src="/_next/static/chunks/131-bae98f790a541679.js" async=""></script><script src="/_next/static/chunks/main-app-e3a5f713ba31557e.js" async=""></script><script src="/_next/static/chunks/197-f7c33a0114fc3db3.js" async=""></script><script src="/_next/static/chunks/867-c078b5b504bf4289.js" async=""></script><script src="/_next/static/chunks/549-5d7c845fb0a27dbe.js" async=""></script><script src="/_next/static/chunks/app/layout-560bd6d173302e5a.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>copilot-operator</title><meta name="description" content="Runs task loops with Microsoft 365 Copilot on this machine."/><script>
|
|
2
2
|
(function () {
|
|
3
3
|
try {
|
|
4
4
|
var d = document.documentElement;
|
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
d.dataset.focus = a.strongFocus ? 'strong' : 'normal';
|
|
14
14
|
} catch (e) {}
|
|
15
15
|
})();
|
|
16
|
-
</script><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><a class="skip-link" href="#main">Skip to the content</a><div class="wrap"><header class="top"><h1><a href="/">copilot-operator</a></h1><nav aria-label="Main"><a href="/"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M4 5h16v4H4zM4 11h16v4H4zM4 17h10v2H4z"></path></svg><span>Sessions</span></a><a href="/defaults"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8zm8.5 4 1.5 1-1.6 2.8-1.8-.4a7 7 0 0 1-1.5 1.5l.4 1.8L14.7 21l-1-1.5a7 7 0 0 1-3.4 0l-1 1.5-2.8-1.6.4-1.8A7 7 0 0 1 5.4 16l-1.8.4L2 13.6 3.5 12.6V11.4L2 10.4l1.6-2.8 1.8.4A7 7 0 0 1 6.9 6.5l-.4-1.8L9.3 3l1 1.5a7 7 0 0 1 3.4 0l1-1.5 2.8 1.6-.4 1.8a7 7 0 0 1 1.5 1.5l1.8-.4L22 10.4l-1.5 1z"></path></svg><span>Settings</span></a><a href="/import"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M12 3v10m0 0 4-4m-4 4-4-4M4 15v4a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg><span>Plan from JSON</span></a><a href="/history"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M12 3a9 9 0 1 0 8.5 6M12 7v5l3 2M3 4v5h5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg><span>Task register</span></a><a href="/level1"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M6 3h9l5 5v13H6zM14 3v6h6M9 13h7M9 17h7" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"></path></svg><span>Level 1 prompt</span></a><a href="/presets"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M5 4h14v4H5zM5 10h14v4H5zM5 16h9v4H5z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"></path></svg><span>Level 2 presets</span></a><a href="/appearance"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M12 3a9 9 0 0 0 0 18c1.5 0 2-1 2-2s-1-1.5-1-2.5S14 15 15.5 15H17a4 4 0 0 0 4-4 8 8 0 0 0-9-8zM8 9a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm4-3a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm4 3a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path></svg><span>Appearance</span></a><a href="/system"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M4 5h16v10H4zM2 19h20M9 15v4M15 15v4" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"></path></svg><span>System</span></a><select aria-label="Language" style="width:auto"><option value="en" selected="">English</option><option value="bg">Български</option></select></nav></header><main id="main"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/webpack-0f31b926d9a9c5a4.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[1205,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"themeScript\"]\n3:I[1205,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"AppearanceProvider\"]\n4:I[867,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"LanguageProvider\"]\n5:I[1035,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"DialogHost\"]\n6:I[8214,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"SkipLink\"]\n7:I[8197,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"\"]\n8:I[8214,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"Nav\"]\n9:I[6657,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"GlobalApprovals\"]\na:I[5204,[],\"\"]\nb:I[2642,[],\"\"]\nc:I[7712,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-7f27ef819d251cc5.js\",\"549\",\"static/chunks/549-a13ae394c5e6a837.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"ScrollJump\"]\nd:I[433,[],\"OutletBoundary\"]\nf:I[9884,[],\"AsyncMeta"])</script><script>self.__next_f.push([1,"dataOutlet\"]\n11:I[433,[],\"ViewportBoundary\"]\n13:I[433,[],\"MetadataBoundary\"]\n14:\"$Sreact.suspense\"\n16:I[3536,[],\"\"]\n:HL[\"/_next/static/css/c37978b44194c37b.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"kkxFcGzA9Uo1uRAgcoDti\",\"p\":\"\",\"c\":[\"\",\"_not-found\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/c37978b44194c37b.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"data-theme\":\"light\",\"data-textsize\":\"normal\",\"data-contrast\":\"normal\",\"data-motion\":\"normal\",\"data-links\":\"plain\",\"data-focus\":\"normal\",\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"script\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"$2\"}}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"$L3\",null,{\"children\":[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$L5\",null,{\"children\":[[\"$\",\"$L6\",null,{}],[\"$\",\"div\",null,{\"className\":\"wrap\",\"children\":[[\"$\",\"header\",null,{\"className\":\"top\",\"children\":[[\"$\",\"h1\",null,{\"children\":[\"$\",\"$L7\",null,{\"href\":\"/\",\"children\":\"copilot-operator\"}]}],[\"$\",\"$L8\",null,{}]]}],[\"$\",\"$L9\",null,{}],[\"$\",\"main\",null,{\"id\":\"main\",\"children\":[\"$\",\"$La\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Lb\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}],[\"$\",\"$Lc\",null,{}]]}]}]}]}]]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$La\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Lb\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$Ld\",null,{\"children\":[\"$Le\",[\"$\",\"$Lf\",null,{\"promise\":\"$@10\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$L11\",null,{\"children\":\"$L12\"}],null],[\"$\",\"$L13\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$14\",null,{\"fallback\":null,\"children\":\"$L15\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$16\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"12:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\ne:null\n"])</script><script>self.__next_f.push([1,"10:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"copilot-operator\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Runs task loops with Microsoft 365 Copilot on this machine.\"}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"15:\"$10:metadata\"\n"])</script></body></html>
|
|
16
|
+
</script><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><a class="skip-link" href="#main">Skip to the content</a><div class="wrap"><header class="top"><h1><a href="/">copilot-operator</a></h1><nav aria-label="Main"><a href="/"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M4 5h16v4H4zM4 11h16v4H4zM4 17h10v2H4z"></path></svg><span>Sessions</span></a><a href="/defaults"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8zm8.5 4 1.5 1-1.6 2.8-1.8-.4a7 7 0 0 1-1.5 1.5l.4 1.8L14.7 21l-1-1.5a7 7 0 0 1-3.4 0l-1 1.5-2.8-1.6.4-1.8A7 7 0 0 1 5.4 16l-1.8.4L2 13.6 3.5 12.6V11.4L2 10.4l1.6-2.8 1.8.4A7 7 0 0 1 6.9 6.5l-.4-1.8L9.3 3l1 1.5a7 7 0 0 1 3.4 0l1-1.5 2.8 1.6-.4 1.8a7 7 0 0 1 1.5 1.5l1.8-.4L22 10.4l-1.5 1z"></path></svg><span>Settings</span></a><a href="/import"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M12 3v10m0 0 4-4m-4 4-4-4M4 15v4a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg><span>Plan from JSON</span></a><a href="/history"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M12 3a9 9 0 1 0 8.5 6M12 7v5l3 2M3 4v5h5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg><span>Task register</span></a><a href="/level1"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M6 3h9l5 5v13H6zM14 3v6h6M9 13h7M9 17h7" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"></path></svg><span>Level 1 prompt</span></a><a href="/presets"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M5 4h14v4H5zM5 10h14v4H5zM5 16h9v4H5z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"></path></svg><span>Level 2 presets</span></a><a href="/appearance"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M12 3a9 9 0 0 0 0 18c1.5 0 2-1 2-2s-1-1.5-1-2.5S14 15 15.5 15H17a4 4 0 0 0 4-4 8 8 0 0 0-9-8zM8 9a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm4-3a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm4 3a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"></path></svg><span>Appearance</span></a><a href="/system"><svg class="nav-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M4 5h16v10H4zM2 19h20M9 15v4M15 15v4" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"></path></svg><span>System</span></a><select aria-label="Language" style="width:auto"><option value="en" selected="">English</option><option value="bg">Български</option></select></nav></header><main id="main"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/webpack-0f31b926d9a9c5a4.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[1205,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"themeScript\"]\n3:I[1205,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"AppearanceProvider\"]\n4:I[867,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"LanguageProvider\"]\n5:I[1035,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"DialogHost\"]\n6:I[8214,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"SkipLink\"]\n7:I[8197,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"\"]\n8:I[8214,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"Nav\"]\n9:I[6657,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"GlobalApprovals\"]\na:I[5204,[],\"\"]\nb:I[2642,[],\"\"]\nc:I[7712,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-c078b5b504bf4289.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"ScrollJump\"]\nd:I[433,[],\"OutletBoundary\"]\nf:I[9884,[],\"AsyncMeta"])</script><script>self.__next_f.push([1,"dataOutlet\"]\n11:I[433,[],\"ViewportBoundary\"]\n13:I[433,[],\"MetadataBoundary\"]\n14:\"$Sreact.suspense\"\n16:I[3536,[],\"\"]\n:HL[\"/_next/static/css/c37978b44194c37b.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"JPmlfAEvbNkbghoyvY9uC\",\"p\":\"\",\"c\":[\"\",\"_not-found\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/c37978b44194c37b.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"data-theme\":\"light\",\"data-textsize\":\"normal\",\"data-contrast\":\"normal\",\"data-motion\":\"normal\",\"data-links\":\"plain\",\"data-focus\":\"normal\",\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"script\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"$2\"}}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"$L3\",null,{\"children\":[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$L5\",null,{\"children\":[[\"$\",\"$L6\",null,{}],[\"$\",\"div\",null,{\"className\":\"wrap\",\"children\":[[\"$\",\"header\",null,{\"className\":\"top\",\"children\":[[\"$\",\"h1\",null,{\"children\":[\"$\",\"$L7\",null,{\"href\":\"/\",\"children\":\"copilot-operator\"}]}],[\"$\",\"$L8\",null,{}]]}],[\"$\",\"$L9\",null,{}],[\"$\",\"main\",null,{\"id\":\"main\",\"children\":[\"$\",\"$La\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Lb\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}],[\"$\",\"$Lc\",null,{}]]}]}]}]}]]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$La\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Lb\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$Ld\",null,{\"children\":[\"$Le\",[\"$\",\"$Lf\",null,{\"promise\":\"$@10\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$L11\",null,{\"children\":\"$L12\"}],null],[\"$\",\"$L13\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$14\",null,{\"fallback\":null,\"children\":\"$L15\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$16\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"12:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\ne:null\n"])</script><script>self.__next_f.push([1,"10:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"copilot-operator\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Runs task loops with Microsoft 365 Copilot on this machine.\"}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"15:\"$10:metadata\"\n"])</script></body></html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[549],{5549:(t,o,e)=>{e.d(o,{AV:()=>a,FH:()=>h,FZ:()=>r,Zm:()=>u,aT:()=>s,c5:()=>y,dK:()=>l,nC:()=>n,rt:()=>d,ub:()=>i,zi:()=>p});let n="/api";function s(t,o){return"/sessions/view?id=".concat(encodeURIComponent(t)).concat(o?"#".concat(o):"")}let c="cop-api-token";function a(){try{let t=/(?:^#|&)token=([0-9a-f]{16,})/i.exec(window.location.hash);if(t)return window.localStorage.setItem(c,t[1]),window.history.replaceState(null,"",window.location.pathname+window.location.search),t[1];return window.localStorage.getItem(c)||""}catch(t){return""}}function i(t){let o=a();return o?"".concat(t).concat(t.includes("?")?"&":"?","token=").concat(encodeURIComponent(o)):t}let r=["exit-zero","exit-nonzero","output-contains","output-omits","output-matches","file-exists","file-missing","file-contains"];function d(t){return t.startsWith("exit-")||t.startsWith("output-")}function l(t){return"output-contains"===t||"output-omits"===t||"output-matches"===t||"file-contains"===t}function u(t){return"limit-reached"===t.status||"aborted"===t.status||!!t.limit&&("failed"===t.status||"blocked"===t.status)}async function m(t,o){let e,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},c=void 0===s.timeoutMs?3e4:s.timeoutMs;try{var i;e=await fetch("".concat(n).concat(t),{...o,...null!==c&&!(null==o?void 0:o.signal)?{signal:AbortSignal.timeout(c)}:{},headers:{"content-type":"application/json",...a()?{"x-cop-token":a()}:{},...null!=(i=null==o?void 0:o.headers)?i:{}}})}catch(o){if("TimeoutError"===o.name)throw Error("The API did not answer within ".concat(Math.round((null!=c?c:0)/1e3)," s (").concat(t.split("?")[0],"). It may be busy; try again."));throw o}if(!e.ok){let t="".concat(e.status," ").concat(e.statusText);try{let o=await e.json();(null==o?void 0:o.message)&&(t=Array.isArray(o.message)?o.message.join("; "):o.message)}catch(t){}throw Error(t)}let r=await e.text();return r?JSON.parse(r):void 0}let h={health:()=>m("/health"),doctor:()=>m("/doctor"),settings:()=>m("/settings"),saveSettings:t=>m("/settings",{method:"PUT",body:JSON.stringify(t)}),level1:()=>m("/level1"),setLevel1:t=>m("/level1",{method:"PUT",body:JSON.stringify({content:t})}),resetLevel1:()=>m("/level1",{method:"DELETE"}),presets:()=>m("/presets"),savePreset:(t,o)=>m("/presets/".concat(encodeURIComponent(t)),{method:"PUT",body:JSON.stringify({content:o})}),deletePreset:t=>m("/presets/".concat(encodeURIComponent(t)),{method:"DELETE"}),personas:()=>m("/personas"),savePersona:(t,o)=>m("/personas/".concat(encodeURIComponent(t)),{method:"PUT",body:JSON.stringify({content:o})}),deletePersona:t=>m("/personas/".concat(encodeURIComponent(t)),{method:"DELETE"}),sessions:()=>m("/sessions"),reorderSessions:t=>m("/sessions-order",{method:"PUT",body:JSON.stringify({ids:t})}),metrics:()=>m("/metrics"),syncPlan:t=>m("/repo/sync?dir=".concat(encodeURIComponent(t))),session:t=>m("/sessions/".concat(t)),createSession:(t,o)=>m("/sessions",{method:"POST",body:JSON.stringify({name:t,projectDir:o})}),updateSession:(t,o)=>m("/sessions/".concat(t),{method:"PUT",body:JSON.stringify(o)}),deleteSession:t=>m("/sessions/".concat(t),{method:"DELETE"}),addTask:(t,o)=>m("/sessions/".concat(t,"/tasks"),{method:"POST",body:JSON.stringify(o)}),updateTask:(t,o,e)=>m("/sessions/".concat(t,"/tasks/").concat(o),{method:"PUT",body:JSON.stringify(e)}),deleteTask:(t,o)=>m("/sessions/".concat(t,"/tasks/").concat(o),{method:"DELETE"}),continueTask:(t,o)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/continue"),{method:"POST",body:"{}"}),rerunTask:function(t,o){let e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};return m("/sessions/".concat(t,"/tasks/").concat(o,"/rerun"),{method:"POST",body:JSON.stringify({...e,...n.buildOnFinished?{buildOnFinished:!0}:{}})})},taskChanges:(t,o,e)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/changes").concat(e?"?run=".concat(encodeURIComponent(e)):"")),taskChangeFile:(t,o,e,n)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/changes/file?path=").concat(encodeURIComponent(e)).concat(n?"&run=".concat(encodeURIComponent(n)):"")),taskStory:(t,o,e)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/story").concat(e?"?run=".concat(encodeURIComponent(e)):"")),taskFiles:(t,o,e)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/files").concat(e?"?run=".concat(encodeURIComponent(e)):"")),taskLogUrl:(t,o,e)=>"".concat(n,"/sessions/").concat(t,"/tasks/").concat(o,"/log").concat(e?"?run=".concat(encodeURIComponent(e)):""),taskFileUrl:(t,o,e,s,c)=>"".concat(n,"/sessions/").concat(t,"/tasks/").concat(o,"/files/").concat(e,"/").concat(encodeURIComponent(s)).concat(c?"?run=".concat(encodeURIComponent(c)):""),saveTaskLog:(t,o,e)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/log").concat(e?"?run=".concat(encodeURIComponent(e)):""),{method:"POST",body:"{}"}),saveTaskFile:(t,o,e,n,s)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/files/").concat(e,"/").concat(encodeURIComponent(n)).concat(s?"?run=".concat(encodeURIComponent(s)):""),{method:"POST",body:"{}"}),start:(t,o,e)=>m("/sessions/".concat(t,"/start"),{method:"POST",body:JSON.stringify({mode:o,name:e})}),stop:t=>m("/sessions/".concat(t,"/stop"),{method:"POST",body:"{}"}),approvals:t=>m("/approvals".concat(t?"?session=".concat(encodeURIComponent(t)):"")),decide:(t,o)=>m("/approvals/".concat(t),{method:"POST",body:JSON.stringify({action:o})}),setRunMode:(t,o)=>m("/sessions/".concat(t,"/mode"),{method:"POST",body:JSON.stringify({mode:o})}),streamUrl:t=>i("".concat(n,"/sessions/").concat(t,"/stream")),batch:()=>m("/batch").then(t=>null!=t?t:null),startBatch:(t,o,e,n,s,c,a)=>m("/batch/start",{method:"POST",body:JSON.stringify({sessionIds:t,mode:o,onFailure:e,model:n,reviewModel:s,name:c,taskIds:a})}),suggestedRunName:t=>m("/batch/name?sessions=".concat(encodeURIComponent(t.join(",")))),stopBatch:()=>m("/batch/stop",{method:"POST",body:"{}"}),pauseBatch:()=>m("/batch/pause",{method:"POST",body:"{}"}),resumeBatch:()=>m("/batch/resume",{method:"POST",body:"{}"}),planBrief:t=>m("/plan/brief?lang=".concat(encodeURIComponent(t))),context:(t,o)=>m("/context/".concat(t,"?lang=").concat(encodeURIComponent(o))),setContext:(t,o)=>m("/context/".concat(t),{method:"PUT",body:JSON.stringify({content:o})}),resetContext:(t,o)=>m("/context/".concat(t,"?lang=").concat(encodeURIComponent(o)),{method:"DELETE"}),checkPlan:t=>m("/plan/check",{method:"POST",body:JSON.stringify({text:t})}),importPlan:t=>m("/plan/import",{method:"POST",body:JSON.stringify({text:t})}),browseFolder:t=>m("/browse-folder",{method:"POST",body:JSON.stringify({start:t})},{timeoutMs:null}),tasks:()=>m("/tasks"),activity:()=>m("/activity"),downloadBundle:async t=>{var o,e,s;let c=await fetch("".concat(n,"/export/bundle"),{method:"POST",headers:{"content-type":"application/json",...a()?{"x-cop-token":a()}:{}},body:JSON.stringify({tasks:t})});if(!c.ok)throw Error(await c.text()||"".concat(c.status," ").concat(c.statusText));let i=null!=(s=c.headers.get("content-disposition"))?s:"",r=null==(o=/filename\*=UTF-8''([^;]+)/i.exec(i))?void 0:o[1],d=null==(e=/filename="([^"]+)"/i.exec(i))?void 0:e[1],l=null!=d?d:"copilot-operator-bundle.json";if(r)try{l=decodeURIComponent(r)}catch(t){}let u=URL.createObjectURL(await c.blob()),m=document.createElement("a");return m.href=u,m.download=l,document.body.appendChild(m),m.click(),m.remove(),setTimeout(()=>URL.revokeObjectURL(u),1e4),l},exportUrl:(t,o)=>{let e=new URLSearchParams;return o.run&&e.set("run",o.run),o.session&&e.set("session",o.session),o.task&&e.set("task",o.task),i("".concat(n,"/export/").concat(t,"?").concat(e.toString()))},debugExportUrl:t=>i("".concat(n,"/debug/export").concat(t.length>0?"?sessions=".concat(encodeURIComponent(t.join(","))):"")),vcsStatus:t=>m("/sessions/".concat(t,"/vcs")),vcsSnapshot:(t,o)=>m("/sessions/".concat(t,"/vcs/snapshot"),{method:"POST",body:JSON.stringify({choices:o})}),restorePreview:(t,o)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/restore")),restore:(t,o)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/restore"),{method:"POST",body:"{}"}),restartPlan:(t,o)=>m("/sessions/".concat(t,"/tasks/").concat(o,"/restart")),restartFrom:function(t,o){let e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return m("/sessions/".concat(t,"/tasks/").concat(o,"/restart"),{method:"POST",body:JSON.stringify(e)})},repoCheck:t=>m("/repo?dir=".concat(encodeURIComponent(t))),project:()=>m("/project"),setProject:t=>m("/project",{method:"PUT",body:JSON.stringify(t)}),models:()=>m("/models"),setDefaultModel:t=>m("/models/default",{method:"PUT",body:JSON.stringify({model:t})}),setDefaultReviewModel:t=>m("/models/review-default",{method:"PUT",body:JSON.stringify({model:t})}),refreshModels:()=>m("/models/refresh",{method:"POST",body:"{}"},{timeoutMs:null}),login:t=>m("/login",{method:"POST",body:JSON.stringify({account:(null==t?void 0:t.trim())||void 0})},{timeoutMs:null})};function p(t){return t<1024?"".concat(t," B"):t<1048576?"".concat((t/1024).toFixed(1)," KB"):"".concat((t/1048576).toFixed(1)," MB")}function y(t){if(void 0===t)return"";let o=Math.round(t/1e3);if(o<60)return"".concat(o,"s");let e=Math.floor(o/60);return e<60?"".concat(e,"m ").concat(o%60,"s"):"".concat(Math.floor(e/60),"h ").concat(e%60,"m")}}}]);
|