chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Resolve the document ID for a Docs API request, preferring the selected
|
||||
* document ID and falling back to a manually entered one. Throws when neither
|
||||
* is present so callers fail loudly before issuing a request.
|
||||
*/
|
||||
export function resolveDocumentId(params: {
|
||||
documentId?: string
|
||||
manualDocumentId?: string
|
||||
}): string {
|
||||
const documentId = params.documentId?.trim() || params.manualDocumentId?.trim()
|
||||
if (!documentId) {
|
||||
throw new Error('Document ID is required')
|
||||
}
|
||||
return documentId
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize an optional boolean param that may arrive as a real boolean or as a
|
||||
* string (`"true"`/`"false"`), which happens when values come from block inputs
|
||||
* or agent tool-calls rather than a typed UI switch. Returns `undefined` when the
|
||||
* value is absent or unrecognized so callers can skip the field entirely.
|
||||
*/
|
||||
export function parseOptionalBoolean(value: unknown): boolean | undefined {
|
||||
if (typeof value === 'boolean') return value
|
||||
if (typeof value === 'string') {
|
||||
const normalized = value.trim().toLowerCase()
|
||||
if (normalized === 'true') return true
|
||||
if (normalized === 'false') return false
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a `Location` for a batchUpdate request when an insertion index is
|
||||
* provided, otherwise fall back to `endOfSegmentLocation` (end of the body).
|
||||
* The Docs API treats index 0 as invalid, so a positive index is required to
|
||||
* use an explicit location.
|
||||
*/
|
||||
export function buildInsertLocation(
|
||||
index?: number
|
||||
): { location: { index: number } } | { endOfSegmentLocation: Record<string, never> } {
|
||||
if (typeof index === 'number' && Number.isFinite(index) && index >= 1) {
|
||||
return { location: { index } }
|
||||
}
|
||||
return { endOfSegmentLocation: {} }
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and validate a Docs API `Range` from a start and end character index.
|
||||
* The Docs API requires `endIndex` to be strictly greater than `startIndex`.
|
||||
* Throws when either index is missing or the range is empty/inverted so callers
|
||||
* fail loudly before issuing a request.
|
||||
*/
|
||||
export function buildContentRange(
|
||||
startIndex: unknown,
|
||||
endIndex: unknown
|
||||
): { startIndex: number; endIndex: number } {
|
||||
const start = Number(startIndex)
|
||||
const end = Number(endIndex)
|
||||
if (!Number.isFinite(start) || !Number.isFinite(end)) {
|
||||
throw new Error('startIndex and endIndex are required')
|
||||
}
|
||||
if (end <= start) {
|
||||
throw new Error('endIndex must be greater than startIndex')
|
||||
}
|
||||
return { startIndex: start, endIndex: end }
|
||||
}
|
||||
|
||||
/**
|
||||
* Build canonical Google Docs metadata from a batchUpdate response. The
|
||||
* `documentId` is taken from the response body when present, otherwise parsed
|
||||
* from the request URL (`.../documents/{id}:batchUpdate`).
|
||||
*/
|
||||
export function buildBatchUpdateMetadata(
|
||||
data: { documentId?: string },
|
||||
responseUrl: string
|
||||
): { documentId: string; title: string; mimeType: string; url: string } {
|
||||
let documentId = data.documentId ?? ''
|
||||
if (!documentId) {
|
||||
const urlParts = responseUrl.split('/')
|
||||
for (let i = 0; i < urlParts.length; i++) {
|
||||
if (urlParts[i] === 'documents' && i + 1 < urlParts.length) {
|
||||
documentId = urlParts[i + 1].split(':')[0]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
documentId,
|
||||
title: 'Updated Document',
|
||||
mimeType: 'application/vnd.google-apps.document',
|
||||
url: `https://docs.google.com/document/d/${documentId}/edit`,
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to extract text content from Google Docs document structure
|
||||
export function extractTextFromDocument(document: any): string {
|
||||
let text = ''
|
||||
|
||||
if (!document.body || !document.body.content) {
|
||||
return text
|
||||
}
|
||||
|
||||
// Process each structural element in the document
|
||||
for (const element of document.body.content) {
|
||||
if (element.paragraph) {
|
||||
for (const paragraphElement of element.paragraph.elements) {
|
||||
if (paragraphElement.textRun?.content) {
|
||||
text += paragraphElement.textRun.content
|
||||
}
|
||||
}
|
||||
} else if (element.table) {
|
||||
// Process tables if needed
|
||||
for (const tableRow of element.table.tableRows) {
|
||||
for (const tableCell of tableRow.tableCells) {
|
||||
if (tableCell.content) {
|
||||
for (const cellContent of tableCell.content) {
|
||||
if (cellContent.paragraph) {
|
||||
for (const paragraphElement of cellContent.paragraph.elements) {
|
||||
if (paragraphElement.textRun?.content) {
|
||||
text += paragraphElement.textRun.content
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
Reference in New Issue
Block a user