tapd-mcp 1.0.3 → 1.0.5

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.
@@ -143,6 +143,30 @@ export interface Release {
143
143
  modified?: string;
144
144
  [key: string]: string | undefined;
145
145
  }
146
+ export interface Timesheet {
147
+ id: string;
148
+ workspace_id: string;
149
+ entity_type: string;
150
+ entity_id: string;
151
+ owner?: string;
152
+ spentdate?: string;
153
+ timespent?: string;
154
+ memo?: string;
155
+ created?: string;
156
+ modified?: string;
157
+ [key: string]: string | undefined;
158
+ }
159
+ export interface CustomFieldSetting {
160
+ workspace_id?: string;
161
+ entry_type?: string;
162
+ field_name?: string;
163
+ field_type?: string;
164
+ field_label?: string;
165
+ required?: string;
166
+ options?: string;
167
+ is_open?: string;
168
+ [key: string]: string | undefined;
169
+ }
146
170
  export interface StoryChange {
147
171
  id: string;
148
172
  story_id: string;
@@ -163,6 +187,15 @@ export interface WorkspaceUser {
163
187
  user_group_id?: string;
164
188
  [key: string]: string | undefined;
165
189
  }
190
+ /**
191
+ * Upsert a "提测时间:YYYY-MM-DD" line inside a story description.
192
+ * Matches both "提测时间" and "提测日期", tolerates :/: and full-width dates,
193
+ * and works whether the description is plain text or HTML.
194
+ */
195
+ export declare function upsertTestSubmissionLine(description: string, testDate: string): {
196
+ newDesc: string;
197
+ previous?: string;
198
+ };
166
199
  export declare class TapdClient {
167
200
  private apiToken;
168
201
  private baseUrl;
@@ -205,6 +238,85 @@ export declare class TapdClient {
205
238
  categoryId?: string;
206
239
  releaseId?: string;
207
240
  }): Promise<Story>;
241
+ /**
242
+ * Look up a custom-field definition by user-facing label or by API name.
243
+ * `query` matches against (in order): the API name itself (e.g. "custom_field_one"),
244
+ * then the Chinese/English label, then the legacy `field_name` key. Match is
245
+ * case-insensitive, whitespace-trimmed, and both English+Chinese punctuation
246
+ * are normalised so users can type "提测时间" or "提测 时间" or "TestDate".
247
+ *
248
+ * Two data sources are tried, in order:
249
+ * 1. /stories/get_fields_info — covers ALL story fields (system + custom)
250
+ * with localized labels. This is the canonical source for workspaces that
251
+ * use TAPD's "field config" UI. Returns 403 in some workspaces; falls
252
+ * back to source 2.
253
+ * 2. /stories/custom_fields_settings — older endpoint; only returns custom
254
+ * fields and may be empty in workspaces that store labels under (1).
255
+ *
256
+ * Returns null when no field matches; otherwise the raw setting plus the
257
+ * resolved API name (the property you POST to /stories with).
258
+ */
259
+ resolveStoryCustomField(workspaceId: string, query: string, entryType?: string): Promise<(CustomFieldSetting & {
260
+ api_name: string;
261
+ }) | null>;
262
+ /**
263
+ * Fetch the workspace's full story field schema via /stories/get_fields_info.
264
+ * Returns a map { api_name -> { label, html_type, options, readonly } }.
265
+ *
266
+ * Caches the result on disk per workspace (see src/fields-cache.ts) — the
267
+ * schema rarely changes, and skipping the network on every resolve speeds
268
+ * up repeated `tapd_set_story_*` calls noticeably. Pass `forceRefresh: true`
269
+ * after a workspace admin edits the field config.
270
+ *
271
+ * Throws (rather than returning {}) on permission errors so callers can fall
272
+ * back to the legacy custom_fields_settings endpoint.
273
+ */
274
+ getStoryFieldsInfo(workspaceId: string, options?: {
275
+ forceRefresh?: boolean;
276
+ }): Promise<Record<string, {
277
+ label?: string;
278
+ html_type?: string;
279
+ options?: any;
280
+ readonly?: number;
281
+ }>>;
282
+ /**
283
+ * Set a custom field on a story by user-facing field name OR by API name.
284
+ *
285
+ * `field` accepts either:
286
+ * - a label (e.g. "提测时间", "TestDate") — resolved via /stories/custom_fields_settings
287
+ * - an API name (e.g. "custom_field_one") — used directly
288
+ *
289
+ * Returns the updated story plus the resolved field metadata so the caller
290
+ * can confirm what was written.
291
+ */
292
+ setStoryCustomField(workspaceId: string, storyId: string, field: string, value: string): Promise<{
293
+ story: Story;
294
+ field: {
295
+ api_name: string;
296
+ label?: string;
297
+ type?: string;
298
+ };
299
+ previous?: string;
300
+ }>;
301
+ /**
302
+ * Set a story's "提测时间" (ready-for-test / QA handoff date).
303
+ *
304
+ * Resolution order:
305
+ * 1. If `customField` is provided -> write to that exact field.
306
+ * 2. Otherwise resolve "提测时间" / "提测日期" against the workspace's
307
+ * story field schema (/stories/get_fields_info, falling back to
308
+ * /stories/custom_fields_settings) and write into the matching field.
309
+ * 3. Fall back to upserting a `提测时间:YYYY-MM-DD` line in the description.
310
+ */
311
+ setStoryTestSubmissionDate(workspaceId: string, storyId: string, testDate: string, options?: {
312
+ customField?: string;
313
+ }): Promise<{
314
+ story: Story;
315
+ mode: 'custom_field' | 'description';
316
+ field?: string;
317
+ label?: string;
318
+ previous?: string;
319
+ }>;
208
320
  getStoryChanges(workspaceId: string, storyId: string, options?: {
209
321
  limit?: number;
210
322
  page?: number;
@@ -344,6 +456,42 @@ export declare class TapdClient {
344
456
  customField?: string;
345
457
  owner?: string;
346
458
  }): Promise<Attachment>;
459
+ /**
460
+ * TAPD timesheet API expects singular entity_type ("task"/"story"/"bug"),
461
+ * but our MCP tool surface uses plural ("tasks"/"stories"/"bugs") for
462
+ * consistency with comments/attachments. Normalize here.
463
+ */
464
+ private toSingularEntityType;
465
+ listTimesheets(workspaceId: string, options?: {
466
+ entityType?: string;
467
+ entityId?: string;
468
+ owner?: string;
469
+ spentdate?: string;
470
+ startDate?: string;
471
+ endDate?: string;
472
+ limit?: number;
473
+ page?: number;
474
+ }): Promise<Timesheet[]>;
475
+ addTimesheet(workspaceId: string, data: {
476
+ entityType: string;
477
+ entityId: string;
478
+ timespent: string;
479
+ spentdate: string;
480
+ owner?: string;
481
+ memo?: string;
482
+ }): Promise<Timesheet>;
483
+ updateTimesheet(workspaceId: string, timesheetId: string, data: {
484
+ timespent?: string;
485
+ spentdate?: string;
486
+ owner?: string;
487
+ memo?: string;
488
+ }): Promise<Timesheet>;
489
+ deleteTimesheet(workspaceId: string, timesheetId: string): Promise<boolean>;
490
+ listAttachments(workspaceId: string, entityType: 'stories' | 'tasks' | 'bugs', entityId: string, options?: {
491
+ limit?: number;
492
+ page?: number;
493
+ }): Promise<Attachment[]>;
494
+ getCustomFieldsSettings(workspaceId: string, entryType?: string): Promise<CustomFieldSetting[]>;
347
495
  translateStoryStatus(status: string): string;
348
496
  translateTaskStatus(status: string): string;
349
497
  translateBugStatus(status: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"tapd-client.d.ts","sourceRoot":"","sources":["../src/tapd-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tapd-client.d.ts","sourceRoot":"","sources":["../src/tapd-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAkCD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAmBxC;AAYD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAC,CAAyC;IAC3D,OAAO,CAAC,kBAAkB,CAAS;gBAEvB,MAAM,EAAE,UAAU;IAO9B,OAAO,CAAC,eAAe;YAQT,OAAO;IA6Df,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IActF,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,KAAK,EAAE,CAAC;IAeb,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACA,OAAO,CAAC,KAAK,CAAC;IAsBX,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;QACJ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACA,OAAO,CAAC,KAAK,CAAC;IAuBjB;;;;;;;;;;;;;;;;;OAiBG;IACG,uBAAuB,CAC3B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,SAAS,SAAU,GAClB,OAAO,CACN,CAAC,kBAAkB,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,GAC3C,IAAI,CACP;IA2CD;;;;;;;;;;;OAWG;IACG,kBAAkB,CACtB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,GACnC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAkCpG;;;;;;;;;OASG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QACT,KAAK,EAAE,KAAK,CAAC;QACb,KAAK,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IAqEF;;;;;;;;;OASG;IACG,0BAA0B,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GACjC,OAAO,CAAC;QACT,KAAK,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,cAAc,GAAG,aAAa,CAAC;QACrC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IAgDI,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,WAAW,EAAE,CAAC;IAanB,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAalE,SAAS,CACb,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,IAAI,EAAE,CAAC;IAgBZ,UAAU,CACd,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,IAAI,CAAC;IAqBV,UAAU,CACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;QACJ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACA,OAAO,CAAC,IAAI,CAAC;IA6BV,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAa/D,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,GAAG,EAAE,CAAC;IAgBX,SAAS,CACb,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GACA,OAAO,CAAC,GAAG,CAAC;IAsBT,SAAS,CACb,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;QACJ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GACA,OAAO,CAAC,GAAG,CAAC;IAwBT,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAajF,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QACR,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GACA,OAAO,CAAC,SAAS,EAAE,CAAC;IAWjB,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GACA,OAAO,CAAC,SAAS,CAAC;IAgBf,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QACJ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,SAAS,CAAC;IAoBf,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,EACvC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,OAAO,EAAE,CAAC;IAYf,UAAU,CACd,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,EACvC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC;IAiBb,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAa3E,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QACR,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GACA,OAAO,CAAC,OAAO,EAAE,CAAC;IAWf,aAAa,CACjB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GACA,OAAO,CAAC,OAAO,CAAC;IAgBb,aAAa,CACjB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;QACJ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,OAAO,CAAC;IAoBb,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAqBpF,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAehE,gBAAgB,CACpB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,EACxC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAC5E,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7F,OAAO,CAAC,UAAU,CAAC;IA+GtB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAKtB,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GACA,OAAO,CAAC,SAAS,EAAE,CAAC;IAoBjB,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GACA,OAAO,CAAC,SAAS,CAAC;IAiBf,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QACJ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GACA,OAAO,CAAC,SAAS,CAAC;IAgBf,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU3E,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,EACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,UAAU,EAAE,CAAC;IAelB,uBAAuB,CAC3B,WAAW,EAAE,MAAM,EACnB,SAAS,SAAU,GAClB,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAWhC,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAI5C,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAI3C,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAI1C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CA0BhG"}
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { readFile } from 'node:fs/promises';
5
5
  import { basename } from 'node:path';
6
+ import { readFieldsCache, writeFieldsCache } from './fields-cache.js';
6
7
  const STATUS_MAP = {
7
8
  'planning': 'planning',
8
9
  'developing': 'developing',
@@ -32,6 +33,29 @@ const TASK_STATUS_MAP = {
32
33
  'progressing': '进行中',
33
34
  'done': '已完成',
34
35
  };
36
+ /**
37
+ * Upsert a "提测时间:YYYY-MM-DD" line inside a story description.
38
+ * Matches both "提测时间" and "提测日期", tolerates :/: and full-width dates,
39
+ * and works whether the description is plain text or HTML.
40
+ */
41
+ export function upsertTestSubmissionLine(description, testDate) {
42
+ const newLine = `提测时间:${testDate}`;
43
+ const re = /(提测(?:时间|日期))\s*[::]\s*([0-90-9]{4}[-/年.][0-90-9]{1,2}[-/月.][0-90-9]{1,2}日?)/;
44
+ const match = description.match(re);
45
+ if (match) {
46
+ const previous = match[2];
47
+ const newDesc = description.replace(re, newLine);
48
+ return { newDesc, previous };
49
+ }
50
+ if (!description) {
51
+ return { newDesc: `<p>${newLine}</p>` };
52
+ }
53
+ // Looks like HTML (contains a tag) -> prepend a <p>; otherwise prepend text + newline.
54
+ if (/<[^>]+>/.test(description)) {
55
+ return { newDesc: `<p>${newLine}</p>${description}` };
56
+ }
57
+ return { newDesc: `${newLine}\n${description}` };
58
+ }
35
59
  const BUG_STATUS_MAP = {
36
60
  'new': '新建',
37
61
  'in_progress': '接受/处理',
@@ -59,14 +83,17 @@ export class TapdClient {
59
83
  }
60
84
  return `Bearer ${this.apiToken}`;
61
85
  }
62
- async request(method, endpoint, params) {
86
+ async request(method, endpoint, params, options) {
63
87
  const url = new URL(endpoint, this.baseUrl);
88
+ const keepEmpty = new Set(options?.keepEmpty || []);
64
89
  const filteredParams = {};
65
90
  if (params) {
66
91
  for (const [key, value] of Object.entries(params)) {
67
- if (value !== undefined && value !== null && value !== '') {
68
- filteredParams[key] = String(value);
69
- }
92
+ if (value === undefined || value === null)
93
+ continue;
94
+ if (value === '' && !keepEmpty.has(key))
95
+ continue;
96
+ filteredParams[key] = String(value);
70
97
  }
71
98
  }
72
99
  const headers = {
@@ -89,11 +116,12 @@ export class TapdClient {
89
116
  }
90
117
  if (!response.ok) {
91
118
  const text = await response.text();
92
- throw new Error(`TAPD API error: ${response.status} ${response.statusText} - ${text}`);
119
+ throw new Error(`TAPD API error [${endpoint}]: HTTP ${response.status} ${response.statusText} - ${text}`);
93
120
  }
94
121
  const data = await response.json();
95
122
  if (data.status !== 1) {
96
- throw new Error(`TAPD API error: ${data.info || 'Unknown error'}`);
123
+ const info = data.info || data.message || 'Unknown error';
124
+ throw new Error(`TAPD API error [${endpoint}]: ${info}`);
97
125
  }
98
126
  // Normalize response: POST returns {data: {Story: ...}}, GET returns {data: [{Story: ...}]}
99
127
  // Convert single object to array format for consistency
@@ -167,6 +195,220 @@ export class TapdClient {
167
195
  }
168
196
  return response.data[0].Story;
169
197
  }
198
+ /**
199
+ * Look up a custom-field definition by user-facing label or by API name.
200
+ * `query` matches against (in order): the API name itself (e.g. "custom_field_one"),
201
+ * then the Chinese/English label, then the legacy `field_name` key. Match is
202
+ * case-insensitive, whitespace-trimmed, and both English+Chinese punctuation
203
+ * are normalised so users can type "提测时间" or "提测 时间" or "TestDate".
204
+ *
205
+ * Two data sources are tried, in order:
206
+ * 1. /stories/get_fields_info — covers ALL story fields (system + custom)
207
+ * with localized labels. This is the canonical source for workspaces that
208
+ * use TAPD's "field config" UI. Returns 403 in some workspaces; falls
209
+ * back to source 2.
210
+ * 2. /stories/custom_fields_settings — older endpoint; only returns custom
211
+ * fields and may be empty in workspaces that store labels under (1).
212
+ *
213
+ * Returns null when no field matches; otherwise the raw setting plus the
214
+ * resolved API name (the property you POST to /stories with).
215
+ */
216
+ async resolveStoryCustomField(workspaceId, query, entryType = 'story') {
217
+ const norm = (s) => (s || '').replace(/\s+/g, '').toLowerCase();
218
+ const target = norm(query);
219
+ try {
220
+ const info = await this.getStoryFieldsInfo(workspaceId);
221
+ for (const [apiName, def] of Object.entries(info)) {
222
+ const label = def.label || '';
223
+ if (norm(apiName) === target || norm(label) === target) {
224
+ return {
225
+ api_name: apiName,
226
+ field_name: apiName,
227
+ field_label: label,
228
+ field_type: def.html_type,
229
+ };
230
+ }
231
+ }
232
+ }
233
+ catch {
234
+ // fall through to legacy endpoint
235
+ }
236
+ const settings = await this.getCustomFieldsSettings(workspaceId, entryType);
237
+ for (const f of settings) {
238
+ const apiName = f.custom_field ||
239
+ f.field_name ||
240
+ f.name ||
241
+ '';
242
+ const label = f.field_label || f.label || f.cn_name || '';
243
+ const enName = f.en_name || f.english_name || '';
244
+ if (norm(apiName) === target ||
245
+ norm(label) === target ||
246
+ norm(enName) === target ||
247
+ norm(f.field_name) === target) {
248
+ return { ...f, api_name: apiName };
249
+ }
250
+ }
251
+ return null;
252
+ }
253
+ /**
254
+ * Fetch the workspace's full story field schema via /stories/get_fields_info.
255
+ * Returns a map { api_name -> { label, html_type, options, readonly } }.
256
+ *
257
+ * Caches the result on disk per workspace (see src/fields-cache.ts) — the
258
+ * schema rarely changes, and skipping the network on every resolve speeds
259
+ * up repeated `tapd_set_story_*` calls noticeably. Pass `forceRefresh: true`
260
+ * after a workspace admin edits the field config.
261
+ *
262
+ * Throws (rather than returning {}) on permission errors so callers can fall
263
+ * back to the legacy custom_fields_settings endpoint.
264
+ */
265
+ async getStoryFieldsInfo(workspaceId, options) {
266
+ if (!options?.forceRefresh) {
267
+ const cached = await readFieldsCache(workspaceId, 'story');
268
+ if (cached?.data)
269
+ return cached.data;
270
+ }
271
+ const url = new URL('/stories/get_fields_info', this.baseUrl);
272
+ url.search = new URLSearchParams({ workspace_id: workspaceId }).toString();
273
+ const res = await fetch(url.toString(), {
274
+ method: 'GET',
275
+ headers: {
276
+ Authorization: this.buildAuthHeader(),
277
+ Accept: 'application/json',
278
+ 'User-Agent': 'TAPD-MCP-Server/1.0',
279
+ },
280
+ });
281
+ if (!res.ok) {
282
+ throw new Error(`get_fields_info HTTP ${res.status} ${res.statusText}`);
283
+ }
284
+ const j = await res.json();
285
+ if (j.status !== 1) {
286
+ throw new Error(`get_fields_info status=${j.status} info=${j.info || 'unknown'}`);
287
+ }
288
+ const data = j.data || {};
289
+ try {
290
+ await writeFieldsCache(workspaceId, 'story', data);
291
+ }
292
+ catch {
293
+ // cache write failure is non-fatal; the network result is still returned
294
+ }
295
+ return data;
296
+ }
297
+ /**
298
+ * Set a custom field on a story by user-facing field name OR by API name.
299
+ *
300
+ * `field` accepts either:
301
+ * - a label (e.g. "提测时间", "TestDate") — resolved via /stories/custom_fields_settings
302
+ * - an API name (e.g. "custom_field_one") — used directly
303
+ *
304
+ * Returns the updated story plus the resolved field metadata so the caller
305
+ * can confirm what was written.
306
+ */
307
+ async setStoryCustomField(workspaceId, storyId, field, value) {
308
+ const looksLikeApiName = /^custom_field(?:_[a-z]+|_\d+)?$/i.test(field);
309
+ let apiName;
310
+ let label;
311
+ let type;
312
+ if (looksLikeApiName) {
313
+ apiName = field;
314
+ }
315
+ else {
316
+ const resolved = await this.resolveStoryCustomField(workspaceId, field);
317
+ if (!resolved) {
318
+ let available = '';
319
+ try {
320
+ const info = await this.getStoryFieldsInfo(workspaceId);
321
+ available = Object.entries(info)
322
+ .filter(([, v]) => !v.readonly)
323
+ .map(([k, v]) => {
324
+ const l = v.label || '';
325
+ return l ? `${k} (${l})` : k;
326
+ })
327
+ .join(', ');
328
+ }
329
+ catch {
330
+ const settings = await this.getCustomFieldsSettings(workspaceId, 'story');
331
+ available = settings
332
+ .map(f => {
333
+ const a = f.custom_field || f.field_name || f.name || '?';
334
+ const l = f.field_label || f.label || '';
335
+ return l ? `${a} (${l})` : a;
336
+ })
337
+ .join(', ');
338
+ }
339
+ throw new Error(`Field "${field}" not found in workspace ${workspaceId}. ` +
340
+ (available ? `Available: ${available}` : 'No fields are defined for stories.'));
341
+ }
342
+ apiName = resolved.api_name;
343
+ label = resolved.field_label || resolved.label;
344
+ type = resolved.field_type;
345
+ }
346
+ if (!apiName) {
347
+ throw new Error(`Could not resolve API name for custom field "${field}"`);
348
+ }
349
+ const before = await this.getStory(workspaceId, storyId, `id,name,${apiName}`);
350
+ if (!before)
351
+ throw new Error(`Story ${storyId} not found`);
352
+ const previous = before[apiName];
353
+ const response = await this.request('POST', '/stories', {
354
+ workspace_id: workspaceId,
355
+ id: storyId,
356
+ [apiName]: value,
357
+ }, { keepEmpty: [apiName] });
358
+ if (!response.data || response.data.length === 0) {
359
+ throw new Error(`Failed to set ${apiName}: no data returned`);
360
+ }
361
+ return {
362
+ story: response.data[0].Story,
363
+ field: { api_name: apiName, label, type },
364
+ previous,
365
+ };
366
+ }
367
+ /**
368
+ * Set a story's "提测时间" (ready-for-test / QA handoff date).
369
+ *
370
+ * Resolution order:
371
+ * 1. If `customField` is provided -> write to that exact field.
372
+ * 2. Otherwise resolve "提测时间" / "提测日期" against the workspace's
373
+ * story field schema (/stories/get_fields_info, falling back to
374
+ * /stories/custom_fields_settings) and write into the matching field.
375
+ * 3. Fall back to upserting a `提测时间:YYYY-MM-DD` line in the description.
376
+ */
377
+ async setStoryTestSubmissionDate(workspaceId, storyId, testDate, options) {
378
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(testDate)) {
379
+ throw new Error(`Invalid test_date: "${testDate}". Expected YYYY-MM-DD.`);
380
+ }
381
+ if (options?.customField) {
382
+ const result = await this.setStoryCustomField(workspaceId, storyId, options.customField, testDate);
383
+ return {
384
+ story: result.story,
385
+ mode: 'custom_field',
386
+ field: result.field.api_name,
387
+ label: result.field.label,
388
+ previous: result.previous,
389
+ };
390
+ }
391
+ for (const candidate of ['提测时间', '提测日期']) {
392
+ const resolved = await this.resolveStoryCustomField(workspaceId, candidate);
393
+ if (resolved && resolved.api_name) {
394
+ const result = await this.setStoryCustomField(workspaceId, storyId, resolved.api_name, testDate);
395
+ return {
396
+ story: result.story,
397
+ mode: 'custom_field',
398
+ field: result.field.api_name,
399
+ label: result.field.label,
400
+ previous: result.previous,
401
+ };
402
+ }
403
+ }
404
+ const before = await this.getStory(workspaceId, storyId, 'id,name,description');
405
+ if (!before)
406
+ throw new Error(`Story ${storyId} not found`);
407
+ const oldDesc = before.description || '';
408
+ const { newDesc, previous } = upsertTestSubmissionLine(oldDesc, testDate);
409
+ const updated = await this.updateStory(workspaceId, storyId, { description: newDesc });
410
+ return { story: updated, mode: 'description', previous };
411
+ }
170
412
  async getStoryChanges(workspaceId, storyId, options) {
171
413
  const response = await this.request('GET', '/story_changes', {
172
414
  workspace_id: workspaceId,
@@ -555,6 +797,93 @@ export class TapdClient {
555
797
  filename: name,
556
798
  };
557
799
  }
800
+ // ==================== Timesheet APIs ====================
801
+ /**
802
+ * TAPD timesheet API expects singular entity_type ("task"/"story"/"bug"),
803
+ * but our MCP tool surface uses plural ("tasks"/"stories"/"bugs") for
804
+ * consistency with comments/attachments. Normalize here.
805
+ */
806
+ toSingularEntityType(entityType) {
807
+ if (!entityType)
808
+ return entityType;
809
+ return entityType.endsWith('s') ? entityType.slice(0, -1) : entityType;
810
+ }
811
+ async listTimesheets(workspaceId, options) {
812
+ const params = {
813
+ workspace_id: workspaceId,
814
+ entity_type: this.toSingularEntityType(options?.entityType),
815
+ entity_id: options?.entityId,
816
+ owner: options?.owner,
817
+ limit: options?.limit || 30,
818
+ page: options?.page || 1,
819
+ };
820
+ if (options?.startDate || options?.endDate) {
821
+ // TAPD supports spentdate[_gte]/[_lte] for range queries
822
+ if (options.startDate)
823
+ params['spentdate[_gte]'] = options.startDate;
824
+ if (options.endDate)
825
+ params['spentdate[_lte]'] = options.endDate;
826
+ }
827
+ else if (options?.spentdate) {
828
+ params.spentdate = options.spentdate;
829
+ }
830
+ const response = await this.request('GET', '/timesheets', params);
831
+ return (response.data || []).map(item => item.Timesheet);
832
+ }
833
+ async addTimesheet(workspaceId, data) {
834
+ const response = await this.request('POST', '/timesheets', {
835
+ workspace_id: workspaceId,
836
+ entity_type: this.toSingularEntityType(data.entityType),
837
+ entity_id: data.entityId,
838
+ timespent: data.timespent,
839
+ spentdate: data.spentdate,
840
+ owner: data.owner,
841
+ memo: data.memo,
842
+ });
843
+ if (!response.data || response.data.length === 0) {
844
+ throw new Error('Failed to add timesheet: no data returned');
845
+ }
846
+ return response.data[0].Timesheet;
847
+ }
848
+ async updateTimesheet(workspaceId, timesheetId, data) {
849
+ const response = await this.request('POST', '/timesheets/update', {
850
+ workspace_id: workspaceId,
851
+ id: timesheetId,
852
+ timespent: data.timespent,
853
+ spentdate: data.spentdate,
854
+ owner: data.owner,
855
+ memo: data.memo,
856
+ });
857
+ if (!response.data || response.data.length === 0) {
858
+ throw new Error('Failed to update timesheet: no data returned');
859
+ }
860
+ return response.data[0].Timesheet;
861
+ }
862
+ async deleteTimesheet(workspaceId, timesheetId) {
863
+ await this.request('POST', '/timesheets/delete', {
864
+ workspace_id: workspaceId,
865
+ id: timesheetId,
866
+ });
867
+ return true;
868
+ }
869
+ // ==================== Attachment List API ====================
870
+ async listAttachments(workspaceId, entityType, entityId, options) {
871
+ // TAPD /attachments uses singular type for filter
872
+ const tapdType = entityType.endsWith('s') ? entityType.slice(0, -1) : entityType;
873
+ const response = await this.request('GET', '/attachments', {
874
+ workspace_id: workspaceId,
875
+ entry_type: tapdType,
876
+ entry_id: entityId,
877
+ limit: options?.limit || 30,
878
+ page: options?.page || 1,
879
+ });
880
+ return (response.data || []).map(item => item.Attachment).filter(Boolean);
881
+ }
882
+ // ==================== Custom Fields Settings API ====================
883
+ async getCustomFieldsSettings(workspaceId, entryType = 'story') {
884
+ const response = await this.request('GET', '/stories/custom_fields_settings', { workspace_id: workspaceId, entry_type: entryType });
885
+ return (response.data || []).map(item => item.CustomFieldSetting).filter(Boolean);
886
+ }
558
887
  // ==================== Utility Methods ====================
559
888
  translateStoryStatus(status) {
560
889
  return STORY_STATUS_MAP[status] || status;