@noclaf/cli 0.4.14 → 0.4.15

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 (103) hide show
  1. package/dist/auth.js +2 -1
  2. package/dist/auth.js.map +1 -1
  3. package/dist/brand.js +82 -0
  4. package/dist/brand.js.map +1 -0
  5. package/dist/cli/commands/auth.js +91 -58
  6. package/dist/cli/commands/auth.js.map +1 -1
  7. package/dist/cli/commands/init/auth-step.js +48 -0
  8. package/dist/cli/commands/init/auth-step.js.map +1 -0
  9. package/dist/cli/commands/init/clients-step.js +76 -0
  10. package/dist/cli/commands/init/clients-step.js.map +1 -0
  11. package/dist/cli/commands/init/context-step.js +66 -0
  12. package/dist/cli/commands/init/context-step.js.map +1 -0
  13. package/dist/cli/commands/init/index.js +67 -0
  14. package/dist/cli/commands/init/index.js.map +1 -0
  15. package/dist/cli/commands/init/project-step.js +105 -0
  16. package/dist/cli/commands/init/project-step.js.map +1 -0
  17. package/dist/cli/commands/init/provision-step.js +76 -0
  18. package/dist/cli/commands/init/provision-step.js.map +1 -0
  19. package/dist/cli/flows/clients.js +27 -17
  20. package/dist/cli/flows/clients.js.map +1 -1
  21. package/dist/cli.js +5 -5
  22. package/dist/cli.js.map +1 -1
  23. package/dist/config.js +19 -11
  24. package/dist/config.js.map +1 -1
  25. package/dist/constants.js +7 -8
  26. package/dist/constants.js.map +1 -1
  27. package/dist/lib/autopull.js +13 -0
  28. package/dist/lib/autopull.js.map +1 -0
  29. package/dist/lib/client-configs.js +37 -25
  30. package/dist/lib/client-configs.js.map +1 -1
  31. package/dist/lib/cowork-extension.js +42 -30
  32. package/dist/lib/cowork-extension.js.map +1 -1
  33. package/dist/lib/dependencies.js +83 -247
  34. package/dist/lib/dependencies.js.map +1 -1
  35. package/dist/lib/dependency-install.js +163 -0
  36. package/dist/lib/dependency-install.js.map +1 -0
  37. package/dist/lib/exec-delegate.js +2 -2
  38. package/dist/lib/exec-delegate.js.map +1 -1
  39. package/dist/lib/exec-engines.js +7 -6
  40. package/dist/lib/exec-engines.js.map +1 -1
  41. package/dist/lib/provision-apply.js +214 -0
  42. package/dist/lib/provision-apply.js.map +1 -0
  43. package/dist/lib/provision-collect.js +47 -0
  44. package/dist/lib/provision-collect.js.map +1 -0
  45. package/dist/lib/provision.js +8 -253
  46. package/dist/lib/provision.js.map +1 -1
  47. package/dist/lib/require-config.js +3 -2
  48. package/dist/lib/require-config.js.map +1 -1
  49. package/dist/lib/skills-cache.js +9 -8
  50. package/dist/lib/skills-cache.js.map +1 -1
  51. package/dist/lib/skills.js +30 -16
  52. package/dist/lib/skills.js.map +1 -1
  53. package/dist/lib/telemetry.js +2 -1
  54. package/dist/lib/telemetry.js.map +1 -1
  55. package/dist/lib/version-check.js +3 -2
  56. package/dist/lib/version-check.js.map +1 -1
  57. package/dist/mcp-server.js +107 -79
  58. package/dist/mcp-server.js.map +1 -1
  59. package/dist/tools/comment-task.js +32 -32
  60. package/dist/tools/comment-task.js.map +1 -1
  61. package/dist/tools/create-task.js +92 -101
  62. package/dist/tools/create-task.js.map +1 -1
  63. package/dist/tools/delegate-exec.js +4 -3
  64. package/dist/tools/delegate-exec.js.map +1 -1
  65. package/dist/tools/end-allocation.js +19 -32
  66. package/dist/tools/end-allocation.js.map +1 -1
  67. package/dist/tools/end-task-allocation.js +17 -26
  68. package/dist/tools/end-task-allocation.js.map +1 -1
  69. package/dist/tools/exec-status.js +4 -3
  70. package/dist/tools/exec-status.js.map +1 -1
  71. package/dist/tools/get-active-allocation.js +53 -60
  72. package/dist/tools/get-active-allocation.js.map +1 -1
  73. package/dist/tools/get-context.js +4 -3
  74. package/dist/tools/get-context.js.map +1 -1
  75. package/dist/tools/get-task.js +144 -142
  76. package/dist/tools/get-task.js.map +1 -1
  77. package/dist/tools/list-my-allocations.js +35 -43
  78. package/dist/tools/list-my-allocations.js.map +1 -1
  79. package/dist/tools/list-projects.js +3 -2
  80. package/dist/tools/list-projects.js.map +1 -1
  81. package/dist/tools/list-tasks.js +117 -124
  82. package/dist/tools/list-tasks.js.map +1 -1
  83. package/dist/tools/move-task.js +37 -39
  84. package/dist/tools/move-task.js.map +1 -1
  85. package/dist/tools/plan.js +3 -2
  86. package/dist/tools/plan.js.map +1 -1
  87. package/dist/tools/record-delivery.js +4 -3
  88. package/dist/tools/record-delivery.js.map +1 -1
  89. package/dist/tools/set-project.js +9 -4
  90. package/dist/tools/set-project.js.map +1 -1
  91. package/dist/tools/start-allocation.js +16 -26
  92. package/dist/tools/start-allocation.js.map +1 -1
  93. package/dist/tools/start-task-allocation.js +72 -92
  94. package/dist/tools/start-task-allocation.js.map +1 -1
  95. package/dist/tools/update-task.js +149 -168
  96. package/dist/tools/update-task.js.map +1 -1
  97. package/dist/tools/validate-plan.js +3 -2
  98. package/dist/tools/validate-plan.js.map +1 -1
  99. package/package.json +1 -1
  100. package/dist/cli/commands/init.js +0 -336
  101. package/dist/cli/commands/init.js.map +0 -1
  102. package/dist/logo.js +0 -17
  103. package/dist/logo.js.map +0 -1
