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
7 changes: 7 additions & 0 deletions .changeset/graph-navigation-retrieval.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@inkcre/core': minor
'@inkcre/ext-mail': minor
'@inkcre/ext-twitter': minor
---

Add peer-local graph-navigation retrieval and the required Resolver preview presentation contract.
9 changes: 0 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,6 @@ jobs:
--core-package packages/core/package.json
--artifact-directory extensions/twitter/dist/client-web

- name: Upload unit-test evidence on failure
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: workspace-failure-evidence
path: test-results/vitest
if-no-files-found: ignore
retention-days: 7

toolchain-shadow:
name: Type-aware and TypeScript 7 shadow
runs-on: ubuntu-latest
Expand Down
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Reason in English. Communicate with humans in Chinese.

- Run `svc status . --json`, then use `svc lookup --keyword` and `svc lookup --path` only for guidance required by the current pressure.
- Read the active Task Packet, relevant durable owner, and nearest local `AGENTS.md` before editing.
- Resolve one semantic owner before adding durable material. Prefer code, types, tests, configuration, and CI for mechanically enforceable truth.
- Resolve one semantic owner before adding durable material. Prefer code, types, configuration, and CI for mechanically enforceable truth.
- Before a reference-sensitive, logic-altering, or non-obviously-local durable mutation, state the target, objective `From -> To`, operation, blast radius, invariants, verification, and uncertainty.
- Search before creating a type, utility, document, or abstraction.
- Keep Task Packets compact and disposable. Add supporting entries only when a distinct owner and coordination pressure exist.
Expand All @@ -31,6 +31,8 @@ Reason in English. Communicate with humans in Chinese.
- Develop: `pnpm dev`, `pnpm dev:all`, or an explicit source lane documented in `docs/40-deployment/development-runtime.md`.
- Required verification: `pnpm check`; required production outputs: `pnpm build`.
- Shadow verification: `pnpm lint:type-aware` and `pnpm type-check:ts7`.
- Follow the organization-wide [Verification and Test Policy](https://github.com/InKCre/.github/blob/main/TESTING.md).
The admitted Playwright E2E suites do not authorize new automation by analogy.
- Follow `.agents/prompts/code-for-human.md` for source changes.
- Require explicit Human authorization before modifying source code and before commit, push, or external publication. Task Packet maintenance is exempt from the source gate.

Expand Down
17 changes: 2 additions & 15 deletions apps/client-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build",
"test": "pnpm --dir ../.. exec vitest --project client-web"
"type-check": "vue-tsc --build"
},
"dependencies": {
"@codemirror/autocomplete": "^6.20.0",
Expand All @@ -19,23 +18,14 @@
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.38.8",
"@inkcre/core": "workspace:*",
"@inkcre/ui-web": "1.2.2",
"@inkcre/ui-web": "1.4.0",
"@module-federation/runtime": "^0.21.4",
"@supabase/postgrest-js": "^2.84.0",
"@vue-flow/background": "^1.3.2",
"@vue-flow/controls": "^1.1.3",
"@vue-flow/core": "^1.48.1",
"@vue-flow/minimap": "^1.5.4",
"@vueuse/core": "^14.0.0",
"d3-force": "^3.0.0",
"dagre": "^0.8.5",
"dayjs": "^1.11.19",
"graphology": "^0.26.0",
"graphology-communities-louvain": "^2.0.2",
"graphology-dag": "^0.4.1",
"graphology-shortest-path": "^2.1.0",
"jose": "^6.1.2",
"ml-matrix": "^6.12.1",
"pinia": "^3.0.3",
"vscode-json-languageservice": "^5.6.4",
"vscode-languageserver-textdocument": "^1.0.12",
Expand All @@ -51,12 +41,9 @@
"@module-federation/enhanced": "^0.22.0",
"@module-federation/vite": "^1.1.0",
"@tsconfig/node22": "^22.0.2",
"@types/d3-force": "^3.0.10",
"@types/dagre": "^0.7.53",
"@types/node": "^22.16.5",
"@vitejs/plugin-vue": "^6.0.1",
"@vitejs/plugin-vue-jsx": "^5.1.2",
"@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.7.0",
"get-port": "^7.1.0",
"npm-run-all2": "^8.0.4",
Expand Down
2 changes: 2 additions & 0 deletions apps/client-web/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import router from './router'
import { createInkRouterAdapter } from './router'
import { INK_ROUTER_KEY } from '@inkcre/ui-web'
import { useRoute } from 'vue-router'
import RecallSearch from './components/recall/RecallSearch.vue'

provide(INK_ROUTER_KEY, createInkRouterAdapter(router, useRoute()))

Expand All @@ -25,6 +26,7 @@ const sidebarExpanded = ref(false)
<router-view />
<AppSidePanel v-model:expanded="sidebarExpanded" />
</div>
<RecallSearch />
</div>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ async function ruminate(): Promise<void> {
</script>

<template>
<InkPopup :open="open" position="right" @update:open="onOpenChange">
<InkPopup :open="open" :scrim="false" position="right" @update:open="onOpenChange">
<section class="block-inspector-popup">
<header class="block-inspector-popup__header">
<h3>{{ t('infoBase.blockInspector.title') }}</h3>
Expand Down
79 changes: 52 additions & 27 deletions apps/client-web/src/components/info-base/BlockNode/BlockNode.scss
Original file line number Diff line number Diff line change
@@ -1,52 +1,77 @@
// Hide default Vue Flow handles - they are only used for edge routing
.block-node__handle {
opacity: 0;
width: 8px;
height: 8px;
width: 6px;
height: 6px;
pointer-events: none;
}

.block-node {
min-width: 180px;
max-width: 360px;
overflow: hidden;
cursor: pointer;
color: sys-var(color, text, base);
background: sys-var(color, surface, base);
border: 1px solid sys-var(color, border, subtle);
border-radius: sys-var(radius, none);
padding: sys-var(space, md) sys-var(space, md);
min-width: 120px;
max-width: 200px;
max-height: 150px;
overflow: hidden;
cursor: pointer;
transition: all 0.2s ease;
@include apply-elevation(sm);
transition:
border-color 140ms ease,
opacity 140ms ease,
filter 140ms ease;

header {
display: flex;
align-items: center;
justify-content: space-between;
gap: sys-var(space, sm);
min-height: 32px;
padding: sys-var(space, xs) sys-var(space, sm);
border-bottom: 1px solid sys-var(color, border, subtle);
}

&:hover {
border-color: sys-var(color, border, primary);
transform: translateY(-1px);
@include apply-elevation(md);
border-color: sys-var(color, border, base);
}

&--selected {
&--focal {
border-color: sys-var(color, border, primary);
@include apply-elevation(md);
box-shadow: 0 0 0 1px sys-var(color, border, primary);
}

&__content {
display: flex;
flex-direction: column;
gap: 6px;
&--muted {
opacity: 0.34;
filter: saturate(0.65);
}

&__resolver {
@include apply-font(label-sm, true);
text-transform: uppercase;
color: sys-var(color, text, subtle);
letter-spacing: 0.5px;
}

&__preview {
@include apply-font(label-lg);
color: sys-var(color, text, base);
word-break: break-word;
overflow: hidden;
&__inspect {
opacity: 0;
transition: opacity 120ms ease;
}

&:hover &__inspect,
&__inspect:focus-within {
opacity: 1;
}

&__content {
min-height: 48px;
padding: sys-var(space, sm) sys-var(space, md) sys-var(space, md);
}

&__preview-error {
color: sys-var(color, text, subtle);
@include apply-font(label-sm);
}
}

@media (prefers-reduced-motion: reduce) {
.block-node,
.block-node__inspect {
transition: none;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { NodeProps } from '@vue-flow/core'
import type { BlockNodeData } from '@inkcre/core'
import type { BlockNodeData } from '@/views/info-base/graph/graph-model'

export type BlockNodeProps = NodeProps<BlockNodeData>

export const blockNodeEmits = {
select: (_blockId: number) => true,
focus: (_blockId: number) => true,
inspect: (_blockId: number) => true,
} as const
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
<script setup lang="ts">
import { computed } from 'vue'
import { Handle, Position } from '@vue-flow/core'
import { InkButton, InkLoading } from '@inkcre/ui-web'
import PreviewRenderer from '@/components/info-base/PreviewRenderer/PreviewRenderer.vue'
import type { BlockNodeProps } from './BlockNode'
import { blockNodeEmits } from './BlockNode'

const props = defineProps<BlockNodeProps>()
const emit = defineEmits(blockNodeEmits)
const resolverName = computed(() => props.data.resolver?.constructor.name ?? 'Block')

const onNodeClick = () => {
emit('select', props.data.block.id)
emit('focus', props.data.block.id)
}

const inspect = () => emit('inspect', props.data.block.id)
</script>

<template>
Expand All @@ -18,10 +24,35 @@ const onNodeClick = () => {
<Handle type="source" :position="Position.Bottom" class="block-node__handle" />
<Handle type="source" :position="Position.Right" class="block-node__handle" />

<div class="block-node" :class="{ 'block-node--selected': selected }" @click="onNodeClick">
<div
class="block-node"
:class="{
'block-node--focal': data.focal,
'block-node--muted': data.muted,
}"
@click="onNodeClick"
>
<header>
<span class="block-node__resolver">{{ resolverName }}</span>
<span class="nodrag nopan block-node__inspect" @pointerdown.stop @click.stop>
<InkButton
icon="i-mdi-information-outline"
theme="subtle"
type="square"
size="sm"
aria-label="Inspect Block"
@click="inspect"
/>
</span>
</header>
<div class="block-node__content">
<span class="block-node__resolver">{{ props.data.block.resolver }}</span>
<span class="block-node__preview">{{ props.data.preview }}</span>
<InkLoading v-if="data.previewStatus === 'loading'" />
<PreviewRenderer
v-else-if="data.previewStatus === 'success' && data.resolver"
:resolver="data.resolver"
:solved-content="data.solvedContent"
/>
<span v-else class="block-node__preview-error">Preview unavailable</span>
</div>
</div>
</template>
Expand Down

This file was deleted.

This file was deleted.

Loading
Loading