copilot-operator 0.1.5 → 0.1.6
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 +5 -2
- package/dist/src/api/operator.service.js +34 -12
- package/dist/src/orchestrator/taskRunner.js +11 -1
- package/dist/src/plan/brief.js +52 -10
- package/dist/src/plan/script.js +13 -0
- package/dist/src/plan/systemGuide.js +1377 -185
- package/dist/src/session/compose.js +5 -1
- package/dist/src/session/exports.js +1 -0
- package/dist/src/session/store.js +4 -1
- package/dist/src/session/story.js +10 -1
- package/dist/src/vcs/taskVcs.js +2 -1
- package/dist/web/404.html +2 -2
- package/dist/web/_next/static/chunks/549-afafecd6bfbb138e.js +1 -0
- package/dist/web/_next/static/chunks/56-91cd1709158ebf99.js +1 -0
- package/dist/web/_next/static/chunks/867-fc983d08916b4e28.js +1 -0
- package/dist/web/_next/static/chunks/app/history/page-b3b4af994c868b5d.js +1 -0
- package/dist/web/_next/static/chunks/app/layout-e0174d863960f109.js +1 -0
- package/dist/web/_next/static/chunks/app/sessions/view/{page-4631bdf5113a73b2.js → page-d4213354730a945c.js} +1 -1
- package/dist/web/_next/static/css/{5a10c60adf9c5336.css → 63fea96806e6b2cb.css} +1 -1
- package/dist/web/appearance.html +2 -2
- package/dist/web/appearance.txt +25 -24
- package/dist/web/defaults.html +2 -2
- package/dist/web/defaults.txt +25 -24
- package/dist/web/history.html +2 -2
- package/dist/web/history.txt +25 -24
- package/dist/web/import.html +2 -2
- package/dist/web/import.txt +25 -24
- package/dist/web/index.html +2 -2
- package/dist/web/index.txt +25 -24
- package/dist/web/level1.html +2 -2
- package/dist/web/level1.txt +25 -24
- package/dist/web/presets.html +2 -2
- package/dist/web/presets.txt +25 -24
- package/dist/web/sessions/view.html +2 -2
- package/dist/web/sessions/view.txt +25 -24
- package/dist/web/system.html +2 -2
- package/dist/web/system.txt +25 -24
- package/package.json +1 -1
- package/dist/web/_next/static/chunks/549-2086c05135bc9753.js +0 -1
- package/dist/web/_next/static/chunks/867-0cd2c3cfd0ff0a45.js +0 -1
- package/dist/web/_next/static/chunks/89-382e9b29486d2747.js +0 -1
- package/dist/web/_next/static/chunks/app/history/page-83543937cecde5de.js +0 -1
- package/dist/web/_next/static/chunks/app/layout-92fa876afe619cf3.js +0 -1
- /package/dist/web/_next/static/{7TE2rEuHqGdGx14If8TEb → WJ_8hRZsp4VWiDZx8NMUw}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{7TE2rEuHqGdGx14If8TEb → WJ_8hRZsp4VWiDZx8NMUw}/_ssgManifest.js +0 -0
|
@@ -133,7 +133,8 @@ let OperatorController = class OperatorController {
|
|
|
133
133
|
return this.ops.continueTask(id, taskId).catch(fail);
|
|
134
134
|
}
|
|
135
135
|
rerunTask(id, taskId, body) {
|
|
136
|
-
|
|
136
|
+
const { buildOnFinished, ...patch } = body ?? {};
|
|
137
|
+
return this.ops.rerunTask(id, taskId, patch, { buildOnFinished: buildOnFinished === true }).catch(fail);
|
|
137
138
|
}
|
|
138
139
|
/** What going back to before this task would do. Changes nothing. */
|
|
139
140
|
restorePreview(id, taskId) {
|
|
@@ -320,13 +321,15 @@ let OperatorController = class OperatorController {
|
|
|
320
321
|
startBatch(body) {
|
|
321
322
|
if (!Array.isArray(body?.sessionIds))
|
|
322
323
|
throw new BadRequestException('sessionIds must be a list of session ids');
|
|
324
|
+
if (body?.taskIds !== undefined && !Array.isArray(body.taskIds))
|
|
325
|
+
throw new BadRequestException('taskIds must be a list of task ids');
|
|
323
326
|
return this.ops
|
|
324
327
|
.startBatch(body.sessionIds, body?.mode === 'unattended' ? 'unattended' : 'confirm', body?.onFailure === 'continue' ? 'continue' : 'stop',
|
|
325
328
|
// Absent or empty means every session keeps the model it already has, which is not the
|
|
326
329
|
// same as "no model": an empty string on a session means "leave the chat alone".
|
|
327
330
|
body?.model,
|
|
328
331
|
// The same for the review: absent means each session keeps whatever it is set to.
|
|
329
|
-
body?.reviewModel, body?.name)
|
|
332
|
+
body?.reviewModel, body?.name, body?.taskIds)
|
|
330
333
|
.catch(fail);
|
|
331
334
|
}
|
|
332
335
|
stopBatch() {
|
|
@@ -20,7 +20,7 @@ import { installLayout } from '../config/layout.js';
|
|
|
20
20
|
import { SessionStore, DEFAULT_VCS, DEFAULT_REVIEW } from '../session/store.js';
|
|
21
21
|
import { EventBus } from '../session/events.js';
|
|
22
22
|
import { newId, tidyVcsPlan } from '../session/model.js';
|
|
23
|
-
import { runSession, openBrowser } from '../orchestrator/taskRunner.js';
|
|
23
|
+
import { runSession, openBrowser, queuedToRun } from '../orchestrator/taskRunner.js';
|
|
24
24
|
import { buildExport } from '../session/exportRecord.js';
|
|
25
25
|
import { buildDebugExport } from '../session/debugExport.js';
|
|
26
26
|
import { buildPlanExport, buildDomainExport, buildBotExport, buildBundleExport, exportFileName, exportMachine, taskAtAttempt, withTask, writeAttemptRecord } from '../session/exports.js';
|
|
@@ -328,16 +328,26 @@ let OperatorService = class OperatorService {
|
|
|
328
328
|
});
|
|
329
329
|
return task;
|
|
330
330
|
}
|
|
331
|
-
async rerunTask(sessionId, taskId, patch = {}
|
|
331
|
+
async rerunTask(sessionId, taskId, patch = {},
|
|
332
|
+
/**
|
|
333
|
+
* A new prompt for a task that ended done builds on what it did: the next attempt works on
|
|
334
|
+
* that attempt's branch. Only for a done task — a failed attempt's work is what is being
|
|
335
|
+
* replaced, so a re-run of one starts again from where the task first started.
|
|
336
|
+
*/
|
|
337
|
+
opts = {}) {
|
|
332
338
|
await this.init();
|
|
333
|
-
const
|
|
339
|
+
const before = (await this.store.getSession(sessionId))?.tasks.find((t) => t.id === taskId);
|
|
340
|
+
const buildsOn = opts.buildOnFinished && before?.status === 'done' ? { fromAttempt: before.attempt ?? 1 } : undefined;
|
|
341
|
+
const task = await this.store.rerunTask(sessionId, taskId, patch, undefined, buildsOn);
|
|
334
342
|
this.bus.publish({
|
|
335
343
|
sessionId,
|
|
336
344
|
taskId,
|
|
337
345
|
type: 'task-requeued',
|
|
338
346
|
level: 'info',
|
|
339
|
-
message:
|
|
340
|
-
|
|
347
|
+
message: buildsOn
|
|
348
|
+
? `"${task.title}" is queued again with a new prompt that builds on attempt ${buildsOn.fromAttempt} (attempt ${task.attempt ?? 1})`
|
|
349
|
+
: `"${task.title}" is queued again (attempt ${task.attempt ?? 1})`,
|
|
350
|
+
data: { attempt: task.attempt, ...(buildsOn ? { buildsOn } : {}) },
|
|
341
351
|
});
|
|
342
352
|
return task;
|
|
343
353
|
}
|
|
@@ -643,7 +653,9 @@ let OperatorService = class OperatorService {
|
|
|
643
653
|
/** A browser that is already open. A batch passes its own; a single run opens one. */
|
|
644
654
|
transport,
|
|
645
655
|
/** The press of a start button this belongs to, stamped onto every task it reaches. */
|
|
646
|
-
runGroup
|
|
656
|
+
runGroup,
|
|
657
|
+
/** Only these queued tasks, when the operator chose some; the rest stay queued. */
|
|
658
|
+
onlyTasks) {
|
|
647
659
|
await this.init();
|
|
648
660
|
// Every project's Desktop copy brought up to date before the chat opens, when the operator
|
|
649
661
|
// asked for that. Before the run rather than before each task: a task's own mirror already
|
|
@@ -655,7 +667,7 @@ let OperatorService = class OperatorService {
|
|
|
655
667
|
const session = await this.store.getSession(sessionId);
|
|
656
668
|
if (!session)
|
|
657
669
|
return { started: false, reason: 'no such session', done: Promise.resolve(idle) };
|
|
658
|
-
const queuedIds = session
|
|
670
|
+
const queuedIds = queuedToRun(session, onlyTasks).map((t) => t.id);
|
|
659
671
|
if (queuedIds.length === 0)
|
|
660
672
|
return { started: false, reason: 'no queued tasks', done: Promise.resolve(idle) };
|
|
661
673
|
const cfg = await this.settings.load();
|
|
@@ -714,6 +726,7 @@ let OperatorService = class OperatorService {
|
|
|
714
726
|
continueOnFailure: session.onFailure === 'continue',
|
|
715
727
|
transport,
|
|
716
728
|
runGroup,
|
|
729
|
+
onlyTasks,
|
|
717
730
|
})
|
|
718
731
|
.then(async (outcome) => ({ ...(await this.tally(sessionId, queuedIds)), paused: outcome.paused }))
|
|
719
732
|
.catch(async (e) => {
|
|
@@ -816,8 +829,15 @@ let OperatorService = class OperatorService {
|
|
|
816
829
|
*/
|
|
817
830
|
reviewModel,
|
|
818
831
|
/** What to call the run. Offered from the plan's name; empty means it goes by its id. */
|
|
819
|
-
name
|
|
832
|
+
name,
|
|
833
|
+
/**
|
|
834
|
+
* The queued tasks to run, when not every queued task of those sessions: what the operator
|
|
835
|
+
* ticked in the register. A session none of whose chosen tasks is queued is skipped; the
|
|
836
|
+
* tasks nobody chose stay queued exactly as they were. Absent means every queued task.
|
|
837
|
+
*/
|
|
838
|
+
taskIds) {
|
|
820
839
|
await this.init();
|
|
840
|
+
const onlyTasks = taskIds && taskIds.length > 0 ? new Set(taskIds.map((t) => t.trim()).filter(Boolean)) : undefined;
|
|
821
841
|
if (this.batch?.running)
|
|
822
842
|
return { started: false, reason: 'a batch is already running' };
|
|
823
843
|
const wanted = [...new Set(sessionIds.map((s) => s.trim()).filter(Boolean))];
|
|
@@ -837,9 +857,9 @@ let OperatorService = class OperatorService {
|
|
|
837
857
|
sessions.push({ sessionId: id, name: id, state: 'skipped', ran: 0, failed: 0, reason: 'no such session' });
|
|
838
858
|
continue;
|
|
839
859
|
}
|
|
840
|
-
const queued = s
|
|
860
|
+
const queued = queuedToRun(s, onlyTasks).length;
|
|
841
861
|
sessions.push(queued === 0
|
|
842
|
-
? { sessionId: id, name: s.name, state: 'skipped', ran: 0, failed: 0, reason: 'nothing queued' }
|
|
862
|
+
? { sessionId: id, name: s.name, state: 'skipped', ran: 0, failed: 0, reason: onlyTasks ? 'none of its chosen tasks is queued' : 'nothing queued' }
|
|
843
863
|
: { sessionId: id, name: s.name, state: 'waiting', ran: 0, failed: 0 });
|
|
844
864
|
}
|
|
845
865
|
if (!sessions.some((s) => s.state === 'waiting')) {
|
|
@@ -899,6 +919,7 @@ let OperatorService = class OperatorService {
|
|
|
899
919
|
id: newId('b-'),
|
|
900
920
|
startedAt: new Date().toISOString(),
|
|
901
921
|
name: chosenName,
|
|
922
|
+
...(onlyTasks ? { onlyTasks: [...onlyTasks] } : {}),
|
|
902
923
|
mode,
|
|
903
924
|
onFailure,
|
|
904
925
|
stopping: false,
|
|
@@ -1045,7 +1066,8 @@ let OperatorService = class OperatorService {
|
|
|
1045
1066
|
s.runGroup = {
|
|
1046
1067
|
...runGroup,
|
|
1047
1068
|
order: at,
|
|
1048
|
-
|
|
1069
|
+
// What this run was asked to do: the chosen tasks, when some were chosen.
|
|
1070
|
+
taskIds: queuedToRun(s, batch.onlyTasks).map((t) => t.id),
|
|
1049
1071
|
mode: batch.mode,
|
|
1050
1072
|
onFailure: batch.onFailure,
|
|
1051
1073
|
};
|
|
@@ -1075,7 +1097,7 @@ let OperatorService = class OperatorService {
|
|
|
1075
1097
|
message: `starting as part of a batch of ${batch.sessions.length} session(s), in ${batch.mode} mode`,
|
|
1076
1098
|
data: { batchId: batch.id },
|
|
1077
1099
|
});
|
|
1078
|
-
const begun = await this.beginRun(entry.sessionId, batch.mode, browser, runGroup);
|
|
1100
|
+
const begun = await this.beginRun(entry.sessionId, batch.mode, browser, runGroup, batch.onlyTasks ? new Set(batch.onlyTasks) : undefined);
|
|
1079
1101
|
if (!begun.started) {
|
|
1080
1102
|
entry.state = 'skipped';
|
|
1081
1103
|
entry.reason = begun.reason;
|
|
@@ -626,6 +626,7 @@ export async function runTask(transport, session, task, deps) {
|
|
|
626
626
|
taskNumber,
|
|
627
627
|
contractAlreadySent: session.contractSent,
|
|
628
628
|
continuing: task.continuing,
|
|
629
|
+
buildsOn: task.buildsOn,
|
|
629
630
|
workDirNote: workingDirNote(work),
|
|
630
631
|
vcsNote: prepared.note,
|
|
631
632
|
readOnlyNote: task.readOnly ? READ_ONLY_NOTE : undefined,
|
|
@@ -1462,6 +1463,15 @@ export async function runTask(transport, session, task, deps) {
|
|
|
1462
1463
|
return await finish('failed', crash ? `${describeCrash(crash)}. Then: ${message}` : message);
|
|
1463
1464
|
}
|
|
1464
1465
|
}
|
|
1466
|
+
/**
|
|
1467
|
+
* The queued tasks of a session a run takes: all of them, or only the ones the operator chose.
|
|
1468
|
+
* One rule for the run itself and for every place that counts or records what a run will do, so
|
|
1469
|
+
* the batch entrance, the run's record and the run cannot disagree about it.
|
|
1470
|
+
*/
|
|
1471
|
+
export function queuedToRun(session, onlyTasks) {
|
|
1472
|
+
const only = onlyTasks ? new Set(onlyTasks) : undefined;
|
|
1473
|
+
return session.tasks.filter((t) => t.status === 'queued' && (!only || only.has(t.id)));
|
|
1474
|
+
}
|
|
1465
1475
|
/**
|
|
1466
1476
|
* Runs every queued task of a session, in order, in one conversation. Stops at the first
|
|
1467
1477
|
* task that does not end with `done` unless `continueOnFailure` is set, because a failed
|
|
@@ -1472,7 +1482,7 @@ export async function runSession(sessionId, deps) {
|
|
|
1472
1482
|
let session = await store.getSession(sessionId);
|
|
1473
1483
|
if (!session)
|
|
1474
1484
|
throw new Error(`Session ${sessionId} does not exist.`);
|
|
1475
|
-
const queued = session
|
|
1485
|
+
const queued = queuedToRun(session, deps.onlyTasks);
|
|
1476
1486
|
if (queued.length === 0) {
|
|
1477
1487
|
bus.publish({ sessionId, type: 'session-idle', level: 'info', message: 'no queued tasks' });
|
|
1478
1488
|
return { ran: 0, paused: false };
|
package/dist/src/plan/brief.js
CHANGED
|
@@ -633,6 +633,18 @@ your paraphrase means. Quote the label, and name the page by the route in the he
|
|
|
633
633
|
button in the guide, say so and ask what they can see, rather than inventing one. A label written
|
|
634
634
|
with {braces} is filled in with a number or a name at the time, so quote it with the braces and
|
|
635
635
|
say what will be in them.
|
|
636
|
+
|
|
637
|
+
**When asked what to do next, or where something is:** first be sure which page they are on and
|
|
638
|
+
what they see — ask, in one line, if it is not clear. Then answer as numbered steps, each naming the
|
|
639
|
+
page by its route, the section by its bold heading from the guide, and the control by its exact
|
|
640
|
+
label. Say the condition a control needs when the guide gives one ("only in the **"Flow"** view",
|
|
641
|
+
"only after **"Work on branches and commit what was changed"** is ticked"), because a control that is
|
|
642
|
+
not showing is otherwise a control that "does not exist".
|
|
643
|
+
|
|
644
|
+
**A run that looks stuck is usually waiting for them.** A step waiting for a decision appears at the
|
|
645
|
+
top of every page under **"A step is waiting for your decision"**, one card per step, with **"Run"**,
|
|
646
|
+
**"Run this and the rest without asking"**, **"Skip"** and **"Abort task"**; the browser tab then
|
|
647
|
+
starts with "(n) waiting for you". Send them there first.
|
|
636
648
|
`.trim();
|
|
637
649
|
const GUIDE_RULE_BG = `
|
|
638
650
|
## Говори с думите от екрана
|
|
@@ -645,6 +657,18 @@ const GUIDE_RULE_BG = `
|
|
|
645
657
|
**Никога не пращай оператора към контрол, който не е изброен там.** Ако това, което искаш да се
|
|
646
658
|
направи, няма бутон в справочника, кажи го и попитай какво вижда, вместо да си измислиш. Надпис с
|
|
647
659
|
{скоби} се попълва с число или име в момента — цитирай го със скобите и казвай какво ще има в тях.
|
|
660
|
+
|
|
661
|
+
**Когато те питат какво следва или къде е нещо:** първо се увери на коя страница е операторът и
|
|
662
|
+
какво вижда — попитай с един ред, ако не е ясно. После отговаряй с номерирани стъпки, като всяка
|
|
663
|
+
назовава страницата с маршрута, раздела с удебеленото му заглавие от справочника и контрола с точния
|
|
664
|
+
му надпис. Казвай условието, което контролът изисква, когато справочникът го дава („само в изгледа
|
|
665
|
+
**„Поток“**“, „само след отметка на **„Работи по клонове и комитвай промененото“**“), защото
|
|
666
|
+
контрол, който не се вижда, иначе е контрол, който „го няма“.
|
|
667
|
+
|
|
668
|
+
**Пускане, което изглежда заседнало, обикновено чака оператора.** Стъпка, чакаща решение, се
|
|
669
|
+
появява горе на всяка страница под **„Стъпка чака вашето решение“**, по една карта за стъпка, с
|
|
670
|
+
**„Изпълни“**, **„Изпълни без да питаш повече“**, **„Пропусни“** и **„Прекрати задачата“**; разделът
|
|
671
|
+
на браузъра тогава започва с „(n) чака вас“. Прати го там първо.
|
|
648
672
|
`.trim();
|
|
649
673
|
/**
|
|
650
674
|
* The persona's two later roles, software level: what the operator brings back when a task
|
|
@@ -699,14 +723,23 @@ in those words, every time:
|
|
|
699
723
|
- **A new prompt.** The task text was ambiguous, a path or a port was wrong, the level 2 forbade
|
|
700
724
|
what the task needed, a check asked the git index about a file the runner had not committed yet,
|
|
701
725
|
or the chat did the wrong thing and the checks caught it. Give the whole replacement text, then:
|
|
702
|
-
1. On \`/history\`, press **"Fix the prompt and queue it again"** on that row.
|
|
726
|
+
1. On \`/history\`, in the **"Flow"** view, press **"Fix the prompt and queue it again"** on that row.
|
|
703
727
|
2. Replace the text with the one above and press **"Save and queue again"**.
|
|
704
|
-
3.
|
|
705
|
-
|
|
706
|
-
|
|
728
|
+
3. Under **"What is next"**, press **"Continue: run the {n} queued task(s) in {s} session(s)"**
|
|
729
|
+
(it reads **"Continue: run {f} failed and {n} queued task(s) in {s} session(s)"** when a chain
|
|
730
|
+
has a failed task).
|
|
731
|
+
4. In **"Before it continues"** every task is ticked. To run only the fixed one, press
|
|
732
|
+
**"only this one"** beside it.
|
|
733
|
+
5. Press **"Continue without asking"** — the left-hand button — to let it run, or
|
|
734
|
+
**"Continue, asking before each command"** beside it to approve every one.
|
|
707
735
|
|
|
708
736
|
A check that is wrong rather than a prompt that is wrong is edited instead: **"Edit"** on the
|
|
709
|
-
task card, then **"What it checks"**, **"Must be"** and **"Command"** under **"Checks"
|
|
737
|
+
task card, then **"What it checks"**, **"Must be"** and **"Command"** under **"Checks"**, then
|
|
738
|
+
**"Save and queue it again"** — which, like every "queue" button, starts nothing by itself.
|
|
739
|
+
A task that ended **limit-reached** is carried on in its own chat instead: **"Continue in the
|
|
740
|
+
same chat"** on its card on the session page, then **"Run {n} task(s)"** at the top of that page.
|
|
741
|
+
When a failure shows up while the run is still going, **"Pause after this task"** holds the rest
|
|
742
|
+
while you work it out.
|
|
710
743
|
Putting the repository back to before the task is **"Restore"**; putting it back and re-running
|
|
711
744
|
that task and every task after it is **"Run again from here"**.
|
|
712
745
|
- **A change to the bot.** No wording fixes it: the shell the task needs is not on the machine,
|
|
@@ -851,14 +884,23 @@ const PHASE3_BG = `
|
|
|
851
884
|
забранявало това, което задачата иска, проверка е питала git индекса за файл, който runner-ът
|
|
852
885
|
още не е комитнал, или чатът е направил грешното нещо и проверките са го хванали. Дай целия
|
|
853
886
|
нов текст, после:
|
|
854
|
-
1. В \`/history
|
|
887
|
+
1. В \`/history\`, в изгледа **„Поток“**, натисни **„Поправи prompt-а и върни в опашката“** на този ред.
|
|
855
888
|
2. Замени текста с горния и натисни **„Запази и върни в опашката“**.
|
|
856
|
-
3.
|
|
857
|
-
|
|
858
|
-
|
|
889
|
+
3. Под **„Какво следва“** натисни **„Продължи: пусни {n} чакащи задачи в {s} сесии“** (пише
|
|
890
|
+
**„Продължи: пусни {f} провалили се и {n} чакащи задачи в {s} сесии“**, когато във верига има
|
|
891
|
+
провалена задача).
|
|
892
|
+
4. В **„Преди да продължи“** всички задачи са отметнати. За да пуснеш само поправената, натисни
|
|
893
|
+
**„само тази“** до нея.
|
|
894
|
+
5. Натисни **„Продължи без да пита“** — левият бутон — за да върви само, или **„Продължи, с
|
|
895
|
+
питане преди всяка команда“** до него, за да одобряваш всяка.
|
|
859
896
|
|
|
860
897
|
Когато е сгрешена проверката, а не prompt-ът, се редактира друго: **„Редактирай“** на картата
|
|
861
|
-
на задачата, после **„Какво проверява“**, **„Трябва“** и **„Команда“** под
|
|
898
|
+
на задачата, после **„Какво проверява“**, **„Трябва“** и **„Команда“** под **„Проверки“**, после
|
|
899
|
+
**„Запази и върни в опашката“** — който, като всеки бутон за връщане в опашката, сам не пуска нищо.
|
|
900
|
+
Задача, завършила с **limit-reached**, продължава в собствения си чат: **„Продължи в същия чат“**
|
|
901
|
+
на картата ѝ на страницата на сесията, после **„Пусни {n} задача(и)“** горе на същата страница.
|
|
902
|
+
Когато провал се покаже, докато пускането още върви, **„Пауза след тази задача“** задържа
|
|
903
|
+
останалото, докато го разбереш.
|
|
862
904
|
Връщането на хранилището отпреди задачата е **„Върни“**; връщането му плюс ново изпълнение на
|
|
863
905
|
тази задача и всички след нея е **„Пусни отново оттук“**.
|
|
864
906
|
- **Промяна по бота.** Никакви думи не го оправят: обвивката, която задачата иска, я няма на
|
package/dist/src/plan/script.js
CHANGED
|
@@ -658,6 +658,19 @@ export const SCRIPT = [
|
|
|
658
658
|
},
|
|
659
659
|
],
|
|
660
660
|
},
|
|
661
|
+
{
|
|
662
|
+
choose: { en: 'Where each session starts, if 1.1 (`startFrom`):', bg: 'Откъде тръгва всяка сесия, ако е 1.1 (`startFrom`):' },
|
|
663
|
+
options: [
|
|
664
|
+
{
|
|
665
|
+
en: 'From the local branch main — every session starts from the same clean code (branch; name another in baseBranch)',
|
|
666
|
+
bg: 'От локалния клон main — всяка сесия тръгва от един и същ чист код (branch; друг клон в baseBranch)',
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
en: "From the previous session's branch — the sessions form a chain (previous-session)",
|
|
670
|
+
bg: 'От клона на предната сесия — сесиите образуват верига (previous-session)',
|
|
671
|
+
},
|
|
672
|
+
],
|
|
673
|
+
},
|
|
661
674
|
{
|
|
662
675
|
choose: { en: 'If a task fails (`onFailure` of the session, required):', bg: 'Ако задача се провали (`onFailure` на сесията, задължително):' },
|
|
663
676
|
options: [
|