
    q%j                    r   d Z ddlmZ ddlZddlmZmZmZ ddlmZ ddl	m
Z
 ddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZ  ej,                  d      Zdddddddddddddg ddddddddgdddddddddg d d!dd"d#dd$d%dd&d'ddd(ddd)ddg d*d+d,d-gddd.d/dd0did0didd1dd2d%dd3d4di d%dd5d6dd7d8d9did%dd:d;dd"d<dd8d=dd>d%dd?d@ddAd"dBdid%ddCdDddEgddFdddGdddHddIdJddKdLddMd"dNdid%dg
ZdqdOZdrdPZdsdtdQZdudRZdvdSZdvdTZdvdUZdvdVZ dvdWZ!dvdXZ"dvdYZ#dvdZZ$dvd[Z%dvd\Z&dwd]Z'dvd^Z(dvd_Z)dvd`Z*dvdaZ+dvdbZ,dvdcZ-dvddZ.dvdeZ/dvdfZ0dvdgZ1i deded&edhe+die,d.e d3e"d5e!d:e#d?e$dKe&dCe%dje(dke)dle*dme-dne.e/e0e1doZ2dxdpZ3y)yu  
庫柏(Cooper)的工具集(階段 7-tools)。

這些是 Cooper 在對話中實際可以「執行」的動作 — 不是只能講,還能做。
透過 Anthropic Claude 的 tool use API 呼叫。

提供工具:
  - create_task         建立任務
  - list_tasks          查任務
  - update_task_status  改任務狀態(完成 / 進行中 / 取消)
  - delete_task         刪任務
  - get_team_members    取得團隊成員清單(給 LLM 知道誰可以指派)

設計重點:
  1. 每個工具回傳的 dict 直接 json.dumps 給 Claude 看,結構要對 LLM 友善
  2. 失敗用 {"error": "..."} 回,Claude 會自然解讀 + 跟使用者解釋
  3. 不 raise,也不靜默吞;失敗訊息要具體
  4. 寫入操作會記 AgentActivity,讓「庫柏動態」面板看得到
    )annotationsN)datedatetimetimezone)Any)UUID)or_select)AsyncSessionLocal)AgentActivity)TaskUserz
coba.toolscreate_tasku   建立一個新任務在團隊的行程規畫系統。當使用者說「幫某人建任務」、「把 X 加到任務」、「派 Y 給阿綠」這類明確命令時用。成功會回傳 task_id 跟細節。objectstringu)   任務標題,動詞開頭,15-50 字最好)typedescriptionu|   負責人的 display_name(必須跟團隊成員實際名字一致;先用 get_team_members 確認)。沒指定就空字串。ux   截止日期 YYYY-MM-DD。沒指定就 null。今天用今天日期。「明天/週三/下週」自己換算成日期。lowmediumhighurgentuG   預設 medium。看到「急」「緊」「重要」拉 high 或 urgent)r   enumr   u   任務細節說明,可選titleassignee_namedue_datepriorityr   r   )r   
propertiesrequired)namer   input_schema
list_tasksu   查詢任務清單。當使用者問「我有什麼任務」、「阿綠的任務」、「最近建了什麼」、「進行中的任務」時用。u$   篩選負責人。空字串 = 不篩)todoin_progressreviewdone	cancelledanyu'   篩選狀態。'any' 或省略 = 全部integeru#   最多回幾筆,預設 10,最多 50)r   statuslimit)r   r    update_task_statusu   更新任務狀態。當使用者說「X 任務完成」、「Y 在做了」、「Z 取消」時用。用 task_id_prefix(8 字)或 title_keyword 找任務。u@   任務 UUID 前 8 字(從 list_tasks 回傳的 id 取),最精確u3   或用任務標題關鍵字模糊找(沒 id 才用)r%   r&   r'   r(   r)   )r   r   )task_id_prefixtitle_keyword
new_statusr2   delete_taskuX   軟刪任務(可恢復)。使用者說「刪掉 X」、「取消那個任務」時用。r   u   為什麼刪(audit 用))r0   r1   reasonget_team_membersu]   取得團隊全部成員的 display_name 清單。在指派任務前用,確認名字拼對。share_dashboard_linku  給對方「工作台永久網址」+ 加到主畫面教學(用密碼或 Face ID 解鎖手機 = 免登)。適用情境:任何人問「工作台在哪」「我要進去看任務」「給我連結」「dashboard 網址」。回應時直接貼永久 URL + 簡短教學「加到主畫面以後免登」。可選參數 quick_login=true:額外多給一個 30 分鐘一次性 magic link,只用在「對方密碼忘了 / 緊急要立刻進不想登入」的場景。一般情況不用。quick_loginbooleanuM   true = 多給一個 30 分鐘一次性免密碼連結(緊急用),預設 falselist_assignment_statusu   列出最近 N 小時(預設 24)系統「自動建出」的任務 + 認領狀態(誰接了 / 誰還沒接)。用在使用者問「最近派的任務誰接了?」「有誰還沒回覆?」「上週派工狀態」回傳每筆:title / assignee / status / accepted(true/false) / accepted_at。u%   回看幾小時(預設 24,最大 168)u*   只看當前頻道(預設 false 看全部))hourschannel_onlyget_team_completion_rateu   列團隊每個成員「本週」的任務完成率 — 完成數 / 總數 + %。用在使用者問「團隊本週進度」「誰最忙」「KPI」「完成率」。回傳每人 {name, total, done, percent}。daysu   回看天數(預設 7 = 本週)save_reflectionu  把一段話存進「體悟 / 復盤」紀錄(寫進 reflection_note,**不會建任務、不會出現在任務看板**)。使用情境(必用此工具,不准用 create_task):  • 使用者明確說『記錄起來 / 記下 / 存起來』而內容是反思類(覆盤、教訓、學到、反省)  • 使用者打『覆盤』『體悟』『反省』『教訓』『學到』開頭的訊息  • 訊息內容是『下次要 X』『以後要記得 Y』這種自我提醒  • 訊息是事後的反思、洞察、心得,不是要 todo 的事項存進去後系統自動跑重複偵測,週六覆盤也會撈出來。你回應簡短:「✓ 記下來了」或「✓ 兩條都記了」就好,不要碎念。contentu,   要存的完整內容(原文或整理過的)u   12 字內摘要(選填)uK   技術 / 客戶 / 團隊 / 自我管理 / 流程 / 商業 / 學習 / 其他)r?   summarytag)r   r!   r    list_recent_reflectionsuF  列過去 N 小時(預設 168 = 一週)群組裡分享的「體悟 / 反思 / 心得」紀錄,由系統自動分類抓出。用在使用者問「最近大家有什麼學到 / 思考 / 體悟」、「上週的反思整理一下」、「我們團隊最近覺得什麼最重要」。回傳每筆 {created_at, by, summary, raw}。r:   u$   回看小時數(預設 168 = 一週)c           	     \  K   |sy| j                  t        t              j                  t        j                  |k(  t        j
                  j                  d                   d{   j                         }|r|S | j                  t        t              j                  t        j                  j                  |      t        j
                  j                  d      t        j                  j                  d                   d{   j                         j                         }|S 7 7 $w)u<   模糊比對成員名稱(支援部分相符,優先 exact)。NT)executer
   r   wheredisplay_name
