copilot-operator 0.1.16 → 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.controller.js +23 -0
- package/dist/src/api/operator.service.js +55 -3
- 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 +60 -0
- package/dist/src/plan/importPlan.js +35 -1
- package/dist/src/plan/schema.js +62 -0
- package/dist/src/plan/systemGuide.js +72 -0
- package/dist/src/protocol/replySchema.js +1 -1
- package/dist/src/protocol/reviewSchema.js +10 -5
- package/dist/src/session/exports.js +46 -13
- package/dist/src/session/model.js +20 -0
- package/dist/src/session/store.js +146 -6
- package/dist/src/vcs/artifacts.js +138 -0
- package/dist/src/vcs/inputs.js +332 -0
- package/dist/src/vcs/snapshot.js +395 -0
- package/dist/src/vcs/taskVcs.js +183 -27
- 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/page-409e37e208dc12e5.js +1 -0
- package/dist/web/_next/static/chunks/app/sessions/view/page-27cb2d544b498d92.js +1 -0
- package/dist/web/_next/static/css/{e2a2c9eb3c226313.css → c37978b44194c37b.css} +1 -1
- package/dist/web/appearance.html +2 -2
- package/dist/web/appearance.txt +12 -12
- package/dist/web/defaults.html +2 -2
- package/dist/web/defaults.txt +12 -12
- package/dist/web/history.html +2 -2
- package/dist/web/history.txt +12 -12
- package/dist/web/import.html +2 -2
- package/dist/web/import.txt +12 -12
- package/dist/web/index.html +2 -2
- package/dist/web/index.txt +12 -12
- package/dist/web/level1.html +2 -2
- package/dist/web/level1.txt +12 -12
- package/dist/web/presets.html +2 -2
- package/dist/web/presets.txt +12 -12
- package/dist/web/sessions/view.html +2 -2
- package/dist/web/sessions/view.txt +12 -12
- package/dist/web/system.html +2 -2
- package/dist/web/system.txt +12 -12
- package/package.json +9 -3
- package/prompts/level1.md +547 -546
- package/dist/web/_next/static/chunks/549-7fd4fe96682299f5.js +0 -1
- package/dist/web/_next/static/chunks/867-631dc4314840fed6.js +0 -1
- package/dist/web/_next/static/chunks/app/history/page-d7314ac22d47a3ab.js +0 -1
- package/dist/web/_next/static/chunks/app/page-13572a726de0b7db.js +0 -1
- package/dist/web/_next/static/chunks/app/sessions/view/page-886f5fc99e146408.js +0 -1
- /package/dist/web/_next/static/{GhdY7nVcYi-WV3j7saVPK → JPmlfAEvbNkbghoyvY9uC}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{GhdY7nVcYi-WV3j7saVPK → JPmlfAEvbNkbghoyvY9uC}/_ssgManifest.js +0 -0
package/dist/src/vcs/taskVcs.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { findSuspicious } from './commitHygiene.js';
|
|
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';
|
|
2
7
|
import { branchExists, branchNameFrom, describeUpdate, updateFromRemote, localBranches, commitAll, commitFiles, commitsBetween, commitSubject, createBranch, foreignCommits, isAncestor, checkoutExisting, freeBranchName, git, isValidBranchName, plannedBranchName, repoState } from './git.js';
|
|
3
8
|
/** Which repository a session works in: its own setting, else the project it mirrors. */
|
|
4
9
|
export function repoDirOf(session) {
|
|
@@ -30,17 +35,67 @@ allSessions = async () => []) {
|
|
|
30
35
|
if (!settings?.enabled)
|
|
31
36
|
return { vcs: {}, note: '' };
|
|
32
37
|
const dir = repoDirOf(session);
|
|
33
|
-
|
|
38
|
+
let state = await repoState(dir);
|
|
34
39
|
if (!state.isRepo) {
|
|
35
40
|
const problem = state.problem ?? 'The repository could not be read.';
|
|
36
41
|
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-unavailable', level: 'warn',
|
|
37
42
|
message: `version control is on but inactive: ${problem}` });
|
|
38
43
|
return { vcs: { problem }, note: '' };
|
|
39
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);
|
|
40
63
|
if (settings.startFrom === 'existing-branch')
|
|
41
|
-
return await onExistingBranch(session, task, dir, state, bus, saveSession);
|
|
64
|
+
return await onExistingBranch(session, task, dir, state, bus, saveSession, allSessions);
|
|
65
|
+
// The session's base is fixed the first time it runs: every per-task branch is cut from it,
|
|
66
|
+
// which is what makes the tasks independent of each other rather than of the calendar. Where
|
|
67
|
+
// it is taken from is the session's `startFrom`; see `sessionStart`.
|
|
68
|
+
let base = session.vcsBaseCommit;
|
|
69
|
+
let start = session.vcsStart;
|
|
70
|
+
/*
|
|
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.
|
|
75
|
+
*/
|
|
76
|
+
const dirty = dirtyPolicy(settings);
|
|
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);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
42
96
|
// A dirty tree is the operator's own work in progress. Committing it under the bot's name
|
|
43
|
-
// or moving it to another branch would both be decisions that are not ours to make
|
|
97
|
+
// or moving it to another branch would both be decisions that are not ours to make — unless
|
|
98
|
+
// the operator made it, with a snapshot policy, above.
|
|
44
99
|
if (state.dirty) {
|
|
45
100
|
const problem = `the repository has uncommitted changes (${state.changed.slice(0, 5).join(', ')}` +
|
|
46
101
|
`${state.changed.length > 5 ? `, and ${state.changed.length - 5} more` : ''}). ` +
|
|
@@ -49,11 +104,6 @@ allSessions = async () => []) {
|
|
|
49
104
|
message: `version control is on but inactive: ${problem}` });
|
|
50
105
|
return { vcs: { problem }, note: '' };
|
|
51
106
|
}
|
|
52
|
-
// The session's base is fixed the first time it runs: every per-task branch is cut from it,
|
|
53
|
-
// which is what makes the tasks independent of each other rather than of the calendar. Where
|
|
54
|
-
// it is taken from is the session's `startFrom`; see `sessionStart`.
|
|
55
|
-
let base = session.vcsBaseCommit;
|
|
56
|
-
let start = session.vcsStart;
|
|
57
107
|
if (!base) {
|
|
58
108
|
const resolved = await sessionStart(session, dir, state.head, allSessions);
|
|
59
109
|
if ('problem' in resolved) {
|
|
@@ -73,6 +123,24 @@ allSessions = async () => []) {
|
|
|
73
123
|
message: describeStart(chosen), data: { ...chosen } });
|
|
74
124
|
}
|
|
75
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
|
+
}
|
|
76
144
|
const attempt = task.attempt ?? 1;
|
|
77
145
|
const prefix = settings.branchPrefix || 'cop/';
|
|
78
146
|
if (settings.branchMode === 'per-session') {
|
|
@@ -124,7 +192,7 @@ export function namedSessionBranch(vcs) {
|
|
|
124
192
|
* refuses the task before a message is sent. The first run records the branch's tip as where the
|
|
125
193
|
* session started, so the record and a restore know what was there before the work.
|
|
126
194
|
*/
|
|
127
|
-
async function onExistingBranch(session, task, dir, state, bus, saveSession) {
|
|
195
|
+
async function onExistingBranch(session, task, dir, state, bus, saveSession, allSessions) {
|
|
128
196
|
const wanted = (session.vcs?.existingBranch ?? '').trim();
|
|
129
197
|
const refuse = (why) => {
|
|
130
198
|
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-refused', level: 'error', message: why });
|
|
@@ -139,7 +207,8 @@ async function onExistingBranch(session, task, dir, state, bus, saveSession) {
|
|
|
139
207
|
}
|
|
140
208
|
if (state.dirty) {
|
|
141
209
|
return refuse(`the repository has uncommitted changes (${state.changed.slice(0, 5).join(', ')}${state.changed.length > 5 ? `, and ${state.changed.length - 5} more` : ''}), ` +
|
|
142
|
-
`so the work cannot be put on "${wanted}" without taking them along. Commit or stash them first. Nothing was run.`
|
|
210
|
+
`so the work cannot be put on "${wanted}" without taking them along. Commit or stash them first. Nothing was run.` +
|
|
211
|
+
(dirtyPolicy(session.vcs).policy !== 'reject' ? ' A starting snapshot does not apply here: it is a branch of its own, and this session works on the branch you named.' : ''));
|
|
143
212
|
}
|
|
144
213
|
let start = session.vcsStart;
|
|
145
214
|
if (!session.vcsBaseCommit || start?.kind !== 'existing-branch' || start.branch !== wanted) {
|
|
@@ -155,6 +224,24 @@ async function onExistingBranch(session, task, dir, state, bus, saveSession) {
|
|
|
155
224
|
bus.publish({ sessionId: session.id, taskId: task.id, type: 'vcs-start', level: updateWarns(chosen) ? 'warn' : 'info', message: describeStart(chosen), data: { ...chosen } });
|
|
156
225
|
}
|
|
157
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
|
+
}
|
|
158
245
|
const prepared = await switchTo(session, task, dir, wanted, undefined, bus, { reuseExisting: true, mustExist: true, start });
|
|
159
246
|
return prepared.vcs.branch === wanted ? prepared : refuse(`the repository could not be put on "${wanted}": ${prepared.vcs.problem ?? 'unknown reason'}. Nothing was run.`);
|
|
160
247
|
}
|
|
@@ -202,6 +289,31 @@ export async function sessionStart(session, dir, head, allSessions) {
|
|
|
202
289
|
if (!tip) {
|
|
203
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}"`);
|
|
204
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
|
+
}
|
|
205
317
|
return { start: { kind: 'previous-session', commit: tip, branch: best.branch, fromSession: { id: best.session.id, name: best.session.name } } };
|
|
206
318
|
}
|
|
207
319
|
/**
|
|
@@ -233,16 +345,25 @@ function normalise(dir) {
|
|
|
233
345
|
/** One line for the log and the event stream: where this session starts, and why. */
|
|
234
346
|
export function describeStart(start) {
|
|
235
347
|
const at = start.commit.slice(0, 8);
|
|
236
|
-
const said = start.kind === '
|
|
237
|
-
? `this session
|
|
238
|
-
: start.kind === '
|
|
239
|
-
? `this session
|
|
240
|
-
: start.kind === 'branch'
|
|
241
|
-
? `this session
|
|
242
|
-
:
|
|
348
|
+
const said = start.kind === 'snapshot'
|
|
349
|
+
? `this session starts from a snapshot of your uncommitted changes: ${start.branch} (${at}), taken on ${start.snapshot?.fromBranch ?? 'a detached HEAD'} at ${(start.snapshot?.fromCommit ?? '').slice(0, 8)}`
|
|
350
|
+
: start.kind === 'previous-session'
|
|
351
|
+
? `this session continues "${start.fromSession?.name ?? '?'}": it starts from the end of its branch ${start.branch} (${at})`
|
|
352
|
+
: start.kind === 'existing-branch'
|
|
353
|
+
? `this session carries on the existing branch ${start.branch}, from its tip ${at}`
|
|
354
|
+
: start.kind === 'branch'
|
|
355
|
+
? `this session starts from the local branch ${start.branch} (${at})`
|
|
356
|
+
: `this session starts from where the repository was (${at})`;
|
|
243
357
|
const updated = start.update ? ` (${describeUpdate(start.update)})` : '';
|
|
244
358
|
return start.note ? `${said}${updated} — ${start.note}` : `${said}${updated}`;
|
|
245
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
|
+
}
|
|
246
367
|
/** Whether the update before a session's start is worth a warning: it did not bring the branch up to date. */
|
|
247
368
|
export function updateWarns(start) {
|
|
248
369
|
return !!start.update && !['updated', 'up-to-date', 'no-remote'].includes(start.update.outcome);
|
|
@@ -318,6 +439,7 @@ opts) {
|
|
|
318
439
|
base: vcs.baseCommit ? { commit: vcs.baseCommit, subject } : undefined,
|
|
319
440
|
earlier,
|
|
320
441
|
start: opts.start,
|
|
442
|
+
artifacts: artifactPatterns(session.vcs),
|
|
321
443
|
});
|
|
322
444
|
return { vcs, note };
|
|
323
445
|
}
|
|
@@ -355,13 +477,15 @@ export function noteFor(repoDir, vcs, ctx = { mode: 'per-task', earlier: [] }) {
|
|
|
355
477
|
* session's files in its tree, and a model not told so reads them as something to redo or
|
|
356
478
|
* doubt; one that starts from `main` has none of them, and a model not told so goes looking.
|
|
357
479
|
*/
|
|
358
|
-
const began = ctx.start?.kind === '
|
|
359
|
-
? `This session
|
|
360
|
-
: ctx.start?.kind === '
|
|
361
|
-
? `This session
|
|
362
|
-
: ctx.start?.kind === 'branch'
|
|
363
|
-
? `This session
|
|
364
|
-
: ''
|
|
480
|
+
const began = ctx.start?.kind === 'snapshot'
|
|
481
|
+
? `This session started from \`${ctx.start.branch}\`: a commit of the operator's own uncommitted changes, taken before the run so that your work is kept apart from theirs. Those files are in your working tree as the starting point; they are not work for you to redo or undo.`
|
|
482
|
+
: ctx.start?.kind === 'previous-session'
|
|
483
|
+
? `This session continues the work of the earlier session "${ctx.start.fromSession?.name ?? ''}": it was started from the end of its branch \`${ctx.start.branch}\`, so that session's work is already in your working tree. Build on it; do not redo it.`
|
|
484
|
+
: ctx.start?.kind === 'existing-branch'
|
|
485
|
+
? `This session carries on the existing branch \`${ctx.start.branch}\`: the work already on it is in your working tree. Build on it; do not redo it.`
|
|
486
|
+
: ctx.start?.kind === 'branch'
|
|
487
|
+
? `This session started from the local branch \`${ctx.start.branch}\`, not from any earlier session's work${ctx.start.note ? ` (${ctx.start.note})` : ''}.`
|
|
488
|
+
: '';
|
|
365
489
|
return [
|
|
366
490
|
'## Version control',
|
|
367
491
|
'',
|
|
@@ -378,6 +502,14 @@ export function noteFor(repoDir, vcs, ctx = { mode: 'per-task', earlier: [] }) {
|
|
|
378
502
|
'commit instead: `git merge-base --is-ancestor <commit> HEAD` exits 0 when it is.',
|
|
379
503
|
'',
|
|
380
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
|
+
: []),
|
|
381
513
|
standing,
|
|
382
514
|
'',
|
|
383
515
|
'- Do not create branches, switch branches, commit, stash, reset or revert. That is the',
|
|
@@ -661,7 +793,7 @@ export async function restoreToBase(session, task, bus) {
|
|
|
661
793
|
};
|
|
662
794
|
}
|
|
663
795
|
/** What the UI shows before a run: is version control going to work here? */
|
|
664
|
-
export async function vcsPreflight(session) {
|
|
796
|
+
export async function vcsPreflight(session, allSessions = async () => []) {
|
|
665
797
|
const settings = session.vcs;
|
|
666
798
|
if (!settings?.enabled)
|
|
667
799
|
return { ok: false, repoDir: '', problem: 'off' };
|
|
@@ -669,12 +801,36 @@ export async function vcsPreflight(session) {
|
|
|
669
801
|
const state = await repoState(repoDir);
|
|
670
802
|
if (!state.isRepo)
|
|
671
803
|
return { ok: false, repoDir, problem: state.problem };
|
|
672
|
-
|
|
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') {
|
|
814
|
+
const snapshot = await planSnapshot(session, allSessions);
|
|
815
|
+
if (snapshot.needed) {
|
|
816
|
+
const listed = snapshot.entries.map((e) => e.path);
|
|
817
|
+
return {
|
|
818
|
+
ok: false,
|
|
819
|
+
repoDir,
|
|
820
|
+
branch: state.branch ?? undefined,
|
|
821
|
+
problem: snapshot.ok
|
|
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'}.`
|
|
823
|
+
: `There are uncommitted changes, and no starting snapshot can be taken: ${snapshot.problem}`,
|
|
824
|
+
snapshot,
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
if (dirty) {
|
|
673
829
|
return {
|
|
674
830
|
ok: false,
|
|
675
831
|
repoDir,
|
|
676
832
|
branch: state.branch ?? undefined,
|
|
677
|
-
problem: `There are uncommitted changes (${
|
|
833
|
+
problem: `There are uncommitted changes (${changed.slice(0, 3).join(', ')}${changed.length > 3 ? '…' : ''}). Commit or stash them first.`,
|
|
678
834
|
};
|
|
679
835
|
}
|
|
680
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-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"themeScript\"]\n3:I[1205,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"AppearanceProvider\"]\n4:I[867,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"LanguageProvider\"]\n5:I[1035,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"DialogHost\"]\n6:I[8214,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"SkipLink\"]\n7:I[8197,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"\"]\n8:I[8214,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.js\",\"177\",\"static/chunks/app/layout-560bd6d173302e5a.js\"],\"Nav\"]\n9:I[6657,[\"197\",\"static/chunks/197-f7c33a0114fc3db3.js\",\"867\",\"static/chunks/867-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.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-631dc4314840fed6.js\",\"549\",\"static/chunks/549-7fd4fe96682299f5.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/e2a2c9eb3c226313.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"GhdY7nVcYi-WV3j7saVPK\",\"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/e2a2c9eb3c226313.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")}}}]);
|