crewx 0.8.9-rc.2 → 0.8.9-rc.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/assets/{MarketPage-BpajB_Ex.js → MarketPage-Cl9KvLAo.js} +1 -1
  2. package/dist/assets/PromptTab-gj_BvClc.js +27 -0
  3. package/dist/assets/{arc-B0fFLEOc.js → arc-DDzVSXZh.js} +1 -1
  4. package/dist/assets/{architectureDiagram-UYN6MBPD-CrC7MKTM.js → architectureDiagram-UYN6MBPD-p8OOXe5w.js} +1 -1
  5. package/dist/assets/{blockDiagram-ZHA2E4KO-DJsG-9x2.js → blockDiagram-ZHA2E4KO-BTlfXGnf.js} +7 -7
  6. package/dist/assets/{c4Diagram-6F5ED5ID-DlkyjvkS.js → c4Diagram-6F5ED5ID-CKbrDPWE.js} +1 -1
  7. package/dist/assets/channel-Hzz-cXd0.js +1 -0
  8. package/dist/assets/{chunk-5HRBRIJM-B_Csqjvw.js → chunk-5HRBRIJM-otR_A_1G.js} +1 -1
  9. package/dist/assets/{chunk-7U56Z5CX-BlNdzxbh.js → chunk-7U56Z5CX-BliJIH4-.js} +1 -1
  10. package/dist/assets/{chunk-ASOPGD6M-BiFWfa3w.js → chunk-ASOPGD6M-CmzypD4Z.js} +1 -1
  11. package/dist/assets/{chunk-KFBOBJHC-ocugjY-9.js → chunk-KFBOBJHC-BW4u3lPL.js} +1 -1
  12. package/dist/assets/{chunk-T2TOU4HS-kUreJ-bv.js → chunk-T2TOU4HS-BAp6Xscz.js} +1 -1
  13. package/dist/assets/{chunk-TMUBEWPD-Du19Q8X-.js → chunk-TMUBEWPD-Bv_RKIlz.js} +1 -1
  14. package/dist/assets/classDiagram-LNE6IOMH-CXR-DJKP.js +1 -0
  15. package/dist/assets/classDiagram-v2-MQ7JQ4JX-CXR-DJKP.js +1 -0
  16. package/dist/assets/{dagre-4EVJKHTY-8N5qxubq.js → dagre-4EVJKHTY-sYyP6lkA.js} +1 -1
  17. package/dist/assets/{diagram-QW4FP2JN-CjLH9uYk.js → diagram-QW4FP2JN-XWldv7Gz.js} +1 -1
  18. package/dist/assets/{erDiagram-6RL3IURR-CXgt8NtN.js → erDiagram-6RL3IURR-Cd8OVAQ0.js} +1 -1
  19. package/dist/assets/{flowDiagram-7ASYPVHJ-CdFlmdmT.js → flowDiagram-7ASYPVHJ-Cc3onSB6.js} +1 -1
  20. package/dist/assets/{ganttDiagram-NTVNEXSI-DDjK4yxy.js → ganttDiagram-NTVNEXSI-Q6HxMUkA.js} +1 -1
  21. package/dist/assets/{gitGraph-YCYPL57B-Bd9jYZ-C.js → gitGraph-YCYPL57B-BUh0zUco.js} +1 -1
  22. package/dist/assets/{gitGraphDiagram-NRZ2UAAF-pmwetPkN.js → gitGraphDiagram-NRZ2UAAF-CvPqw-ya.js} +1 -1
  23. package/dist/assets/{infoDiagram-A4XQUW5V-BoDEaOyd.js → infoDiagram-A4XQUW5V-CbKGdGqb.js} +1 -1
  24. package/dist/assets/{journeyDiagram-G5WM74LC-D1LRuhB3.js → journeyDiagram-G5WM74LC-BXyAvuxS.js} +1 -1
  25. package/dist/assets/{kanban-definition-QRCXZQQD-B66SGjA2.js → kanban-definition-QRCXZQQD-CxBFX9if.js} +1 -1
  26. package/dist/assets/{linear-VMCGabuP.js → linear-Bu0P9vdO.js} +1 -1
  27. package/dist/assets/main-AYmbxFu4.css +10 -0
  28. package/dist/assets/main-CcrxU2Tf.js +1454 -0
  29. package/dist/assets/{mindmap-definition-GWI6TPTV--NljwHD9.js → mindmap-definition-GWI6TPTV-BbXI83yG.js} +1 -1
  30. package/dist/assets/{pieDiagram-YF2LJOPJ-CP4IPp3Q.js → pieDiagram-YF2LJOPJ-DuXspLPW.js} +1 -1
  31. package/dist/assets/{quadrantDiagram-OS5C2QUG-baFc-DtQ.js → quadrantDiagram-OS5C2QUG-DnngSA8p.js} +1 -1
  32. package/dist/assets/{requirementDiagram-MIRIMTAZ-BTWwNcnt.js → requirementDiagram-MIRIMTAZ-ChJE8XYc.js} +1 -1
  33. package/dist/assets/{sankeyDiagram-Y46BX6SQ-CnrACC1i.js → sankeyDiagram-Y46BX6SQ-BlkQKMk0.js} +1 -1
  34. package/dist/assets/{sequenceDiagram-G6AWOVSC-Ct5WkHJl.js → sequenceDiagram-G6AWOVSC-BvYCRnWL.js} +1 -1
  35. package/dist/assets/{stateDiagram-MAYHULR4-DeZHZmIy.js → stateDiagram-MAYHULR4-Cb6BiEq_.js} +1 -1
  36. package/dist/assets/stateDiagram-v2-4JROLMXI-31Hvt1M0.js +1 -0
  37. package/dist/assets/{timeline-definition-U7ZMHBDA-BZfUE50X.js → timeline-definition-U7ZMHBDA-w1-dGiEP.js} +1 -1
  38. package/dist/assets/{xychartDiagram-6QU3TZC5-DV6BFyHM.js → xychartDiagram-6QU3TZC5-B85iIKzT.js} +1 -1
  39. package/dist/index.html +2 -2
  40. package/dist-server/__stubs__/ccusage-codex.js +8 -0
  41. package/dist-server/app.module.js +2 -0
  42. package/dist-server/common/limits/defaults.js +3 -3
  43. package/dist-server/domain/agent/agent.service.js +11 -0
  44. package/dist-server/domain/cli/cli.service.js +3 -3
  45. package/dist-server/domain/cron/cron.service.js +5 -1
  46. package/dist-server/domain/doc/doc.controller.js +22 -0
  47. package/dist-server/domain/doc/doc.service.js +42 -10
  48. package/dist-server/domain/git/git.controller.js +180 -0
  49. package/dist-server/domain/git/git.module.js +2 -0
  50. package/dist-server/domain/git/git.service.js +327 -34
  51. package/dist-server/domain/message/message.service.js +18 -8
  52. package/dist-server/domain/onboarding/onboarding.service.js +1 -1
  53. package/dist-server/domain/onboarding/presets/custom.js +2 -2
  54. package/dist-server/domain/onboarding/presets/dev-team.js +7 -7
  55. package/dist-server/domain/onboarding/presets/marketing-team.js +5 -5
  56. package/dist-server/domain/onboarding/presets/planning-team.js +5 -5
  57. package/dist-server/domain/onboarding/presets/solo.js +3 -3
  58. package/dist-server/domain/settings/settings.module.js +2 -0
  59. package/dist-server/domain/settings/settings.service.js +75 -8
  60. package/dist-server/domain/task/task.service.js +7 -7
  61. package/dist-server/domain/thread/thread.service.js +2 -1
  62. package/dist-server/domain/usage/usage.controller.js +30 -0
  63. package/dist-server/domain/usage/usage.service.js +212 -0
  64. package/dist-server/domain/wi/wi.controller.js +43 -0
  65. package/dist-server/domain/wi/wi.module.js +22 -0
  66. package/dist-server/domain/wi/wi.service.js +110 -0
  67. package/dist-server/domain/wi/wi.types.js +2 -0
  68. package/dist-server/domain/workspace/workspace.service.js +4 -1
  69. package/dist-server/modules/crewx-pool.service.js +194 -53
  70. package/dist-server/repository/task.repository.js +5 -1
  71. package/package.json +16 -14
  72. package/packages/cli/dist/commands/agent.js +1 -1
  73. package/packages/cli/dist/commands/init.d.ts +2 -0
  74. package/packages/cli/dist/commands/init.js +198 -6
  75. package/packages/cli/package.json +3 -2
  76. package/dist/assets/PromptTab-HhD4MQcW.js +0 -37
  77. package/dist/assets/channel-ClmdPiZd.js +0 -1
  78. package/dist/assets/classDiagram-LNE6IOMH-Q0hRWLPF.js +0 -1
  79. package/dist/assets/classDiagram-v2-MQ7JQ4JX-Q0hRWLPF.js +0 -1
  80. package/dist/assets/main-AqROOc4i.css +0 -10
  81. package/dist/assets/main-DWCTap27.js +0 -1289
  82. package/dist/assets/stateDiagram-v2-4JROLMXI-DVsMMyDB.js +0 -1