deleted_atis_scalar_one_or_nonecontains	is_activescalarsfirst)dbr"   us      ;/volume1/homes/robertsu/coba/app/app/services/coba_tools.py_find_user_by_namerQ      s     zzt4,,4doo6I6I$6OP 
  	zzt&&t,OO%NNt$	
 
 wy  H

s%   A#D,%D(&BD,D*#D,*D,c                  K   |r| j                  t        t              j                  t        j                  j                  d             j                  t        j                  j                               j                  d             d {   j                         j                         }|j                         j                  dd      }|D ]H  }t        |j                        j                  dd      j                         j!                  |      sF|c S  |r| j                  t        t              j                  t        j"                  j%                  |      t        j                  j                  d             j                  t        j                  j                                      d {   j                         j'                         }|S y 7 J7 &w)N   - )rD   r
   r   rE   rG   rH   order_by
created_atdescr-   rL   alllowerreplacestrid
startswithr   rJ   rM   )rN   r0   r1   	all_tasksprefixts         rP   
_find_taskrb     sW     ::4Lt22489Xdoo**,-U3Z
 
 79SSU	 	
  %%'//R8A144y  b)//1<<VD  ::4L

##M2##D) ht++-.	
 

 79UUW 	
 #

s,   BGGBGBG3G4$GGc           	     >  K   	 t               4 d {   }|j                  t        | |||             |j                          d {    d d d       d {    y 7 K7 7 	# 1 d {  7  sw Y   y xY w# t        $ r t
        j                  d       Y y w xY ww)Nactivity_typeuser_idr@   extrazlog activity failed)r   addr   commit	Exceptionlogger	exception)re   r@   rf   rg   rN   s        rP   _logrm     s     
0$&&"FF=+	  ))+ '&&  '&&&  0./0s   BA9 AA9 2A$A 	A$A9 A"A9 BA9  A$"A9 $A6*A-+A62A9 5B6A9 9BBBBc                   K   	 ddl m} |j                  d| d|       d{    y7 # t        $ r t        j                  d|        Y yw xY ww)u   工具改完 DB 後 push WS 事件,前端對應 view 自動 refresh,不用 F5。

    entity: 'tasks' / 'reflections' / 'meetings' / 'users'
    extra:  附加資訊(例:task_id, action='create'/'update'/'delete')
    r   )managerdata_changed)r   entityNz'broadcast data_changed failed entity=%s)app.core.ws_managerro   	broadcastrj   rk   rl   )rq   rg   
ws_managers      rP   _broadcast_data_changedru   -  s_     L="""$
 $
  	 	
  LBFKLs1   A+ )+ A+ A
AAAc           
       K   | j                  d      xs dj                         }|sddiS t        |      dkD  r|d d }t               4 d {   }d }d }| j                  d      xs dj                         }|rIt	        ||       d {   }|r|j
                  }|j                  }nd| dd	d
cd d d       d {    S d }| j                  d      }	|	r%	 t        j                  |	d      j                         }| j                  d      xs dj                         }
|
dvrd}
t        || j                  d      xs d |
|||d      }|j                  |       |j                          d {    |j!                  |       d {    t#        |j
                        }d d d       d {    t%        dd| |dd       d {    d|d d |||xs dr|j'                         nd 
ddS 7 7 n7 =# t        t        f$ r dd|	dicY cd d d       d {  7   S w xY w7 7 7 # 1 d {  7  sw Y   xY w7 {w)Nr   rU   erroru   title 是必填rS   r   u   找不到團隊成員「   」u$   用 get_team_members 看正確名字)rw   hintr   z%Y-%m-%du2   due_date 格式錯誤(期望 YYYY-MM-DD,給的是 )r   r   r   r   r%   )r   r   r   r   assignee_id
created_byr,   task_create_autou   庫柏建任務:	tool_call)task_idr   viare   r@   rf   rg   T   u	   未指派)successtask_id_shorttask_id_fullr   assigneer   r   r,   )getstriplenr   rQ   r]   rF   r   strptimer   
ValueError	TypeErrorrZ   r   rh   ri   refreshr\   rm   	isoformat)argsrequester_idr   rN   r{   assignee_name_actualr   rO   r   due_strr   taskr   s                rP   tool_create_taskr   >  sv    XXg$"++-E*++
5zCds ""b#/28b??A(];;Add'(~~$  8cJB #""" ((:&d#,,WjAFFH HHZ(4H;;=>>H/74##
 	tiikjjdgg,S #"V ("5'*1
		 	 	  !(7K,4H&&($	 	m # < #, 	* d#UV]U``a!bcc/ #"",d" 	Q #"""V	s   AI
G5I
9H3
G8'H32I
>G;?I
H3$G>>A2H30H-1H3	H/
H3#I
.H1/I
I)I
8H3;I
>H*H3I
"H%#I
)H**H3/H31I
3I9H<:II
c                  K   t               4 d {   }t        t              j                  t        j                  j                  d             }| j                  d      xs dj                         }|dv r"|j                  t        j                  |k(        }| j                  d      xs dj                         }d }|rit        ||       d {   }|r9|j                  t        j                  |j                  k(        }|j                  }nd| dg dcd d d       d {    S t        t        d	t!        | j                  d
      xs d            d      }|j#                  t        j$                  j'                               j)                  |      }|j+                  |       d {   j-                         j/                         }	|	D 
ch c]  }
|
j                  s|
j                   }}
i }|r|j+                  t        t0              j                  t0        j                  j3                  |                   d {   j-                         j/                         }|D ci c]  }|j                  |j                   }}d d d       d {    dk7  r|nddt5        	      |	D 
cg c]  }
t7        |
j                        d d |
j8                  |
j                  |
j:                  |
j<                  r|
j<                  j?                         nd |
j                  rj                  |
j                        nd d c}
dS 7 77 {7 *7 c c}
w 7 c c}w 7 # 1 d {  7  sw Y   xY wc c}
w w)Nr,   r*   r/   r   rU   u   找不到「rx   )rw   tasks   r-   
   2   rY   )r,   r   r   )id_shortr   r,   r   r   r   )filtercountr   ) r   r
   r   rE   rG   rH   r   rZ   r,   r   rQ   r{   r]   rF   minmaxintrV   rW   rX   r-   rD   rL   rY   r   in_r   r\   r   r   r   r   )r   r   rN   stmtstr   assignee_filterrO   r-   r   ra   assignee_idsassignee_mapuserss                 rP   tool_list_tasksr     s     ""bd|!!$//"5"5d";<hhx )E002GG::dkkR/0D/28b??A(];;Azz$"2"2add":;"#..#/c!BRP #""" C3txx06B78"=}}T__1134::5Azz$''002668 05Fu!uF::t""477;;|#<= wy  ;@@%QADD!..0%L@9 #"@ %KbU'
 U 

   IbqM((JJ67jjAJJ002d?@}}L,,Q]];RV 

 = # < #& ( G A9 #"""H

