crewly 1.20.406 → 1.20.408
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/backend/backend/src/constants.d.ts +34 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +34 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/activity/activity.controller.d.ts +29 -0
- package/dist/backend/backend/src/controllers/activity/activity.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/activity/activity.controller.js +77 -0
- package/dist/backend/backend/src/controllers/activity/activity.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +49 -0
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/system.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/system.routes.js +3 -0
- package/dist/backend/backend/src/routes/modules/system.routes.js.map +1 -1
- package/dist/backend/backend/src/services/activity/activity-log.service.d.ts +192 -0
- package/dist/backend/backend/src/services/activity/activity-log.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/activity/activity-log.service.js +343 -0
- package/dist/backend/backend/src/services/activity/activity-log.service.js.map +1 -0
- package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.js +7 -0
- package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts +13 -0
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.js +39 -0
- package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.wiring.js +2 -0
- package/dist/backend/backend/src/services/decisions/decision.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +8 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +24 -5
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +34 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +34 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/middleware/agent-origin-correction.d.ts +31 -0
- package/dist/cli/backend/src/middleware/agent-origin-correction.d.ts.map +1 -0
- package/dist/cli/backend/src/middleware/agent-origin-correction.js +31 -0
- package/dist/cli/backend/src/middleware/agent-origin-correction.js.map +1 -0
- package/dist/cli/backend/src/middleware/api-token.middleware.d.ts +171 -0
- package/dist/cli/backend/src/middleware/api-token.middleware.d.ts.map +1 -0
- package/dist/cli/backend/src/middleware/api-token.middleware.js +329 -0
- package/dist/cli/backend/src/middleware/api-token.middleware.js.map +1 -0
- package/dist/cli/backend/src/middleware/caller-identity.middleware.d.ts +290 -0
- package/dist/cli/backend/src/middleware/caller-identity.middleware.d.ts.map +1 -0
- package/dist/cli/backend/src/middleware/caller-identity.middleware.js +658 -0
- package/dist/cli/backend/src/middleware/caller-identity.middleware.js.map +1 -0
- package/dist/cli/backend/src/middleware/require-auth.middleware.d.ts +60 -0
- package/dist/cli/backend/src/middleware/require-auth.middleware.d.ts.map +1 -0
- package/dist/cli/backend/src/middleware/require-auth.middleware.js +127 -0
- package/dist/cli/backend/src/middleware/require-auth.middleware.js.map +1 -0
- package/dist/cli/backend/src/services/activity/activity-log.service.d.ts +192 -0
- package/dist/cli/backend/src/services/activity/activity-log.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/activity/activity-log.service.js +343 -0
- package/dist/cli/backend/src/services/activity/activity-log.service.js.map +1 -0
- package/dist/cli/backend/src/services/core/peer-process.service.d.ts +168 -0
- package/dist/cli/backend/src/services/core/peer-process.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/core/peer-process.service.js +352 -0
- package/dist/cli/backend/src/services/core/peer-process.service.js.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts +13 -0
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision.service.js +39 -0
- package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +8 -0
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +24 -5
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system.routes.js","sourceRoot":"","sources":["../../../../../../backend/src/routes/modules/system.routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,cAAc,MAAM,+CAA+C,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,MAAM,uDAAuD,CAAC;AACpG,OAAO,EAAE,uBAAuB,EAAE,MAAM,4DAA4D,CAAC;AACrG,OAAO,EAAE,6BAA6B,EAAE,MAAM,yDAAyD,CAAC;AACxG,OAAO,EAAE,0BAA0B,EAAE,MAAM,sDAAsD,CAAC;AAClG,OAAO,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,oDAAoD,CAAC;
|
|
1
|
+
{"version":3,"file":"system.routes.js","sourceRoot":"","sources":["../../../../../../backend/src/routes/modules/system.routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { type ComponentLogger } from '../core/logger.service.js';
|
|
2
|
+
import { type CallerIdentity, type IdentifiableRequest } from '../../middleware/caller-identity.middleware.js';
|
|
3
|
+
/** Who acted. */
|
|
4
|
+
export type ActivityActorType = 'owner' | 'agent' | 'system';
|
|
5
|
+
/** The actor of an entry. */
|
|
6
|
+
export interface ActivityActor {
|
|
7
|
+
/** Owner, an agent, or Crewly itself (schedulers, deadlines, anonymous local calls) */
|
|
8
|
+
type: ActivityActorType;
|
|
9
|
+
/** The agent session, Slack user id, scheduler name, … when known */
|
|
10
|
+
id?: string;
|
|
11
|
+
/** How the actor was recognised (`owner-session`, `api-token`, `agent-badge`, `deadline`, …) */
|
|
12
|
+
via?: string;
|
|
13
|
+
}
|
|
14
|
+
/** What an entry is about. */
|
|
15
|
+
export interface ActivityTarget {
|
|
16
|
+
/** `team`, `member`, `decision`, … */
|
|
17
|
+
type: string;
|
|
18
|
+
id: string;
|
|
19
|
+
/** Display name at the time of the action */
|
|
20
|
+
name?: string;
|
|
21
|
+
}
|
|
22
|
+
/** One line of the log. */
|
|
23
|
+
export interface ActivityEntry {
|
|
24
|
+
id: string;
|
|
25
|
+
/** ISO timestamp */
|
|
26
|
+
ts: string;
|
|
27
|
+
actor: ActivityActor;
|
|
28
|
+
/** Dotted, past tense: `team.member.updated`, `decision.resolved` */
|
|
29
|
+
action: string;
|
|
30
|
+
target: ActivityTarget;
|
|
31
|
+
/** Changed fields before the action (masked, truncated) */
|
|
32
|
+
before?: Record<string, unknown>;
|
|
33
|
+
/** Changed fields after the action (masked, truncated) */
|
|
34
|
+
after?: Record<string, unknown>;
|
|
35
|
+
/** The Crewly Request this happened under, when known */
|
|
36
|
+
requestId?: string;
|
|
37
|
+
/** The WorkItem this happened under, when known */
|
|
38
|
+
workItemId?: string;
|
|
39
|
+
/** Short free text (an answer, a reason) */
|
|
40
|
+
note?: string;
|
|
41
|
+
}
|
|
42
|
+
/** What a writer hands in; id and timestamp are filled here. */
|
|
43
|
+
export type ActivityEntryInput = Omit<ActivityEntry, 'id' | 'ts'> & {
|
|
44
|
+
ts?: string;
|
|
45
|
+
};
|
|
46
|
+
/** Filters of a read. All optional; `action` and ids match exactly, `action` also by `prefix.` */
|
|
47
|
+
export interface ActivityQuery {
|
|
48
|
+
actorType?: ActivityActorType;
|
|
49
|
+
actorId?: string;
|
|
50
|
+
/** Exact action, or a dotted prefix such as `team.` */
|
|
51
|
+
action?: string;
|
|
52
|
+
targetType?: string;
|
|
53
|
+
targetId?: string;
|
|
54
|
+
/** ISO timestamp (inclusive) */
|
|
55
|
+
since?: string;
|
|
56
|
+
/** ISO timestamp (inclusive) */
|
|
57
|
+
until?: string;
|
|
58
|
+
limit?: number;
|
|
59
|
+
}
|
|
60
|
+
/** File operations the log uses (injectable to simulate failures). */
|
|
61
|
+
export interface ActivityFsOps {
|
|
62
|
+
mkdir(dir: string, opts: {
|
|
63
|
+
recursive: true;
|
|
64
|
+
}): Promise<unknown>;
|
|
65
|
+
appendFile(file: string, data: string): Promise<void>;
|
|
66
|
+
readFile(file: string): Promise<string>;
|
|
67
|
+
readdir(dir: string): Promise<string[]>;
|
|
68
|
+
}
|
|
69
|
+
/** Construction options. */
|
|
70
|
+
export interface ActivityLogOptions {
|
|
71
|
+
/** Log directory (default `<CREWLY_HOME>/activity-log`) */
|
|
72
|
+
dir?: string;
|
|
73
|
+
fs?: ActivityFsOps;
|
|
74
|
+
now?: () => Date;
|
|
75
|
+
logger?: ComponentLogger;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Whether a string names an actor type.
|
|
79
|
+
*
|
|
80
|
+
* @param value - Candidate
|
|
81
|
+
* @returns True for owner / agent / system
|
|
82
|
+
*/
|
|
83
|
+
export declare function isActivityActorType(value: unknown): value is ActivityActorType;
|
|
84
|
+
/**
|
|
85
|
+
* Mask secret-looking keys and cut long strings, recursively. Arrays and plain
|
|
86
|
+
* objects are walked; anything else is kept as is.
|
|
87
|
+
*
|
|
88
|
+
* @param value - Any JSON-ish value
|
|
89
|
+
* @returns The value safe to write
|
|
90
|
+
*/
|
|
91
|
+
export declare function maskForActivity(value: unknown): unknown;
|
|
92
|
+
/**
|
|
93
|
+
* The fields that differ between two shallow records, as a before / after
|
|
94
|
+
* pair (masked). Equal fields are left out so an entry shows only the change;
|
|
95
|
+
* a key absent on one side appears as `undefined` → left out of that side.
|
|
96
|
+
*
|
|
97
|
+
* @param before - Record before the change (null when created)
|
|
98
|
+
* @param after - Record after the change (null when deleted)
|
|
99
|
+
* @returns Masked before / after summaries, each undefined when empty
|
|
100
|
+
*/
|
|
101
|
+
export declare function summarizeChange(before: Record<string, unknown> | null | undefined, after: Record<string, unknown> | null | undefined): {
|
|
102
|
+
before?: Record<string, unknown>;
|
|
103
|
+
after?: Record<string, unknown>;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* The actor behind a caller identity: owner credentials (dashboard session,
|
|
107
|
+
* API token, phone / portal relay, cloud) are the owner; an agent is itself;
|
|
108
|
+
* schedulers and anonymous local calls are the system.
|
|
109
|
+
*
|
|
110
|
+
* @param identity - What the caller-identity middleware decided
|
|
111
|
+
* @returns The actor
|
|
112
|
+
*/
|
|
113
|
+
export declare function actorFromCaller(identity: CallerIdentity): ActivityActor;
|
|
114
|
+
/**
|
|
115
|
+
* The actor of an HTTP request.
|
|
116
|
+
*
|
|
117
|
+
* @param req - Request
|
|
118
|
+
* @returns The actor
|
|
119
|
+
*/
|
|
120
|
+
export declare function actorFromRequest(req: IdentifiableRequest): ActivityActor;
|
|
121
|
+
/**
|
|
122
|
+
* The append-only activity log.
|
|
123
|
+
*/
|
|
124
|
+
export declare class ActivityLogService {
|
|
125
|
+
private readonly dir;
|
|
126
|
+
private readonly fs;
|
|
127
|
+
private readonly now;
|
|
128
|
+
private readonly logger;
|
|
129
|
+
private chain;
|
|
130
|
+
private dirReady;
|
|
131
|
+
private seq;
|
|
132
|
+
/**
|
|
133
|
+
* @param options - Directory, file ops, clock, logger (all optional)
|
|
134
|
+
*/
|
|
135
|
+
constructor(options?: ActivityLogOptions);
|
|
136
|
+
/**
|
|
137
|
+
* Append one entry. Returns at once; the write is chained after earlier
|
|
138
|
+
* writes and a failure is logged, never thrown.
|
|
139
|
+
*
|
|
140
|
+
* @param input - The entry without id / timestamp
|
|
141
|
+
* @returns The entry as it will be written
|
|
142
|
+
*/
|
|
143
|
+
record(input: ActivityEntryInput): ActivityEntry;
|
|
144
|
+
/**
|
|
145
|
+
* Wait for every write handed in so far.
|
|
146
|
+
*
|
|
147
|
+
* @returns When the chain is idle
|
|
148
|
+
*/
|
|
149
|
+
flush(): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* Read entries newest first.
|
|
152
|
+
*
|
|
153
|
+
* @param query - Filters and limit
|
|
154
|
+
* @returns Matching entries, newest first, at most `limit`
|
|
155
|
+
*/
|
|
156
|
+
list(query?: ActivityQuery): Promise<ActivityEntry[]>;
|
|
157
|
+
/**
|
|
158
|
+
* The monthly files worth opening for a query, newest first, bounded by
|
|
159
|
+
* MAX_FILES_PER_READ and by the query's time window.
|
|
160
|
+
*
|
|
161
|
+
* @param query - Filters (since / until narrow the months)
|
|
162
|
+
* @returns File names
|
|
163
|
+
*/
|
|
164
|
+
private monthlyFiles;
|
|
165
|
+
/**
|
|
166
|
+
* The file an entry at a timestamp belongs to.
|
|
167
|
+
*
|
|
168
|
+
* @param ts - ISO timestamp
|
|
169
|
+
* @returns Absolute path
|
|
170
|
+
*/
|
|
171
|
+
private fileFor;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* The process-wide activity log.
|
|
175
|
+
*
|
|
176
|
+
* @returns The log (created on first use)
|
|
177
|
+
*/
|
|
178
|
+
export declare function getActivityLog(): ActivityLogService;
|
|
179
|
+
/**
|
|
180
|
+
* Replace the process-wide log (tests).
|
|
181
|
+
*
|
|
182
|
+
* @param log - Log, or null to rebuild the default lazily
|
|
183
|
+
*/
|
|
184
|
+
export declare function setActivityLogForTesting(log: ActivityLogService | null): void;
|
|
185
|
+
/**
|
|
186
|
+
* Append to the process-wide log without ever throwing. The one call writers
|
|
187
|
+
* make.
|
|
188
|
+
*
|
|
189
|
+
* @param input - The entry
|
|
190
|
+
*/
|
|
191
|
+
export declare function recordActivity(input: ActivityEntryInput): void;
|
|
192
|
+
//# sourceMappingURL=activity-log.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-log.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/activity/activity-log.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity log (crewly#881): the append-only record of who did what and when.
|
|
3
|
+
*
|
|
4
|
+
* - One `<CREWLY_HOME>/activity-log/YYYY-MM.jsonl` file per month, one JSON
|
|
5
|
+
* entry per line. Nothing is ever rewritten or deleted here.
|
|
6
|
+
* - Each entry names the actor (owner / agent / system, with its id and how it
|
|
7
|
+
* was recognised), the action (`team.member.updated`, `decision.resolved`,
|
|
8
|
+
* …), the target, and a before / after summary of the changed fields with
|
|
9
|
+
* secret-looking keys masked and long strings cut.
|
|
10
|
+
* - Writes are chained on one promise and never awaited by callers; a failed
|
|
11
|
+
* write is logged, never thrown. Reads walk the monthly files newest first
|
|
12
|
+
* and stop once the limit is reached.
|
|
13
|
+
*
|
|
14
|
+
* Writers: team / member config handlers (`team.controller.ts`) and owner
|
|
15
|
+
* decisions (`decision.service.ts`). Reader: `GET /api/activity`.
|
|
16
|
+
*
|
|
17
|
+
* `specs/2026-10-25-activity-log.md`
|
|
18
|
+
*
|
|
19
|
+
* @module services/activity/activity-log.service
|
|
20
|
+
*/
|
|
21
|
+
import { promises as fsp } from 'fs';
|
|
22
|
+
import * as path from 'path';
|
|
23
|
+
import { ACTIVITY_LOG_CONSTANTS } from '../../constants.js';
|
|
24
|
+
import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
|
|
25
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
26
|
+
import { getCallerIdentity } from '../../middleware/caller-identity.middleware.js';
|
|
27
|
+
const NODE_FS = {
|
|
28
|
+
mkdir: (dir, opts) => fsp.mkdir(dir, opts),
|
|
29
|
+
appendFile: (file, data) => fsp.appendFile(file, data, 'utf8'),
|
|
30
|
+
readFile: (file) => fsp.readFile(file, 'utf8'),
|
|
31
|
+
readdir: (dir) => fsp.readdir(dir),
|
|
32
|
+
};
|
|
33
|
+
const ACTOR_TYPES = new Set(['owner', 'agent', 'system']);
|
|
34
|
+
/**
|
|
35
|
+
* Whether a string names an actor type.
|
|
36
|
+
*
|
|
37
|
+
* @param value - Candidate
|
|
38
|
+
* @returns True for owner / agent / system
|
|
39
|
+
*/
|
|
40
|
+
export function isActivityActorType(value) {
|
|
41
|
+
return typeof value === 'string' && ACTOR_TYPES.has(value);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Mask secret-looking keys and cut long strings, recursively. Arrays and plain
|
|
45
|
+
* objects are walked; anything else is kept as is.
|
|
46
|
+
*
|
|
47
|
+
* @param value - Any JSON-ish value
|
|
48
|
+
* @returns The value safe to write
|
|
49
|
+
*/
|
|
50
|
+
export function maskForActivity(value) {
|
|
51
|
+
if (typeof value === 'string') {
|
|
52
|
+
return value.length > ACTIVITY_LOG_CONSTANTS.MAX_SUMMARY_CHARS ? `${value.slice(0, ACTIVITY_LOG_CONSTANTS.MAX_SUMMARY_CHARS)}…` : value;
|
|
53
|
+
}
|
|
54
|
+
if (Array.isArray(value))
|
|
55
|
+
return value.map(maskForActivity);
|
|
56
|
+
if (value && typeof value === 'object') {
|
|
57
|
+
const out = {};
|
|
58
|
+
for (const [k, v] of Object.entries(value)) {
|
|
59
|
+
out[k] = ACTIVITY_LOG_CONSTANTS.SECRET_KEY_PATTERN.test(k) && v !== undefined && v !== null ? ACTIVITY_LOG_CONSTANTS.MASK : maskForActivity(v);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The fields that differ between two shallow records, as a before / after
|
|
67
|
+
* pair (masked). Equal fields are left out so an entry shows only the change;
|
|
68
|
+
* a key absent on one side appears as `undefined` → left out of that side.
|
|
69
|
+
*
|
|
70
|
+
* @param before - Record before the change (null when created)
|
|
71
|
+
* @param after - Record after the change (null when deleted)
|
|
72
|
+
* @returns Masked before / after summaries, each undefined when empty
|
|
73
|
+
*/
|
|
74
|
+
export function summarizeChange(before, after) {
|
|
75
|
+
const b = {};
|
|
76
|
+
const a = {};
|
|
77
|
+
const keys = new Set([...Object.keys(before ?? {}), ...Object.keys(after ?? {})]);
|
|
78
|
+
for (const k of keys) {
|
|
79
|
+
const bv = before?.[k];
|
|
80
|
+
const av = after?.[k];
|
|
81
|
+
if (JSON.stringify(bv) === JSON.stringify(av))
|
|
82
|
+
continue;
|
|
83
|
+
if (bv !== undefined)
|
|
84
|
+
b[k] = bv;
|
|
85
|
+
if (av !== undefined)
|
|
86
|
+
a[k] = av;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
...(Object.keys(b).length ? { before: maskForActivity(b) } : {}),
|
|
90
|
+
...(Object.keys(a).length ? { after: maskForActivity(a) } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The actor behind a caller identity: owner credentials (dashboard session,
|
|
95
|
+
* API token, phone / portal relay, cloud) are the owner; an agent is itself;
|
|
96
|
+
* schedulers and anonymous local calls are the system.
|
|
97
|
+
*
|
|
98
|
+
* @param identity - What the caller-identity middleware decided
|
|
99
|
+
* @returns The actor
|
|
100
|
+
*/
|
|
101
|
+
export function actorFromCaller(identity) {
|
|
102
|
+
switch (identity.kind) {
|
|
103
|
+
case 'owner':
|
|
104
|
+
case 'relay-owner':
|
|
105
|
+
case 'cloud':
|
|
106
|
+
return { type: 'owner', via: identity.via };
|
|
107
|
+
case 'agent':
|
|
108
|
+
return { type: 'agent', ...(identity.session ? { id: identity.session } : {}), via: identity.via };
|
|
109
|
+
case 'scheduler':
|
|
110
|
+
return { type: 'system', id: identity.sender ?? 'scheduler', via: identity.via };
|
|
111
|
+
default:
|
|
112
|
+
return { type: 'system', id: 'anonymous', via: identity.via };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The actor of an HTTP request.
|
|
117
|
+
*
|
|
118
|
+
* @param req - Request
|
|
119
|
+
* @returns The actor
|
|
120
|
+
*/
|
|
121
|
+
export function actorFromRequest(req) {
|
|
122
|
+
return actorFromCaller(getCallerIdentity(req));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The append-only activity log.
|
|
126
|
+
*/
|
|
127
|
+
export class ActivityLogService {
|
|
128
|
+
dir;
|
|
129
|
+
fs;
|
|
130
|
+
now;
|
|
131
|
+
logger;
|
|
132
|
+
chain = Promise.resolve();
|
|
133
|
+
dirReady = false;
|
|
134
|
+
seq = 0;
|
|
135
|
+
/**
|
|
136
|
+
* @param options - Directory, file ops, clock, logger (all optional)
|
|
137
|
+
*/
|
|
138
|
+
constructor(options = {}) {
|
|
139
|
+
this.dir = options.dir ?? path.join(getCrewlyHomePath(), ACTIVITY_LOG_CONSTANTS.DIR);
|
|
140
|
+
this.fs = options.fs ?? NODE_FS;
|
|
141
|
+
this.now = options.now ?? (() => new Date());
|
|
142
|
+
this.logger = options.logger ?? LoggerService.getInstance().createComponentLogger('ActivityLog');
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Append one entry. Returns at once; the write is chained after earlier
|
|
146
|
+
* writes and a failure is logged, never thrown.
|
|
147
|
+
*
|
|
148
|
+
* @param input - The entry without id / timestamp
|
|
149
|
+
* @returns The entry as it will be written
|
|
150
|
+
*/
|
|
151
|
+
record(input) {
|
|
152
|
+
const ts = input.ts ?? this.now().toISOString();
|
|
153
|
+
const entry = {
|
|
154
|
+
id: `${Date.parse(ts).toString(36)}-${(this.seq++).toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
|
|
155
|
+
ts,
|
|
156
|
+
actor: input.actor,
|
|
157
|
+
action: input.action,
|
|
158
|
+
target: input.target,
|
|
159
|
+
...(input.before ? { before: maskForActivity(input.before) } : {}),
|
|
160
|
+
...(input.after ? { after: maskForActivity(input.after) } : {}),
|
|
161
|
+
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
162
|
+
...(input.workItemId ? { workItemId: input.workItemId } : {}),
|
|
163
|
+
...(input.note ? { note: maskForActivity(input.note) } : {}),
|
|
164
|
+
};
|
|
165
|
+
const file = this.fileFor(ts);
|
|
166
|
+
this.chain = this.chain
|
|
167
|
+
.then(async () => {
|
|
168
|
+
if (!this.dirReady) {
|
|
169
|
+
await this.fs.mkdir(this.dir, { recursive: true });
|
|
170
|
+
this.dirReady = true;
|
|
171
|
+
}
|
|
172
|
+
await this.fs.appendFile(file, `${JSON.stringify(entry)}\n`);
|
|
173
|
+
})
|
|
174
|
+
.catch((err) => {
|
|
175
|
+
this.dirReady = false;
|
|
176
|
+
this.logger.warn('Activity log write failed', { action: entry.action, error: err instanceof Error ? err.message : String(err) });
|
|
177
|
+
});
|
|
178
|
+
return entry;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Wait for every write handed in so far.
|
|
182
|
+
*
|
|
183
|
+
* @returns When the chain is idle
|
|
184
|
+
*/
|
|
185
|
+
flush() {
|
|
186
|
+
return this.chain;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Read entries newest first.
|
|
190
|
+
*
|
|
191
|
+
* @param query - Filters and limit
|
|
192
|
+
* @returns Matching entries, newest first, at most `limit`
|
|
193
|
+
*/
|
|
194
|
+
async list(query = {}) {
|
|
195
|
+
await this.flush();
|
|
196
|
+
const limit = Math.max(1, Math.min(ACTIVITY_LOG_CONSTANTS.MAX_LIMIT, Math.floor(query.limit ?? ACTIVITY_LOG_CONSTANTS.DEFAULT_LIMIT)));
|
|
197
|
+
const files = await this.monthlyFiles(query);
|
|
198
|
+
const out = [];
|
|
199
|
+
for (const file of files) {
|
|
200
|
+
let raw;
|
|
201
|
+
try {
|
|
202
|
+
raw = await this.fs.readFile(path.join(this.dir, file));
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const lines = raw.split('\n');
|
|
208
|
+
for (let i = lines.length - 1; i >= 0 && out.length < limit; i--) {
|
|
209
|
+
const entry = parseLine(lines[i]);
|
|
210
|
+
if (entry && matches(entry, query))
|
|
211
|
+
out.push(entry);
|
|
212
|
+
}
|
|
213
|
+
if (out.length >= limit)
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
return out;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* The monthly files worth opening for a query, newest first, bounded by
|
|
220
|
+
* MAX_FILES_PER_READ and by the query's time window.
|
|
221
|
+
*
|
|
222
|
+
* @param query - Filters (since / until narrow the months)
|
|
223
|
+
* @returns File names
|
|
224
|
+
*/
|
|
225
|
+
async monthlyFiles(query) {
|
|
226
|
+
let names;
|
|
227
|
+
try {
|
|
228
|
+
names = await this.fs.readdir(this.dir);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
const sinceMonth = query.since ? monthOf(query.since) : null;
|
|
234
|
+
const untilMonth = query.until ? monthOf(query.until) : null;
|
|
235
|
+
return names
|
|
236
|
+
.filter((n) => n.endsWith(ACTIVITY_LOG_CONSTANTS.FILE_EXT))
|
|
237
|
+
.map((n) => n.slice(0, -ACTIVITY_LOG_CONSTANTS.FILE_EXT.length))
|
|
238
|
+
.filter((m) => /^\d{4}-\d{2}$/.test(m))
|
|
239
|
+
.filter((m) => (!sinceMonth || m >= sinceMonth) && (!untilMonth || m <= untilMonth))
|
|
240
|
+
.sort()
|
|
241
|
+
.reverse()
|
|
242
|
+
.slice(0, ACTIVITY_LOG_CONSTANTS.MAX_FILES_PER_READ)
|
|
243
|
+
.map((m) => `${m}${ACTIVITY_LOG_CONSTANTS.FILE_EXT}`);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The file an entry at a timestamp belongs to.
|
|
247
|
+
*
|
|
248
|
+
* @param ts - ISO timestamp
|
|
249
|
+
* @returns Absolute path
|
|
250
|
+
*/
|
|
251
|
+
fileFor(ts) {
|
|
252
|
+
return path.join(this.dir, `${monthOf(ts) ?? 'unknown'}${ACTIVITY_LOG_CONSTANTS.FILE_EXT}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* `YYYY-MM` of an ISO timestamp (UTC), or null when unparsable.
|
|
257
|
+
*
|
|
258
|
+
* @param ts - ISO timestamp
|
|
259
|
+
* @returns The month key
|
|
260
|
+
*/
|
|
261
|
+
function monthOf(ts) {
|
|
262
|
+
const ms = Date.parse(ts);
|
|
263
|
+
if (Number.isNaN(ms))
|
|
264
|
+
return null;
|
|
265
|
+
return new Date(ms).toISOString().slice(0, 7);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Parse one log line; a blank or damaged line is skipped.
|
|
269
|
+
*
|
|
270
|
+
* @param line - Raw line
|
|
271
|
+
* @returns The entry or null
|
|
272
|
+
*/
|
|
273
|
+
function parseLine(line) {
|
|
274
|
+
if (!line.trim())
|
|
275
|
+
return null;
|
|
276
|
+
try {
|
|
277
|
+
const v = JSON.parse(line);
|
|
278
|
+
return typeof v.id === 'string' && typeof v.ts === 'string' && typeof v.action === 'string' && v.actor && v.target ? v : null;
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Whether an entry passes a query's filters. Times compare as instants, so
|
|
286
|
+
* `…T00:00:00Z` and `…T00:00:00.000Z` are the same moment.
|
|
287
|
+
*
|
|
288
|
+
* @param e - Entry
|
|
289
|
+
* @param q - Query
|
|
290
|
+
* @returns True when it matches
|
|
291
|
+
*/
|
|
292
|
+
function matches(e, q) {
|
|
293
|
+
if (q.actorType && e.actor.type !== q.actorType)
|
|
294
|
+
return false;
|
|
295
|
+
if (q.actorId && e.actor.id !== q.actorId)
|
|
296
|
+
return false;
|
|
297
|
+
if (q.action && e.action !== q.action && !(q.action.endsWith('.') && e.action.startsWith(q.action)))
|
|
298
|
+
return false;
|
|
299
|
+
if (q.targetType && e.target.type !== q.targetType)
|
|
300
|
+
return false;
|
|
301
|
+
if (q.targetId && e.target.id !== q.targetId)
|
|
302
|
+
return false;
|
|
303
|
+
const ms = Date.parse(e.ts);
|
|
304
|
+
if (q.since && ms < Date.parse(q.since))
|
|
305
|
+
return false;
|
|
306
|
+
if (q.until && ms > Date.parse(q.until))
|
|
307
|
+
return false;
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
let instance = null;
|
|
311
|
+
/**
|
|
312
|
+
* The process-wide activity log.
|
|
313
|
+
*
|
|
314
|
+
* @returns The log (created on first use)
|
|
315
|
+
*/
|
|
316
|
+
export function getActivityLog() {
|
|
317
|
+
if (!instance)
|
|
318
|
+
instance = new ActivityLogService();
|
|
319
|
+
return instance;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Replace the process-wide log (tests).
|
|
323
|
+
*
|
|
324
|
+
* @param log - Log, or null to rebuild the default lazily
|
|
325
|
+
*/
|
|
326
|
+
export function setActivityLogForTesting(log) {
|
|
327
|
+
instance = log;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Append to the process-wide log without ever throwing. The one call writers
|
|
331
|
+
* make.
|
|
332
|
+
*
|
|
333
|
+
* @param input - The entry
|
|
334
|
+
*/
|
|
335
|
+
export function recordActivity(input) {
|
|
336
|
+
try {
|
|
337
|
+
getActivityLog().record(input);
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
// A broken log never breaks the action it describes.
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=activity-log.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-log.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/activity/activity-log.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-heartbeat-monitor.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/agent-heartbeat-monitor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAQ5D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-heartbeat-monitor.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/agent-heartbeat-monitor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAQ5D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAoB/E;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,qBAAqB,EAAE,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,0BAA0B;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,2EAA2E;IAC3E,kBAAkB,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,4BAA4B;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA6C;IACpE,OAAO,CAAC,MAAM,CAAkB;IAEhC,4BAA4B;IAC5B,OAAO,CAAC,UAAU,CAA+C;IAEjE,8BAA8B;IAC9B,OAAO,CAAC,SAAS,CAAuB;IAExC,iCAAiC;IACjC,OAAO,CAAC,WAAW,CAA6C;IAEhE,kDAAkD;IAClD,OAAO,CAAC,cAAc,CAAgC;IACtD,OAAO,CAAC,wBAAwB,CAAyC;IACzE,OAAO,CAAC,cAAc,CAA+B;IAErD,OAAO;IAIP;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,4BAA4B;IAOlD;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAO5B;;;;;;OAMG;IACH,eAAe,CACd,cAAc,EAAE,eAAe,EAC/B,wBAAwB,EAAE,wBAAwB,EAClD,cAAc,EAAE,cAAc,GAC5B,IAAI;IAMP;;;OAGG;IACH,KAAK,IAAI,IAAI;IAyBb;;OAEG;IACH,IAAI,IAAI,IAAI;IAUZ;;;;OAIG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;OAIG;IACH,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAIhD;;;;;OAKG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAS1C;;;;;;;;;;;OAWG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA6NnC;;;;;;;;;OASG;IACH;;;;;;OAMG;YACW,sBAAsB;YAWtB,gBAAgB;IAiB9B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;;;;;;;;;;;;;OAcG;YACW,mBAAmB;IA0HjC;;;;;;;;OAQG;YACW,cAAc;CA6E5B"}
|
|
@@ -38,6 +38,7 @@ import { getTerminalGateway } from '../../websocket/terminal.gateway.js';
|
|
|
38
38
|
import { isUnderMemoryPressure, getMemoryStats } from '../core/system-health.util.js';
|
|
39
39
|
import { isInProcessRuntimeActive } from './crewly-agent/in-process-runtime-registry.js';
|
|
40
40
|
import { isPlannedRelaunch } from './planned-relaunch.registry.js';
|
|
41
|
+
import { getRestoreQueue } from './restore-queue.js';
|
|
41
42
|
import { createSessionCommandHelper } from '../session/session-command-helper.js';
|
|
42
43
|
/**
|
|
43
44
|
* Number of consecutive dead-process checks before triggering a restart.
|
|
@@ -232,6 +233,12 @@ export class AgentHeartbeatMonitorService {
|
|
|
232
233
|
}
|
|
233
234
|
continue;
|
|
234
235
|
}
|
|
236
|
+
// Still in the boot restore queue (one launch every 15 s, so the
|
|
237
|
+
// last of five starts well after the startup grace period): its
|
|
238
|
+
// session does not exist yet by design — not a ghost (2026-10-25).
|
|
239
|
+
if (getRestoreQueue().isRestoring(member.sessionName)) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
235
242
|
if (!this.sessionBackend.sessionExists(member.sessionName)) {
|
|
236
243
|
this.agentStates.delete(member.sessionName);
|
|
237
244
|
// The teams were read before this loop. A deliberate stop (idle
|