copilot-operator 0.1.38 → 0.1.40

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.
Files changed (55) hide show
  1. package/dist/src/api/operator.controller.js +128 -2
  2. package/dist/src/api/operator.service.js +473 -39
  3. package/dist/src/api/server.js +7 -0
  4. package/dist/src/log/terminal.js +145 -0
  5. package/dist/src/orchestrator/contract.js +77 -6
  6. package/dist/src/plan/brief.js +1375 -1369
  7. package/dist/src/plan/schema.js +5 -0
  8. package/dist/src/plan/systemGuide.js +218 -20
  9. package/dist/src/session/exports.js +1 -0
  10. package/dist/src/session/startFailure.js +91 -0
  11. package/dist/src/vcs/prepareFromRemote.js +7 -20
  12. package/dist/src/vcs/remoteAuth.js +26 -1
  13. package/dist/src/vcs/runPreflight.js +31 -14
  14. package/dist/src/vcs/snapshot.js +3 -1
  15. package/dist/src/vcs/startChoice.js +295 -0
  16. package/dist/src/vcs/taskVcs.js +61 -5
  17. package/dist/web/404.html +2 -2
  18. package/dist/web/_next/static/chunks/499-28e118e33ce07935.js +1 -0
  19. package/dist/web/_next/static/chunks/{549-7e35e4fdefadb05d.js → 549-f295c8429e83b25b.js} +1 -1
  20. package/dist/web/_next/static/chunks/584-578be94a0786334b.js +1 -0
  21. package/dist/web/_next/static/chunks/867-8dc5bbb092ca2c5c.js +1 -0
  22. package/dist/web/_next/static/chunks/app/history/page-9f69ccde726c9be2.js +1 -0
  23. package/dist/web/_next/static/chunks/app/layout-73f28bc065a46ed3.js +1 -0
  24. package/dist/web/_next/static/chunks/app/page-e557d58476ae6383.js +1 -0
  25. package/dist/web/_next/static/chunks/app/sessions/view/page-0485ee7f781156ec.js +1 -0
  26. package/dist/web/_next/static/chunks/app/system/{page-5ae1f8054208e6eb.js → page-227a259e383ca2a0.js} +1 -1
  27. package/dist/web/_next/static/css/cea7913ba416dbb7.css +1 -0
  28. package/dist/web/appearance.html +2 -2
  29. package/dist/web/appearance.txt +28 -26
  30. package/dist/web/defaults.html +2 -2
  31. package/dist/web/defaults.txt +28 -26
  32. package/dist/web/history.html +2 -2
  33. package/dist/web/history.txt +28 -26
  34. package/dist/web/import.html +2 -2
  35. package/dist/web/import.txt +28 -26
  36. package/dist/web/index.html +2 -2
  37. package/dist/web/index.txt +28 -26
  38. package/dist/web/level1.html +2 -2
  39. package/dist/web/level1.txt +28 -26
  40. package/dist/web/presets.html +2 -2
  41. package/dist/web/presets.txt +28 -26
  42. package/dist/web/sessions/view.html +2 -2
  43. package/dist/web/sessions/view.txt +28 -26
  44. package/dist/web/system.html +2 -2
  45. package/dist/web/system.txt +28 -26
  46. package/package.json +158 -156
  47. package/dist/web/_next/static/chunks/36-94660f1cde2da529.js +0 -1
  48. package/dist/web/_next/static/chunks/867-d4f5bd8c5805bffb.js +0 -1
  49. package/dist/web/_next/static/chunks/app/history/page-a0bd59986f7c8beb.js +0 -1
  50. package/dist/web/_next/static/chunks/app/layout-630b663626cebe4a.js +0 -1
  51. package/dist/web/_next/static/chunks/app/page-4defcfd1eb482644.js +0 -1
  52. package/dist/web/_next/static/chunks/app/sessions/view/page-ce99494b1997ee25.js +0 -1
  53. package/dist/web/_next/static/css/c37978b44194c37b.css +0 -1
  54. /package/dist/web/_next/static/{8C2D7RnTerPO3g_WyLEC3 → Y9tuV5LV-O0XyCREkeGc5}/_buildManifest.js +0 -0
  55. /package/dist/web/_next/static/{8C2D7RnTerPO3g_WyLEC3 → Y9tuV5LV-O0XyCREkeGc5}/_ssgManifest.js +0 -0
@@ -55,6 +55,29 @@ function asContextKind(kind) {
55
55
  }
56
56
  return kind;