s   M=MM=B;M#MAM#M=$M%M=*BM#,M-$M#M#M1AM#M$M#)MM#	M=M!M=2BM8M=M#M=M#M#M#!M=#M5)M,*M51M=c           
       K   | j                  d      xs dj                         }|dvrdd|iS t               4 d {   }t        || j                  d      | j                  d             d {   }|ddicd d d       d {    S |j                  }||_        |d	k(  r)t        j                  t        j                        |_	        nd |_	        |j                          d {    |j                  }t        |j                        }d d d       d {    t        d
d d d| |||dd       d {    d|d d |||dS 7 7 7 7 l7 =# 1 d {  7  sw Y   MxY w7 /w)Nr2   rU   r/   rw   uF   new_status 必須是 todo/in_progress/review/done/cancelled,給的是 r0   r1   ;   找不到任務(用 task_id_prefix 8 字 或 title_keyword)r(   r}   u   庫柏改狀態 : u    → r~   )r   
old_statusr2   r   r   Tr   )r   r   r   r   r2   )r   rZ   r   rb   r,   r   nowr   utccompleted_atri   r   r\   r]   rm   )r   r   r2   rN   r   r   r   tids           rP   tool_update_task_statusr     su    ((<(.B557JOOablaopqq ""bDHH-=$>@YZZ<Z[ #"" [[
  (X\\ :D $Diik

$''l #" ("5'J<uZLIZzZef	   Ra   ) #Z # 	 #"""s   =E1E E1/E2E3	E<E1E	E1AE)E*%EE1E$E1?E/ E1EE1EE1E, E#!E,(E1c           	     b  K   t               4 d {   }t        || j                  d      | j                  d             d {   }|ddicd d d       d {    S |j                  }t	        |j
                        }t        j                  t        j                        |_
        d|_        |j                          d {    d d d       d {    t        dd || j                  d      d	d
       d {    d|d d |dS 7 7 7 7 P7 B# 1 d {  7  sw Y   RxY w7 ,w)Nr0   r1   rw   u   找不到任務r)   task_cancelu   庫柏刪任務:r4   r~   )r   r4   r   r   Tr   )r   r   r   )r   rb   r   r   r\   r]   r   r   r   r   rG   r,   ri   rm   )r   r   rN   r   r   r   s         rP   tool_delete_taskr     s     ""bDHH-=$>@YZZ<./ #"" 

$''l",,x||4!iik #" #"5'*();KP	   c"1gFF! #Z # 	 #"""s   D/DD//DD	DD/DD/ A#DDDD/D,D/ D-D/DD/DD/D*D!D*&D/c                   K   d}t        | j                  d            }|dz   dd}|r|ddlm}  ||      |d<   d	|d
<   d|d<   |S w)u   預設給「永久工作台 URL」+ 加到主畫面說明。

    參數 quick_login=true(可選):多回一個 30 分鐘 magic link 給「沒空登入、要立刻進」的場景。
    z$https://cooper-nas.taila49e28.ts.netr7   /u!  這是工作台永久網址。第一次:打開 → 用 email + 密碼登一次 → iPhone Safari 點底部「分享」→「加入主畫面」(Android Chrome:右上「⋮」→「安裝應用程式」)之後從手機桌面 icon 開,Face ID 解鎖手機後直接進系統,永遠免登入。)permanent_urlnoter   )generate_magic_linkquick_login_linki  quick_login_valid_secondsuH   緊急免密碼進入(30 分鐘一次性,密碼忘了 / 急著看才用)quick_login_note)boolr   app.services.magic_linkr   )r   r   base_urlquickresultr   s         rP   tool_share_dashboard_linkr     sl     
 6H-()E!CgF )?%8%F!".2*+%o!"Ms   AAc           	     P  K   t               4 d {   }|j                  t        t              j	                  t        j
                  j                  d      t        j                  j                  d             j                  t        j                               d {   j                         j                         }d d d       d {    dD cg c])  }|j                  |j                  |j                  dk(  d+ c}iS 7 7 i7 ?# 1 d {  7  sw Y   OxY wc c}w w)NTmembersowner)rF   roleis_owner)r   rD   r
   r   rE   rK   rH   rG   rV   rW   rL   rY   rF   r   )r   r   rN   r   rO   s        rP   tool_get_team_membersr     s      ""bzz4LU4>>%%d+T__-@-@-FGXdoo&
 
 79SSU	 	 #" 	 
 	 !"FFg-
 
	 	 #
 #"""
sc   D&DD&B	DD D?D&
D
	D&.D!D&D
D&DDDD&c                  K   ddl m} t        | j                  d      xs d      }t	        dt        |d            } |d |       d {   }|s
|g d| d	d
S |D cg c]
  }|d   r	| }}|D cg c]
  }|d   s	| }}|t        |      t        |      t        |      |D cg c]  }|d   |d   |d   |d   |d   d c}dS 7 c c}w c c}w c c}w w)Nr   )r9   r:      r      )
channel_idr:   u   最近 u"    小時沒有自動建出的任務)r:   itemsr@   acceptedr   r   r,   accepted_at)r   r   r,   r   r   )r:   totalaccepted_countpending_countr   )app.services.task_acceptancer9   r   r   r   r   r   )r   r   r9   r:   r   ipendingr   s           rP   tool_list_assignment_statusr      s    C!'R(E3uc?#E(DFFE'%Hj8kll5%Qq}q%G5 25aAjM5H2Uh-W 	
  7o.H+jM / 	
  G 62	
sH   AC
CC
C*C.C4
C?C%C(CCCc           	     f  K   ddl m }mm} t        | j	                  d      xs d      }t        dt        |d            } |j                  j                         ||      z
  }t               4 d {   }|j                  t        t              j                  t        j                  j                  d      t        j                   j                  d                    d {   j#                         j%                         }|j                  t        t&              j                  t&        j                   j                  d                    d {   j#                         j%                         }fd	}	|D 
cg c]R  }
 |	|
