11import * as asana from "asana" ;
22
33import {
4+ type Activity ,
45 type ActivityLink ,
56 ActivityLinkType ,
7+ ActivityMeta ,
68 ActivityType ,
79 type NewActivityWithNotes ,
810 type NewNote ,
9- Uuid ,
11+ type Serializable ,
1012} from "@plotday/twister" ;
1113import type {
1214 Project ,
@@ -74,13 +76,9 @@ export class Asana extends Tool<Asana> implements ProjectTool {
7476 * Request Asana OAuth authorization
7577 */
7678 async requestAuth <
77- TCallback extends ( auth : ProjectAuth , ...args : any [ ] ) => any
78- > (
79- callback : TCallback ,
80- ...extraArgs : TCallback extends ( auth : any , ...rest : infer R ) => any
81- ? R
82- : [ ]
83- ) : Promise < ActivityLink > {
79+ TArgs extends Serializable [ ] ,
80+ TCallback extends ( auth : ProjectAuth , ...args : TArgs ) => any
81+ > ( callback : TCallback , ...extraArgs : TArgs ) : Promise < ActivityLink > {
8482 const asanaScopes = [ "default" ] ;
8583
8684 // Generate opaque token for authorization
@@ -153,16 +151,15 @@ export class Asana extends Tool<Asana> implements ProjectTool {
153151 * Start syncing tasks from an Asana project
154152 */
155153 async startSync <
156- TCallback extends ( task : NewActivityWithNotes , ...args : any [ ] ) => any
154+ TArgs extends Serializable [ ] ,
155+ TCallback extends ( task : NewActivityWithNotes , ...args : TArgs ) => any
157156 > (
158157 options : {
159158 authToken : string ;
160159 projectId : string ;
161160 } & ProjectSyncOptions ,
162161 callback : TCallback ,
163- ...extraArgs : TCallback extends ( task : any , ...rest : infer R ) => any
164- ? R
165- : [ ]
162+ ...extraArgs : TArgs
166163 ) : Promise < void > {
167164 const { authToken, projectId, timeMin } = options ;
168165
@@ -384,7 +381,10 @@ export class Asana extends Tool<Asana> implements ProjectTool {
384381 } ,
385382 author : authorContact ,
386383 assignee : assigneeContact ?? null , // Explicitly set to null for unassigned tasks
387- done : task . completed && task . completed_at ? new Date ( task . completed_at ) : null ,
384+ done :
385+ task . completed && task . completed_at
386+ ? new Date ( task . completed_at )
387+ : null ,
388388 notes,
389389 } ;
390390 }
@@ -393,37 +393,29 @@ export class Asana extends Tool<Asana> implements ProjectTool {
393393 * Update task with new values
394394 *
395395 * @param authToken - Authorization token
396- * @param update - ActivityUpdate with changed fields
396+ * @param activity - The updated activity
397397 */
398- async updateIssue (
399- authToken : string ,
400- update : import ( "@plotday/twister" ) . ActivityUpdate
401- ) : Promise < void > {
398+ async updateIssue ( authToken : string , activity : Activity ) : Promise < void > {
402399 // Extract Asana task GID from meta
403- const source = update . meta ?. source as string | undefined ;
404- const taskGid = source ?. split ( ":" ) . pop ( ) ;
400+ const taskGid = activity . meta ?. taskGid as string | undefined ;
405401 if ( ! taskGid ) {
406- throw new Error ( "Invalid source format for Asana task " ) ;
402+ throw new Error ( "Asana task GID not found in activity meta " ) ;
407403 }
408404
409405 const client = await this . getClient ( authToken ) ;
410406 const updateFields : any = { } ;
411407
412408 // Handle title
413- if ( update . title !== undefined ) {
414- updateFields . name = update . title ;
409+ if ( activity . title !== null ) {
410+ updateFields . name = activity . title ;
415411 }
416412
417413 // Handle assignee
418- if ( update . assignee !== undefined ) {
419- updateFields . assignee = update . assignee ?. id || null ;
420- }
414+ updateFields . assignee = activity . assignee ?. id || null ;
421415
422416 // Handle completion status based on done
423417 // Asana only has completed boolean (no In Progress state)
424- if ( update . done !== undefined ) {
425- updateFields . completed = update . done !== null ;
426- }
418+ updateFields . completed = activity . done !== null ;
427419
428420 // Apply updates if any fields changed
429421 if ( Object . keys ( updateFields ) . length > 0 ) {
@@ -435,17 +427,21 @@ export class Asana extends Tool<Asana> implements ProjectTool {
435427 * Add a comment (story) to an Asana task
436428 *
437429 * @param authToken - Authorization token
438- * @param issueId - Asana task GID
430+ * @param meta - Activity metadata containing taskGid
439431 * @param body - Comment text (markdown not directly supported, plain text)
440432 */
441433 async addIssueComment (
442434 authToken : string ,
443- issueId : string ,
435+ meta : ActivityMeta ,
444436 body : string
445437 ) : Promise < void > {
438+ const taskGid = meta . taskGid as string | undefined ;
439+ if ( ! taskGid ) {
440+ throw new Error ( "Asana task GID not found in activity meta" ) ;
441+ }
446442 const client = await this . getClient ( authToken ) ;
447443
448- await client . tasks . addComment ( issueId , {
444+ await client . tasks . addComment ( taskGid , {
449445 text : body ,
450446 } ) ;
451447 }
0 commit comments