-
Notifications
You must be signed in to change notification settings - Fork 5
✨ Import the reference client stack (client core, hub-shim, UI, harnesses, demo) #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ibolton336
wants to merge
4
commits into
konveyor:main
Choose a base branch
from
ibolton336:clients-reference-stack
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
e403b3b
Import the reference client stack under clients/
ibolton336 cb37ca2
Align client stack with merged #33/#34
ibolton336 130a052
Address CodeRabbit review findings
ibolton336 e05dd42
clients: surface AgentPlaybookRuns — list view, stage ladder, run badges
ibolton336 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| kind: feature | ||
|
|
||
| description: > | ||
| Import the reference client stack under clients/ — isomorphic client | ||
| core, hub-shim (the proposed Hub passthrough proxy surface), PatternFly | ||
| browser UI, mock and goose agent harnesses, in-cluster deploy manifests, | ||
| and the end-to-end demo — plus ADRs 0004 (verified client contract and | ||
| transports) and 0005 (platform-resolved params). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| node_modules/ | ||
| dist/ | ||
|
|
||
| .claude/settings.local.json | ||
| .DS_Store |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| # clients/ — reference client stack | ||
|
|
||
| Working client-side implementation of this repository's AgentRun/ACP | ||
| contract, developed against the live controller on minikube and verified | ||
| end-to-end with both a deterministic mock agent and a real goose+Bedrock | ||
| agent. It exists so the Hub, UI, and base-image streams can build against | ||
| running code instead of a whiteboard: | ||
|
|
||
| - the **hub-shim** HTTP surface is the proposed contract for the Hub | ||
| passthrough proxy (stream 2, issue #21) — see ADR 0004 | ||
| - the **UI** and **client core** are the reference for the tackle2-ui | ||
| client layer (stream 3, issues #22–#24) | ||
| - the **goose harness** is a working reference for the interactive | ||
| (ACP-serving) side of the base image (stream 4, issues #25/#26). The | ||
| batch-mode harness landed separately as the repo-root `harness/` Go | ||
| module + `images/agent-base-goose-java` (#33); both consume the same | ||
| `KONVEYOR_MODEL_*` env contract. | ||
|
|
||
| ## Layout | ||
|
|
||
| | Path | What | | ||
| |------|------| | ||
| | `packages/agentic-client/` | Isomorphic (browser + node) client core: CRD contract types + helpers, `AcpSession` over WebSocket (JSON-RPC 2.0), hub-shim HTTP transport. Zero runtime dependencies. | | ||
| | `packages/agentrun-client/` | Node-side client: create/watch AgentRuns against the apiserver, resolve the ACP endpoint (`status.sandboxName` → pod, `status.secretKeyRef` → key), port-forward tunnel. Shaped for konveyor/editor-extensions. | | ||
| | `packages/hub-shim/` | Localhost gateway serving the SHIM HTTP API v1 (REST + WS `/acp` proxy with server-side `X-Secret-Key` injection). Stands in for the future Hub passthrough proxy. | | ||
| | `ui/` | Browser SPA (PatternFly): run list, create form with platform-resolved params (ADR 0005), streaming chat with permission (HITL) round-trips. | | ||
| | `harness-mock/` | Deterministic ACP agent (no LLM): real protocol via the ACP SDK's server side, scripted behaviors (`TEST_PERMISSION`, `TEST_CANCEL`, `TEST_DROP`). Test fixture and demo agent. | | ||
| | `harness-goose/` | Real agent base: goose `serve` on `:4000` behind an entrypoint that adapts the controller's `KONVEYOR_*` env contract (clones the `repository` param, maps model env, writes prompt hints). | | ||
| | `deploy/` | In-cluster deployment of gateway + UI (interim, pre-Hub). | | ||
| | `manifests/` | Sample Agent/LLMProvider CRs: `samples.yaml` (mock) and `goose-bedrock.yaml` (real goose on AWS Bedrock). | | ||
| | `hack/` | `demo-up.sh` / `demo-check.sh` / `demo-down.sh` — converge the cluster, smoke the full ACP round-trip, tear down. | | ||
| | `docs/DEMO.md` | Narrated end-to-end demo runbook (browser + IDE + real agent). | | ||
|
|
||
| Architecture write-ups live with the repo's ADRs: `docs/adr/0004` | ||
| (verified client contract and layered transports) and `docs/adr/0005` | ||
| (platform-resolved params). | ||
|
|
||
| ## Quickstart | ||
|
|
||
| Prereqs: minikube running, Agent Sandbox v0.5.0 installed, the controller | ||
| deployed from the repo root (`make docker-build deploy IMG=agentic-controller:dev`), | ||
| Node ≥ 22.9. | ||
|
|
||
| ```sh | ||
| cd clients | ||
| hack/demo-up.sh # converge cluster + start shim & UI, prints URLs | ||
| hack/demo-check.sh # smoke: full ACP round-trip on a throwaway mock run | ||
| hack/demo-down.sh # stop local processes; cluster untouched | ||
| ``` | ||
|
|
||
| Then follow `docs/DEMO.md`. | ||
|
|
||
| ## Status: interim by design | ||
|
|
||
| The controller and CRDs are the real ones from this repository. The rest | ||
| is scaffolding with a named replacement: | ||
|
|
||
| - `hub-shim` → the real Hub passthrough proxy (its route table is the | ||
| handover spec) | ||
| - `ui` → absorbed into tackle2-ui | ||
| - `harness-goose` → the stream-4 base image (the batch side already exists: | ||
| repo-root `harness/` + `images/agent-base-goose-java`, #33; this one | ||
| covers the interactive `goose serve` / ACP mode until they converge) | ||
| - `harness-mock` → stays, as a deterministic test fixture | ||
|
|
||
| Every piece encodes contract facts verified against the live controller | ||
| (pod name == `status.sandboxName`, ACP Secret data key `secret-key`, | ||
| headless portless Service, whole-spec immutability) — see ADR 0004 for | ||
| the full list and rationale. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| # In-cluster deployment (interim, pre-Hub) | ||
|
|
||
| Runs the browser UI + gateway **on the cluster** — no laptop processes. | ||
| Both components are interim by design: the gateway seat is replaced by the | ||
| real Konveyor Hub passthrough proxy later, and the UI page is absorbed | ||
| into tackle2-ui (see `docs/adr/0004-client-contract-and-transports.md`). | ||
|
|
||
| ``` | ||
| browser ── ingress/route (TLS + SSO) ── agentic-ui (nginx, static SPA) | ||
| │ /api + WS, same-origin | ||
| agentic-gateway (SA + RBAC) | ||
| │ CRs via k8s API · pod :4000 via service DNS | ||
| agentic-controller / Agent Sandbox / sandbox pods | ||
| ``` | ||
|
|
||
| Differences from laptop mode: the gateway **direct-dials** | ||
| `<sandboxName>.<ns>.svc:4000` (no port-forwarding; auto-detected | ||
| in-cluster, `ACP_DIAL` overrides) and authenticates as a namespace-scoped | ||
| ServiceAccount instead of your kubeconfig. | ||
|
|
||
| ## Build the images (context = repo root) | ||
|
|
||
| ```sh | ||
| # local cluster (minikube): | ||
| minikube image build -t agentic-gateway:dev -f deploy/gateway/Dockerfile . | ||
| minikube image build -t agentic-ui:dev -f deploy/ui/Dockerfile . | ||
|
|
||
| # real cluster: docker build + push, then kustomize-patch the image refs. | ||
| ``` | ||
|
|
||
| ## Deploy | ||
|
|
||
| ```sh | ||
| kubectl apply -k deploy/manifests | ||
| kubectl -n konveyor-agents rollout status deploy/agentic-gateway deploy/agentic-ui | ||
| ``` | ||
|
|
||
| Prereqs already on the cluster: the agentic-controller (deployed from | ||
| the repo root: `make deploy`), Agent Sandbox, and the sample | ||
| Agents/LLMProviders (`hack/demo-up.sh` converges all of that). | ||
|
|
||
| ## Access | ||
|
|
||
| With an ingress (see `ingress.example.yaml`) — or without one: | ||
|
|
||
| ```sh | ||
| kubectl -n konveyor-agents port-forward svc/agentic-ui 8081:80 | ||
| open http://localhost:8081 | ||
| ``` | ||
|
|
||
| Everything (REST + WebSocket chat) flows through that single origin. | ||
|
|
||
| ## Verify | ||
|
|
||
| The browser-constraint smoke works through the deployed stack end to end | ||
| (nginx → gateway → controller → sandbox ACP): | ||
|
|
||
| ```sh | ||
| cd packages/hub-shim | ||
| SHIM_URL=http://localhost:8081 npx tsx dev/browser-smoke.ts | ||
| ``` | ||
|
|
||
| ## Teardown | ||
|
|
||
| ```sh | ||
| kubectl delete -k deploy/manifests | ||
| ``` | ||
|
|
||
| ## Auth (deliberate gap) | ||
|
|
||
| The gateway has no auth of its own — protect it at the ingress (oauth2-proxy, | ||
| or an OpenShift Route with an oauth-proxy sidecar). Per-user identity and | ||
| RBAC on runs is precisely the value the real Hub proxy adds; bolting a full | ||
| auth stack onto this interim component would be building Hub twice. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # agentic-gateway: the hub-shim packaged for in-cluster use. | ||
| # Build context is the REPO ROOT (the shim imports ../agentrun-client/src): | ||
| # docker build -t agentic-gateway:dev -f deploy/gateway/Dockerfile . | ||
| # minikube image build -t agentic-gateway:dev -f deploy/gateway/Dockerfile . | ||
| FROM node:22-slim | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| # Install each package's deps (tsx runs the TypeScript sources directly, | ||
| # matching the repo's dev style; dev deps are required for that). | ||
| COPY packages/agentrun-client/package*.json packages/agentrun-client/ | ||
| COPY packages/hub-shim/package*.json packages/hub-shim/ | ||
| RUN cd packages/agentrun-client && npm ci --no-audit --no-fund \ | ||
| && cd ../hub-shim && npm ci --no-audit --no-fund | ||
|
|
||
| COPY packages/agentrun-client packages/agentrun-client | ||
| COPY packages/hub-shim packages/hub-shim | ||
|
|
||
| # In-cluster defaults: bind all interfaces; ACP dial mode auto-detects | ||
| # "direct" from the serviceaccount env (no port-forwarding in-cluster). | ||
| ENV HOST=0.0.0.0 \ | ||
| PORT=7080 \ | ||
| NAMESPACE=konveyor-agents | ||
|
|
||
| USER node | ||
| EXPOSE 7080 | ||
| WORKDIR /app/packages/hub-shim | ||
| CMD ["npx", "tsx", "src/server.ts"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # agentic-gateway: in-cluster stand-in for the future Hub passthrough proxy. | ||
| # Namespace-scoped RBAC — exactly the surface the SHIM API v1 needs. | ||
| --- | ||
| apiVersion: v1 | ||
| kind: ServiceAccount | ||
| metadata: | ||
| name: agentic-gateway | ||
| namespace: konveyor-agents | ||
| --- | ||
| apiVersion: rbac.authorization.k8s.io/v1 | ||
| kind: Role | ||
| metadata: | ||
| name: agentic-gateway | ||
| namespace: konveyor-agents | ||
| rules: | ||
| - apiGroups: ["konveyor.io"] | ||
| resources: ["agentruns"] | ||
| verbs: ["get", "list", "watch", "create", "delete"] | ||
| - apiGroups: ["konveyor.io"] | ||
| resources: ["agents", "llmproviders"] | ||
| verbs: ["get", "list"] | ||
| - apiGroups: [""] | ||
| resources: ["secrets"] | ||
| verbs: ["get"] | ||
| - apiGroups: [""] | ||
| resources: ["pods"] | ||
| verbs: ["get", "list"] | ||
| --- | ||
| apiVersion: rbac.authorization.k8s.io/v1 | ||
| kind: RoleBinding | ||
| metadata: | ||
| name: agentic-gateway | ||
| namespace: konveyor-agents | ||
| roleRef: | ||
| apiGroup: rbac.authorization.k8s.io | ||
| kind: Role | ||
| name: agentic-gateway | ||
| subjects: | ||
| - kind: ServiceAccount | ||
| name: agentic-gateway | ||
| namespace: konveyor-agents | ||
| --- | ||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: agentic-gateway | ||
| namespace: konveyor-agents | ||
| labels: | ||
| app.kubernetes.io/name: agentic-gateway | ||
| spec: | ||
| replicas: 1 | ||
| selector: | ||
| matchLabels: | ||
| app.kubernetes.io/name: agentic-gateway | ||
| template: | ||
| metadata: | ||
| labels: | ||
| app.kubernetes.io/name: agentic-gateway | ||
| spec: | ||
| serviceAccountName: agentic-gateway | ||
| containers: | ||
| - name: gateway | ||
| image: agentic-gateway:dev | ||
| imagePullPolicy: IfNotPresent | ||
| ports: | ||
| - containerPort: 7080 | ||
| name: http | ||
| env: | ||
| - name: NAMESPACE | ||
| valueFrom: | ||
| fieldRef: | ||
| fieldPath: metadata.namespace | ||
| readinessProbe: | ||
| httpGet: | ||
| path: /healthz | ||
| port: http | ||
| initialDelaySeconds: 2 | ||
| periodSeconds: 5 | ||
| resources: | ||
| requests: | ||
| cpu: 50m | ||
| memory: 128Mi | ||
| limits: | ||
| memory: 512Mi | ||
| --- | ||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| name: agentic-gateway | ||
| namespace: konveyor-agents | ||
| labels: | ||
| app.kubernetes.io/name: agentic-gateway | ||
| spec: | ||
| selector: | ||
| app.kubernetes.io/name: agentic-gateway | ||
| ports: | ||
| - name: http | ||
| port: 7080 | ||
| targetPort: http | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # EXAMPLE — not applied by the kustomization. Adapt host/class/TLS to your | ||
| # environment and put SSO in front (oauth2-proxy annotations, or on | ||
| # OpenShift use a Route with an oauth-proxy sidecar instead). | ||
| # | ||
| # Only the UI needs exposing: nginx inside agentic-ui proxies /api (HTTP + | ||
| # WebSocket) to the gateway Service, so one host serves everything | ||
| # same-origin. | ||
| apiVersion: networking.k8s.io/v1 | ||
| kind: Ingress | ||
| metadata: | ||
| name: agentic-ui | ||
| namespace: konveyor-agents | ||
| annotations: | ||
| # WebSocket sessions are long-lived: | ||
| nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" | ||
| nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" | ||
| spec: | ||
| ingressClassName: nginx | ||
| rules: | ||
| - host: agentic.example.com | ||
| http: | ||
| paths: | ||
| - path: / | ||
| pathType: Prefix | ||
| backend: | ||
| service: | ||
| name: agentic-ui | ||
| port: | ||
| number: 80 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| apiVersion: kustomize.config.k8s.io/v1beta1 | ||
| kind: Kustomization | ||
|
|
||
| # In-cluster deployment of the interim agentic UI + gateway. | ||
| # Prereqs: the agentic-controller and Agent Sandbox are already installed | ||
| # (see manifests/controller/install.yaml), and the agentic-gateway:dev / | ||
| # agentic-ui:dev images are loadable by the cluster (minikube image build, | ||
| # or retag + push to a registry and patch the images below). | ||
| resources: | ||
| - gateway.yaml | ||
| - ui.yaml | ||
|
|
||
| # Ingress is environment-specific — see ingress.example.yaml. Put TLS and | ||
| # SSO (oauth2-proxy / OpenShift Route auth) in front: the gateway itself | ||
| # is deliberately auth-less, exactly like the future Hub proxy seat it | ||
| # stands in for is not. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Missing
securityContexthardening across both deploy Deployments. Neitheragentic-gatewaynoragentic-uisets a pod/containersecurityContext, so both run with the default (root-capable, writable-rootfs, privilege-escalation-allowed) context. Same fix pattern applies to both; the gateway is higher priority since it also holds RBAC to readsecretsandpods.clients/deploy/manifests/gateway.yaml#L59-L84: addsecurityContext.runAsNonRoot: true+seccompProfile.type: RuntimeDefaultat pod level, andallowPrivilegeEscalation: false,readOnlyRootFilesystem: true,capabilities.drop: ["ALL"]on thegatewaycontainer.clients/deploy/manifests/ui.yaml#L21-L40: add the same pod-levelsecurityContext, andallowPrivilegeEscalation: false+capabilities.drop: ["ALL"]on theuicontainer (if addingreadOnlyRootFilesystem: true, mountemptyDirvolumes for nginx's writable dirs, e.g./var/cache/nginx,/tmp,/var/run).📍 Affects 2 files
clients/deploy/manifests/gateway.yaml#L59-L84(this comment)clients/deploy/manifests/ui.yaml#L21-L40🤖 Prompt for AI Agents
Source: Linters/SAST tools