j(                        r |	|
j(                        |k\  s' |	|
j*                        r |	|
j*                        |k\  r|
T }}
i }|D ]  }|j,                  ddd
||j.                  <   ! |D ]Q  }
|
j0                  xs |
j2                  }||vr"||   dxx   dz  cc<   |
j4                  dk(  sB||   dxx   dz  cc<   S d d d       d {    g }j7                         D ]B  \  }}|d   rt9        |d   |d   z  dz        nd}|j;                  |d   |d   |d   |d       D |j=                  d        t?        d |D              }|rt9        |tA        |      z  d      nd}d| d| d}|||||dS 7 7 )7 c c}
w 7 # 1 d {  7  sw Y   xY ww)Nr   )r   r   	timedeltar=      r   Z   r=   Tc                ^    | y| j                   | j                  j                        S | S )uF   SQLite 存的 datetime 可能是 naive(UTC),補上 tzinfo 再比較。N)tzinfo)r   r[   r   )dtr   s    rP   _tz_safez/tool_get_team_completion_rate.<locals>._tz_safeH  s/    zyy zzz66I    )r"   r   r(   r   r(   d   r"   )r"   r   r(   percentc                    | d    | d    fS )Nr(   r    )ms    rP   <lambda>z/tool_get_team_completion_rate.<locals>.<lambda>j  s    6
QwZK8r   )keyc              3  &   K   | ]	  }|d      yw)r(   Nr   ).0r   s     rP   	<genexpr>z0tool_get_team_completion_rate.<locals>.<genexpr>m  s     01QvYs   u   用累積完成件數排序(不用百分比,因為 1/2 = 50% 跟 9/20 = 45% 看起來假性接近,實際產出差很多)。本期合計 u    件、平均 u    件/人。)r=   r   team_total_doneavg_done_per_personranking_note)!r   r   r   r   r   r   r   r   r   r   rD   r
   r   rE   rK   rH   rG   rL   rY   r   rW   r   rF   r]   r{   r|   r,   r   roundappendsortsumr   )r   r   r   tdr=   	cutoff_dtrN   r   rowsr   ra   relevantstatsrO   uidr   spct
total_doneavg_doner   r   s                        @rP   tool_get_team_completion_rater   ;  s    <<txx$1%Dq#dB- DX\\*RT]:I ""bzz4Lt~~11$79L9LT9RS
 
79SSU 	 jj4Lt22489
 
79SSU 		 
!&8ALL+AY+N(Xann-E-R t 	 

 A#$>>AqIE!$$K A--/1<<C%#Jw1$xx6!c
6"a'" 1 #"@ G++-Q56wZeAfI'
*S01QfIwZfI	
 	   LL8L9 000J6=uZ#g,.21H11;N8*T_	a 	
 %' g #


! #"""s   A3L16L7L1:A,L&L'A-LL)L>ALA+LLL1LB.L1LLLL1L."L%#L.*L1c                  K   ddl m }m}m} | j                  d      xs dj	                         }|sddiS | j                  d      xs |dd	 j	                         }| j                  d
      xs dj	                         xs d}g }	 ddlm}	  |	|dd d       d{   }
 |j                  |j                         |d      z
  }|
xs g D ]  }|j                  d      }|r*	  |j                  |j                  dd            }||k  r?	 |j                  d      xs ddk\  sY|j                  t        |d   d      |j                  d      xs ddd d        |dd }t%               4 d{   }|j'                  t)        d|d|dd  |dd |||t+        |      dd !             |j-                          d{    ddd      d{    d"||t+        |      |rd#t+        |       d$d&S d%d&S 7 ^# t        t        f$ r Y w xY w# t        $ r t         j#                  d       Y w xY w7 7 w7 i# 1 d{  7  sw Y   yxY ww)'u@   把內容存進 reflection_note(體悟紀錄),不會建任務。r   r   r   r   r?   rU   rw   u   content 必填r@   Nr   rA   )search_relevant,     )queryr-      r   rW   Zz+00:00scoregffffff?   P   )r  preview   u%   save_reflection 相似度比對失敗reflection_note   體悟:<     r~   )rawr@   rA   
similar_tosimilar_countr   rd   Tu   ⚠ 過去 30 天有 u    則相似體悟u"   已歸檔,週六覆盤會帶出來)r   r@   rA   r  r   )r   r   r   r   r   app.services.coba_memoryr   r   r   fromisoformatr[   r   r   r   r   rj   rk   rl   r   rh   r   r   ri   )r   r   r   r   r   r?   r@   rA   r  r   simr   r   ts_strr   rN   s                   rP   tool_save_reflectionr  |  sz    66xx	"(b//1G)**xx	"2gcrl99;G88E? b
'
'
)
1TC JB<#'$3-rBB HLL.1CC	))AUU<(F///sH0MNBI~  & g#!+!!"1W:q1 !i 0 6B<#    ^
 !""b
}+ gcrl^,u~"(!$Z"	
 	 iik #"" Z )Z(99IJ  %I I C #I.   B@AB # 	 #"""s   BIH G:AH $'G=H &>H $I2H73I6AH=H9H=IH;(I:H =HH HH H41I3H44I9H=;I=IIIIc                   K   ddl m} t        | j                  d      xs d      }t	        dt        |d            } ||       d {   }|t        |      |d d d	S 7 w)
Nr   )rB   r:   r   r   i  )r:   r  )r:   r   r   )app.services.coba_acknowledgerB   r   r   r   r   r   )r   r   rB   r:   r   s        rP   tool_list_recent_reflectionsr    sc     E!(S)E3ug&'E)66EUs  7s   AA"	A 
A"c                  K   ddl m }m}m}  |j                  |j                         |d      z
  }|r'| j                  t        t              j                  t        j                  dk(  t        j                  j                  d            j                  t        j                  j                               j                  d             d{   j!                         j#                         }|j%                         j'                  dd	      }|D ]H  }	t)        |	j*                        j'                  dd	      j%                         j-                  |      sF|	c S  |r%|j/                         }
