@owlmeans/viable-common 0.0.24 → 0.0.25
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.
- package/README.md +4 -4
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/agent-presentation/SKILL.md +1 -1
- package/agent-meta/skills/viable-common/SKILL.md +10 -9
- package/build/blueprint/case.js +3 -3
- package/build/connect/consts.d.ts +10 -43
- package/build/connect/consts.d.ts.map +1 -1
- package/build/connect/consts.js +13 -48
- package/build/connect/consts.js.map +1 -1
- package/build/connect/entrypoints.d.ts +22 -19
- package/build/connect/entrypoints.d.ts.map +1 -1
- package/build/connect/entrypoints.js +8 -4
- package/build/connect/entrypoints.js.map +1 -1
- package/build/connect/index.d.ts +0 -1
- package/build/connect/index.d.ts.map +1 -1
- package/build/connect/index.js +0 -1
- package/build/connect/index.js.map +1 -1
- package/build/connect/ops.d.ts +1 -4
- package/build/connect/ops.d.ts.map +1 -1
- package/build/connect/references.d.ts +20 -16
- package/build/connect/references.d.ts.map +1 -1
- package/build/connect/references.js +3 -1
- package/build/connect/references.js.map +1 -1
- package/build/connect/schemas.d.ts +6 -3
- package/build/connect/schemas.d.ts.map +1 -1
- package/build/connect/schemas.js +4 -4
- package/build/connect/schemas.js.map +1 -1
- package/build/connect/types.d.ts +36 -66
- package/build/connect/types.d.ts.map +1 -1
- package/build/design/runtime.d.ts +1 -1
- package/build/design/runtime.d.ts.map +1 -1
- package/build/planning/consts.d.ts +1 -1
- package/build/planning/consts.js +1 -1
- package/build/skills/catalogue.d.ts.map +1 -1
- package/build/skills/catalogue.js +22 -15
- package/build/skills/catalogue.js.map +1 -1
- package/package.json +8 -8
- package/src/blueprint/case.ts +3 -3
- package/src/connect/consts.ts +10 -45
- package/src/connect/entrypoints.ts +26 -20
- package/src/connect/index.ts +0 -1
- package/src/connect/ops.ts +1 -4
- package/src/connect/references.ts +34 -28
- package/src/connect/schemas.ts +8 -8
- package/src/connect/types.ts +38 -69
- package/src/design/runtime.ts +1 -1
- package/src/planning/consts.ts +1 -1
- package/src/skills/catalogue.ts +22 -15
- package/tests/connect-convert.spec.ts +2 -8
- package/tests/connect-entrypoints.spec.ts +11 -29
- package/build/connect/jobs.d.ts +0 -25
- package/build/connect/jobs.d.ts.map +0 -1
- package/build/connect/jobs.js +0 -29
- package/build/connect/jobs.js.map +0 -1
- package/src/connect/jobs.ts +0 -40
package/src/connect/types.ts
CHANGED
|
@@ -4,8 +4,8 @@ import type {
|
|
|
4
4
|
OriginState, StoryEstimateBand
|
|
5
5
|
} from '../convert/index.js'
|
|
6
6
|
import type {
|
|
7
|
-
ConnectExecutor, ConnectHarness,
|
|
8
|
-
|
|
7
|
+
ConnectExecutor, ConnectHarness, ConnectLlm, ConnectSessionStatus, ConnectTarget,
|
|
8
|
+
ConnectTransport, ConnectWaitReason, ModelTier
|
|
9
9
|
} from './consts.js'
|
|
10
10
|
import type { InquiryAnswerPayload, InquiryPayload } from './ops.js'
|
|
11
11
|
|
|
@@ -82,68 +82,22 @@ export interface ConnectSessionView {
|
|
|
82
82
|
expiresAt: string
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
* Never stored. It is composed per request from the project lock, the slot record, the story
|
|
89
|
-
* card, the latest pipeline run row and the operations queued for the project — the same facts
|
|
90
|
-
* the manager UI reads, arranged for a caller that has one question ("may I stop waiting?") and
|
|
91
|
-
* one follow-up ("what do I call next?").
|
|
92
|
-
*
|
|
93
|
-
* Its `id` is composed and parsed only through `jobIdOf` / `parseJobId`.
|
|
94
|
-
*/
|
|
95
|
-
export interface ConnectJob {
|
|
96
|
-
id: string
|
|
97
|
-
kind: ConnectJobKind
|
|
98
|
-
status: ConnectJobStatus
|
|
99
|
-
/** The project CARD id. */
|
|
100
|
-
projectId: string
|
|
101
|
-
/**
|
|
102
|
-
* The story CARD id — never the story's code.
|
|
103
|
-
*
|
|
104
|
-
* The name is kept because a parent agent reads it: a wire field name is that agent's
|
|
105
|
-
* vocabulary and is never renamed, only re-documented.
|
|
106
|
-
*/
|
|
107
|
-
storyId?: string
|
|
108
|
-
runId?: string
|
|
109
|
-
/** The pipeline step in flight, when a run row says. */
|
|
110
|
-
phase?: string
|
|
111
|
-
progress?: ConnectJobProgress
|
|
112
|
-
blockedOn?: ConnectJobBlock
|
|
113
|
-
/**
|
|
114
|
-
* The question a parked run is waiting on — present exactly when it is blocked on one.
|
|
115
|
-
*
|
|
116
|
-
* Carried on the job rather than left to a second lookup because a parent reads a job and
|
|
117
|
-
* nothing else while it polls: a run that stopped for a person, described only as "blocked",
|
|
118
|
-
* is a run whose parent waits out the timeout for a question it was never shown. It is also
|
|
119
|
-
* the ONLY way back to a question whose operation timed out while nobody was attached — the
|
|
120
|
-
* connector's own queue holds nothing at that point.
|
|
121
|
-
*/
|
|
122
|
-
inquiry?: InquiryPayload
|
|
123
|
-
/** One sentence a parent agent can show a human. */
|
|
124
|
-
message?: string
|
|
125
|
-
/** Present on `Failed`, and on `Done` where the run recorded a warning. */
|
|
126
|
-
error?: string
|
|
127
|
-
/** Kind-specific payload once `Done`. */
|
|
128
|
-
result?: Record<string, unknown>
|
|
129
|
-
startedAt?: string
|
|
130
|
-
updatedAt: string
|
|
85
|
+
export interface ConnectPullQuery {
|
|
86
|
+
/** Seconds to wait before answering; clamped to the pull ceiling. */
|
|
87
|
+
wait?: number
|
|
131
88
|
}
|
|
132
89
|
|
|
133
|
-
export interface
|
|
90
|
+
export interface ConnectRunStatus {
|
|
91
|
+
runId: string
|
|
92
|
+
pipeline: string
|
|
93
|
+
status: string
|
|
134
94
|
step?: string
|
|
135
95
|
completed: string[]
|
|
136
96
|
pending: string[]
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
jobId: string
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export interface ConnectWaitQuery {
|
|
145
|
-
/** Seconds to wait before answering; clamped to the pull ceiling. */
|
|
146
|
-
wait?: number
|
|
97
|
+
warnings?: string[]
|
|
98
|
+
error?: string
|
|
99
|
+
startedAt?: string
|
|
100
|
+
updatedAt?: string
|
|
147
101
|
}
|
|
148
102
|
|
|
149
103
|
/** What a connector needs to know about a project in one call. */
|
|
@@ -181,18 +135,30 @@ export interface ConnectProjectStatus {
|
|
|
181
135
|
}
|
|
182
136
|
production?: { id: string, status: string, host?: string }
|
|
183
137
|
agent: { locked: boolean, task?: string, lockedAt?: string }
|
|
184
|
-
run?:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
status: string
|
|
188
|
-
step?: string
|
|
189
|
-
completed: string[]
|
|
190
|
-
pending: string[]
|
|
191
|
-
error?: string
|
|
192
|
-
}
|
|
138
|
+
run?: ConnectRunStatus
|
|
139
|
+
waitingFor?: ConnectWaitReason
|
|
140
|
+
pendingInquiry?: InquiryPayload
|
|
193
141
|
session?: ConnectSessionView
|
|
194
142
|
/** Set for a local target: the connector should not offer cloud-only operations. */
|
|
195
143
|
local: boolean
|
|
144
|
+
updatedAt: string
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** A story card composed with its deterministic development run. */
|
|
148
|
+
export interface ConnectStoryStatus {
|
|
149
|
+
projectId: string
|
|
150
|
+
story: {
|
|
151
|
+
id: string
|
|
152
|
+
code: string
|
|
153
|
+
title: string
|
|
154
|
+
status: string
|
|
155
|
+
intrinsic: string
|
|
156
|
+
warning?: string
|
|
157
|
+
}
|
|
158
|
+
run?: ConnectRunStatus
|
|
159
|
+
waitingFor?: ConnectWaitReason
|
|
160
|
+
pendingInquiry?: InquiryPayload
|
|
161
|
+
updatedAt: string
|
|
196
162
|
}
|
|
197
163
|
|
|
198
164
|
/** The record a local project keeps so a later session knows what it is. */
|
|
@@ -217,7 +183,7 @@ export interface ConnectProfileSettingsView extends ConnectProfileSettings {
|
|
|
217
183
|
* The profile's preference for who performs a CONVERSION's model calls.
|
|
218
184
|
*
|
|
219
185
|
* Its own setting rather than a reading of `llmMode`, because the two answer for different
|
|
220
|
-
* work: a conversion reads somebody else's whole repository, which is the one
|
|
186
|
+
* work: a conversion reads somebody else's whole repository, which is the one case where handing
|
|
221
187
|
* the inference to the parent agent is the cheap default rather than the experimental option.
|
|
222
188
|
*
|
|
223
189
|
* OPTIONAL for the same reason {@link ConnectCapabilitiesView.defaults} carries `converterLlm`
|
|
@@ -397,6 +363,7 @@ export interface ConversionStatusView {
|
|
|
397
363
|
runId?: string
|
|
398
364
|
/** Set exactly when `status` is `Waiting`: the question the run stopped on. */
|
|
399
365
|
pendingInquiry?: InquiryPayload
|
|
366
|
+
waitingFor?: ConnectWaitReason
|
|
400
367
|
lastError?: string
|
|
401
368
|
updatedAt: string
|
|
402
369
|
}
|
|
@@ -428,6 +395,8 @@ export interface ConnectPipelineState {
|
|
|
428
395
|
failedAt?: string
|
|
429
396
|
error?: string
|
|
430
397
|
note?: string
|
|
398
|
+
waitingFor?: ConnectWaitReason
|
|
399
|
+
pendingInquiry?: InquiryPayload
|
|
431
400
|
attempts: number
|
|
432
401
|
startedAt: string
|
|
433
402
|
heartbeatAt: string
|
package/src/design/runtime.ts
CHANGED
|
@@ -40,7 +40,7 @@ export const isEphemeralActor = (actor?: StoryActor): boolean =>
|
|
|
40
40
|
export interface StoryDesignJob {
|
|
41
41
|
/** The queue it is enqueued onto. */
|
|
42
42
|
queue: string
|
|
43
|
-
/** The job name, which
|
|
43
|
+
/** The job name, which becomes the backend-only `job:<name>` protocol alias. */
|
|
44
44
|
name: string
|
|
45
45
|
/** The processor module, relative to the worker package's `src`. */
|
|
46
46
|
path: string
|
package/src/planning/consts.ts
CHANGED
|
@@ -35,7 +35,7 @@ export const VIABLE_SPEC_FLOW = 'viable:spec'
|
|
|
35
35
|
* The story flow's status keys.
|
|
36
36
|
*
|
|
37
37
|
* Byte-identical to the strings a story has always carried — the frontmatter of
|
|
38
|
-
* `docs/stories/<code>.md`,
|
|
38
|
+
* `docs/stories/<code>.md`, connector status rendering, the board's columns, their i18n
|
|
39
39
|
* keys and every end-to-end selector read these exact values. A key is a wire contract and is
|
|
40
40
|
* never renamed.
|
|
41
41
|
*/
|
package/src/skills/catalogue.ts
CHANGED
|
@@ -82,9 +82,6 @@ export const ALIAS_CONVENTION = `
|
|
|
82
82
|
\`web:layout:\` alias and no \`app.web.layout\` — writing either addresses nothing.
|
|
83
83
|
- An endpoint alias is \`api:<entity>:<action>\` — \`api:task:list\`, \`api:task:create\`. The
|
|
84
84
|
group alias that carries the shared path and guard is \`api:<entity>\` — \`api:task\`.
|
|
85
|
-
- A queued job alias is \`job:<entity>:<action>\` — \`job:report:build\`, \`job:contract:analyze\`.
|
|
86
|
-
A job is never given a \`web:\` or \`api:\` alias, and an endpoint is never given a \`job:\` one:
|
|
87
|
-
the prefix is what says which side serves it.
|
|
88
85
|
- Lowercase kebab-case in every segment. The prefix is NOT optional and NOT decorative: access
|
|
89
86
|
rules are applied per side by it.
|
|
90
87
|
`.trim()
|
|
@@ -103,11 +100,12 @@ The generated project is a \`@owlmeans/create-app\` monorepo with five workspace
|
|
|
103
100
|
- \`sources/web\` — the react application.
|
|
104
101
|
- \`sources/worker\` — the queue consumer. Same context, no HTTP routes, one processor per job.
|
|
105
102
|
|
|
106
|
-
These files are the CONTRACT between the packages. Every screen
|
|
107
|
-
them
|
|
103
|
+
These files are the CONTRACT between the public packages. Every screen and endpoint passes through
|
|
104
|
+
them; technical worker protocols live in the backend package instead:
|
|
108
105
|
|
|
109
106
|
- \`sources/common/src/consts.ts\` — the \`app\` alias tree.
|
|
110
107
|
- \`sources/common/src/entrypoints.ts\` — the shared immutable protocol tree (\`appEntrypoints\`).
|
|
108
|
+
- \`sources/backend/src/jobs/index.ts\` — backend-only queue protocols and declarations.
|
|
111
109
|
- \`sources/api/src/entrypoints.ts\` — server bindings: \`bind\` + one \`handlers<Context>()\` wrap
|
|
112
110
|
per handler.
|
|
113
111
|
- \`sources/web/src/entrypoints.ts\` — client bindings (\`bindAll\` + \`bindScreen\`).
|
|
@@ -1390,25 +1388,34 @@ the work is invisible and the user is left pressing a button that appears to do
|
|
|
1390
1388
|
`),
|
|
1391
1389
|
|
|
1392
1390
|
skill(ViableSkill.WorkerJobs, 'Queues, jobs and processors', `
|
|
1393
|
-
Three
|
|
1391
|
+
Three server-side bindings have to agree, and a job that exists in two of the three is worse than one that
|
|
1394
1392
|
exists in none — a declared name nothing processes is a message that piles up, and a processor
|
|
1395
1393
|
with no declaration is dead code the barrel still imports.
|
|
1396
1394
|
|
|
1397
|
-
## 1. The queue — \`sources/backend/src/jobs/index.ts\`
|
|
1395
|
+
## 1. The protocol and queue — \`sources/backend/src/jobs/index.ts\`
|
|
1398
1396
|
A queue is an ADDRESS: it says what exists and which job names it accepts. Both the api (which
|
|
1399
1397
|
enqueues) and the worker (which consumes) read this one list, and a job name the queue does not
|
|
1400
|
-
declare is refused at enqueue time.
|
|
1398
|
+
declare is refused at enqueue time. The technical protocol belongs here too; common and web must
|
|
1399
|
+
not import it.
|
|
1401
1400
|
|
|
1402
1401
|
\`\`\`ts
|
|
1402
|
+
export const jobProtocols = {
|
|
1403
|
+
reportBuild: protocol(route(
|
|
1404
|
+
'job:report:build', '/report-build',
|
|
1405
|
+
queueRoute({ service: APP_WORKER, queue: APP_QUEUE, timeout: 30_000 }),
|
|
1406
|
+
), contract(typed())),
|
|
1407
|
+
}
|
|
1403
1408
|
export const queues: QueueDeclaration[] = [
|
|
1404
|
-
{ name: APP_QUEUE, jobs: [
|
|
1409
|
+
{ name: APP_QUEUE, jobs: [jobProtocols.reportBuild.alias],
|
|
1405
1410
|
worker: { concurrency: 4, lockDuration: 60_000 } },
|
|
1406
1411
|
]
|
|
1407
1412
|
\`\`\`
|
|
1408
1413
|
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1414
|
+
Use \`job()\` from \`@owlmeans/queue\`, never from the generic route package.
|
|
1415
|
+
|
|
1416
|
+
## 2. The producer — \`sources/api/src/entrypoints.ts\`
|
|
1417
|
+
Bind \`bindClient(jobProtocols.reportBuild)\`. Public API contracts in common describe the domain
|
|
1418
|
+
operation and do not disclose that the handler delegates to a queue.
|
|
1412
1419
|
|
|
1413
1420
|
## 3. The processor — \`sources/worker/src/jobs/<name>.ts\`
|
|
1414
1421
|
A PLAIN exported async function — named exports only, exactly like an endpoint handler. It never
|
|
@@ -1421,7 +1428,7 @@ imports \`handlers\` and never calls \`handlers<Context>()\`; that belongs only
|
|
|
1421
1428
|
// sources/worker/src/entrypoints.ts — the ONLY wrap
|
|
1422
1429
|
import * as jobs from '@/jobs/index.js'
|
|
1423
1430
|
const worker = handlers<Context>()
|
|
1424
|
-
bind(
|
|
1431
|
+
bind(jobProtocols.reportBuild, worker.request(jobProtocols.reportBuild, jobs.handleReportBuildJob))
|
|
1425
1432
|
|
|
1426
1433
|
WRONG — the processor module ALSO calls \`handlers()\` and wraps itself, so the export bound above
|
|
1427
1434
|
is wrapped a SECOND time. \`tsc\` catches it (\`TS2345 "BoundEntrypointHandler<…> is not
|
|
@@ -1430,7 +1437,7 @@ function\`:
|
|
|
1430
1437
|
|
|
1431
1438
|
// WRONG — sources/worker/src/jobs/report-build.ts
|
|
1432
1439
|
const worker = handlers<Context>()
|
|
1433
|
-
export const handleReportBuildJob = worker.request(
|
|
1440
|
+
export const handleReportBuildJob = worker.request(jobProtocols.reportBuild, async (req, ctx) => { ... })
|
|
1434
1441
|
|
|
1435
1442
|
It RETURNS its result; throwing a \`ResilientError\` subclass is how a refusal is reported, and the
|
|
1436
1443
|
class survives the broker.
|
|
@@ -1443,7 +1450,7 @@ Two rules with no equivalent on the HTTP side:
|
|
|
1443
1450
|
what it created, and say in a comment which of the two this one does.
|
|
1444
1451
|
|
|
1445
1452
|
Enqueue from an endpoint with the same typed call used for HTTP:
|
|
1446
|
-
\`context.entrypoint(
|
|
1453
|
+
\`context.entrypoint(jobProtocols.<name>).call({ body: data })\`.
|
|
1447
1454
|
`),
|
|
1448
1455
|
|
|
1449
1456
|
skill(ViableSkill.TargetAgents, 'LLM agents inside the application', `
|
|
@@ -3,7 +3,7 @@ import Ajv from 'ajv'
|
|
|
3
3
|
import addFormats from 'ajv-formats'
|
|
4
4
|
import { RouteMethod, route } from '@owlmeans/route'
|
|
5
5
|
import { aliasOf, openProtocol, protocols } from '@owlmeans/entrypoint'
|
|
6
|
-
import { connect, ConnectInquiryKind,
|
|
6
|
+
import { connect, ConnectInquiryKind, ConnectOpKind } from '../src/connect/consts.js'
|
|
7
7
|
import { connectProtocols } from '../src/connect/entrypoints.js'
|
|
8
8
|
import { connectRef } from '../src/connect/references.js'
|
|
9
9
|
import {
|
|
@@ -151,12 +151,6 @@ describe('viable-common - the conversion additions to the connector contract', (
|
|
|
151
151
|
// while the two enums stay byte-identical — `manager-api` does not depend on the model
|
|
152
152
|
// runtime, so nothing else in the stack would notice one of them gaining a fourth shape.
|
|
153
153
|
expect(Object.values(ConnectInquiryKind)).toEqual(Object.values(InquiryKind))
|
|
154
|
-
|
|
155
|
-
// names, so a single `convert` kind would match whichever run row happened to be newest.
|
|
156
|
-
expect(ConnectJobKind.ConvertIntake).toBe('convert-intake')
|
|
157
|
-
expect(ConnectJobKind.ConvertAnalysis).toBe('convert-analysis')
|
|
158
|
-
expect(ConnectJobKind.ConvertExtraction).toBe('convert-extraction')
|
|
159
|
-
expect(ConnectJobKind.ConvertImplementation).toBe('convert-implementation')
|
|
160
|
-
expect(ConnectJobKind.ConvertPurge).toBe('convert-purge')
|
|
154
|
+
expect(connect.convert.status).toBe('viable:manager-api:connect:convert:status')
|
|
161
155
|
})
|
|
162
156
|
})
|
|
@@ -2,9 +2,8 @@ import { describe, expect, test } from 'bun:test'
|
|
|
2
2
|
import { openProtocol, protocols } from '@owlmeans/entrypoint'
|
|
3
3
|
import { DEFAULT_GUARD } from '@owlmeans/auth-common'
|
|
4
4
|
import { route } from '@owlmeans/route'
|
|
5
|
-
import { connect
|
|
5
|
+
import { connect } from '../src/connect/consts.js'
|
|
6
6
|
import { connectProtocols } from '../src/connect/entrypoints.js'
|
|
7
|
-
import { JOB_SEPARATOR, jobIdOf, parseJobId } from '../src/connect/jobs.js'
|
|
8
7
|
import { connectRef } from '../src/connect/references.js'
|
|
9
8
|
|
|
10
9
|
describe('@owlmeans/viable-common — connector protocol tree', () => {
|
|
@@ -18,6 +17,7 @@ describe('@owlmeans/viable-common — connector protocol tree', () => {
|
|
|
18
17
|
expect(tree.session.open.alias).toBe(connect.session.open)
|
|
19
18
|
expect(tree.project.llm.alias).toBe(connect.project.llm)
|
|
20
19
|
expect(tree.project.converterLlm.alias).toBe(connect.project.converterLlm)
|
|
20
|
+
expect(tree.story.status.alias).toBe(connect.story.status)
|
|
21
21
|
expect(tree.convert.proceed.alias).toBe(connect.convert.proceed)
|
|
22
22
|
expect(tree.inquiry.answer.alias).toBe(connect.inquiry.answer)
|
|
23
23
|
expect(tree.files.list.alias).toBe(connect.files.list)
|
|
@@ -25,33 +25,15 @@ describe('@owlmeans/viable-common — connector protocol tree', () => {
|
|
|
25
25
|
expect(new Set(protocols(tree).map(protocol => protocol.alias)).size).toBe(32)
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
test('
|
|
29
|
-
expect((tree
|
|
30
|
-
expect((connect
|
|
31
|
-
expect((connectRef
|
|
32
|
-
expect(
|
|
28
|
+
test('keeps story mutations in planning and exposes only the composed story status', () => {
|
|
29
|
+
expect(Object.keys(tree.story)).toEqual(['status'])
|
|
30
|
+
expect(Object.keys(connect.story)).toEqual(['status'])
|
|
31
|
+
expect(Object.keys(connectRef.story)).toEqual(['status'])
|
|
32
|
+
expect(tree.story.status.route.route.path).toBe('/project/:id/story/:storyId/status')
|
|
33
33
|
})
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const id = jobIdOf(ConnectJobKind.StoryDevelop, 'project-card', 'story-card')
|
|
39
|
-
|
|
40
|
-
expect(id).toBe(['story-develop', 'project-card', 'story-card'].join(JOB_SEPARATOR))
|
|
41
|
-
expect(parseJobId(id)).toEqual({
|
|
42
|
-
kind: ConnectJobKind.StoryDevelop, projectId: 'project-card', suffix: 'story-card',
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
test('a job with no subject carries no suffix', () => {
|
|
47
|
-
expect(parseJobId(jobIdOf(ConnectJobKind.ProjectInit, 'p1'))).toEqual({
|
|
48
|
-
kind: ConnectJobKind.ProjectInit, projectId: 'p1',
|
|
49
|
-
})
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
test('a suffix that contains the separator is rejoined, never truncated', () => {
|
|
53
|
-
const suffix = `run${JOB_SEPARATOR}tail`
|
|
54
|
-
|
|
55
|
-
expect(parseJobId(jobIdOf(ConnectJobKind.PipelineResume, 'p1', suffix)).suffix).toBe(suffix)
|
|
34
|
+
test('has no generic connector job endpoint', () => {
|
|
35
|
+
expect((tree.project as Record<string, unknown>).job).toBeUndefined()
|
|
36
|
+
expect((connect.project as Record<string, unknown>).job).toBeUndefined()
|
|
37
|
+
expect((connectRef.project as Record<string, unknown>).job).toBeUndefined()
|
|
56
38
|
})
|
|
57
39
|
})
|
package/build/connect/jobs.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { ConnectJobKind } from './consts.js';
|
|
2
|
-
/**
|
|
3
|
-
* The separator a job id is joined with.
|
|
4
|
-
*
|
|
5
|
-
* `~`, because every other separator in play is already spoken for: a route alias is
|
|
6
|
-
* colon-delimited and so is every run id (`init:<projectId>`, `story:<storyId>`), so a job id
|
|
7
|
-
* built with one could not be split back apart.
|
|
8
|
-
*/
|
|
9
|
-
export declare const JOB_SEPARATOR = "~";
|
|
10
|
-
/**
|
|
11
|
-
* A job's id: its kind, the project card it belongs to, and the subject it is about.
|
|
12
|
-
*
|
|
13
|
-
* The suffix is a CARD id for a story job and a run id for a pipeline job — never a story code.
|
|
14
|
-
* Declared here rather than by whoever answers the job, because the SDK composes the id it then
|
|
15
|
-
* polls for: two spellings of one id is a job nobody can find.
|
|
16
|
-
*/
|
|
17
|
-
export declare const jobIdOf: (kind: ConnectJobKind, projectId: string, suffix?: string) => string;
|
|
18
|
-
export interface ParsedJobId {
|
|
19
|
-
kind: ConnectJobKind;
|
|
20
|
-
projectId: string;
|
|
21
|
-
suffix?: string;
|
|
22
|
-
}
|
|
23
|
-
/** Split a job id back into what {@link jobIdOf} composed it from. */
|
|
24
|
-
export declare const parseJobId: (jobId: string) => ParsedJobId;
|
|
25
|
-
//# sourceMappingURL=jobs.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../src/connect/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,MAAM,CAAA;AAEhC;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,SAAU,cAAc,aAAa,MAAM,WAAW,MAAM,KAAG,MACP,CAAA;AAE5E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,sEAAsE;AACtE,eAAO,MAAM,UAAU,UAAW,MAAM,KAAG,WAW1C,CAAA"}
|
package/build/connect/jobs.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The separator a job id is joined with.
|
|
3
|
-
*
|
|
4
|
-
* `~`, because every other separator in play is already spoken for: a route alias is
|
|
5
|
-
* colon-delimited and so is every run id (`init:<projectId>`, `story:<storyId>`), so a job id
|
|
6
|
-
* built with one could not be split back apart.
|
|
7
|
-
*/
|
|
8
|
-
export const JOB_SEPARATOR = '~';
|
|
9
|
-
/**
|
|
10
|
-
* A job's id: its kind, the project card it belongs to, and the subject it is about.
|
|
11
|
-
*
|
|
12
|
-
* The suffix is a CARD id for a story job and a run id for a pipeline job — never a story code.
|
|
13
|
-
* Declared here rather than by whoever answers the job, because the SDK composes the id it then
|
|
14
|
-
* polls for: two spellings of one id is a job nobody can find.
|
|
15
|
-
*/
|
|
16
|
-
export const jobIdOf = (kind, projectId, suffix) => [kind, projectId, ...(suffix != null ? [suffix] : [])].join(JOB_SEPARATOR);
|
|
17
|
-
/** Split a job id back into what {@link jobIdOf} composed it from. */
|
|
18
|
-
export const parseJobId = (jobId) => {
|
|
19
|
-
const [kind, projectId, ...rest] = jobId.split(JOB_SEPARATOR);
|
|
20
|
-
// A suffix may carry the separator back if one ever ends up in a card or run id, so the tail is
|
|
21
|
-
// rejoined rather than taken as its first segment.
|
|
22
|
-
const suffix = rest.length > 0 ? rest.join(JOB_SEPARATOR) : undefined;
|
|
23
|
-
return {
|
|
24
|
-
kind: kind,
|
|
25
|
-
projectId: projectId ?? '',
|
|
26
|
-
...(suffix != null ? { suffix } : {}),
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
//# sourceMappingURL=jobs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/connect/jobs.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAA;AAEhC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAoB,EAAE,SAAiB,EAAE,MAAe,EAAU,EAAE,CAC1F,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;AAQ5E,sEAAsE;AACtE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAe,EAAE;IACvD,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;IAC7D,gGAAgG;IAChG,mDAAmD;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAErE,OAAO;QACL,IAAI,EAAE,IAAsB;QAC5B,SAAS,EAAE,SAAS,IAAI,EAAE;QAC1B,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAA;AACH,CAAC,CAAA"}
|
package/src/connect/jobs.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { ConnectJobKind } from './consts.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The separator a job id is joined with.
|
|
5
|
-
*
|
|
6
|
-
* `~`, because every other separator in play is already spoken for: a route alias is
|
|
7
|
-
* colon-delimited and so is every run id (`init:<projectId>`, `story:<storyId>`), so a job id
|
|
8
|
-
* built with one could not be split back apart.
|
|
9
|
-
*/
|
|
10
|
-
export const JOB_SEPARATOR = '~'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A job's id: its kind, the project card it belongs to, and the subject it is about.
|
|
14
|
-
*
|
|
15
|
-
* The suffix is a CARD id for a story job and a run id for a pipeline job — never a story code.
|
|
16
|
-
* Declared here rather than by whoever answers the job, because the SDK composes the id it then
|
|
17
|
-
* polls for: two spellings of one id is a job nobody can find.
|
|
18
|
-
*/
|
|
19
|
-
export const jobIdOf = (kind: ConnectJobKind, projectId: string, suffix?: string): string =>
|
|
20
|
-
[kind, projectId, ...(suffix != null ? [suffix] : [])].join(JOB_SEPARATOR)
|
|
21
|
-
|
|
22
|
-
export interface ParsedJobId {
|
|
23
|
-
kind: ConnectJobKind
|
|
24
|
-
projectId: string
|
|
25
|
-
suffix?: string
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Split a job id back into what {@link jobIdOf} composed it from. */
|
|
29
|
-
export const parseJobId = (jobId: string): ParsedJobId => {
|
|
30
|
-
const [kind, projectId, ...rest] = jobId.split(JOB_SEPARATOR)
|
|
31
|
-
// A suffix may carry the separator back if one ever ends up in a card or run id, so the tail is
|
|
32
|
-
// rejoined rather than taken as its first segment.
|
|
33
|
-
const suffix = rest.length > 0 ? rest.join(JOB_SEPARATOR) : undefined
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
kind: kind as ConnectJobKind,
|
|
37
|
-
projectId: projectId ?? '',
|
|
38
|
-
...(suffix != null ? { suffix } : {}),
|
|
39
|
-
}
|
|
40
|
-
}
|