コンテキストストレージシステムは、タスク実行中の全ての情報(メッセージ、要約、ツール呼び出し、プランニング履歴)を永続化し、タスクの中断・再開、コンテキスト継承を実現します。
- タスクコンテキスト管理: タスク単位でのコンテキスト情報の一元管理
- メッセージストレージ: LLMとのやり取りの完全な履歴保存
- コンテキスト圧縮: トークン制限対応のための自動圧縮・要約
- コンテキスト継承: 前回タスクからのコンテキスト引き継ぎ
- ツール呼び出し記録: 実行された全ツール呼び出しの記録
- プランニング履歴: タスク計画の変遷記録
contexts/
├── running/ # 実行中タスク
│ └── {uuid}/
│ ├── metadata.json
│ ├── messages.jsonl
│ ├── current.jsonl
│ ├── summaries.jsonl
│ ├── tools.jsonl
│ └── planning.jsonl
├── completed/ # 完了タスク
│ └── {uuid}/
│ ├── metadata.json
│ ├── messages.jsonl
│ ├── final_summary.txt
│ ├── summaries.jsonl
│ ├── tools.jsonl
│ └── planning.jsonl
├── paused/ # 一時停止タスク
│ └── {uuid}/
│ └── (running/と同じ構造)
└── tasks.db # タスク管理データベース
classDiagram
class TaskContextManager {
+MessageStore message_store
+SummaryStore summary_store
+ToolStore tool_store
+PlanningHistoryStore planning_store
+ContextInheritanceManager inheritance_manager
+get_message_store() MessageStore
+get_summary_store() SummaryStore
+get_tool_store() ToolStore
+update_status(status, error_message)
+complete()
+stop()
+fail(error_message)
}
class MessageStore {
-Path context_dir
-dict config
-int _next_seq
+add_message(role, content, tool_name) int
+get_current_context_file() Path
+get_current_token_count() int
+count_messages() int
+recreate_current_context(summary, unsummarized_file)
}
class SummaryStore {
-Path context_dir
-int _next_id
+add_summary(summary, compressed_count, tokens_saved) int
+get_latest_summary() dict
+count_summaries() int
}
class ToolStore {
-Path context_dir
-int _next_seq
+add_tool_call(tool_name, arguments, result, error) int
+count_tool_calls() int
}
class ContextCompressor {
-TaskContextManager task_ctx
-dict config
-LLMClient llm_client
+should_compress() bool
+compress() int
+create_final_summary() int
}
class ContextInheritanceManager {
-Path base_dir
-dict config
+find_previous_contexts(task_key) list
+get_inheritance_context(previous_uuid) InheritanceContext
+create_initial_context(task_ctx, inheritance_ctx)
+generate_notification_comment(inheritance_ctx) str
}
class PreviousContext {
+str uuid
+str status
+datetime completed_at
+dict metadata
}
class InheritanceContext {
+str uuid
+str final_summary
+list planning_history
+dict metadata
}
TaskContextManager --> MessageStore
TaskContextManager --> SummaryStore
TaskContextManager --> ToolStore
TaskContextManager --> ContextInheritanceManager
ContextCompressor --> TaskContextManager
ContextInheritanceManager --> PreviousContext
ContextInheritanceManager --> InheritanceContext
ファイル: context_storage/task_context_manager.py
メソッド: __init__(base_dir, task_key, config, llm_client=None)
処理内容:
- 基本パラメータを保存:
base_dir: コンテキストベースディレクトリtask_key: タスクキー情報uuid: タスクUUID(task_keyから取得)config: アプリケーション設定
- コンテキストディレクトリの決定:
is_resumedフラグに基づき、pausedまたはrunningディレクトリを選択- ディレクトリパス:
{base_dir}/running/{uuid}/または{base_dir}/paused/{uuid}/
- コンテキストディレクトリを作成(存在しない場合)
- サブストアの初期化:
MessageStore: メッセージ管理SummaryStore: 要約管理ToolStore: ツール呼び出し記録PlanningHistoryStore: プランニング履歴
- タスクDB登録/更新:
- 新規タスク: INSERT
- 再開タスク: UPDATE(statusをrunningに変更)
- メタデータファイル作成(新規タスクの場合)
- コンテキスト継承の初期化(必要な場合)
- completion/stopフックの初期化(空辞書)
パラメータ:
base_dir: コンテキストベースディレクトリ(Path)task_key: TaskKeyインスタンスconfig: アプリケーション設定辞書llm_client: LLMクライアント(オプション、コンテキスト継承用)
処理内容: MessageStoreインスタンスを返します。
戻り値: MessageStoreインスタンス
処理内容: SummaryStoreインスタンスを返します。
戻り値: SummaryStoreインスタンス
処理内容: ToolStoreインスタンスを返します。
戻り値: ToolStoreインスタンス
処理内容: PlanningHistoryStoreインスタンスを返します。
戻り値: PlanningHistoryStoreインスタンス
処理内容: LLMクライアントを設定します。コンテキスト圧縮とコンテキスト継承で使用されます。
パラメータ:
llm_client: LLMクライアントインスタンス
処理内容: 継承されたコンテキスト情報を取得します。
戻り値: InheritanceContextインスタンス(継承がない場合はNone)
処理内容: コンテキスト継承があるかどうかを判定します。
戻り値: bool(True: 継承あり、False: 継承なし)
処理内容: コンテキスト継承の通知コメントを取得します。
戻り値: str(通知コメント、継承がない場合はNone)
処理内容: 継承コンテキストを使用して初期コンテキストを作成します。
詳細処理:
ContextInheritanceManager.create_initial_context()を呼び出し- 前回タスクの要約とプランニング履歴から初期メッセージを生成
- MessageStoreに初期メッセージを追加
パラメータ:
system_message: システムメッセージ
処理内容: tasks.dbのタスクステータスを更新します。
詳細処理:
- tasks.dbに接続
- UUIDに基づきステータスを更新
- error_messageが指定されている場合、error_messageカラムも更新
- updated_atタイムスタンプを更新
パラメータ:
status: ステータス文字列("running", "completed", "failed", "paused")error_message: エラーメッセージ(オプション)
処理内容: tasks.dbのタスク統計情報を更新します。
詳細処理:
- tasks.dbに接続
- UUIDに基づき統計情報を更新:
total_messages: 総メッセージ数total_summaries: 総要約数total_tool_calls: 総ツール呼び出し数final_token_count: 最終トークン数final_message_count: 最終メッセージ数
- updated_atタイムスタンプを更新
パラメータ:
total_messages: 総メッセージ数total_summaries: 総要約数total_tool_calls: 総ツール呼び出し数final_token_count: 最終トークン数final_message_count: 最終メッセージ数
処理内容: タスク完了時に実行されるフック関数を登録します。
パラメータ:
hook_name: フック名hook_func: フック関数
処理内容: タスク停止時に実行されるフック関数を登録します。
パラメータ:
hook_name: フック名hook_func: フック関数
処理内容: タスクを正常完了として処理します。
詳細処理:
- 情報ログ出力
- 登録された完了フックを全て実行
- 最終要約の作成(LLMクライアントが設定されている場合)
- タスクDB更新とディレクトリ移動:
- ステータス: "completed"
- 統計情報の更新
- running/{uuid}/ → completed/{uuid}/
処理内容: タスクを一時停止として処理します。
詳細処理:
- 情報ログ出力
- 登録された停止フックを全て実行
- タスクDB更新とディレクトリ移動:
- ステータス: "paused"
- 統計情報の更新
- running/{uuid}/ → paused/{uuid}/
処理内容: タスクを失敗として処理します。
詳細処理:
- エラーログ出力
- タスクDB更新とディレクトリ移動:
- ステータス: "failed"
- error_messageの記録
- 統計情報の更新
- running/{uuid}/ → completed/{uuid}/
パラメータ:
error_message: エラーメッセージ
処理内容: タスクDBを更新し、コンテキストディレクトリを移動します。
詳細処理:
- 統計情報を収集:
- メッセージ数
- 要約数
- ツール呼び出し数
- 最終トークン数
- 最終メッセージ数
update_statistics()で統計情報を更新update_status()でステータスを更新- 移動先ディレクトリを決定:
- "paused": paused/{uuid}/
- その他: completed/{uuid}/
- 移動先の親ディレクトリを作成
shutil.move()でディレクトリを移動
パラメータ:
status: 最終ステータスerror_message: エラーメッセージ(オプション)
処理内容: タスク完了時に最終要約を作成します。
詳細処理:
- LLMクライアントの存在確認
ContextCompressorを初期化create_final_summary()を呼び出し- 最終要約の作成を試行
- エラー時は警告ログを出力して継続
処理内容: metadata.jsonファイルを作成します。
詳細処理:
- メタデータ辞書を作成:
uuid: タスクUUIDcreated_at: 作成日時(ISO形式)task_type: タスクタイプtask_identifier: タスク識別子repository: リポジトリ名user: ユーザー名
- JSON形式でmetadata.jsonに書き込み(インデント2)
処理内容: tasks.dbにタスクを登録または更新します。
詳細処理:
- tasks.dbに接続
- UUIDでタスクを検索
- 既存タスクが存在しない場合:
- INSERTクエリを実行
- 初期ステータス: "running"
- メタデータをJSON形式で保存
- 既存タスクが存在する場合(再開):
- UPDATEクエリを実行
- ステータスを"running"に変更
- 変更をコミット
ファイル: context_storage/message_store.py
メソッド: __init__(context_dir, config)
処理内容:
- パラメータを保存:
context_dir: コンテキストディレクトリconfig: アプリケーション設定
- ファイルパスを設定:
messages_file: messages.jsonl(全メッセージ履歴)current_file: current.jsonl(現在のコンテキスト)
_next_seqを初期化:- messages.jsonlが存在する場合、最大seq + 1
- 存在しない場合、1
処理内容: メッセージを追加します。
詳細処理:
- シーケンス番号を取得(
_get_next_seq()) - トークン数を推定:
- 文字数を4で割る(英語想定)
- 日本語文字が50%以上の場合、文字数を2で割る
- タイムスタンプを生成(ISO形式、UTC)
- messages.jsonlに追記:
- seq、role、content、timestamp、tokens、tool_name
- current.jsonlに追記:
- role、content、tool_name(OpenAI API互換形式)
- シーケンス番号を返す
パラメータ:
role: メッセージロール("system", "user", "assistant", "tool")content: メッセージ内容tool_name: ツール名(オプション)
戻り値: int(シーケンス番号)
処理内容: 現在のコンテキストファイルパスを返します。
詳細処理:
unsummarized_file_pathが指定されている場合:- そのパスを返す
- 指定されていない場合:
- current.jsonlのパスを返す
パラメータ:
unsummarized_file_path: 未要約ファイルパス(オプション)
戻り値: Path(コンテキストファイルパス)
処理内容: current.jsonlの推定トークン数を計算します。
詳細処理:
- current.jsonlが存在しない場合、0を返す
- current.jsonlの全行を読み込み
- 各行のcontentからトークン数を推定:
- 文字数を4で割る(英語想定)
- 日本語文字が50%以上の場合、文字数を2で割る
- 合計トークン数を返す
戻り値: int(推定トークン数)
処理内容: messages.jsonlのメッセージ数をカウントします。
詳細処理:
- messages.jsonlが存在しない場合、0を返す
- ファイルの行数をカウント
- 行数を返す
戻り値: int(メッセージ数)
処理内容: 圧縮後のコンテキストを再構築します。
詳細処理:
- current.jsonlを削除(存在する場合)
- current.jsonlに要約メッセージを書き込み:
- role: "system"
- content: summary
- unsummarized_fileが指定されている場合:
- unsummarized_fileの内容をcurrent.jsonlに追記
- unsummarized_fileを削除
- current.jsonlの行数をカウントして返す
パラメータ:
summary: 要約テキストunsummarized_file: 未要約ファイルパス(オプション)
戻り値: int(再構築後のメッセージ数)
処理内容: 次のシーケンス番号を取得して、内部カウンターを増加させます。
戻り値: int(次のシーケンス番号)
ファイル: context_storage/summary_store.py
メソッド: __init__(context_dir)
処理内容:
context_dirを保存summaries_fileパスを設定(summaries.jsonl)_next_idを初期化:- summaries.jsonlが存在する場合、最大id + 1
- 存在しない場合、1
処理内容: 要約を追加します。
詳細処理:
- ID番号を取得(
_get_next_id()) - タイムスタンプを生成(ISO形式、UTC)
- 要約レコードを作成:
- id、summary、compressed_message_count、tokens_saved、created_at
- summaries.jsonlに追記
- ID番号を返す
パラメータ:
summary: 要約テキストcompressed_count: 圧縮されたメッセージ数tokens_saved: 節約されたトークン数
戻り値: int(ID番号)
処理内容: 最新の要約を取得します。
詳細処理:
- summaries.jsonlが存在しない場合、Noneを返す
- ファイルの全行を読み込み
- 最後の行をJSONとしてパース
- 要約レコードを返す
戻り値: dict(要約レコード、存在しない場合はNone)
処理内容: summaries.jsonlの要約数をカウントします。
詳細処理:
- summaries.jsonlが存在しない場合、0を返す
- ファイルの行数をカウント
- 行数を返す
戻り値: int(要約数)
処理内容: 次のID番号を取得して、内部カウンターを増加させます。
戻り値: int(次のID番号)
ファイル: context_storage/tool_store.py
メソッド: __init__(context_dir)
処理内容:
context_dirを保存tools_fileパスを設定(tools.jsonl)_next_seqを初期化:- tools.jsonlが存在する場合、最大seq + 1
- 存在しない場合、1
処理内容: ツール呼び出しを記録します。
詳細処理:
- シーケンス番号を取得(
_get_next_seq()) - タイムスタンプを生成(ISO形式、UTC)
- ツール呼び出しレコードを作成:
- seq、tool_name、arguments、result、error、timestamp
- tools.jsonlに追記
- シーケンス番号を返す
パラメータ:
tool_name: ツール名arguments: 引数(dict)result: 実行結果(オプション)error: エラー情報(オプション)
戻り値: int(シーケンス番号)
処理内容: tools.jsonlのツール呼び出し数をカウントします。
詳細処理:
- tools.jsonlが存在しない場合、0を返す
- ファイルの行数をカウント
- 行数を返す
戻り値: int(ツール呼び出し数)
処理内容: 次のシーケンス番号を取得して、内部カウンターを増加させます。
戻り値: int(次のシーケンス番号)
ファイル: context_storage/context_compressor.py
メソッド: __init__(task_ctx, config, llm_client)
処理内容:
- パラメータを保存:
task_ctx: TaskContextManagerインスタンスconfig: アプリケーション設定llm_client: LLMクライアント
- 圧縮設定を取得:
token_threshold: 圧縮トリガーのトークン数(デフォルト: 8000)keep_recent: 圧縮時に保持する最近のメッセージ数(デフォルト: 10)min_to_compress: 圧縮する最小メッセージ数(デフォルト: 5)
処理内容: コンテキスト圧縮が必要かどうかを判定します。
詳細処理:
- 現在のトークン数を取得(
message_store.get_current_token_count()) - トークン数がthresholdを超えているかチェック
- 結果を返す
戻り値: bool(True: 圧縮必要、False: 圧縮不要)
処理内容: コンテキストを圧縮します。
詳細処理:
- 情報ログ出力(圧縮開始)
- 一時ファイルを作成:
to_summarize.jsonl: 要約対象メッセージunsummarized.jsonl: 未要約メッセージ(保持対象)request.jsonl: LLMリクエスト
- 要約対象メッセージを抽出(
_extract_messages_to_summarize()) - 抽出数が
min_to_compress未満の場合、圧縮をスキップ - 最近のメッセージを抽出(
_extract_recent_messages()) - LLMリクエストを作成(
_create_summary_request()) - LLMから要約を取得(
_get_summary_from_llm()) - 要約をSummaryStoreに保存
- current.jsonlを再構築(
message_store.recreate_current_context()) - 一時ファイルを削除
- 節約されたトークン数を返す
戻り値: int(節約されたトークン数)
処理内容: タスク完了時に最終要約を作成します。
詳細処理:
- 情報ログ出力(最終要約作成開始)
- 一時ファイルを作成:
all_messages.jsonl: 全メッセージrequest.jsonl: LLMリクエストfinal_summary.txt: 最終要約
- 全メッセージを抽出(
_extract_all_messages()) - 最終要約リクエストを作成(
_create_final_summary_request()) - LLMから要約を取得(
_get_summary_from_llm()) - final_summary.txtに書き込み
- 一時ファイルを削除
- 要約文字数を返す
戻り値: int(要約文字数)
処理内容: messages.jsonlから全メッセージを抽出してall_messages.jsonlに書き込みます。
詳細処理:
- messages.jsonlを開く
- 各行をJSONとしてパース
- OpenAI API形式でall_messages.jsonlに書き込み:
- role、content、tool_name(存在する場合)
- メッセージ数を返す
パラメータ:
output_file: 出力ファイルパス
戻り値: int(メッセージ数)
処理内容: 最終要約用のLLMリクエストを作成します。
詳細処理:
- システムメッセージを作成(
_final_summary_prompt()) - all_messages.jsonlの内容を読み込み
- システムメッセージと全メッセージを結合
- request.jsonlに書き込み
パラメータ:
messages_file: メッセージファイルパスoutput_file: 出力ファイルパス
処理内容: 最終要約用のシステムプロンプトを生成します。
戻り値: str(システムプロンプト)
処理内容: 最近のメッセージをunsummarized.jsonlに抽出します。
詳細処理:
- current.jsonlを開く
- 全行を読み込み
- 最後の
keep_recent行を抽出 - unsummarized.jsonlに書き込み
パラメータ:
output_file: 出力ファイルパス
処理内容: 要約対象メッセージをto_summarize.jsonlに抽出します。
詳細処理:
- current.jsonlを開く
- 全行を読み込み
- 最近の
keep_recent行を除外 - 残りをto_summarize.jsonlに書き込み
- 抽出されたメッセージ数を返す
パラメータ:
output_file: 出力ファイルパス
戻り値: int(抽出されたメッセージ数)
処理内容: 要約用のLLMリクエストを作成します。
詳細処理:
- システムメッセージを作成(
_default_summary_prompt()) - to_summarize.jsonlの内容を読み込み
- システムメッセージと要約対象メッセージを結合
- request.jsonlに書き込み
パラメータ:
to_summarize_file: 要約対象ファイルパスoutput_file: 出力ファイルパス
処理内容: LLMから要約を取得します。
詳細処理:
- request.jsonlを読み込み
- LLMクライアントの
create_chat_completion()を呼び出し - レスポンスから要約テキストを抽出
- 要約テキストを返す
パラメータ:
request_file: リクエストファイルパス
戻り値: str(要約テキスト)
処理内容: デフォルトの要約プロンプトを生成します。
戻り値: str(システムプロンプト)
ファイル: context_storage/context_inheritance_manager.py
メソッド: __init__(base_dir, config)
処理内容:
- パラメータを保存:
base_dir: コンテキストベースディレクトリconfig: アプリケーション設定
- tasks.dbのパスを設定
- 継承設定を取得:
max_summary_tokens: 要約の最大トークン数(デフォルト: 4000)
処理内容: 前回のタスクコンテキストを検索します。
詳細処理:
- タスクキーから検索条件を構築:
task_type: タスクタイプtask_identifier: タスク識別子(Issue番号、PR番号等)repository: リポジトリ名user: ユーザー名
- tasks.dbから前回タスクを検索:
- 条件一致
- ステータス: "completed"または"failed"
- 降順(completed_at DESC)
- 検索結果をPreviousContextのリストとして返す
パラメータ:
task_key: TaskKeyインスタンス
戻り値: list[PreviousContext](前回タスクのリスト)
処理内容: 指定されたUUIDの継承コンテキストを取得します。
詳細処理:
- tasks.dbから前回タスクを検索
- タスクが存在しない場合、Noneを返す
_build_previous_context_from_db()で詳細情報を構築- InheritanceContextインスタンスを作成して返す
パラメータ:
previous_uuid: 前回タスクのUUID
戻り値: InheritanceContext(継承コンテキスト、存在しない場合はNone)
処理内容: 継承コンテキストから初期コンテキストメッセージを作成します。
詳細処理:
- 最終要約を取得
- プランニング履歴サマリーを作成(
_build_planning_summary()) - 初期メッセージを構築:
- 前回タスクの要約
- プランニング履歴
- 継続作業の指示
- MessageStoreに追加
- 追加されたメッセージのseq番号を返す
パラメータ:
task_ctx: TaskContextManagerインスタンスinheritance_ctx: InheritanceContextインスタンス
戻り値: int(追加されたメッセージのseq番号)
処理内容: 継承コンテキストに関する通知コメントを生成します。
詳細処理:
- 通知テンプレートを作成:
- 前回タスクのUUID
- 前回タスクのステータス
- 完了日時
- フォーマットされた通知コメントを返す
パラメータ:
inheritance_ctx: InheritanceContextインスタンス
戻り値: str(通知コメント)
処理内容: データベースから前回タスクの詳細情報を構築します。
詳細処理:
- 最終要約を読み込み(
_load_final_summary()) - メタデータを読み込み(
_load_metadata()) - プランニング履歴を読み込み(
_load_planning_history()) - PreviousContextインスタンスを作成して返す
パラメータ:
uuid: タスクUUIDstatus: タスクステータスcompleted_at: 完了日時
戻り値: PreviousContext
処理内容: final_summary.txtを読み込みます。
詳細処理:
- completedディレクトリのfinal_summary.txtを検索
- ファイルが存在しない場合、Noneを返す
- ファイル内容を読み込んで返す
パラメータ:
uuid: タスクUUID
戻り値: str(最終要約、存在しない場合はNone)
処理内容: metadata.jsonを読み込みます。
詳細処理:
- completedディレクトリのmetadata.jsonを検索
- ファイルが存在しない場合、空辞書を返す
- JSONファイルをパースして返す
パラメータ:
uuid: タスクUUID
戻り値: dict(メタデータ)
処理内容: planning.jsonlを読み込みます。
詳細処理:
- completedディレクトリのplanning.jsonlを検索
- ファイルが存在しない場合、空リストを返す
- 各行をJSONとしてパースしてリストに追加
- プランニング履歴リストを返す
パラメータ:
uuid: タスクUUID
戻り値: list[dict](プランニング履歴)
処理内容: プランニング履歴からサマリーを作成します。
詳細処理:
- プランニング履歴が空の場合、空文字列を返す
- 各プランニングエントリーをフォーマット:
- タイムスタンプ
- プランタイプ
- プラン内容
- フォーマットされたサマリーを返す
- トークン数制限を超える場合、切り詰め(
_truncate_summary_if_needed())
パラメータ:
planning_history: プランニング履歴リスト
戻り値: str(プランニングサマリー)
処理内容: サマリーが最大トークン数を超える場合、切り詰めます。
詳細処理:
- トークン数を推定
- 最大トークン数を超えていない場合、そのまま返す
- 超えている場合:
- 最大文字数を計算
- サマリーを切り詰め
- 切り詰めメッセージを追加
- 切り詰められたサマリーを返す
パラメータ:
summary: サマリーテキスト
戻り値: str(切り詰められたサマリー)
処理内容: サマリーにプレフィックスを付与してフォーマットします。
パラメータ:
summary: サマリーテキストprefix: プレフィックス
戻り値: str(フォーマットされたサマリー)
ファイル: context_storage/context_inheritance_manager.py
フィールド:
uuid: タスクUUID(str)status: タスクステータス(str)completed_at: 完了日時(datetime)metadata: メタデータ(dict)final_summary: 最終要約(str、オプション)planning_history: プランニング履歴(list、オプション)
用途: 前回タスクの基本情報を保持
ファイル: context_storage/context_inheritance_manager.py
フィールド:
uuid: 継承元タスクUUID(str)final_summary: 最終要約(str)planning_history: プランニング履歴(list)metadata: メタデータ(dict)
用途: コンテキスト継承時の詳細情報を保持
flowchart TD
A[TaskContextManager.__init__] --> B{再開タスク?}
B -->|Yes| C[paused/{uuid}/を使用]
B -->|No| D[running/{uuid}/を作成]
C --> E[サブストア初期化]
D --> E
E --> F[MessageStore]
E --> G[SummaryStore]
E --> H[ToolStore]
E --> I[PlanningHistoryStore]
F --> J{新規タスク?}
G --> J
H --> J
I --> J
J -->|Yes| K[tasks.db INSERT]
J -->|No| L[tasks.db UPDATE<br/>status=running]
K --> M[metadata.json作成]
L --> N{コンテキスト継承?}
M --> N
N -->|Yes| O[ContextInheritanceManager初期化]
N -->|No| P[完了]
O --> Q[前回タスク検索]
Q --> R[継承コンテキスト構築]
R --> P
style A fill:#e1f5ff
style P fill:#ccffcc
flowchart TD
A[add_message] --> B[シーケンス番号取得]
B --> C[トークン数推定]
C --> D{日本語50%以上?}
D -->|Yes| E[文字数÷2]
D -->|No| F[文字数÷4]
E --> G[タイムスタンプ生成]
F --> G
G --> H[messages.jsonlに追記<br/>seq,role,content,timestamp,tokens,tool_name]
H --> I[current.jsonlに追記<br/>role,content,tool_name]
I --> J[シーケンス番号を返す]
style A fill:#e1f5ff
style J fill:#ccffcc
flowchart TD
A[compress] --> B[一時ファイル作成]
B --> C[要約対象メッセージ抽出<br/>to_summarize.jsonl]
C --> D{抽出数≥min_to_compress?}
D -->|No| E[圧縮スキップ]
D -->|Yes| F[最近のメッセージ抽出<br/>unsummarized.jsonl]
F --> G[LLMリクエスト作成<br/>request.jsonl]
G --> H[LLMから要約取得]
H --> I[SummaryStoreに保存]
I --> J[current.jsonl再構築<br/>要約+unsummarized]
J --> K[一時ファイル削除]
K --> L[節約トークン数を返す]
E --> M[0を返す]
style A fill:#e1f5ff
style L fill:#ccffcc
style M fill:#ccffcc
sequenceDiagram
participant Handler
participant TaskCtx
participant Hooks
participant Compressor
participant DB
participant FileSystem
Handler->>TaskCtx: complete()
TaskCtx->>TaskCtx: ログ出力
TaskCtx->>Hooks: 完了フック実行
TaskCtx->>Compressor: create_final_summary()
Compressor->>Compressor: 全メッセージ抽出
Compressor->>Compressor: LLMリクエスト作成
Compressor->>Compressor: LLMから最終要約取得
Compressor->>FileSystem: final_summary.txt書き込み
Compressor-->>TaskCtx: 完了
TaskCtx->>TaskCtx: _finalize_task_db_and_move()
TaskCtx->>TaskCtx: 統計情報収集
TaskCtx->>DB: update_statistics()
TaskCtx->>DB: update_status(completed)
TaskCtx->>FileSystem: running/{uuid}/ → completed/{uuid}/
TaskCtx-->>Handler: 完了
flowchart TD
A[新規タスク開始] --> B[ContextInheritanceManager<br/>find_previous_contexts]
B --> C[tasks.db検索<br/>同一task_type/identifier/repo/user]
C --> D{前回タスク存在?}
D -->|No| E[コンテキスト継承なし]
D -->|Yes| F[get_inheritance_context]
F --> G[final_summary.txt読み込み]
F --> H[metadata.json読み込み]
F --> I[planning.jsonl読み込み]
G --> J[InheritanceContext作成]
H --> J
I --> J
J --> K[create_initial_context]
K --> L[初期メッセージ作成<br/>要約+プランニング履歴+指示]
L --> M[MessageStoreに追加]
M --> N[generate_notification_comment]
N --> O[通知コメント生成]
O --> P[タスク処理開始]
E --> P
style A fill:#e1f5ff
style P fill:#ccffcc
形式: JSON Lines(1行1メッセージ)
フィールド:
{
"seq": 1,
"role": "user",
"content": "メッセージ内容",
"timestamp": "2024-12-07T03:00:00+00:00",
"tokens": 150,
"tool_name": "function_name"
}形式: JSON Lines(OpenAI API互換)
フィールド:
{
"role": "user",
"content": "メッセージ内容",
"tool_name": "function_name"
}形式: JSON Lines(1行1要約)
フィールド:
{
"id": 1,
"summary": "要約テキスト",
"compressed_message_count": 50,
"tokens_saved": 5000,
"created_at": "2024-12-07T03:00:00+00:00"
}形式: JSON Lines(1行1ツール呼び出し)
フィールド:
{
"seq": 1,
"tool_name": "function_name",
"arguments": {"arg1": "value1"},
"result": "実行結果",
"error": null,
"timestamp": "2024-12-07T03:00:00+00:00"
}形式: JSON Lines(1行1プランニングエントリー)
フィールド:
{
"id": 1,
"plan_type": "initial",
"plan_content": "プラン内容",
"created_at": "2024-12-07T03:00:00+00:00"
}形式: JSON
フィールド:
{
"uuid": "task-uuid",
"created_at": "2024-12-07T03:00:00+00:00",
"task_type": "github_issue",
"task_identifier": "123",
"repository": "owner/repo",
"user": "username"
}形式: プレーンテキスト
内容: タスク全体の最終要約(LLMにより生成)
CREATE TABLE tasks (
uuid TEXT PRIMARY KEY,
status TEXT NOT NULL,
task_type TEXT NOT NULL,
task_identifier TEXT,
repository TEXT,
user TEXT,
created_at TEXT NOT NULL,
updated_at TEXT,
completed_at TEXT,
metadata TEXT,
total_messages INTEGER DEFAULT 0,
total_summaries INTEGER DEFAULT 0,
total_tool_calls INTEGER DEFAULT 0,
final_token_count INTEGER,
final_message_count INTEGER,
error_message TEXT
);
CREATE INDEX idx_tasks_status ON tasks(status);
CREATE INDEX idx_tasks_task_type ON tasks(task_type);
CREATE INDEX idx_tasks_repository ON tasks(repository);
CREATE INDEX idx_tasks_user ON tasks(user);
CREATE INDEX idx_tasks_completed_at ON tasks(completed_at);フィールド説明:
uuid: タスクの一意識別子status: タスクステータス("running", "completed", "failed", "paused")task_type: タスクタイプ("github_issue", "gitlab_mr"等)task_identifier: タスク識別子(Issue番号、MR番号等)repository: リポジトリ名("owner/repo"形式)user: ユーザー名created_at: 作成日時(ISO形式)updated_at: 更新日時(ISO形式)completed_at: 完了日時(ISO形式)metadata: メタデータ(JSON形式)total_messages: 総メッセージ数total_summaries: 総要約数total_tool_calls: 総ツール呼び出し数final_token_count: 最終トークン数final_message_count: 最終メッセージ数error_message: エラーメッセージ
context:
# コンテキストベースディレクトリ
base_dir: "contexts"
# コンテキスト圧縮設定
compression:
token_threshold: 8000 # 圧縮トリガーのトークン数
keep_recent: 10 # 圧縮時に保持する最近のメッセージ数
min_to_compress: 5 # 圧縮する最小メッセージ数
# コンテキスト継承設定
inheritance:
enabled: true # コンテキスト継承を有効化
max_summary_tokens: 4000 # 継承要約の最大トークン数完了タスクのアーカイブ:
# 30日以上前の完了タスクを削除
find contexts/completed -type d -name "*-*-*-*-*" -mtime +30 -exec rm -rf {} +データベースのバキューム:
sqlite3 contexts/tasks.db "VACUUM;"コンテキストが見つからない:
- tasks.dbを確認
- ディレクトリの存在確認
- ログでUUIDを確認
圧縮が動作しない:
- トークン数を確認(
get_current_token_count()) token_threshold設定を確認- LLMクライアントが設定されているか確認
継承が動作しない:
- 前回タスクのステータスを確認(completedまたはfailed)
- final_summary.txtの存在確認
- task_type/identifier/repository/userの一致確認
- 完全な履歴保存: 全メッセージ、要約、ツール呼び出しを永続化
- 自動コンテキスト圧縮: トークン制限対応のための自動圧縮
- コンテキスト継承: 前回タスクからのシームレスな引き継ぎ
- 柔軟な状態管理: running/completed/paused/failedの状態遷移
- 統計情報記録: タスクの実行統計を自動収集
- SQLiteベース(1タスク1プロセス前提)
- トークン数は推定値(厳密ではない)
- LLMクライアントが必要(圧縮・最終要約用)
- CONTEXT_FILE_SPEC.md - コンテキストファイル化仕様
- CONTEXT_INHERITANCE_SPECIFICATION.md - コンテキスト継承仕様
- MAIN_SPEC.md - main.pyの詳細設計
文書バージョン: 2.0
最終更新日: 2024-12-07
ステータス: 実装済み・設計書