| j                  t        t              j                  t        j                  dk(  t        j                  j                  d      t        j                  |k\        j                  t        j                  j                               j                  d             d{   j!                         j#                         }|D ]D  }	|	j0                  xs i }|
|j3                  d
      xs d	v s|
|j3                  d      xs d	v sB|	c S  y7 7 mw)uH   找一筆 reflection_note。用 id 前 8 碼或 raw/summary 關鍵字。r   r   r  r   r	  NrS   rT   rU   r  r@   )r   r   r   r   r   rD   r
   r   rE   re   rG   rH   rV   rW   rX   r-   rL   rY   rZ   r[   r\   r]   r^   r   rg   r   )rN   reflection_id_prefixcontent_keywordr   r   r   cutoffr   r`   rkwes               rP   _find_reflectionr    s    66X\\(,,')*<<Fjj=!''++/@@((,,T2 h}//4467c
	
 

 79SSU 	 &++-55c2>A144y  b)//1<<VD  ""$jj=!''++/@@((,,T2((F2 h}//4467c

 
 79SSU 	 A2AaeeEl(b)RAEE)4D4J-K  /

s3   CJJBJCJJ	A#J J	Jc           	       K   ddl m }m} t               4 d{   }t        || j	                  d      | j	                  d             d{   }|ddicddd      d{    S |j
                  xs i }|j	                  d      xs |j	                  d	      xs d
dd }t        |j                        } |j                  |j                        |_
        |j                          d{    ddd      d{    t        dddd  ||dd       d{    d|dd |dS 7 7 7 7 E7 7# 1 d{  7  sw Y   GxY w7 -w)u   軟刪覆盤(set deleted_at)。r   r   r   Nr  r  rw   uI   找不到對應覆盤(用 reflection_id_prefix 8 字 或 content_keyword)r@   r  rU   r   reflection_deleteu   庫柏刪覆盤:r~   )reflection_idold_summaryr   r   Tr   )r   reflection_id_shortr$  )r   r   r   r  r   rg   r\   r]   r   r   rG   ri   rm   )	r   r   r   r   rN   targetr  r$  rids	            rP   tool_delete_reflectionr(    sK    + ""b'HH+,HH&'
 

 >hi #"" LLBeeI&C155<+=2s*C&))n(HLL6iik #" )";s#3"45 #KT	   "2Aw" ) #
 # 	 #"""s   ED+E/D6D.	D6E"D0#E(BD6,D2-D61E<D4= EEE.D60E2D64E6E<D?=EEc                  K   | j                  d      }| j                  d      }| j                  d      }|||ddiS t               4 d{   }t        || j                  d      | j                  d             d{   }|dd	icddd      d{    S t        |j                  xs i       }t        |      }|/|j                         }|sdd
icddd      d{    S |dd |d<   ||j                         dd |d<   ||j                         xs d|d<   ||_        d|v r|d   rd|d   dd  |_        t        |j                        }	|j                          d{    ddd      d{    t        ddj                  d      xs ddd  |	dD 
ci c]  }
|
j                  |
       c}
dD 
ci c]  }
|
|j                  |
       c}
dd       d{    d|	dd |j                  d      |j                  d      dS 7 7 7 7 >7 7 # 1 d{  7  sw Y   xY wc c}
w c c}
w 7 [w)u'   改覆盤的 content / summary / tag。new_contentnew_summarynew_tagNrw   u=   至少要給 new_content / new_summary / new_tag 其中一個r  r  u   找不到對應覆盤u   new_content 不能是空字串r  r  r  r@   rA   r
  r  reflection_updateu   庫柏改覆盤:rU   r   )r  r@   rA   r~   )r#  oldnewr   r   Tr   )r   r%  r@   rA   )r   r   r  dictrg   r   r@   r\   r]   ri   rm   )r   r   r*  r+  r,  rN   r&  r  old_er'  ks              rP   tool_update_reflectionr3     sr    ((=)K((=)Khhy!G{2wXYY ""b'HH+,HH&'
 

 >45 #"" #$Q"%++-K!AB #""  #5D)AeH"&,,.s3AiL}}.$AeH>a	l&q|CR'8&9:FN&))niik9 #"< )"AEE)$4$:CR#@"AB -FG-FAuyy|O-FG)BC)BAAquuQxK)BC	
	
 
 
 "2Aw55#uuU|	 S #
 #"8 	9 #"""H HC
s   AI
HI
/H)H	H)I
HI
;H)I
$H"%I
*BH)+H%,H)0I
;H'<*I
&H>?I
II
,I--I
H)I
"I
%H)'I
)H;/H20H;7I
c                <  K   ddl m }m} | j                  d      xs dj                         }|sddiS t	               4 d{   }t        || j                  d      | j                  d	             d{   }|dd
icddd      d{    S |j                  xs i }|j                  d      xs d}t        |j                        }	 |j                  |j                        |_        |j                          d{    ddd      d{    || j                  d      | j                  d      | j                  d      | j                  d      xs d}
t        |
|       d{   }d|v rt	               4 d{   }|j                  t        t               j#                  t         j                  j                  k(               d{   j%                         }d|_        |j                          d{    ddd      d{    dd|d    iS |j                  d      }| j                  d      rt'        |dd|       d{    t)        dd| |	dd |t+        | j                  d            dd       d{    d|	dd ||t+        | j                  d            d| j                  d      rdz   d S dz   d S 7 7 ^7 K7 7 # 1 d{  7  sw Y   xY w7 7 v7 )7 7 # 1 d{  7  sw Y   xY w7 7 w)!u   誤分類修正:把覆盤升級成任務,順便軟刪原覆盤。

    必填:
      - reflection_id_prefix(或 content_keyword)
      - title:任務標題
    選填:assignee_name / due_date / priority / description / mark_done(bool,直接標完成)
    r   r!  r   rU   rw   u   title 必填(任務標題)Nr  r  u!   找不到要轉成任務的覆盤r  r   r   r   r   r   u    建任務失敗,覆盤已回滾:r   	mark_doner(   )r0   r2   reflection_convert_to_tasku   庫柏把覆盤轉成任務:r   r~   )old_reflection_idold_rawnew_task_id_shortmarked_doner   r   Tr   u"   原覆盤已軟刪,新任務建好u   並已標 done)r   old_reflection_id_shortr9  r   r:  r   )r   r   r   r   r   r  rg   r\   r]   r   r   rG   ri   r   rD   r
   r   rE   
scalar_oner   rm   r   )r   r   r   r   r   rN   r&  r1  r8  old_ridcreate_argscreate_resultra   new_task_ids                 rP   tool_convert_reflection_to_taskrA  9  s     ,XXg$"++-E566 !""b'HH+,HH&'
 

 >@A #"" "))E"(bfii.(HLL6iik #"" /2HHZ(HHZ(xx.9'K +;EEM-$&&"zz}%++M,<,<		,IJ z|   AL))+ '& ;M'<R;STUU##O4K xx%*&A
 	
 	

 2.ug6!(t}!, 56
	   #*2A;(DHH[124DHHU`La8Hj  hjj o #
 # 	 #""". F '  '&&&	