@@ -50,8 +50,9 @@ let MessageService = MessageService_1 = class MessageService {
50
50
  const taskItems = [];
51
51
  for (let i = 0; i < ctx.hot.length; i++) {
52
52
  const msg = ctx.hot[i];
53
- if (msg.role === 'assistant' && msg.metadata?.task) {
54
- const t = msg.metadata.task;
53
+ const taskMeta = msg.metadata && 'task' in msg.metadata ? msg.metadata.task : undefined;
54
+ if (msg.role === 'assistant' && taskMeta) {
55
+ const t = taskMeta;
55
56
  taskItems.push({
56
57
  type: 'task',
57
58
  taskId: t.taskId,
@@ -64,6 +65,7 @@ let MessageService = MessageService_1 = class MessageService {
64
65
  startedAt: t.startedAt,
65
66
  completedAt: t.completedAt ?? undefined,
66
67
  durationMs: t.durationMs ?? undefined,
68
+ callerAgentId: t.callerAgentId ?? undefined,
67
69
  });
68
70
  }
69
71
  }
@@ -72,9 +74,13 @@ let MessageService = MessageService_1 = class MessageService {
72
74
  // 1) running/pending tasks always include logs regardless of logsTail
73
75
  for (const item of taskItems) {
74
76
  if (item.status === 'running' || item.status === 'pending') {
75
- const assistantMsg = ctx.hot.find((m) => m.role === 'assistant' && m.metadata?.task?.taskId === item.taskId);
76
- if (assistantMsg?.metadata?.task?.logs) {
77
- item.logs = this.filterLogs(assistantMsg.metadata.task.logs);
77
+ const assistantMsg = ctx.hot.find((m) => {
78
+ const meta = m.role === 'assistant' && m.metadata && 'task' in m.metadata ? m.metadata.task : undefined;
79
+ return meta?.taskId === item.taskId;
80
+ });
81
+ const meta = assistantMsg?.metadata && 'task' in assistantMsg.metadata ? assistantMsg.metadata.task : undefined;
82
+ if (meta?.logs) {
83
+ item.logs = this.filterLogs(meta.logs);
78
84
  }
79
85
  }
80
86
  }
@@ -84,9 +90,13 @@ let MessageService = MessageService_1 = class MessageService {
84
90
  const startIdx = Math.max(0, completedItems.length - logsTail);
85
91
  for (let i = startIdx; i < completedItems.length; i++) {
86
92
  const taskId = completedItems[i].taskId;
87
- const assistantMsg = ctx.hot.find((m) => m.role === 'assistant' && m.metadata?.task?.taskId === taskId);
88
- if (assistantMsg?.metadata?.task?.logs) {
89
- completedItems[i].logs = this.filterLogs(assistantMsg.metadata.task.logs);
93
+ const assistantMsg = ctx.hot.find((m) => {
94
+ const meta = m.role === 'assistant' && m.metadata && 'task' in m.metadata ? m.metadata.task : undefined;
95
+ return meta?.taskId === taskId;
96
+ });
97
+ const meta = assistantMsg?.metadata && 'task' in assistantMsg.metadata ? assistantMsg.metadata.task : undefined;
98
+ if (meta?.logs) {
99
+ completedItems[i].logs = this.filterLogs(meta.logs);
90
100
  }
91
101
  }
92
102
  }
@@ -62,7 +62,7 @@ let OnboardingService = class OnboardingService {
62
62
  throw new common_1.ConflictException({
63
63
  statusCode: 409,
64
64
  error: 'AGENTS_EXIST',
65
- message: '이미 에이전트가 등록되어 있습니다',
65
+ message: 'Agents are already registered',
66
66
  existingAgentCount: existingAgents.length,
67
67
  });
68
68
  }
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.customPreset = void 0;
4
4
  exports.customPreset = {
5
5
  id: 'custom',
6
- name: '직접 구성',
7
- description: '에이전트를 직접 추가하여 나만의 팀을 구성합니다',
6
+ name: 'Custom',
7
+ description: 'Build your own team by adding agents manually',
8
8
  icon: '➕',
9
9
  agents: [],
10
10
  };
@@ -3,39 +3,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.devTeamPreset = void 0;
4
4
  exports.devTeamPreset = {
5
5
  id: 'dev-team',
6
- name: '개발팀',
7
- description: '풀스택 개발에 최적화된 AI 에이전트 ',
6
+ name: 'Development Team',
7
+ description: 'AI agent team optimized for full-stack development',
8
8
  icon: '💻',
9
9
  agents: [
10
10
  {
11
11
  id: 'backend_dev',
12
12
  name: 'Backend Developer',
13
13
  role: 'Backend Senior Developer',
14
- description: 'NestJS 백엔드 API 구현 전문',
14
+ description: 'Specializes in NestJS backend API implementation',
15
15
  },
16
16
  {
17
17
  id: 'frontend_dev',
18
18
  name: 'Frontend Developer',
19
19
  role: 'Frontend Senior Developer',
20
- description: 'React + TailwindCSS 프론트엔드 구현 전문',
20
+ description: 'Specializes in React and TailwindCSS frontend implementation',
21
21
  },
22
22
  {
23
23
  id: 'devops',
24
24
  name: 'DevOps Engineer',
25
25
  role: 'DevOps Engineer',
26
- description: 'CI/CD, 인프라, 배포 자동화',
26
+ description: 'CI/CD, infrastructure, and deployment automation',
27
27
  },
28
28
  {
29
29
  id: 'qa_engineer',
30
30
  name: 'QA Engineer',
31
31
  role: 'QA Engineer',
32
- description: '테스트 전략 수립 품질 관리',
32
+ description: 'Test strategy and quality management',
33
33
  },
34
34
  {
35
35
  id: 'tech_lead',
36
36
  name: 'Tech Lead',
37
37
  role: 'Technical Lead',
38
- description: '기술 의사결정 코드 리뷰',
38
+ description: 'Technical decisions and code review',
39
39
  },
40
40
  ],
41
41
  };
@@ -3,27 +3,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.marketingTeamPreset = void 0;
4
4
  exports.marketingTeamPreset = {
5
5
  id: 'marketing-team',
6
- name: '마케팅팀',
7
- description: '콘텐츠 마케팅과 브랜딩에 특화된 AI 에이전트 ',
6
+ name: 'Marketing Team',
7
+ description: 'AI agent team for content marketing and branding',
8
8
  icon: '📢',
9
9
  agents: [
10
10
  {
11
11
  id: 'content_writer',
12
12
  name: 'Content Writer',
13
13
  role: 'Content Strategist',
14
- description: '블로그, SNS, 뉴스레터 콘텐츠 작성',
14
+ description: 'Writes blog, social media, and newsletter content',
15
15
  },
16
16
  {
17
17
  id: 'seo_specialist',
18
18
  name: 'SEO Specialist',
19
19
  role: 'SEO Analyst',
20
- description: 'SEO 최적화 키워드 분석',
20
+ description: 'SEO optimization and keyword analysis',
21
21
  },
22
22
  {
23
23
  id: 'brand_designer',
24
24
  name: 'Brand Designer',
25
25
  role: 'Brand Designer',
26
- description: '브랜드 가이드라인 비주얼 디자인',
26
+ description: 'Brand guidelines and visual design',
27
27
  },
28
28
  ],
29
29
  };
@@ -3,27 +3,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.planningTeamPreset = void 0;
4
4
  exports.planningTeamPreset = {
5
5
  id: 'planning-team',
6
- name: '기획팀',
7
- description: '제품 기획과 프로젝트 관리에 특화된 AI 에이전트 ',
6
+ name: 'Planning Team',
7
+ description: 'AI agent team for product planning and project management',
8
8
  icon: '📋',
9
9
  agents: [
10
10
  {
11
11
  id: 'product_manager',
12
12
  name: 'Product Manager',
13
13
  role: 'Product Manager',
14
- description: 'PRD 작성 제품 전략 수립',
14
+ description: 'PRD writing and product strategy',
15
15
  },
16
16
  {
17
17
  id: 'ux_researcher',
18
18
  name: 'UX Researcher',
19
19
  role: 'UX Researcher',
20
- description: '사용자 리서치 인사이트 도출',
20
+ description: 'User research and insight discovery',
21
21
  },
22
22
  {
23
23
  id: 'project_coordinator',
24
24
  name: 'Project Coordinator',
25
25
  role: 'Project Coordinator',
26
- description: '일정 관리 이해관계자 조율',
26
+ description: 'Schedule management and stakeholder coordination',
27
27
  },
28
28
  ],
29
29
  };
@@ -3,15 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.soloPreset = void 0;
4
4
  exports.soloPreset = {
5
5
  id: 'solo',
6
- name: '1인 만능자',
7
- description: '혼자서 모든 것을 처리하는 올라운더 AI 에이전트',
6
+ name: 'Solo All-Rounder',
7
+ description: 'An all-rounder AI agent that handles everything solo',
8
8
  icon: '🦸',
9
9
  agents: [
10
10
  {
11
11
  id: 'all_rounder',
12
12
  name: 'All Rounder',
13
13
  role: 'Full-stack Developer',
14
- description: '개발, 기획, 디자인을 아우르는 만능 에이전트',
14
+ description: 'All-purpose agent covering development, planning, and design',
15
15
  },
16
16
  ],
17
17
  };
@@ -10,11 +10,13 @@ exports.SettingsModule = void 0;
10
10
  const common_1 = require("@nestjs/common");
11
11
  const settings_controller_js_1 = require("./settings.controller.js");
12
12
  const settings_service_js_1 = require("./settings.service.js");
13
+ const crewx_module_js_1 = require("../../modules/crewx.module.js");
13
14
  let SettingsModule = class SettingsModule {
14
15
  };
15
16
  exports.SettingsModule = SettingsModule;
16
17
  exports.SettingsModule = SettingsModule = __decorate([
17
18
  (0, common_1.Module)({
19
+ imports: [crewx_module_js_1.CrewxModule],
18
20
  controllers: [settings_controller_js_1.SettingsController],
19
21
  providers: [settings_service_js_1.SettingsService],
20
22
  exports: [settings_service_js_1.SettingsService],
@@ -47,36 +47,102 @@ const fs_1 = require("fs");
47
47
  const common_1 = require("@nestjs/common");
48
48
  const yaml = __importStar(require("js-yaml"));
49
49
  const analytics_client_js_1 = require("../../common/analytics.client.js");
50
+ const crewx_pool_service_js_1 = require("../../modules/crewx-pool.service.js");
51
+ const workspace_context_store_js_1 = require("../../common/workspace-context.store.js");
50
52
  let SettingsService = class SettingsService {
51
53
  analyticsService;
52
- constructor(analyticsService) {
54
+ pool;
55
+ constructor(analyticsService, pool) {
53
56
  this.analyticsService = analyticsService;
57
+ this.pool = pool;
54
58
  }
55
59
  get configPath() {
56
- return process.env.CREWX_CONFIG || 'crewx.yaml';
60
+ return this.pool.resolveConfigPath((0, workspace_context_store_js_1.getWorkspacePath)()) ?? 'crewx.yaml';
57
61
  }
58
62
  getSettings() {
59
63
  const config = this.loadConfig();
60
64
  const settings = (config.settings ?? {});
65
+ const dreaming = (settings.dreaming ?? {});
66
+ const continuity = (dreaming.continuity ?? {});
67
+ const template = (settings.template ?? {});
68
+ const exec = (template.exec ?? {});
61
69
  return {
62
70
  analytics: settings.analytics !== false,
71
+ continuity: {
72
+ lookback: typeof continuity.lookback === 'number' ? continuity.lookback : 1,
73
+ reuseReadOnly: continuity.reuseReadOnly !== false,
74
+ },
75
+ execSandbox: {
76
+ timeout: typeof exec.timeout === 'number' ? exec.timeout : 30,
77
+ allow: Array.isArray(exec.allow) ? exec.allow : [],
78
+ },
63
79
  };
64
80
  }
65
81
  updateSettings(patch) {
66
82
  const config = this.loadConfig();
67
- if (!config.settings || typeof config.settings !== 'object') {
68
- config.settings = {};
69
- }
70
- const settings = config.settings;
83
+ let dirty = false;
84
+ let analyticsValue;
71
85
  if (patch.analytics !== undefined) {
86
+ if (!config.settings || typeof config.settings !== 'object') {
87
+ config.settings = {};
88
+ }
89
+ const settings = config.settings;
72
90
  if (patch.analytics) {
73
91
  delete settings.analytics;
74
92
  }
75
93
  else {
76
94
  settings.analytics = false;
77
95
  }
96
+ dirty = true;
97
+ analyticsValue = patch.analytics;
98
+ }
99
+ if (patch.continuity !== undefined) {
100
+ if (!config.settings || typeof config.settings !== 'object') {
101
+ config.settings = {};
102
+ }
103
+ const settings = config.settings;
104
+ if (!settings.dreaming || typeof settings.dreaming !== 'object') {
105
+ settings.dreaming = {};
106
+ }
107
+ const dreaming = settings.dreaming;
108
+ if (!dreaming.continuity || typeof dreaming.continuity !== 'object') {
109
+ dreaming.continuity = {};
110
+ }
111
+ const continuity = dreaming.continuity;
112
+ if (patch.continuity.lookback !== undefined) {
113
+ continuity.lookback = patch.continuity.lookback;
114
+ }
115
+ if (patch.continuity.reuseReadOnly !== undefined) {
116
+ continuity.reuseReadOnly = patch.continuity.reuseReadOnly;
117
+ }
118
+ dirty = true;
119
+ }
120
+ if (patch.execSandbox !== undefined) {
121
+ if (!config.settings || typeof config.settings !== 'object') {
122
+ config.settings = {};
123
+ }
124
+ const settings = config.settings;
125
+ if (!settings.template || typeof settings.template !== 'object') {
126
+ settings.template = {};
127
+ }
128
+ const template = settings.template;
129
+ if (!template.exec || typeof template.exec !== 'object') {
130
+ template.exec = {};
131
+ }
132
+ const exec = template.exec;
133
+ if (patch.execSandbox.timeout !== undefined) {
134
+ exec.timeout = patch.execSandbox.timeout;
135
+ }
136
+ if (patch.execSandbox.allow !== undefined) {
137
+ exec.allow = patch.execSandbox.allow;
138
+ }
139
+ dirty = true;
140
+ }
141
+ if (dirty) {
78
142
  this.saveConfig(config);
79
- this.analyticsService.setEnabled(patch.analytics);
143
+ if (analyticsValue !== undefined) {
144
+ this.analyticsService.setEnabled(analyticsValue);
145
+ }
80
146
  }
81
147
  return this.getSettings();
82
148
  }
@@ -101,5 +167,6 @@ let SettingsService = class SettingsService {
101
167
  exports.SettingsService = SettingsService;
102
168
  exports.SettingsService = SettingsService = __decorate([
103
169
  (0, common_1.Injectable)(),
104
- __metadata("design:paramtypes", [analytics_client_js_1.AnalyticsService])
170
+ __metadata("design:paramtypes", [analytics_client_js_1.AnalyticsService,
171
+ crewx_pool_service_js_1.CrewxPoolService])
105
172
  ], SettingsService);
@@ -122,19 +122,19 @@ let TaskService = TaskService_1 = class TaskService {
122
122
  this.validateTaskId(taskId);
123
123
  const task = this.taskRepo.findTaskForStop(taskId, workspaceId);
124
124
  if (!task) {
125
- throw new common_1.HttpException({ code: 'TASK_NOT_FOUND', message: '태스크를 찾을 수 없습니다' }, 404);
125
+ throw new common_1.HttpException({ code: 'TASK_NOT_FOUND', message: 'Task not found' }, 404);
126
126
  }
127
127
  if (task.status !== 'running') {
128
- throw new common_1.HttpException({ code: 'TASK_NOT_RUNNING', message: '실행 중인 태스크만 중지할 있습니다' }, 400);
128
+ throw new common_1.HttpException({ code: 'TASK_NOT_RUNNING', message: 'Only running tasks can be stopped' }, 400);
129
129
  }
130
130
  if (task.pid == null) {
131
- throw new common_1.HttpException({ code: 'PID_NOT_FOUND', message: '프로세스 ID 찾을 수 없습니다' }, 422);
131
+ throw new common_1.HttpException({ code: 'PID_NOT_FOUND', message: 'Process ID not found' }, 422);
132
132
  }
133
133
  // PID ownership verification: ensure PID belongs to a crewx-related process
134
134
  try {
135
135
  const cmdOutput = (0, child_process_1.execSync)(`ps -p ${task.pid} -o command=`, { encoding: 'utf-8', timeout: 3000 }).trim();
136
136
  if (!cmdOutput.includes('crewx') && !cmdOutput.includes('claude') && !cmdOutput.includes('node')) {
137
- throw new common_1.HttpException({ code: 'PID_NOT_FOUND', message: '프로세스 ID 찾을 수 없습니다' }, 422);
137
+ throw new common_1.HttpException({ code: 'PID_NOT_FOUND', message: 'Process ID not found' }, 422);
138
138
  }
139
139
  }
140
140
  catch (err) {
@@ -151,7 +151,7 @@ let TaskService = TaskService_1 = class TaskService {
151
151
  catch (err) {
152
152
  const code = err.code;
153
153
  if (code === 'EPERM') {
154
- throw new common_1.HttpException({ code: 'PERMISSION_DENIED', message: '프로세스 중지 권한이 없습니다' }, 403);
154
+ throw new common_1.HttpException({ code: 'PERMISSION_DENIED', message: 'No permission to stop the process' }, 403);
155
155
  }
156
156
  // ESRCH = process already gone — proceed to update DB
157
157
  if (code !== 'ESRCH')
@@ -168,11 +168,11 @@ let TaskService = TaskService_1 = class TaskService {
168
168
  }, 2000);
169
169
  }
170
170
  // Conditionally update DB (race condition safe)
171
- this.taskRepo.markTaskFailed(taskId, '사용자에 의해 중지됨');
171
+ this.taskRepo.markTaskFailed(taskId, 'Stopped by user');
172
172
  return {
173
173
  taskId,
174
174
  status: 'failed',
175
- error: '사용자에 의해 중지됨',
175
+ error: 'Stopped by user',
176
176
  stoppedAt: new Date().toISOString(),
177
177
  };
178
178
  }
@@ -274,7 +274,7 @@ let ThreadService = ThreadService_1 = class ThreadService {
274
274
  role: 'user',
275
275
  content: task.prompt,
276
276
  timestamp: task.started_at,
277
- metadata: null,
277
+ metadata: { callerAgentId: task.caller_agent_id ?? null },
278
278
  });
279
279
  }
280
280
  if (task.result || task.status !== 'pending') {
@@ -324,6 +324,7 @@ let ThreadService = ThreadService_1 = class ThreadService {
324
324
  sessionId,
325
325
  error: task.error || null,
326
326
  logs: this.parseLogs(task.logs, 50, this.extractAdapterKey(task)),
327
+ callerAgentId: task.caller_agent_id ?? null,
327
328
  },
328
329
  },
329
330
  });
@@ -38,6 +38,19 @@ let UsageController = class UsageController {
38
38
  const data = this.usageService.getAgentUsageTrend(from, to, tz, workspace);
39
39
  return { success: true, data };
40
40
  }
41
+ // USG.PROVIDER: 프로바이더별 사용량 집계
42
+ getProviderUsage(from, to, workspace) {
43
+ if (!from || !to) {
44
+ throw new common_1.BadRequestException('Both "from" and "to" query parameters are required (ISO 8601)');
45
+ }
46
+ const data = this.usageService.getProviderUsage(from, to, workspace);
47
+ return { success: true, data };
48
+ }
49
+ // USG.LIMITS: 구독 한도 조회
50
+ async getSubscriptionLimits() {
51
+ const data = await this.usageService.getSubscriptionLimits();
52
+ return { success: true, data };
53
+ }
41
54
  // USG.DAILY: 일별 사용량 조회
42
55
  async getDailyUsage(provider = 'all', force = 'false', res) {
43
56
  const validProvider = this.validateProvider(provider);
@@ -91,6 +104,23 @@ __decorate([
91
104
  __metadata("design:paramtypes", [String, String, String, String]),
92
105
  __metadata("design:returntype", void 0)
93
106
  ], UsageController.prototype, "getAgentUsageTrend", null);
107
+ __decorate([
108
+ (0, swagger_1.ApiOperation)({ operationId: 'USG.PROVIDER', summary: 'Get per-provider usage aggregation' }),
109
+ (0, common_1.Get)('providers'),
110
+ __param(0, (0, common_1.Query)('from')),
111
+ __param(1, (0, common_1.Query)('to')),
112
+ __param(2, (0, common_1.Query)('workspace')),
113
+ __metadata("design:type", Function),
114
+ __metadata("design:paramtypes", [String, String, String]),
115
+ __metadata("design:returntype", void 0)
116
+ ], UsageController.prototype, "getProviderUsage", null);
117
+ __decorate([
118
+ (0, swagger_1.ApiOperation)({ operationId: 'USG.LIMITS', summary: 'Get subscription limit windows (Codex + Claude)' }),
119
+ (0, common_1.Get)('limits'),
120
+ __metadata("design:type", Function),
121
+ __metadata("design:paramtypes", []),
122
+ __metadata("design:returntype", Promise)
123
+ ], UsageController.prototype, "getSubscriptionLimits", null);
94
124
  __decorate([
95
125
  (0, swagger_1.ApiOperation)({ operationId: 'USG.DAILY', summary: 'Get daily usage statistics' }),
96
126
  (0, common_1.Get)('daily'),