crewly 1.20.187 → 1.20.188
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/skills/agent/core/project-tickets/SKILL.md +3 -2
- package/config/skills/agent/core/project-tickets/execute.sh +4 -4
- package/config/skills/agent/core/project-tickets/execute.test.sh +2 -2
- package/dist/backend/backend/src/constants.d.ts +70 -12
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +70 -12
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js +5 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.d.ts +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.js +1 -1
- package/dist/backend/backend/src/controllers/system/usage.controller.d.ts +46 -0
- package/dist/backend/backend/src/controllers/system/usage.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/system/usage.controller.js +181 -0
- package/dist/backend/backend/src/controllers/system/usage.controller.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts +7 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +59 -4
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/system.routes.js +3 -3
- package/dist/backend/backend/src/routes/modules/system.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +7 -7
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.d.ts +4 -2
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js +6 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js +2 -2
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +4 -2
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.d.ts +130 -0
- package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.js +274 -0
- package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.js.map +1 -0
- package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.d.ts +152 -0
- package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.js +311 -0
- package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.js.map +1 -0
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts +53 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js +51 -3
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts +4 -4
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.d.ts +4 -3
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.js +7 -4
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts +40 -9
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +68 -20
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap-command.d.ts +48 -18
- package/dist/backend/backend/src/services/spend/spend-cap-command.d.ts.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap-command.js +195 -62
- package/dist/backend/backend/src/services/spend/spend-cap-command.js.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap.gate.d.ts +11 -15
- package/dist/backend/backend/src/services/spend/spend-cap.gate.d.ts.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap.gate.js +8 -13
- package/dist/backend/backend/src/services/spend/spend-cap.gate.js.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap.service.d.ts +179 -64
- package/dist/backend/backend/src/services/spend/spend-cap.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap.service.js +406 -149
- package/dist/backend/backend/src/services/spend/spend-cap.service.js.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap.store.d.ts +52 -11
- package/dist/backend/backend/src/services/spend/spend-cap.store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap.store.js +67 -21
- package/dist/backend/backend/src/services/spend/spend-cap.store.js.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap.wiring.d.ts +3 -1
- package/dist/backend/backend/src/services/spend/spend-cap.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap.wiring.js +21 -7
- package/dist/backend/backend/src/services/spend/spend-cap.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-ledger.service.d.ts +57 -36
- package/dist/backend/backend/src/services/spend/spend-ledger.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-ledger.service.js +80 -55
- package/dist/backend/backend/src/services/spend/spend-ledger.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/work-item-usage.d.ts +10 -1
- package/dist/backend/backend/src/services/task-pool/work-item-usage.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/work-item-usage.js +2 -0
- package/dist/backend/backend/src/services/task-pool/work-item-usage.js.map +1 -1
- package/dist/backend/backend/src/services/usage/token-format.d.ts +49 -0
- package/dist/backend/backend/src/services/usage/token-format.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage/token-format.js +81 -0
- package/dist/backend/backend/src/services/usage/token-format.js.map +1 -0
- package/dist/backend/backend/src/services/usage/usage-stats.service.d.ts +132 -0
- package/dist/backend/backend/src/services/usage/usage-stats.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/usage/usage-stats.service.js +226 -0
- package/dist/backend/backend/src/services/usage/usage-stats.service.js.map +1 -0
- package/dist/backend/backend/src/types/decision.types.d.ts +2 -2
- package/dist/backend/backend/src/types/ticket-autopilot.types.d.ts +24 -7
- package/dist/backend/backend/src/types/ticket-autopilot.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/ticket-autopilot.types.js +29 -13
- package/dist/backend/backend/src/types/ticket-autopilot.types.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +70 -12
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +70 -12
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +7 -7
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.d.ts +4 -2
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js +6 -1
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js +2 -2
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.js +4 -2
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts +53 -1
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js +51 -3
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js.map +1 -1
- package/dist/cli/backend/src/services/spend/spend-cap.gate.d.ts +11 -15
- package/dist/cli/backend/src/services/spend/spend-cap.gate.d.ts.map +1 -1
- package/dist/cli/backend/src/services/spend/spend-cap.gate.js +8 -13
- package/dist/cli/backend/src/services/spend/spend-cap.gate.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/work-item-usage.d.ts +10 -1
- package/dist/cli/backend/src/services/task-pool/work-item-usage.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/work-item-usage.js +2 -0
- package/dist/cli/backend/src/services/task-pool/work-item-usage.js.map +1 -1
- package/dist/cli/backend/src/services/usage/token-format.d.ts +49 -0
- package/dist/cli/backend/src/services/usage/token-format.d.ts.map +1 -0
- package/dist/cli/backend/src/services/usage/token-format.js +81 -0
- package/dist/cli/backend/src/services/usage/token-format.js.map +1 -0
- package/dist/cli/backend/src/types/decision.types.d.ts +2 -2
- package/dist/cli/backend/src/types/ticket-autopilot.types.d.ts +24 -7
- package/dist/cli/backend/src/types/ticket-autopilot.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/ticket-autopilot.types.js +29 -13
- package/dist/cli/backend/src/types/ticket-autopilot.types.js.map +1 -1
- package/frontend/dist/assets/{index-15c2faf2.js → index-49f50b45.js} +276 -276
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
- package/dist/backend/backend/src/controllers/system/spend.controller.d.ts +0 -32
- package/dist/backend/backend/src/controllers/system/spend.controller.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/system/spend.controller.js +0 -100
- package/dist/backend/backend/src/controllers/system/spend.controller.js.map +0 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage stats — tokens grouped by agent, team, project, work item, runtime
|
|
3
|
+
* or day, over the last N local days (`GET /api/system/usage`).
|
|
4
|
+
*
|
|
5
|
+
* The unit is the token unit ({@link eventTokens}: input incl. cached +
|
|
6
|
+
* output); cached input is reported beside it. Every event lands in exactly
|
|
7
|
+
* one row of a grouping (unattributable usage gets its own row), so each
|
|
8
|
+
* grouping sums to the same total — except `workItem`, which lists the top
|
|
9
|
+
* work items only.
|
|
10
|
+
*
|
|
11
|
+
* Attribution:
|
|
12
|
+
* - team: the session's team membership (the orc and unknown sessions are
|
|
13
|
+
* "(unattributed)");
|
|
14
|
+
* - work item: {@link computeWorkItemUsage} — the agent's usage between the
|
|
15
|
+
* item's start and completion (clipped to the window);
|
|
16
|
+
* - project: the work item running when the event happened, if it names a
|
|
17
|
+
* project (`metadata.projectId`) or its agent's team works on exactly one
|
|
18
|
+
* project; otherwise the session's team when it works on exactly one
|
|
19
|
+
* project; otherwise "(unattributed)".
|
|
20
|
+
*
|
|
21
|
+
* specs/2026-10-02-spend-cap.md §Stats
|
|
22
|
+
*
|
|
23
|
+
* @module services/usage/usage-stats.service
|
|
24
|
+
*/
|
|
25
|
+
import { type TokenUsageEvent } from '../monitoring/token-usage.service.js';
|
|
26
|
+
import { type SessionUsageWindowSource } from '../task-pool/work-item-usage.js';
|
|
27
|
+
/** A grouping. */
|
|
28
|
+
export type UsageGroupBy = 'agent' | 'team' | 'project' | 'workItem' | 'runtime' | 'day';
|
|
29
|
+
/** Token figures. */
|
|
30
|
+
export interface UsageTokens {
|
|
31
|
+
/** Input tokens, cached included */
|
|
32
|
+
input: number;
|
|
33
|
+
/** Of `input`, the cached part */
|
|
34
|
+
cachedInput: number;
|
|
35
|
+
output: number;
|
|
36
|
+
/** input + output — the unit caps count */
|
|
37
|
+
total: number;
|
|
38
|
+
/** Usage events (model calls / turns) */
|
|
39
|
+
events: number;
|
|
40
|
+
}
|
|
41
|
+
/** One row of a grouping. */
|
|
42
|
+
export interface UsageRow extends UsageTokens {
|
|
43
|
+
/** Session / team id / project id / work item id / runtime / `YYYY-MM-DD` */
|
|
44
|
+
key: string;
|
|
45
|
+
label: string;
|
|
46
|
+
/** Share of the window total (0–1) */
|
|
47
|
+
share: number;
|
|
48
|
+
/** Dashboard link (work items) */
|
|
49
|
+
link?: string;
|
|
50
|
+
/** Extra facts: `team` / `agent` / `status` / `runtimes` */
|
|
51
|
+
meta?: Record<string, string | string[]>;
|
|
52
|
+
}
|
|
53
|
+
/** What `GET /api/system/usage` returns. */
|
|
54
|
+
export interface UsageStats {
|
|
55
|
+
days: number;
|
|
56
|
+
/** Window start (local midnight), ISO */
|
|
57
|
+
since: string;
|
|
58
|
+
/** Local day of now */
|
|
59
|
+
today: string;
|
|
60
|
+
totals: UsageTokens;
|
|
61
|
+
todayTotals: UsageTokens;
|
|
62
|
+
groupBy: UsageGroupBy[];
|
|
63
|
+
/** Rows of the first grouping */
|
|
64
|
+
rows: UsageRow[];
|
|
65
|
+
/** Rows of every requested grouping */
|
|
66
|
+
groups: Partial<Record<UsageGroupBy, UsageRow[]>>;
|
|
67
|
+
}
|
|
68
|
+
/** A team as stats need it. */
|
|
69
|
+
export interface UsageTeam {
|
|
70
|
+
id: string;
|
|
71
|
+
name: string;
|
|
72
|
+
members: Array<{
|
|
73
|
+
session: string;
|
|
74
|
+
name: string;
|
|
75
|
+
}>;
|
|
76
|
+
projectIds: string[];
|
|
77
|
+
}
|
|
78
|
+
/** A work item as stats need it. */
|
|
79
|
+
export interface UsageWorkItem {
|
|
80
|
+
id: string;
|
|
81
|
+
title: string;
|
|
82
|
+
status: string;
|
|
83
|
+
/** Agent session that ran it */
|
|
84
|
+
target?: string;
|
|
85
|
+
createdAt: string;
|
|
86
|
+
startedAt?: string;
|
|
87
|
+
completedAt?: string;
|
|
88
|
+
metadata?: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
/** Collaborators. */
|
|
91
|
+
export interface UsageStatsDeps {
|
|
92
|
+
/** The token ledger (TokenUsageService) */
|
|
93
|
+
ledger: SessionUsageWindowSource & {
|
|
94
|
+
forEachEvent(visit: (sessionName: string, event: TokenUsageEvent) => void, since?: Date): void;
|
|
95
|
+
};
|
|
96
|
+
teams: () => Promise<UsageTeam[]>;
|
|
97
|
+
projects: () => Promise<Array<{
|
|
98
|
+
id: string;
|
|
99
|
+
name: string;
|
|
100
|
+
}>>;
|
|
101
|
+
workItems: () => Promise<UsageWorkItem[]>;
|
|
102
|
+
now?: () => Date;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Parse `groupBy` (one value or a comma list).
|
|
106
|
+
*
|
|
107
|
+
* @param raw - Query value
|
|
108
|
+
* @returns Valid groupings (default `agent`)
|
|
109
|
+
*/
|
|
110
|
+
export declare function parseGroupBy(raw: unknown): UsageGroupBy[];
|
|
111
|
+
/**
|
|
112
|
+
* Token usage stats.
|
|
113
|
+
*/
|
|
114
|
+
export declare class UsageStatsService {
|
|
115
|
+
private readonly deps;
|
|
116
|
+
private readonly now;
|
|
117
|
+
/** @param deps - Collaborators */
|
|
118
|
+
constructor(deps: UsageStatsDeps);
|
|
119
|
+
/**
|
|
120
|
+
* Aggregate the window.
|
|
121
|
+
*
|
|
122
|
+
* @param days - Local days, today included (clamped to 1…MAX_DAYS)
|
|
123
|
+
* @param groupBy - Groupings
|
|
124
|
+
* @returns Stats
|
|
125
|
+
*/
|
|
126
|
+
query(days: number, groupBy: UsageGroupBy[]): Promise<UsageStats>;
|
|
127
|
+
/**
|
|
128
|
+
* Top work items in the window by tokens.
|
|
129
|
+
*/
|
|
130
|
+
private workItemRows;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=usage-stats.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-stats.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/usage/usage-stats.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage stats — tokens grouped by agent, team, project, work item, runtime
|
|
3
|
+
* or day, over the last N local days (`GET /api/system/usage`).
|
|
4
|
+
*
|
|
5
|
+
* The unit is the token unit ({@link eventTokens}: input incl. cached +
|
|
6
|
+
* output); cached input is reported beside it. Every event lands in exactly
|
|
7
|
+
* one row of a grouping (unattributable usage gets its own row), so each
|
|
8
|
+
* grouping sums to the same total — except `workItem`, which lists the top
|
|
9
|
+
* work items only.
|
|
10
|
+
*
|
|
11
|
+
* Attribution:
|
|
12
|
+
* - team: the session's team membership (the orc and unknown sessions are
|
|
13
|
+
* "(unattributed)");
|
|
14
|
+
* - work item: {@link computeWorkItemUsage} — the agent's usage between the
|
|
15
|
+
* item's start and completion (clipped to the window);
|
|
16
|
+
* - project: the work item running when the event happened, if it names a
|
|
17
|
+
* project (`metadata.projectId`) or its agent's team works on exactly one
|
|
18
|
+
* project; otherwise the session's team when it works on exactly one
|
|
19
|
+
* project; otherwise "(unattributed)".
|
|
20
|
+
*
|
|
21
|
+
* specs/2026-10-02-spend-cap.md §Stats
|
|
22
|
+
*
|
|
23
|
+
* @module services/usage/usage-stats.service
|
|
24
|
+
*/
|
|
25
|
+
import { ORCHESTRATOR_SESSION_NAME, SPEND_CAP_CONSTANTS, USAGE_CONSTANTS as U } from '../../constants.js';
|
|
26
|
+
import { eventTokens } from '../monitoring/token-usage.service.js';
|
|
27
|
+
import { localDateKey } from '../project-tickets/ticket-autopilot-decision.js';
|
|
28
|
+
import { runtimeOfEvent, windowDays } from '../spend/spend-ledger.service.js';
|
|
29
|
+
import { computeWorkItemUsage } from '../task-pool/work-item-usage.js';
|
|
30
|
+
/** Zero figures. */
|
|
31
|
+
function zero() {
|
|
32
|
+
return { input: 0, cachedInput: 0, output: 0, total: 0, events: 0 };
|
|
33
|
+
}
|
|
34
|
+
/** Add one event's tokens. */
|
|
35
|
+
function add(into, e) {
|
|
36
|
+
const t = eventTokens(e);
|
|
37
|
+
into.input += t.input;
|
|
38
|
+
into.cachedInput += t.cachedInput;
|
|
39
|
+
into.output += t.output;
|
|
40
|
+
into.total += t.total;
|
|
41
|
+
into.events += 1;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse `groupBy` (one value or a comma list).
|
|
45
|
+
*
|
|
46
|
+
* @param raw - Query value
|
|
47
|
+
* @returns Valid groupings (default `agent`)
|
|
48
|
+
*/
|
|
49
|
+
export function parseGroupBy(raw) {
|
|
50
|
+
const parts = String(raw ?? '')
|
|
51
|
+
.split(',')
|
|
52
|
+
.map((s) => s.trim())
|
|
53
|
+
.filter((s) => U.GROUP_BY.includes(s));
|
|
54
|
+
return parts.length > 0 ? [...new Set(parts)] : ['agent'];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Token usage stats.
|
|
58
|
+
*/
|
|
59
|
+
export class UsageStatsService {
|
|
60
|
+
deps;
|
|
61
|
+
now;
|
|
62
|
+
/** @param deps - Collaborators */
|
|
63
|
+
constructor(deps) {
|
|
64
|
+
this.deps = deps;
|
|
65
|
+
this.now = deps.now ?? (() => new Date());
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Aggregate the window.
|
|
69
|
+
*
|
|
70
|
+
* @param days - Local days, today included (clamped to 1…MAX_DAYS)
|
|
71
|
+
* @param groupBy - Groupings
|
|
72
|
+
* @returns Stats
|
|
73
|
+
*/
|
|
74
|
+
async query(days, groupBy) {
|
|
75
|
+
const now = this.now();
|
|
76
|
+
const n = Math.min(SPEND_CAP_CONSTANTS.MAX_DAYS, Math.max(1, Math.floor(Number.isFinite(days) ? days : SPEND_CAP_CONSTANTS.DEFAULT_DAYS)));
|
|
77
|
+
const { since } = windowDays(now, n);
|
|
78
|
+
const today = localDateKey(now);
|
|
79
|
+
const [teams, projects, items] = await Promise.all([
|
|
80
|
+
this.deps.teams().catch(() => []),
|
|
81
|
+
this.deps.projects().catch(() => []),
|
|
82
|
+
groupBy.includes('workItem') || groupBy.includes('project') ? this.deps.workItems().catch(() => []) : Promise.resolve([]),
|
|
83
|
+
]);
|
|
84
|
+
const teamOf = new Map();
|
|
85
|
+
const nameOf = new Map([[ORCHESTRATOR_SESSION_NAME, 'Orc']]);
|
|
86
|
+
for (const t of teams) {
|
|
87
|
+
for (const m of t.members) {
|
|
88
|
+
if (!m.session)
|
|
89
|
+
continue;
|
|
90
|
+
if (!teamOf.has(m.session))
|
|
91
|
+
teamOf.set(m.session, t);
|
|
92
|
+
nameOf.set(m.session, m.name || m.session);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const projectName = new Map(projects.map((p) => [p.id, p.name]));
|
|
96
|
+
const teamProject = (t) => (t && t.projectIds.length === 1 ? t.projectIds[0] : null);
|
|
97
|
+
// Work item windows per session, for project attribution.
|
|
98
|
+
const windows = new Map();
|
|
99
|
+
for (const wi of items) {
|
|
100
|
+
if (!wi.target)
|
|
101
|
+
continue;
|
|
102
|
+
const pid = typeof wi.metadata?.projectId === 'string' ? wi.metadata.projectId : teamProject(teamOf.get(wi.target));
|
|
103
|
+
if (!pid)
|
|
104
|
+
continue;
|
|
105
|
+
const start = new Date(wi.startedAt ?? wi.createdAt).getTime();
|
|
106
|
+
const end = wi.completedAt ? new Date(wi.completedAt).getTime() : now.getTime();
|
|
107
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || end < start)
|
|
108
|
+
continue;
|
|
109
|
+
const list = windows.get(wi.target) ?? [];
|
|
110
|
+
list.push({ start, end, projectId: pid });
|
|
111
|
+
windows.set(wi.target, list);
|
|
112
|
+
}
|
|
113
|
+
for (const list of windows.values())
|
|
114
|
+
list.sort((a, b) => b.start - a.start);
|
|
115
|
+
const projectOfEvent = (session, ms) => {
|
|
116
|
+
const hit = windows.get(session)?.find((w) => w.start <= ms && ms <= w.end);
|
|
117
|
+
return hit?.projectId ?? teamProject(teamOf.get(session));
|
|
118
|
+
};
|
|
119
|
+
const totals = zero();
|
|
120
|
+
const todayTotals = zero();
|
|
121
|
+
const buckets = new Map();
|
|
122
|
+
const bucketOf = (g, key, label, meta) => {
|
|
123
|
+
let map = buckets.get(g);
|
|
124
|
+
if (!map) {
|
|
125
|
+
map = new Map();
|
|
126
|
+
buckets.set(g, map);
|
|
127
|
+
}
|
|
128
|
+
let row = map.get(key);
|
|
129
|
+
if (!row) {
|
|
130
|
+
row = { key, label, share: 0, ...zero(), ...(meta ? { meta } : {}) };
|
|
131
|
+
map.set(key, row);
|
|
132
|
+
}
|
|
133
|
+
return row;
|
|
134
|
+
};
|
|
135
|
+
const eventGroupings = groupBy.filter((g) => g !== 'workItem');
|
|
136
|
+
const runtimesOf = new Map();
|
|
137
|
+
this.deps.ledger.forEachEvent((session, e) => {
|
|
138
|
+
const ms = new Date(e.timestamp).getTime();
|
|
139
|
+
if (!Number.isFinite(ms) || ms > now.getTime())
|
|
140
|
+
return;
|
|
141
|
+
add(totals, e);
|
|
142
|
+
const day = localDateKey(new Date(ms));
|
|
143
|
+
if (day === today)
|
|
144
|
+
add(todayTotals, e);
|
|
145
|
+
const runtime = runtimeOfEvent(e);
|
|
146
|
+
runtimesOf.set(session, (runtimesOf.get(session) ?? new Set()).add(runtime));
|
|
147
|
+
for (const g of eventGroupings) {
|
|
148
|
+
let row;
|
|
149
|
+
if (g === 'agent') {
|
|
150
|
+
const team = teamOf.get(session);
|
|
151
|
+
row = bucketOf(g, session, nameOf.get(session) ?? session, team ? { team: team.name } : undefined);
|
|
152
|
+
}
|
|
153
|
+
else if (g === 'team') {
|
|
154
|
+
const team = teamOf.get(session);
|
|
155
|
+
row = team ? bucketOf(g, team.id, team.name) : bucketOf(g, U.UNATTRIBUTED, session === ORCHESTRATOR_SESSION_NAME ? 'Orc (no team)' : U.UNATTRIBUTED);
|
|
156
|
+
}
|
|
157
|
+
else if (g === 'runtime') {
|
|
158
|
+
row = bucketOf(g, runtime, runtime);
|
|
159
|
+
}
|
|
160
|
+
else if (g === 'day') {
|
|
161
|
+
row = bucketOf(g, day, day);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
const pid = projectOfEvent(session, ms);
|
|
165
|
+
row = pid ? bucketOf(g, pid, projectName.get(pid) ?? pid) : bucketOf(g, U.UNATTRIBUTED, U.UNATTRIBUTED);
|
|
166
|
+
}
|
|
167
|
+
add(row, e);
|
|
168
|
+
}
|
|
169
|
+
}, since);
|
|
170
|
+
const groups = {};
|
|
171
|
+
for (const g of groupBy) {
|
|
172
|
+
let rows;
|
|
173
|
+
if (g === 'workItem') {
|
|
174
|
+
rows = this.workItemRows(items, since, now, teamOf, nameOf);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
rows = [...(buckets.get(g)?.values() ?? [])];
|
|
178
|
+
if (g === 'agent')
|
|
179
|
+
for (const r of rows)
|
|
180
|
+
r.meta = { ...(r.meta ?? {}), runtimes: [...(runtimesOf.get(r.key) ?? [])].sort() };
|
|
181
|
+
if (g === 'day')
|
|
182
|
+
rows.sort((a, b) => a.key.localeCompare(b.key));
|
|
183
|
+
else
|
|
184
|
+
rows.sort((a, b) => b.total - a.total);
|
|
185
|
+
}
|
|
186
|
+
for (const r of rows)
|
|
187
|
+
r.share = totals.total > 0 ? r.total / totals.total : 0;
|
|
188
|
+
groups[g] = rows;
|
|
189
|
+
}
|
|
190
|
+
return { days: n, since: since.toISOString(), today, totals, todayTotals, groupBy, rows: groups[groupBy[0]] ?? [], groups };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Top work items in the window by tokens.
|
|
194
|
+
*/
|
|
195
|
+
workItemRows(items, since, now, teamOf, nameOf) {
|
|
196
|
+
const rows = [];
|
|
197
|
+
for (const wi of items) {
|
|
198
|
+
if (!wi.target)
|
|
199
|
+
continue;
|
|
200
|
+
const startMs = new Date(wi.startedAt ?? wi.createdAt).getTime();
|
|
201
|
+
const endMs = wi.completedAt ? new Date(wi.completedAt).getTime() : now.getTime();
|
|
202
|
+
if (!Number.isFinite(startMs) || !Number.isFinite(endMs) || endMs < since.getTime() || startMs > now.getTime())
|
|
203
|
+
continue;
|
|
204
|
+
const clipped = { createdAt: wi.createdAt, startedAt: new Date(Math.max(startMs, since.getTime())).toISOString(), completedAt: wi.completedAt };
|
|
205
|
+
const usage = computeWorkItemUsage(clipped, wi.target, this.deps.ledger, now);
|
|
206
|
+
if (!usage || usage.totalTokens <= 0)
|
|
207
|
+
continue;
|
|
208
|
+
const team = teamOf.get(wi.target);
|
|
209
|
+
rows.push({
|
|
210
|
+
key: wi.id,
|
|
211
|
+
label: wi.title || wi.id,
|
|
212
|
+
share: 0,
|
|
213
|
+
input: usage.totalTokens - usage.outputTokens,
|
|
214
|
+
cachedInput: usage.cachedInputTokens,
|
|
215
|
+
output: usage.outputTokens,
|
|
216
|
+
total: usage.totalTokens,
|
|
217
|
+
events: 0,
|
|
218
|
+
link: `/workitems/${wi.id}`,
|
|
219
|
+
meta: { agent: nameOf.get(wi.target) ?? wi.target, status: wi.status, ...(team ? { team: team.name } : {}) },
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
rows.sort((a, b) => b.total - a.total);
|
|
223
|
+
return rows.slice(0, U.MAX_WORK_ITEM_ROWS);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=usage-stats.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-stats.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/usage/usage-stats.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,8 +21,8 @@ export type DecisionSensitiveKind = 'email' | 'publish' | 'deploy' | 'spend' | '
|
|
|
21
21
|
* (specs/2026-10-01-runtime-terms-consent.md)
|
|
22
22
|
* - `reply_question`: a question an agent asked the owner in a reply, turned
|
|
23
23
|
* into a card on its behalf (specs/2026-10-01-reply-open-items.md)
|
|
24
|
-
* - `spend_cap`: an agent hit
|
|
25
|
-
* keep it stopped (specs/2026-10-02-spend-cap.md)
|
|
24
|
+
* - `spend_cap`: an agent / team / all agents hit a daily token cap — boost it
|
|
25
|
+
* for today (+X or unlimited) or keep it stopped (specs/2026-10-02-spend-cap.md)
|
|
26
26
|
*/
|
|
27
27
|
export type DecisionKind = 'browser_action' | 'runtime_terms' | 'reply_question' | 'spend_cap';
|
|
28
28
|
/** How a decision came to be: asked live, or carded by the open-items backfill. */
|
|
@@ -13,9 +13,17 @@ export interface TicketAutopilotSettings {
|
|
|
13
13
|
/** Session that triages; absent = the lead of the project's team */
|
|
14
14
|
driver?: string;
|
|
15
15
|
/**
|
|
16
|
-
* Daily
|
|
17
|
-
* which the autopilot pauses for the rest of the
|
|
18
|
-
*
|
|
16
|
+
* Daily tokens (input incl. cached + output) of the project's team agents
|
|
17
|
+
* since local midnight at which the autopilot pauses for the rest of the
|
|
18
|
+
* day. Absent = the default
|
|
19
|
+
* ({@link TICKET_AUTOPILOT_CONSTANTS.DEFAULT_DAILY_BUDGET_TOKENS}). A usage
|
|
20
|
+
* boost on the project's teams raises it for the day.
|
|
21
|
+
*/
|
|
22
|
+
dailyBudgetTokens?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Pre-token budget in USD. Read only to migrate it: converted with
|
|
25
|
+
* {@link USAGE_CONSTANTS.TOKENS_PER_USD} (see {@link legacyBudgetTokens}).
|
|
26
|
+
* @deprecated
|
|
19
27
|
*/
|
|
20
28
|
dailyBudgetUsd?: number;
|
|
21
29
|
/** In-progress tickets one member may hold at a time (default 1) */
|
|
@@ -26,7 +34,7 @@ export interface ResolvedTicketAutopilotSettings {
|
|
|
26
34
|
enabled: boolean;
|
|
27
35
|
/** The configured driver, or null (= the project team's lead) */
|
|
28
36
|
driver: string | null;
|
|
29
|
-
|
|
37
|
+
dailyBudgetTokens: number;
|
|
30
38
|
maxInFlightPerMember: number;
|
|
31
39
|
}
|
|
32
40
|
/** A change request for the settings (API / skill body). */
|
|
@@ -34,7 +42,9 @@ export interface TicketAutopilotSettingsInput {
|
|
|
34
42
|
enabled?: unknown;
|
|
35
43
|
/** A session name; `null` or `''` resets to the team lead */
|
|
36
44
|
driver?: unknown;
|
|
37
|
-
/**
|
|
45
|
+
/** Tokens: a positive number or text like "20M"; `null` resets to the default */
|
|
46
|
+
dailyBudgetTokens?: unknown;
|
|
47
|
+
/** Rejected: budgets are in tokens now */
|
|
38
48
|
dailyBudgetUsd?: unknown;
|
|
39
49
|
/** An integer 1..limit; `null` resets to the default */
|
|
40
50
|
maxInFlightPerMember?: unknown;
|
|
@@ -53,6 +63,13 @@ export type TicketAutopilotInputResult = {
|
|
|
53
63
|
* @param stored - `Project.ticketAutopilot` (may be undefined or partial)
|
|
54
64
|
* @returns Settings with defaults
|
|
55
65
|
*/
|
|
66
|
+
/**
|
|
67
|
+
* The token budget a stored pre-token USD budget converts to, or null.
|
|
68
|
+
*
|
|
69
|
+
* @param stored - Stored settings
|
|
70
|
+
* @returns Tokens (USD × TOKENS_PER_USD), or null when there is no USD budget
|
|
71
|
+
*/
|
|
72
|
+
export declare function legacyBudgetTokens(stored: Partial<TicketAutopilotSettings> | undefined | null): number | null;
|
|
56
73
|
export declare function resolveTicketAutopilotSettings(stored: Partial<TicketAutopilotSettings> | undefined | null): ResolvedTicketAutopilotSettings;
|
|
57
74
|
/**
|
|
58
75
|
* Apply a change request to the stored settings, validating every field.
|
|
@@ -65,8 +82,8 @@ export declare function resolveTicketAutopilotSettings(stored: Partial<TicketAut
|
|
|
65
82
|
*
|
|
66
83
|
* @example
|
|
67
84
|
* ```typescript
|
|
68
|
-
* applyTicketAutopilotInput(undefined, { enabled: true,
|
|
69
|
-
* // → { ok: true, settings: { enabled: true,
|
|
85
|
+
* applyTicketAutopilotInput(undefined, { enabled: true, dailyBudgetTokens: '10M' });
|
|
86
|
+
* // → { ok: true, settings: { enabled: true, dailyBudgetTokens: 10000000 } }
|
|
70
87
|
* ```
|
|
71
88
|
*/
|
|
72
89
|
export declare function applyTicketAutopilotInput(current: Partial<TicketAutopilotSettings> | undefined | null, input: TicketAutopilotSettingsInput): TicketAutopilotInputResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticket-autopilot.types.d.ts","sourceRoot":"","sources":["../../../../../backend/src/types/ticket-autopilot.types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"ticket-autopilot.types.d.ts","sourceRoot":"","sources":["../../../../../backend/src/types/ticket-autopilot.types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,6CAA6C;AAC7C,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,4DAA4D;AAC5D,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0CAA0C;IAC1C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,oDAAoD;AACpD,MAAM,MAAM,0BAA0B,GAClC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,uBAAuB,CAAA;CAAE,GAC/C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;;;;;GAKG;AACH;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG7G;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG,+BAA+B,CAY3I;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS,GAAG,IAAI,EAC5D,KAAK,EAAE,4BAA4B,GAClC,0BAA0B,CAuC5B"}
|
|
@@ -6,20 +6,31 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module types/ticket-autopilot.types
|
|
8
8
|
*/
|
|
9
|
-
import { TICKET_AUTOPILOT_CONSTANTS } from '../constants.js';
|
|
9
|
+
import { TICKET_AUTOPILOT_CONSTANTS, USAGE_CONSTANTS } from '../constants.js';
|
|
10
|
+
import { parseTokenAmount } from '../services/usage/token-format.js';
|
|
10
11
|
/**
|
|
11
12
|
* Fill in the defaults of stored (possibly absent) settings.
|
|
12
13
|
*
|
|
13
14
|
* @param stored - `Project.ticketAutopilot` (may be undefined or partial)
|
|
14
15
|
* @returns Settings with defaults
|
|
15
16
|
*/
|
|
17
|
+
/**
|
|
18
|
+
* The token budget a stored pre-token USD budget converts to, or null.
|
|
19
|
+
*
|
|
20
|
+
* @param stored - Stored settings
|
|
21
|
+
* @returns Tokens (USD × TOKENS_PER_USD), or null when there is no USD budget
|
|
22
|
+
*/
|
|
23
|
+
export function legacyBudgetTokens(stored) {
|
|
24
|
+
const usd = stored?.dailyBudgetUsd;
|
|
25
|
+
return typeof usd === 'number' && Number.isFinite(usd) && usd > 0 ? Math.round(usd * USAGE_CONSTANTS.TOKENS_PER_USD) : null;
|
|
26
|
+
}
|
|
16
27
|
export function resolveTicketAutopilotSettings(stored) {
|
|
17
|
-
const budget = stored?.
|
|
28
|
+
const budget = stored?.dailyBudgetTokens ?? legacyBudgetTokens(stored) ?? undefined;
|
|
18
29
|
const cap = stored?.maxInFlightPerMember;
|
|
19
30
|
return {
|
|
20
31
|
enabled: stored?.enabled === true,
|
|
21
32
|
driver: typeof stored?.driver === 'string' && stored.driver.trim() ? stored.driver.trim() : null,
|
|
22
|
-
|
|
33
|
+
dailyBudgetTokens: typeof budget === 'number' && Number.isFinite(budget) && budget > 0 ? budget : TICKET_AUTOPILOT_CONSTANTS.DEFAULT_DAILY_BUDGET_TOKENS,
|
|
23
34
|
maxInFlightPerMember: typeof cap === 'number' && Number.isInteger(cap) && cap >= 1 && cap <= TICKET_AUTOPILOT_CONSTANTS.MAX_IN_FLIGHT_PER_MEMBER_LIMIT
|
|
24
35
|
? cap
|
|
25
36
|
: TICKET_AUTOPILOT_CONSTANTS.DEFAULT_MAX_IN_FLIGHT_PER_MEMBER,
|
|
@@ -36,16 +47,18 @@ export function resolveTicketAutopilotSettings(stored) {
|
|
|
36
47
|
*
|
|
37
48
|
* @example
|
|
38
49
|
* ```typescript
|
|
39
|
-
* applyTicketAutopilotInput(undefined, { enabled: true,
|
|
40
|
-
* // → { ok: true, settings: { enabled: true,
|
|
50
|
+
* applyTicketAutopilotInput(undefined, { enabled: true, dailyBudgetTokens: '10M' });
|
|
51
|
+
* // → { ok: true, settings: { enabled: true, dailyBudgetTokens: 10000000 } }
|
|
41
52
|
* ```
|
|
42
53
|
*/
|
|
43
54
|
export function applyTicketAutopilotInput(current, input) {
|
|
44
55
|
const next = { enabled: current?.enabled === true };
|
|
45
56
|
if (typeof current?.driver === 'string' && current.driver.trim())
|
|
46
57
|
next.driver = current.driver.trim();
|
|
47
|
-
if (typeof current?.
|
|
48
|
-
next.
|
|
58
|
+
if (typeof current?.dailyBudgetTokens === 'number')
|
|
59
|
+
next.dailyBudgetTokens = current.dailyBudgetTokens;
|
|
60
|
+
else if (legacyBudgetTokens(current) !== null)
|
|
61
|
+
next.dailyBudgetTokens = legacyBudgetTokens(current);
|
|
49
62
|
if (typeof current?.maxInFlightPerMember === 'number')
|
|
50
63
|
next.maxInFlightPerMember = current.maxInFlightPerMember;
|
|
51
64
|
if (input.enabled !== undefined) {
|
|
@@ -62,13 +75,16 @@ export function applyTicketAutopilotInput(current, input) {
|
|
|
62
75
|
return { ok: false, error: 'driver must be a session name (or null for the team lead)' };
|
|
63
76
|
}
|
|
64
77
|
if (input.dailyBudgetUsd !== undefined) {
|
|
65
|
-
|
|
66
|
-
|
|
78
|
+
return { ok: false, error: 'Budgets are in tokens now: send dailyBudgetTokens (e.g. 20000000 or "20M") instead of dailyBudgetUsd' };
|
|
79
|
+
}
|
|
80
|
+
if (input.dailyBudgetTokens !== undefined) {
|
|
81
|
+
if (input.dailyBudgetTokens === null)
|
|
82
|
+
delete next.dailyBudgetTokens;
|
|
67
83
|
else {
|
|
68
|
-
const n =
|
|
69
|
-
if (
|
|
70
|
-
return { ok: false, error: '
|
|
71
|
-
next.
|
|
84
|
+
const n = parseTokenAmount(input.dailyBudgetTokens);
|
|
85
|
+
if (n === null)
|
|
86
|
+
return { ok: false, error: 'dailyBudgetTokens must be a positive number of tokens (e.g. 20000000 or "20M")' };
|
|
87
|
+
next.dailyBudgetTokens = n;
|
|
72
88
|
}
|
|
73
89
|
}
|
|
74
90
|
if (input.maxInFlightPerMember !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticket-autopilot.types.js","sourceRoot":"","sources":["../../../../../backend/src/types/ticket-autopilot.types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"ticket-autopilot.types.js","sourceRoot":"","sources":["../../../../../backend/src/types/ticket-autopilot.types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAqDrE;;;;;GAKG;AACH;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA2D;IAC5F,MAAM,GAAG,GAAG,MAAM,EAAE,cAAc,CAAC;IACnC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9H,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,MAA2D;IACxG,MAAM,MAAM,GAAG,MAAM,EAAE,iBAAiB,IAAI,kBAAkB,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC;IACpF,MAAM,GAAG,GAAG,MAAM,EAAE,oBAAoB,CAAC;IACzC,OAAO;QACL,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI;QACjC,MAAM,EAAE,OAAO,MAAM,EAAE,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;QAChG,iBAAiB,EAAE,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,0BAA0B,CAAC,2BAA2B;QACxJ,oBAAoB,EAClB,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,0BAA0B,CAAC,8BAA8B;YAC9H,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,0BAA0B,CAAC,gCAAgC;KAClE,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAA4D,EAC5D,KAAmC;IAEnC,MAAM,IAAI,GAA4B,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;IAC7E,IAAI,OAAO,OAAO,EAAE,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACtG,IAAI,OAAO,OAAO,EAAE,iBAAiB,KAAK,QAAQ;QAAE,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;SAClG,IAAI,kBAAkB,CAAC,OAAO,CAAC,KAAK,IAAI;QAAE,IAAI,CAAC,iBAAiB,GAAG,kBAAkB,CAAC,OAAO,CAAW,CAAC;IAC9G,IAAI,OAAO,OAAO,EAAE,oBAAoB,KAAK,QAAQ;QAAE,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAEhH,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC;QACrG,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC;aAChE,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;;YAC/F,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2DAA2D,EAAE,CAAC;IAChG,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACvC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,sGAAsG,EAAE,CAAC;IACtI,CAAC;IACD,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAC1C,IAAI,KAAK,CAAC,iBAAiB,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,iBAAiB,CAAC;aAC/D,CAAC;YACJ,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACpD,IAAI,CAAC,KAAK,IAAI;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gFAAgF,EAAE,CAAC;YAC9H,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QAC7C,IAAI,KAAK,CAAC,oBAAoB,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,oBAAoB,CAAC;aACrE,CAAC;YACJ,MAAM,CAAC,GAAG,OAAO,KAAK,CAAC,oBAAoB,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC;YAC3H,MAAM,KAAK,GAAG,0BAA0B,CAAC,8BAA8B,CAAC;YACxE,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC;gBACxE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yDAAyD,KAAK,EAAE,EAAE,CAAC;YAChG,CAAC;YACD,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC"}
|