s%  A LKL/K5K6	K?LKLA.K?K KLKAL+K5,LK8LALK;,L?K> LLL ALL:LLALKLKLK2%K(&K2-	L8L;L>L LLL	L	LLc                8	  K   t               4 d{   }t        || j                  d      | j                  d             d{   }|ddicddd      d{    S |j                  |j                  r|j                  j                         nd|j                  |j                  rt        |j                        ndd}i }| j                  d      }|r(||j                  k7  r|j                  |d|d	<   ||_        | j                  d
      }|2||j                  k7  r#|j                  xs ddd |dd d|d<   ||_	        | j                  d      }|rT|j                         }|dvrdd|icddd      d{    S ||j                  k7  r|j                  |d|d<   ||_        | j                  d      }	|	ddlm}
 |	dk(  s|	j                         dk(  r4|j                  |j                  j                         dd|d<   d|_        nd	 |
j                  |	      }||j                  k7  rC|j                  r|j                  j                         nd|j                         d|d<   ||_        | j                  d      }||dk(  s|j                         dk(  r/|j                  t        |j                        dd|d<   d|_        nt        ||       d{   }|dd| dicddd      d{    S |j                  |j                   k7  rX|j                  rt        |j                        nd|j"                  t        |j                         d|d<   |j                   |_        |s8ddt        |j                         dd |j                  d cddd      d{    S |j%                          d{    |j                  }t        |j                         }ddd      d{    t'        d!d" d#d$j)                  d% j+                         D              z   ||d&d'd()       d{    d|dd ||d*S 7 27 7 7 # t        $ r dd|	icY cddd      d{  7   S w xY w7 7 7 7 7 # 1 d{  7  sw Y   xY w7 cw)+u   改任務的 due_date / priority / title / description / assignee。

    比 update_task_status 完整 — 改一切 task 欄位,但不改 status(用既有 update_task_status)。
    Nr0   r1   rw   r   )r   r   r   r{   	new_title)fromtor   new_descriptionrU   r   r   new_priorityr   u8   new_priority 必須是 low/medium/high/urgent,給的是 r   new_due_dater   )r   nullr   u3   new_due_date 格式錯誤,要 YYYY-MM-DD,給的是 new_assignee_name)from_idrE  r   u   找不到名字含「u   」的成員)rK  rE  to_idTr   )r   	no_changer   r   r}   u   庫柏改任務《u   》: z, c              3  "   K   | ]  }|  	 y wNr   )r   r2  s     rP   r   z#tool_update_task.<locals>.<genexpr>  s     =]nfns   r~   update_task)r   changesold_snapshotr   toolr   )r   r   r   rQ  )r   rb   r   r   r   r   r   r{   r\   r   rZ   r   r   r  r   rQ   r]   rF   ri   rm   joinkeys)r   r   rN   r   rR  rQ  rC  new_descrG  new_due_dateparsedrJ  r&  r   r   s                   rP   tool_update_taskrZ    s    
 !""bDHH-=$>@YZZ<Z[ #"" ZZ59]]//1484D4D3t//0$	
 $&HH[)	djj0(,

)DGG"DJ88-.H0@0@$@/3/?/?/E2s.KS[\_]_S`%aGM"'Dxx/'--/L#FF#[\h[k!lm7 #""8 t}},/3}}L&Q
# ,((>*."}6 9==,37==3J3J3LTX*YGJ'$(DMh"009F T]]*=A]] 7 7 9PT$..0+GJ' %+DM HH%89( B&*;*A*A*Cv*M##/69$:J:J6KSW*XGJ''+D$1"6GHH>#'<=N<O|%\]{ #""| ##vyy0<@<L<L3t'7'7#8RV$11!$VYY+GJ'
 (.yyD$#$TWWVXWXIYdhdndnoO #""R iik

$''lW #"Z ($UG51DII=]glln=]4]](!
	   Ra	 s #Z #"T " h#'Z[bZe%fggW #""Th" Iw #"R 	S #"""Zs3  RQR/RQ	RRQ	R DR1R=Q>RBRQ"B;RQ7R+R7Q:8R=BRR"Q=#R(R;Q?<%R!R,R-AR4R5RR	RRQ4R R,Q/-R3Q44R:R=R?RRR	R
RRc                   K   t        | j                  d      | j                  d      | j                  d      d|       d{   S 7 w)u?   轉指派任務 — `update_task` 的 sugar(只改 assignee)。r0   r1   rJ  )r0   r1   rJ  N)rZ  r   )r   r   s     rP   tool_reassign_taskr\    sM     !"hh'78!XXo6!%*=!>	

 	   s   AA
AA
c                l  K   | j                  d      xs dj                         }|sddiS | j                  d      xs dj                         }|dvrdd|iS | j                  d	      }| j                  d
      }| j                  d      }t               4 d{   }|j	                  t        t              j                  t        j                  |k(  t        j                  j                  d                   d{   j                         }|2dd| dt        |j                        dd  dicddd      d{    S |r|j	                  t        t              j                  t        j                  |k(  t        j                  j                  d                   d{   j                         }	|	&dd| d|	j                   dicddd      d{    S |r|j	                  t        t              j                  t        j                  |k(  t        j                  j                  d                   d{   j                         }
|
#dd|
j                   dicddd      d{    S ddlm} t        ||xs$ d|j                         j%                  dd       d |d|z         |||d      }|j'                  |       |j)                          d{    |j+                  |       d{    t        |j                        }ddd      d{    t-        dd| d | d!|||t/        |      t/        |      d"d#d$%       d{    d|dd ||d&|xs d' d(| d)|rd*z   d,S d+z   d,S 7 7 7 H7 7 7 N7 7 7 7 v# 1 d{  7  sw Y   xY w7 Uw)-u   新增團隊成員。

    必填:display_name
    選填:role (member / manager / owner,預設 member)
          email
          line_user_id(LINE 個人 ID,Uxxxxxx 格式)
          job_title
    rF   rU   rw   u   display_name 不能空r   member)r   ro   r^  u.   role 必須是 owner/manager/member,給的是 emailline_user_id	job_titleNu   已有同名成員「u   」(id=r   u   ),請改用別的 display_nameu   email「u   」已被「u	   」使用u   LINE id 已被「r   )hash_passwordzplaceholder. _z@coba.localz
ChangeMe!_T)rF   r_  password_hashr   ra  r`  rK   r}   u   庫柏新增成員:(rz   r~   add_team_member)new_user_idrF   r   	has_emailhas_line_user_idr   rS  r   u,   成員已建。請告知本人:用 email 「u   (請管理者改 email)u   」+ 預設密碼 ChangeMe!_u/    登入,然後立刻去個人設定改密碼。u   LINE 已綁定。uX    還沒綁 LINE,本人之後在 LINE 對 Cooper 機器人發 /bind 拿驗證碼綁定。)r   user_id_shortrF   r   	next_step)r   r   rZ   r   rD   r
   r   rE   rF   rG   rH   rI   r\   r]   r_  r`  app.core.securityrb  r[   rh   ri   r   rm   r   )r   r   rF   r   r_  r`  ra  rN   dupdup_edup_lrb  new_usernew_ids                 rP   tool_add_team_memberrs    s     HH^,299;L122HHV(//1D11I$RSSHHWE88N+L%I ""bZZ4Lt00L@$//BUBUVZB[\
 
 	 ?4\N'#cff+VXWX/IZZxyz #"" ::t""4::#68K8KD8QR !!#   8E7,u?Q?Q>RR[!\] #""" ::t""4#4#4#DdooFYFYZ^F_` !!#   #4U5G5G4H	!RS- #""2 	4%]\,*<*<*>*F*FsC*P)QQ\]'|(CD%
 	xiikjj"""X[[!M #"P (%l^1TF!<!(e $\ 2%
	   $4455QR^Q_  `OP&2"T
 
 9ST
 
m #
 # #$% #H 	"K #"""Ps  BN4NN4A N?N 4N4N4 NN4A!N'N((NN4NN4"A!NN%N)N45N6N4;A+N&N'N?N NN4$N%7N4N2&N4NN4NN4NN4NNN4N/#N&$N/+N4c                  K   ddl m}m } ddlm}m}m}m} | j                  d      xs dj                         }|sddiS | j                  d      xs dj                         }	| j                  d	      xs g }
t        |
t              r|
g}
| j                  d
      xs g }t        |t              r|g}| j                  d      xs g }t        |t              r|g}t               4 d{   } ||d|      }|j                  |       |j                          d{    |j                  }|	s|
