@@ -1013,10 +1013,409 @@
1013 1013 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
click.echo("Dropbox authentication successful.")
1014 1014 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
else:
1015 1015 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
click.echo("Dropbox authentication failed.", err=True)
1016 1016 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
sys.exit(1)
1017 1017 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1018 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1019 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @cli.group()
1020 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def gws():
1021 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Google Workspace: fetch docs, sheets, and slides via the gws CLI."""
1022 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pass
1023 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1024 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1025 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @gws.command("list")
1026 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--folder-id", type=str, default=None, help="Drive folder ID to list")
1027 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--query", "-q", type=str, default=None, help="Drive search query")
1028 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--json", "as_json", is_flag=True, help="Output as JSON")
1029 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def gws_list(folder_id, query, as_json):
1030 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """List documents in Google Drive.
1031 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1032 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Examples:
1033 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1034 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon gws list
1035 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1036 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon gws list --folder-id 1abc...
1037 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1038 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon gws list -q "name contains 'PRD'" --json
1039 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """
1040 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.sources.gws_source import GWSSource
1041 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1042 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source = GWSSource(folder_id=folder_id, query=query)
1043 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not source.authenticate():
1044 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Error: gws CLI not available or not authenticated.", err=True)
1045 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Install: npm install -g @googleworkspace/cli", err=True)
1046 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Auth: gws auth login", err=True)
1047 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
1048 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1049 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ files = source.list_videos(folder_id=folder_id)
1050 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if as_json:
1051 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(json.dumps([f.model_dump() for f in files], indent=2, default=str))
1052 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ else:
1053 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not files:
1054 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("No documents found.")
1055 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
1056 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for f in files:
1057 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ size = f"{f.size_bytes / 1024:.0f}KB" if f.size_bytes else "—"
1058 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" {f.id[:12]}… {size:>8s} {f.mime_type or ''} {f.name}")
1059 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1060 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1061 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @gws.command("fetch")
1062 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.argument("doc_ids", nargs=-1)
1063 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--folder-id", type=str, default=None, help="Fetch all docs in a folder")
1064 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("-o", "--output", type=click.Path(), default=None, help="Output directory")
1065 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def gws_fetch(doc_ids, folder_id, output):
1066 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Fetch Google Docs/Sheets/Slides as text files.
1067 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1068 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Examples:
1069 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1070 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon gws fetch DOC_ID1 DOC_ID2 -o ./docs
1071 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1072 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon gws fetch --folder-id 1abc... -o ./docs
1073 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """
1074 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.sources.gws_source import GWSSource
1075 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1076 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source = GWSSource(folder_id=folder_id, doc_ids=list(doc_ids))
1077 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not source.authenticate():
1078 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Error: gws CLI not available or not authenticated.", err=True)
1079 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
1080 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1081 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ out_dir = Path(output) if output else Path.cwd() / "gws_docs"
1082 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ out_dir.mkdir(parents=True, exist_ok=True)
1083 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1084 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ files = source.list_videos(folder_id=folder_id)
1085 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not files:
1086 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("No documents found.")
1087 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
1088 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1089 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for f in files:
1090 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ safe_name = f.name.replace("/", "_").replace("\\", "_")
1091 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ dest = out_dir / f"{safe_name}.txt"
1092 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
1093 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source.download(f, dest)
1094 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" ✓ {f.name} → {dest}")
1095 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
1096 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" ✗ {f.name}: {e}", err=True)
1097 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1098 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f"\nFetched {len(files)} document(s) to {out_dir}")
1099 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @gws.command("ingest")
1102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--folder-id", type=str, default=None, help="Drive folder ID")
1103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--doc-id", type=str, multiple=True, help="Specific doc IDs (repeatable)")
1104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--query", "-q", type=str, default=None, help="Drive search query")
1105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("-o", "--output", type=click.Path(), default=None, help="Output directory")
1106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--db-path", type=click.Path(), default=None, help="Existing DB to merge into")
1107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option(
1108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "-p",
1109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "--provider",
1110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type=click.Choice(
1111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ [
1112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "auto",
1113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "openai",
1114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "anthropic",
1115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "gemini",
1116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ollama",
1117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "azure",
1118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "together",
1119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "fireworks",
1120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "cerebras",
1121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "xai",
1122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ]
1123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ),
1124 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default="auto",
1125 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ help="API provider",
1126 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
1127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--chat-model", type=str, default=None, help="Override model for LLM/chat tasks")
1128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.pass_context
1129 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def gws_ingest(ctx, folder_id, doc_id, query, output, db_path, provider, chat_model):
1130 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Fetch Google Workspace docs and ingest into a knowledge graph.
1131 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1132 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Combines gws fetch + planopticon ingest in one step.
1133 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1134 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Examples:
1135 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1136 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon gws ingest --folder-id 1abc...
1137 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1138 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon gws ingest --doc-id DOC1 --doc-id DOC2 -o ./results
1139 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1140 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon gws ingest -q "name contains 'spec'" --db-path existing.db
1141 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """
1142 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ import tempfile
1143 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1144 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.integrators.knowledge_graph import KnowledgeGraph
1145 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.processors.ingest import ingest_file
1146 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.providers.manager import ProviderManager
1147 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.sources.gws_source import GWSSource
1148 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1149 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source = GWSSource(folder_id=folder_id, doc_ids=list(doc_id), query=query)
1150 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not source.authenticate():
1151 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Error: gws CLI not available or not authenticated.", err=True)
1152 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Install: npm install -g @googleworkspace/cli", err=True)
1153 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Auth: gws auth login", err=True)
1154 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
1155 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1156 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Fetch docs to temp dir
1157 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ files = source.list_videos(folder_id=folder_id)
1158 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not files:
1159 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("No documents found.")
1160 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
1161 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1162 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f"Found {len(files)} document(s), fetching...")
1163 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1164 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ with tempfile.TemporaryDirectory() as tmp_dir:
1165 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tmp_path = Path(tmp_dir)
1166 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ local_files = []
1167 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for f in files:
1168 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ safe_name = f.name.replace("/", "_").replace("\\", "_")
1169 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ dest = tmp_path / f"{safe_name}.txt"
1170 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
1171 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source.download(f, dest)
1172 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ local_files.append(dest)
1173 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" ✓ {f.name}")
1174 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
1175 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" ✗ {f.name}: {e}", err=True)
1176 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1177 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not local_files:
1178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("No documents fetched successfully.", err=True)
1179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
1180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Set up KG
1182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ prov = None if provider == "auto" else provider
1183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pm = ProviderManager(chat_model=chat_model, provider=prov)
1184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if db_path:
1186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path = Path(db_path)
1187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ elif output:
1188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ out_dir = Path(output)
1189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ out_dir.mkdir(parents=True, exist_ok=True)
1190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path = out_dir / "knowledge_graph.db"
1191 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ else:
1192 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path = Path.cwd() / "knowledge_graph.db"
1193 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1194 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path.parent.mkdir(parents=True, exist_ok=True)
1195 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg = KnowledgeGraph(provider_manager=pm, db_path=kg_path)
1196 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1197 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_chunks = 0
1198 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for lf in local_files:
1199 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
1200 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ count = ingest_file(lf, kg)
1201 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_chunks += count
1202 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Ingested {lf.stem}: {count} chunks")
1203 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
1204 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Failed to ingest {lf.stem}: {e}", err=True)
1205 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1206 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg.save(kg_path)
1207 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg.save(kg_path.with_suffix(".json"))
1208 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1209 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entity_count = kg._store.get_entity_count()
1210 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rel_count = kg._store.get_relationship_count()
1211 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1212 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("\nIngestion complete:")
1213 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Documents: {len(local_files)}")
1214 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Chunks: {total_chunks}")
1215 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Entities: {entity_count}")
1216 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Relationships: {rel_count}")
1217 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Knowledge graph: {kg_path}")
1218 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1219 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1220 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @cli.group()
1221 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def m365():
1222 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Microsoft 365: fetch docs from SharePoint and OneDrive via the m365 CLI."""
1223 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pass
1224 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1225 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1226 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @m365.command("list")
1227 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--web-url", type=str, required=True, help="SharePoint site URL")
1228 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--folder-url", type=str, required=True, help="Server-relative folder URL")
1229 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--recursive", is_flag=True, help="Include subfolders")
1230 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--json", "as_json", is_flag=True, help="Output as JSON")
1231 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def m365_list(web_url, folder_url, recursive, as_json):
1232 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """List documents in SharePoint or OneDrive.
1233 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1234 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Examples:
1235 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1236 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon m365 list --web-url https://contoso.sharepoint.com/sites/proj \\
1237 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ --folder-url /sites/proj/Shared\\ Documents
1238 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1239 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon m365 list --web-url URL --folder-url FOLDER --recursive --json
1240 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """
1241 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.sources.m365_source import M365Source
1242 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1243 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source = M365Source(web_url=web_url, folder_url=folder_url, recursive=recursive)
1244 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not source.authenticate():
1245 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Error: m365 CLI not available or not logged in.", err=True)
1246 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Install: npm install -g @pnp/cli-microsoft365", err=True)
1247 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Auth: m365 login", err=True)
1248 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
1249 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1250 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ files = source.list_videos()
1251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if as_json:
1252 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(json.dumps([f.model_dump() for f in files], indent=2, default=str))
1253 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ else:
1254 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not files:
1255 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("No documents found.")
1256 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
1257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for f in files:
1258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ size = f"{f.size_bytes / 1024:.0f}KB" if f.size_bytes else "—"
1259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" {f.id[:12]}… {size:>8s} {f.name}")
1260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @m365.command("fetch")
1263 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--web-url", type=str, required=True, help="SharePoint site URL")
1264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--folder-url", type=str, default=None, help="Server-relative folder URL")
1265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--file-id", type=str, multiple=True, help="Specific file IDs (repeatable)")
1266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("-o", "--output", type=click.Path(), default=None, help="Output directory")
1267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def m365_fetch(web_url, folder_url, file_id, output):
1268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Fetch SharePoint/OneDrive documents as local files.
1269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Examples:
1271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon m365 fetch --web-url URL --folder-url FOLDER -o ./docs
1273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon m365 fetch --web-url URL --file-id ID1 --file-id ID2 -o ./docs
1275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """
1276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.sources.m365_source import M365Source
1277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source = M365Source(web_url=web_url, folder_url=folder_url, file_ids=list(file_id))
1279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not source.authenticate():
1280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Error: m365 CLI not available or not logged in.", err=True)
1281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
1282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ out_dir = Path(output) if output else Path.cwd() / "m365_docs"
1284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ out_dir.mkdir(parents=True, exist_ok=True)
1285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ files = source.list_videos()
1287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not files:
1288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("No documents found.")
1289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
1290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for f in files:
1292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ dest = out_dir / f.name
1293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
1294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source.download(f, dest)
1295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" fetched {f.name}")
1296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
1297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" failed {f.name}: {e}", err=True)
1298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f"\nFetched {len(files)} document(s) to {out_dir}")
1300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @m365.command("ingest")
1303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--web-url", type=str, required=True, help="SharePoint site URL")
1304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--folder-url", type=str, default=None, help="Server-relative folder URL")
1305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--file-id", type=str, multiple=True, help="Specific file IDs (repeatable)")
1306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("-o", "--output", type=click.Path(), default=None, help="Output directory")
1307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--db-path", type=click.Path(), default=None, help="Existing DB to merge into")
1308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option(
1309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "-p",
1310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "--provider",
1311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type=click.Choice(
1312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ [
1313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "auto",
1314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "openai",
1315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "anthropic",
1316 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "gemini",
1317 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ollama",
1318 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "azure",
1319 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "together",
1320 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "fireworks",
1321 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "cerebras",
1322 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "xai",
1323 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ]
1324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ),
1325 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default="auto",
1326 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ help="API provider",
1327 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
1328 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.option("--chat-model", type=str, default=None, help="Override model for LLM/chat tasks")
1329 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @click.pass_context
1330 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ def m365_ingest(ctx, web_url, folder_url, file_id, output, db_path, provider, chat_model):
1331 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """Fetch SharePoint/OneDrive docs and ingest into a knowledge graph.
1332 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1333 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Examples:
1334 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1335 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon m365 ingest --web-url URL --folder-url FOLDER
1336 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1337 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ planopticon m365 ingest --web-url URL --file-id ID1 --file-id ID2 -o ./results
1338 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ """
1339 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ import tempfile
1340 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1341 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.integrators.knowledge_graph import KnowledgeGraph
1342 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.processors.ingest import ingest_file
1343 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.providers.manager import ProviderManager
1344 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ from video_processor.sources.m365_source import M365Source
1345 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1346 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source = M365Source(web_url=web_url, folder_url=folder_url, file_ids=list(file_id))
1347 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not source.authenticate():
1348 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Error: m365 CLI not available or not logged in.", err=True)
1349 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Install: npm install -g @pnp/cli-microsoft365", err=True)
1350 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("Auth: m365 login", err=True)
1351 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
1352 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1353 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ files = source.list_videos()
1354 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not files:
1355 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("No documents found.")
1356 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
1357 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1358 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f"Found {len(files)} document(s), fetching...")
1359 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1360 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ with tempfile.TemporaryDirectory() as tmp_dir:
1361 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tmp_path = Path(tmp_dir)
1362 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ local_files = []
1363 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for f in files:
1364 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ dest = tmp_path / f.name
1365 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
1366 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ source.download(f, dest)
1367 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Extract text for non-text formats
1368 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ text_dest = tmp_path / f"{Path(f.name).stem}.txt"
1369 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ text = source.download_as_text(f)
1370 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ text_dest.write_text(text, encoding="utf-8")
1371 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ local_files.append(text_dest)
1372 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" fetched {f.name}")
1373 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
1374 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" failed {f.name}: {e}", err=True)
1375 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1376 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if not local_files:
1377 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("No documents fetched successfully.", err=True)
1378 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sys.exit(1)
1379 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1380 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ prov = None if provider == "auto" else provider
1381 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pm = ProviderManager(chat_model=chat_model, provider=prov)
1382 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1383 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if db_path:
1384 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path = Path(db_path)
1385 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ elif output:
1386 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ out_dir = Path(output)
1387 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ out_dir.mkdir(parents=True, exist_ok=True)
1388 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path = out_dir / "knowledge_graph.db"
1389 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ else:
1390 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path = Path.cwd() / "knowledge_graph.db"
1391 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1392 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg_path.parent.mkdir(parents=True, exist_ok=True)
1393 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg = KnowledgeGraph(provider_manager=pm, db_path=kg_path)
1394 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1395 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_chunks = 0
1396 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for lf in local_files:
1397 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ try:
1398 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ count = ingest_file(lf, kg)
1399 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ total_chunks += count
1400 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Ingested {lf.stem}: {count} chunks")
1401 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ except Exception as e:
1402 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Failed to ingest {lf.stem}: {e}", err=True)
1403 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1404 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg.save(kg_path)
1405 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ kg.save(kg_path.with_suffix(".json"))
1406 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1407 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ entity_count = kg._store.get_entity_count()
1408 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rel_count = kg._store.get_relationship_count()
1409 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1410 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo("\nIngestion complete:")
1411 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Documents: {len(local_files)}")
1412 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Chunks: {total_chunks}")
1413 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Entities: {entity_count}")
1414 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Relationships: {rel_count}")
1415 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ click.echo(f" Knowledge graph: {kg_path}")
1416 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1018 1417 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1019 1418 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@cli.group()
1020 1419 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
def kg():
1021 1420 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"""Knowledge graph utilities: convert, sync, and inspect."""
1022 1421 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
pass
1023 1422 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!