feat: scratchpad tool + fix Claude auth token expiry warning

- Add cortex/tools/scratch.py with scratch_read/write/append/clear tools
- Register all four scratch tools in the orchestrator tool registry
- Create inara/SCRATCH.md as the backing file (never distilled/archived)
- Fix auth.py: expiresAt reflects short-lived access token (~8h) not the
  1-year refresh token — suppress expiry warning when refreshToken is present

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-20 21:10:03 -04:00
parent 31a5ef0541
commit 1b32667872
4 changed files with 169 additions and 4 deletions

View File

@@ -23,6 +23,12 @@ from tools.files import file_read as _file_read
from tools.system import claude_allow_dir as _claude_allow_dir
from tools.tasks import task_list as _task_list, task_create as _task_create
from tools.tasks import task_update as _task_update, task_complete as _task_complete
from tools.scratch import (
scratch_read as _scratch_read,
scratch_write as _scratch_write,
scratch_append as _scratch_append,
scratch_clear as _scratch_clear,
)
# ---------------------------------------------------------------------------
@@ -179,6 +185,10 @@ _CALLABLES: dict[str, callable] = {
"task_create": _task_create,
"task_update": _task_update,
"task_complete": _task_complete,
"scratch_read": _scratch_read,
"scratch_write": _scratch_write,
"scratch_append": _scratch_append,
"scratch_clear": _scratch_clear,
}
_claude_allow_dir_declaration = types.FunctionDeclaration(
@@ -305,6 +315,64 @@ _task_complete_declaration = types.FunctionDeclaration(
),
)
_scratch_read_declaration = types.FunctionDeclaration(
name="scratch_read",
description=(
"Read the full contents of the scratchpad. "
"Use this to recall working notes, mid-task context, or anything previously jotted down. "
"The scratchpad is transient — nothing here is distilled or archived."
),
parameters=types.Schema(type=types.Type.OBJECT, properties={}),
)
_scratch_write_declaration = types.FunctionDeclaration(
name="scratch_write",
description=(
"Replace the entire scratchpad with new content. "
"Use this to set a clean working note, replacing whatever was there before. "
"For adding without replacing, use scratch_append instead."
),
parameters=types.Schema(
type=types.Type.OBJECT,
properties={
"content": types.Schema(
type=types.Type.STRING,
description="The new scratchpad content (markdown supported)",
),
},
required=["content"],
),
)
_scratch_append_declaration = types.FunctionDeclaration(
name="scratch_append",
description=(
"Add a new section to the bottom of the scratchpad without replacing existing content. "
"Each section gets a timestamp heading unless you supply one."
),
parameters=types.Schema(
type=types.Type.OBJECT,
properties={
"content": types.Schema(
type=types.Type.STRING,
description="The content to append (markdown supported)",
),
"heading": types.Schema(
type=types.Type.STRING,
description="Optional section heading. Defaults to current UTC timestamp.",
),
},
required=["content"],
),
)
_scratch_clear_declaration = types.FunctionDeclaration(
name="scratch_clear",
description="Erase everything in the scratchpad. Use when the working notes are no longer needed.",
parameters=types.Schema(type=types.Type.OBJECT, properties={}),
)
# Gemini Tool object — pass this to GenerateContentConfig
TOOL_DECLARATIONS = [
types.Tool(function_declarations=[
@@ -318,6 +386,10 @@ TOOL_DECLARATIONS = [
_task_create_declaration,
_task_update_declaration,
_task_complete_declaration,
_scratch_read_declaration,
_scratch_write_declaration,
_scratch_append_declaration,
_scratch_clear_declaration,
])
]