r,|j                   |||	xs d|
rt        |
      ndd             t!        |      D ]  \  }}t        |t              r)|j                   |||j                         |             ?t        |t"              sP|j                   |||j                  d      xs dj                         |j                  d      xs d|              t!        |      D ]  \  }}t        |t              r)|j                   |||j                         |             ?t        |t"              sP|j                  d      xs dj                         }|svd}|j                  d      }|r"t%        ||       d{   }|r|j                  }|j                  d      }|r	 |j'                  |       |j                   ||||||              |j+                          d{    t        |      }ddd      d{    t-        dd|dd  ||t/        |      t/        |      dd        d{    d!|dd" |t1        |	xs |
      t/        |      t/        |      d#|dd"  d$d%S 7 7 7 # t(        $ r d}Y w xY w7 7 # 1 d{  7  sw Y   xY w7 iw)&u  直接從文字記錄一場會議。

    必填:title (字串)
    選填:
      - executive_summary:濃縮摘要(2-4 句)
      - key_topics:list[str] 主題
      - decisions:list[str] 或 list[dict{decision, context}] — 重要決策
      - action_items:list[str] 或 list[dict{description, assignee_name, due_date}] — 待辦事項
      - meeting_date:YYYY-MM-DD,沒給就用今天

    建出來:status='completed',audio_path=None(代表手動輸入)
    r   )r   r   MeetingMeetingSummaryMeetingDecisionMeetingActionItemr   rU   rw   u   title 必填executive_summary
key_topics	decisionsaction_itemsN	completed)r   r,   r|   u   (無摘要)zcooper-line-record)
meeting_idrz  r{  generated_by)r  decisionorder_indexr  context)r  r  r  r  )r  r   r  r   r   r   )r  r   suggested_assignee_idsuggested_due_dater  meeting_recordu   庫柏記會議:r   r~   )r  r   decisions_countaction_items_countr   r   Tr   z.https://cooper-nas.taila49e28.ts.net/?meeting=u:   會議已記錄。dashboard 的會議分頁可看詳細。)r   meeting_id_shortr   summary_addedr  r  urlr   )r   r   app.models.meetingrv  rw  rx  ry  r   r   
isinstancer\   r   rh   flushr]   list	enumerater0  rQ   r  r   ri   rm   r   r   )r   r   rX  r   rv  rw  rx  ry  r   r@   r{  r|  r}  rN   meetingmidr   darX   r{   anamerO   duemid_strs                            rP   tool_record_meetingr  Z  s     1  XXg$"++-E((xx+,299;G,'-2J*c" \
%+I)S!K	88N+1rL,$$~ ""b#

 	whhjjj jFF>")":]/94
+t1	  i(DAq!S!#	WXYZAt$"eeJ/52<<>UU9-5 !	 	 ) l+DAq!S!("	q  At$m,299;"o.0U;;A&'ddeeJ'#++C0 (" $*5'* ! - ,< iikc( #"B &"5":,/!"9~"%l"3
	   #BQKg34y>!,/?}ML	 	[ # 	J < & #"# 	} #"""Bs   C'O)N *O-0N=N#BN=9B+N=%A
N=/N&0%N=N('1N=N9N=(O3N;44O(O)8O#N=&N=(N63N=5N66N=;O=OOOOc           
     ,  K   ddl m} t        | j                  d      xs d      }t	        dt        |d            }t               4 d{   }|j                  t        |      j                  |j                  j                  d            j                  |j                  j                               j                  |             d{   j!                         j#                         }g }|D ]  }d}|j$                  rmddl m}	 |j                  t        |	      j                  |	j(                  |j$                  k(               d{   j+                         }
|
r|
j,                  dd	 }|j/                  t1        |j$                        dd
 |j2                  |j4                  |j                  r|j                  j7                         nd|d        ddd      d{    t9              |dS 7 7 -7 7 # 1 d{  7  sw Y   *xY ww)u   列最近會議。r   rv  r-   r   r   r   N)rw  x   r   )r   r   r,   rW   summary_preview)r   r   )r  rv  r   r   r   r   r   rD   r
   rE   rG   rH   rV   rW   rX   r-   rL   rY   r]   rw  r  rI   rz  r   r\   r   r,   r   r   )r   r   rv  r-   rN   r   outr   summrw  r   s              rP   tool_list_meetingsr    s    *!'R(E3ub>"E ""bjj7O!!'"4"4"8"8">?Xg((--/0u
 
 79SSU 	
 ADtt=::>*001J1Jadd1RS %%'  ..t4DJJIbqM((:;,,all446D#'   #"0 X,,1 #
 #"""so   A	HG5HA<G?G8A>G?
