Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/docs/content/docs/cli/logs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ sim logs get <runId> [options]

| Option | Required | Description |
| --- | --- | --- |
| `--include-workflow-state` | No | Include the saved workflow snapshot (default: true). Set false to omit block configuration from a log read. Other run fields are unchanged. |
| `--no-include-workflow-state` | No | Send --include-workflow-state as false. |
| `--trace` | No | Show expanded trace spans with inputs, outputs, errors, timing, and cost. |

</CommandTable>
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/content/docs/cli/reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2731,6 +2731,8 @@ sim logs get <runId> [options]

| Option | Required | Description |
| --- | --- | --- |
| `--include-workflow-state` | No | Include the saved workflow snapshot (default: true). Set false to omit block configuration from a log read. Other run fields are unchanged. |
| `--no-include-workflow-state` | No | Send --include-workflow-state as false. |
| `--trace` | No | Show expanded trace spans with inputs, outputs, errors, timing, and cost. |

</CommandTable>
Expand Down
12 changes: 8 additions & 4 deletions apps/docs/content/docs/integrations/stripe.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ Cancel a subscription

### Stripe Resume Subscription

Resume a subscription that was scheduled for cancellation
Resume a paused subscription

#### Input

Expand Down Expand Up @@ -1299,7 +1299,7 @@ Resume a subscription that was scheduled for cancellation

### Stripe List Subscriptions

List all subscriptions
List one page of subscriptions. Follow starting_after while metadata.has_more is true.

#### Input

Expand All @@ -1309,6 +1309,8 @@ List all subscriptions
| `limit` | number | No | Number of results to return \(default 10, max 100\) |
| `customer` | string | No | Filter by customer ID |
| `status` | string | No | Filter by status \(active, past_due, unpaid, canceled, incomplete, incomplete_expired, trialing, all\) |
| `starting_after` | string | No | Next-page cursor: last subscription ID from the previous page. Do not combine with ending_before. |
| `ending_before` | string | No | Previous-page cursor: first subscription ID from the current page. Do not combine with starting_after. |
| `price` | string | No | Filter by price ID |

#### Output
Expand Down Expand Up @@ -1378,14 +1380,15 @@ List all subscriptions

### Stripe Search Subscriptions

Search for subscriptions using query syntax
Search one page of subscriptions using query syntax. Pass metadata.next_page as page to continue.

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Stripe API key \(secret key\) |
| `query` | string | Yes | Search query \(e.g., "status:'active' AND customer:'cus_xxx'"\) |
| `query` | string | Yes | Search query \(e.g., "status:'active' AND metadata\['order_id'\]:'6735'"\) |
| `page` | string | No | Pagination token from metadata.next_page. Omit for the first page and keep the same query. |
| `limit` | number | No | Number of results to return \(default 10, max 100\) |

#### Output
Expand Down Expand Up @@ -1452,6 +1455,7 @@ Search for subscriptions using query syntax
| `metadata` | json | Search metadata |
| ↳ `count` | number | Number of items returned |
| ↳ `has_more` | boolean | Whether more items exist beyond this page |
| ↳ `next_page` | string | Token for the next page of search results, or null when there are no more results |

### Stripe Create Invoice