57
57
  }
58
+ /**
59
+ * The start window's choices as the service takes them: one per session id, each of a known shape, and
60
+ * nothing else. A choice of any other shape is dropped, which leaves that session on its settings.
61
+ */
62
+ function startsFrom(raw) {
63
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
64
+ return undefined;
65
+ const out = {};
66
+ for (const [id, c] of Object.entries(raw)) {
67
+ if (!c || typeof c !== 'object')
68
+ continue;
69
+ const x = c;
70
+ const branch = typeof x.branch === 'string' ? x.branch : '';
71
+ const onBranch = x.onBranch === true ? { onBranch: true } : {};
72
+ if (x.from === 'previous-session')
73
+ out[id] = { from: 'previous-session' };
74
+ else if (x.from === 'local' && branch)
75
+ out[id] = { from: 'local', branch, ...onBranch };
76
+ else if (x.from === 'remote' && branch && typeof x.remote === 'string' && x.remote)
77
+ out[id] = { from: 'remote', remote: x.remote, branch, ...onBranch };
78
+ }
79
+ return Object.keys(out).length > 0 ? out : undefined;
80
+ }
58
81
  function contentDisposition(fileName) {
59
82
  const ascii = fileName.replace(/[^\x20-\x7e]/g, '_').replace(/["\\]/g, '_');
60
83
  return `attachment; filename="${ascii}"; filename*=UTF-8''${encodeURIComponent(fileName)}`;
@@ -171,6 +194,16 @@ let OperatorController = class OperatorController {
171
194
  const { buildOnFinished, ...patch } = body ?? {};
172
195
  return this.ops.rerunTask(id, taskId, patch, { buildOnFinished: buildOnFinished === true }).catch(fail);
173
196
  }
197
+ /** How the task contradicts itself, with the ways out of each contradiction. Changes nothing. */
198
+ contractCheck(id, taskId) {
199
+ return this.ops.contractCheck(id, taskId).catch(fail);
200
+ }
201
+ /** Applies one chosen fix per contradiction (-1 = none) and queues the task; starts nothing. */
202
+ applyContractFix(id, taskId, body) {
203
+ if (body?.expect !== undefined && (!Array.isArray(body.expect) || body.expect.some((x) => typeof x !== 'string')))
204
+ throw new BadRequestException('expect must be a list of the contradictions shown');
205
+ return this.ops.applyContractFix(id, taskId, body?.choices ?? [], body?.expect).catch(fail);
206
+ }
174
207
  /** What going back to before this task would do. Changes nothing. */
175
208
  restorePreview(id, taskId) {
176
209
  return this.ops.restorePreview(id, taskId).catch(fail);
@@ -339,7 +372,47 @@ let OperatorController = class OperatorController {
339
372
  }
340
373
  // --- run control ------------------------------------------------------------------------
341
374
  start(id, body) {
342
- return this.ops.start(id, body?.mode === 'unattended' ? 'unattended' : 'confirm', body?.name);
375
+ return this.ops.start(id, body?.mode === 'unattended' ? 'unattended' : 'confirm', body?.name, startsFrom(body?.starts));
376
+ }
377
+ /**
378
+ * The start window's question: where each of these sessions starts, and the branches of their
379
+ * repositories as they are here (nothing fetched). See `vcs/startChoice.ts`.
380
+ */
381
+ startOptions(sessions) {
382
+ return this.ops.startChoices((sessions ?? '').split(',').map((x) => x.trim()).filter(Boolean)).catch(fail);
383
+ }
384
+ /** Fetches branches of a remote for the start window — through Git's password window when it asks. */
385
+ startFetch(body) {
386
+ const branches = Array.isArray(body?.branches) ? body.branches.filter((b) => typeof b === 'string') : null;
387
+ return this.ops.startFetch(body?.dir ?? '', body?.remote ?? '', branches).catch(fail);
388
+ }
389
+ /** Starts that did not get as far as a first task, newest first; `unanswered=1` only those no press was answered with. */
390
+ startFailures(unanswered) {
391
+ return this.ops.recentStartFailures(unanswered === '1' || unanswered === 'true');
392
+ }
393
+ /** One of them as a text file: the error, where it stopped, the run's record, the events and the console. */
394
+ async startFailureReport(id, res) {
395
+ try {
396
+ const { fileName, content } = await this.ops.startFailureReport(id);
397
+ res.type('text/plain; charset=utf-8');
398
+ res.setHeader('content-disposition', contentDisposition(fileName));
399
+ res.send(content);
400
+ }
401
+ catch (e) {
402
+ failText(res, e);
403
+ }
404
+ }
405
+ /** What the bot's console showed, the latest lines, as a text file. See `log/terminal.ts`. */
406
+ async terminal(res) {
407
+ try {
408
+ const { fileName, content } = await this.ops.terminalReport();
409
+ res.type('text/plain; charset=utf-8');
410
+ res.setHeader('content-disposition', contentDisposition(fileName));
411
+ res.send(content);
412
+ }
413
+ catch (e) {
414
+ failText(res, e);
415
+ }
343
416
  }
344
417
  stop(id) {
345
418
  return this.ops.stop(id);
@@ -377,7 +450,7 @@ let OperatorController = class OperatorController {
377
450
  // same as "no model": an empty string on a session means "leave the chat alone".
378
451
  body?.model,
379
452
  // The same for the review: absent means each session keeps whatever it is set to.
380
- body?.reviewModel, body?.name, body?.taskIds)
453
+ body?.reviewModel, body?.name, body?.taskIds, startsFrom(body?.starts))
381
454
  .catch(fail);
382
455
  }
383
456
  stopBatch() {
@@ -738,6 +811,23 @@ __decorate([
738
811
  __metadata("design:paramtypes", [String, String, Object]),
739
812
  __metadata("design:returntype", Promise)
740
813
  ], OperatorController.prototype, "rerunTask", null);
814
+ __decorate([
815
+ Get('sessions/:id/tasks/:taskId/contract'),
816
+ __param(0, Param('id')),
817
+ __param(1, Param('taskId')),
818
+ __metadata("design:type", Function),
819
+ __metadata("design:paramtypes", [String, String]),
820
+ __metadata("design:returntype", Promise)
821
+ ], OperatorController.prototype, "contractCheck", null);
822
+ __decorate([
823
+ Post('sessions/:id/tasks/:taskId/contract-fix'),
824
+ __param(0, Param('id')),
825
+ __param(1, Param('taskId')),
826
+ __param(2, Body()),
827
+ __metadata("design:type", Function),
828
+ __metadata("design:paramtypes", [String, String, Object]),
829
+ __metadata("design:returntype", Promise)
830
+ ], OperatorController.prototype, "applyContractFix", null);
741
831
  __decorate([
742
832
  Get('sessions/:id/tasks/:taskId/restore'),
743
833
  __param(0, Param('id')),
@@ -895,6 +985,42 @@ __decorate([
895
985
  __metadata("design:paramtypes", [String, Object]),
896
986
  __metadata("design:returntype", Promise)
897
987
  ], OperatorController.prototype, "start", null);
988
+ __decorate([
989
+ Get('start/options'),
990
+ __param(0, Query('sessions')),
991
+ __metadata("design:type", Function),
992
+ __metadata("design:paramtypes", [String]),
993
+ __metadata("design:returntype", Promise)
994
+ ], OperatorController.prototype, "startOptions", null);
995
+ __decorate([
996
+ Post('start/fetch'),
997
+ __param(0, Body()),
998
+ __metadata("design:type", Function),
999
+ __metadata("design:paramtypes", [Object]),
1000
+ __metadata("design:returntype", Promise)
1001
+ ], OperatorController.prototype, "startFetch", null);
1002
+ __decorate([
1003
+ Get('start/failures'),
1004
+ __param(0, Query('unanswered')),
1005
+ __metadata("design:type", Function),
1006
+ __metadata("design:paramtypes", [String]),
1007
+ __metadata("design:returntype", Object)
1008
+ ], OperatorController.prototype, "startFailures", null);
1009
+ __decorate([
1010
+ Get('start/failures/:id/report'),
1011
+ __param(0, Param('id')),
1012
+ __param(1, Res()),
1013
+ __metadata("design:type", Function),
1014
+ __metadata("design:paramtypes", [String, Object]),
1015
+ __metadata("design:returntype", Promise)
1016
+ ], OperatorController.prototype, "startFailureReport", null);
1017
+ __decorate([
1018
+ Get('terminal'),
1019
+ __param(0, Res()),
1020
+ __metadata("design:type", Function),
1021
+ __metadata("design:paramtypes", [Object]),
1022
+ __metadata("design:returntype", Promise)
1023
+ ], OperatorController.prototype, "terminal", null);
898
1024
  __decorate([
899
1025
  Post('sessions/:id/stop'),
900
1026
  __param(0, Param('id')),