G;BG?H"G=#H8G?;G?=H?HHHHc                v   K   ddl mm}m}m} ddlm}  fd}t               4 d{   } ||       d{   }|ddicddd      d{    S |j                  t        |      j                  |j                  |j                  k(               d{   j                         }	|j                  t        |      j                  |j                  |j                  k(        j                  |j                               d{   j!                         j#                         }
|j                  t        |      j                  |j                  |j                  k(        j                  |j                               d{   j!                         j#                         }ddlm} t)        |D ch c]  }|j*                  s|j*                   c}      }i }|r|j                  t        |      j                  |j                  j-                  |                   d{   j!                         j#                         }|D ci c]  }|j                  |j.                   }}t1        |j                        dd	 |j2                  |j4                  |j6                  r|j6                  j9                         nd|	r|	j:                  nd|	r|	j<                  nd|
D cg c]  }|j>                  |j@                  d
 c}|D cg c]W  }|jB                  |jE                  |j*                        |jF                  |jH                  rt1        |jH                        nddY c}dcddd      d{    S 7 N7 A7 .7 7 |7 c c}w 7 jc c}w c c}w c c}w 7 .# 1 d{  7  sw Y   yxY ww)u>   看一場會議完整內容(摘要 + 決策 + action items)。r   ru  )selectinloadc                  K   j                  d      xs dj                         }j                  d      xs dj                         }|r	| j                  t              j	                  j
                  j                  d             j                  j                  j                               j                  d             d {   j                         j                         }|j                         j                  dd      }|D ]H  }t        |j                         j                  dd      j                         j#                  |      sF|c S  |r| j                  t              j	                  j$                  j'                  |      j
                  j                  d             j                  j                  j                                      d {   j                         j)                         S y 7 87 $w)Nmeeting_id_prefixrU   r1   rS   rT   )r   r   rD   r
   rE   rG   rH   rV   rW   rX   r-   rL   rY   rZ   r[   r\   r]   r^   r   rJ   rM   )rN   r`   title_kwr   pr   rv  r   s         rP   _findz&tool_get_meeting_detail.<locals>._find  s    ((./52<<>HH_-3::<**w%%g&8&8&<&<T&BC',,1134UU3Z  wy  &&sB/Aqtt9$$S"-335@@CH  **w%%MM**84&&**40 (7--2245	 
 wy! s,   CHH 	BHBHH"HHNrw   u8   找不到會議(用 meeting_id_prefix 或 title_keyword)r   r   )r  r  )r   r   r   converted_task_id)r   r   r,   rW   rz  r{  r|  r}  )%r  rv  rw  rx  ry  sqlalchemy.ormr  r   rD   r
   rE   r  r]   rI   rV   r  rL   rY   app.models.userr   r  r  r   rF   r\   r   r,   rW   r   rz  r{  r  r  r   r   r  r  )r   r   rw  rx  ry  r  r  rN   r   r   r|  r   r   r  a_uidsu_mapusrO   r  rv  s   `                  @rP   tool_get_meeting_detailr    s      ,* !""b)O9WX #""
 ::>"(()B)Badd)JK
 
 	
 ::?#))/*D*D*LMXo112
 
 79SSU 	
 zz$%++,=,H,HADD,PQX'334
 
 79SSU 	 	)Y1AXAXq..YZ

6$<#5#5dggkk&6I#JKKTTVZZ\B3562aQTT1>>)2E6 ADD	"1WWhh67ll!,,00289!4!4t*+!,, #"A ZZAII>"  A $%== %		!*A*A B ! 4 4EFEXEXQ-@-@)A^b	 
7 #"" #




 Z L6M #"""s   'N9M9N9N$M<	N$N9M?N9AN$NA.N$	N
A<N$N/N$6N
N
AN$&N'$N$N)A8N$! NN$AN#N$'N93N"4N9<N$?N9N$N$N$N$N$"N9$N6*N-+N62N9c           	       K   ddl m }m} ddlm} | j	                  d      xs dj                         }| j	                  d      xs dj                         }|s|sddiS t               4 d	{   }d	}|r	|j                  t        |      j                  |j                  j                  d	            j                  |j                  j                               j                  d
             d	{   j!                         j#                         }	|j%                         j'                  dd      }
|	D ]H  }t)        |j*                        j'                  dd      j%                         j-                  |
      sF|} n ||r|j                  t        |      j                  |j.                  j1                  |      |j                  j                  d	                   d	{   j!                         j3                         }|ddicd	d	d	      d	{    S |j.                  }t)        |j*                        } |j4                  |j6                        |_
        |j9                          d	{    d	d	d	      d	{    t;        ddd	d  |dd       d	{    d|d	d |dS 7 A7 7 7 7 G7 9# 1 d	{  7  sw Y   IxY w7 0w)u   軟刪會議。r   r!  r  r  rU   r1   rw   u0   至少要給 meeting_id_prefix 或 title_keywordNrS   rT   u   找不到會議meeting_deleteu   庫柏刪會議:r   r~   )r  r   r   Tr   )r   r  r   )r   r   r  rv  r   r   r   rD   r
   rE   rG   rH   rV   rW   rX   r-   rL   rY   rZ   r[   r\   r]   r^   r   rJ   rM   r   r   ri   rm   )r   r   r   r   rv  r`   r  rN   r   r   r  xr   r  s                 rP   tool_delete_meetingr  F  sj    +*hh*+1r88:F)/R668H(KLL ""b**w%%g&8&8&<&<T&BC',,1134UU3Z  wy  &&sB/Aqtt9$$S"-335@@CA5  9zzw%%MM**84&&**40 
 wy  9./' #""* add)#x||HLL1iik1 #"4 &"5":,/$[9	   !uMMA # #0 	1 #"""4s   A+K-J..K1BJ<2J13BJ<;A(J<#J4$%J<	KJ6KAJ<0J81J<5K J:K K!K1J<4J<6K8J<:K<KKK
KrP  reassign_taskdelete_reflectionupdate_reflectionconvert_reflection_to_taskrg  record_meeting)list_meetingsget_meeting_detaildelete_meetingc                  K   t         j                  |       }|dd|  iS 	  ||xs i |       d{   S 7 # t        $ r=}t        j	                  d|        ddt        |      j                   d| icY d}~S d}~ww xY ww)uC   執行單一工具呼叫,失敗也回 dict(讓 Claude 看得懂)。Nrw   u   未知工具:ztool %s failedu   工具執行例外:r   )	_DISPATCHr   rj   rk   rl   r   __name__)r"   r   r   fnr  s        rP   execute_toolr    s     	t	B	z=/00H
L1111 H)40.tAw/?/?.@1#FGGHs=   B9 79 B9 	A?2A:4A?5B:A??B)r"   r\   returnzUser | None)r0   
str | Noner1   r  r  zTask | NonerO  )re   r\   r@   r\   rf   zUUID | Nonerg   zdict | None)rq   r\   r  None)r   r0  r   r   r  r0  )r  r  r  r  r  zAgentActivity | None)r"   r\   r   r0  r   r   r  r0  )4__doc__
__future__r   loggingr   r   r   typingr   uuidr   
sqlalchemyr	   r
   app.databaser   app.models.agent_activityr   app.models.taskr   r  r   	getLoggerrk   TOOLS_SCHEMArQ   rb   rm   ru   r   r   r   r   r   r   r   r   r  r  r  r(  r3  rA  rZ  r\  rs  r  r  r  r  r  r  r   r   rP   <module>r     s  ( #  - -   " * 3     
		<	( 3
  %#N
 % $b"
 % $^
 %?#l %#> %. !	3
"H K  %#I"
 %Y#L &#H
4 %F  %#e#
 %#X"
 %R &!
4 q#)8"4"((!3#+<UV
 #v
 'i %#r 
( )]
 "+<cd)2Co p
  +;
 ;\]
 "g "$,=kl$,=VW (  :G  H
. *= )<bc
aN*00L"FR0fDG(006>B8v	><6rLfcL	Uxyx-DK
\*NZ#/ 1 #	
 ' # - 5 9  = ; + / / !"A  +!" )#$ (1))	0	Hr   