@pgflow/core 0.0.5 → 0.0.7

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.
Files changed (110) hide show
  1. package/{CHANGELOG.md → dist/CHANGELOG.md} +6 -0
  2. package/package.json +8 -5
  3. package/__tests__/mocks/index.ts +0 -1
  4. package/__tests__/mocks/postgres.ts +0 -37
  5. package/__tests__/types/PgflowSqlClient.test-d.ts +0 -59
  6. package/docs/options_for_flow_and_steps.md +0 -75
  7. package/docs/pgflow-blob-reference-system.md +0 -179
  8. package/eslint.config.cjs +0 -22
  9. package/example-flow.mermaid +0 -5
  10. package/example-flow.svg +0 -1
  11. package/flow-lifecycle.mermaid +0 -83
  12. package/flow-lifecycle.svg +0 -1
  13. package/out-tsc/vitest/__tests__/mocks/index.d.ts +0 -2
  14. package/out-tsc/vitest/__tests__/mocks/index.d.ts.map +0 -1
  15. package/out-tsc/vitest/__tests__/mocks/postgres.d.ts +0 -15
  16. package/out-tsc/vitest/__tests__/mocks/postgres.d.ts.map +0 -1
  17. package/out-tsc/vitest/__tests__/types/PgflowSqlClient.test-d.d.ts +0 -2
  18. package/out-tsc/vitest/__tests__/types/PgflowSqlClient.test-d.d.ts.map +0 -1
  19. package/out-tsc/vitest/tsconfig.spec.tsbuildinfo +0 -1
  20. package/out-tsc/vitest/vite.config.d.ts +0 -3
  21. package/out-tsc/vitest/vite.config.d.ts.map +0 -1
  22. package/pkgs/core/dist/index.js +0 -54
  23. package/pkgs/core/dist/pkgs/core/LICENSE.md +0 -660
  24. package/pkgs/core/dist/pkgs/core/README.md +0 -373
  25. package/pkgs/dsl/dist/index.js +0 -123
  26. package/pkgs/dsl/dist/pkgs/dsl/README.md +0 -11
  27. package/pkgs/edge-worker/dist/index.js +0 -953
  28. package/pkgs/edge-worker/dist/index.js.map +0 -7
  29. package/pkgs/edge-worker/dist/pkgs/edge-worker/LICENSE.md +0 -660
  30. package/pkgs/edge-worker/dist/pkgs/edge-worker/README.md +0 -46
  31. package/pkgs/example-flows/dist/index.js +0 -152
  32. package/pkgs/example-flows/dist/pkgs/example-flows/README.md +0 -11
  33. package/project.json +0 -125
  34. package/prompts/architect.md +0 -87
  35. package/prompts/condition.md +0 -33
  36. package/prompts/declarative_sql.md +0 -15
  37. package/prompts/deps_in_payloads.md +0 -20
  38. package/prompts/dsl-multi-arg.ts +0 -48
  39. package/prompts/dsl-options.md +0 -39
  40. package/prompts/dsl-single-arg.ts +0 -51
  41. package/prompts/dsl-two-arg.ts +0 -61
  42. package/prompts/dsl.md +0 -119
  43. package/prompts/fanout_steps.md +0 -1
  44. package/prompts/json_schemas.md +0 -36
  45. package/prompts/one_shot.md +0 -286
  46. package/prompts/pgtap.md +0 -229
  47. package/prompts/sdk.md +0 -59
  48. package/prompts/step_types.md +0 -62
  49. package/prompts/versioning.md +0 -16
  50. package/queries/fail_permanently.sql +0 -17
  51. package/queries/fail_task.sql +0 -21
  52. package/queries/sequential.sql +0 -47
  53. package/queries/two_roots_left_right.sql +0 -59
  54. package/schema.svg +0 -1
  55. package/scripts/colorize-pgtap-output.awk +0 -72
  56. package/scripts/run-test-with-colors +0 -5
  57. package/scripts/watch-test +0 -7
  58. package/src/PgflowSqlClient.ts +0 -85
  59. package/src/database-types.ts +0 -759
  60. package/src/index.ts +0 -3
  61. package/src/types.ts +0 -103
  62. package/supabase/config.toml +0 -32
  63. package/supabase/seed.sql +0 -202
  64. package/supabase/tests/add_step/basic_step_addition.test.sql +0 -29
  65. package/supabase/tests/add_step/circular_dependency.test.sql +0 -21
  66. package/supabase/tests/add_step/flow_isolation.test.sql +0 -26
  67. package/supabase/tests/add_step/idempotent_step_addition.test.sql +0 -20
  68. package/supabase/tests/add_step/invalid_step_slug.test.sql +0 -16
  69. package/supabase/tests/add_step/nonexistent_dependency.test.sql +0 -16
  70. package/supabase/tests/add_step/nonexistent_flow.test.sql +0 -13
  71. package/supabase/tests/add_step/options.test.sql +0 -66
  72. package/supabase/tests/add_step/step_with_dependency.test.sql +0 -36
  73. package/supabase/tests/add_step/step_with_multiple_dependencies.test.sql +0 -46
  74. package/supabase/tests/complete_task/archives_message.test.sql +0 -67
  75. package/supabase/tests/complete_task/completes_run_if_no_more_remaining_steps.test.sql +0 -62
  76. package/supabase/tests/complete_task/completes_task_and_updates_dependents.test.sql +0 -64
  77. package/supabase/tests/complete_task/decrements_remaining_steps_if_completing_step.test.sql +0 -62
  78. package/supabase/tests/complete_task/saves_output_when_completing_run.test.sql +0 -57
  79. package/supabase/tests/create_flow/flow_creation.test.sql +0 -27
  80. package/supabase/tests/create_flow/idempotency_and_duplicates.test.sql +0 -26
  81. package/supabase/tests/create_flow/invalid_slug.test.sql +0 -13
  82. package/supabase/tests/create_flow/options.test.sql +0 -57
  83. package/supabase/tests/fail_task/exponential_backoff.test.sql +0 -70
  84. package/supabase/tests/fail_task/mark_as_failed_if_no_retries_available.test.sql +0 -49
  85. package/supabase/tests/fail_task/respects_flow_retry_settings.test.sql +0 -48
  86. package/supabase/tests/fail_task/respects_step_retry_settings.test.sql +0 -48
  87. package/supabase/tests/fail_task/retry_task_if_retries_available.test.sql +0 -39
  88. package/supabase/tests/is_valid_slug.test.sql +0 -72
  89. package/supabase/tests/poll_for_tasks/builds_proper_input_from_deps_outputs.test.sql +0 -35
  90. package/supabase/tests/poll_for_tasks/hides_messages.test.sql +0 -35
  91. package/supabase/tests/poll_for_tasks/increments_attempts_count.test.sql +0 -35
  92. package/supabase/tests/poll_for_tasks/multiple_task_processing.test.sql +0 -24
  93. package/supabase/tests/poll_for_tasks/polls_only_queued_tasks.test.sql +0 -35
  94. package/supabase/tests/poll_for_tasks/reads_messages.test.sql +0 -38
  95. package/supabase/tests/poll_for_tasks/returns_no_tasks_if_no_step_task_for_message.test.sql +0 -34
  96. package/supabase/tests/poll_for_tasks/returns_no_tasks_if_queue_is_empty.test.sql +0 -19
  97. package/supabase/tests/poll_for_tasks/returns_no_tasks_when_qty_set_to_0.test.sql +0 -22
  98. package/supabase/tests/poll_for_tasks/sets_vt_delay_based_on_opt_timeout.test.sql +0 -41
  99. package/supabase/tests/poll_for_tasks/tasks_reapppear_if_not_processed_in_time.test.sql +0 -59
  100. package/supabase/tests/start_flow/creates_run.test.sql +0 -24
  101. package/supabase/tests/start_flow/creates_step_states_for_all_steps.test.sql +0 -25
  102. package/supabase/tests/start_flow/creates_step_tasks_only_for_root_steps.test.sql +0 -54
  103. package/supabase/tests/start_flow/returns_run.test.sql +0 -24
  104. package/supabase/tests/start_flow/sends_messages_on_the_queue.test.sql +0 -50
  105. package/supabase/tests/start_flow/starts_only_root_steps.test.sql +0 -21
  106. package/supabase/tests/step_dsl_is_idempotent.test.sql +0 -34
  107. package/tsconfig.json +0 -16
  108. package/tsconfig.lib.json +0 -26
  109. package/tsconfig.spec.json +0 -35
  110. package/vite.config.ts +0 -57
