copilot-operator 0.1.17 → 0.1.19
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 +33 -2
- package/dist/src/cli.js +11 -29
- package/dist/src/config/version.js +30 -0
- package/dist/src/orchestrator/derivedChecks.js +19 -1
- package/dist/src/orchestrator/review.js +2 -2
- package/dist/src/orchestrator/taskRunner.js +130 -10
- package/dist/src/plan/brief.js +38 -4
- package/dist/src/plan/importPlan.js +42 -1
- package/dist/src/plan/schema.js +53 -0
- package/dist/src/plan/systemGuide.js +50 -2
- package/dist/src/protocol/replySchema.js +1 -1
- package/dist/src/protocol/reviewSchema.js +10 -5
- package/dist/src/session/exports.js +53 -13
- package/dist/src/session/model.js +20 -0
- package/dist/src/session/store.js +80 -0
- package/dist/src/vcs/artifacts.js +185 -0
- package/dist/src/vcs/inputs.js +449 -0
- package/dist/src/vcs/snapshot.js +174 -22
- package/dist/src/vcs/taskVcs.js +272 -37
- 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-d9c54f7a2b285b3f.js +1 -0
- package/dist/web/_next/static/chunks/app/appearance/page-a18019cdc395de3d.js +1 -0
- package/dist/web/_next/static/chunks/app/history/page-a0bd59986f7c8beb.js +1 -0
- package/dist/web/_next/static/chunks/app/layout-3efbb282292ccc38.js +1 -0
- package/dist/web/_next/static/chunks/app/sessions/view/page-99f9153fd75078d0.js +1 -0
- package/dist/web/_next/static/chunks/app/system/page-5ae1f8054208e6eb.js +1 -0
- package/dist/web/appearance.html +2 -2
- package/dist/web/appearance.txt +25 -26
- package/dist/web/defaults.html +2 -2
- package/dist/web/defaults.txt +25 -26
- package/dist/web/history.html +2 -2
- package/dist/web/history.txt +25 -26
- package/dist/web/import.html +2 -2
- package/dist/web/import.txt +25 -26
- package/dist/web/index.html +2 -2
- package/dist/web/index.txt +25 -26
- package/dist/web/level1.html +2 -2
- package/dist/web/level1.txt +25 -26
- package/dist/web/presets.html +2 -2
- package/dist/web/presets.txt +25 -26
- package/dist/web/sessions/view.html +2 -2
- package/dist/web/sessions/view.txt +25 -26
- package/dist/web/system.html +2 -2
- package/dist/web/system.txt +25 -26
- package/package.json +8 -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/appearance/page-9b13583bfee63b32.js +0 -1
- package/dist/web/_next/static/chunks/app/history/page-d7314ac22d47a3ab.js +0 -1
- package/dist/web/_next/static/chunks/app/layout-560bd6d173302e5a.js +0 -1
- package/dist/web/_next/static/chunks/app/sessions/view/page-d28825430ca280de.js +0 -1
- package/dist/web/_next/static/chunks/app/system/page-3aa2a0fef5454e69.js +0 -1
- /package/dist/web/_next/static/{kkxFcGzA9Uo1uRAgcoDti → ofnRLEgWx9th5w_qtuFnB}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{kkxFcGzA9Uo1uRAgcoDti → ofnRLEgWx9th5w_qtuFnB}/_ssgManifest.js +0 -0
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) {
|
|
@@ -27,6 +31,23 @@ export function trackedRepoOf(session) {
|
|
|
27
31
|
export async function prepareForTask(session, task, bus, saveSession,
|
|
28
32
|
/** Every session on record, for `startFrom: previous-session` to find the one before this. */
|
|
29
33
|
allSessions = async () => []) {
|
|
34
|
+
const prepared = await prepare(session, task, bus, saveSession, allSessions);
|
|
35
|
+
/*
|
|
36
|
+
* Version control that is on but cannot do its part refuses the task, whatever the cause — a dirty
|
|
37
|
+
* tree, a starting branch that is not there, a branch git would not make. It used to be "on but
|
|
38
|
+
* inactive": the task ran, nothing was committed, and the task still ended done with its work
|
|
39
|
+
* loose in the tree. A task that cannot be committed is not run.
|
|
40
|
+
*/
|
|
41
|
+
// Not when the operator chose no commits (`commitOnFinish` false): earlier tasks' files are then
|
|
42
|
+
// meant to stay in the tree, and refusing would stop every task after the first.
|
|
43
|
+
if (session.vcs?.enabled && session.vcs.commitOnFinish !== false && !prepared.refuse && !prepared.vcs.branch && prepared.vcs.problem) {
|
|
44
|
+
const why = `version control is on and cannot work for this task: ${prepared.vcs.problem.replace(/\.?\s*$/, '.')} Nothing was run.`;
|
|
45
|
+
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-refused', level: 'error', message: why });
|
|
46
|
+
return { ...prepared, refuse: why };
|
|
47
|
+
}
|
|
48
|
+
return prepared;
|
|
49
|
+
}
|
|
50
|
+
async function prepare(session, task, bus, saveSession, allSessions) {
|
|
30
51
|
const settings = session.vcs;
|
|
31
52
|
if (!settings?.enabled)
|
|
32
53
|
return { vcs: {}, note: '' };
|
|
@@ -38,35 +59,79 @@ allSessions = async () => []) {
|
|
|
38
59
|
message: `version control is on but inactive: ${problem}` });
|
|
39
60
|
return { vcs: { problem }, note: '' };
|
|
40
61
|
}
|
|
62
|
+
const refuse = (why) => {
|
|
63
|
+
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-refused', level: 'error', message: why });
|
|
64
|
+
return { vcs: { problem: why }, note: '', refuse: why };
|
|
65
|
+
};
|
|
66
|
+
/*
|
|
67
|
+
* The session's artifacts are never committed: their patterns go into the repository's own
|
|
68
|
+
* exclude file before anything looks at the tree, so they neither make it dirty nor go into a
|
|
69
|
+
* commit. See `artifacts.ts`.
|
|
70
|
+
*/
|
|
71
|
+
const excluded = await excludeArtifacts(dir, session);
|
|
72
|
+
if (excluded.problem)
|
|
73
|
+
return refuse(`the session's artifacts could not be kept out of git: ${excluded.problem}. Nothing was run.`);
|
|
74
|
+
if (excluded.tracked.length > 0) {
|
|
75
|
+
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-artifacts-tracked', level: 'warn',
|
|
76
|
+
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.` });
|
|
77
|
+
}
|
|
78
|
+
if (excluded.tracked.length > 0 || artifactPatterns(settings).length > 0)
|
|
79
|
+
state = await repoState(dir);
|
|
41
80
|
if (settings.startFrom === 'existing-branch')
|
|
42
|
-
return await onExistingBranch(session, task, dir, state, bus, saveSession);
|
|
81
|
+
return await onExistingBranch(session, task, dir, state, bus, saveSession, allSessions);
|
|
43
82
|
// The session's base is fixed the first time it runs: every per-task branch is cut from it,
|
|
44
83
|
// which is what makes the tasks independent of each other rather than of the calendar. Where
|
|
45
84
|
// it is taken from is the session's `startFrom`; see `sessionStart`.
|
|
46
85
|
let base = session.vcsBaseCommit;
|
|
47
86
|
let start = session.vcsStart;
|
|
48
87
|
/*
|
|
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.
|
|
88
|
+
* The operator's own changes before the session's first task — under a snapshot policy, or its
|
|
89
|
+
* input files: they become the commit the session starts from (see `snapshot.ts`). Asked for
|
|
90
|
+
* approval, the run is refused until the list has been approved on the session's page; running
|
|
91
|
+
* without version control instead would be the one outcome the operator chose against.
|
|
53
92
|
*/
|
|
54
93
|
const dirty = dirtyPolicy(settings);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
94
|
+
const inputs = inputSettings(settings);
|
|
95
|
+
// Input files are looked for even in a clean tree: an ignored input does not make it dirty.
|
|
96
|
+
if ((state.dirty || inputs) && !base && (dirty.policy !== 'reject' || inputs)) {
|
|
97
|
+
const plan = await planSnapshot(session, allSessions);
|
|
98
|
+
if (plan.needed) {
|
|
99
|
+
if (!plan.ok)
|
|
100
|
+
return refuse(`the starting snapshot cannot be taken: ${plan.problem} Nothing was run.`);
|
|
101
|
+
if (plan.requireApproval) {
|
|
102
|
+
return refuse(`the repository has uncommitted changes (${someOf(plan.entries.map((e) => e.path))}), and this session takes them as its starting snapshot ` +
|
|
103
|
+
'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.');
|
|
104
|
+
}
|
|
105
|
+
const taken = await takeSnapshot(session, { approved: false }, bus, saveSession, allSessions);
|
|
106
|
+
if (!taken.ok)
|
|
107
|
+
return refuse(`the starting snapshot of the uncommitted changes was not taken: ${taken.problem} Nothing was run.`);
|
|
108
|
+
base = taken.start.commit;
|
|
109
|
+
start = taken.start;
|
|
110
|
+
state = await repoState(dir);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/*
|
|
114
|
+
* Started already, and input files changed or were added since: taken onto the session's line of
|
|
115
|
+
* work (see `recaptureInputs`), with the operator's approval unless they said otherwise. They used
|
|
116
|
+
* to be "a dirty tree to commit or stash": version control went off and the task ran without it.
|
|
117
|
+
*/
|
|
118
|
+
if (base && inputs) {
|
|
119
|
+
const plan = await planSnapshot(session, allSessions);
|
|
120
|
+
if (plan.needed && plan.recapture) {
|
|
121
|
+
if (!plan.ok)
|
|
122
|
+
return refuse(`the input files changed since the session started cannot be taken: ${plan.problem} Nothing was run.`);
|
|
123
|
+
if (plan.requireApproval) {
|
|
124
|
+
return refuse(`input files changed or were added since the session started (${someOf(plan.entries.map((e) => e.path))}). Approve them on the session's page, ` +
|
|
125
|
+
'Version control → "Uncommitted changes", and they are committed on its line of work before the next task. Nothing was run.');
|
|
126
|
+
}
|
|
127
|
+
const taken = await takeSnapshot(session, { approved: false }, bus, saveSession, allSessions);
|
|
128
|
+
if (!taken.ok)
|
|
129
|
+
return refuse(`the changed input files were not taken: ${taken.problem} Nothing was run.`);
|
|
130
|
+
start = taken.start;
|
|
131
|
+
if (plan.recapture.newBranch)
|
|
132
|
+
base = taken.start.inputs?.recaptured?.at(-1)?.commit ?? base;
|
|
133
|
+
state = await repoState(dir);
|
|
63
134
|
}
|
|
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
135
|
}
|
|
71
136
|
// A dirty tree is the operator's own work in progress. Committing it under the bot's name
|
|
72
137
|
// or moving it to another branch would both be decisions that are not ours to make — unless
|
|
@@ -74,9 +139,11 @@ allSessions = async () => []) {
|
|
|
74
139
|
if (state.dirty) {
|
|
75
140
|
const problem = `the repository has uncommitted changes (${state.changed.slice(0, 5).join(', ')}` +
|
|
76
141
|
`${state.changed.length > 5 ? `, and ${state.changed.length - 5} more` : ''}). ` +
|
|
77
|
-
|
|
142
|
+
(base
|
|
143
|
+
? 'Commit or stash them, so the task starts from a known state.'
|
|
144
|
+
: 'Commit or stash them, or choose "Take them as a starting snapshot" under Version control → "Uncommitted changes" (input files: "Input files").');
|
|
78
145
|
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-dirty', level: 'warn',
|
|
79
|
-
message: `version control
|
|
146
|
+
message: `version control cannot start: ${problem}` });
|
|
80
147
|
return { vcs: { problem }, note: '' };
|
|
81
148
|
}
|
|
82
149
|
if (!base) {
|
|
@@ -98,6 +165,24 @@ allSessions = async () => []) {
|
|
|
98
165
|
message: describeStart(chosen), data: { ...chosen } });
|
|
99
166
|
}
|
|
100
167
|
}
|
|
168
|
+
/*
|
|
169
|
+
* The operator's input files, in the commit the session starts from whatever its `startFrom`, with
|
|
170
|
+
* their sums on the record. Once per session: a start that has recorded them has them.
|
|
171
|
+
*/
|
|
172
|
+
if (inputs && start && !start.inputs) {
|
|
173
|
+
const settled = await settleInputs(session, dir, start, allSessions);
|
|
174
|
+
if ('problem' in settled)
|
|
175
|
+
return refuse(`${settled.problem} Nothing was run.`);
|
|
176
|
+
const chosen = settled.start;
|
|
177
|
+
start = chosen;
|
|
178
|
+
base = chosen.commit;
|
|
179
|
+
await saveSession((s) => {
|
|
180
|
+
s.vcsBaseCommit = chosen.commit;
|
|
181
|
+
s.vcsStart = chosen;
|
|
182
|
+
});
|
|
183
|
+
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-inputs', level: 'info',
|
|
184
|
+
message: describeInputs(chosen), data: { files: chosen.inputs?.files.length ?? 0, carried: chosen.inputs?.carried } });
|
|
185
|
+
}
|
|
101
186
|
const attempt = task.attempt ?? 1;
|
|
102
187
|
const prefix = settings.branchPrefix || 'cop/';
|
|
103
188
|
if (settings.branchMode === 'per-session') {
|
|
@@ -149,7 +234,7 @@ export function namedSessionBranch(vcs) {
|
|
|
149
234
|
* refuses the task before a message is sent. The first run records the branch's tip as where the
|
|
150
235
|
* session started, so the record and a restore know what was there before the work.
|
|
151
236
|
*/
|
|
152
|
-
async function onExistingBranch(session, task, dir, state, bus, saveSession) {
|
|
237
|
+
async function onExistingBranch(session, task, dir, state, bus, saveSession, allSessions) {
|
|
153
238
|
const wanted = (session.vcs?.existingBranch ?? '').trim();
|
|
154
239
|
const refuse = (why) => {
|
|
155
240
|
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-refused', level: 'error', message: why });
|
|
@@ -181,6 +266,24 @@ async function onExistingBranch(session, task, dir, state, bus, saveSession) {
|
|
|
181
266
|
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-start', level: updateWarns(chosen) ? 'warn' : 'info', message: describeStart(chosen), data: { ...chosen } });
|
|
182
267
|
}
|
|
183
268
|
}
|
|
269
|
+
/*
|
|
270
|
+
* The input files must already be on the branch, as they are: the runner commits nothing onto a
|
|
271
|
+
* branch the operator named, so one that lacks them, or has them otherwise, is refused.
|
|
272
|
+
*/
|
|
273
|
+
if (inputSettings(session.vcs) && start && !start.inputs) {
|
|
274
|
+
const settled = await settleInputs(session, dir, start, allSessions);
|
|
275
|
+
if ('problem' in settled)
|
|
276
|
+
return refuse(`${settled.problem} Nothing was run.`);
|
|
277
|
+
if (settled.start.commit !== start.commit) {
|
|
278
|
+
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. ` +
|
|
279
|
+
`Commit them on "${wanted}" yourself. Nothing was run.`);
|
|
280
|
+
}
|
|
281
|
+
const chosen = settled.start;
|
|
282
|
+
start = chosen;
|
|
283
|
+
await saveSession((s) => {
|
|
284
|
+
s.vcsStart = chosen;
|
|
285
|
+
});
|
|
286
|
+
}
|
|
184
287
|
const prepared = await switchTo(session, task, dir, wanted, undefined, bus, { reuseExisting: true, mustExist: true, start });
|
|
185
288
|
return prepared.vcs.branch === wanted ? prepared : refuse(`the repository could not be put on "${wanted}": ${prepared.vcs.problem ?? 'unknown reason'}. Nothing was run.`);
|
|
186
289
|
}
|
|
@@ -213,20 +316,88 @@ export async function sessionStart(session, dir, head, allSessions) {
|
|
|
213
316
|
};
|
|
214
317
|
if (how === 'branch')
|
|
215
318
|
return await fromBranch();
|
|
319
|
+
/*
|
|
320
|
+
* The session before this one: the one that ran last in this repository, however it ended — not the
|
|
321
|
+
* last one that happened to commit, which skipped a predecessor that had failed or committed
|
|
322
|
+
* nothing and continued from older work as if it were the latest. A session set aside does not count.
|
|
323
|
+
*/
|
|
216
324
|
const here = normalise(dir);
|
|
217
|
-
let
|
|
325
|
+
let pred = null;
|
|
218
326
|
for (const other of await allSessions()) {
|
|
219
|
-
if (other.id === session.id || !other.vcs?.enabled || normalise(repoDirOf(other)) !== here)
|
|
327
|
+
if (other.id === session.id || !other.vcs?.enabled || other.active === false || normalise(repoDirOf(other)) !== here)
|
|
220
328
|
continue;
|
|
221
|
-
const
|
|
222
|
-
if (
|
|
223
|
-
|
|
329
|
+
const at = lastActivityOf(other);
|
|
330
|
+
if (at && (!pred || at > pred.at))
|
|
331
|
+
pred = { session: other, at };
|
|
332
|
+
}
|
|
333
|
+
if (!pred)
|
|
334
|
+
return await fromBranch(`no earlier session has run in this repository, so it starts from "${baseBranch}"`);
|
|
335
|
+
const before = pred.session;
|
|
336
|
+
/*
|
|
337
|
+
* Checked before anything is carried on: the previous session finished, and what it produced is
|
|
338
|
+
* there — a final commit on a branch that still exists, or a result that is artifacts only (or no
|
|
339
|
+
* change at all), which ends where it started. Anything else is refused with what is wrong; it used
|
|
340
|
+
* to fall back to the base branch with a note, and the chain went on without the work it needed.
|
|
341
|
+
*/
|
|
342
|
+
const unfinished = before.tasks.filter((t) => t.status !== 'done');
|
|
343
|
+
if (unfinished.length > 0) {
|
|
344
|
+
return {
|
|
345
|
+
problem: `this session continues the previous session in this repository, "${before.name}", which has not finished: ` +
|
|
346
|
+
`${unfinished.slice(0, 6).map((t) => `"${t.title}" is ${t.status}`).join(', ')}${unfinished.length > 6 ? `, and ${unfinished.length - 6} more` : ''}. ` +
|
|
347
|
+
'Finish it first (Continue or Run again), or choose another "Start from".',
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
const work = lastWorkOf(before);
|
|
351
|
+
if (!work) {
|
|
352
|
+
const startedAt = before.vcsBaseCommit;
|
|
353
|
+
if (!startedAt || !(await git(dir, ['cat-file', '-e', `${startedAt}^{commit}`])).ok) {
|
|
354
|
+
return { problem: `the previous session "${before.name}" committed nothing, and the commit it started from is not in the repository, so there is nothing to carry on from.` };
|
|
355
|
+
}
|
|
356
|
+
const artifactsOnly = before.tasks.some((t) => (t.artifactsKept?.length ?? 0) > 0);
|
|
357
|
+
return {
|
|
358
|
+
start: {
|
|
359
|
+
kind: 'previous-session',
|
|
360
|
+
commit: startedAt,
|
|
361
|
+
...(before.vcsStart?.branch ? { branch: before.vcsStart.branch } : {}),
|
|
362
|
+
fromSession: { id: before.id, name: before.name },
|
|
363
|
+
note: artifactsOnly
|
|
364
|
+
? `"${before.name}" committed nothing — its result is artifacts only — so this session starts where it started (${startedAt.slice(0, 8)})`
|
|
365
|
+
: `"${before.name}" changed nothing, so this session starts where it started (${startedAt.slice(0, 8)})`,
|
|
366
|
+
},
|
|
367
|
+
};
|
|
224
368
|
}
|
|
225
|
-
|
|
226
|
-
return await fromBranch(`no earlier session has committed work in this repository, so it starts from "${baseBranch}"`);
|
|
369
|
+
const best = { session: before, ...work };
|
|
227
370
|
const tip = await branchTip(dir, best.branch);
|
|
228
371
|
if (!tip) {
|
|
229
|
-
return
|
|
372
|
+
return {
|
|
373
|
+
problem: `the branch of the previous session "${best.session.name}" (${best.branch}) is no longer in the repository, so its final commit cannot be carried on. ` +
|
|
374
|
+
'Restore the branch, or choose another "Start from".',
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
/*
|
|
378
|
+
* The whole of that session's done work, or nothing. In per-task mode every task has a branch of
|
|
379
|
+
* its own, all cut from one commit, so the branch of the task that finished last holds that task's
|
|
380
|
+
* work only — a chain that started there began without the files the earlier tasks had made,
|
|
381
|
+
* though they were in the repository on other branches. The runner does not merge them; it says
|
|
382
|
+
* which are missing and refuses, rather than start from part of the work as if it were all.
|
|
383
|
+
*/
|
|
384
|
+
const missing = [];
|
|
385
|
+
for (const t of best.session.tasks) {
|
|
386
|
+
if (t.status !== 'done')
|
|
387
|
+
continue;
|
|
388
|
+
const done = [{ vcs: t.vcs, at: t.finishedAt }, ...(t.attempts ?? []).map((a) => ({ vcs: a.vcs, at: a.finishedAt }))]
|
|
389
|
+
.filter((v) => !!v.vcs?.commit && !!v.vcs.branch)
|
|
390
|
+
.sort((a, b) => (b.at ?? '').localeCompare(a.at ?? ''))[0];
|
|
391
|
+
if (done?.vcs?.commit && !(await isAncestor(dir, done.vcs.commit, tip)))
|
|
392
|
+
missing.push(`"${t.title}" (on ${done.vcs.branch})`);
|
|
393
|
+
}
|
|
394
|
+
if (missing.length > 0) {
|
|
395
|
+
return {
|
|
396
|
+
problem: `this session continues the previous session "${best.session.name}", whose done work is not on one branch: ${best.branch} does not have ` +
|
|
397
|
+
`${missing.slice(0, 8).join(', ')}${missing.length > 8 ? `, and ${missing.length - 8} more` : ''}. ` +
|
|
398
|
+
'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"), ' +
|
|
399
|
+
'or run that session "One branch for the whole session" so the next one can carry on from it.',
|
|
400
|
+
};
|
|
230
401
|
}
|
|
231
402
|
return { start: { kind: 'previous-session', commit: tip, branch: best.branch, fromSession: { id: best.session.id, name: best.session.name } } };
|
|
232
403
|
}
|
|
@@ -247,6 +418,17 @@ function lastWorkOf(session) {
|
|
|
247
418
|
}
|
|
248
419
|
return best;
|
|
249
420
|
}
|
|
421
|
+
/** When a session last did anything: the latest start or end of any of its tasks' attempts. */
|
|
422
|
+
function lastActivityOf(session) {
|
|
423
|
+
let at = null;
|
|
424
|
+
for (const t of session.tasks) {
|
|
425
|
+
for (const v of [t.finishedAt, t.startedAt, ...(t.attempts ?? []).flatMap((a) => [a.finishedAt, a.startedAt])]) {
|
|
426
|
+
if (v && (!at || v > at))
|
|
427
|
+
at = v;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return at;
|
|
431
|
+
}
|
|
250
432
|
async function branchTip(dir, branch) {
|
|
251
433
|
if (!(await isValidBranchName(dir, branch)))
|
|
252
434
|
return null;
|
|
@@ -271,6 +453,13 @@ export function describeStart(start) {
|
|
|
271
453
|
const updated = start.update ? ` (${describeUpdate(start.update)})` : '';
|
|
272
454
|
return start.note ? `${said}${updated} — ${start.note}` : `${said}${updated}`;
|
|
273
455
|
}
|
|
456
|
+
/** One line for the log: the session's input files, and whether the runner had to commit them on its start. */
|
|
457
|
+
export function describeInputs(start) {
|
|
458
|
+
const n = start.inputs?.files.length ?? 0;
|
|
459
|
+
const carried = start.inputs?.carried;
|
|
460
|
+
return (`${n} input file(s) in the session's start (${start.commit.slice(0, 8)})${start.inputs?.readOnly ? ', read-only' : ''}` +
|
|
461
|
+
(carried ? `: they were not in ${carried.onto.slice(0, 8)}, so they were committed on top of it as ${carried.branch}, from ${carried.from}` : ''));
|
|
462
|
+
}
|
|
274
463
|
/** Whether the update before a session's start is worth a warning: it did not bring the branch up to date. */
|
|
275
464
|
export function updateWarns(start) {
|
|
276
465
|
return !!start.update && !['updated', 'up-to-date', 'no-remote'].includes(start.update.outcome);
|
|
@@ -346,6 +535,7 @@ opts) {
|
|
|
346
535
|
base: vcs.baseCommit ? { commit: vcs.baseCommit, subject } : undefined,
|
|
347
536
|
earlier,
|
|
348
537
|
start: opts.start,
|
|
538
|
+
artifacts: artifactPatterns(session.vcs),
|
|
349
539
|
});
|
|
350
540
|
return { vcs, note };
|
|
351
541
|
}
|
|
@@ -408,6 +598,14 @@ export function noteFor(repoDir, vcs, ctx = { mode: 'per-task', earlier: [] }) {
|
|
|
408
598
|
'commit instead: `git merge-base --is-ancestor <commit> HEAD` exits 0 when it is.',
|
|
409
599
|
'',
|
|
410
600
|
...(began ? [began, ''] : []),
|
|
601
|
+
...(inputsNote(ctx.start?.inputs) ? [inputsNote(ctx.start?.inputs), ''] : []),
|
|
602
|
+
...((ctx.artifacts?.length ?? 0) > 0
|
|
603
|
+
? [
|
|
604
|
+
`Evidence goes under ${ctx.artifacts?.map((a) => `\`${a}\``).join(', ')}: those files are kept with the run's record and are never committed, ` +
|
|
605
|
+
'so write reports, archives and test results there rather than changing .gitignore for them.',
|
|
606
|
+
'',
|
|
607
|
+
]
|
|
608
|
+
: []),
|
|
411
609
|
standing,
|
|
412
610
|
'',
|
|
413
611
|
'- Do not create branches, switch branches, commit, stash, reset or revert. That is the',
|
|
@@ -515,6 +713,30 @@ export async function commitTaskResult(session, task, outcome, bus) {
|
|
|
515
713
|
...(foreign.length > 0 ? { foreignCommits: foreign } : {}),
|
|
516
714
|
});
|
|
517
715
|
}
|
|
716
|
+
/**
|
|
717
|
+
* Why a task's work is not committed although version control is on and commits it, or undefined
|
|
718
|
+
* when it is (or there was nothing to commit). Read after `commitTaskResult`; a task that would end
|
|
719
|
+
* done ends failed with this instead. See `finish` in the runner.
|
|
720
|
+
*/
|
|
721
|
+
export async function commitShortfall(session, before, after, error) {
|
|
722
|
+
if (!session.vcs?.enabled || !session.vcs.commitOnFinish)
|
|
723
|
+
return undefined;
|
|
724
|
+
if (error)
|
|
725
|
+
return `version control failed after the task, so its work was not committed: ${error}. The changes are left in the working tree.`;
|
|
726
|
+
if (!after?.branch) {
|
|
727
|
+
// Never on a branch of its own. The start refuses that now; whatever got through, it is said.
|
|
728
|
+
const state = await repoState(repoDirOf(session));
|
|
729
|
+
return state.isRepo && state.dirty
|
|
730
|
+
? `version control is on but was not active for this task (${after?.problem ?? before?.problem ?? 'no branch was made'}), so its changes were not committed: ${someOf(state.changed)}. They are left in the working tree.`
|
|
731
|
+
: undefined;
|
|
732
|
+
}
|
|
733
|
+
if (after.problem)
|
|
734
|
+
return `the runner could not commit the task's work: ${after.problem}`;
|
|
735
|
+
if (after.afterCommit && !after.afterCommit.clean) {
|
|
736
|
+
return `after the runner's commit the working tree still has uncommitted changes (${someOf(after.afterCommit.changed)}), so not all of the task's work is on ${after.branch}.`;
|
|
737
|
+
}
|
|
738
|
+
return undefined;
|
|
739
|
+
}
|
|
518
740
|
/**
|
|
519
741
|
* Commits what a task left behind when the process running it ended before it could.
|
|
520
742
|
*
|
|
@@ -699,27 +921,40 @@ export async function vcsPreflight(session, allSessions = async () => []) {
|
|
|
699
921
|
const state = await repoState(repoDir);
|
|
700
922
|
if (!state.isRepo)
|
|
701
923
|
return { ok: false, repoDir, problem: state.problem };
|
|
702
|
-
//
|
|
703
|
-
|
|
924
|
+
// Artifacts do not count: the run keeps them out of git before it looks (see `excludeArtifacts`).
|
|
925
|
+
const artifacts = artifactPatterns(settings);
|
|
926
|
+
const changed = state.dirty && artifacts.length > 0 ? (await workingTreePaths(repoDir)).filter((p) => !inScope(p, artifacts)) : state.changed;
|
|
927
|
+
const dirty = changed.length > 0;
|
|
928
|
+
/*
|
|
929
|
+
* Before the first task, under a snapshot policy or with input files: the list to approve, file by
|
|
930
|
+
* file. Input files are looked for even in a clean tree — an ignored input does not make it dirty.
|
|
931
|
+
*/
|
|
932
|
+
const inputs = !!inputSettings(settings);
|
|
933
|
+
if ((dirty || inputs) && (!session.vcsBaseCommit || inputs) && (dirtyPolicy(settings).policy !== 'reject' || inputs) && settings.startFrom !== 'existing-branch') {
|
|
704
934
|
const snapshot = await planSnapshot(session, allSessions);
|
|
705
935
|
if (snapshot.needed) {
|
|
936
|
+
const listed = snapshot.entries.map((e) => e.path);
|
|
706
937
|
return {
|
|
707
938
|
ok: false,
|
|
708
939
|
repoDir,
|
|
709
940
|
branch: state.branch ?? undefined,
|
|
710
|
-
problem: snapshot.
|
|
711
|
-
?
|
|
712
|
-
|
|
941
|
+
problem: snapshot.recapture
|
|
942
|
+
? snapshot.ok
|
|
943
|
+
? `Input files changed or were added since the session started (${someOf(listed, 3)}). They are committed on its line of work ${snapshot.requireApproval ? 'once you approve the list below' : 'when its next task starts'}.`
|
|
944
|
+
: `Input files changed since the session started, and they cannot be taken: ${snapshot.problem}`
|
|
945
|
+
: snapshot.ok
|
|
946
|
+
? `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'}.`
|
|
947
|
+
: `There are uncommitted changes, and no starting snapshot can be taken: ${snapshot.problem}`,
|
|
713
948
|
snapshot,
|
|
714
949
|
};
|
|
715
950
|
}
|
|
716
951
|
}
|
|
717
|
-
if (
|
|
952
|
+
if (dirty) {
|
|
718
953
|
return {
|
|
719
954
|
ok: false,
|
|
720
955
|
repoDir,
|
|
721
956
|
branch: state.branch ?? undefined,
|
|
722
|
-
problem: `There are uncommitted changes (${
|
|
957
|
+
problem: `There are uncommitted changes (${changed.slice(0, 3).join(', ')}${changed.length > 3 ? '…' : ''}). Commit or stash them first.`,
|
|
723
958
|
};
|
|
724
959
|
}
|
|
725
960
|
return { ok: true, repoDir, branch: state.branch ?? undefined };
|
package/dist/web/404.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--ofnRLEgWx9th5w_qtuFnB--><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-d9c54f7a2b285b3f.js" async=""></script><script src="/_next/static/chunks/549-5d7c845fb0a27dbe.js" async=""></script><script src="/_next/static/chunks/app/layout-3efbb282292ccc38.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[8078,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-d9c54f7a2b285b3f.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-3efbb282292ccc38.js\"],\"AppearanceProvider\"]\n3:I[867,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-d9c54f7a2b285b3f.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-3efbb282292ccc38.js\"],\"LanguageProvider\"]\n4:I[1035,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-d9c54f7a2b285b3f.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-3efbb282292ccc38.js\"],\"DialogHost\"]\n5:I[8214,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-d9c54f7a2b285b3f.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-3efbb282292ccc38.js\"],\"SkipLink\"]\n6:I[8197,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-d9c54f7a2b285b3f.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-3efbb282292ccc38.js\"],\"\"]\n7:I[8214,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-d9c54f7a2b285b3f.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-3efbb282292ccc38.js\"],\"Nav\"]\n8:I[6657,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-d9c54f7a2b285b3f.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-3efbb282292ccc38.js\"],\"GlobalApprovals\"]\n9:I[5204,[],\"\"]\na:I[2642,[],\"\"]\nb:I[7712,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-d9c54f7a2b285b3f.js\",\"549\",\"static/chunks/549-5d7c845fb0a27dbe.js\",\"177\",\"static/chunks/app/layout-3efbb282292ccc38.js\"],\"ScrollJump\"]\nc:I[433,[],\"OutletBoundary\"]\ne:I[9884,[],\"AsyncMetadataOutlet\"]\n10:I[433,[],\"ViewportBoundary\"]\n12:I[433,[],\"MetadataBoundary\"]\n13:\"$Sreact.suspense\"\n15:I[3536,[],\"\"]\n:HL[\"/_next/static/css/c37978b44194c37b.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"ofnRLEgWx9th5w_qtuFnB\",\"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\":\"\\n(function () {\\n try {\\n var d = document.documentElement;\\n var raw = localStorage.getItem('cop.appearance');\\n var a = raw ? JSON.parse(raw) : {};\\n if (!a || typeof a !== 'object') a = {};\\n d.dataset.theme = a.theme === 'dark' ? 'dark' : 'light';\\n d.dataset.textsize = [\\\"small\\\",\\\"normal\\\",\\\"large\\\",\\\"huge\\\",\\\"giant\\\"].indexOf(a.textSize) \u003e= 0 ? a.textSize : 'normal';\\n d.dataset.contrast = a.highContrast ? 'high' : 'normal';\\n d.dataset.motion = a.reduceMotion ? 'reduced' : 'normal';\\n d.dataset.links = a.underlineLinks ? 'underline' : 'plain';\\n d.dataset.focus = a.strongFocus ? 'strong' : 'normal';\\n } catch (e) {}\\n})();\\n\"}}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"$L2\",null,{\"children\":[\"$\",\"$L3\",null,{\"children\":[\"$\",\"$L4\",null,{\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"div\",null,{\"className\":\"wrap\",\"children\":[[\"$\",\"header\",null,{\"className\":\"top\",\"children\":[[\"$\",\"h1\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/\",\"children\":\"copilot-operator\"}]}],[\"$\",\"$L7\",null,{}]]}],[\"$\",\"$L8\",null,{}],[\"$\",\"main\",null,{\"id\":\"main\",\"children\":[\"$\",\"$L9\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$La\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}],[\"$\",\"$Lb\",null,{}]]}]}]}]}]]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L9\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$La\",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,[\"$\",\"$Lc\",null,{\"children\":[\"$Ld\",[\"$\",\"$Le\",null,{\"promise\":\"$@f\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$L10\",null,{\"children\":\"$L11\"}],null],[\"$\",\"$L12\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$13\",null,{\"fallback\":null,\"children\":\"$L14\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$15\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"11:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\nd:null\n"])</script><script>self.__next_f.push([1,"f:{\"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,"14:\"$f: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")}}}]);
|