arcade-google-docs 3.1.1__py3-none-any.whl → 4.1.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.
- arcade_google_docs/__init__.py +2 -0
- arcade_google_docs/docmd.py +534 -0
- arcade_google_docs/enum.py +1 -0
- arcade_google_docs/models/document.py +953 -0
- arcade_google_docs/models/document_writables.py +735 -0
- arcade_google_docs/models/requests.py +1315 -0
- arcade_google_docs/tools/__init__.py +2 -0
- arcade_google_docs/tools/edit_agent/edit_agent.py +56 -0
- arcade_google_docs/tools/edit_agent/executor.py +103 -0
- arcade_google_docs/tools/edit_agent/models/planning.py +89 -0
- arcade_google_docs/tools/edit_agent/planner.py +130 -0
- arcade_google_docs/tools/edit_agent/progress_tracker.py +32 -0
- arcade_google_docs/tools/edit_agent/prompts.py +204 -0
- arcade_google_docs/tools/edit_agent/request_generator.py +150 -0
- arcade_google_docs/tools/edit_agent/utils.py +21 -0
- arcade_google_docs/{file_picker.py → tools/file_picker.py} +14 -6
- arcade_google_docs/tools/get.py +27 -4
- arcade_google_docs/tools/search.py +6 -26
- arcade_google_docs/tools/update.py +1 -4
- {arcade_google_docs-3.1.1.dist-info → arcade_google_docs-4.1.0.dist-info}/METADATA +2 -1
- arcade_google_docs-4.1.0.dist-info/RECORD +28 -0
- arcade_google_docs/decorators.py +0 -24
- arcade_google_docs-3.1.1.dist-info/RECORD +0 -17
- {arcade_google_docs-3.1.1.dist-info → arcade_google_docs-4.1.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from arcade_tdk.errors import ToolExecutionError
|
|
6
|
+
from openai import OpenAI
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from arcade_google_docs.docmd import DocMD
|
|
10
|
+
from arcade_google_docs.tools.edit_agent.models.planning import EditItem, Step
|
|
11
|
+
from arcade_google_docs.tools.edit_agent.prompts import (
|
|
12
|
+
DETERMINE_BLOCK_ID_SYSTEM_PROMPT,
|
|
13
|
+
ERROR_FEEDBACK_PROMPT,
|
|
14
|
+
GENERATE_EDIT_REQUEST_SYSTEM_PROMPT,
|
|
15
|
+
GENERATE_EDIT_REQUEST_SYSTEM_PROMPT_WITH_LOCATION_TAGS,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _determine_block_id(openai_client: OpenAI, docmd: DocMD, edit_instruction: str) -> str:
|
|
20
|
+
"""Determine the block id that the edit instruction is targeting."""
|
|
21
|
+
|
|
22
|
+
class ValidBlockIds(BaseModel):
|
|
23
|
+
block_id: Literal[tuple(docmd.block_ids)] # type: ignore[valid-type]
|
|
24
|
+
|
|
25
|
+
completion = openai_client.beta.chat.completions.parse(
|
|
26
|
+
model="gpt-4o",
|
|
27
|
+
messages=[
|
|
28
|
+
{"role": "developer", "content": DETERMINE_BLOCK_ID_SYSTEM_PROMPT},
|
|
29
|
+
{"role": "user", "content": f"{docmd}\n\nEDIT REQUEST:\n{edit_instruction}"},
|
|
30
|
+
],
|
|
31
|
+
response_format=ValidBlockIds,
|
|
32
|
+
)
|
|
33
|
+
parsed_response = completion.choices[0].message.parsed
|
|
34
|
+
if not parsed_response:
|
|
35
|
+
raise ToolExecutionError("Failed to determine a block id from the edit instruction")
|
|
36
|
+
return str(parsed_response.block_id)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
async def _generate_api_request_for_edit_item(
|
|
40
|
+
openai_client: OpenAI,
|
|
41
|
+
docmd: DocMD,
|
|
42
|
+
edit_item: EditItem,
|
|
43
|
+
previous_error: str | None = None,
|
|
44
|
+
failed_requests: list[dict] | None = None,
|
|
45
|
+
) -> dict | None:
|
|
46
|
+
"""Generate a single edit request asynchronously.
|
|
47
|
+
|
|
48
|
+
Returns a request dictionary for the batchUpdate endpoint or None
|
|
49
|
+
"""
|
|
50
|
+
edit_instruction = edit_item.edit_instruction
|
|
51
|
+
edit_request_type = edit_item.edit_request_type
|
|
52
|
+
edit_item_thoughts = edit_item.thoughts
|
|
53
|
+
|
|
54
|
+
messages = []
|
|
55
|
+
if edit_request_type.is_location_based():
|
|
56
|
+
# Run blocking operation in thread pool to avoid blocking event loop
|
|
57
|
+
loop = asyncio.get_event_loop()
|
|
58
|
+
block_id = await loop.run_in_executor(
|
|
59
|
+
None, _determine_block_id, openai_client, docmd, edit_instruction
|
|
60
|
+
)
|
|
61
|
+
annotated_docmd = docmd.get_docmd_with_annotated_block(block_id).to_string()
|
|
62
|
+
messages.extend([
|
|
63
|
+
{
|
|
64
|
+
"role": "developer",
|
|
65
|
+
"content": GENERATE_EDIT_REQUEST_SYSTEM_PROMPT_WITH_LOCATION_TAGS,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"role": "user",
|
|
69
|
+
"content": (
|
|
70
|
+
"DOCUMENT:\n"
|
|
71
|
+
f"{annotated_docmd}\n\n"
|
|
72
|
+
"THOUGHTS THAT OCCURRED WHEN CONSTRUCTING YOUR INSTRUCTIONS:\n"
|
|
73
|
+
f"{edit_item_thoughts}\n\n"
|
|
74
|
+
"YOUR JOB IS TO CONSTRUCT A SINGLE EDIT REQUEST OBJECT THAT SATISFIES "
|
|
75
|
+
"THE FOLLOWING INSTRUCTIONS:\n"
|
|
76
|
+
f"{edit_instruction}"
|
|
77
|
+
),
|
|
78
|
+
},
|
|
79
|
+
])
|
|
80
|
+
else:
|
|
81
|
+
messages.extend([
|
|
82
|
+
{"role": "developer", "content": GENERATE_EDIT_REQUEST_SYSTEM_PROMPT},
|
|
83
|
+
{
|
|
84
|
+
"role": "user",
|
|
85
|
+
"content": (
|
|
86
|
+
"DOCUMENT:\n"
|
|
87
|
+
f"{docmd.to_string()}\n\n"
|
|
88
|
+
"THOUGHTS THAT OCCURRED WHEN CONSTRUCTING YOUR INSTRUCTIONS:\n"
|
|
89
|
+
f"{edit_item_thoughts}\n\n"
|
|
90
|
+
"YOUR JOB AND SOLE PURPOSE IS TO CONSTRUCT A SINGLE EDIT REQUEST "
|
|
91
|
+
"OBJECT THAT SATISFIES THE FOLLOWING INSTRUCTIONS:\n"
|
|
92
|
+
f"{edit_instruction}"
|
|
93
|
+
),
|
|
94
|
+
},
|
|
95
|
+
])
|
|
96
|
+
|
|
97
|
+
if previous_error and failed_requests:
|
|
98
|
+
error_feedback = ERROR_FEEDBACK_PROMPT.format(
|
|
99
|
+
error=previous_error, failed_requests=json.dumps(failed_requests, indent=2)
|
|
100
|
+
)
|
|
101
|
+
messages.append({"role": "assistant", "content": "I failed to edit the document."})
|
|
102
|
+
messages.append({"role": "user", "content": error_feedback})
|
|
103
|
+
|
|
104
|
+
# Run OpenAI API call in thread pool to avoid blocking
|
|
105
|
+
loop = asyncio.get_event_loop()
|
|
106
|
+
completion = await loop.run_in_executor(
|
|
107
|
+
None,
|
|
108
|
+
lambda: openai_client.beta.chat.completions.parse(
|
|
109
|
+
model="gpt-5",
|
|
110
|
+
messages=messages, # type: ignore[arg-type]
|
|
111
|
+
response_format=edit_request_type.get_request_model(),
|
|
112
|
+
reasoning_effort="minimal", # type: ignore[arg-type]
|
|
113
|
+
),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
request = completion.choices[0].message.parsed
|
|
117
|
+
if request:
|
|
118
|
+
return {edit_request_type.value: request.model_dump(exclude_none=True)}
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
async def generate_api_request_for_step(
|
|
123
|
+
openai_client: OpenAI,
|
|
124
|
+
docmd: DocMD,
|
|
125
|
+
step: Step,
|
|
126
|
+
previous_error: str | None = None,
|
|
127
|
+
failed_requests: list[dict] | None = None,
|
|
128
|
+
) -> list[dict]:
|
|
129
|
+
"""Generate edit requests for a single step.
|
|
130
|
+
|
|
131
|
+
Returns a list of request dictionaries for the Google batchUpdate endpoint
|
|
132
|
+
"""
|
|
133
|
+
if not step.edit_items:
|
|
134
|
+
return []
|
|
135
|
+
|
|
136
|
+
# Generate requests for all edit items in the step in parallel
|
|
137
|
+
tasks = []
|
|
138
|
+
for edit_item in step.edit_items:
|
|
139
|
+
task = _generate_api_request_for_edit_item(
|
|
140
|
+
openai_client,
|
|
141
|
+
docmd,
|
|
142
|
+
edit_item,
|
|
143
|
+
previous_error,
|
|
144
|
+
failed_requests,
|
|
145
|
+
)
|
|
146
|
+
tasks.append(task)
|
|
147
|
+
|
|
148
|
+
results = await asyncio.gather(*tasks)
|
|
149
|
+
|
|
150
|
+
return [result for result in results if result is not None]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from arcade_google_docs.docmd import DocMD, build_docmd
|
|
4
|
+
from arcade_google_docs.models.document import Document
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_docmd(google_service: Any, document_id: str) -> DocMD:
|
|
8
|
+
"""
|
|
9
|
+
Helper function to get a Google Doc and convert it to DocMD format.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
google_service: The authenticated Google Docs service
|
|
13
|
+
document_id: The ID of the document to fetch
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
DocMD object
|
|
17
|
+
"""
|
|
18
|
+
google_get_response = google_service.documents().get(documentId=document_id).execute()
|
|
19
|
+
document = Document(**google_get_response)
|
|
20
|
+
docmd = build_docmd(document)
|
|
21
|
+
return docmd
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import base64
|
|
2
2
|
import json
|
|
3
|
+
from typing import Annotated
|
|
3
4
|
|
|
4
|
-
from arcade_tdk import ToolContext, ToolMetadataKey
|
|
5
|
+
from arcade_tdk import ToolContext, ToolMetadataKey, tool
|
|
6
|
+
from arcade_tdk.auth import Google
|
|
5
7
|
from arcade_tdk.errors import ToolExecutionError
|
|
6
8
|
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
@tool(
|
|
11
|
+
requires_auth=Google(),
|
|
12
|
+
requires_metadata=[ToolMetadataKey.CLIENT_ID, ToolMetadataKey.COORDINATOR_URL],
|
|
13
|
+
)
|
|
14
|
+
def generate_google_file_picker_url(
|
|
15
|
+
context: ToolContext,
|
|
16
|
+
) -> Annotated[dict, "Google File Picker URL for user file selection and permission granting"]:
|
|
9
17
|
"""Generate a Google File Picker URL for user-driven file selection and authorization.
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
This tool generates a URL that directs the end-user to a Google File Picker interface where
|
|
12
20
|
where they can select or upload Google Drive files. Users can grant permission to access their
|
|
13
21
|
Drive files, providing a secure and authorized way to interact with their files.
|
|
14
22
|
|
|
@@ -17,8 +25,8 @@ def generate_google_file_picker_url(context: ToolContext) -> dict:
|
|
|
17
25
|
(Requested entity was not found) or permission errors. Once the user completes the file
|
|
18
26
|
picker flow, the prior tool can be retried.
|
|
19
27
|
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
Suggest this tool to users when they are surprised or confused that the file they are
|
|
29
|
+
searching for or attempting to access cannot be found.
|
|
22
30
|
"""
|
|
23
31
|
client_id = context.get_metadata(ToolMetadataKey.CLIENT_ID)
|
|
24
32
|
client_id_parts = client_id.split("-")
|
|
@@ -44,6 +52,6 @@ def generate_google_file_picker_url(context: ToolContext) -> dict:
|
|
|
44
52
|
"url": url,
|
|
45
53
|
"llm_instructions": (
|
|
46
54
|
"Instruct the user to click the following link to open the Google Drive File Picker. "
|
|
47
|
-
|
|
55
|
+
"This will allow them to select files and grant access permissions: {url}"
|
|
48
56
|
),
|
|
49
57
|
}
|
arcade_google_docs/tools/get.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from typing import Annotated
|
|
2
2
|
|
|
3
|
-
from arcade_tdk import ToolContext,
|
|
3
|
+
from arcade_tdk import ToolContext, tool
|
|
4
4
|
from arcade_tdk.auth import Google
|
|
5
5
|
|
|
6
|
-
from arcade_google_docs.
|
|
6
|
+
from arcade_google_docs.docmd import build_docmd
|
|
7
|
+
from arcade_google_docs.models.document import Document
|
|
7
8
|
from arcade_google_docs.utils import build_docs_service
|
|
8
9
|
|
|
9
10
|
|
|
@@ -16,14 +17,13 @@ from arcade_google_docs.utils import build_docs_service
|
|
|
16
17
|
"https://www.googleapis.com/auth/drive.file",
|
|
17
18
|
],
|
|
18
19
|
),
|
|
19
|
-
requires_metadata=[ToolMetadataKey.CLIENT_ID, ToolMetadataKey.COORDINATOR_URL],
|
|
20
20
|
)
|
|
21
|
-
@with_filepicker_fallback
|
|
22
21
|
async def get_document_by_id(
|
|
23
22
|
context: ToolContext,
|
|
24
23
|
document_id: Annotated[str, "The ID of the document to retrieve."],
|
|
25
24
|
) -> Annotated[dict, "The document contents as a dictionary"]:
|
|
26
25
|
"""
|
|
26
|
+
DEPRECATED DO NOT USE THIS TOOL
|
|
27
27
|
Get the latest version of the specified Google Docs document.
|
|
28
28
|
"""
|
|
29
29
|
service = build_docs_service(context.get_auth_token_or_empty())
|
|
@@ -33,3 +33,26 @@ async def get_document_by_id(
|
|
|
33
33
|
request = service.documents().get(documentId=document_id)
|
|
34
34
|
response = request.execute()
|
|
35
35
|
return dict(response)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@tool(
|
|
39
|
+
requires_auth=Google(
|
|
40
|
+
scopes=[
|
|
41
|
+
"https://www.googleapis.com/auth/drive.file",
|
|
42
|
+
],
|
|
43
|
+
),
|
|
44
|
+
)
|
|
45
|
+
async def get_document_as_docmd(
|
|
46
|
+
context: ToolContext,
|
|
47
|
+
document_id: Annotated[str, "The ID of the document to retrieve."],
|
|
48
|
+
) -> Annotated[str, "The document contents as DocMD"]:
|
|
49
|
+
"""
|
|
50
|
+
Get the latest version of the specified Google Docs document as DocMD.
|
|
51
|
+
The DocMD output will include tags that can be used to annotate the document with location
|
|
52
|
+
information, the type of block, block IDs, and other metadata.
|
|
53
|
+
"""
|
|
54
|
+
service = build_docs_service(context.get_auth_token_or_empty())
|
|
55
|
+
|
|
56
|
+
request = service.documents().get(documentId=document_id)
|
|
57
|
+
response = request.execute()
|
|
58
|
+
return build_docmd(Document(**response)).to_string()
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
from typing import Annotated, Any
|
|
2
2
|
|
|
3
|
-
from arcade_tdk import ToolContext,
|
|
3
|
+
from arcade_tdk import ToolContext, tool
|
|
4
4
|
from arcade_tdk.auth import Google
|
|
5
5
|
|
|
6
6
|
from arcade_google_docs.doc_to_html import convert_document_to_html
|
|
7
7
|
from arcade_google_docs.doc_to_markdown import convert_document_to_markdown
|
|
8
|
+
from arcade_google_docs.docmd import build_docmd
|
|
8
9
|
from arcade_google_docs.enum import DocumentFormat, OrderBy
|
|
9
|
-
from arcade_google_docs.
|
|
10
|
-
from arcade_google_docs.templates import optional_file_picker_instructions_template
|
|
10
|
+
from arcade_google_docs.models.document import Document
|
|
11
11
|
from arcade_google_docs.tools import get_document_by_id
|
|
12
12
|
from arcade_google_docs.utils import (
|
|
13
13
|
build_drive_service,
|
|
@@ -23,7 +23,6 @@ from arcade_google_docs.utils import (
|
|
|
23
23
|
requires_auth=Google(
|
|
24
24
|
scopes=["https://www.googleapis.com/auth/drive.file"],
|
|
25
25
|
),
|
|
26
|
-
requires_metadata=[ToolMetadataKey.CLIENT_ID, ToolMetadataKey.COORDINATOR_URL],
|
|
27
26
|
)
|
|
28
27
|
async def search_documents(
|
|
29
28
|
context: ToolContext,
|
|
@@ -112,19 +111,9 @@ async def search_documents(
|
|
|
112
111
|
if not pagination_token or len(batch) < page_size:
|
|
113
112
|
break
|
|
114
113
|
|
|
115
|
-
file_picker_response = generate_google_file_picker_url(
|
|
116
|
-
context,
|
|
117
|
-
)
|
|
118
|
-
|
|
119
114
|
return {
|
|
120
115
|
"documents_count": len(files),
|
|
121
116
|
"documents": files,
|
|
122
|
-
"file_picker": {
|
|
123
|
-
"url": file_picker_response["url"],
|
|
124
|
-
"llm_instructions": optional_file_picker_instructions_template.format(
|
|
125
|
-
url=file_picker_response["url"]
|
|
126
|
-
),
|
|
127
|
-
},
|
|
128
117
|
}
|
|
129
118
|
|
|
130
119
|
|
|
@@ -132,7 +121,6 @@ async def search_documents(
|
|
|
132
121
|
requires_auth=Google(
|
|
133
122
|
scopes=["https://www.googleapis.com/auth/drive.file"],
|
|
134
123
|
),
|
|
135
|
-
requires_metadata=[ToolMetadataKey.CLIENT_ID, ToolMetadataKey.COORDINATOR_URL],
|
|
136
124
|
)
|
|
137
125
|
async def search_and_retrieve_documents(
|
|
138
126
|
context: ToolContext,
|
|
@@ -203,24 +191,16 @@ async def search_and_retrieve_documents(
|
|
|
203
191
|
for item in response["documents"]:
|
|
204
192
|
document = await get_document_by_id(context, document_id=item["id"])
|
|
205
193
|
|
|
206
|
-
if return_format == DocumentFormat.
|
|
194
|
+
if return_format == DocumentFormat.DOCMD:
|
|
195
|
+
document = build_docmd(Document(**document)).to_string()
|
|
196
|
+
elif return_format == DocumentFormat.MARKDOWN:
|
|
207
197
|
document = convert_document_to_markdown(document)
|
|
208
198
|
elif return_format == DocumentFormat.HTML:
|
|
209
199
|
document = convert_document_to_html(document)
|
|
210
200
|
|
|
211
201
|
documents.append(document)
|
|
212
202
|
|
|
213
|
-
file_picker_response = generate_google_file_picker_url(
|
|
214
|
-
context,
|
|
215
|
-
)
|
|
216
|
-
|
|
217
203
|
return {
|
|
218
204
|
"documents_count": len(documents),
|
|
219
205
|
"documents": documents,
|
|
220
|
-
"file_picker": {
|
|
221
|
-
"url": file_picker_response["url"],
|
|
222
|
-
"llm_instructions": optional_file_picker_instructions_template.format(
|
|
223
|
-
url=file_picker_response["url"]
|
|
224
|
-
),
|
|
225
|
-
},
|
|
226
206
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from typing import Annotated
|
|
2
2
|
|
|
3
|
-
from arcade_tdk import ToolContext,
|
|
3
|
+
from arcade_tdk import ToolContext, tool
|
|
4
4
|
from arcade_tdk.auth import Google
|
|
5
5
|
|
|
6
|
-
from arcade_google_docs.decorators import with_filepicker_fallback
|
|
7
6
|
from arcade_google_docs.tools.get import get_document_by_id
|
|
8
7
|
from arcade_google_docs.utils import build_docs_service
|
|
9
8
|
|
|
@@ -16,9 +15,7 @@ from arcade_google_docs.utils import build_docs_service
|
|
|
16
15
|
"https://www.googleapis.com/auth/drive.file",
|
|
17
16
|
],
|
|
18
17
|
),
|
|
19
|
-
requires_metadata=[ToolMetadataKey.CLIENT_ID, ToolMetadataKey.COORDINATOR_URL],
|
|
20
18
|
)
|
|
21
|
-
@with_filepicker_fallback
|
|
22
19
|
async def insert_text_at_end_of_document(
|
|
23
20
|
context: ToolContext,
|
|
24
21
|
document_id: Annotated[str, "The ID of the document to update."],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arcade_google_docs
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.1.0
|
|
4
4
|
Summary: Arcade.dev LLM tools for Google Docs
|
|
5
5
|
Author-email: Arcade <dev@arcade.dev>
|
|
6
6
|
License: Proprietary - Arcade Software License Agreement v1.0
|
|
@@ -11,6 +11,7 @@ Requires-Dist: google-api-python-client<3.0.0,>=2.137.0
|
|
|
11
11
|
Requires-Dist: google-auth-httplib2<1.0.0,>=0.2.0
|
|
12
12
|
Requires-Dist: google-auth<3.0.0,>=2.32.0
|
|
13
13
|
Requires-Dist: googleapis-common-protos<2.0.0,>=1.63.2
|
|
14
|
+
Requires-Dist: openai==1.82.1
|
|
14
15
|
Provides-Extra: dev
|
|
15
16
|
Requires-Dist: arcade-ai[evals]<3.0.0,>=2.0.4; extra == 'dev'
|
|
16
17
|
Requires-Dist: arcade-serve<3.0.0,>=2.0.0; extra == 'dev'
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
arcade_google_docs/__init__.py,sha256=nZoMwH9HWZLpfNMIioUXLDlZ7QDR-E4C1_8hySt_CkU,604
|
|
2
|
+
arcade_google_docs/doc_to_html.py,sha256=6RTpzRSrazNa6AndLZhA20wgVDzZuHUqpu3WAkAsbjQ,3146
|
|
3
|
+
arcade_google_docs/doc_to_markdown.py,sha256=eT-sc6ruxN8nEtUm9mBHFOWXajEBTTXkxsn6XsLHIxo,2020
|
|
4
|
+
arcade_google_docs/docmd.py,sha256=rgxUt0k2Nes0GWLlPR49qU0nnM8e6HCiqd61Z7zNfTk,20173
|
|
5
|
+
arcade_google_docs/enum.py,sha256=kuXlsHcMYbN28Qg-Dwp4viz-CZ8z85_WVjQVZj2EsEY,3441
|
|
6
|
+
arcade_google_docs/templates.py,sha256=pxbdMj57eV3-ImW3CixDWscpVKS94Z8nTNyTxDhUfGY,283
|
|
7
|
+
arcade_google_docs/utils.py,sha256=XMgKcWPWKy8SbH3y2eCil01hssHhUgYxVrwXyvHEU4A,3748
|
|
8
|
+
arcade_google_docs/models/document.py,sha256=0RvZ2_dfpz6ZoF1aUucYWOkRYWy_K_hiChSzoQtwhTc,30419
|
|
9
|
+
arcade_google_docs/models/document_writables.py,sha256=DMBT5A05y7o7_PYlBB6O3KThma6-pm6hd5nxKGydT5Q,27575
|
|
10
|
+
arcade_google_docs/models/requests.py,sha256=8Cga7QECmQWNFhM2QiGudvnQcgA_THi7ThNsUb7uavg,52176
|
|
11
|
+
arcade_google_docs/tools/__init__.py,sha256=s0FS3z-uXE4lQH06YhnUKgIOT-Kq-v6rQMqXUGdPDnw,827
|
|
12
|
+
arcade_google_docs/tools/comment.py,sha256=Qm5NHdNHONs3j4gqbZ7Fw9NrTVBb_mZ-th1X-z2IoLM,2836
|
|
13
|
+
arcade_google_docs/tools/create.py,sha256=AuYy8yMGscrxAdLJQX0WiisGHCTufSlaRu_QGMMKQmM,2764
|
|
14
|
+
arcade_google_docs/tools/file_picker.py,sha256=Dqn-hfMoTsWyHM8QCakVgHr5TKrzL_1Lj-vYHVGtOW4,2342
|
|
15
|
+
arcade_google_docs/tools/get.py,sha256=Aby3iI1EzjfZTovGH4OdwpIhuazfV4SQinpXDOl87cg,2076
|
|
16
|
+
arcade_google_docs/tools/search.py,sha256=1k1cI-fKOo4SZU4ufCwZ4DysK3l9MhPScZggPfNCC5Y,8261
|
|
17
|
+
arcade_google_docs/tools/update.py,sha256=_dReYit0s7ykn2bYQEUwohl3D_63U5leF87egO4eEiQ,1836
|
|
18
|
+
arcade_google_docs/tools/edit_agent/edit_agent.py,sha256=1LIgKrQ70pDWzWNoaoy1st659perqa-ZW_ALmbVRbW0,2439
|
|
19
|
+
arcade_google_docs/tools/edit_agent/executor.py,sha256=YbJqNXF0fw4N-u59gTbLpOBwKfoL7N6KZIOzV0pTllc,3718
|
|
20
|
+
arcade_google_docs/tools/edit_agent/planner.py,sha256=38aslAnlPDEY3JEoVXtHqL3Oq_9RDEFxyETqoEBsJLk,4053
|
|
21
|
+
arcade_google_docs/tools/edit_agent/progress_tracker.py,sha256=eb69tk-yL3uhEEo4ggPoBFtZtHTA6OwgcPxELtvbeEs,1280
|
|
22
|
+
arcade_google_docs/tools/edit_agent/prompts.py,sha256=M_f-HsPJppd3FQPhRAw7pKpaArkVfz213mKVx8qHp8A,15149
|
|
23
|
+
arcade_google_docs/tools/edit_agent/request_generator.py,sha256=eVDmzJDsOmJ-S8yANmJATt_G51rgCcCga6ArX4DTShM,5399
|
|
24
|
+
arcade_google_docs/tools/edit_agent/utils.py,sha256=6lYmdQfX4CHfemP5PfxcXKSYpbdqFyEad997-gzCD48,639
|
|
25
|
+
arcade_google_docs/tools/edit_agent/models/planning.py,sha256=RWQFB_KHl3Pq-snv1rHzoRxVvTnHVLZEGRpdohSX7wc,2962
|
|
26
|
+
arcade_google_docs-4.1.0.dist-info/METADATA,sha256=ufO055P83TTGSEMN81EVwVhp6KusftVC20JpJwu0BRE,1127
|
|
27
|
+
arcade_google_docs-4.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
28
|
+
arcade_google_docs-4.1.0.dist-info/RECORD,,
|
arcade_google_docs/decorators.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import functools
|
|
2
|
-
from collections.abc import Callable
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
from arcade_tdk import ToolContext
|
|
6
|
-
from googleapiclient.errors import HttpError
|
|
7
|
-
|
|
8
|
-
from arcade_google_docs.file_picker import generate_google_file_picker_url
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def with_filepicker_fallback(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
12
|
-
""" """
|
|
13
|
-
|
|
14
|
-
@functools.wraps(func)
|
|
15
|
-
async def async_wrapper(context: ToolContext, *args: Any, **kwargs: Any) -> Any:
|
|
16
|
-
try:
|
|
17
|
-
return await func(context, *args, **kwargs)
|
|
18
|
-
except HttpError as e:
|
|
19
|
-
if e.status_code in [403, 404]:
|
|
20
|
-
file_picker_response = generate_google_file_picker_url(context)
|
|
21
|
-
return file_picker_response
|
|
22
|
-
raise
|
|
23
|
-
|
|
24
|
-
return async_wrapper
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
arcade_google_docs/__init__.py,sha256=J3c3lEuqb86UE5zScpv7Gd4TltmzTUq_tWyA2Ff0gmI,528
|
|
2
|
-
arcade_google_docs/decorators.py,sha256=5ONZ3vS2lZBmog5c1TcuWjyPDeftBPAJ7vXyLjSPFRk,751
|
|
3
|
-
arcade_google_docs/doc_to_html.py,sha256=6RTpzRSrazNa6AndLZhA20wgVDzZuHUqpu3WAkAsbjQ,3146
|
|
4
|
-
arcade_google_docs/doc_to_markdown.py,sha256=eT-sc6ruxN8nEtUm9mBHFOWXajEBTTXkxsn6XsLHIxo,2020
|
|
5
|
-
arcade_google_docs/enum.py,sha256=vFJWPe1JPG6I9xqdVVvuaEeen4LvvtJxax1sDYeh4UU,3421
|
|
6
|
-
arcade_google_docs/file_picker.py,sha256=kGfUVfH5QVlIW1sL-_gAwPokt7TwVEcPk3Vnk53GKUE,2005
|
|
7
|
-
arcade_google_docs/templates.py,sha256=pxbdMj57eV3-ImW3CixDWscpVKS94Z8nTNyTxDhUfGY,283
|
|
8
|
-
arcade_google_docs/utils.py,sha256=XMgKcWPWKy8SbH3y2eCil01hssHhUgYxVrwXyvHEU4A,3748
|
|
9
|
-
arcade_google_docs/tools/__init__.py,sha256=vtn_NKrYwgWsdgcDYBY4t8m_XF73jB4j7zrpt-NC-dI,707
|
|
10
|
-
arcade_google_docs/tools/comment.py,sha256=Qm5NHdNHONs3j4gqbZ7Fw9NrTVBb_mZ-th1X-z2IoLM,2836
|
|
11
|
-
arcade_google_docs/tools/create.py,sha256=AuYy8yMGscrxAdLJQX0WiisGHCTufSlaRu_QGMMKQmM,2764
|
|
12
|
-
arcade_google_docs/tools/get.py,sha256=2wi9ZF9s_57mMbIGgsqr53Fr0AJyrYVOQ11x7nAyk8Y,1339
|
|
13
|
-
arcade_google_docs/tools/search.py,sha256=6wMacfbO3Pzxu30I-otaFIA5b9b9AKcIkgHr8M9QXLo,9007
|
|
14
|
-
arcade_google_docs/tools/update.py,sha256=9SvffQIHnmYiEgyE1VrhXG2aHb0hIfWYPzPLc4nTdKI,2030
|
|
15
|
-
arcade_google_docs-3.1.1.dist-info/METADATA,sha256=reKLvMCf-wM_GLIExvxUYXYUiCxYxoRXqN9vpiNa-24,1097
|
|
16
|
-
arcade_google_docs-3.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
17
|
-
arcade_google_docs-3.1.1.dist-info/RECORD,,
|
|
File without changes
|