better-notion 1.5.4__py3-none-any.whl → 1.6.0__py3-none-any.whl

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.
@@ -0,0 +1,369 @@
1
+ """Agents plugin schema for AI agent documentation.
2
+
3
+ This module provides comprehensive documentation about the agents workflow
4
+ system that AI agents can consume to understand how to work with the system.
5
+
6
+ This is the SINGLE SOURCE OF TRUTH for agents documentation. All other
7
+ documentation (CLI help, website, etc.) should be derived from this schema.
8
+ """
9
+
10
+ from better_notion._cli.docs.base import (
11
+ Command,
12
+ Concept,
13
+ Schema,
14
+ Workflow,
15
+ WorkflowStep,
16
+ )
17
+
18
+ # =============================================================================
19
+ # CONCEPTS
20
+ # =============================================================================
21
+
22
+ WORKSPACE_CONCEPT = Concept(
23
+ name="workspace",
24
+ description=(
25
+ "A workspace is a collection of 8 interconnected databases that implement "
26
+ "a complete software development workflow management system. It provides "
27
+ "the structure for tracking organizations, projects, versions, tasks, ideas, "
28
+ "work issues, and incidents in a unified manner."
29
+ ),
30
+ properties={
31
+ "databases": [
32
+ "Organizations",
33
+ "Tags",
34
+ "Projects",
35
+ "Versions",
36
+ "Tasks",
37
+ "Ideas",
38
+ "Work Issues",
39
+ "Incidents",
40
+ ],
41
+ "initialization": "Created via 'agents init' command",
42
+ "detection": "Automatically detected by scanning for expected databases",
43
+ "uniqueness": "One workspace per Notion page",
44
+ },
45
+ relationships={
46
+ "Organizations → Projects": "Many-to-one (many projects belong to one organization)",
47
+ "Projects → Versions": "Many-to-one (many versions belong to one project)",
48
+ "Versions → Tasks": "Many-to-one (many tasks belong to one version)",
49
+ "Tasks → Tasks": "Self-referential (tasks can depend on other tasks)",
50
+ },
51
+ )
52
+
53
+ TASK_CONCEPT = Concept(
54
+ name="task",
55
+ description=(
56
+ "A task represents a unit of work that needs to be completed as part of "
57
+ "a project version. Tasks have states (Todo, In Progress, Done, Cancelled) "
58
+ "and can depend on other tasks."
59
+ ),
60
+ properties={
61
+ "required_properties": {
62
+ "Title": "Task name (title property)",
63
+ "Status": "Current state: Todo, In Progress, Done, Cancelled",
64
+ "Version": "Relation to Version database (required)",
65
+ },
66
+ "optional_properties": {
67
+ "Target Version": "Version where task should be implemented",
68
+ "Dependencies": "Other tasks this task depends on",
69
+ "Dependent Tasks": "Tasks that depend on this task",
70
+ },
71
+ "workflow": "Todo → In Progress → Done",
72
+ },
73
+ relationships={
74
+ "Version": "Required - each task must belong to one version",
75
+ "Dependencies": "Optional - tasks that must complete before this task",
76
+ "Dependent Tasks": "Inverse of dependencies - tasks blocked by this task",
77
+ },
78
+ )
79
+
80
+ PROJECT_CONCEPT = Concept(
81
+ name="project",
82
+ description=(
83
+ "A project represents a software project or product being developed. "
84
+ "Projects belong to organizations and contain multiple versions."
85
+ ),
86
+ properties={
87
+ "required_properties": {
88
+ "Title": "Project name",
89
+ "Organization": "Relation to organization (required)",
90
+ },
91
+ "contains": ["Versions", "Tasks", "Ideas", "Work Issues", "Incidents"],
92
+ },
93
+ relationships={
94
+ "Organization": "Required - each project belongs to one organization",
95
+ "Versions": "One-to-many - project contains multiple versions",
96
+ },
97
+ )
98
+
99
+ VERSION_CONCEPT = Concept(
100
+ name="version",
101
+ description=(
102
+ "A version represents a release or milestone of a project. Examples: "
103
+ "v1.0.0, v1.1.0, v2.0.0. Tasks are created within versions."
104
+ ),
105
+ properties={
106
+ "required_properties": {
107
+ "Title": "Version name (e.g., v1.0.0)",
108
+ "Project": "Relation to project (required)",
109
+ },
110
+ "contains": ["Tasks"],
111
+ "examples": ["v1.0.0", "v1.1.0", "v2.0.0-beta", "sprint-1"],
112
+ },
113
+ relationships={
114
+ "Project": "Required - each version belongs to one project",
115
+ "Tasks": "One-to-many - version contains multiple tasks",
116
+ },
117
+ )
118
+
119
+ # =============================================================================
120
+ # WORKFLOWS
121
+ # =============================================================================
122
+
123
+ INITIALIZE_WORKSPACE = Workflow(
124
+ name="initialize_workspace",
125
+ description="Create a complete agents workflow management system with 8 databases",
126
+ steps=[
127
+ WorkflowStep(
128
+ description="Detect existing workspace in page",
129
+ purpose="Prevent duplicate workspace creation",
130
+ ),
131
+ WorkflowStep(
132
+ description="Create Organizations database",
133
+ command="notion databases create --parent PAGE_ID --title Organizations",
134
+ ),
135
+ WorkflowStep(
136
+ description="Create Tags database",
137
+ command="notion databases create --parent PAGE_ID --title Tags",
138
+ ),
139
+ WorkflowStep(
140
+ description="Create Projects database",
141
+ command="notion databases create --parent PAGE_ID --title Projects",
142
+ ),
143
+ WorkflowStep(
144
+ description="Create Versions database",
145
+ command="notion databases create --parent PAGE_ID --title Versions",
146
+ ),
147
+ WorkflowStep(
148
+ description="Create Tasks database",
149
+ command="notion databases create --parent PAGE_ID --title Tasks",
150
+ ),
151
+ WorkflowStep(
152
+ description="Create Ideas database",
153
+ command="notion databases create --parent PAGE_ID --title Ideas",
154
+ ),
155
+ WorkflowStep(
156
+ description="Create Work Issues database",
157
+ command="notion databases create --parent PAGE_ID --title 'Work Issues'",
158
+ ),
159
+ WorkflowStep(
160
+ description="Create Incidents database",
161
+ command="notion databases create --parent PAGE_ID --title Incidents",
162
+ ),
163
+ WorkflowStep(
164
+ description="Establish database relationships",
165
+ purpose="Create relations between databases (Projects→Organizations, etc.)",
166
+ ),
167
+ WorkflowStep(
168
+ description="Save workspace metadata",
169
+ command="agents info --parent-page PAGE_ID",
170
+ purpose="Verify setup and get database IDs",
171
+ ),
172
+ ],
173
+ commands=[
174
+ "agents init --parent-page PAGE_ID",
175
+ "agents info --parent-page PAGE_ID",
176
+ ],
177
+ prerequisites=["valid_page_id"],
178
+ error_recovery={
179
+ "workspace_exists": {
180
+ "message": "Detected 5+ expected databases in page",
181
+ "meaning": "Workspace already initialized in this page",
182
+ "solutions": [
183
+ {
184
+ "flag": "--skip",
185
+ "action": "use_existing_workspace",
186
+ "description": "Skip initialization and use existing workspace",
187
+ "when_to_use": "You want to keep existing data",
188
+ },
189
+ {
190
+ "flag": "--reset",
191
+ "action": "recreate_workspace",
192
+ "description": "Delete all databases and recreate (WARNING: data loss)",
193
+ "warning": "This will delete all existing databases and their content",
194
+ "when_to_use": "You want to start completely fresh",
195
+ },
196
+ ],
197
+ }
198
+ },
199
+ )
200
+
201
+ CREATE_TASK_WORKFLOW = Workflow(
202
+ name="create_task",
203
+ description="Create a new task in the agents workflow system",
204
+ steps=[
205
+ WorkflowStep(
206
+ description="Verify workspace is initialized",
207
+ command="agents info --parent-page PAGE_ID",
208
+ purpose="Get database IDs and verify workspace exists",
209
+ ),
210
+ WorkflowStep(
211
+ description="Identify target Version",
212
+ purpose="Tasks must belong to a Version (required relation)",
213
+ ),
214
+ WorkflowStep(
215
+ description="Create task page with proper properties",
216
+ command="notion pages create --parent TASKS_DB_ID --title 'Task Name' --properties '{...}'",
217
+ purpose="Create task with Status and Version relation",
218
+ ),
219
+ ],
220
+ commands=[
221
+ "agents info --parent-page PAGE_ID",
222
+ "notion pages create --parent TASKS_DB_ID --title 'Task' --properties '{\"Status\": \"Todo\", \"Version\": \"VERSION_ID\"}'",
223
+ ],
224
+ prerequisites=["workspace_initialized"],
225
+ error_recovery={
226
+ "workspace_not_found": {
227
+ "message": "No workspace detected in page",
228
+ "solution": "Run 'agents init' first to create workspace",
229
+ },
230
+ "missing_version_relation": {
231
+ "message": "Task must have a Version relation",
232
+ "solution": "Always specify Version property when creating task",
233
+ },
234
+ },
235
+ )
236
+
237
+ QUERY_TASKS_WORKFLOW = Workflow(
238
+ name="query_tasks",
239
+ description="Query and filter tasks in the workspace",
240
+ steps=[
241
+ WorkflowStep(
242
+ description="Get workspace database IDs",
243
+ command="agents info --parent-page PAGE_ID",
244
+ purpose="Obtain tasks database ID",
245
+ ),
246
+ WorkflowStep(
247
+ description="Query tasks database",
248
+ command="notion databases query --database TASKS_DB_ID --filter '{...}'",
249
+ purpose="Retrieve tasks with optional filtering",
250
+ ),
251
+ ],
252
+ commands=[
253
+ "agents info --parent-page PAGE_ID",
254
+ "notion databases query --database TASKS_DB_ID",
255
+ ],
256
+ prerequisites=["workspace_initialized"],
257
+ )
258
+
259
+ # =============================================================================
260
+ # COMMANDS
261
+ # =============================================================================
262
+
263
+ INIT_COMMAND = Command(
264
+ name="init",
265
+ purpose="Initialize a new agents workspace or manage existing one",
266
+ description=(
267
+ "Creates a complete workflow management system with 8 databases "
268
+ "and their relationships. Can detect existing workspaces to prevent duplicates."
269
+ ),
270
+ flags={
271
+ "--parent-page": "Parent page ID where workspace will be created",
272
+ "--workspace-name": "Name for the workspace (default: 'Agents Workspace')",
273
+ "--reset": "Force recreation (deletes existing databases and recreates)",
274
+ "--skip": "Skip initialization if workspace already exists",
275
+ "--debug": "Enable debug output",
276
+ },
277
+ workflow="initialize_workspace",
278
+ when_to_use=[
279
+ "First time setting up agents system in a page",
280
+ "Starting fresh in a new page",
281
+ "Recovering from corrupted workspace (use --reset)",
282
+ "Safely checking for existing workspace (use --skip)",
283
+ ],
284
+ error_recovery={
285
+ "workspace_exists": {
286
+ "solutions": [
287
+ {"flag": "--skip", "use_case": "Keep existing workspace"},
288
+ {"flag": "--reset", "use_case": "Delete and recreate (data loss)"},
289
+ ]
290
+ }
291
+ },
292
+ )
293
+
294
+ INFO_COMMAND = Command(
295
+ name="info",
296
+ purpose="Display workspace status and metadata",
297
+ description="Shows whether a workspace exists, database IDs, and workspace info",
298
+ flags={
299
+ "--parent-page": "Parent page ID to check for workspace",
300
+ },
301
+ workflow=None,
302
+ when_to_use=[
303
+ "Verify workspace initialization",
304
+ "Get database IDs for queries",
305
+ "Check workspace version and metadata",
306
+ "Debug workspace issues",
307
+ ],
308
+ )
309
+
310
+ # =============================================================================
311
+ # COMPLETE SCHEMA
312
+ # =============================================================================
313
+
314
+ AGENTS_SCHEMA = Schema(
315
+ name="agents",
316
+ version="1.0.0",
317
+ description=(
318
+ "Workflow management system for software development. "
319
+ "Provides complete structure for tracking organizations, projects, "
320
+ "versions, tasks, ideas, work issues, and incidents."
321
+ ),
322
+ concepts=[
323
+ WORKSPACE_CONCEPT,
324
+ TASK_CONCEPT,
325
+ PROJECT_CONCEPT,
326
+ VERSION_CONCEPT,
327
+ ],
328
+ workflows=[
329
+ INITIALIZE_WORKSPACE,
330
+ CREATE_TASK_WORKFLOW,
331
+ QUERY_TASKS_WORKFLOW,
332
+ ],
333
+ commands={
334
+ "init": INIT_COMMAND,
335
+ "info": INFO_COMMAND,
336
+ },
337
+ best_practices=[
338
+ "Always run 'agents info' before database operations to verify workspace state",
339
+ "Use --skip flag to safely check for existing workspaces (prevents duplicates)",
340
+ "Use --reset flag only when you need to recreate workspace (causes data loss)",
341
+ "Tasks must have a Version relation - always specify Version property",
342
+ "Check task dependencies before marking tasks as complete",
343
+ "Projects belong to Organizations - create organization first",
344
+ "Versions belong to Projects - create project first",
345
+ "Query tasks by Status to find next available task",
346
+ ],
347
+ examples={
348
+ "initial_setup": """# First time setup
349
+ notion agents init --parent-page PAGE_ID
350
+
351
+ # Verify setup
352
+ notion agents info --parent-page PAGE_ID""",
353
+
354
+ "safe_initialization": """# Check if workspace exists, use if found
355
+ notion agents init --parent-page PAGE_ID --skip""",
356
+
357
+ "force_recreate": """# Delete existing workspace and recreate (WARNING: data loss)
358
+ notion agents init --parent-page PAGE_ID --reset""",
359
+
360
+ "query_workspace": """# Get workspace info and database IDs
361
+ notion agents info --parent-page PAGE_ID""",
362
+
363
+ "create_task": """# After workspace is initialized
364
+ notion pages create \\
365
+ --parent TASKS_DB_ID \\
366
+ --title "Fix login bug" \\
367
+ --properties '{"Status": "Todo", "Version": "VERSION_ID"}'""",
368
+ },
369
+ )
@@ -0,0 +1,185 @@
1
+ """Workspace metadata management for agents plugin.
2
+
3
+ This module provides functionality to manage workspace metadata,
4
+ including detecting duplicate workspaces and storing workspace information.
5
+ """
6
+
7
+ import json
8
+ import logging
9
+ from datetime import datetime, timezone
10
+ from pathlib import Path
11
+ from typing import Any, Optional
12
+ from uuid import uuid4
13
+
14
+ from better_notion._sdk.client import NotionClient
15
+ from better_notion._sdk.models.page import Page
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class WorkspaceMetadata:
21
+ """Manage workspace metadata for duplicate detection."""
22
+
23
+ # Property names used in Notion page
24
+ PROP_WORKSPACE_ID = "agents_workspace_id"
25
+ PROP_WORKSPACE_NAME = "agents_workspace_name"
26
+ PROP_INITIALIZED_AT = "agents_workspace_created"
27
+ PROP_VERSION = "agents_workspace_version"
28
+ PROP_DATABASE_IDS = "agents_workspace_databases"
29
+
30
+ @staticmethod
31
+ def generate_workspace_id() -> str:
32
+ """Generate a unique workspace ID.
33
+
34
+ Returns:
35
+ Unique workspace ID (UUID without hyphens for compactness)
36
+ """
37
+ return str(uuid4()).replace("-", "")
38
+
39
+ @staticmethod
40
+ def extract_metadata_from_page(page: Page) -> dict[str, Any]:
41
+ """Extract workspace metadata from page properties.
42
+
43
+ Args:
44
+ page: Page object to extract metadata from
45
+
46
+ Returns:
47
+ Dict with workspace metadata (empty if not initialized)
48
+
49
+ Example:
50
+ >>> metadata = WorkspaceMetadata.extract_metadata_from_page(page)
51
+ >>> if metadata.get("workspace_id"):
52
+ ... print(f"Workspace: {metadata['workspace_name']}")
53
+ """
54
+ metadata = {}
55
+
56
+ # Try to get workspace ID from icon (stored as emoji)
57
+ # Notion doesn't support custom properties, so we use creative approaches
58
+
59
+ # Check if page icon contains our metadata marker
60
+ icon = page.icon
61
+ if icon and icon.startswith("🤖"):
62
+ metadata["is_agents_workspace"] = True
63
+ # Could encode data in icon, but keep it simple for now
64
+
65
+ return metadata
66
+
67
+ @staticmethod
68
+ async def detect_workspace(
69
+ page: Page,
70
+ client: NotionClient
71
+ ) -> dict[str, Any] | None:
72
+ """Detect if page already has an agents workspace.
73
+
74
+ Args:
75
+ page: Parent page to check
76
+ client: NotionClient instance
77
+
78
+ Returns:
79
+ Workspace metadata dict if found, None otherwise
80
+ """
81
+ # Primary detection: Scan for databases with expected names
82
+ expected_databases = [
83
+ "Organizations",
84
+ "Tags",
85
+ "Projects",
86
+ "Versions",
87
+ "Tasks",
88
+ "Ideas",
89
+ "Work Issues",
90
+ "Incidents"
91
+ ]
92
+
93
+ try:
94
+ # Search for databases in this page
95
+ results = await client.search(
96
+ query="",
97
+ filter={"value": "database", "property": "object"}
98
+ )
99
+
100
+ databases_found = []
101
+ database_ids = {}
102
+
103
+ for result in results:
104
+ if hasattr(result, 'title') and result.title in expected_databases:
105
+ databases_found.append(result.title)
106
+ # Extract the key name (lowercase with underscores)
107
+ key = result.title.lower().replace(" ", "_")
108
+ database_ids[key] = result.id
109
+
110
+ # Check if we have at least 5 of the expected databases
111
+ matches = len(databases_found)
112
+ if matches >= 5:
113
+ logger.info(f"Detected existing workspace with {matches}/{len(expected_databases)} databases in page {page.id}")
114
+
115
+ # Try to load workspace metadata from local config to get workspace_id
116
+ workspace_id = None
117
+ workspace_name = None
118
+ initialized_at = None
119
+
120
+ try:
121
+ config_path = Path.home() / ".notion" / "workspace.json"
122
+ if config_path.exists():
123
+ with open(config_path, "r", encoding="utf-8") as f:
124
+ config = json.load(f)
125
+ # Only use config if it matches this page
126
+ if config.get("parent_page") == page.id:
127
+ workspace_id = config.get("workspace_id")
128
+ workspace_name = config.get("workspace_name")
129
+ initialized_at = config.get("initialized_at")
130
+ logger.info(f"Config file matches this page, workspace_id: {workspace_id}")
131
+ except Exception as e:
132
+ logger.debug(f"Could not load local config: {e}")
133
+
134
+ return {
135
+ "workspace_id": workspace_id,
136
+ "workspace_name": workspace_name,
137
+ "initialized_at": initialized_at,
138
+ "database_ids": database_ids,
139
+ "detection_method": "database_scan",
140
+ "databases_count": matches
141
+ }
142
+ except Exception as e:
143
+ logger.debug(f"Could not scan for databases: {e}")
144
+
145
+ return None
146
+
147
+ @staticmethod
148
+ def save_workspace_config(
149
+ page_id: str,
150
+ workspace_id: str,
151
+ workspace_name: str,
152
+ database_ids: dict[str, str],
153
+ path: Optional[Path] = None
154
+ ) -> Path:
155
+ """Save workspace configuration to local file.
156
+
157
+ Args:
158
+ page_id: Parent page ID
159
+ workspace_id: Unique workspace ID
160
+ workspace_name: Workspace name
161
+ database_ids: Dict of database name to ID
162
+ path: Optional custom path for config file
163
+
164
+ Returns:
165
+ Path to saved config file
166
+ """
167
+ if path is None:
168
+ path = Path.home() / ".notion" / "workspace.json"
169
+
170
+ path.parent.mkdir(parents=True, exist_ok=True)
171
+
172
+ config = {
173
+ "workspace_id": workspace_id,
174
+ "workspace_name": workspace_name,
175
+ "parent_page": page_id,
176
+ "initialized_at": datetime.now(timezone.utc).isoformat(),
177
+ "version": "1.5.4", # Track version for migrations
178
+ "database_ids": database_ids
179
+ }
180
+
181
+ with open(path, "w", encoding="utf-8") as f:
182
+ json.dump(config, f, indent=2)
183
+
184
+ logger.info(f"Saved workspace config to {path}")
185
+ return path
@@ -6,12 +6,14 @@ required databases for the workflow management system.
6
6
 