@@ -1,7 +1,9 @@
1
1
  import { jsonResult, errorResult } from '../lib/tool-result.js';
2
+ import { isErrorResult } from '../lib/require-config.js';
2
3
  import { durationSeconds } from '../lib/duration.js';
4
+ import { brand } from '../brand.js';
3
5
  export const definition = {
4
- name: 'nos_get_active_allocation',
6
+ name: `${brand.toolPrefix}get_active_allocation`,
5
7
  description: 'Retorna o estado atual de cronometragem do usuário: alocação ativa, task atual sendo ' +
6
8
  'cronometrada, e segmentos por task na alocação atual.',
7
9
  inputSchema: {
@@ -10,61 +12,8 @@ export const definition = {
10
12
  additionalProperties: false,
11
13
  },
12
14
  };
13
- export async function handler(_args, ctx) {
14
- const { supabase } = ctx;
15
- const allocRes = await supabase
16
- .from('allocations')
17
- .select('id, start_time')
18
- .eq('user_id', ctx.user.id)
19
- .is('end_time', null)
20
- .maybeSingle();
21
- if (allocRes.error)
22
- return errorResult(`Erro ao buscar alocação ativa: ${allocRes.error.message}`);
23
- if (!allocRes.data) {
24
- return jsonResult({
25
- allocation: null,
26
- active_task: null,
27
- segments: [],
28
- total_seconds_today: 0,
29
- });
30
- }
31
- const allocation = allocRes.data;
32
- const segmentsRes = await supabase
33
- .from('task_allocations')
34
- .select('id, task_id, start_time, end_time, is_overtime')
35
- .eq('allocation_id', allocation.id)
36
- .order('start_time', { ascending: true });
37
- if (segmentsRes.error)
38
- return errorResult(`Erro ao buscar segmentos: ${segmentsRes.error.message}`);
39
- const segmentRows = segmentsRes.data ?? [];
40
- // Carrega tasks + projetos referenciados
41
- const taskIds = Array.from(new Set(segmentRows.map((s) => s.task_id)));
42
- const tasksById = new Map();
43
- const projectsById = new Map();
44
- if (taskIds.length > 0) {
45
- const tasksRes = await supabase
46
- .from('tasks')
47
- .select('id, key, title, project_id')
48
- .in('id', taskIds);
49
- if (tasksRes.error)
50
- return errorResult(`Erro ao buscar tarefas: ${tasksRes.error.message}`);
51
- for (const t of tasksRes.data ?? []) {
52
- tasksById.set(t.id, { key: t.key, title: t.title, project_id: t.project_id });
53
- }
54
- const projectIds = Array.from(new Set((tasksRes.data ?? []).map((t) => t.project_id)));
55
- if (projectIds.length > 0) {
56
- const projectsRes = await supabase
57
- .from('projects')
58
- .select('id, name')
59
- .in('id', projectIds);
60
- if (projectsRes.error) {
61
- return errorResult(`Erro ao buscar projetos: ${projectsRes.error.message}`);
62
- }
63
- for (const p of projectsRes.data ?? [])
64
- projectsById.set(p.id, p.name);
65
- }
66
- }
67
- const taskInfo = (taskId) => {
15
+ function taskInfoLookup(tasksById, projectsById) {
16
+ return (taskId) => {
68
17
  const t = tasksById.get(taskId);
69
18
  return {
70
19
  id: taskId,
@@ -73,6 +22,10 @@ export async function handler(_args, ctx) {
73
22
  project_name: t ? projectsById.get(t.project_id) ?? null : null,
74
23
  };
75
24
  };
25
+ }
26
+ /** Monta a resposta de alocação ativa: allocation, task ativa, segmentos e total do dia. Pura. */
27
+ export function formatActiveAllocation(allocation, segmentRows, tasksById, projectsById) {
28
+ const taskInfo = taskInfoLookup(tasksById, projectsById);
76
29
  const segments = segmentRows.map((s) => ({
77
30
  task_allocation_id: s.id,
78
31
  task: taskInfo(s.task_id),
@@ -91,8 +44,7 @@ export async function handler(_args, ctx) {
91
44
  is_overtime: activeSegment.is_overtime,
92
45
  }
93
46
  : null;
94
- const totalSecondsToday = segments.reduce((acc, s) => acc + s.duration_seconds, 0);
95
- return jsonResult({
47
+ return {
96
48
  allocation: {
97
49
  id: allocation.id,
98
50
  start_time: allocation.start_time,
@@ -100,7 +52,48 @@ export async function handler(_args, ctx) {
100
52
  },
101
53
  active_task: activeTask,
102
54
  segments,
103
- total_seconds_today: totalSecondsToday,
104
- });
55
+ total_seconds_today: segments.reduce((acc, s) => acc + s.duration_seconds, 0),
56
+ };
57
+ }
58
+ async function loadTaskAndProjectRefs(supabase, taskIds) {
59
+ const tasksById = new Map();
60
+ const projectsById = new Map();
61
+ if (taskIds.length === 0)
62
+ return { tasksById, projectsById };
63
+ const tasksRes = await supabase.from('tasks').select('id, key, title, project_id').in('id', taskIds);
64
+ if (tasksRes.error)
65
+ return errorResult(`Erro ao buscar tarefas: ${tasksRes.error.message}`);
66
+ for (const t of tasksRes.data ?? [])
67
+ tasksById.set(t.id, { key: t.key, title: t.title, project_id: t.project_id });
68
+ const projectIds = Array.from(new Set((tasksRes.data ?? []).map((t) => t.project_id)));
69
+ if (projectIds.length > 0) {
70
+ const projectsRes = await supabase.from('projects').select('id, name').in('id', projectIds);
71
+ if (projectsRes.error)
72
+ return errorResult(`Erro ao buscar projetos: ${projectsRes.error.message}`);
73
+ for (const p of projectsRes.data ?? [])
74
+ projectsById.set(p.id, p.name);
75
+ }
76
+ return { tasksById, projectsById };
77
+ }
78
+ export async function handler(_args, ctx) {
79
+ const { supabase } = ctx;
80
+ const allocRes = await supabase.from('allocations').select('id, start_time').eq('user_id', ctx.user.id).is('end_time', null).maybeSingle();
81
+ if (allocRes.error)
82
+ return errorResult(`Erro ao buscar alocação ativa: ${allocRes.error.message}`);
83
+ if (!allocRes.data)
84
+ return jsonResult({ allocation: null, active_task: null, segments: [], total_seconds_today: 0 });
85
+ const allocation = allocRes.data;
86
+ const segmentsRes = await supabase
87
+ .from('task_allocations')
88
+ .select('id, task_id, start_time, end_time, is_overtime')
89
+ .eq('allocation_id', allocation.id)
90
+ .order('start_time', { ascending: true });
91
+ if (segmentsRes.error)
92
+ return errorResult(`Erro ao buscar segmentos: ${segmentsRes.error.message}`);
93
+ const segmentRows = segmentsRes.data ?? [];
94
+ const refs = await loadTaskAndProjectRefs(supabase, Array.from(new Set(segmentRows.map((s) => s.task_id))));
95
+ if (isErrorResult(refs))
96
+ return refs;
97
+ return jsonResult(formatActiveAllocation(allocation, segmentRows, refs.tasksById, refs.projectsById));
105
98
  }
106
99
  //# sourceMappingURL=get-active-allocation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-active-allocation.js","sourceRoot":"","sources":["../../src/tools/get-active-allocation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-active-allocation.js","sourceRoot":"","sources":["../../src/tools/get-active-allocation.ts"],"names":[],"mappings":"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"}
@@ -2,24 +2,25 @@ import { z } from 'zod';
2
2
  import { jsonResult, errorResult } from '../lib/tool-result.js';
3
3
  import { fetchProjectContext, ProjectContextError } from '../lib/project-context.js';
4
4
  import { resolveProjectConfig, isErrorResult } from '../lib/require-config.js';
5
+ import { brand } from '../brand.js';
5
6
  const ArgsSchema = z
6
7
  .object({
7
8
  project_id: z.string().uuid().optional(),
8
9
  })
9
10
  .strict();
10
11
  export const definition = {
11
- name: 'nos_get_context',
12
+ name: `${brand.toolPrefix}get_context`,
12
13
  description: 'Retorna o contexto completo do projeto NOS ativo: dados do projeto, repositórios, ' +
13
14
  'sprint ativa, membros e usuário autenticado. Use SEMPRE no início de uma conversa ' +
14
15
  'pra entender em que projeto você está operando. Sem projeto selecionado, use ' +
15
- '`nos_list_projects` + `nos_set_project` antes.',
16
+ `\`${brand.toolPrefix}list_projects\` + \`${brand.toolPrefix}set_project\` antes.`,
16
17
  inputSchema: {
17
18
  type: 'object',
18
19
  properties: {
19
20
  project_id: {
20
21
  type: 'string',
21
22
  format: 'uuid',
22
- description: 'Override do projeto. Se omitido, usa o projeto ativo (nos_set_project) ou o default.',
23
+ description: `Override do projeto. Se omitido, usa o projeto ativo (${brand.toolPrefix}set_project) ou o default.`,
23
24
  },
24
25
  },
25
26
  additionalProperties: false,
@@ -1 +1 @@
1
- {"version":3,"file":"get-context.js","sourceRoot":"","sources":["../../src/tools/get-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE/E,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC;IACN,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;CACzC,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,oFAAoF;QACpF,oFAAoF;QACpF,+EAA+E;QAC/E,gDAAgD;IAClD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,sFAAsF;aACpG;SACF;QACD,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAa,EAAE,GAAgB;IAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,WAAW,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,GAAG,GAAG,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,aAAa,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACpE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;YACvC,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,WAAW,CAAC,oBAAqB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"get-context.js","sourceRoot":"","sources":["../../src/tools/get-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC;IACN,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;CACzC,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,IAAI,EAAE,GAAG,KAAK,CAAC,UAAU,aAAa;IACtC,WAAW,EACT,oFAAoF;QACpF,oFAAoF;QACpF,+EAA+E;QAC/E,KAAK,KAAK,CAAC,UAAU,uBAAuB,KAAK,CAAC,UAAU,sBAAsB;IACpF,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,yDAAyD,KAAK,CAAC,UAAU,4BAA4B;aACnH;SACF;QACD,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAa,EAAE,GAAgB;IAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,WAAW,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,GAAG,GAAG,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,aAAa,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACpE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;YACvC,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,WAAW,CAAC,oBAAqB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;AACH,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { jsonResult, errorResult } from '../lib/tool-result.js';
3
3
  import { resolveProjectConfig, isErrorResult } from '../lib/require-config.js';
4
+ import { brand } from '../brand.js';
4
5
  const ArgsSchema = z
5
6
  .object({
6
7
  task_id: z.string().uuid(),
@@ -8,7 +9,7 @@ const ArgsSchema = z
8
9
  })
9
10
  .strict();
10
11
  export const definition = {
11
- name: 'nos_get_task',
12
+ name: `${brand.toolPrefix}get_task`,
12
13
  description: 'Retorna detalhes completos de uma tarefa: descrição, assignees, checklist, comentários, ' +
13
14
  'histórico recente, repositórios vinculados e labels.',
14
15
  inputSchema: {
@@ -18,7 +19,7 @@ export const definition = {
18
19
  project_id: {
19
20
  type: 'string',
20
21
  format: 'uuid',
21
- description: 'Override do projeto. Se omitido, usa o projeto ativo (nos_set_project) ou o default.',
22
+ description: `Override do projeto. Se omitido, usa o projeto ativo (${brand.toolPrefix}set_project) ou o default.`,
22
23
  },
23
24
  },
24
25
  required: ['task_id'],
@@ -39,54 +40,116 @@ async function fetchProfiles(supabase, userIds) {
39
40
  { full_name: p.full_name, username: p.username, avatar_url: p.avatar_url },
40
41
  ]));
41
42
  }
42
- export async function handler(args, ctx) {
43
- const parsed = ArgsSchema.safeParse(args);
44
- if (!parsed.success) {
45
- return errorResult(`Argumento inválido: ${parsed.error.message}`);
46
- }
47
- const { task_id } = parsed.data;
48
- const cfg = resolveProjectConfig(ctx, parsed.data.project_id);
49
- if (isErrorResult(cfg))
50
- return cfg;
51
- const { supabase } = ctx;
52
- const taskRes = await supabase
53
- .from('tasks')
54
- .select('*')
55
- .eq('id', task_id)
56
- .eq('project_id', cfg.project_id)
57
- .maybeSingle();
58
- if (taskRes.error)
59
- return errorResult(`Erro ao buscar tarefa: ${taskRes.error.message}`);
60
- if (!taskRes.data)
61
- return errorResult('Tarefa não encontrada ou fora do projeto atual.');
62
- const task = taskRes.data;
43
+ /** Coleta os ids de usuário/repo/label referenciados pela task e suas relações. Pura. */
44
+ export function collectRelatedIds(task, rows) {
45
+ const userIds = new Set();
46
+ for (const r of rows.assigneeRows)
47
+ userIds.add(r.user_id);
48
+ for (const c of rows.commentRows)
49
+ userIds.add(c.author_id);
50
+ for (const h of rows.historyRows)
51
+ userIds.add(h.user_id);
52
+ userIds.add(task.reporter_id);
53
+ return {
54
+ userIds: Array.from(userIds),
55
+ repoIds: rows.repoRows.map((r) => r.repository_id),
56
+ labelIds: rows.labelRows.map((l) => l.label_id),
57
+ };
58
+ }
59
+ function formatTaskCore(task, profiles) {
60
+ return {
61
+ id: task.id,
62
+ key: task.key,
63
+ title: task.title,
64
+ description: task.description,
65
+ status: task.status,
66
+ priority: task.priority,
67
+ type: task.type,
68
+ sprint_id: task.sprint_id,
69
+ team: task.team,
70
+ url: task.url,
71
+ branch: task.branch,
72
+ start_date: task.start_date,
73
+ end_date: task.end_date,
74
+ reporter: {
75
+ user_id: task.reporter_id,
76
+ full_name: profiles.get(task.reporter_id)?.full_name ?? null,
77
+ username: profiles.get(task.reporter_id)?.username ?? null,
78
+ },
79
+ created_at: task.created_at,
80
+ updated_at: task.updated_at,
81
+ };
82
+ }
83
+ /** Monta o payload completo de detalhe da task a partir das linhas carregadas + refs resolvidas. Pura. */
84
+ export function formatTaskDetail(task, rows, refs) {
85
+ return {
86
+ task: formatTaskCore(task, refs.profiles),
87
+ assignees: rows.assigneeRows.map((a) => ({
88
+ user_id: a.user_id,
89
+ full_name: refs.profiles.get(a.user_id)?.full_name ?? null,
90
+ username: refs.profiles.get(a.user_id)?.username ?? null,
91
+ avatar_url: refs.profiles.get(a.user_id)?.avatar_url ?? null,
92
+ })),
93
+ checklist: rows.checklistRows.map((c) => ({ id: c.id, text: c.text, checked: c.checked, order: c.order })),
94
+ comments: rows.commentRows.map((c) => ({
95
+ id: c.id,
96
+ content: c.content,
97
+ created_at: c.created_at,
98
+ updated_at: c.updated_at,
99
+ author: {
100
+ user_id: c.author_id,
101
+ full_name: refs.profiles.get(c.author_id)?.full_name ?? null,
102
+ username: refs.profiles.get(c.author_id)?.username ?? null,
103
+ },
104
+ })),
105
+ history: rows.historyRows.map((h) => ({
106
+ id: h.id,
107
+ action: h.action,
108
+ field: h.field,
109
+ old_value: h.old_value,
110
+ new_value: h.new_value,
111
+ created_at: h.created_at,
112
+ user: {
113
+ user_id: h.user_id,
114
+ full_name: refs.profiles.get(h.user_id)?.full_name ?? null,
115
+ username: refs.profiles.get(h.user_id)?.username ?? null,
116
+ },
117
+ })),
118
+ repositories: rows.repoRows.map((r) => ({
119
+ id: r.repository_id,
120
+ name: refs.reposById.get(r.repository_id)?.name ?? null,
121
+ url: refs.reposById.get(r.repository_id)?.url ?? null,
122
+ default_branch: refs.reposById.get(r.repository_id)?.default_branch ?? null,
123
+ })),
124
+ labels: rows.labelRows.map((l) => ({
125
+ id: l.label_id,
126
+ name: refs.labelsById.get(l.label_id)?.name ?? null,
127
+ color: refs.labelsById.get(l.label_id)?.color ?? null,
128
+ })),
129
+ };
130
+ }
131
+ async function loadTaskRelationRows(supabase, taskId) {
63
132
  const [assigneesRes, checklistRes, commentsRes, historyRes, reposRes, labelsRes] = await Promise.all([
64
- supabase.from('task_assignees').select('user_id').eq('task_id', task_id),
133
+ supabase.from('task_assignees').select('user_id').eq('task_id', taskId),
65
134
  supabase
66
135
  .from('task_checklist_items')
67
136
  .select('id, text, checked, order')
68
- .eq('task_id', task_id)
137
+ .eq('task_id', taskId)
69
138
  .order('order', { ascending: true }),
70
139
  supabase
71
140
  .from('task_comments')
72
141
  .select('id, content, created_at, updated_at, author_id')
73
- .eq('task_id', task_id)
142
+ .eq('task_id', taskId)
74
143
  .order('created_at', { ascending: true })
75
144
  .limit(50),
76
145
  supabase
77
146
  .from('task_history')
78
147
  .select('id, action, field, old_value, new_value, created_at, user_id')
79
- .eq('task_id', task_id)
148
+ .eq('task_id', taskId)
80
149
  .order('created_at', { ascending: false })
81
150
  .limit(50),
82
- supabase
83
- .from('task_repositories')
84
- .select('repository_id')
85
- .eq('task_id', task_id),
86
- supabase
87
- .from('task_label_assignments')
88
- .select('label_id')
89
- .eq('task_id', task_id),
151
+ supabase.from('task_repositories').select('repository_id').eq('task_id', taskId),
152
+ supabase.from('task_label_assignments').select('label_id').eq('task_id', taskId),
90
153
  ]);
91
154
  if (assigneesRes.error)
92
155
  return errorResult(`Erro ao buscar assignees: ${assigneesRes.error.message}`);
@@ -100,124 +163,63 @@ export async function handler(args, ctx) {
100
163
  return errorResult(`Erro ao buscar repositórios: ${reposRes.error.message}`);
101
164
  if (labelsRes.error)
102
165
  return errorResult(`Erro ao buscar labels: ${labelsRes.error.message}`);
103
- const assigneeRows = assigneesRes.data ?? [];
104
- const checklistRows = checklistRes.data ?? [];
105
- const commentRows = commentsRes.data ?? [];
106
- const historyRows = historyRes.data ?? [];
107
- const repoRows = reposRes.data ?? [];
108
- const labelRows = labelsRes.data ?? [];
109
- // Coleta ids pra resolver em lote
110
- const userIds = new Set();
111
- for (const r of assigneeRows)
112
- userIds.add(r.user_id);
113
- for (const c of commentRows)
114
- userIds.add(c.author_id);
115
- for (const h of historyRows)
116
- userIds.add(h.user_id);
117
- userIds.add(task.reporter_id);
118
- const repoIds = repoRows.map((r) => r.repository_id);
119
- const labelIds = labelRows.map((l) => l.label_id);
120
- let profiles;
121
- try {
122
- profiles = await fetchProfiles(supabase, Array.from(userIds));
123
- }
124
- catch (err) {
125
- return errorResult(err.message);
126
- }
166
+ return {
167
+ assigneeRows: assigneesRes.data ?? [],
168
+ checklistRows: checklistRes.data ?? [],
169
+ commentRows: commentsRes.data ?? [],
170
+ historyRows: historyRes.data ?? [],
171
+ repoRows: reposRes.data ?? [],
172
+ labelRows: labelsRes.data ?? [],
173
+ };
174
+ }
175
+ async function loadRepoAndLabelRefs(supabase, repoIds, labelIds) {
127
176
  const reposById = new Map();
128
177
  if (repoIds.length > 0) {
129
- const repoFetch = await supabase
130
- .from('repositories')
131
- .select('id, name, url, default_branch')
132
- .in('id', repoIds);
178
+ const repoFetch = await supabase.from('repositories').select('id, name, url, default_branch').in('id', repoIds);
133
179
  if (repoFetch.error)
134
180
  return errorResult(`Erro ao buscar repositórios: ${repoFetch.error.message}`);
135
- for (const r of repoFetch.data ?? []) {
181
+ for (const r of repoFetch.data ?? [])
136
182
  reposById.set(r.id, { name: r.name, url: r.url, default_branch: r.default_branch });
137
- }
138
183
  }
139
184
  const labelsById = new Map();
140
185
  if (labelIds.length > 0) {
141
- const labelFetch = await supabase
142
- .from('task_labels')
143
- .select('id, name, color')
144
- .in('id', labelIds);
186
+ const labelFetch = await supabase.from('task_labels').select('id, name, color').in('id', labelIds);
145
187
  if (labelFetch.error)
146
188
  return errorResult(`Erro ao buscar labels: ${labelFetch.error.message}`);
147
- for (const l of labelFetch.data ?? []) {
189
+ for (const l of labelFetch.data ?? [])
148
190
  labelsById.set(l.id, { name: l.name, color: l.color });
149
- }
150
191
  }
151
- return jsonResult({
152
- task: {
153
- id: task.id,
154
- key: task.key,
155
- title: task.title,
156
- description: task.description,
157
- status: task.status,
158
- priority: task.priority,
159
- type: task.type,
160
- sprint_id: task.sprint_id,
161
- team: task.team,
162
- url: task.url,
163
- branch: task.branch,
164
- start_date: task.start_date,
165
- end_date: task.end_date,
166
- reporter: {
167
- user_id: task.reporter_id,
168
- full_name: profiles.get(task.reporter_id)?.full_name ?? null,
169
- username: profiles.get(task.reporter_id)?.username ?? null,
170
- },
171
- created_at: task.created_at,
172
- updated_at: task.updated_at,
173
- },
174
- assignees: assigneeRows.map((a) => ({
175
- user_id: a.user_id,
176
- full_name: profiles.get(a.user_id)?.full_name ?? null,
177
- username: profiles.get(a.user_id)?.username ?? null,
178
- avatar_url: profiles.get(a.user_id)?.avatar_url ?? null,
179
- })),
180
- checklist: checklistRows.map((c) => ({
181
- id: c.id,
182
- text: c.text,
183
- checked: c.checked,
184
- order: c.order,
185
- })),
186
- comments: commentRows.map((c) => ({
187
- id: c.id,
188
- content: c.content,
189
- created_at: c.created_at,
190
- updated_at: c.updated_at,
191
- author: {
192
- user_id: c.author_id,
193
- full_name: profiles.get(c.author_id)?.full_name ?? null,
194
- username: profiles.get(c.author_id)?.username ?? null,
195
- },
196
- })),
197
- history: historyRows.map((h) => ({
198
- id: h.id,
199
- action: h.action,
200
- field: h.field,
201
- old_value: h.old_value,
202
- new_value: h.new_value,
203
- created_at: h.created_at,
204
- user: {
205
- user_id: h.user_id,
206
- full_name: profiles.get(h.user_id)?.full_name ?? null,
207
- username: profiles.get(h.user_id)?.username ?? null,
208
- },
209
- })),
210
- repositories: repoRows.map((r) => ({
211
- id: r.repository_id,
212
- name: reposById.get(r.repository_id)?.name ?? null,
213
- url: reposById.get(r.repository_id)?.url ?? null,
214
- default_branch: reposById.get(r.repository_id)?.default_branch ?? null,
215
- })),
216
- labels: labelRows.map((l) => ({
217
- id: l.label_id,
218
- name: labelsById.get(l.label_id)?.name ?? null,
219
- color: labelsById.get(l.label_id)?.color ?? null,
220
- })),
221
- });
192
+ return { reposById, labelsById };
193
+ }
194
+ export async function handler(args, ctx) {
195
+ const parsed = ArgsSchema.safeParse(args);
196
+ if (!parsed.success)
197
+ return errorResult(`Argumento inválido: ${parsed.error.message}`);
198
+ const { task_id } = parsed.data;
199
+ const cfg = resolveProjectConfig(ctx, parsed.data.project_id);
200
+ if (isErrorResult(cfg))
201
+ return cfg;
202
+ const { supabase } = ctx;
203
+ const taskRes = await supabase.from('tasks').select('*').eq('id', task_id).eq('project_id', cfg.project_id).maybeSingle();
204
+ if (taskRes.error)
205
+ return errorResult(`Erro ao buscar tarefa: ${taskRes.error.message}`);
206
+ if (!taskRes.data)
207
+ return errorResult('Tarefa não encontrada ou fora do projeto atual.');
208
+ const task = taskRes.data;
209
+ const rows = await loadTaskRelationRows(supabase, task_id);
210
+ if (isErrorResult(rows))
211
+ return rows;
212
+ const { userIds, repoIds, labelIds } = collectRelatedIds(task, rows);
213
+ let profiles;
214
+ try {
215
+ profiles = await fetchProfiles(supabase, userIds);
216
+ }
217
+ catch (err) {
218
+ return errorResult(err.message);
219
+ }
220
+ const refs = await loadRepoAndLabelRefs(supabase, repoIds, labelIds);
221
+ if (isErrorResult(refs))
222
+ return refs;
223
+ return jsonResult(formatTaskDetail(task, rows, { profiles, ...refs }));
222
224
  }
223
225
  //# sourceMappingURL=get-task.js.map