crewly 1.20.307 → 1.20.308
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/config/hooks/agent-status/report.sh +5 -5
- package/dist/backend/backend/src/constants.d.ts +66 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +66 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts +9 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +126 -2
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/board/board-activity.normalizer.d.ts +17 -0
- package/dist/backend/backend/src/services/board/board-activity.normalizer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/board/board-activity.normalizer.js +8 -5
- package/dist/backend/backend/src/services/board/board-activity.normalizer.js.map +1 -1
- package/dist/backend/backend/src/services/board/board-activity.tracker.d.ts +5 -0
- package/dist/backend/backend/src/services/board/board-activity.tracker.d.ts.map +1 -1
- package/dist/backend/backend/src/services/board/board-activity.tracker.js +25 -1
- package/dist/backend/backend/src/services/board/board-activity.tracker.js.map +1 -1
- package/dist/backend/backend/src/services/board/board-push.service.d.ts +20 -2
- package/dist/backend/backend/src/services/board/board-push.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/board/board-push.service.js +71 -9
- package/dist/backend/backend/src/services/board/board-push.service.js.map +1 -1
- package/dist/backend/backend/src/services/board/board-snapshot.builder.d.ts +7 -0
- package/dist/backend/backend/src/services/board/board-snapshot.builder.d.ts.map +1 -1
- package/dist/backend/backend/src/services/board/board-snapshot.builder.js +2 -0
- package/dist/backend/backend/src/services/board/board-snapshot.builder.js.map +1 -1
- package/dist/backend/backend/src/services/board/board.sources.d.ts.map +1 -1
- package/dist/backend/backend/src/services/board/board.sources.js +7 -0
- package/dist/backend/backend/src/services/board/board.sources.js.map +1 -1
- package/dist/backend/backend/src/services/board/board.types.d.ts +5 -0
- package/dist/backend/backend/src/services/board/board.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/board/canvas/canvas-inbound.service.d.ts +122 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-inbound.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-inbound.service.js +339 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-inbound.service.js.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-redact.d.ts +44 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-redact.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-redact.js +161 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-redact.js.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-step.normalizer.d.ts +57 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-step.normalizer.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-step.normalizer.js +164 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-step.normalizer.js.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-step.stream.d.ts +140 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-step.stream.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-step.stream.js +300 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-step.stream.js.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-terminal.service.d.ts +99 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-terminal.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-terminal.service.js +223 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-terminal.service.js.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-transcript.tail.d.ts +126 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-transcript.tail.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-transcript.tail.js +385 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-transcript.tail.js.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-wiring.d.ts +103 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-wiring.js +124 -0
- package/dist/backend/backend/src/services/board/canvas/canvas-wiring.js.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas.types.d.ts +88 -0
- package/dist/backend/backend/src/services/board/canvas/canvas.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/board/canvas/canvas.types.js +8 -0
- package/dist/backend/backend/src/services/board/canvas/canvas.types.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js +2 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +66 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +66 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.js +1 -0
- package/dist/cli/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Masked terminal tail for the canvas (crewly#1247 v2).
|
|
3
|
+
*
|
|
4
|
+
* The owner opens an agent's terminal in the portal: Cloud relays
|
|
5
|
+
* `terminal_open`, and this service posts the agent's PTY tail to Cloud about
|
|
6
|
+
* once a second - the first frame is the last 200 lines - until the viewer
|
|
7
|
+
* stops renewing (a lease of 2 minutes, renewed by `terminal_renew` every
|
|
8
|
+
* 60 s), closes it, the agent's session ends, Cloud says it is no longer
|
|
9
|
+
* wanted, or the stream has run 30 minutes.
|
|
10
|
+
*
|
|
11
|
+
* Every frame is masked on the machine ({@link maskTerminalText}: secrets by
|
|
12
|
+
* value, by name and by shape, emails, URL queries, bearer tokens, password
|
|
13
|
+
* prompts, long token-like words) BEFORE it is posted; a frame is only posted
|
|
14
|
+
* when its masked content changed. Frames are never written to disk here and
|
|
15
|
+
* Cloud keeps them in memory only.
|
|
16
|
+
*
|
|
17
|
+
* @module services/board/canvas/canvas-terminal.service
|
|
18
|
+
*/
|
|
19
|
+
import type { SecretEnvValue } from '../../../utils/secret-env.js';
|
|
20
|
+
import { type ComponentLogger } from '../../core/logger.service.js';
|
|
21
|
+
import type { TerminalFrame } from './canvas.types.js';
|
|
22
|
+
/** The Cloud session (CloudClientService). */
|
|
23
|
+
export interface TerminalCloud {
|
|
24
|
+
getToken(): string | null;
|
|
25
|
+
getCloudUrl(): string | null;
|
|
26
|
+
tryRefreshToken?(): Promise<boolean>;
|
|
27
|
+
}
|
|
28
|
+
/** Constructor dependencies. */
|
|
29
|
+
export interface CanvasTerminalDeps {
|
|
30
|
+
cloud: TerminalCloud;
|
|
31
|
+
/** This machine's Cloud instance id */
|
|
32
|
+
identity: () => Promise<{
|
|
33
|
+
instanceId: string;
|
|
34
|
+
}>;
|
|
35
|
+
/** The raw PTY tail of a session, or null when it has none */
|
|
36
|
+
capture: (session: string, lines: number) => string | null;
|
|
37
|
+
/** Whether the agent's terminal session exists */
|
|
38
|
+
exists: (session: string) => boolean;
|
|
39
|
+
/** Exact secret values to mask */
|
|
40
|
+
secrets?: () => readonly SecretEnvValue[];
|
|
41
|
+
fetchImpl?: (input: string, init: RequestInit) => Promise<Response>;
|
|
42
|
+
now?: () => number;
|
|
43
|
+
setTimeout?: (fn: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
44
|
+
clearTimeout?: (h: ReturnType<typeof setTimeout>) => void;
|
|
45
|
+
logger?: ComponentLogger;
|
|
46
|
+
}
|
|
47
|
+
/** Why a stream could not be opened. */
|
|
48
|
+
export type TerminalOpenResult = {
|
|
49
|
+
ok: true;
|
|
50
|
+
} | {
|
|
51
|
+
ok: false;
|
|
52
|
+
code: 'no_session' | 'too_many_streams' | 'not_signed_in';
|
|
53
|
+
};
|
|
54
|
+
/** Streams masked PTY tails to Cloud while a viewer holds a lease. */
|
|
55
|
+
export declare class CanvasTerminalService {
|
|
56
|
+
private readonly deps;
|
|
57
|
+
private readonly streams;
|
|
58
|
+
private readonly logger;
|
|
59
|
+
private readonly now;
|
|
60
|
+
private readonly fetchImpl;
|
|
61
|
+
private readonly setTimer;
|
|
62
|
+
private readonly clearTimer;
|
|
63
|
+
constructor(deps: CanvasTerminalDeps);
|
|
64
|
+
/** Sessions being streamed. */
|
|
65
|
+
active(): string[];
|
|
66
|
+
/**
|
|
67
|
+
* Start (or restart) a stream; the first frame goes out at once.
|
|
68
|
+
*
|
|
69
|
+
* @param session - Agent session
|
|
70
|
+
* @returns Whether it is streaming
|
|
71
|
+
*/
|
|
72
|
+
open(session: string): TerminalOpenResult;
|
|
73
|
+
/**
|
|
74
|
+
* The viewer is still there: extend the lease.
|
|
75
|
+
*
|
|
76
|
+
* @param session - Agent session
|
|
77
|
+
* @returns False when no stream is open (the viewer must open again)
|
|
78
|
+
*/
|
|
79
|
+
renew(session: string): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Stop a stream; a last frame tells Cloud it ended.
|
|
82
|
+
*
|
|
83
|
+
* @param session - Agent session
|
|
84
|
+
* @param reason - Why it ended
|
|
85
|
+
*/
|
|
86
|
+
close(session: string, reason?: NonNullable<TerminalFrame['reason']>): void;
|
|
87
|
+
/** Stop every stream (shutdown). */
|
|
88
|
+
closeAll(): void;
|
|
89
|
+
private schedule;
|
|
90
|
+
/** One frame: stop if the stream is over, else mask the tail and post it when it changed. */
|
|
91
|
+
private tick;
|
|
92
|
+
/**
|
|
93
|
+
* Post one frame.
|
|
94
|
+
*
|
|
95
|
+
* @returns `ok`; `stop` when Cloud no longer wants frames (404 / 403 / 410, `keep: false`); `retry` on any other failure
|
|
96
|
+
*/
|
|
97
|
+
private post;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=canvas-terminal.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-terminal.service.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/board/canvas/canvas-terminal.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEnF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC7B,QAAQ,IAAI,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,IAAI,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACrC;AAED,gCAAgC;AAChC,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,aAAa,CAAC;IACrB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,8DAA8D;IAC9D,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC3D,kDAAkD;IAClD,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACrC,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,SAAS,cAAc,EAAE,CAAC;IAC1C,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IAC3E,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,CAAC;IAC1D,MAAM,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,wCAAwC;AACxC,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,YAAY,GAAG,kBAAkB,GAAG,eAAe,CAAA;CAAE,CAAC;AAezH,sEAAsE;AACtE,qBAAa,qBAAqB;IAQrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0D;IACpF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgE;IACzF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6C;gBAE3C,IAAI,EAAE,kBAAkB;IAcrD,+BAA+B;IAC/B,MAAM,IAAI,MAAM,EAAE;IAIlB;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB;IAkBzC;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAO/B;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAY,GAAG,IAAI;IASrF,oCAAoC;IACpC,QAAQ,IAAI,IAAI;IAIhB,OAAO,CAAC,QAAQ;IAQhB,6FAA6F;YAC/E,IAAI;IAqClB;;;;OAIG;YACW,IAAI;CA4ClB"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Masked terminal tail for the canvas (crewly#1247 v2).
|
|
3
|
+
*
|
|
4
|
+
* The owner opens an agent's terminal in the portal: Cloud relays
|
|
5
|
+
* `terminal_open`, and this service posts the agent's PTY tail to Cloud about
|
|
6
|
+
* once a second - the first frame is the last 200 lines - until the viewer
|
|
7
|
+
* stops renewing (a lease of 2 minutes, renewed by `terminal_renew` every
|
|
8
|
+
* 60 s), closes it, the agent's session ends, Cloud says it is no longer
|
|
9
|
+
* wanted, or the stream has run 30 minutes.
|
|
10
|
+
*
|
|
11
|
+
* Every frame is masked on the machine ({@link maskTerminalText}: secrets by
|
|
12
|
+
* value, by name and by shape, emails, URL queries, bearer tokens, password
|
|
13
|
+
* prompts, long token-like words) BEFORE it is posted; a frame is only posted
|
|
14
|
+
* when its masked content changed. Frames are never written to disk here and
|
|
15
|
+
* Cloud keeps them in memory only.
|
|
16
|
+
*
|
|
17
|
+
* @module services/board/canvas/canvas-terminal.service
|
|
18
|
+
*/
|
|
19
|
+
import { gzipSync } from 'zlib';
|
|
20
|
+
import { CANVAS_CONSTANTS, BOARD_CONSTANTS } from '../../../constants.js';
|
|
21
|
+
import { LoggerService } from '../../core/logger.service.js';
|
|
22
|
+
import { maskTerminalText } from './canvas-redact.js';
|
|
23
|
+
const C = CANVAS_CONSTANTS;
|
|
24
|
+
/** Streams masked PTY tails to Cloud while a viewer holds a lease. */
|
|
25
|
+
export class CanvasTerminalService {
|
|
26
|
+
deps;
|
|
27
|
+
streams = new Map();
|
|
28
|
+
logger;
|
|
29
|
+
now;
|
|
30
|
+
fetchImpl;
|
|
31
|
+
setTimer;
|
|
32
|
+
clearTimer;
|
|
33
|
+
constructor(deps) {
|
|
34
|
+
this.deps = deps;
|
|
35
|
+
this.logger = deps.logger ?? LoggerService.getInstance().createComponentLogger('CanvasTerminal');
|
|
36
|
+
this.now = deps.now ?? Date.now;
|
|
37
|
+
this.fetchImpl = deps.fetchImpl ?? ((input, init) => fetch(input, init));
|
|
38
|
+
this.setTimer =
|
|
39
|
+
deps.setTimeout ??
|
|
40
|
+
((fn, ms) => {
|
|
41
|
+
const t = setTimeout(fn, ms);
|
|
42
|
+
t.unref?.();
|
|
43
|
+
return t;
|
|
44
|
+
});
|
|
45
|
+
this.clearTimer = deps.clearTimeout ?? ((h) => clearTimeout(h));
|
|
46
|
+
}
|
|
47
|
+
/** Sessions being streamed. */
|
|
48
|
+
active() {
|
|
49
|
+
return [...this.streams.keys()];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Start (or restart) a stream; the first frame goes out at once.
|
|
53
|
+
*
|
|
54
|
+
* @param session - Agent session
|
|
55
|
+
* @returns Whether it is streaming
|
|
56
|
+
*/
|
|
57
|
+
open(session) {
|
|
58
|
+
if (!this.deps.cloud.getToken() || !this.deps.cloud.getCloudUrl())
|
|
59
|
+
return { ok: false, code: 'not_signed_in' };
|
|
60
|
+
if (!this.deps.exists(session))
|
|
61
|
+
return { ok: false, code: 'no_session' };
|
|
62
|
+
const existing = this.streams.get(session);
|
|
63
|
+
if (existing) {
|
|
64
|
+
existing.leaseUntil = this.now() + C.TERMINAL_LEASE_MS;
|
|
65
|
+
existing.force = true;
|
|
66
|
+
this.schedule(existing, 0);
|
|
67
|
+
return { ok: true };
|
|
68
|
+
}
|
|
69
|
+
if (this.streams.size >= C.TERMINAL_MAX_STREAMS)
|
|
70
|
+
return { ok: false, code: 'too_many_streams' };
|
|
71
|
+
const now = this.now();
|
|
72
|
+
const stream = { session, seq: 0, startedAt: now, leaseUntil: now + C.TERMINAL_LEASE_MS, lastKey: null, failures: 0, timer: null, busy: false, force: true };
|
|
73
|
+
this.streams.set(session, stream);
|
|
74
|
+
this.schedule(stream, 0);
|
|
75
|
+
return { ok: true };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The viewer is still there: extend the lease.
|
|
79
|
+
*
|
|
80
|
+
* @param session - Agent session
|
|
81
|
+
* @returns False when no stream is open (the viewer must open again)
|
|
82
|
+
*/
|
|
83
|
+
renew(session) {
|
|
84
|
+
const s = this.streams.get(session);
|
|
85
|
+
if (!s)
|
|
86
|
+
return false;
|
|
87
|
+
s.leaseUntil = this.now() + C.TERMINAL_LEASE_MS;
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Stop a stream; a last frame tells Cloud it ended.
|
|
92
|
+
*
|
|
93
|
+
* @param session - Agent session
|
|
94
|
+
* @param reason - Why it ended
|
|
95
|
+
*/
|
|
96
|
+
close(session, reason = 'closed') {
|
|
97
|
+
const s = this.streams.get(session);
|
|
98
|
+
if (!s)
|
|
99
|
+
return;
|
|
100
|
+
this.streams.delete(session);
|
|
101
|
+
if (s.timer)
|
|
102
|
+
this.clearTimer(s.timer);
|
|
103
|
+
s.timer = null;
|
|
104
|
+
void this.post(s, [], true, reason).catch(() => undefined);
|
|
105
|
+
}
|
|
106
|
+
/** Stop every stream (shutdown). */
|
|
107
|
+
closeAll() {
|
|
108
|
+
for (const session of [...this.streams.keys()])
|
|
109
|
+
this.close(session, 'closed');
|
|
110
|
+
}
|
|
111
|
+
schedule(s, delayMs) {
|
|
112
|
+
if (s.timer)
|
|
113
|
+
this.clearTimer(s.timer);
|
|
114
|
+
s.timer = this.setTimer(() => {
|
|
115
|
+
s.timer = null;
|
|
116
|
+
void this.tick(s);
|
|
117
|
+
}, delayMs);
|
|
118
|
+
}
|
|
119
|
+
/** One frame: stop if the stream is over, else mask the tail and post it when it changed. */
|
|
120
|
+
async tick(s) {
|
|
121
|
+
if (this.streams.get(s.session) !== s || s.busy)
|
|
122
|
+
return;
|
|
123
|
+
s.busy = true;
|
|
124
|
+
try {
|
|
125
|
+
const now = this.now();
|
|
126
|
+
if (now > s.leaseUntil)
|
|
127
|
+
return this.close(s.session, 'lease_expired');
|
|
128
|
+
if (now - s.startedAt > C.TERMINAL_MAX_STREAM_MS)
|
|
129
|
+
return this.close(s.session, 'too_long');
|
|
130
|
+
if (!this.deps.exists(s.session))
|
|
131
|
+
return this.close(s.session, 'session_gone');
|
|
132
|
+
let raw = null;
|
|
133
|
+
try {
|
|
134
|
+
raw = this.deps.capture(s.session, C.TERMINAL_TAIL_LINES);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
raw = null;
|
|
138
|
+
}
|
|
139
|
+
if (raw !== null) {
|
|
140
|
+
const lines = maskTerminalText(raw, this.deps.secrets?.() ?? []);
|
|
141
|
+
const key = lines.join('\n');
|
|
142
|
+
if (s.force || key !== s.lastKey) {
|
|
143
|
+
const outcome = await this.post(s, lines, false);
|
|
144
|
+
if (this.streams.get(s.session) !== s)
|
|
145
|
+
return;
|
|
146
|
+
if (outcome === 'stop')
|
|
147
|
+
return this.close(s.session, 'cloud_stopped');
|
|
148
|
+
if (outcome === 'ok') {
|
|
149
|
+
s.lastKey = key;
|
|
150
|
+
s.force = false;
|
|
151
|
+
s.failures = 0;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
s.failures += 1;
|
|
155
|
+
if (s.failures >= C.TERMINAL_MAX_FAILURES)
|
|
156
|
+
return this.close(s.session, 'send_failed');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (this.streams.get(s.session) === s)
|
|
161
|
+
this.schedule(s, C.TERMINAL_FRAME_INTERVAL_MS);
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
s.busy = false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Post one frame.
|
|
169
|
+
*
|
|
170
|
+
* @returns `ok`; `stop` when Cloud no longer wants frames (404 / 403 / 410, `keep: false`); `retry` on any other failure
|
|
171
|
+
*/
|
|
172
|
+
async post(s, lines, closed, reason) {
|
|
173
|
+
const token = this.deps.cloud.getToken();
|
|
174
|
+
const base = this.deps.cloud.getCloudUrl();
|
|
175
|
+
if (!token || !base)
|
|
176
|
+
return 'retry';
|
|
177
|
+
const instanceId = (await this.deps.identity()).instanceId;
|
|
178
|
+
s.seq += 1;
|
|
179
|
+
const frame = {
|
|
180
|
+
instanceId,
|
|
181
|
+
session: s.session,
|
|
182
|
+
seq: s.seq,
|
|
183
|
+
at: new Date(this.now()).toISOString(),
|
|
184
|
+
lines,
|
|
185
|
+
...(closed ? { closed: true, ...(reason ? { reason } : {}) } : {}),
|
|
186
|
+
};
|
|
187
|
+
let refreshed = false;
|
|
188
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
189
|
+
let response;
|
|
190
|
+
try {
|
|
191
|
+
response = await this.fetchImpl(`${base.replace(/\/$/, '')}${C.TERMINAL_FRAME_PATH}`, {
|
|
192
|
+
method: 'POST',
|
|
193
|
+
headers: {
|
|
194
|
+
Authorization: `Bearer ${this.deps.cloud.getToken() ?? token}`,
|
|
195
|
+
'Content-Type': 'application/json',
|
|
196
|
+
'Content-Encoding': 'gzip',
|
|
197
|
+
[BOARD_CONSTANTS.INSTANCE_HEADER]: instanceId,
|
|
198
|
+
},
|
|
199
|
+
body: gzipSync(Buffer.from(JSON.stringify(frame))),
|
|
200
|
+
signal: AbortSignal.timeout(C.REQUEST_TIMEOUT_MS),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return 'retry';
|
|
205
|
+
}
|
|
206
|
+
if (response.status === 401 && !refreshed && this.deps.cloud.tryRefreshToken) {
|
|
207
|
+
refreshed = true;
|
|
208
|
+
if (await this.deps.cloud.tryRefreshToken().catch(() => false))
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (response.status === 404 || response.status === 403 || response.status === 410)
|
|
212
|
+
return 'stop';
|
|
213
|
+
if (!response.ok)
|
|
214
|
+
return 'retry';
|
|
215
|
+
if (closed)
|
|
216
|
+
return 'ok';
|
|
217
|
+
const parsed = (await response.json().catch(() => null));
|
|
218
|
+
return parsed?.data?.keep === false ? 'stop' : 'ok';
|
|
219
|
+
}
|
|
220
|
+
return 'retry';
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=canvas-terminal.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-terminal.service.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/board/canvas/canvas-terminal.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transcript tail for the canvas (crewly#1247 v2): the agent's own short text
|
|
3
|
+
* lines (and, for Codex, its tool calls) from the runtime's own transcript.
|
|
4
|
+
*
|
|
5
|
+
* - Claude Code: `<claude home>/projects/<cwd>/<session id>.jsonl` (located the
|
|
6
|
+
* way the turn-state fallback does). Only `assistant` `text` blocks become
|
|
7
|
+
* steps, reduced by {@link shortAgentLine}; a `tool_result`'s `is_error` flag
|
|
8
|
+
* marks its step failed. Tool inputs, tool OUTPUTS, thinking and user
|
|
9
|
+
* messages are never read into anything.
|
|
10
|
+
* - Codex: `<codex home>/sessions/.../rollout-*-<conversation id>.jsonl`.
|
|
11
|
+
* Assistant `output_text` becomes text steps; shell / exec / apply_patch
|
|
12
|
+
* calls become command / edit steps (reduced to executable + subcommand /
|
|
13
|
+
* file name), paired with their output by call id for the duration. Output
|
|
14
|
+
* bodies are not read.
|
|
15
|
+
*
|
|
16
|
+
* Incremental: a byte cursor per file, only whole new lines, at most
|
|
17
|
+
* {@link CANVAS_CONSTANTS.TAIL_MAX_READ_BYTES} per pass; lines that cannot be
|
|
18
|
+
* a text / error line are skipped by substring before any JSON.parse (tool
|
|
19
|
+
* results are the bulk of a transcript). Nothing is logged or stored beyond
|
|
20
|
+
* the redacted step.
|
|
21
|
+
*
|
|
22
|
+
* @module services/board/canvas/canvas-transcript.tail
|
|
23
|
+
*/
|
|
24
|
+
import type { SecretEnvValue } from '../../../utils/secret-env.js';
|
|
25
|
+
import { relativePath } from '../board-redact.js';
|
|
26
|
+
import { type StepShape } from './canvas-step.normalizer.js';
|
|
27
|
+
import type { StepStream } from './canvas-step.stream.js';
|
|
28
|
+
/** What a chunk of transcript says. */
|
|
29
|
+
export type TailItem = {
|
|
30
|
+
kind: 'text';
|
|
31
|
+
id: string;
|
|
32
|
+
at: number;
|
|
33
|
+
text: string;
|
|
34
|
+
} | {
|
|
35
|
+
kind: 'tool_error';
|
|
36
|
+
toolUseId: string;
|
|
37
|
+
at: number;
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'step_start';
|
|
40
|
+
id: string;
|
|
41
|
+
at: number;
|
|
42
|
+
shape: StepShape;
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'step_end';
|
|
45
|
+
id: string;
|
|
46
|
+
at: number;
|
|
47
|
+
};
|
|
48
|
+
/** Parse options. */
|
|
49
|
+
export interface TailParseOptions {
|
|
50
|
+
secrets?: readonly SecretEnvValue[];
|
|
51
|
+
roots?: readonly string[];
|
|
52
|
+
/** Drop text older than this (epoch ms) */
|
|
53
|
+
minAt?: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Items from whole lines of a Claude Code transcript.
|
|
57
|
+
*
|
|
58
|
+
* @param text - Whole JSONL lines
|
|
59
|
+
* @param opts - Secrets to mask, oldest text to keep
|
|
60
|
+
* @param now - Fallback time for an entry with no timestamp
|
|
61
|
+
* @returns Items in file order
|
|
62
|
+
*/
|
|
63
|
+
export declare function parseClaudeTail(text: string, opts?: TailParseOptions, now?: number): TailItem[];
|
|
64
|
+
/**
|
|
65
|
+
* Items from whole lines of a Codex rollout.
|
|
66
|
+
*
|
|
67
|
+
* @param text - Whole JSONL lines
|
|
68
|
+
* @param opts - Secrets to mask, project roots, oldest text to keep
|
|
69
|
+
* @param now - Fallback time for an entry with no timestamp
|
|
70
|
+
* @returns Items in file order
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseCodexTail(text: string, opts?: TailParseOptions, now?: number): TailItem[];
|
|
73
|
+
/** Where a session's transcript is. */
|
|
74
|
+
export interface TailTarget {
|
|
75
|
+
kind: 'claude' | 'codex';
|
|
76
|
+
file: string;
|
|
77
|
+
}
|
|
78
|
+
/** Collaborators. */
|
|
79
|
+
export interface TranscriptTailDeps {
|
|
80
|
+
steps: StepStream;
|
|
81
|
+
/** Sessions to follow */
|
|
82
|
+
sessions: () => string[];
|
|
83
|
+
/** The session's transcript, or null (Gemini, agy: none) */
|
|
84
|
+
locate: (session: string) => Promise<TailTarget | null> | TailTarget | null;
|
|
85
|
+
/** Project roots of a session (relative paths) */
|
|
86
|
+
roots?: (session: string) => readonly string[];
|
|
87
|
+
/** Exact secret values to mask */
|
|
88
|
+
secrets?: () => readonly SecretEnvValue[];
|
|
89
|
+
/** Someone is watching: poll faster */
|
|
90
|
+
isLive?: () => boolean;
|
|
91
|
+
now?: () => number;
|
|
92
|
+
setTimeout?: (fn: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
93
|
+
clearTimeout?: (h: ReturnType<typeof setTimeout>) => void;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Follows the transcripts of the agents and feeds the step stream.
|
|
97
|
+
*/
|
|
98
|
+
export declare class TranscriptTailService {
|
|
99
|
+
private readonly deps;
|
|
100
|
+
private readonly cursors;
|
|
101
|
+
private readonly located;
|
|
102
|
+
private timer;
|
|
103
|
+
private running;
|
|
104
|
+
private started;
|
|
105
|
+
private readonly now;
|
|
106
|
+
private readonly setTimer;
|
|
107
|
+
private readonly clearTimer;
|
|
108
|
+
constructor(deps: TranscriptTailDeps);
|
|
109
|
+
/** Start polling. Idempotent. */
|
|
110
|
+
start(): void;
|
|
111
|
+
/** Stop polling. */
|
|
112
|
+
stop(): void;
|
|
113
|
+
private schedule;
|
|
114
|
+
/**
|
|
115
|
+
* One pass over every followed session. Never throws.
|
|
116
|
+
*
|
|
117
|
+
* @returns Items fed to the stream
|
|
118
|
+
*/
|
|
119
|
+
tick(): Promise<number>;
|
|
120
|
+
private target;
|
|
121
|
+
private follow;
|
|
122
|
+
private feed;
|
|
123
|
+
}
|
|
124
|
+
/** Re-exported for the wiring: a path made relative to project roots. */
|
|
125
|
+
export { relativePath };
|
|
126
|
+
//# sourceMappingURL=canvas-transcript.tail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-transcript.tail.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/board/canvas/canvas-transcript.tail.ts"],"names":[],"mappings":"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"}
|