7
7
  import json
8
8
  import logging
9
+ from datetime import datetime, timezone
9
10
  from pathlib import Path
10
11
  from typing import Any, Dict, Optional
11
12
 
12
13
  from better_notion._cli.config import Config
13
14
  from better_notion._sdk.client import NotionClient
14
15
  from better_notion._sdk.models.page import Page
16
+ from better_notion.utils.agents.metadata import WorkspaceMetadata
15
17
  from better_notion.utils.agents.schemas import (
16
18
  IncidentSchema,
17
19
  IdeaSchema,
@@ -48,11 +50,15 @@ class WorkspaceInitializer:
48
50
  """
49
51
  self._client = client
50
52
  self._database_ids: Dict[str, str] = {}
53
+ self._workspace_id: Optional[str] = None
54
+ self._parent_page_id: Optional[str] = None
55
+ self._workspace_name: Optional[str] = None
51
56
 
52
57
  async def initialize_workspace(
53
58
  self,
54
59
  parent_page_id: str,
55
60
  workspace_name: str = "Agents Workspace",
61
+ skip_detection: bool = False,
56
62
  ) -> Dict[str, str]:
57
63
  """Initialize a complete workspace with all databases.
58
64
 
@@ -62,15 +68,22 @@ class WorkspaceInitializer:
62
68
  Args:
63
69
  parent_page_id: ID of the parent page where databases will be created
64
70
  workspace_name: Name for the workspace (used for database titles)
71
+ skip_detection: If True, skip duplicate detection (for reset operation)
65
72
 
66
73
  Returns:
67
74
  Dict mapping database names to their IDs
68
75
 
69
76
  Raises:
70
77
  Exception: If database creation fails with detailed error message
78
+ Exception: If workspace already exists (and skip_detection is False)
71
79
  """
72
80
  logger.info(f"Initializing workspace '{workspace_name}' in page {parent_page_id}")
73
81
 
82
+ # Store workspace info
83
+ self._parent_page_id = parent_page_id
84
+ self._workspace_name = workspace_name
85
+ self._workspace_id = WorkspaceMetadata.generate_workspace_id()
86
+
74
87
  # Get parent page
75
88
  try:
76
89
  parent = await Page.get(parent_page_id, client=self._client)
@@ -80,6 +93,26 @@ class WorkspaceInitializer:
80
93
  logger.error(error_msg)
81
94
  raise Exception(error_msg) from e
82
95
 
96
+ # Check for existing workspace unless skipped
97
+ if not skip_detection:
98
+ existing = await WorkspaceMetadata.detect_workspace(parent, self._client)
99
+ if existing:
100
+ workspace_info = {
101
+ "workspace_id": existing.get("workspace_id", "unknown"),
102
+ "workspace_name": existing.get("workspace_name", workspace_name),
103
+ "initialized_at": existing.get("initialized_at", "unknown"),
104
+ "databases": existing.get("database_ids", {})
105
+ }
106
+ error_msg = (
107
+ f"Workspace already initialized in this page\n"
108
+ f"Workspace ID: {workspace_info['workspace_id']}\n"
109
+ f"Initialized: {workspace_info['initialized_at']}\n"
110
+ f"Databases: {len(workspace_info.get('databases', {}))} created\n"
111
+ f"Use --reset to reinitialize or --skip to keep existing"
112
+ )
113
+ logger.error(error_msg)
114
+ raise Exception(error_msg) from None
115
+
83
116
  # Create databases in order (independent first, then dependent)
84
117
  self._database_ids = {}
85
118
  databases_order = [
@@ -108,7 +141,11 @@ class WorkspaceInitializer:
108
141
  logger.error(error_msg)
109
142
  raise Exception(error_msg) from e
110
143
 
144
+ # Save workspace metadata
145
+ self.save_database_ids()
146
+
111
147
  logger.info(f"Workspace initialization complete. Created {len(self._database_ids)} databases")
148
+ logger.info(f"Workspace ID: {self._workspace_id}")
112
149
  return self._database_ids
113
150
 
114
151
  async def _create_organizations_db(self, parent: Page) -> None:
@@ -312,7 +349,7 @@ class WorkspaceInitializer:
312
349
  pass
313
350
 
314
351
  def save_database_ids(self, path: Optional[Path] = None) -> None:
315
- """Save database IDs to a config file.
352
+ """Save workspace metadata (database IDs and workspace info) to config file.
316
353
 
317
354
  Args:
318
355
  path: Path to save config file (default: ~/.notion/workspace.json)
@@ -322,8 +359,18 @@ class WorkspaceInitializer:
322
359
 
323
360
  path.parent.mkdir(parents=True, exist_ok=True)
324
361
 
362
+ # Save full workspace metadata
363
+ config = {
364
+ "workspace_id": self._workspace_id,
365
+ "workspace_name": self._workspace_name,
366
+ "parent_page": self._parent_page_id,
367
+ "initialized_at": datetime.now(timezone.utc).isoformat(),
368
+ "version": "1.5.4",
369
+ "database_ids": self._database_ids
370
+ }
371
+
325
372
  with open(path, "w", encoding="utf-8") as f:
326
- json.dump(self._database_ids, f, indent=2)
373
+ json.dump(config, f, indent=2)
327
374
 
328
375
  @classmethod
329
376
  def load_database_ids(cls, path: Optional[Path] = None) -> Dict[str, str]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: better-notion
3
- Version: 1.5.4
3
+ Version: 1.6.0
4
4
  Summary: A high-level Python SDK for the Notion API with developer experience in mind.
5
5
  Project-URL: Homepage, https://github.com/nesalia-inc/better-notion
6
6
  Project-URL: Documentation, https://github.com/nesalia-inc/better-notion#readme