@@ -1,46 +0,0 @@
1
- <div align="center">
2
- <h1>Edge Worker</h1>
3
- <a href="https://pgflow.dev">
4
- <h3>📚 Documentation @ pgflow.dev</h3>
5
- </a>
6
-
7
- <h4>⚠️ <strong>ADVANCED PROOF of CONCEPT - NOT PRODUCTION READY</strong> ⚠️</h4>
8
- </div>
9
-
10
- A task queue worker for Supabase Edge Functions that extends background tasks with useful features.
11
-
12
- > [!NOTE]
13
- > This project is licensed under [AGPL v3](./LICENSE.md) license and is part of **pgflow** stack.
14
- > See [LICENSING_OVERVIEW.md](../../LICENSING_OVERVIEW.md) in root of this monorepo for more details.
15
-
16
- ## What is Edge Worker?
17
-
18
- Edge Worker processes messages from a queue and executes user-defined functions with their payloads. It builds upon [Supabase Background Tasks](https://supabase.com/docs/guides/functions/background-tasks) to add reliability features like retries, concurrency control and monitoring.
19
-
20
- ## Key Features
21
-
22
- - ⚡ **Reliable Processing**: Retries with configurable delays
23
- - 🔄 **Concurrency Control**: Limit parallel task execution
24
- - 📊 **Observability**: Built-in heartbeats and logging
25
- - 📈 **Horizontal Scaling**: Deploy multiple edge functions for the same queue
26
- - 🛡️ **Edge-Native**: Designed for Edge Functions' CPU/clock limits
27
-
28
- ## How It Works
29
-
30
- [![Architecture Diagram](https://mermaid.ink/img/pako:eNplkcFugzAMhl8lyrl9AQ47VLBxqdSqlZAGHEziASokyEkmTaXvvoR0o1VziGL_n_9Y9pULLZEnvFItwdSxc1op5o9xTUxU_OQmaMAgy2SL7N0pYXutTMUjGU5WlItYaLog1VFAJSv14paCXdweyw8f-2MZLnZ06LBelXxXRk_DztAM-Gp9KA-kpRP-W7bdvs3Ga4aNaAy0OC_WdzD4B4IQVsLMvvkIZMUiA4mu_8ZHYjW5MxNp4dUnKC9zUHJA-h9R_VQTG-sQyDYINlTs-IaPSCP00q_gGvCK2w5HP53EPyXQJczp5jlwVp9-lOCJJYcbTtq13V_gJgkW0x78lEeefMFgfHYC9an1GqPsraZ9XPiy99svlAqmtA?type=png)](https://mermaid.live/edit#pako:eNplkcFugzAMhl8lyrl9AQ47VLBxqdSqlZAGHEziASokyEkmTaXvvoR0o1VziGL_n_9Y9pULLZEnvFItwdSxc1op5o9xTUxU_OQmaMAgy2SL7N0pYXutTMUjGU5WlItYaLog1VFAJSv14paCXdweyw8f-2MZLnZ06LBelXxXRk_DztAM-Gp9KA-kpRP-W7bdvs3Ga4aNaAy0OC_WdzD4B4IQVsLMvvkIZMUiA4mu_8ZHYjW5MxNp4dUnKC9zUHJA-h9R_VQTG-sQyDYINlTs-IaPSCP00q_gGvCK2w5HP53EPyXQJczp5jlwVp9-lOCJJYcbTtq13V_gJgkW0x78lEeefMFgfHYC9an1GqPsraZ9XPiy99svlAqmtA)
31
-
32
- ## Edge Function Optimization
33
-
34
- Edge Worker is specifically designed to handle Edge Function limitations:
35
-
36
- - Stops polling near CPU/clock limits
37
- - Gracefully aborts pending tasks
38
- - Uses PGMQ's visibility timeout to prevent message loss
39
- - Auto-spawns new instances for continuous operation
40
- - Monitors worker health with database heartbeats
41
-
42
-
43
- ## Documentation
44
-
45
- For detailed documentation and getting started guide, visit [pgflow.dev](https://pgflow.dev).
46
-
@@ -1,152 +0,0 @@
1
- // ../dsl/src/utils.ts
2
- function validateSlug(slug) {
3
- if (slug.length > 128) {
4
- throw new Error(`Slug cannot be longer than 128 characters`);
5
- }
6
- if (/^\d/.test(slug)) {
7
- throw new Error(`Slug cannot start with a number`);
8
- }
9
- if (/^_/.test(slug)) {
10
- throw new Error(`Slug cannot start with an underscore`);
11
- }
12
- if (/\s/.test(slug)) {
13
- throw new Error(`Slug cannot contain spaces`);
14
- }
15
- if (/[/:#\-?]/.test(slug)) {
16
- throw new Error(
17
- `Slug cannot contain special characters like /, :, ?, #, -`
18
- );
19
- }
20
- }
21
- function validateRuntimeOptions(options, opts = { optional: false }) {
22
- const { maxAttempts, baseDelay, timeout } = options;
23
- if (maxAttempts !== void 0 && maxAttempts !== null) {
24
- if (maxAttempts < 1) {
25
- throw new Error("maxAttempts must be greater than or equal to 1");
26
- }
27
- } else if (!opts.optional) {
28
- throw new Error("maxAttempts is required");
29
- }
30
- if (baseDelay !== void 0 && baseDelay !== null) {
31
- if (baseDelay < 1) {
32
- throw new Error("baseDelay must be greater than or equal to 1");
33
- }
34
- } else if (!opts.optional) {
35
- throw new Error("baseDelay is required");
36
- }
37
- if (timeout !== void 0 && timeout !== null) {
38
- if (timeout < 3) {
39
- throw new Error("timeout must be greater than or equal to 3");
40
- }
41
- } else if (!opts.optional) {
42
- throw new Error("timeout is required");
43
- }
44
- }
45
-
46
- // ../dsl/src/dsl.ts
47
- var Flow = class _Flow {
48
- /**
49
- * Store step definitions with their proper types
50
- *
51
- * This is typed as a generic record because TypeScript cannot track the exact relationship
52
- * between step slugs and their corresponding input/output types at the container level.
53
- * Type safety is enforced at the method level when adding or retrieving steps.
54
- */
55
- stepDefinitions;
56
- stepOrder;
57
- slug;
58
- options;
59
- constructor(config, stepDefinitions = {}, stepOrder = []) {
60
- const { slug, ...options } = config;
61
- validateSlug(slug);
62
- validateRuntimeOptions(options, { optional: true });
63
- this.slug = slug;
64
- this.options = options;
65
- this.stepDefinitions = stepDefinitions;
66
- this.stepOrder = [...stepOrder];
67
- }
68
- /**
69
- * Get a specific step definition by slug with proper typing
70
- * @throws Error if the step with the given slug doesn't exist
71
- */
72
- getStepDefinition(slug) {
73
- if (!(slug in this.stepDefinitions)) {
74
- throw new Error(
75
- `Step "${String(slug)}" does not exist in flow "${this.slug}"`
76
- );
77
- }
78
- return this.stepDefinitions[slug];
79
- }
80
- // SlugType extends keyof Steps & keyof StepDependencies
81
- step(opts, handler) {
82
- const slug = opts.slug;
83
- validateSlug(slug);
84
- if (this.stepDefinitions[slug]) {
85
- throw new Error(`Step "${slug}" already exists in flow "${this.slug}"`);
86
- }
87
- const dependencies = opts.dependsOn || [];
88
- if (dependencies.length > 0) {
89
- for (const dep of dependencies) {
90
- if (!this.stepDefinitions[dep]) {
91
- throw new Error(`Step "${slug}" depends on undefined step "${dep}"`);
92
- }
93
- }
94
- }
95
- const options = {};
96
- if (opts.maxAttempts !== void 0)
97
- options.maxAttempts = opts.maxAttempts;
98
- if (opts.baseDelay !== void 0)
99
- options.baseDelay = opts.baseDelay;
100
- if (opts.timeout !== void 0)
101
- options.timeout = opts.timeout;
102
- validateRuntimeOptions(options, { optional: true });
103
- const newStepDefinition = {
104
- slug,
105
- handler,
106
- dependencies,
107
- options
108
- };
109
- const newStepDefinitions = {
110
- ...this.stepDefinitions,
111
- [slug]: newStepDefinition
112
- };
113
- const newStepOrder = [...this.stepOrder, slug];
114
- return new _Flow(
115
- { slug: this.slug, ...this.options },
116
- newStepDefinitions,
117
- newStepOrder
118
- );
119
- }
120
- };
121
-
122
- // ../example-flows/src/example-flow.ts
123
- var ExampleFlow = new Flow({
124
- slug: "example_flow",
125
- maxAttempts: 3
126
- }).step({ slug: "rootStep" }, async (input) => ({
127
- doubledValue: input.run.value * 2
128
- })).step(
129
- { slug: "normalStep", dependsOn: ["rootStep"], maxAttempts: 5 },
130
- async (input) => ({
131
- doubledValueArray: [input.rootStep.doubledValue]
132
- })
133
- ).step({ slug: "thirdStep", dependsOn: ["normalStep"] }, async (input) => ({
134
- // input.rootStep would be a type error since it's not in dependsOn
135
- finalValue: input.normalStep.doubledValueArray.length
136
- }));
137
- var stepTaskRecord = {
138
- flow_slug: "example_flow",
139
- run_id: "123",
140
- step_slug: "normalStep",
141
- input: {
142
- run: { value: 23 },
143
- rootStep: { doubledValue: 23 }
144
- // thirdStep: { finalValue: 23 }, --- this should be an error
145
- // normalStep: { doubledValueArray: [1, 2, 3] }, --- this should be an error
146
- },
147
- msg_id: 1
148
- };
149
- export {
150
- ExampleFlow,
151
- stepTaskRecord
152
- };
@@ -1,11 +0,0 @@
1
- # example-flows
2
-
3
- This library was generated with [Nx](https://nx.dev).
4
-
5
- ## Building
6
-
7
- Run `nx build example-flows` to build the library.
8
-
9
- ## Running unit tests
10
-
11
- Run `nx test example-flows` to execute the unit tests via [Vitest](https://vitest.dev/).
package/project.json DELETED
@@ -1,125 +0,0 @@
1
- {
2
- "name": "core",
3
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
- "sourceRoot": "pkgs/core/src",
5
- "projectType": "library",
6
- "tags": [],
7
- "targets": {
8
- "build": {
9
- "executor": "@nx/esbuild:esbuild",
10
- "outputs": ["{options.outputPath}"],
11
- "options": {
12
- "outputPath": "pkgs/core/dist",
13
- "main": "pkgs/core/src/index.ts",
14
- "tsConfig": "pkgs/core/tsconfig.lib.json",
15
- "assets": ["pkgs/core/*.md"]
16
- }
17
- },
18
- "lint": {
19
- "executor": "nx:run-commands",
20
- "options": {
21
- "cwd": "{projectRoot}",
22
- "commands": ["sqruff --config=../../.sqruff lint --parsing-errors"],
23
- "inputs": ["{projectRoot}/**/*.sql", "{workspaceRoot}/.sqruff"],
24
- "parallel": false
25
- }
26
- },
27
- "fix-sql": {
28
- "executor": "nx:run-commands",
29
- "options": {
30
- "cwd": "{projectRoot}",
31
- "commands": [
32
- "sqruff --config=../../.sqruff fix --force --parsing-errors"
33
- ],
34
- "inputs": ["{projectRoot}/**/*.sql", "{workspaceRoot}/.sqruff"],
35
- "parallel": false
36
- }
37
- },
38
- "supabase:ensure-started": {
39
- "executor": "nx:run-commands",
40
- "options": {
41
- "cwd": "{projectRoot}",
42
- "commands": [
43
- "supabase status || (echo \"Starting Supabase...\" && supabase start)"
44
- ],
45
- "parallel": false
46
- }
47
- },
48
- "supabase:start": {
49
- "executor": "nx:run-commands",
50
- "options": {
51
- "cwd": "{projectRoot}",
52
- "commands": ["supabase start"],
53
- "parallel": false
54
- }
55
- },
56
- "supabase:stop": {
57
- "executor": "nx:run-commands",
58
- "options": {
59
- "cwd": "{projectRoot}",
60
- "commands": ["supabase stop --no-backup"],
61
- "parallel": false
62
- }
63
- },
64
- "supabase:status": {
65
- "executor": "nx:run-commands",
66
- "options": {
67
- "cwd": "{projectRoot}",
68
- "commands": ["supabase status"],
69
- "parallel": false
70
- }
71
- },
72
- "supabase:restart": {
73
- "executor": "nx:run-commands",
74
- "options": {
75
- "cwd": "{projectRoot}",
76
- "commands": ["supabase stop --no-backup", "supabase start"],
77
- "parallel": false
78
- }
79
- },
80
- "supabase:reset": {
81
- "executor": "nx:run-commands",
82
- "options": {
83
- "cwd": "{projectRoot}",
84
- "commands": ["supabase db reset"],
85
- "parallel": false
86
- }
87
- },
88
- "test": {
89
- "executor": "nx:noop",
90
- "dependsOn": ["test:pgtap", "test:vitest"]
91
- },
92
- "test:pgtap": {
93
- "executor": "nx:run-commands",
94
- "dependsOn": ["supabase:ensure-started"],
95
- "options": {
96
- "cwd": "{projectRoot}",
97
- "commands": ["scripts/run-test-with-colors"],
98
- "parallel": false
99
- }
100
- },
101
- "test:vitest": {
102
- "executor": "@nx/vite:test",
103
- "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
104
- "options": {
105
- "passWithNoTests": true,
106
- "reportsDirectory": "{workspaceRoot}/coverage/{projectRoot}"
107
- }
108
- },
109
- "test:pgtap:watch": {
110
- "executor": "nx:run-commands",
111
- "options": {
112
- "cwd": "{projectRoot}",
113
- "command": "scripts/watch-test"
114
- },
115
- "cache": false
116
- },
117
- "gen-types": {
118
- "executor": "nx:run-commands",
119
- "options": {
120
- "command": "supabase gen types --local --schema pgflow --schema pgmq > src/database-types.ts",
121
- "cwd": "{projectRoot}"
122
- }
123
- }
124
- }
125
- }
@@ -1,87 +0,0 @@
1
- # Architect Mode
2
-
3
- ## Your Role
4
- You are a senior software architect with extensive experience designing scalable, maintainable systems. Your purpose is to thoroughly analyze requirements and design optimal solutions before any implementation begins. You must resist the urge to immediately write code and instead focus on comprehensive planning and architecture design.
5
-
6
- ## Your Behavior Rules
7
- - You must thoroughly understand requirements before proposing solutions
8
- - You must reach 90% confidence in your understanding before suggesting implementation
9
- - You must identify and resolve ambiguities through targeted questions
10
- - You must document all assumptions clearly
11
-
12
- ## Process You Must Follow
13
-
14
- ### Phase 1: Requirements Analysis
15
- 1. Carefully read all provided information about the project or feature
16
- 2. Extract and list all functional requirements explicitly stated
17
- 3. Identify implied requirements not directly stated
18
- 4. Determine non-functional requirements including:
19
- - Performance expectations
20
- - Security requirements
21
- - Scalability needs
22
- - Maintenance considerations
23
- 5. Ask clarifying questions about any ambiguous requirements
24
- 6. Report your current understanding confidence (0-100%)
25
-
26
- ### Phase 2: System Context Examination
27
- 1. If an existing codebase is available:
28
- - Request to examine directory structure
29
- - Ask to review key files and components
30
- - Identify integration points with the new feature
31
- 2. Identify all external systems that will interact with this feature
32
- 3. Define clear system boundaries and responsibilities
33
- 4. If beneficial, create a high-level system context diagram
34
- 5. Update your understanding confidence percentage
35
-
36
- ### Phase 3: Architecture Design
37
- 1. Propose 2-3 potential architecture patterns that could satisfy requirements
38
- 2. For each pattern, explain:
39
- - Why it's appropriate for these requirements
40
- - Key advantages in this specific context
41
- - Potential drawbacks or challenges
42
- 3. Recommend the optimal architecture pattern with justification
43
- 4. Define core components needed in the solution, with clear responsibilities for each
44
- 5. Design all necessary interfaces between components
45
- 6. If applicable, design database schema showing:
46
- - Entities and their relationships
47
- - Key fields and data types
48
- - Indexing strategy
49
- 7. Address cross-cutting concerns including:
50
- - Authentication/authorization approach
51
- - Error handling strategy
52
- - Logging and monitoring
53
- - Security considerations
54
- 8. Update your understanding confidence percentage
55
-
56
- ### Phase 4: Technical Specification
57
- 1. Recommend specific technologies for implementation, with justification
58
- 2. Break down implementation into distinct phases with dependencies
59
- 3. Identify technical risks and propose mitigation strategies
60
- 4. Create detailed component specifications including:
61
- - API contracts
62
- - Data formats
63
- - State management
64
- - Validation rules
65
- 5. Define technical success criteria for the implementation
66
- 6. Update your understanding confidence percentage
67
-
68
- ### Phase 5: Transition Decision
69
- 1. Summarize your architectural recommendation concisely
70
- 2. Present implementation roadmap with phases
71
- 3. State your final confidence level in the solution
72
- 4. If confidence ≥ 90%:
73
- - State: "I'm ready to build! Switch to Agent mode and tell me to continue."
74
- 5. If confidence < 90%:
75
- - List specific areas requiring clarification
76
- - Ask targeted questions to resolve remaining uncertainties
77
- - State: "I need additional information before we start coding."
78
-
79
- ## Response Format
80
- Always structure your responses in this order:
81
- 1. Current phase you're working on
82
- 2. Findings or deliverables for that phase
83
- 3. Current confidence percentage
84
- 4. Questions to resolve ambiguities (if any)
85
- 5. Next steps
86
-
87
- Remember: Your primary value is in thorough design that prevents costly implementation mistakes. Take the time to design correctly before suggesting to use Agent mode.
@@ -1,33 +0,0 @@
1
- # Conditional Steps in the Flow DSL
2
-
3
- Conditional steps allow steps to run only when certain criteria are met based on the incoming payload. Instead of always executing as soon as their dependencies complete, these steps check the provided condition against the input data.
4
-
5
- ## How It Works
6
-
7
- - **Definition**: A condition is supplied as a JSON fragment via the step options (for example, using `runIf` or `runUnless`).
8
- - **Evaluation**: At runtime, the system evaluates the condition by comparing the step's combined inputs against the JSON fragment.
9
- - **Mechanism**: Under the hood, the payload is matched against the condition using a JSON containment operator (`@>`), commonly available in PostgreSQL. This operator checks if the input JSON "contains" the condition JSON structure.
10
- - **Outcome**:
11
- - If the condition is met (for `runIf`) or not met (for `runUnless`), the step is executed.
12
- - If the condition fails, the step is marked as skipped, and its downstream dependent steps are not executed (or are similarly marked as skipped).
13
-
14
- This design helps ensure that unnecessary processing is avoided when prerequisites are not satisfied.
15
-
16
- ## Type safety
17
-
18
- Options object can be strictly type-safe and only allow values that are available in the payload,
19
- so it is impossible to define invalid condition object.
20
-
21
- ## Marking as skipped
22
-
23
- Skipped steps are not considered a failure but will propagate skipped status to all dependent steps and
24
- they will not run.
25
-
26
- This way we can achieve a kinda robust low level branching logic - users can define branches
27
- by creating steps with mutually-exclusive conditions, so only one branch will be executed:
28
-
29
- ```ts
30
- const ScrapeWebsiteFlow = new Flow<{ input: true }>()
31
- .step({ slug: 'run_if_true', runIf: { run: { input: true } } }, handler)
32
- .step({ slug: 'run_if_false', runUnless: { run: { input: true } } }, handler);
33
- ```
@@ -1,15 +0,0 @@
1
- ### Declarative vs procedural
2
-
3
- **YOU MUST ALWAYS PRIORITIZE DECLARATIVE STYLE** and prioritize Batching operations.
4
-
5
- Avoid plpgsql as much as you can.
6
- It is important to have your DB procedures run in batched ways and use declarative rather than procedural constructs where possible:
7
-
8
- - do not ever use `language plplsql` in functions, always use `language sql`
9
- - don't do loops, do SQL statements that address multiple rows at once.
10
- - don't write trigger functions that fire for a single row, use `FOR EACH STATEMENT` instead.
11
- - don't call functions for each row in a result set, a condition, a join, or whatever; instead use functions that return `SETOF` and join against these.
12
-
13
- If you're constructing dynamic SQL, you should only ever use `%I` and `%L` when using `FORMAT` or similar; you should never see `%s` (with the very rare exception of where you're merging in another SQL fragment that you've previously formatted using %I and %L).
14
-
15
- Remember, that functions have significant overhead in Postgres - instead of factoring into lots of tiny functions, think about how to make your code more expressive so there's no need.
@@ -1,20 +0,0 @@
1
- currently the 'input' jsonb that we are building contains only the 'run' input
2
-
3
- we really want to have this jsonb to contain all the deps outputs
4
- by dep output i mean a step_tasks.output value that corresponds to step_states row that is a dependency of the given updated_step_tasks (via step_states->steps)
5
- the step_slug of a given dependency should be used as key and its output as value in the input jsonb
6
-
7
- so, if a given updated_step_task belongs to step_state, that have 2 dependencies:
8
-
9
- step_slug=dep_a output=123
10
- step_slug=dep_b output=456
11
-
12
- we would like the final 'input' jsonb to look like this:
13
-
14
- {
15
- "run": r.input,
16
- "dep_a": dep_a_step_task.output,
17
- "dep_b": dep_b_step_task.output
18
- }
19
-
20
- write appropriate joins and augment this code with this requirements
@@ -1,48 +0,0 @@
1
- const ScrapeWebsiteFlow = new Flow<Input>()
2
- .step('verify_status', async (payload) => {
3
- // Placeholder function
4
- return { status: 'success' };
5
- })
6
- .step(
7
- 'when_success',
8
- ['verify_status'],
9
- async (payload) => {
10
- // Placeholder function
11
- return await scrapeSubpages(
12
- payload.run.url,
13
- payload.table_of_contents.urls_of_subpages
14
- );
15
- },
16
- { runIf: { verify_status: { status: 'success' } } }
17
- )
18
- .step(
19
- 'when_server_error',
20
- ['verify_status'],
21
- async (payload) => {
22
- // Placeholder function
23
- return await generateSummaries(payload.subpages.contentsOfSubpages);
24
- },
25
- { runUnless: { verify_status: { status: 'success' } } }
26
- )
27
-
28
- .step(
29
- 'sentiments',
30
- ['subpages'],
31
- async (payload) => {
32
- // Placeholder function
33
- return await analyzeSentiments(payload.subpages.contentsOfSubpages);
34
- },
35
- { maxAttempts: 5, baseDelay: 10 }
36
- )
37
- .step(
38
- 'save_to_db',
39
- ['subpages', 'summaries', 'sentiments'],
40
- async (payload) => {
41
- // Placeholder function
42
- return await saveToDb(
43
- payload.subpages,
44
- payload.summaries,
45
- payload.sentiments
46
- );
47
- }
48
- );
@@ -1,39 +0,0 @@
1
- # Flow DSL with options
2
-
3
- The idea is to add 4th argument to the `.step` method which will be an object
4
- for the step options:
5
-
6
- ```ts
7
- {
8
- runIf: Json;
9
- runUnless: Json;
10
- maxAttempts: number;
11
- baseDelay: number;
12
- }
13
- ```
14
-
15
- ## Full flow example
16
-
17
- ```ts
18
- const ScrapeWebsiteFlow = new Flow<Input>()
19
- .step('verify_status', async (payload) => {
20
- // Placeholder function
21
- return { status: 'success' }
22
- })
23
- .step('when_success', ['verify_status'], async (payload) => {
24
- // Placeholder function
25
- return await scrapeSubpages(payload.run.url, payload.table_of_contents.urls_of_subpages);
26
- }, { runIf: { status: 'success' } })
27
- .step('when_server_error', ['verify_status'], async (payload) => {
28
- // Placeholder function
29
- return await generateSummaries(payload.subpages.contentsOfSubpages);
30
- }, { runUnless: { status: 'success' } })
31
- .step('sentiments', ['subpages'], async (payload) => {
32
- // Placeholder function
33
- return await analyzeSentiments(payload.subpages.contentsOfSubpages);
34
- }, { maxAttempts: 5, baseDelay: 10 })
35
- .step('save_to_db', ['subpages', 'summaries', 'sentiments'], async (payload) => {
36
- // Placeholder function
37
- return await saveToDb(payload.subpages, payload.summaries, payload.sentiments);
38
- });
39
- ```
@@ -1,51 +0,0 @@
1
- const ScrapeWebsiteFlow = new Flow<Input>()
2
- .step({
3
- id: 'verify_status',
4
- handler: async (payload) => {
5
- // Placeholder function
6
- return { status: 'success' };
7
- },
8
- })
9
- .step({
10
- id: 'when_success',
11
- deps: ['verify_status'],
12
- runIf: { verify_status: { status: 'success' } },
13
- async handler(payload) {
14
- // Placeholder function
15
- return await scrapeSubpages(
16
- payload.run.url,
17
- payload.table_of_contents.urls_of_subpages
18
- );
19
- }
20
- })
21
- .step({
22
- id: 'when_server_error',
23
- deps: ['verify_status'],
24
- runUnless: { verify_status: { status: 'success' } },
25
- async handler(payload) {
26
- // Placeholder function
27
- return await generateSummaries(payload.subpages.contentsOfSubpages);
28
- }
29
- })
30
- .step({
31
- id: 'sentiments',
32
- deps: ['subpages'],
33
- async handler(payload) {
34
- // Placeholder function
35
- return await analyzeSentiments(payload.subpages.contentsOfSubpages);
36
- },
37
- maxAttempts: 5,
38
- baseDelay: 10
39
- })
40
- .step({
41
- id: 'save_to_db',
42
- deps: ['subpages', 'summaries', 'sentiments'],
43
- async handler(payload) {
44
- // Placeholder function
45
- return await saveToDb(
46
- payload.subpages,
47
- payload.summaries,
48
- payload.sentiments
49
- );
50
- },
51
- });