Expand Down
12 changes: 11 additions & 1 deletion apps/docs/openapi-v2-logs.json
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,16 @@
"pattern": "^[A-Za-z0-9._:-]+$",
"description": "Unique workflow run identifier."
}
},
{
"name": "includeWorkflowState",
"in": "query",
"required": false,
"description": "Include the saved workflow snapshot (default: true). Set false to omit block configuration from a log read. Other run fields are unchanged.",
"schema": {
"description": "Include the saved workflow snapshot (default: true). Set false to omit block configuration from a log read. Other run fields are unchanged.",
"type": "boolean"
}
}
],
"responses": {
Expand Down Expand Up @@ -1602,7 +1612,7 @@
"type": "null"
}
],
"description": "Workflow graph captured for the run, or null if unavailable. Sensitive values are redacted to null; environment-variable references may be preserved."
"description": "Workflow graph captured for the run, or null if unavailable or includeWorkflowState=false. Sensitive values are redacted to null; environment-variable references may be preserved."
},
"traceSpans": {
"type": "array",
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/app/api/v2/logs/[runId]/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ describe('GET /api/v2/logs/[runId]', () => {
expect(body.data).not.toHaveProperty('executionData')
expect(mocks.execute).toHaveBeenCalledWith({
principal: auth.principal,
input: { runId: 'run-1' },
input: { runId: 'run-1', includeWorkflowState: true },
request,
})
})
Expand Down
5 changes: 4 additions & 1 deletion apps/sim/app/api/v2/logs/[runId]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ export const GET = defineV2JsonRoute({
operation: logOperations.readDetail,
rateLimit: v2RateLimits.publicApi,
errorPolicy: v2LogErrorPolicies.concealDetailAuthorization,
mapInput: ({ params }) => ({ runId: params.runId }),
mapInput: ({ params, query }) => ({
runId: params.runId,
includeWorkflowState: query.includeWorkflowState,
}),
useCase: getPublicLog,
present: ({ log, workflowFolderPath, executionData, costLedger }) => {
const detail: V2LogDetail = {
Expand Down
36 changes: 32 additions & 4 deletions apps/sim/blocks/blocks/stripe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,30 @@ export const StripeBlock: BlockConfig<StripeResponse> = {
},
required: true,
},
{
id: 'starting_after',
title: 'Starting After',
type: 'short-input',
placeholder: 'Last subscription ID from the previous page',
condition: { field: 'operation', value: 'list_subscriptions' },
mode: 'advanced',
},
{
id: 'ending_before',
title: 'Ending Before',
type: 'short-input',
placeholder: 'First subscription ID from the current page',
condition: { field: 'operation', value: 'list_subscriptions' },
mode: 'advanced',
},
{
id: 'page',
title: 'Search Page',
type: 'short-input',
placeholder: 'Token from metadata.next_page; omit for the first page',
condition: { field: 'operation', value: 'search_subscriptions' },
mode: 'advanced',
},
// Additional filters for specific list operations
{
id: 'status',
Expand Down Expand Up @@ -976,6 +1000,9 @@ export const StripeBlock: BlockConfig<StripeResponse> = {
recurring: { type: 'json', description: 'Recurring billing configuration' },
// List/Search inputs
limit: { type: 'number', description: 'Maximum results to return' },
starting_after: { type: 'string', description: 'Next-page subscription ID cursor' },
ending_before: { type: 'string', description: 'Previous-page subscription ID cursor' },
page: { type: 'string', description: 'Subscription search token from metadata.next_page' },
query: { type: 'string', description: 'Search query' },
status: { type: 'string', description: 'Status filter' },
type: { type: 'string', description: 'Event type filter' },
Expand Down Expand Up @@ -1096,19 +1123,20 @@ export const StripeBlockMeta = {
description:
'Create and confirm a Stripe payment intent to collect a charge from a customer.',
content:
'# Collect Payment\n\nCharge a customer by creating and confirming a payment intent.\n\n## Steps\n1. Run Create Payment Intent with the amount, currency, and customer.\n2. Confirm the intent with Confirm Payment Intent, or Capture Payment Intent if it was created for manual capture.\n3. If a charge needs to be aborted, run Cancel Payment Intent instead.\n\n## Output\nReturn the payment intent ID, its status (succeeded, requires action, or canceled), and the captured amount.',
'# Collect Payment\n\nCharge a customer by creating and confirming a payment intent.\n\n## Steps\n1. Run Create Payment Intent with the amount, currency, and customer.\n2. Confirm the intent with Confirm Payment Intent and a payment method. If the confirmed intent has status requires_capture, run Capture Payment Intent to collect the authorized funds.\n3. If a charge needs to be aborted, run Cancel Payment Intent instead.\n\n## Output\nReturn the payment intent ID, its status (succeeded, requires action, or canceled), and the captured amount.',
},
{
name: 'manage-subscription',
description: 'Create, update, pause, or cancel a Stripe subscription for a customer.',
description:
'Create a Stripe subscription, manage its cancellation, or resume a paused subscription.',
content:
'# Manage Subscription\n\nHandle the lifecycle of a recurring subscription.\n\n## Steps\n1. To start a subscription, run Create Subscription with the customer and price items.\n2. To change a plan, run Update Subscription with the new items. To pause and later restart, use Cancel Subscription or Resume Subscription as appropriate.\n3. Confirm the current state with Retrieve Subscription.\n\n## Output\nReturn the subscription ID, its status, current period end, and the plan items, and note exactly what changed.',
'# Manage Subscription\n\nHandle the lifecycle of a recurring subscription.\n\n## Steps\n1. To start a subscription, run Create Subscription with the customer and price items.\n2. Use Update Subscription with cancel_at_period_end to schedule or reverse a cancellation before it takes effect. Use Cancel Subscription only for immediate cancellation. Resume Subscription applies only to a paused subscription; it does not restart a canceled subscription.\n3. Confirm the current state with Retrieve Subscription.\n\n## Output\nReturn the subscription ID, its status, and the returned subscription items, and note exactly what changed.',
Comment thread
waleedlatif1 marked this conversation as resolved.
},
{
name: 'issue-invoice',
description: 'Create, finalize, and send a Stripe invoice to a customer, then track payment.',
content:
'# Issue Invoice\n\nBill a customer with a Stripe invoice.\n\n## Steps\n1. Run Create Invoice for the customer with the line items.\n2. Run Finalize Invoice to lock it, then Send Invoice to deliver it to the customer.\n3. Track payment with Retrieve Invoice, or run Pay Invoice to charge a saved payment method. Use Void Invoice to cancel an unpaid invoice.\n\n## Output\nReturn the invoice ID, its status (draft, open, paid, or void), the amount due, and the hosted invoice URL when available.',
'# Issue Invoice\n\nBill a customer with a Stripe invoice.\n\n## Steps\n1. Run Create Invoice for the customer. This tool does not add line items; add them in Stripe and verify the draft with Retrieve Invoice before finalizing.\n2. Run Finalize Invoice to lock it, then Send Invoice to deliver it to the customer.\n3. Track payment with Retrieve Invoice, or run Pay Invoice to charge a saved payment method. Use Void Invoice to cancel an unpaid invoice.\n\n## Output\nReturn the invoice ID, its status (draft, open, paid, or void), the amount due, and the hosted invoice URL when available.',
},
{
name: 'find-customer-activity',
Expand Down
24 changes: 18 additions & 6 deletions apps/sim/lib/api/contracts/v2/logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { z } from 'zod'
import { traceSpansSchema } from '@/lib/api/contracts/logs'
import {
booleanQueryFlagSchema,
noInputSchema,
runIdSchema,
workspaceIdSchema,
} from '@/lib/api/contracts/primitives'
Expand All @@ -24,9 +23,8 @@ import { v2RunFileSchema } from '@/lib/api/contracts/v2/workflows'
import { PERSISTED_WORKFLOW_EXECUTION_STATUSES } from '@/lib/logs/types'

/**
* v2 logs contracts. The query schemas are reused verbatim from v1 (the request
* shape is unchanged); only the response envelope is upgraded to the canonical
* v2 shapes with concrete item schemas.
* v2 logs contracts. List queries retain the v1 filters; responses use the
* canonical v2 envelope and concrete item schemas.
*/

const v2LogCostSchema = z
Expand Down Expand Up @@ -164,7 +162,7 @@ const v2LogWorkflowStateSchema = z
)
.nullable()
.describe(
'Workflow graph captured for the run, or null if unavailable. Sensitive values are redacted to null; environment-variable references may be preserved.'
'Workflow graph captured for the run, or null if unavailable or includeWorkflowState=false. Sensitive values are redacted to null; environment-variable references may be preserved.'
)

const v2LogWorkflowSummarySchema = z.object({
Expand Down Expand Up @@ -717,7 +715,21 @@ export const v2ListLogsContract = defineRouteContract({
export const v2GetLogContract = defineRouteContract({
method: 'GET',
path: '/api/v2/logs/[runId]',
query: noInputSchema,
query: z
.object({
includeWorkflowState: booleanQueryFlagSchema
.default(true)
.describe(
'Include the saved workflow snapshot (default: true). Set false to omit block configuration from a log read. Other run fields are unchanged.'
),
})
.strict()
.meta({
id: 'GetLogQuery',
title: 'Execution log detail options',
description: 'Controls whether a log detail read includes its saved workflow snapshot.',
examples: [{ includeWorkflowState: false }],
}),
params: v2LogParamsSchema,
response: {
mode: 'json',
Expand Down
6 changes: 4 additions & 2 deletions apps/sim/lib/logs/application/get-public-log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface PublicLogContext extends ActiveWorkspaceApplicationContext {

export interface GetPublicLogInput {
runId: string
includeWorkflowState?: boolean
}

export interface GetPublicLogResult {
Expand Down Expand Up @@ -94,7 +95,7 @@ export const getPublicLog = defineAuthorizedWorkspaceUseCase({
return { ...workspace, executionId: scope.executionId, workflowId: scope.workflowId }
},
authorizationOptions: logDelegationAuthorization<PublicLogContext>(),
execute: async ({ principal, context }): Promise<GetPublicLogResult> => {
execute: async ({ principal, input, context }): Promise<GetPublicLogResult> => {
/**
* Attribution and the projection subject in one value; a workspace API key
* represents no user and therefore reads the run whole. See
Expand All @@ -118,7 +119,8 @@ export const getPublicLog = defineAuthorizedWorkspaceUseCase({

const log = await getPublicWorkflowLog(
{ column: 'executionId', value: context.executionId },
context.workspaceId
context.workspaceId,
{ includeWorkflowState: input.includeWorkflowState }
)
if (!log || log.workflowId !== context.workflowId) {
throw new OrchestrationError('not_found', 'Log not found')
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/lib/logs/application/public-log-use-cases.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ describe('public log application use cases', () => {
expect(mocks.loadWorkspace).toHaveBeenCalledWith('workspace-1')
expect(mocks.getLog).toHaveBeenCalledWith(
{ column: 'executionId', value: 'run-1' },
'workspace-1'
'workspace-1',
{ includeWorkflowState: undefined }
)
expect(mocks.materialize).toHaveBeenCalledWith(
{ pointer: true },
Expand Down
11 changes: 9 additions & 2 deletions apps/sim/lib/logs/public-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,11 @@ export async function getPublicWorkflowLogScope(executionId: string) {
* is deliberately left-sided: a missing snapshot does not make an otherwise
* valid execution disappear from the log resource.
*/
export async function getPublicWorkflowLog(lookup: PublicWorkflowLogLookup, workspaceId?: string) {
export async function getPublicWorkflowLog(
lookup: PublicWorkflowLogLookup,
workspaceId?: string,
options: { includeWorkflowState?: boolean } = {}
) {
const lookupCondition =
lookup.column === 'id'
? eq(workflowExecutionLogs.id, lookup.value)
Expand All @@ -478,7 +482,10 @@ export async function getPublicWorkflowLog(lookup: PublicWorkflowLogLookup, work
costTotal: workflowExecutionLogs.costTotal,
files: workflowExecutionLogs.files,
createdAt: workflowExecutionLogs.createdAt,
workflowState: workflowExecutionSnapshots.stateData,
workflowState:
options.includeWorkflowState === false
? sql<null>`null`
: workflowExecutionSnapshots.stateData,
workflowName: workflow.name,
workflowDescription: workflow.description,
workflowFolderId: workflow.folderId,
Expand Down
Loading
Loading