Merge branch 'jb/release/vere' into jb/restage/chop-fast

This commit is contained in:
Joe Bryan 2022-11-18 10:41:23 -05:00
commit f78e6a5447
153 changed files with 42292 additions and 49622 deletions

View File

@ -34,7 +34,7 @@ jobs:
call-vere: call-vere:
uses: ./.github/workflows/vere.yml uses: ./.github/workflows/vere.yml
with: with:
pace: 'often' pace: 'edge' # XX s/b once?
upload: >- upload: >-
${{ ${{
(github.ref_name == 'next/vere' && github.ref_type == 'branch') (github.ref_name == 'next/vere' && github.ref_type == 'branch')

View File

@ -12,11 +12,13 @@ on:
pace: pace:
description: 'release pace' description: 'release pace'
type: string type: string
default: 'often' default: 'edge'
required: false required: false
secrets: secrets:
CACHIX_AUTH_TOKEN: CACHIX_AUTH_TOKEN:
required: false required: false
GCP_CREDENTIALS:
required: false
GCS_SERVICE_ACCOUNT_KEY: GCS_SERVICE_ACCOUNT_KEY:
required: false required: false
GCS_PROJECT: GCS_PROJECT:
@ -33,7 +35,7 @@ on:
description: 'release pace' description: 'release pace'
type: choice type: choice
options: options:
- often - edge
- soon - soon
- live - live
@ -48,8 +50,9 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- { os: ubuntu-latest } - { os: ubuntu-latest, type: linux }
- { os: macos-latest } - { os: macos-latest, type: macos }
- { os: buildjet-4vcpu-ubuntu-2204-arm, type: linux }
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -64,7 +67,7 @@ jobs:
with: with:
extra_nix_config: | extra_nix_config: |
system-features = nixos-test benchmark big-parallel kvm system-features = nixos-test benchmark big-parallel kvm
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.type == 'linux' }}
- uses: cachix/install-nix-action@v16 - uses: cachix/install-nix-action@v16
if: ${{ matrix.os != 'ubuntu-latest' }} if: ${{ matrix.os != 'ubuntu-latest' }}
@ -73,6 +76,11 @@ jobs:
name: ares name: ares
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
# run unit tests early on linux (x-compilation will skip them)
- name: build dynamic binary (and run tests)
if: ${{ matrix.type == 'linux' }}
run: nix-build -A urbit
- name: build static binary - name: build static binary
run: | run: |
nix-build -A urbit \ nix-build -A urbit \
@ -84,7 +92,7 @@ jobs:
cat ./urbit-derivation cat ./urbit-derivation
- name: confirm binary is mostly static - name: confirm binary is mostly static
if: matrix.os == 'macos-latest' if: matrix.type == 'macos'
run: | run: |
bin="${{ env.urbit_static }}/bin/urbit" bin="${{ env.urbit_static }}/bin/urbit"
@ -117,19 +125,20 @@ jobs:
echo -n "$version" > ./version-string echo -n "$version" > ./version-string
- name: upload version string artifact - name: upload version string artifact
if: matrix.os == 'ubuntu-latest' if: matrix.type == 'linux'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: version-string name: version-string
path: version-string path: version-string
- uses: google-github-actions/setup-gcloud@v0.2.0 - uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GCP_CREDENTIALS }}
- uses: google-github-actions/setup-gcloud@v1
if: inputs.upload if: inputs.upload
with: with:
version: '290.0.1'
service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}
project_id: ${{ secrets.GCS_PROJECT }} project_id: ${{ secrets.GCS_PROJECT }}
export_default_credentials: true
- name: upload binary to bootstrap.urbit.org - name: upload binary to bootstrap.urbit.org
if: inputs.upload if: inputs.upload
@ -174,6 +183,7 @@ jobs:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
- run: mingw32-make build/urbit - run: mingw32-make build/urbit
- run: mingw32-make test
- run: > - run: >
build/urbit -l -d -B ../../bin/solid.pill -F bus && build/urbit -l -d -B ../../bin/solid.pill -F bus &&
curl -f --data '{"source":{"dojo":"+hood/exit"},"sink":{"app":"hood"}}' curl -f --data '{"source":{"dojo":"+hood/exit"},"sink":{"app":"hood"}}'
@ -232,9 +242,7 @@ jobs:
after: after:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [urbit, mingw] needs: [urbit, mingw]
# XX disabled due to missing storage.objects.delete access if: inputs.upload
if: false
# if: inputs.upload
steps: steps:
- uses: google-github-actions/setup-gcloud@v0.2.0 - uses: google-github-actions/setup-gcloud@v0.2.0
with: with:

View File

@ -27,12 +27,12 @@ identity, use [Bridge][brid].
## Install ## Install
To install and run Urbit, please follow the instructions at To install and run Urbit, please follow the instructions at
[urbit.org/using/install][start]. You'll be on the live network in a [urbit.org/install][start]. You'll be on the live network in a
few minutes. few minutes.
If you're interested in Urbit development, keep reading. If you're interested in Urbit development, keep reading.
[start]: https://urbit.org/using/install/ [start]: https://urbit.org/install/
## Development ## Development

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:c45166ff0f8ab8dc1552bcef519c77c0afa6ca52f8ed1ba31ed632012667d619 oid sha256:d737f88463f683173b5f6cbf41fc38705d4d3d67263c675d7e99841cd8485d81
size 8674763 size 6026086

View File

@ -56,6 +56,9 @@ let
crossSystem = crossSystem =
if system == "x86_64-linux" && crossSystem == null && enableStatic then if system == "x86_64-linux" && crossSystem == null && enableStatic then
"x86_64-unknown-linux-musl" "x86_64-unknown-linux-musl"
else
if system == "aarch64-linux" && crossSystem == null && enableStatic then
"aarch64-unknown-linux-musl"
else else
crossSystem; crossSystem;
}; };

View File

@ -25,6 +25,7 @@ let
(import ./overlays/native.nix) (import ./overlays/native.nix)
# Specific overrides guarded by the host platform. # Specific overrides guarded by the host platform.
(import ./overlays/musl.nix) (import ./overlays/musl.nix)
(import ./overlays/arm.nix)
]; ];
}; };

View File

@ -3,10 +3,11 @@ final: prev:
let let
isAarch64 = prev.stdenv.hostPlatform.isAarch64; isAarch64 = prev.stdenv.hostPlatform.isAarch64;
isDarwin = prev.stdenv.isDarwin;
in prev.lib.optionalAttrs isAarch64 { in prev.lib.optionalAttrs (isAarch64 && !isDarwin) {
libsigsegv = prev.libsigsegv.overrideAttrs (attrs: { libsigsegv = prev.libsigsegv.overrideAttrs (attrs: {
preConfigure = (old.preConfigure or "") + '' preConfigure = (prev.preConfigure or "") + ''
sed -i 's/^CFG_FAULT=$/CFG_FAULT=fault-linux-arm.h/' configure sed -i 's/^CFG_FAULT=$/CFG_FAULT=fault-linux-arm.h/' configure
''; '';
}); });

18
nix/sources-openssl.json Normal file
View File

@ -0,0 +1,18 @@
{
"openssl": {
"branch": "1_1_1n",
"homepage": "https://www.openssl.org/",
"pmnsh": {
"include": "build/include",
"lib": "build",
"prepare": "./config --prefix=`mkdir -p build && readlink -f ./build` --libdir=. no-shared no-tests",
"make": "install_dev"
},
"owner": "openssl",
"repo": "openssl",
"rev": "OpenSSL_1_1_1n",
"type": "tarball",
"url": "https://github.com/openssl/openssl/archive/refs/tags/OpenSSL_1_1_1n.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/refs/tags/<rev>.tar.gz"
}
}

View File

@ -4,6 +4,11 @@
"description": "A command line tool and library for transferring data with URL syntax", "description": "A command line tool and library for transferring data with URL syntax",
"homepage": "http://curl.se/", "homepage": "http://curl.se/",
"pmnsh": { "pmnsh": {
"compat": {
"openbsd": {
"prepare": "autoreconf -vfi && ./configure --disable-shared --disable-ldap --disable-rtsp --without-brotli --without-libidn2 --without-libpsl --without-nghttp2 --with-openssl=`readlink -f ../openssl/build`"
}
},
"include": "include", "include": "include",
"lib": "lib/.libs", "lib": "lib/.libs",
"prepare": "autoreconf -vfi && ./configure --disable-shared --disable-ldap --disable-rtsp --without-brotli --without-libidn2 --without-libpsl --without-nghttp2 --with-openssl", "prepare": "autoreconf -vfi && ./configure --disable-shared --disable-ldap --disable-rtsp --without-brotli --without-libidn2 --without-libpsl --without-nghttp2 --with-openssl",
@ -76,6 +81,13 @@
}, },
"urcrypt": { "urcrypt": {
"pmnsh": { "pmnsh": {
"compat": {
"openbsd": {
"make": "install prefix=`readlink -f .` exec_prefix=`readlink -f .`",
"include": "include",
"lib": "lib"
}
},
"prepare": "./autogen.sh && ./configure --disable-shared PKG_CONFIG_PATH=../secp256k1 CFLAGS=\"-I../secp256k1/include -I../libaes_siv\" LDFLAGS=-L../libaes_siv", "prepare": "./autogen.sh && ./configure --disable-shared PKG_CONFIG_PATH=../secp256k1 CFLAGS=\"-I../secp256k1/include -I../libaes_siv\" LDFLAGS=-L../libaes_siv",
"make": "install" "make": "install"
} }

View File

@ -8,6 +8,9 @@
"compat": { "compat": {
"mingw": { "mingw": {
"prepare": "cmake -G\"MSYS Makefiles\" -DCMAKE_INSTALL_PREFIX=. ." "prepare": "cmake -G\"MSYS Makefiles\" -DCMAKE_INSTALL_PREFIX=. ."
},
"openbsd": {
"prepare": "cmake -DOPENSSL_ROOT_DIR=`readlink -f ../openssl/build` ."
} }
}, },
"include": "include", "include": "include",
@ -35,6 +38,10 @@
"mingw": { "mingw": {
"make": "aes_siv_static", "make": "aes_siv_static",
"prepare": "cmake -G\"MSYS Makefiles\" -DDISABLE_DOCS:BOOL=ON ." "prepare": "cmake -G\"MSYS Makefiles\" -DDISABLE_DOCS:BOOL=ON ."
},
"openbsd": {
"make": "aes_siv_static",
"prepare": "cmake -DDISABLE_DOCS:BOOL=ON -DOPENSSL_ROOT_DIR=`readlink -f ../openssl/build` ."
} }
} }
}, },
@ -98,6 +105,10 @@
"mingw": { "mingw": {
"lib": "build/Win64-MinGW-w64", "lib": "build/Win64-MinGW-w64",
"make": "-C build/Win64-MinGW-w64 libsoftfloat3.a" "make": "-C build/Win64-MinGW-w64 libsoftfloat3.a"
},
"openbsd": {
"lib": "build/template-FAST_INT64",
"make": "-C build/template-FAST_INT64 libsoftfloat3.a"
} }
}, },
"include": "source/include" "include": "source/include"

View File

@ -6,22 +6,16 @@
default-agent, default-agent,
verb, verb,
dbug dbug
:: Generally don't update the snapshot until we have clay tombstoning.
::
/* snap %azimuth-snapshot /app/azimuth/version-0/azimuth-snapshot
:: To update, run from dojo: :: To update, run from dojo:
:: -azimuth-snap-state %default 'version-0' :: -azimuth-snap-state %default 'version-0'
:: ::
:: To recreate from a full list of logs (at /app/azimuth/logs/eth-logs): :: To recreate from a full list of logs (at /app/azimuth/logs/eth-logs):
:: -azimuth-snap-logs %default 'version-0' :: -azimuth-snap-logs %default 'version-0'
:: ::
=/ snap=snap-state snap
=/ last-snap=@ number.id.snap
::
=, jael =, jael
|% |%
+$ app-state +$ app-state
$: %6 $: %7
url=@ta url=@ta
=net =net
refresh=_~m5 refresh=_~m5
@ -30,10 +24,14 @@
own=owners own=owners
spo=sponsors spo=sponsors
logs=(list =event-log:rpc:ethereum) logs=(list =event-log:rpc:ethereum)
sap=snap-state
== ==
:: ::
+$ poke-data +$ poke-data
$% :: %listen $% :: %load: load snapshot
::
[%load snap=snap-state]
:: %listen
:: ::
[%listen whos=(list ship) =source:jael] [%listen whos=(list ship) =source:jael]
:: %watch: configure node url and network :: %watch: configure node url and network
@ -75,14 +73,18 @@
== ==
:: ::
++ init-timer ++ init-timer
|= =bowl:gall |= at=@da
^- card ^- card
[%pass /init %arvo %b %wait now.bowl] [%pass /init %arvo %b %wait at]
:: ::
++ start-log-retrieval ++ start-log-retrieval
|= [=ship args=vase] |= [=ship args=vase]
^- card ^- card
[%pass /wa %agent [ship %eth-watcher] %poke %eth-watcher-poke args] [%pass /wa %agent [ship %eth-watcher] %poke %eth-watcher-poke args]
::
++ start-azimuth-load
^- card
[%pass /al %arvo %k %fard %base %azimuth-load %noun !>(~)]
-- --
:: ::
=< =<
@ -92,22 +94,10 @@
def ~(. (default-agent this %|) bowl) def ~(. (default-agent this %|) bowl)
:: ::
++ on-init ++ on-init
^- (quip card _this)
=/ points=@ud ~(wyt by points.nas.snap)
%- %- slog
[leaf+"ship: loading azimuth snapshot ({<points>} points)"]~
::
=: net.state %default
nas.state nas.snap
own.state owners.snap
spo.state sponsors.snap
url.state 'http://eth-mainnet.urbit.org:8545'
==
:_ this :_ this
?: .^(? %j /(scot %p our.bowl)/fake/(scot %da now.bowl)) ?: .^(? %j /(scot %p our.bowl)/fake/(scot %da now.bowl))
~ ~
~[(nuke-azimuth-tracker bowl) (init-timer bowl)] ~[(init-timer now.bowl)]
::
++ on-save !>(state) ++ on-save !>(state)
++ on-load ++ on-load
|= old=vase |= old=vase
@ -122,7 +112,7 @@
`old-state `old-state
%- %- slog :_ ~ %- %- slog :_ ~
leaf+"ship: loading snapshot with {<(lent logs.old-state)>} events" leaf+"ship: loading snapshot with {<(lent logs.old-state)>} events"
=. +.state +:(state-5-to-6 old-state) =. +.state +:(state-6-to-7 (state-5-to-6 old-state))
=^ cards state =^ cards state
(%*(run-logs do nas.state *^state:naive) logs.state) (%*(run-logs do nas.state *^state:naive) logs.state)
[(jael-update:do (to-udiffs:do cards)) state] [(jael-update:do (to-udiffs:do cards)) state]
@ -130,12 +120,12 @@
?. ?=(%2 -.old-state) ?. ?=(%2 -.old-state)
`old-state `old-state
~& > '%azimuth: updating to state 3' ~& > '%azimuth: updating to state 3'
=. +.state +:(state-5-to-6 old-state) =. +.state +:(state-6-to-7 (state-5-to-6 old-state))
:: replace naive state and indices with snapshot :: replace naive state and indices with snapshot
:: ::
=: nas.state nas.snap =: nas.state nas.sap.state
own.state owners.snap own.state owners.sap.state
spo.state sponsors.snap spo.state sponsors.sap.state
logs.state ~ logs.state ~
:: TODO: shouldn't be needed but have seen eth-watcher :: TODO: shouldn't be needed but have seen eth-watcher
:: threads use a url='' if this is not used :: threads use a url='' if this is not used
@ -144,8 +134,8 @@
== ==
=/ points=@ud ~(wyt by points.nas.state) =/ points=@ud ~(wyt by points.nas.state)
%- %- slog :_ ~ %- %- slog :_ ~
leaf+"ship: processing azimuth snapshot ({<points>} points)" leaf+"ship: processing azimuth snapshot (~{<points>} points)"
=/ snap-cards=udiffs:point (run-state:do id.snap points.nas.state) =/ snap-cards=udiffs:point (run-state:do id.sap.state points.nas.state)
:_ [%3 url net whos nas own spo logs]:state :_ [%3 url net whos nas own spo logs]:state
%+ weld %+ weld
(jael-update:do snap-cards) (jael-update:do snap-cards)
@ -160,22 +150,30 @@
=^ cards-4 old-state =^ cards-4 old-state
?. ?=(%4 -.old-state) [cards-3 old-state] ?. ?=(%4 -.old-state) [cards-3 old-state]
=^ cards this =^ cards this
%- %*(. on-poke +.state.this +:(state-5-to-6 old-state)) %- %*(. on-poke +.state.this +:(state-6-to-7 (state-5-to-6 old-state)))
[%azimuth-poke !>([%watch [url net]:old-state])] [%azimuth-poke !>([%watch [url net]:old-state])]
~& > '%azimuth: updating to state 5' ~& > '%azimuth: updating to state 5'
[cards [%5 url net whos nas own spo logs]:state.this] [cards [%5 url net whos nas own spo logs]:state.this]
=? old-state ?=(%5 -.old-state) =? old-state ?=(%5 -.old-state)
(state-5-to-6 old-state) (state-5-to-6 old-state)
?> ?=(%6 -.old-state) =? old-state ?=(%6 -.old-state)
(state-6-to-7 old-state)
?> ?=(%7 -.old-state)
[cards-4 this(state old-state)] [cards-4 this(state old-state)]
:: ::
++ app-states $%(state-0 state-1-2-3-4-5 app-state) ++ app-states $%(state-0 state-1-2-3-4-5 state-6 app-state)
::
++ state-5-to-6
|= state-1-2-3-4-5
^- app-state
[%6 url net ~m5 whos nas own spo logs]
:: ::
+$ state-6
$: %6
url=@ta
=net
refresh=_~m5
whos=(set ship)
nas=^state:naive
own=owners
spo=sponsors
logs=(list =event-log:rpc:ethereum)
==
+$ state-1-2-3-4-5 +$ state-1-2-3-4-5
$: ?(%1 %2 %3 %4 %5) $: ?(%1 %2 %3 %4 %5)
url=@ta url=@ta
@ -196,6 +194,15 @@
own=owners own=owners
logs=(list =event-log:rpc:ethereum) logs=(list =event-log:rpc:ethereum)
== ==
++ state-5-to-6
|= state-1-2-3-4-5
^- state-6
[%6 url net ~m5 whos nas own spo logs]
::
++ state-6-to-7
|= state-6
^- app-state
[%7 url net refresh whos nas own spo logs *snap-state]
-- --
:: ::
++ on-poke ++ on-poke
@ -219,9 +226,9 @@
[(subscribe-to-eth-watcher bowl)]~ [(subscribe-to-eth-watcher bowl)]~
:: ::
%resnap %resnap
=: nas.state nas.snap =: nas.state nas.sap.state
own.state owners.snap own.state owners.sap.state
spo.state sponsors.snap spo.state sponsors.sap.state
== ==
`this `this
== ==
@ -229,7 +236,23 @@
?. ?=(%azimuth-poke mark) ?. ?=(%azimuth-poke mark)
(on-poke:def mark vase) (on-poke:def mark vase)
=+ !<(poke=poke-data vase) =+ !<(poke=poke-data vase)
|-
?- -.poke ?- -.poke
%load
=/ points=@ud ~(wyt by points.nas.snap.poke)
%- %- slog
[leaf+"ship: loading azimuth snapshot ({<points>} points)"]~
::
=: net.state %default
nas.state nas.snap.poke
own.state owners.snap.poke
spo.state sponsors.snap.poke
url.state 'http://eth-mainnet.urbit.org:8545'
sap.state snap.poke
logs.state ~
==
$(poke [%kick ~])
::
%listen %listen
[[(listen-to-azimuth (silt whos.poke) source.poke)]~ this] [[(listen-to-azimuth (silt whos.poke) source.poke)]~ this]
:: ::
@ -237,8 +260,8 @@
=/ last-block=@ =/ last-block=@
?^ logs.state ?^ logs.state
number:(last-block-id:dice logs.state) number:(last-block-id:dice logs.state)
~& >> %no-logs-in-azimuth-state :: ~& >> %no-logs-in-azimuth-state
last-snap number.id.sap.state
=+ [our=(scot %p our.bowl) now=(scot %da now.bowl)] =+ [our=(scot %p our.bowl) now=(scot %da now.bowl)]
=+ .^(dudes=(set [dude:gall ?]) %ge our %base now /) =+ .^(dudes=(set [dude:gall ?]) %ge our %base now /)
=/ running=? (~(has in dudes) [%eth-watcher &]) =/ running=? (~(has in dudes) [%eth-watcher &])
@ -246,12 +269,14 @@
|((~(has in dudes) [%eth-watcher &]) (~(has in dudes) [%eth-watcher |])) |((~(has in dudes) [%eth-watcher &]) (~(has in dudes) [%eth-watcher |]))
:_ this :_ this
=/ cards=(list card) =/ cards=(list card)
:- :: %jael will re-subscribe to get all azimuth diffs ?: installed
~
:: reinstall %base desk
:: ::
(listen-to-azimuth ~ [%| dap.bowl]) =+ spo=(sein:title [our now our]:bowl)
:: we poke eth-watcher to retrieve logs from the latest we have ~& >> re-installing-base-from+spo
:: =/ fresh=[desk ship desk] [%base spo %kids]
%*(start do last-snap last-block) [%pass /fresh %agent [our.bowl %hood] %poke kiln-install+!>(fresh)]~
=? cards !running =? cards !running
:: restart %eth-watcher :: restart %eth-watcher
:: ::
@ -259,30 +284,29 @@
=/ rein=[desk rein] [%base %.y [%eth-watcher ~ ~] ~] =/ rein=[desk rein] [%base %.y [%eth-watcher ~ ~] ~]
:_ cards :_ cards
[%pass /rein %agent [our.bowl %hood] %poke kiln-rein+!>(rein)] [%pass /rein %agent [our.bowl %hood] %poke kiln-rein+!>(rein)]
=? cards !installed =. cards
:: reinstall %base desk :: we poke eth-watcher to retrieve logs from the latest we have
:: ::
=+ spo=(sein:title [our now our]:bowl) (weld %*(start do number.id.sap.state last-block) cards)
~& >> re-installing-base-from+spo =? cards !(~(has by wex.bowl) [/eth-watcher our.bowl %eth-watcher])
=/ fresh=[desk ship desk] [%base spo %kids]
:_ cards
[%pass /fresh %agent [our.bowl %hood] %poke kiln-install+!>(fresh)]
:: resubscribe if we somehow get unsubscribed from eth-watcher :: resubscribe if we somehow get unsubscribed from eth-watcher
:: ::
?: (~(has by wex.bowl) [/eth-watcher our.bowl %eth-watcher])
cards
~& >> %resubscribing-to-eth-watcher
[(subscribe-to-eth-watcher bowl) cards] [(subscribe-to-eth-watcher bowl) cards]
=. cards
:: %jael will re-subscribe to get all azimuth diffs
::
[(listen-to-azimuth ~ [%| dap.bowl]) cards]
(flop cards)
:: ::
%watch %watch
=: nas.state ?:(?=(%default net.poke) nas.snap *^state:naive) =: nas.state ?:(?=(%default net.poke) nas.sap.state *^state:naive)
own.state ?:(?=(%default net.poke) owners.snap ~) own.state ?:(?=(%default net.poke) owners.sap.state ~)
spo.state ?:(?=(%default net.poke) sponsors.snap ~) spo.state ?:(?=(%default net.poke) sponsors.sap.state ~)
net.state net.poke net.state net.poke
url.state url.poke url.state url.poke
logs.state ~ logs.state ~
== ==
[start:do this] `this
== ==
:: ::
++ on-watch ++ on-watch
@ -309,7 +333,7 @@
:- %leaf :- %leaf
"ship: processing azimuth snapshot ({<points>} points)" "ship: processing azimuth snapshot ({<points>} points)"
=/ snap-cards=udiffs:point =/ snap-cards=udiffs:point
(%*(run-state do logs.state ~) id.snap points.nas.state) (%*(run-state do logs.state ~) id.sap.state points.nas.state)
[(weld (jael-update:do snap-cards) start:do) this] [(weld (jael-update:do snap-cards) start:do) this]
:: ::
++ on-leave on-leave:def ++ on-leave on-leave:def
@ -325,6 +349,7 @@
[%x %spo ~] ``noun+!>(spo.state) [%x %spo ~] ``noun+!>(spo.state)
[%x %refresh ~] ``atom+!>(refresh.state) [%x %refresh ~] ``atom+!>(refresh.state)
[%x %point @ ~] ``noun+(point i.t.t.path) [%x %point @ ~] ``noun+(point i.t.t.path)
[%x %last-snap ~] ``noun+!>(sap.state)
== ==
:: ::
++ point ++ point
@ -369,19 +394,24 @@
:: ::
++ on-arvo ++ on-arvo
|= [=wire =sign-arvo] |= [=wire =sign-arvo]
?: &(=(/al wire) ?=(%arow +<.sign-arvo))
?- -.p.sign-arvo
%& `this
%|
%- (slog 'loading azimuth snapshot failed! still trying' p.p.sign-arvo)
[~[(init-timer (add ~s10 now.bowl))] this]
==
?. &(=(/init wire) ?=(%wake +<.sign-arvo)) ?. &(=(/init wire) ?=(%wake +<.sign-arvo))
(on-arvo:def wire sign-arvo) (on-arvo:def wire sign-arvo)
?^ error.sign-arvo ?^ error.sign-arvo
%- (slog 'azimuth: failed to initialize!' ~) %- (slog 'azimuth: failed to initialize!' ~)
`this `this
:_ this :_ this
~[(subscribe-to-eth-watcher bowl) (listen-to-azimuth ~ [%| dap.bowl])] ~[start-azimuth-load]
:: ::
++ on-fail on-fail:def ++ on-fail on-fail:def
-- --
|_ =bowl:gall |_ =bowl:gall
:: TODO: maybe flop the endianness here so metamask signs it in normal
:: order?
:: ::
++ verifier ++ verifier
^- ^verifier:naive ^- ^verifier:naive
@ -514,7 +544,7 @@
:+ %watch /[dap.bowl] :+ %watch /[dap.bowl]
^- config:eth-watcher ^- config:eth-watcher
:* url.state =(%czar (clan:title our.bowl)) refresh.state ~h30 :* url.state =(%czar (clan:title our.bowl)) refresh.state ~h30
(max launch.net ?:(=(net.state %default) +(last-snap) 0)) (max launch.net ?:(=(net.state %default) +(number.id.sap.state) 0))
~ ~
~[azimuth.net] ~[azimuth.net]
~[naive.net] ~[naive.net]

View File

@ -532,10 +532,11 @@
?: ?=([%show %3] -.mad) ?: ?=([%show %3] -.mad)
(dy-rash %tan (dy-show-source q.mad) ~) (dy-rash %tan (dy-show-source q.mad) ~)
?: ?=(%brev -.mad) ?: ?=(%brev -.mad)
?: ?=(?(%eny %now %our) p.mad)
(dy-rash %tan (cat 3 p.mad ' is immutable') ~)
=. var (~(del by var) p.mad) =. var (~(del by var) p.mad)
=< dy-amok =< dy-amok
?+ p.mad . ?+ p.mad .
$?(%eny %now %our) !!
%lib .(lib ~) %lib .(lib ~)
%sur .(sur ~) %sur .(sur ~)
%dir .(dir [[our.hid %base ud+0] /]) %dir .(dir [[our.hid %base ud+0] /])
@ -543,13 +544,12 @@
=+ cay=(~(got by rez) p.q.mad) =+ cay=(~(got by rez) p.q.mad)
?- -.p.mad ?- -.p.mad
%verb %verb
?: ?=(?(%eny %now %our) p.p.mad)
(dy-rash %tan (cat 3 p.p.mad ' is immutable') ~)
=. var (~(put by var) p.p.mad cay) =. var (~(put by var) p.p.mad cay)
~| bad-set+[p.p.mad p.q.cay] ~| bad-set+[p.p.mad p.q.cay]
=< dy-amok =< dy-amok
?+ p.p.mad . ?+ p.p.mad .
%eny ~|(%entropy-is-eternal !!)
%now ~|(%time-is-immutable !!)
%our ~|(%self-is-immutable !!)
%lib %lib
%_ . %_ .
lib lib
@ -568,6 +568,8 @@
?: ?=([@ ~] pax) ~[i.pax %base '0'] ?: ?=([@ ~] pax) ~[i.pax %base '0']
?: ?=([@ @ ~] pax) ~[i.pax i.t.pax '0'] ?: ?=([@ @ ~] pax) ~[i.pax i.t.pax '0']
pax pax
?: =(~ .^((list path) %ct pax))
+(..dy (he-diff %tan 'dojo: dir does not exist' ~))
=. dir (need (de-beam pax)) =. dir (need (de-beam pax))
=- +>(..dy (he-diff %tan - ~)) =- +>(..dy (he-diff %tan - ~))
rose+[" " `~]^~[leaf+"=%" (smyt (en-beam he-beak s.dir))] rose+[" " `~]^~[leaf+"=%" (smyt (en-beam he-beak s.dir))]
@ -735,9 +737,9 @@
^+ +>+> ^+ +>+>
=^ dat say (~(transceive sole say) cal) =^ dat say (~(transceive sole say) cal)
?: |(?=(^ per) ?=(^ pux) ?=(~ pro)) ?: |(?=(^ per) ?=(^ pux) ?=(~ pro))
~& %dy-edit-busy
=^ lic say (~(transmit sole say) dat) =^ lic say (~(transmit sole say) dat)
(dy-diff %mor [%det lic] [%bel ~] ~) =/ tip=@t 'dojo: busy (press backspace to abort)'
(dy-diff %mor [%det lic] [%bel ~] [%tan [tip ~]] ~)
=> .(per `dat) => .(per `dat)
=/ res (mule |.((slam u.pro !>((tufa buf.say))))) =/ res (mule |.((slam u.pro !>((tufa buf.say)))))
?: ?=(%| -.res) ?: ?=(%| -.res)

View File

@ -469,6 +469,10 @@
[~ this(dogs.state (~(put by dogs.state) path u.dog(running ~)))] [~ this(dogs.state (~(put by dogs.state) path u.dog(running ~)))]
:: ::
%thread-done %thread-done
:: if empty, that means we cancelled this thread
::
?: =(*vase q.cage.sign)
`this
=+ !<([vows=disavows pup=watchpup] q.cage.sign) =+ !<([vows=disavows pup=watchpup] q.cage.sign)
=. u.dog =. u.dog
%_ u.dog %_ u.dog

View File

@ -0,0 +1,46 @@
:: print [len] %ames flows, sorted by number-per-ship
::
:- %say
|= [[now=@da eny=@uvJ bec=beak] arg=$@(~ [len=@ ~]) ~]
:- %noun
::
=; flows
^- (list [=ship open=[out-open=@ out-closing=@ in=@ nax=@] corked=@])
=/ len ?^(arg len.arg 50)
(scag len (sort flows |=([[@ [a=@ud *] *] @ [b=@ud *] *] (gth a b))))
::
=/ peers-map
.^ (map ship ?(%alien %known))
%ax /(scot %p p.bec)//(scot %da now)/peers
==
=/ peers=(list ship)
%+ murn ~(tap by peers-map)
|= [=ship val=?(%alien %known)]
?: =(ship p.bec)
~ :: this is weird, but we saw it
?- val
%alien ~
%known (some ship)
==
::
^- (list [=ship open=[out-open=@ out-closing=@ in=@ nax=@] corked=@])
%+ turn peers
|= =ship
=+ .^ =ship-state:ames
%ax /(scot %p p.bec)//(scot %da now)/peers/(scot %p ship)
==
=/ =peer-state:ames ?>(?=(%known -.ship-state) +.ship-state)
=/ corked ~(wyt in corked.peer-state)
=- [ship - corked]
::
=+ %+ roll ~(tap in ~(key by snd.peer-state))
|= [b=bone [out=(list bone) in=(list bone) nax=(list bone)]]
=/ m (mod b 4)
?+ m ~|([%odd-bone b] !!)
%0 [[b out] in nax]
%1 [out [b in] nax]
%3 [out in [b nax]]
==
=/ [out-closing=(list bone) out-open=(list bone)]
(skid out ~(has ^in closing.peer-state))
[(lent out-open) (lent out-closing) (lent in) (lent nax)]

View File

@ -0,0 +1,20 @@
:: print [len] %ames message-pump timers, sorted by number-per-ship
::
:- %say
|= [[now=@da eny=@uvJ bec=beak] arg=$@(~ [len=@ ~]) ~]
:- %noun
::
=; who
^- (list [@ta @ud])
=/ len ?^(arg len.arg 50)
(scag len (sort ~(tap by who) |=([[@ a=@ud] @ b=@ud] (gth a b))))
::
=| who=(map @ta @ud)
=/ tim .^((list (pair @da duct)) bx+/(scot %p p.bec)//(scot %da now)/debug/timers)
|- ^+ who
?~ tim who
?. &(?=(^ q.i.tim) ?=([%ames %pump ^] i.q.i.tim))
$(tim t.tim)
=* her i.t.t.i.q.i.tim
=/ i (~(gut by who) her 0)
$(tim t.tim, who (~(put by who) her +(i)))

View File

@ -1,5 +0,0 @@
:: Kick azimuth
::
:- %say
|= *
[%azimuth-poke %kick ~]

View File

@ -0,0 +1,10 @@
:: +gall-nonces: print %gall agent subscription nonces, highest-last
::
:- %say
|= [[now=@da eny=@uvJ bec=beak] ~ ~]
:- %noun
^- (list [dude:gall @ud])
%+ sort
%~ tap by
.^((map dude:gall @ud) %gf /(scot %p p.bec)//(scot %da now))
|=([[* a=@ud] [* b=@ud]] (lth a b))

View File

@ -0,0 +1,8 @@
:- %say
|= $: [now=@da eny=@uvJ bec=beak]
~
[dude=_`dude:gall`%$ ship=_`@p`(bex 128)]
==
=/ darg=(unit dude:gall) ?:(=(%$ dude) ~ `dude)
=/ sarg=(unit ^ship) ?:(=((bex 128) ship) ~ `ship)
[%helm-doff darg sarg]

View File

@ -0,0 +1,8 @@
:: Helm: Set Gall Verbosity by Agent
::
/? 310
::
:- %say
|= [^ dudes=(list dude:gall) ~]
:- %helm-gall-sift
dudes

View File

@ -0,0 +1,11 @@
:: Helm: Adjust Gall verbosity
::
:: List of diagnostic flags is in verb:gall in zuse.hoon, documented in
:: gall.hoon
::
/? 310
::
:- %say
|= [^ veb=(list verb:gall) ~]
:- %helm-gall-verb
veb

View File

@ -9,7 +9,9 @@
:- %kiln-rein :- %kiln-rein
:- desk :- desk
%+ roll arg %+ roll arg
=| =rein:hood =/ =rein:hood
=< rein.arak
.^(vat:hood %gx /(scot %p p.bec)/hood/(scot %da now)/kiln/vat/[desk]/noun)
|: [*[on=? =dude:gall] rein=rein(liv liv)] |: [*[on=? =dude:gall] rein=rein(liv liv)]
?: on ?: on
rein(add (~(put in add.rein) dude)) rein(add (~(put in add.rein) dude))

View File

@ -77,7 +77,8 @@
:: ::
++ de-gill :: gill from wire ++ de-gill :: gill from wire
|= way=wire ^- gill:gall |= way=wire ^- gill:gall
?>(?=([@ @ ~] way) [(slav %p i.way) i.t.way]) ~| way
?>(?=([@ @ *] way) [(slav %p i.way) i.t.way])
-- --
:: TODO: remove .ost :: TODO: remove .ost
:: ::

View File

@ -230,6 +230,14 @@
|= veb=(list verb:ames) =< abet |= veb=(list verb:ames) =< abet
(emit %pass /helm %arvo %a %spew veb) (emit %pass /helm %arvo %a %spew veb)
:: ::
++ poke-gall-sift
|= dudes=(list dude:gall) =< abet
(emit %pass /helm %arvo %g %sift dudes)
::
++ poke-gall-verb
|= veb=(list verb:gall) =< abet
(emit %pass /helm %arvo %g %spew veb)
::
++ poke-ames-wake ++ poke-ames-wake
|= ~ =< abet |= ~ =< abet
(emit %pass /helm %arvo %a %stir '') (emit %pass /helm %arvo %a %stir '')
@ -252,6 +260,11 @@
=< abet =< abet
(emit %pass /helm/cors/reject %arvo %e %reject-origin origin) (emit %pass /helm/cors/reject %arvo %e %reject-origin origin)
:: ::
++ poke-doff
|= [dude=(unit dude:gall) ship=(unit ship)]
=< abet
(emit %pass /helm/doff %arvo %g %doff dude ship)
::
++ poke ++ poke
|= [=mark =vase] |= [=mark =vase]
?> ?| ?=(%helm-hi mark) ?> ?| ?=(%helm-hi mark)
@ -269,6 +282,9 @@
%helm-code =;(f (f !<(_+<.f vase)) poke-code) %helm-code =;(f (f !<(_+<.f vase)) poke-code)
%helm-cors-approve =;(f (f !<(_+<.f vase)) poke-cors-approve) %helm-cors-approve =;(f (f !<(_+<.f vase)) poke-cors-approve)
%helm-cors-reject =;(f (f !<(_+<.f vase)) poke-cors-reject) %helm-cors-reject =;(f (f !<(_+<.f vase)) poke-cors-reject)
%helm-doff =;(f (f !<(_+<.f vase)) poke-doff)
%helm-gall-sift =;(f (f !<(_+<.f vase)) poke-gall-sift)
%helm-gall-verb =;(f (f !<(_+<.f vase)) poke-gall-verb)
%helm-hi =;(f (f !<(_+<.f vase)) poke-hi) %helm-hi =;(f (f !<(_+<.f vase)) poke-hi)
%helm-knob =;(f (f !<(_+<.f vase)) poke-knob) %helm-knob =;(f (f !<(_+<.f vase)) poke-knob)
%helm-pans =;(f (f !<(_+<.f vase)) poke-pans) %helm-pans =;(f (f !<(_+<.f vase)) poke-pans)

View File

@ -0,0 +1,203 @@
/+ *test, test-pub, test-sub
/= ames-raw /sys/vane/ames
/= gall-raw /sys/vane/gall
::
=/ ames-bunt (ames-raw ~zod)
=/ gall-bunt (gall-raw ~zod)
:: basic helpers
::
|%
++ make-gall
|= =ship
=/ gall-pupa (gall-raw ship)
=/ gall-core (gall-pupa now=~1111.1.1 eny=`@`0xdead.beef scry=*roof)
=+ [out adult]=(call:gall-core duct=~[/init] dud=~ task=[%init ~])
adult
::
++ ames-nec-bud
:: create ~nec
::
=/ nec (ames-raw ~nec)
=. now.nec ~1111.1.1
=. eny.nec 0xdead.beef
=. life.ames-state.nec 2
=. rof.nec |=(* ``[%noun !>(*(list turf))])
=. crypto-core.ames-state.nec (pit:nu:crub:crypto 512 (shaz 'nec'))
=/ nec-pub pub:ex:crypto-core.ames-state.nec
=/ nec-sec sec:ex:crypto-core.ames-state.nec
:: create ~bud
::
=/ bud (ames-raw ~bud)
=. now.bud ~1111.1.1
=. eny.bud 0xbeef.dead
=. life.ames-state.bud 3
=. rof.bud |=(* ``[%noun !>(*(list turf))])
=. crypto-core.ames-state.bud (pit:nu:crub:crypto 512 (shaz 'bud'))
=/ bud-pub pub:ex:crypto-core.ames-state.bud
=/ bud-sec sec:ex:crypto-core.ames-state.bud
::
=/ nec-sym (derive-symmetric-key:ames-raw bud-pub nec-sec)
=/ bud-sym (derive-symmetric-key:ames-raw nec-pub bud-sec)
?> =(nec-sym bud-sym)
:: tell ~nec about ~bud
::
=. peers.ames-state.nec
%+ ~(put by peers.ames-state.nec) ~bud
=| =peer-state:ames
=. -.peer-state
:* symmetric-key=bud-sym
life=3
rift=0
public-key=bud-pub
sponsor=~bud
==
=. route.peer-state `[direct=%.y `lane:ames`[%& ~bud]]
[%known peer-state]
:: tell ~bud about ~nec
::
=. peers.ames-state.bud
%+ ~(put by peers.ames-state.bud) ~nec
=| =peer-state:ames
=. -.peer-state
:* symmetric-key=nec-sym
life=2
rift=0
public-key=nec-pub
sponsor=~nec
==
=. route.peer-state `[direct=%.y `lane:ames`[%& ~nec]]
[%known peer-state]
:: metamorphose
::
=> .(nec +:(call:(nec) ~[//unix] ~ %born ~))
=> .(bud +:(call:(bud) ~[//unix] ~ %born ~))
::
[nec=nec bud=bud]
--
:: forward-declare to avoid repeated metamorphoses
=/ gall-adult (make-gall ~zod)
=/ ames-adult nec:ames-nec-bud
:: main core
::
|%
+$ gall-gate _gall-adult
+$ ames-gate _ames-adult
::
++ nec-bud
=/ a ames-nec-bud
=/ gall-nec (make-gall ~nec)
=. gall-nec (load-agent ~nec gall-nec %sub test-sub)
=/ gall-bud (make-gall ~bud)
=. gall-bud (load-agent ~bud gall-bud %pub test-pub)
:* nec=[ames=nec.a gall=gall-nec]
bud=[ames=bud.a gall=gall-bud]
==
:: +gall-check-call: run gall task, assert produces expected-moves
::
++ gall-check-call
|= $: =gall-gate
[now=@da eny=@ =roof]
[=duct task=(hobo task:gall)]
expected-moves=(list move:gall-bunt)
==
^- [tang ^gall-gate]
=/ gall-core (gall-gate now eny roof)
=^ moves gall-gate (call:gall-core duct dud=~ task)
[(expect-eq !>(expected-moves) !>(moves)) gall-gate]
::
++ gall-call
|= [=gall-gate =duct task=(hobo task:gall) =roof]
%. [duct dud=~ task]
call:(gall-gate now=~1111.1.1 eny=`@`0xdead.beef roof)
:: +gall-check-take: run gall sign, assert produces expected-moves
::
++ gall-check-take
|= $: =gall-gate
[now=@da eny=@ =roof]
[=wire =duct =sign-arvo]
expected-moves=(list move:gall-bunt)
==
^- [tang ^gall-gate]
=/ gall-core (gall-gate now eny roof)
=^ moves gall-gate (take:gall-core wire duct dud=~ sign-arvo)
[(expect-eq !>(expected-moves) !>(moves)) gall-gate]
::
++ gall-take
|= [=gall-gate =wire =duct =sign-arvo =roof]
%. [wire duct dud=~ sign-arvo]
take:(gall-gate now=~1111.1.1 eny=`@`0xdead.beef roof)
:: +ames-check-call: run gall task, assert produces expected-moves
::
++ ames-check-call
|= $: =ames-gate
[now=@da eny=@ =roof]
[=duct task=(hobo task:ames)]
expected-moves=(list move:ames-bunt)
==
^- [tang ^ames-gate]
=/ ames-core (ames-gate now eny roof)
=^ moves ames-gate (call:ames-core duct dud=~ task)
[(expect-eq !>(expected-moves) !>(moves)) ames-gate]
::
++ ames-call
|= [=ames-gate =duct task=(hobo task:ames) =roof]
%. [duct dud=~ task]
call:(ames-gate now=~1111.1.1 eny=`@`0xdead.beef roof)
:: +ames: run ames sign, assert produces expected-moves
::
++ ames-check-take
|= $: =ames-gate
[now=@da eny=@ =roof]
[=wire =duct =sign:ames-bunt]
expected-moves=(list move:ames-bunt)
==
^- [tang ^ames-gate]
=/ ames-core (ames-gate now eny roof)
=^ moves ames-gate (take:ames-core wire duct dud=~ sign)
[(expect-eq !>(expected-moves) !>(moves)) ames-gate]
::
++ ames-scry-peer
|= $: =ames-gate
[now=@da eny=@ =roof]
our=ship
her=ship
==
^- peer-state:ames
=- ?>(?=(%known -<) ->)
!< ship-state:ames
=< q
%- need %- need
%- scry:(ames-gate now eny roof)
[~ %x [[our %$ da+now] /peers/(scot %p her)]]
::
++ gall-scry-nonce
|= $: =gall-gate
[now=@da eny=@ =roof]
our=ship
=dude:gall
sub=[=ship =term =wire]
==
^- @ud
!< @ud
=< q
%- need %- need
%- scry:(gall-gate now eny roof)
[~ %n [[our dude da+now] [(scot %p ship.sub) [term wire]:sub]]]
::
++ load-agent
|= [=ship =gall-gate =dude:gall =agent:gall]
=^ * gall-gate
(gall-call gall-gate ~[/jolt] [%jolt %base dude] *roof)
=^ * gall-gate
=/ =sign-arvo
:+ %clay %writ
`[[%a da+~1111.1.1 %base] /app/[dude]/hoon vase+!>(!>(agent))]
%: gall-take
gall-gate
/sys/cor/[dude]/(scot %p ship)/base/(scot %da ~1111.1.1)
~[/jolt]
sign-arvo
*roof
==
gall-gate
--

View File

@ -0,0 +1,36 @@
/+ default-agent, verb, dbug
::
=| state=~
%- agent:dbug
%+ verb &
^- agent:gall
|_ =bowl:gall
+* this .
def ~(. (default-agent this %|) bowl)
::
++ on-poke
|= [=mark =vase]
(on-poke:def +<)
::
++ on-watch
|= =path
`this
::
++ on-agent
|= [=wire =sign:agent:gall]
(on-agent:def +<)
::
++ on-fail
|= [=term =tang]
(mean ':pub +on-fail' term tang)
::
++ on-leave
|= =path
`this
::
++ on-init `this
++ on-save !>(state)
++ on-load |=(old=vase `this(state !<(_state old)))
++ on-arvo on-arvo:def
++ on-peek on-peek:def
--

View File

@ -0,0 +1,47 @@
/+ default-agent, verb, dbug
::
=| state=~
%- agent:dbug
%+ verb &
^- agent:gall
|_ =bowl:gall
+* this .
def ~(. (default-agent this %|) bowl)
::
++ on-poke
|= [=mark =vase]
=+ !<(=ship vase)
:_ this
?+ mark !!
%leave [%pass /sub-foo/(scot %p ship) %agent [ship %pub] %leave ~]~
%watch [%pass /sub-foo/(scot %p ship) %agent [ship %pub] %watch /foo]~
==
::
++ on-watch
|= =path
(on-watch:def +<)
::
++ on-agent
|= [=wire =sign:agent:gall]
=/ =ship (slav %p &2.wire)
?+ -.sign !!
%fact `this
%watch-ack `this
%kick
[[%pass /sub-foo/(scot %p ship) %agent [ship %pub] %watch /foo]~ this]
==
::
++ on-fail
|= [=term =tang]
(mean ':sub +on-fail' term tang)
::
++ on-leave
|= =path
`this
::
++ on-init `this
++ on-save !>(state)
++ on-load |=(old=vase `this(state !<(_state old)))
++ on-arvo on-arvo:def
++ on-peek on-peek:def
--

View File

@ -0,0 +1,12 @@
/- *aquarium
|_ af=aqua-effect
++ grad %noun
++ grow
|%
++ noun af
--
++ grab
|%
++ noun aqua-effect
--
--

View File

@ -1,21 +0,0 @@
::
:::: /hoon/css/mar
::
/? 310
=, eyre
=, mimes:html
|_ mud=@t
++ grow :: convert to
|% ++ mime [/text/css (as-octs mud)] :: convert to %mime
++ elem ;style :: convert to %hymn
;- (trip mud)
==
++ hymn ;html:(head:"{elem}" body)
--
++ grab
|% :: convert from
++ mime |=([p=mite q=octs] (@t q.q))
++ noun @t :: clam from %noun
--
++ grad %mime
--

1
pkg/arvo/mar/css.hoon Symbolic link
View File

@ -0,0 +1 @@
../../base-dev/mar/css.hoon

View File

@ -8,5 +8,14 @@
++ grab ++ grab
|% |%
+$ noun [ship binding] +$ noun [ship binding]
++ json
=, dejs:format
|= jon=json
%. jon
%- ot
:~ [%ship |=(j=json ?>(?=([%s *] j) (rash +.j fed:ag)))]
[%address |=(j=json ?>(?=([%s *] j) [%if (rash +.j ip4:eyre)]))]
[%turf (ar so)]
==
-- --
-- --

View File

@ -0,0 +1,16 @@
/- *dns
|_ r=request
++ grad %noun
++ grow
|%
++ json
%- pairs:enjs:format
:~ ['ship' (ship:enjs:format ship.r)]
['address' s+(rsh 3 (scot %if +.address.r))]
==
--
++ grab
|%
++ noun request
--
--

View File

@ -7,6 +7,7 @@
+$ owners (jug owner ship) +$ owners (jug owner ship)
+$ sponsors (map ship [residents=(set ship) requests=(set ship)]) +$ sponsors (map ship [residents=(set ship) requests=(set ship)])
+$ history (map address:ethereum (tree hist-tx)) +$ history (map address:ethereum (tree hist-tx))
+$ events (list event-log:rpc:ethereum)
+$ net ?(%mainnet %ropsten %local %default) +$ net ?(%mainnet %ropsten %local %default)
+$ snap-state [%0 =id:block:jael nas=^state:naive =owners =sponsors] +$ snap-state [%0 =id:block:jael nas=^state:naive =owners =sponsors]
:: ::

View File

@ -351,6 +351,7 @@
:: %hear: packet from unix :: %hear: packet from unix
:: %heed: track peer's responsiveness; gives %clog if slow :: %heed: track peer's responsiveness; gives %clog if slow
:: %jilt: stop tracking peer's responsiveness :: %jilt: stop tracking peer's responsiveness
:: %cork: request to delete message flow
:: %plea: request to send message :: %plea: request to send message
:: ::
:: System and Lifecycle Tasks :: System and Lifecycle Tasks
@ -367,6 +368,7 @@
$% [%hear =lane =blob] $% [%hear =lane =blob]
[%heed =ship] [%heed =ship]
[%jilt =ship] [%jilt =ship]
[%cork =ship]
$>(%plea vane-task) $>(%plea vane-task)
:: ::
$>(%born vane-task) $>(%born vane-task)
@ -511,6 +513,9 @@
:: entry and emit a nack to the local vane that asked us to send :: entry and emit a nack to the local vane that asked us to send
:: the message. :: the message.
:: heeds: listeners for %clog notifications :: heeds: listeners for %clog notifications
:: closing: bones closed on the sender side
:: corked: bones closed on both sender and receiver
:: krocs: bones that need to be sent again to the publisher
:: ::
+$ peer-state +$ peer-state
$: $: =symmetric-key $: $: =symmetric-key
@ -526,6 +531,9 @@
rcv=(map bone message-sink-state) rcv=(map bone message-sink-state)
nax=(set [=bone =message-num]) nax=(set [=bone =message-num])
heeds=(set duct) heeds=(set duct)
closing=(set bone)
corked=(set bone)
krocs=(set bone)
== ==
:: $qos: quality of service; how is our connection to a peer doing? :: $qos: quality of service; how is our connection to a peer doing?
:: ::
@ -1651,15 +1659,18 @@
[%jolt =desk =dude] :: (re)start agent [%jolt =desk =dude] :: (re)start agent
[%idle =dude] :: suspend agent [%idle =dude] :: suspend agent
[%nuke =dude] :: delete agent [%nuke =dude] :: delete agent
[%doff dude=(unit dude) ship=(unit ship)] :: kill subscriptions
[%rake dude=(unit dude) all=?] :: reclaim old subs
$>(%init vane-task) :: set owner $>(%init vane-task) :: set owner
$>(%trim vane-task) :: trim state $>(%trim vane-task) :: trim state
$>(%vega vane-task) :: report upgrade $>(%vega vane-task) :: report upgrade
$>(%plea vane-task) :: network request $>(%plea vane-task) :: network request
[%spew veb=(list verb)] :: set verbosity
[%sift dudes=(list dude)] :: per agent
== :: == ::
+$ bitt (map duct (pair ship path)) :: incoming subs +$ bitt (map duct (pair ship path)) :: incoming subs
+$ boat :: outgoing subs +$ boat (map [=wire =ship =term] [acked=? =path]) :: outgoing subs
%+ map [=wire =ship =term] :: +$ boar (map [=wire =ship =term] nonce=@) :: and their nonces
[acked=? =path] ::
+$ bowl :: standard app state +$ bowl :: standard app state
$: $: our=ship :: host $: $: our=ship :: host
src=ship :: guest src=ship :: guest
@ -1695,6 +1706,9 @@
$% [%raw-fact =mark =noun] $% [%raw-fact =mark =noun]
sign:agent sign:agent
== ==
:: TODO: add more flags?
::
+$ verb ?(%odd)
:: ::
:: +agent: app core :: +agent: app core
:: ::

File diff suppressed because it is too large Load Diff

View File

@ -45,60 +45,64 @@
|= [[now=@da =duct] state=behn-state] |= [[now=@da =duct] state=behn-state]
:: ::
|% |%
:: %entry-points
:: ::
:: +born: urbit restarted; refresh :next-wake and store wakeup timer duct +| %helpers
:: ::
++ born set-unix-wake(next-wake.state ~, unix-duct.state duct) ++ this .
:: +crud: handle failure of previous arvo event ++ emit |=(m=move this(moves [m moves]))
:: ++ abet
++ crud
|= [tag=@tas error=tang]
^+ [moves state] ^+ [moves state]
:: behn must get activated before other vanes in a %wake :: moves are statefully pre-flopped to ensure that
:: any prepended %doze is emitted first
:: ::
?. =(%wake tag) =. moves (flop moves)
~& %behn-crud-not-wake^tag =/ new=(unit @da) (bind (pry:timer-map timers.state) head)
[[duct %slip %d %flog %crud tag error]~ state] :: emit %doze if needed
:: ::
?: =(~ timers.state) =? ..this
~|(%behn-crud-no-timer^tag^error !!) ?~ unix-duct.state |
=/ dif=[old=(unit @da) new=(unit @da)] [next-wake.state new]
?+ dif ~|([%unpossible dif] !!)
[~ ~] | :: no-op
[~ ^] & :: set
[^ ~] & :: clear
[^ ^] !=(u.old.dif u.new.dif) :: set if changed
==
(emit(next-wake.state new) [unix-duct.state %give %doze new])
:: ::
(wake `error) [moves state]
:: +rest: cancel the timer at :date, then adjust unix wakeup
:: +wait: set a new timer at :date, then adjust unix wakeup
:: ::
++ rest |=(date=@da set-unix-wake(timers.state (unset-timer [date duct]))) +| %entry-points
++ wait |=(date=@da set-unix-wake(timers.state (set-timer [date duct])))
:: +huck: give back immediately
:: ::
:: Useful if you want to continue working after other moves finish. ++ call
|= [=task error=(unit tang)]
^+ this
?: ?& ?=(^ error)
!?=(%wake -.task)
==
:: XX more and better error handling
:: ::
++ huck ~& %behn-crud-not-wake^-.task
|= syn=sign-arvo (emit [duct %slip %d %flog %crud -.task u.error])
=< [moves state]
event-core(moves [duct %give %heck syn]~)
:: +drip: XX
:: ::
++ drip ?- -.task
|= mov=vase %born this(next-wake.state ~, unix-duct.state duct)
=< [moves state] %drip (drip p.task)
^+ event-core %huck (emit [duct %give %heck syn.task])
=. moves %rest this(timers.state (unset-timer [p.task duct]))
[duct %pass /drip/(scot %ud count.drips.state) %b %wait +(now)]~ %trim this
=. movs.drips.state %vega this
(~(put by movs.drips.state) count.drips.state mov) %wait this(timers.state (set-timer [p.task duct]))
=. count.drips.state +(count.drips.state) %wake (wake(next-wake.state ~) error)
event-core ==
:: +take-drip: XX ::
:: +take-drip: the future is now, %give the deferred move
:: ::
++ take-drip ++ take-drip
|= [num=@ud error=(unit tang)] |= [num=@ud error=(unit tang)]
=< [moves state] ^+ this
^+ event-core
=/ drip (~(got by movs.drips.state) num) =/ drip (~(got by movs.drips.state) num)
=. movs.drips.state (~(del by movs.drips.state) num) %- emit(movs.drips.state (~(del by movs.drips.state) num))
=/ =move
=/ card [%give %meta drip] =/ card [%give %meta drip]
?~ error ?~ error
[duct card] [duct card]
@ -108,98 +112,45 @@
:: [duct %hurl fail/tang card] :: [duct %hurl fail/tang card]
:: ::
[duct %pass /drip-slog %d %flog %crud %drip-fail tang] [duct %pass /drip-slog %d %flog %crud %drip-fail tang]
event-core(moves [move moves])
:: +trim: in response to memory pressue
:: ::
++ trim [moves state] +| %tasks
:: +vega: learn of a kernel upgrade
:: ::
++ vega [moves state] :: +drip: enqueue a future gift (as a vase), %pass ourselves a %wait
:: +wake: unix says wake up; process the elapsed timer and set :next-wake ::
++ drip
|= vax=vase
^+ this
%. [duct %pass /drip/(scot %ud count.drips.state) %b %wait +(now)]
%= emit
movs.drips.state (~(put by movs.drips.state) count.drips.state vax)
count.drips.state +(count.drips.state)
==
::
:: +wake: unix says wake up; process the elapsed timer (or forward error)
:: ::
++ wake ++ wake
|= error=(unit tang) |= error=(unit tang)
^+ [moves state] ^+ this
?: =(~ timers.state)
:: no-op on spurious but innocuous unix wakeups :: no-op on spurious but innocuous unix wakeups
:: ::
?: =(~ timers.state)
~? ?=(^ error) %behn-wake-no-timer^u.error ~? ?=(^ error) %behn-wake-no-timer^u.error
[moves state] this
:: if we errored, pop the timer and notify the client vane of the error
::
?^ error
=< set-unix-wake
=^ =timer timers.state pop-timer
(emit-vane-wake duct.timer error)
:: if unix woke us too early, retry by resetting the unix wakeup timer
::
=/ [=timer later-timers=_timers.state] pop-timer =/ [=timer later-timers=_timers.state] pop-timer
?: (gth date.timer now) ?: (gth date.timer now)
set-unix-wake(next-wake.state ~) :: no-op if timer is early, (+abet will reset)
:: pop first timer, tell vane it has elapsed, and adjust next unix wakeup
:: ::
=< set-unix-wake this
(emit-vane-wake(timers.state later-timers) duct.timer ~) :: pop the first timer and notify client vane,
:: %utilities :: forwarding error if present
:: ::
::+| :: XX %wake errors should be signaled out-of-band
:: [duct.timer %hurl goof %give %wake ~]
:: ::
++ event-core . (emit(timers.state later-timers) [duct.timer %give %wake error])
:: +emit-vane-wake: produce a move to wake a vane; assumes no prior moves
:: ::
++ emit-vane-wake +| %implementation
|= [=^duct error=(unit tang)]
event-core(moves [duct %give %wake error]~)
:: +emit-doze: set new unix wakeup timer in state and emit move to unix
:: ::
:: We prepend the unix %doze event so that it is handled first. Arvo must
:: handle this first because the moves %behn emits will get handled in
:: depth-first order. If we're handling a %wake which causes a move to a
:: different vane and a %doze event to send to unix, Arvo needs to process
:: the %doze first because otherwise if the move to the other vane calls
:: back into %behn and emits a second %doze, the second %doze would be
:: handled by unix first which is incorrect.
::
++ emit-doze
|= =date=(unit @da)
^+ event-core
:: no-op if .unix-duct has not yet been set
::
?~ unix-duct.state
event-core
:: make sure we don't try to wake up in the past
::
=? date-unit ?=(^ date-unit) `(max now u.date-unit)
::
%_ event-core
next-wake.state date-unit
moves [[unix-duct.state %give %doze date-unit] moves]
==
:: +set-unix-wake: set or unset next unix wakeup timer based on :i.timers
::
++ set-unix-wake
=< [moves state]
~% %set-unix-wake ..part ~ |-
^+ event-core
::
=* next-wake next-wake.state
=* timers timers.state
:: if no timers, cancel existing wakeup timer or no-op
::
=/ first=(unit [date=@da *]) (pry:timer-map timers.state)
?~ first
?~ next-wake
event-core
(emit-doze ~)
:: if :next-wake is in the past or not soon enough, reset it
::
?^ next-wake
?: &((gte date.u.first u.next-wake) (lte now u.next-wake))
event-core
(emit-doze `date.u.first)
:: there was no unix wakeup timer; set one
::
(emit-doze `date.u.first)
:: +pop-timer: dequeue and produce earliest timer :: +pop-timer: dequeue and produce earliest timer
:: ::
++ pop-timer ++ pop-timer
@ -267,27 +218,10 @@
wrapped-task=(hobo task) wrapped-task=(hobo task)
== ==
^- [(list move) _behn-gate] ^- [(list move) _behn-gate]
::
=/ =task ((harden task) wrapped-task) =/ =task ((harden task) wrapped-task)
=/ event-core (per-event [now hen] state) =/ event-core (per-event [now hen] state)
::
=^ moves state =^ moves state
:: abet:(call:event-core task ?~(dud ~ `tang.u.dud))
:: handle error notifications
::
?^ dud
(crud:event-core -.task tang.u.dud)
::
?- -.task
%born born:event-core
%rest (rest:event-core date=p.task)
%drip (drip:event-core move=p.task)
%huck (huck:event-core syn.task)
%trim trim:event-core
%vega vega:event-core
%wait (wait:event-core date=p.task)
%wake (wake:event-core error=~)
==
[moves behn-gate] [moves behn-gate]
:: +load: migrate an old state to a new behn version :: +load: migrate an old state to a new behn version
:: ::
@ -378,6 +312,6 @@
?> ?=([%drip @ ~] tea) ?> ?=([%drip @ ~] tea)
=/ event-core (per-event [now hen] state) =/ event-core (per-event [now hen] state)
=^ moves state =^ moves state
(take-drip:event-core (slav %ud i.t.tea) error.hin) abet:(take-drip:event-core (slav %ud i.t.tea) error.hin)
[moves behn-gate] [moves behn-gate]
-- --

View File

@ -251,7 +251,7 @@
;meta(charset "utf-8"); ;meta(charset "utf-8");
;meta(name "viewport", content "width=device-width, initial-scale=1, shrink-to-fit=no"); ;meta(name "viewport", content "width=device-width, initial-scale=1, shrink-to-fit=no");
;link(rel "icon", type "image/svg+xml", href (weld "data:image/svg+xml;utf8," favicon)); ;link(rel "icon", type "image/svg+xml", href (weld "data:image/svg+xml;utf8," favicon));
;title:"OS1" ;title:"Urbit"
;style:''' ;style:'''
@import url("https://rsms.me/inter/inter.css"); @import url("https://rsms.me/inter/inter.css");
@font-face { @font-face {
@ -2178,7 +2178,7 @@
:: XX cancel active too if =(0 trim-priority) ? :: XX cancel active too if =(0 trim-priority) ?
:: ::
?: ?=(%trim -.task) ?: ?=(%trim -.task)
=/ event-args [[eny duct now rof] server-state.ax] =* event-args [[eny duct now rof] server-state.ax]
=* by-channel by-channel:(per-server-event event-args) =* by-channel by-channel:(per-server-event event-args)
=* channel-state channel-state.server-state.ax =* channel-state channel-state.server-state.ax
:: ::

View File

@ -4,17 +4,47 @@
:: ::
:::: ::::
|= our=ship |= our=ship
:: veb: verbosity flags
::
=/ veb-all-off
:: TODO: add more flags?
::
:* odd=`?`%.n :: unusual events
==
=, gall =, gall
=> =>
|% |%
+| %helpers
:: +trace: print if .verb is set and we're tracking .dude
::
++ trace
|= [verb=? =dude dudes=(set dude) print=tang]
^+ same
?. verb
same
?. => [dude=dude dudes=dudes in=in]
~+ |(=(~ dudes) (~(has in dudes) dude))
same
(slog print)
::
:: $bug: debug printing configuration
::
:: veb: verbosity toggles
:: dudes: app filter; if ~, print for all
::
+$ bug
$: veb=_veb-all-off
dudes=(set dude)
==
::
+| %main +| %main
:: ::
:: $move: Arvo-level move :: $move: Arvo-level move
:: ::
+$ move [=duct move=(wind note-arvo gift-arvo)] +$ move [=duct move=(wind note-arvo gift-arvo)]
:: $state-8: overall gall state, versioned :: $state-10: overall gall state, versioned
:: ::
+$ state-8 [%8 state] +$ state-10 [%10 state]
:: $state: overall gall state :: $state: overall gall state
:: ::
:: system-duct: TODO document :: system-duct: TODO document
@ -22,6 +52,7 @@
:: contacts: other ships we're in communication with :: contacts: other ships we're in communication with
:: yokes: running agents :: yokes: running agents
:: blocked: moves to agents that haven't been started yet :: blocked: moves to agents that haven't been started yet
:: bug: debug printing configuration
:: ::
+$ state +$ state
$: system-duct=duct $: system-duct=duct
@ -29,13 +60,8 @@
contacts=(set ship) contacts=(set ship)
yokes=(map term yoke) yokes=(map term yoke)
blocked=(map term (qeu blocked-move)) blocked=(map term (qeu blocked-move))
=bug
== ==
:: $watches: subscribers and publications
::
:: TODO: rename this, to $ties?
:: TODO: rename $boat and $bitt and document
::
+$ watches [inbound=bitt outbound=boat]
:: $routes: new cuff; TODO: document :: $routes: new cuff; TODO: document
:: ::
+$ routes +$ routes
@ -45,19 +71,26 @@
:: $yoke: agent runner state :: $yoke: agent runner state
:: ::
:: control-duct: TODO document :: control-duct: TODO document
:: live: is this agent running? TODO document better :: run-nonce: unique for each rebuild
:: sub-nonce: app-wide global %watch nonce
:: live: is this agent running? TODO document boarer
:: stats: TODO document :: stats: TODO document
:: watches: incoming and outgoing subscription state :: bitt: incoming subscriptions
:: boat: outgoing subscriptions
:: boar: and their nonces
:: agent: agent core :: agent: agent core
:: beak: compilation source :: beak: compilation source
:: marks: mark conversion requests :: marks: mark conversion requests
:: ::
+$ yoke +$ yoke
$: control-duct=duct $: control-duct=duct
nonce=@t run-nonce=@t
live=? ::TODO remove, replaced by -.agent sub-nonce=_1
live=?
=stats =stats
=watches =bitt
=boat
=boar
agent=(each agent vase) agent=(each agent vase)
=beak =beak
marks=(map duct mark) marks=(map duct mark)
@ -116,21 +149,25 @@
:: $spore: structures for update, produced by +stay :: $spore: structures for update, produced by +stay
:: ::
+$ spore +$ spore
$: %8 $: %10
system-duct=duct system-duct=duct
outstanding=(map [wire duct] (qeu remote-request)) outstanding=(map [wire duct] (qeu remote-request))
contacts=(set ship) contacts=(set ship)
eggs=(map term egg) eggs=(map term egg)
blocked=(map term (qeu blocked-move)) blocked=(map term (qeu blocked-move))
=bug
== ==
:: $egg: migratory agent state; $yoke with .old-state instead of .agent :: $egg: migratory agent state; $yoke with .old-state instead of .agent
:: ::
+$ egg +$ egg
$: control-duct=duct $: control-duct=duct
nonce=@t run-nonce=@t
sub-nonce=@
live=? live=?
=stats =stats
=watches =bitt
=boat
=boar
old-state=(each vase vase) old-state=(each vase vase)
=beak =beak
marks=(map duct mark) marks=(map duct mark)
@ -139,6 +176,7 @@
:: pupal gall core, on upgrade :: pupal gall core, on upgrade
:: ::
=< =* adult-gate . =< =* adult-gate .
=| spore-tag=@ud
=| =spore =| =spore
|= [now=@da eny=@uvJ rof=roof] |= [now=@da eny=@uvJ rof=roof]
=* pupal-gate . =* pupal-gate .
@ -164,10 +202,12 @@
[^duct %pass /whiz/gall %$ %whiz ~]~ [^duct %pass /whiz/gall %$ %whiz ~]~
=/ adult adult-core =/ adult adult-core
=. state.adult =. state.adult
[%8 system-duct outstanding contacts yokes=~ blocked]:spore [%10 system-duct outstanding contacts yokes=~ blocked bug]:spore
=/ mo-core (mo-abed:mo:adult duct) =/ mo-core (mo-abed:mo:adult system-duct.state.adult)
=. mo-core
=/ apps=(list [dap=term =egg]) ~(tap by eggs.spore) =/ apps=(list [dap=term =egg]) ~(tap by eggs.spore)
:: upgrade %base apps and suspend others
::
=. mo-core
|- ^+ mo-core |- ^+ mo-core
?~ apps mo-core ?~ apps mo-core
?. =(%base q.beak.egg.i.apps) ?. =(%base q.beak.egg.i.apps)
@ -223,9 +263,11 @@
:: ::
++ load ++ load
|^ |= old=spore-any |^ |= old=spore-any
=? old ?=(%7 -.old) =. spore-tag `@ud`-.old
(spore-7-to-8 old) =? old ?=(%7 -.old) (spore-7-to-8 old)
?> ?=(%8 -.old) =? old ?=(%8 -.old) (spore-8-to-9 old)
=? old ?=(%9 -.old) (spore-9-to-10 old)
?> ?=(%10 -.old)
=. spore old =. spore old
?. =(~ eggs.spore) ?. =(~ eggs.spore)
pupal-gate pupal-gate
@ -234,32 +276,100 @@
state spore(eggs *(map term yoke)) state spore(eggs *(map term yoke))
== ==
:: ::
+$ spore-any $%(^spore spore-7) +$ spore-any $%(^spore spore-9 spore-8 spore-7)
+$ spore-7 +$ spore-7
$: %7 $: %7
wipe-eyre-subs=_| ::NOTE band-aid for #3196 wipe-eyre-subs=_| ::NOTE band-aid for #3196
system-duct=duct system-duct=duct
outstanding=(map [wire duct] (qeu remote-request)) outstanding=(map [wire duct] (qeu remote-request-9))
contacts=(set ship) contacts=(set ship)
eggs=(map term egg) eggs=(map term egg-7)
blocked=(map term (qeu blocked-move)) blocked=(map term (qeu blocked-move))
== ==
:: ::
+$ spore-8
$: %8
system-duct=duct
outstanding=(map [wire duct] (qeu remote-request-9))
contacts=(set ship)
eggs=(map term egg-8)
blocked=(map term (qeu blocked-move))
==
::
+$ egg-7 egg-8
+$ egg-8
$: control-duct=duct
run-nonce=@t
live=?
=stats
watches=watches-8
old-state=(each vase vase)
=beak
marks=(map duct mark)
==
::
+$ watches-8 [inbound=bitt outbound=boat-8]
+$ boat-8 (map [wire ship term] [acked=? =path])
::
+$ spore-9
$: %9
system-duct=duct
outstanding=(map [wire duct] (qeu remote-request-9))
contacts=(set ship)
eggs=(map term egg)
blocked=(map term (qeu blocked-move))
=bug
==
::
+$ remote-request-9
?(remote-request %cork)
::
++ spore-7-to-8 ++ spore-7-to-8
|= old=spore-7 |= old=spore-7
^- ^spore ^- spore-8
:- %8 :- %8
=. eggs.old =. eggs.old
%- ~(urn by eggs.old) %- ~(urn by eggs.old)
|= [a=term e=egg] |= [a=term e=egg-7]
::NOTE kiln will kick off appropriate app revival ::NOTE kiln will kick off appropriate app revival
e(old-state [%| p.old-state.e]) e(old-state [%| p.old-state.e])
+>.old +>.old
::
++ spore-8-to-9
|= old=spore-8
^- spore-9
=- old(- %9, eggs -, blocked [blocked.old *bug])
%- ~(run by eggs.old)
|= =egg-8
^- egg
=/ [=bitt =boat =boar] (watches-8-to-9 watches.egg-8)
:* control-duct.egg-8
run-nonce.egg-8
sub-nonce=1
live.egg-8
stats.egg-8
bitt boat boar
[old-state beak marks]:egg-8
==
::
++ watches-8-to-9
|= watches-8
^- [bitt boat boar]
[inbound outbound (~(run by outbound) |=([acked=? =path] nonce=0))]
::
++ spore-9-to-10
|= old=spore-9
=- old(- %10, outstanding -)
%- ~(run by outstanding.old)
|= q=(qeu remote-request-9)
%- ~(gas to *(qeu remote-request))
%+ murn ~(tap to q)
|=(r=remote-request-9 ?:(?=(%cork r) ~ `r))
-- --
-- --
:: adult gall vane interface, for type compatibility with pupa :: adult gall vane interface, for type compatibility with pupa
:: ::
=| state=state-8 =| state=state-10
|= [now=@da eny=@uvJ rof=roof] |= [now=@da eny=@uvJ rof=roof]
=* gall-payload . =* gall-payload .
=< ~% %gall-wrap ..mo ~ =< ~% %gall-wrap ..mo ~
@ -280,6 +390,12 @@
++ mo ++ mo
~% %gall-mo +> ~ ~% %gall-mo +> ~
|_ [hen=duct moves=(list move)] |_ [hen=duct moves=(list move)]
::
++ trace
|= [verb=? =dude print=tang]
^+ same
(^trace verb dude dudes.bug.state print)
::
:: +mo-abed: initialise state with the provided duct :: +mo-abed: initialise state with the provided duct
:: +mo-abet: finalize, reversing moves :: +mo-abet: finalize, reversing moves
:: +mo-pass: prepend a standard %pass to the current list of moves :: +mo-pass: prepend a standard %pass to the current list of moves
@ -288,8 +404,9 @@
++ mo-core . ++ mo-core .
++ mo-abed |=(hun=duct mo-core(hen hun)) ++ mo-abed |=(hun=duct mo-core(hen hun))
++ mo-abet [(flop moves) gall-payload] ++ mo-abet [(flop moves) gall-payload]
++ mo-pass |=(p=[wire note-arvo] mo-core(moves [[hen pass+p] moves]))
++ mo-give |=(g=gift mo-core(moves [[hen give+g] moves])) ++ mo-give |=(g=gift mo-core(moves [[hen give+g] moves]))
++ mo-pass |=(p=[wire note-arvo] mo-core(moves [[hen pass+p] moves]))
++ mo-slip |=(p=note-arvo mo-core(moves [[hen slip+p] moves]))
++ mo-past ++ mo-past
|= =(list [wire note-arvo]) |= =(list [wire note-arvo])
?~ list ?~ list
@ -317,6 +434,30 @@
=/ =case [%da now] =/ =case [%da now]
=/ =wire /sys/cor/[dap]/(scot %p ship)/[desk]/(scot case) =/ =wire /sys/cor/[dap]/(scot %p ship)/[desk]/(scot case)
(mo-pass wire %c %warp ship desk ~ %sing %a case /app/[dap]/hoon) (mo-pass wire %c %warp ship desk ~ %sing %a case /app/[dap]/hoon)
:: +mo-doff: kill all outgoing subscriptions
::
++ mo-doff
|= [dude=(unit dude) ship=(unit ship)]
^+ mo-core
=/ apps=(list (pair term yoke))
?~ dude ~(tap by yokes.state)
(drop (bind (~(get by yokes.state) u.dude) (lead u.dude)))
|- ^+ mo-core
?~ apps mo-core
=/ ap-core (ap-yoke:ap p.i.apps [~ our] q.i.apps)
$(apps t.apps, mo-core ap-abet:(ap-doff:ap-core ship))
:: +mo-rake: send %cork's for old subscriptions if needed
::
++ mo-rake
|= [dude=(unit dude) all=?]
^+ mo-core
=/ apps=(list (pair term yoke))
?~ dude ~(tap by yokes.state)
(drop (bind (~(get by yokes.state) u.dude) (lead u.dude)))
|- ^+ mo-core
?~ apps mo-core
=/ ap-core (ap-yoke:ap p.i.apps [~ our] q.i.apps)
$(apps t.apps, mo-core ap-abet:(ap-rake:ap-core all))
:: +mo-receive-core: receives an app core built by %ford. :: +mo-receive-core: receives an app core built by %ford.
:: ::
:: Presuming we receive a good core, we first check to see if the agent :: Presuming we receive a good core, we first check to see if the agent
@ -357,7 +498,7 @@
control-duct hen control-duct hen
beak bek beak bek
agent &+agent agent &+agent
nonce (scot %uw (end 5 (shas %yoke-nonce eny))) run-nonce (scot %uw (end 5 (shas %yoke-nonce eny)))
== ==
:: ::
=/ old mo-core =/ old mo-core
@ -457,8 +598,12 @@
=. outstanding.state =. outstanding.state
=/ stand =/ stand
(~(gut by outstanding.state) [wire hen] *(qeu remote-request)) (~(gut by outstanding.state) [wire hen] *(qeu remote-request))
(~(put by outstanding.state) [wire hen] (~(put to stand) -.deal)) %+ ~(put by outstanding.state) [wire hen]
(mo-pass wire note-arvo) (~(gas to stand) ?.(?=(%leave -.deal) ~[-.deal] ~[%leave]))
=. mo-core (mo-pass wire note-arvo)
?. ?=(%leave -.deal)
mo-core
(mo-pass wire [%a [%cork ship]])
:: +mo-track-ship: subscribe to ames and jael for notices about .ship :: +mo-track-ship: subscribe to ames and jael for notices about .ship
:: ::
++ mo-track-ship ++ mo-track-ship
@ -680,7 +825,10 @@
(~(put to *(qeu remote-request)) %missing) (~(put to *(qeu remote-request)) %missing)
~| [full-wire=full-wire hen=hen stand=stand] ~| [full-wire=full-wire hen=hen stand=stand]
=^ rr stand ~(get to stand) =^ rr stand ~(get to stand)
[rr (~(put by outstanding.state) [full-wire hen] stand)] :- rr
?: =(~ stand)
(~(del by outstanding.state) [full-wire hen])
(~(put by outstanding.state) [full-wire hen] stand)
:: non-null case of wire is old, remove on next breach after :: non-null case of wire is old, remove on next breach after
:: 2019/12 :: 2019/12
:: ::
@ -696,7 +844,7 @@
%watch (mo-give %unto %watch-ack err) %watch (mo-give %unto %watch-ack err)
%poke (mo-give %unto %poke-ack err) %poke (mo-give %unto %poke-ack err)
%leave mo-core %leave mo-core
%missing (mo-give:(mo-give %unto %watch-ack err) %unto %poke-ack err) %missing ~>(%slog.[3 'gall: missing'] mo-core)
== ==
:: ::
[%ames %boon *] [%ames %boon *]
@ -705,7 +853,18 @@
:: ::
!! !!
=/ =ames-response ;;(ames-response payload.sign-arvo) =/ =ames-response ;;(ames-response payload.sign-arvo)
(mo-handle-ames-response ames-response) :: %d: diff; ask clay to validate .noun as .mark
:: %x: kick; tell agent the publisher canceled the subscription, and
:: cork; tell ames to close the associated flow.
::
?- -.ames-response
%d (mo-give %unto %raw-fact mark.ames-response noun.ames-response)
%x =. mo-core (mo-give %unto %kick ~)
=/ key [[%sys wire] hen]
=? outstanding.state =(~ (~(gut by outstanding.state) key ~))
(~(del by outstanding.state) key)
(mo-pass [%sys wire] %a %cork ship)
==
:: ::
[%ames %lost *] [%ames %lost *]
:: note this should only happen on reverse bones, so only facts :: note this should only happen on reverse bones, so only facts
@ -738,9 +897,18 @@
?~ yoke ?~ yoke
%- (slog leaf+"gall: {<dap>} dead, got {<+<.sign-arvo>}" ~) %- (slog leaf+"gall: {<dap>} dead, got {<+<.sign-arvo>}" ~)
mo-core mo-core
?. =(nonce.u.yoke i.t.wire) ?. =(run-nonce.u.yoke i.t.wire)
%- (slog leaf+"gall: got old {<+<.sign-arvo>} for {<dap>}" ~) %- (slog leaf+"gall: got old {<+<.sign-arvo>} for {<dap>}" ~)
mo-core mo-core
:: if agent must be running, revive all needed agents then apply
::
?: ?& ?=(%| -.agent.u.yoke)
?=(?(%dojo %hood) dap)
==
=. mo-core (mo-pass /nowhere %g %jolt %base %hood)
=. mo-core (mo-pass /nowhere %g %jolt %base %dojo)
(mo-pass use+wire %b %huck sign-arvo)
::
?. ?=([?(%gall %behn) %unto *] sign-arvo) ?. ?=([?(%gall %behn) %unto *] sign-arvo)
?: ?=(%| -.agent.u.yoke) ?: ?=(%| -.agent.u.yoke)
%- (slog leaf+"gall: {<dap>} dozing, dropping {<+<.sign-arvo>}" ~) %- (slog leaf+"gall: {<dap>} dozing, dropping {<+<.sign-arvo>}" ~)
@ -917,8 +1085,17 @@
=/ running (~(get by yokes.state) agent) =/ running (~(get by yokes.state) agent)
=/ is-running ?~(running %| ?=(%& -.agent.u.running)) =/ is-running ?~(running %| ?=(%& -.agent.u.running))
=/ is-blocked (~(has by blocked.state) agent) =/ is-blocked (~(has by blocked.state) agent)
:: agent is running; deliver move normally
::
?. |(!is-running is-blocked)
(mo-apply agent routes deal)
:: if agent must be running, revive all needed agents then apply
::
?: ?=(?(%hood %dojo) agent)
=. mo-core (mo-pass /nowhere %g %jolt %base %hood)
=. mo-core (mo-pass /nowhere %g %jolt %base %dojo)
(mo-slip %g %deal [ship our] agent deal)
:: ::
?: |(!is-running is-blocked)
=/ blocked=(qeu blocked-move) =/ blocked=(qeu blocked-move)
=/ waiting (~(get by blocked.state) agent) =/ waiting (~(get by blocked.state) agent)
=/ deals (fall waiting *(qeu blocked-move)) =/ deals (fall waiting *(qeu blocked-move))
@ -929,7 +1106,6 @@
%_ mo-core %_ mo-core
blocked.state (~(put by blocked.state) agent blocked) blocked.state (~(put by blocked.state) agent blocked)
== ==
(mo-apply agent routes deal)
:: +mo-handle-ames-request: handle %ames request message. :: +mo-handle-ames-request: handle %ames request message.
:: ::
++ mo-handle-ames-request ++ mo-handle-ames-request
@ -950,18 +1126,28 @@
%u [%leave ~] %u [%leave ~]
== ==
(mo-pass wire %g %deal [ship our] agent-name deal) (mo-pass wire %g %deal [ship our] agent-name deal)
:: +mo-handle-ames-response: handle ames response message. :: +mo-spew: handle request to set verbosity toggles on debug output
:: ::
++ mo-handle-ames-response ++ mo-spew
|= =ames-response |= verbs=(list verb)
^+ mo-core ^+ mo-core
:: %d: diff; ask clay to validate .noun as .mark :: start from all %.n's, then flip requested toggles
:: %x: kick; tell agent the publisher canceled the subscription
:: ::
?- -.ames-response =. veb.bug.state
%d (mo-give %unto %raw-fact mark.ames-response noun.ames-response) %+ roll verbs
%x (mo-give %unto %kick ~) |= [=verb acc=_veb-all-off]
^+ veb.bug.state
?- verb
%odd acc(odd %.y)
== ==
mo-core
:: +mo-sift: handle request to filter debug output by agent
::
++ mo-sift
|= dudes=(list dude)
^+ mo-core
=. dudes.bug.state (sy dudes)
mo-core
:: +ap: agent engine :: +ap: agent engine
:: ::
:: An inner, agent-level core. The sample refers to the agent we're :: An inner, agent-level core. The sample refers to the agent we're
@ -976,6 +1162,19 @@
agent-config=(list (each suss tang)) agent-config=(list (each suss tang))
=yoke =yoke
== ==
::
++ trace
|= [verb=? print=tang]
^+ same
(^trace verb agent-name print)
::
++ ap-nonce-wire
|= [=wire =dock]
^+ wire
=/ nonce=@ (~(got by boar.yoke) wire dock)
?: =(0 nonce) wire
[(scot %ud nonce) wire]
::
++ ap-core . ++ ap-core .
:: +ap-abed: initialise state for an agent, with the supplied routes. :: +ap-abed: initialise state for an agent, with the supplied routes.
:: ::
@ -1036,11 +1235,9 @@
:: ::
++ ap-nuke ++ ap-nuke
^+ ap-core ^+ ap-core
=/ out=(list [[=wire =ship =term] ? =path])
~(tap by outbound.watches.yoke)
=/ inbound-paths=(set path) =/ inbound-paths=(set path)
%- silt %- silt
%+ turn ~(tap by inbound.watches.yoke) %+ turn ~(tap by bitt.yoke)
|= [=duct =ship =path] |= [=duct =ship =path]
path path
=/ will=(list card:agent:gall) =/ will=(list card:agent:gall)
@ -1048,9 +1245,9 @@
?: =(~ inbound-paths) ?: =(~ inbound-paths)
~ ~
[%give %kick ~(tap in inbound-paths) ~]~ [%give %kick ~(tap in inbound-paths) ~]~
%+ turn ~(tap by outbound.watches.yoke) %+ turn ~(tap by boat.yoke)
|= [[=wire =ship =term] ? =path] |= [[=wire =dock] ? =path]
[%pass wire %agent [ship term] %leave ~] [%pass wire %agent dock %leave ~]
=^ maybe-tang ap-core (ap-ingest ~ |.([will *agent])) =^ maybe-tang ap-core (ap-ingest ~ |.([will *agent]))
ap-core ap-core
:: +ap-from-internal: internal move to move. :: +ap-from-internal: internal move to move.
@ -1133,12 +1330,13 @@
tang.neet tang.neet
== ==
=. wire =. wire
:^ %use agent-name run-nonce.yoke
?- -.neet ?- -.neet
%agent [%out (scot %p ship.neet) name.neet wire] %agent [%out (scot %p ship.neet) name.neet wire]
%huck [%out (scot %p ship.neet) name.neet wire] %huck [%out (scot %p ship.neet) name.neet wire]
%arvo [(scot %p attributing.agent-routes) wire] %arvo [(scot %p attributing.agent-routes) wire]
== ==
=. wire [%use agent-name nonce.yoke wire] ::
=/ =note-arvo =/ =note-arvo
?- -.neet ?- -.neet
%arvo note-arvo.neet %arvo note-arvo.neet
@ -1152,8 +1350,7 @@
++ ap-breach ++ ap-breach
|= =ship |= =ship
^+ ap-core ^+ ap-core
=/ in=(list [=duct =^ship =path]) =/ in=(list [=duct =^ship =path]) ~(tap by bitt.yoke)
~(tap by inbound.watches.yoke)
|- ^+ ap-core |- ^+ ap-core
?^ in ?^ in
=? ap-core =(ship ship.i.in) =? ap-core =(ship ship.i.in)
@ -1161,14 +1358,15 @@
core(agent-duct agent-duct) core(agent-duct agent-duct)
$(in t.in) $(in t.in)
:: ::
=/ out=(list [[=wire =^ship =term] ? =path]) =/ out=(list [=wire =^ship =term])
~(tap by outbound.watches.yoke) ~(tap ^in ~(key by boat.yoke))
|- ^+ ap-core |- ^+ ap-core
?~ out ?~ out
ap-core ap-core
=? ap-core =(ship ship.i.out) =? ap-core =(ship ship.i.out)
=/ core =/ core
=. agent-duct system-duct.state =. agent-duct system-duct.state
=. wire.i.out (ap-nonce-wire i.out)
=/ way [%out (scot %p ship) term.i.out wire.i.out] =/ way [%out (scot %p ship) term.i.out wire.i.out]
(ap-specific-take way %kick ~) (ap-specific-take way %kick ~)
core(agent-duct agent-duct) core(agent-duct agent-duct)
@ -1184,8 +1382,7 @@
|= =ship |= =ship
^+ ap-core ^+ ap-core
:: ::
=/ in=(list [=duct =^ship =path]) =/ in=(list [=duct =^ship =path]) ~(tap by bitt.yoke)
~(tap by inbound.watches.yoke)
|- ^+ ap-core |- ^+ ap-core
?~ in ap-core ?~ in ap-core
:: ::
@ -1206,7 +1403,7 @@
?~ target-paths ?~ target-paths
?~ target-ship ?~ target-ship
~[agent-duct] ~[agent-duct]
%+ murn ~(tap by inbound.watches.yoke) %+ murn ~(tap by bitt.yoke)
|= [=duct =ship =path] |= [=duct =ship =path]
^- (unit ^duct) ^- (unit ^duct)
?: =(target-ship `ship) ?: =(target-ship `ship)
@ -1221,7 +1418,7 @@
++ ap-ducts-from-path ++ ap-ducts-from-path
|= [target-path=path target-ship=(unit ship)] |= [target-path=path target-ship=(unit ship)]
^- (list duct) ^- (list duct)
%+ murn ~(tap by inbound.watches.yoke) %+ murn ~(tap by bitt.yoke)
|= [=duct =ship =path] |= [=duct =ship =path]
^- (unit ^duct) ^- (unit ^duct)
?: ?& =(target-path path) ?: ?& =(target-path path)
@ -1284,15 +1481,6 @@
?: ?=(%& -.res) ?: ?=(%& -.res)
``want^p.res ``want^p.res
((slog leaf+"peek failed tube from {(trip have)} to {(trip want)}" ~) ~) ((slog leaf+"peek failed tube from {(trip have)} to {(trip want)}" ~) ~)
:: +ap-update-subscription: update subscription.
::
++ ap-update-subscription
~/ %ap-update-subscription
|= [is-ok=? =other=ship other-agent=term =wire]
^+ ap-core
?: is-ok
ap-core
(ap-kill-down wire [other-ship other-agent])
:: +ap-move: send move :: +ap-move: send move
:: ::
++ ap-move ++ ap-move
@ -1316,8 +1504,8 @@
attributing.agent-routes :: guest attributing.agent-routes :: guest
agent-name :: agent agent-name :: agent
== :: == ::
:* wex=outbound.watches.yoke :: outgoing :* wex=boat.yoke :: outgoing
sup=inbound.watches.yoke :: incoming sup=bitt.yoke :: incoming
== :: == ::
:* act=change.stats.yoke :: tick :* act=change.stats.yoke :: tick
eny=eny.stats.yoke :: nonce eny=eny.stats.yoke :: nonce
@ -1353,8 +1541,7 @@
|= pax=path |= pax=path
^+ ap-core ^+ ap-core
=/ incoming [attributing.agent-routes pax] =/ incoming [attributing.agent-routes pax]
=. inbound.watches.yoke =. bitt.yoke (~(put by bitt.yoke) agent-duct incoming)
(~(put by inbound.watches.yoke) agent-duct incoming)
=^ maybe-tang ap-core =^ maybe-tang ap-core
%+ ap-ingest %watch-ack |. %+ ap-ingest %watch-ack |.
(on-watch:ap-agent-core pax) (on-watch:ap-agent-core pax)
@ -1404,6 +1591,7 @@
=/ other-agent i.t.t.wire =/ other-agent i.t.t.wire
=/ =dock [other-ship other-agent] =/ =dock [other-ship other-agent]
=/ agent-wire t.t.t.wire =/ agent-wire t.t.t.wire
=/ nonce=@ 0
:: ::
=^ =sign:agent ap-core =^ =sign:agent ap-core
?. ?=(%raw-fact -.unto) ?. ?=(%raw-fact -.unto)
@ -1424,48 +1612,106 @@
%- ap-move :_ ~ %- ap-move :_ ~
:^ hen %pass /nowhere :^ hen %pass /nowhere
[%c %warp our q.beak.yoke ~ %sing %b case /[mark.unto]] [%c %warp our q.beak.yoke ~ %sing %b case /[mark.unto]]
|^ ^+ ap-core
:: %poke-ack has no nonce; ingest directly
:: ::
:: if subscription ack or close, handle before calling user code ?: ?=(%poke-ack -.sign)
ingest-and-check-error
:: if .agent-wire matches, it's an old pre-nonce subscription
:: ::
=? outbound.watches.yoke ?=(%kick -.sign) ?: (~(has by boat.yoke) sub-key)
%- ~(del by outbound.watches.yoke) run-sign
[agent-wire dock] :: if an app happened to use a null wire, no-op
?: ?& ?=(%watch-ack -.sign) ::
!(~(has by outbound.watches.yoke) [agent-wire dock]) ?: =(~ agent-wire)
on-missing
=/ has-nonce=(unit @ud) (slaw %ud (head agent-wire))
?: &(?=(~ has-nonce) ?=(%kick -.sign))
on-weird-kick
:: pop nonce off .agent-wire and match against stored subscription
::
?> ?=(^ has-nonce)
=: nonce u.has-nonce
agent-wire (tail agent-wire)
== ==
%- %: slog ?~ got=(~(get by boar.yoke) sub-key)
on-missing
?: =(nonce.u.got nonce)
run-sign
(on-bad-nonce nonce.u.got)
::
++ sub-key [agent-wire dock]
++ ingest (ap-ingest ~ |.((on-agent:ap-agent-core agent-wire sign)))
++ run-sign
?- -.sign
%poke-ack !!
%fact
=^ tan ap-core ingest
?~ tan ap-core
=. ap-core (ap-kill-down sub-key)
(ap-error -.sign leaf/"take %fact failed, closing subscription" u.tan)
::
%kick
=: boar.yoke (~(del by boar.yoke) sub-key)
boat.yoke (~(del by boat.yoke) sub-key)
==
ingest-and-check-error
::
%watch-ack
?. (~(has by boat.yoke) sub-key)
%. ap-core
%+ trace odd.veb.bug.state :~
leaf+"{<agent-name>}: got ack for nonexistent subscription" leaf+"{<agent-name>}: got ack for nonexistent subscription"
leaf+"{<dock>}: {<agent-wire>}" leaf+"{<dock>}: {<agent-wire>}"
>wire=wire< >wire=wire<
~
== ==
ap-core =? boar.yoke ?=(^ p.sign) (~(del by boar.yoke) sub-key)
:: ::
=? outbound.watches.yoke ?=(%watch-ack -.sign) =. boat.yoke
?^ p.sign ?^ p.sign (~(del by boat.yoke) sub-key)
%- ~(del by outbound.watches.yoke)
[agent-wire dock]
%+ ~(jab by outbound.watches.yoke) [agent-wire dock]
|= [acked=? =path]
=. .
?. acked
.
%- =/ =tape
"{<agent-name>}: received 2nd watch-ack on {<wire dock path>}"
(slog leaf+tape ~)
.
[& path]
:: ::
=^ maybe-tang ap-core %+ ~(jab by boat.yoke) sub-key
%+ ap-ingest ~ |. |= val=[acked=? =path]
(on-agent:ap-agent-core agent-wire sign) %. val(acked &)
:: if failed %fact handling, kill subscription %^ trace &(odd.veb.bug.state acked.val)
leaf/"{<agent-name>} 2nd watch-ack on {<val>}" ~
:: ::
=? ap-core ?=(%fact -.sign) ingest-and-check-error
(ap-update-subscription =(~ maybe-tang) p.dock q.dock agent-wire) ==
?^ maybe-tang ::
(ap-error -.sign leaf/"closing subscription" u.maybe-tang) ++ on-missing
ap-core %. ap-core
%+ trace odd.veb.bug.state :~
leaf+"{<agent-name>}: got {<-.sign>} for nonexistent subscription"
leaf+"{<dock>}: {<[nonce=nonce agent-wire]>}"
>wire=wire<
==
::
++ on-weird-kick
%. run-sign
%+ trace odd.veb.bug.state :~
leaf+"{<agent-name>}: got %kick for nonexistent subscription"
leaf+"{<dock>}: {<agent-wire>}"
>wire=wire<
==
::
++ on-bad-nonce
|= stored-nonce=@
%. ap-core
%- slog :~
=/ nonces [expected=stored-nonce got=nonce]
=/ ok |(?=(?(%fact %kick) -.sign) =(~ p.sign))
leaf+"{<agent-name>}: stale {<-.sign>} {<nonces>} ok={<ok>}"
::
leaf+"{<dock>}: {<agent-wire>}"
>wire=wire<
==
::
++ ingest-and-check-error
^+ ap-core
=^ tan ap-core ingest
?~(tan ap-core (ap-error -.sign leaf/"take {<-.sign>} failed" u.tan))
--
:: +ap-install: install wrapper. :: +ap-install: install wrapper.
:: ::
++ ap-install ++ ap-install
@ -1499,24 +1745,18 @@
:: ::
++ ap-silent-delete ++ ap-silent-delete
^+ ap-core ^+ ap-core
:: ap-core(bitt.yoke (~(del by bitt.yoke) agent-duct))
%= ap-core
inbound.watches.yoke
(~(del by inbound.watches.yoke) agent-duct)
==
:: +ap-load-delete: load delete. :: +ap-load-delete: load delete.
:: ::
++ ap-load-delete ++ ap-load-delete
^+ ap-core ^+ ap-core
:: ::
=/ maybe-incoming =/ maybe-incoming (~(get by bitt.yoke) agent-duct)
(~(get by inbound.watches.yoke) agent-duct)
?~ maybe-incoming ?~ maybe-incoming
ap-core ap-core
:: ::
=/ incoming u.maybe-incoming =/ incoming u.maybe-incoming
=. inbound.watches.yoke =. bitt.yoke (~(del by bitt.yoke) agent-duct)
(~(del by inbound.watches.yoke) agent-duct)
:: ::
=^ maybe-tang ap-core =^ maybe-tang ap-core
%+ ap-ingest ~ |. %+ ap-ingest ~ |.
@ -1550,12 +1790,76 @@
:: Must process leave first in case kick handler rewatches. :: Must process leave first in case kick handler rewatches.
:: ::
++ ap-kill-down ++ ap-kill-down
|= [=wire =dock] |= [sub-wire=wire =dock]
^+ ap-core ^+ ap-core
::
=. ap-core =. ap-core
(ap-pass wire %agent dock %leave ~) :: we take care to include the nonce in the "kernel-facing" wire
(ap-pass wire %huck dock %b %huck `sign-arvo`[%gall %unto %kick ~]) ::
(ap-pass (ap-nonce-wire sub-wire dock) %agent dock %leave ~)
(ap-pass sub-wire %huck dock %b %huck `sign-arvo`[%gall %unto %kick ~])
:: +ap-doff: kill old-style outgoing subscriptions
::
++ ap-doff
|= ship=(unit ship)
^+ ap-core
=/ subs ~(tap in ~(key by boat.yoke))
|- ^+ ap-core
?~ subs ap-core
=+ [wyr dok]=i.subs
?: &(?=(^ ship) !=(u.ship ship.dok))
$(subs t.subs)
:: if we haven't created new-style (nonced) subscriptions yet,
:: kick the old-style (nonceless) one that's in use right now.
::
::NOTE yes, still safe for pre-release ships with nonce=1,
:: this makes a new flow but cleans it up right away.
::
=? ap-core (gte 1 (~(got by boar.yoke) wyr dok))
(ap-pass wyr %agent dok %leave ~)
$(subs t.subs)
:: +ap-rake: clean up the dead %leave's
::
++ ap-rake
|= all=?
=/ subs ~(tap in ~(key by boat.yoke))
|^ ^+ ap-core
?~ subs ap-core
=/ [=wire =dock] i.subs
=/ non (~(got by boar.yoke) wire dock)
?: &(!all =(0 non))
$(subs t.subs)
?~ per=(scry-peer-state p.dock)
$(subs t.subs)
::
=/ dud=(set duct)
=/ mod=^wire
:* %gall %use agent-name run-nonce.yoke
%out (scot %p p.dock) q.dock
'0' wire
==
%- ~(rep by by-duct.ossuary.u.per)
|= [[=duct =bone] out=(set duct)]
^+ out
?. ?& ?=([* [%gall %use @ @ %out @ @ @ *] *] duct)
=(mod i.t.duct(i.t.t.t.t.t.t.t '0'))
==
out
?: (~(has in closing.u.per) bone) out
~> %slog.0^leaf+"gall: rake {<i.t.duct>}"
(~(put in out) duct)
::
%- ap-move
(turn ~(tap in dud) |=(d=duct [+.d %pass -.d %a %cork p.dock]))
::
++ scry-peer-state
|= her=ship
~+ ^- (unit peer-state:ames)
=/ sky (rof [~ ~] %ax [our %$ da+now] /peers/(scot %p her))
?: |(?=(~ sky) ?=(~ u.sky))
~
=/ sat !<(ship-state:ames q.u.u.sky)
?>(?=(%known -.sat) (some +.sat))
--
:: +ap-mule: run virtualized with intercepted scry, preserving type :: +ap-mule: run virtualized with intercepted scry, preserving type
:: ::
:: Compare +mute and +mule. Those pass through scry, which :: Compare +mute and +mule. Those pass through scry, which
@ -1622,10 +1926,9 @@
:: ::
=. agent.yoke &++.p.result =. agent.yoke &++.p.result
=/ moves (zing (turn -.p.result ap-from-internal)) =/ moves (zing (turn -.p.result ap-from-internal))
=. inbound.watches.yoke =. bitt.yoke (ap-handle-kicks moves)
(ap-handle-kicks moves)
(ap-handle-peers moves) (ap-handle-peers moves)
:: +ap-handle-kicks: handle cancels of inbound.watches :: +ap-handle-kicks: handle cancels of bitt.watches
:: ::
++ ap-handle-kicks ++ ap-handle-kicks
~/ %ap-handle-kicks ~/ %ap-handle-kicks
@ -1641,8 +1944,8 @@
:: ::
=/ quit-map=bitt =/ quit-map=bitt
(malt (turn quits |=(=duct [duct *[ship path]]))) (malt (turn quits |=(=duct [duct *[ship path]])))
(~(dif by inbound.watches.yoke) quit-map) (~(dif by bitt.yoke) quit-map)
:: +ap-handle-peers: handle new outbound.watches :: +ap-handle-peers: handle new boat.watches
:: ::
++ ap-handle-peers ++ ap-handle-peers
~/ %ap-handle-peers ~/ %ap-handle-peers
@ -1656,34 +1959,59 @@
?: ?=([* %pass * %g %deal * * %leave *] move) ?: ?=([* %pass * %g %deal * * %leave *] move)
=/ =wire p.move.move =/ =wire p.move.move
?> ?=([%use @ @ %out @ @ *] wire) ?> ?=([%use @ @ %out @ @ *] wire)
=/ short-wire t.t.t.t.t.t.wire
=/ =dock [q.p q]:q.move.move =/ =dock [q.p q]:q.move.move
=. outbound.watches.yoke =/ sys-wire=^wire (scag 6 `^wire`wire)
(~(del by outbound.watches.yoke) [short-wire dock]) =/ sub-wire=^wire (slag 6 `^wire`wire)
::
?. (~(has by boat.yoke) sub-wire dock)
%. $(moves t.moves)
%^ trace odd.veb.bug.state
leaf/"gall: {<agent-name>} missing subscription, got %leave" ~
=/ nonce=@ (~(got by boar.yoke) sub-wire dock)
=. p.move.move
%+ weld sys-wire
(ap-nonce-wire sub-wire dock)
=: boat.yoke (~(del by boat.yoke) [sub-wire dock])
boar.yoke (~(del by boar.yoke) [sub-wire dock])
==
:: if nonce = 0, this was a pre-nonce subscription so later
:: subscriptions need to start subscribing on the next nonce
::
=? sub-nonce.yoke =(nonce 0) +(sub-nonce.yoke)
$(moves t.moves, new-moves [move new-moves]) $(moves t.moves, new-moves [move new-moves])
?. ?=([* %pass * %g %deal * * ?(%watch %watch-as) *] move) ?. ?=([* %pass * %g %deal * * ?(%watch %watch-as) *] move)
$(moves t.moves, new-moves [move new-moves]) $(moves t.moves, new-moves [move new-moves])
=/ =wire p.move.move =/ =wire p.move.move
?> ?=([%use @ @ %out @ @ *] wire) ?> ?=([%use @ @ %out @ @ *] wire)
=/ short-wire t.t.t.t.t.t.wire =/ sys-wire=^wire (scag 6 `^wire`wire)
=/ =dock [q.p q]:q.move.move =/ sub-wire=^wire (slag 6 `^wire`wire)
=/ =path =/ [=dock =deal] [[q.p q] r]:q.move.move
?- -.r.q.move.move ::
%watch path.r.q.move.move ?: (~(has by boat.yoke) sub-wire dock)
%watch-as path.r.q.move.move
==
?: (~(has by outbound.watches.yoke) short-wire dock)
=. ap-core =. ap-core
=/ =tang =/ =tang
~[leaf+"subscribe wire not unique" >agent-name< >short-wire< >dock<] ~[leaf+"subscribe wire not unique" >agent-name< >sub-wire< >dock<]
=/ have =/ have (~(got by boat.yoke) sub-wire dock)
(~(got by outbound.watches.yoke) short-wire dock)
%- (slog >out=have< tang) %- (slog >out=have< tang)
(ap-error %watch-not-unique tang) :: reentrant, maybe bad? (ap-error %watch-not-unique tang) :: reentrant, maybe bad?
$(moves t.moves) $(moves t.moves)
=. outbound.watches.yoke ::
(~(put by outbound.watches.yoke) [short-wire dock] [| path]) ::NOTE 0-check guards against pre-release bug
$(moves t.moves, new-moves [move new-moves]) =? p.move.move !=(0 sub-nonce.yoke)
(weld sys-wire [(scot %ud sub-nonce.yoke) sub-wire])
%_ $
moves t.moves
new-moves [move new-moves]
sub-nonce.yoke +(sub-nonce.yoke)
::
boat.yoke
%+ ~(put by boat.yoke) [sub-wire dock]
:- acked=|
path=?+(-.deal !! %watch path.deal, %watch-as path.deal)
::
boar.yoke
(~(put by boar.yoke) [sub-wire dock] sub-nonce.yoke)
==
-- --
-- --
:: +call: request :: +call: request
@ -1726,6 +2054,10 @@
%jolt mo-abet:(mo-jolt:mo-core dude.task our desk.task) %jolt mo-abet:(mo-jolt:mo-core dude.task our desk.task)
%idle mo-abet:(mo-idle:mo-core dude.task) %idle mo-abet:(mo-idle:mo-core dude.task)
%nuke mo-abet:(mo-nuke:mo-core dude.task) %nuke mo-abet:(mo-nuke:mo-core dude.task)
%doff mo-abet:(mo-doff:mo-core +.task)
%rake mo-abet:(mo-rake:mo-core +.task)
%spew mo-abet:(mo-spew:mo-core veb.task)
%sift mo-abet:(mo-sift:mo-core dudes.task)
%trim [~ gall-payload] %trim [~ gall-payload]
%vega [~ gall-payload] %vega [~ gall-payload]
== ==
@ -1797,6 +2129,28 @@
acc acc
(~(put in acc) [dude -.agent.yoke]) (~(put in acc) [dude -.agent.yoke])
:: ::
?: ?& =(%f care)
=(~ path)
=([%$ %da now] coin)
=(our ship)
==
:+ ~ ~
:- %nonces !> ^- (map dude @)
(~(run by yokes.state) |=(yoke sub-nonce))
::
?: ?& =(%n care)
?=([@ @ ^] path)
=([%$ %da now] coin)
=(our ship)
==
?~ yok=(~(get by yokes.state) dap)
[~ ~]
=/ [=^ship =term =wire]
[(slav %p i.path) i.t.path t.t.path]
?~ nonce=(~(get by boar.u.yok) [wire ship term])
[~ ~]
[~ ~ atom+!>(u.nonce)]
::
?. =(our ship) ?. =(our ship)
~ ~
?. =([%$ %da now] coin) ?. =([%$ %da now] coin)

View File

@ -306,28 +306,6 @@
%^ poke-watch hen %azimuth %^ poke-watch hen %azimuth
%+ fall node.tac %+ fall node.tac
(need (de-purl:html 'http://eth-mainnet.urbit.org:8545')) (need (de-purl:html 'http://eth-mainnet.urbit.org:8545'))
=. +>.$
:: get everything from /app/azimuth because jael subscriptions
:: seem to be flaky for now
::
?: &
%- curd =< abet
(sources:~(feel su hen now pki etn) ~ [%| %azimuth])
::
?- (clan:title our)
%czar
%- curd =< abet
(sources:~(feel su hen now pki etn) ~ [%| %azimuth])
::
*
=. +>.$
%- curd =< abet
%+ sources:~(feel su hen now pki etn)
(silt (turn spon-points head))
[%| %azimuth]
%- curd =< abet
(sources:~(feel su hen now pki etn) ~ [%& (need spon-ship)])
==
:: ::
=. moz =. moz
%+ weld moz %+ weld moz
@ -391,7 +369,7 @@
:: [%listen whos=(set ship) =source] :: [%listen whos=(set ship) =source]
:: ::
%listen %listen
~& [%jael-listen whos source]:tac :: %- (slog leaf+"jael: listen {<whos.tac>} {<source.tac>}" ~)
%- curd =< abet %- curd =< abet
(sources:~(feel su hen now pki etn) [whos source]:tac) (sources:~(feel su hen now pki etn) [whos source]:tac)
:: ::

View File

@ -0,0 +1,15 @@
/- spider, *dice
/+ strand, strandio, naive, dice
=, strand=strand:spider
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
=/ url=tape
?~ lur=!<((unit tape) arg)
"https://bootstrap.urbit.org/mainnet.azimuth-snapshot"
u.lur
;< =cord bind:m (fetch-cord:strandio url)
=+ ;;(snap=snap-state (cue cord))
;< ~ bind:m (poke-our:strandio %azimuth %azimuth-poke !>([%load snap]))
(pure:m !>(~))

View File

@ -25,17 +25,17 @@
|= if=@if |= if=@if
=/ m (strand ,~) =/ m (strand ,~)
^- form:m ^- form:m
=/ collector-app `dock`[~zod %dns-collector] =/ collector-app `dock`[~deg %dns-collector]
;< good=? bind:m (self-check-http:libdns |+if 2) ;< good=? bind:m (self-check-http:libdns |+if 2)
?. good ?. good
%+ strand-fail:strandio %bail-early-self-check %+ strand-fail:strandio %bail-early-self-check
[>"couldn't access ship on port 80"< ~] [>"couldn't access ship on port 80"< ~]
;< our=@p bind:m get-our:strandio
;< ~ bind:m (watch:strandio /response collector-app /(scot %p our))
;< ~ bind:m (poke:strandio collector-app %dns-address !>([%if if])) ;< ~ bind:m (poke:strandio collector-app %dns-address !>([%if if]))
=/ msg=cord =/ msg=cord
(cat 3 'request for DNS sent to ' (scot %p p:collector-app)) (cat 3 'request for DNS sent to ' (scot %p p:collector-app))
;< ~ bind:m (app-message:strandio %dns msg ~) ;< ~ bind:m (app-message:strandio %dns msg ~)
;< our=@p bind:m get-our:strandio
;< ~ bind:m (watch:strandio /sub collector-app /(scot %p our))
=/ msg=cord =/ msg=cord
(cat 3 'awaiting response from ' (scot %p p:collector-app)) (cat 3 'awaiting response from ' (scot %p p:collector-app))
;< ~ bind:m (app-message:strandio %dns msg ~) ;< ~ bind:m (app-message:strandio %dns msg ~)
@ -45,7 +45,7 @@
=/ m (strand ,~) =/ m (strand ,~)
^- form:m ^- form:m
;< our=ship bind:m get-our:strandio ;< our=ship bind:m get-our:strandio
;< =cage bind:m (take-fact:strandio /(scot %p our)) ;< =cage bind:m (take-fact:strandio /response)
?> ?=(%dns-binding p.cage) ?> ?=(%dns-binding p.cage)
=/ =binding:dns !<(binding:dns q.cage) =/ =binding:dns !<(binding:dns q.cage)
;< good=? bind:m (turf-confirm-install:libdns turf.binding) ;< good=? bind:m (turf-confirm-install:libdns turf.binding)

View File

@ -1,21 +1,33 @@
:: Test that these hints do not crash the runtime :: Test that these hints do not crash the runtime
:: there is no need to include the hints for dynamic %bout :: there is no need to include a test for dynamic %bout
:: since all hoon tests exersize dynamic %bout :: since all hoon tests exersize dynamic %bout
|% |%
:: these test that the hilt-trace hints :: test that these trace hints
:: are safe to run or ignore :: are safe to run or ignore
++ test-hela-hilt ++ test-hilt-hela
~> %hela ~> %hela
~ ~
++ test-nara-hilt ++ test-hint-hela
~> %hela.[1 leaf+"test-hint-hela ~"]
~
++ test-hilt-nara
~> %nara ~> %nara
~ ~
:: these test that the hint-trace hints ++ test-hint-nara
:: are safe to run or ignore ~> %nara.[1 leaf+"test-hint-nara ~"]
++ test-hela-hint
~> %hela.[1 leaf+"test-hela-trace-hint"]
~ ~
++ test-nara-hint :: test that theses bytecode-report hints
~> %nara.[1 leaf+"test-nara-trace-hint"] :: are safe to run or ignore
++ test-hilt-xray
~> %xray
~
++ test-hint-xray
~> %xray.[1 leaf+"test-hint-xray ~"]
~
:: test that the hilt bout hint
:: is safe to run or ignore
++ test-hilt-bout
~> %bout
~ ~
-- --

504
pkg/arvo/tests/sys/grq.hoon Normal file
View File

@ -0,0 +1,504 @@
:: test gall subscription nonce incrementation and ames flow killing
::
/+ *test, v=test-ames-gall
|%
++ test-watch
%- run-chain
|. :- %|
=+ nec-bud:v
:: uncomment to turn on verbose debug output
::=^ * ames.nec
:: (ames-call:v ames.nec ~[/none] [%spew ~[%msg %snd %rcv %odd]] *roof)
::=^ * ames.bud
:: (ames-call:v ames.bud ~[/none] [%spew ~[%msg %snd %rcv %odd]] *roof)
:: poke %sub to tell it to subscribe
=/ =task:gall [%deal [~nec ~nec] %sub %poke watch+!>(~bud)]
=^ t1 gall.nec
%: gall-check-call:v gall.nec
[~1111.1.1 0xdead.beef *roof]
[~[/foo] task]
:~ :- ~[/foo] [%give %unto %poke-ack ~]
:- ~[/init]
:* %pass /use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
[%g %deal [~nec ~bud] %pub %watch /foo]
== ==
==
:- t1 |. :- %|
:: handle gall passing the %watch to itself, which passes to ames
=^ t2 gall.nec
%: gall-check-call:v gall.nec
[~1111.1.1 0xdead.beef *roof]
:- ~[/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud /init]
[%deal [~nec ~bud] %pub %watch /foo]
:~ :- ~[/init] [%pass /sys/lag %a %heed ~bud]
:- ~[/init] [%pass /sys/era %j %public-keys (sy ~bud ~)]
:- ~[/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud /init]
[%pass /sys/way/~bud/pub %a %plea ~bud %g /ge/pub [%0 %s /foo]]
==
==
:- t2 |. :- %|
:: subscriber ames handles %plea from gall, gives a packet to vere
=^ t3 ames.nec
%: ames-check-call:v ames.nec
[~1111.1.1 0xdead.beef *roof]
:- :~ /sys/way/~bud/pub
/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
/init
==
[%plea ~bud %g /ge/pub [%0 %s /foo]]
:~ :- ~[//unix]
:* %give %send [%& ~bud]
0xae59.5b29.277b.22c1.20b7.a8db.9086.46df.31bd.f9bc.
2633.7300.17d4.f5fc.8be5.8bfe.5c9d.36d9.2ea1.7cb3.
8a00.0200.0132.8fd4.f000
==
:- ~[/ames] [%pass /pump/~bud/0 %b %wait ~1111.1.1..00.00.01]
==
==
:- t3 |. :- %|
:: publisher ames hears %watch, passes to gall
=^ t4 ames.bud
%: ames-check-call:v ames.bud
[~1111.1.2 0xbeef.dead *roof]
:- ~[//unix]
:* %hear [%& ~nec]
0xae59.5b29.277b.22c1.20b7.a8db.9086.46df.31bd.f9bc.
2633.7300.17d4.f5fc.8be5.8bfe.5c9d.36d9.2ea1.7cb3.
8a00.0200.0132.8fd4.f000
==
:~ :- ~[//unix] [%pass /qos %d %flog %text "; ~nec is your neighbor"]
:- ~[//unix]
[%pass /bone/~nec/0/1 %g %plea ~nec %g /ge/pub [%0 %s /foo]]
==
==
:- t4 |. :- %|
:: publisher gall hears %watch from ames, passes to itself
=^ t5 gall.bud
%: gall-check-call:v gall.bud
[~1111.1.2 0xbeef.dead *roof]
:- ~[/bone/~nec/0/1 //unix]
[%plea ~nec %g /ge/pub [%0 %s /foo]]
:~ :- ~[/init] [%pass /sys/lag %a %heed ~nec]
:- ~[/init] [%pass /sys/era %j %public-keys (sy ~nec ~)]
:- ~[/bone/~nec/0/1 //unix]
[%pass /sys/req/~nec/pub %g %deal [~nec ~bud] %pub %watch /foo]
==
==
:- t5 |. :- %|
:: publisher gall runs %pub with %watch, gives ack to itself
=^ t6 gall.bud
%: gall-check-call:v gall.bud
[~1111.1.2 0xbeef.dead *roof]
:- ~[/sys/req/~nec/pub /bone/~nec/0/1 //unix]
[%deal [~nec ~bud] %pub %watch /foo]
:~ :- ~[/sys/req/~nec/pub /bone/~nec/0/1 //unix]
[%give %unto %watch-ack ~]
==
==
:- t6 |. :- %|
:: gall gives ack to ames
=^ t7 gall.bud
%: gall-check-take:v gall.bud
[~1111.1.2 0xbeef.dead *roof]
:+ /sys/req/~nec/pub ~[/bone/~nec/0/1 //unix]
[%gall %unto %watch-ack ~]
:~ :- ~[/bone/~nec/0/1 //unix] [%give %done ~]
==
==
:- t7 |. :- %|
:: publisher ames hears ack from gall, sends over the network
=^ t8 ames.bud
%: ames-check-take:v ames.bud
[~1111.1.2 0xbeef.dead *roof]
:+ /bone/~nec/0/1 ~[//unix]
[%gall %done ~]
:~ :- ~[//unix]
:* %give %send [%& ~nec]
0x2.0219.8100.0485.5530.3c88.9068.3cc6.484e.
2d9d.076e.6d00.0100.0223.9ae9.5000
== ==
==
:- t8 |. :- %|
:: subscriber ames hears watch-ack packet, gives to gall
=^ t9 ames.nec
%: ames-check-call:v ames.nec
[~1111.1.3 0xdead.beef *roof]
:- ~[//unix]
:* %hear [%& ~bud]
0x2.0219.8100.0485.5530.3c88.9068.3cc6.484e.
2d9d.076e.6d00.0100.0223.9ae9.5000
==
:~ :- ~[//unix] [%pass /qos %d %flog %text "; ~bud is your neighbor"]
:- :~ /sys/way/~bud/pub
/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
/init
==
[%give %done ~]
:- ~[/ames] [%pass /pump/~bud/0 %b %rest ~1111.1.1..00.00.01]
==
==
:- t9 |. :- %|
:: gall gives %done to itself
=^ t10 gall.nec
%: gall-check-take:v gall.nec
[~1111.1.3 0xdead.beef *roof]
:+ /sys/way/~bud/pub
~[/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud /init]
[%ames %done ~]
:~ :- ~[/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud /init]
[%give %unto %watch-ack ~]
==
==
:- t10 |. :- %|
:: gall gives watch-ack to itself
=^ t11 gall.nec
%: gall-check-take:v gall.nec
[~1111.1.3 0xdead.beef *roof]
:+ /use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
~[/init]
[%gall %unto %watch-ack ~]
~
==
:- t11 |. :- %|
:: start the clog and kick process; give clog to publisher gall
=^ t12 gall.bud
%: gall-check-take:v gall.bud
[~1111.1.4 0xbeef.dead *roof]
:+ /sys/lag ~[/init]
[%ames %clog ~nec]
:~ :- ~[/sys/req/~nec/pub /bone/~nec/0/1 //unix]
[%give %unto %kick ~]
==
==
:- t12 |. :- %|
:: gall gives %kick %boon to ames
=^ t13 gall.bud
%: gall-check-take:v gall.bud
[~1111.1.4 0xbeef.dead *roof]
:+ /sys/req/~nec/pub ~[/bone/~nec/0/1 //unix]
[%gall %unto %kick ~]
:~ :- ~[/bone/~nec/0/1 //unix] [%give %boon %x ~]
==
==
:- t13 |. :- %|
:: ames gives kick over the network
=^ t14 ames.bud
%: ames-check-take:v ames.bud
[~1111.1.4 0xbeef.dead *roof]
:+ /bone/~nec/0/1 ~[//unix]
[%gall %boon %x ~]
:~ :- ~[//unix]
:* %give %send [%& ~nec]
0xa1fc.cd35.c730.9a00.07e0.90a2.f87c.3657.935e.
4ca0.801d.3ddc.d400.0100.0223.bc18.1000
==
:- ~[/ames] [%pass /pump/~nec/1 %b %wait ~1111.1.4..00.00.01]
==
==
:- t14 |. :- %|
:: subscriber ames receives kick, gives to gall and gives ack to unix
=^ t15 ames.nec
%: ames-check-call:v ames.nec
[~1111.1.5 0xdead.beef *roof]
:- ~[//unix]
:* %hear [%& ~bud]
0xa1fc.cd35.c730.9a00.07e0.90a2.f87c.3657.935e.
4ca0.801d.3ddc.d400.0100.0223.bc18.1000
==
:~ :- :~ /sys/way/~bud/pub
/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
/init
==
[%give %boon %x ~]
:- ~[//unix]
:* %give %send [%& ~bud]
0xfe.e208.da00.0491.bf7f.9594.2ddc.0948.
9de0.3906.b678.6e00.0200.0132.e55d.5000
== ==
==
:- t15 |. :- %|
:: subscriber gall receives kick %boon from ames, gives to self
=^ t16 gall.nec
%: gall-check-take:v gall.nec
[~1111.1.5 0xdead.beef *roof]
:+ /sys/way/~bud/pub
~[/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud /init]
[%ames %boon %x ~]
:~ :- ~[/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud /init]
[%give %unto %kick ~]
:- ~[/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud /init]
[%pass /sys/way/~bud/pub %a %cork ~bud]
==
==
:: subscriber gall receives %kick from itself
=^ t17 gall.nec
%: gall-check-take:v gall.nec
[~1111.1.5 0xdead.beef *roof]
:+ /use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
~[/init]
[%gall %unto %kick ~]
:~ :- ~[/init]
:* %pass /use/sub/0w1.d6Isf/out/~bud/pub/2/sub-foo/~bud
[%g %deal [~nec ~bud] %pub %watch /foo]
== ==
==
:- t17 |. :- %|
:: gall receives %deal %watch from itself, passes to ames
=^ t18 gall.nec
%: gall-check-call:v gall.nec
[~1111.1.5 0xdead.beef *roof]
:- ~[/use/sub/0w1.d6Isf/out/~bud/pub/2/sub-foo/~bud /init]
[%deal [~nec ~bud] %pub %watch /foo]
:~ :- ~[/use/sub/0w1.d6Isf/out/~bud/pub/2/sub-foo/~bud /init]
[%pass /sys/way/~bud/pub %a %plea ~bud %g /ge/pub [%0 %s /foo]]
==
==
:- t18 |. :- %|
:: subscriber ames sends new %watch
=^ t19 ames.nec
%: ames-check-call:v ames.nec
[~1111.1.5 0xdead.beef *roof]
:- :~ /sys/way/~bud/pub
/use/sub/0w1.d6Isf/out/~bud/pub/2/sub-foo/~bud
/init
==
[%plea ~bud %g /ge/pub [%0 %s /foo]]
:~ :- ~[//unix]
:* %give %send [%& ~bud]
0xfe.9174.6d7c.e042.4ea7.cf3c.08da.3acf.68ec.3bd1.1f2c.abfe.f500.
1897.c42e.a3ec.2159.86d6.e2f1.b344.9d06.b600.0200.0132.ebe7.8800
==
:- ~[/ames] [%pass /pump/~bud/4 %b %wait ~1111.1.5..00.00.01]
==
==
:- t19 |. :- %|
:: subscriber ames sends %cork
=^ t20 ames.nec
%: ames-check-call:v ames.nec
[~1111.1.5 0xdead.beef *roof]
:- :~ /sys/way/~bud/pub
/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
/init
==
[%cork ~bud]
:~ :- ~[//unix]
:* %give %send [%& ~bud]
0xb.130c.ab37.ca24.49cd.aecb.23ba.70f1.6f1c.4d00.124e.c9a5.
3413.3843.d81c.47c4.7040.6e62.3700.0200.0132.e1ab.9000
==
:- ~[/ames] [%pass /pump/~bud/0 %b %wait ~1111.1.5..00.02.00]
==
==
:: publisher ames hears %kick ack
:- t20 |. :- %|
=^ t21 ames.bud
%: ames-check-call:v ames.bud
[~1111.1.6 0xbeef.dead *roof]
:- ~[//unix]
:* %hear [%& ~nec]
0xfe.e208.da00.0491.bf7f.9594.2ddc.0948.
9de0.3906.b678.6e00.0200.0132.e55d.5000
==
:~ :- ~[/ames] [%pass /pump/~nec/1 %b %rest ~1111.1.4..00.00.01]
==
==
:: publisher ames hears new %watch
:- t21 |. :- %|
=^ t22 ames.bud
%: ames-check-call:v ames.bud
[~1111.1.7 0xbeef.dead *roof]
:- ~[//unix]
:* %hear [%& ~nec]
0xfe.9174.6d7c.e042.4ea7.cf3c.08da.3acf.68ec.3bd1.1f2c.abfe.f500.
1897.c42e.a3ec.2159.86d6.e2f1.b344.9d06.b600.0200.0132.ebe7.8800
==
:~ :- ~[//unix]
[%pass /bone/~nec/0/5 %g %plea ~nec %g /ge/pub [%0 %s /foo]]
==
==
:: publisher gall hears new %watch, passes to self
:- t22 |. :- %|
=^ t23 gall.bud
%: gall-check-call:v gall.bud
[~1111.1.7 0xbeef.dead *roof]
:- ~[/bone/~nec/0/5 //unix]
[%plea ~nec %g /ge/pub [%0 %s /foo]]
:~ :- ~[/bone/~nec/0/5 //unix]
[%pass /sys/req/~nec/pub %g %deal [~nec ~bud] %pub %watch /foo]
==
==
:: publisher gall runs :pub's +on-watch, gives ack to self
:- t23 |. :- %|
=^ t24 gall.bud
%: gall-check-call:v gall.bud
[~1111.1.7 0xbeef.dead *roof]
:- ~[/sys/req/~nec/pub /bone/~nec/0/5 //unix]
[%deal [~nec ~bud] %pub %watch /foo]
:~ :- ~[/sys/req/~nec/pub /bone/~nec/0/5 //unix]
[%give %unto %watch-ack ~]
==
==
:: publisher gall hears %watch-ack, gives to ames
:- t24 |. :- %|
=^ t25 gall.bud
%: gall-check-take:v gall.bud
[~1111.1.7 0xbeef.dead *roof]
:+ /sys/req/~nec/pub ~[/bone/~nec/0/5 //unix]
[%gall %unto %watch-ack ~]
:~ :- ~[/bone/~nec/0/5 //unix] [%give %done ~]
==
==
:: publisher ames hears done from gall, sends over the network
:- t25 |. :- %|
=^ t26 ames.bud
%: ames-check-take:v ames.bud
[~1111.1.7 0xbeef.dead *roof]
:+ /bone/~nec/0/5 ~[//unix]
[%gall %done ~]
:~ :- ~[//unix]
:* %give %send [%& ~nec]
0x5f5.c27c.c400.0587.8b0d.0a5d.eb8e.39fa.
49f4.4848.bfa6.f600.0100.0223.c98c.8800
== ==
==
:: publisher ames hears %cork, passes to itself
:- t26 |. :- %|
=^ t27 ames.bud
%: ames-check-call:v ames.bud
[~1111.1.8 0xbeef.dead *roof]
:- ~[//unix]
:* %hear [%& ~nec]
0xb.130c.ab37.ca24.49cd.aecb.23ba.70f1.6f1c.4d00.124e.c9a5.
3413.3843.d81c.47c4.7040.6e62.3700.0200.0132.e1ab.9000
==
:~ :- ~[//unix] [%pass /bone/~nec/0/1 %a %plea ~nec [%a /close ~]]
==
==
:- t27 |. :- %|
:: publisher ames hear cork plea from self, give %done to self
=^ t28 ames.bud
%: ames-check-call:v ames.bud
[~1111.1.8 0xbeef.dead *roof]
:- ~[/bone/~nec/0/1 //unix]
[%plea ~nec [%a /close ~]]
:~ :- ~[/bone/~nec/0/1 //unix] [%give %done ~]
==
==
:: publisher ames hears cork done from self, sends ack packet
:- t28 |. :- %|
=^ t29 ames.bud
%: ames-check-take:v ames.bud
[~1111.1.8 0xbeef.dead *roof]
:+ /bone/~nec/0/1
~[//unix]
[%ames %done ~]
:~ :- ~[//unix]
:* %give %send [%& ~nec]
0x5f.f966.8e00.0449.bdec.9006.c7e5.1237.
1d87.53fe.d7bb.ad00.0100.0223.c6a8.5800
== ==
==
:: subscriber ames hears %watch-ack, gives to gall
:- t29 |. :- %|
=^ t30 ames.nec
%: ames-check-call:v ames.nec
[~1111.1.9 0xdead.beef *roof]
:- ~[//unix]
:* %hear [%& ~bud]
0x5f5.c27c.c400.0587.8b0d.0a5d.eb8e.39fa.
49f4.4848.bfa6.f600.0100.0223.c98c.8800
==
:~ :- :~ /sys/way/~bud/pub
/use/sub/0w1.d6Isf/out/~bud/pub/2/sub-foo/~bud
/init
==
[%give %done ~]
:- ~[/ames] [%pass /pump/~bud/4 %b %rest ~1111.1.5..00.00.01]
==
==
:: subscriber gall hears new %watch-ack from ames, gives to self
:- t30 |. :- %|
=^ t31 gall.nec
%: gall-check-take:v gall.nec
[~1111.1.9 0xdead.beef *roof]
:+ /sys/way/~bud/pub
:~ /use/sub/0w1.d6Isf/out/~bud/pub/2/sub-foo/~bud
/init
==
[%ames %done ~]
:~ :- :~ /use/sub/0w1.d6Isf/out/~bud/pub/2/sub-foo/~bud
/init
==
[%give %unto %watch-ack ~]
==
==
:: subscriber gall hears new %watch-ack from self, tells :sub
:- t31 |. :- %|
=^ t32 gall.nec
%: gall-check-take:v gall.nec
[~1111.1.9 0xdead.beef *roof]
:+ /use/sub/0w1.d6Isf/out/~bud/pub/2/sub-foo/~bud
~[/init]
[%gall %unto %watch-ack ~]
~
==
:: subscriber ames hears %cork ack
:- t32 |. :- %|
=^ t33 ames.nec
%: ames-check-call:v ames.nec
[~1111.1.10 0xdead.beef *roof]
:- ~[//unix]
:* %hear [%& ~bud]
0x5f.f966.8e00.0449.bdec.9006.c7e5.1237.
1d87.53fe.d7bb.ad00.0100.0223.c6a8.5800
==
:~ :- :~ /sys/way/~bud/pub
/use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
/init
==
[%give %done ~]
:- ~[/ames] [%pass /pump/~bud/0 %b %rest ~1111.1.5..00.02.00]
==
==
:: subscriber gall hears %cork ack from ames
:- t33 |. :- %|
=^ t34 gall.nec
%: gall-check-take:v gall.nec
[~1111.1.10 0xdead.beef *roof]
:+ /sys/way/~bud/pub
:~ /use/sub/0w1.d6Isf/out/~bud/pub/1/sub-foo/~bud
/init
==
[%ames %done ~]
~
==
:- t34 |. :- %&
;: weld
%+ expect-eq
!> (sy 0 ~)
!> =< corked
%: ames-scry-peer:v
ames.nec
[~1111.1.10 0xdead.beef *roof]
[~nec ~bud]
==
::
%+ expect-eq
!> (sy 1 ~)
!> =< corked
%: ames-scry-peer:v
ames.bud
[~1111.1.8 0xbeef.dead *roof]
[~bud ~nec]
==
::
%+ expect-eq
!> 2
!> %: gall-scry-nonce:v
gall.nec
[~1111.1.10 0xdead.beef *roof]
~nec %sub
[~bud %pub /sub-foo/~bud]
==
==
--

View File

@ -353,10 +353,14 @@
!> [~[/g/talk] %give %boon [%post 'first1']] !> [~[/g/talk] %give %boon [%post 'first1']]
!> (snag 0 `(list move:ames)`moves6) !> (snag 0 `(list move:ames)`moves6)
== ==
:: +test-comet-message-flow: galaxy<->comet comms
::
:: same as test-message-flow, but ~nec will send a sendkeys packet to
:: request comet's self-attestation directly
:: ::
++ test-comet-message-flow ^- tang ++ test-comet-message-flow ^- tang
:: same as test-message-flow, but ~nec will send a sendkeys packet to request ::=^ * nec (call nec ~[//nemo] %spew ~[%snd %rcv %odd %msg])
:: comet's self-attestation directly ::=^ * comet (call comet ~[//nemo] %spew ~[%snd %rcv %odd %msg])
:: ::
=^ moves0 nec (call nec ~[/g/talk] %plea our-comet %g /talk [%get %post]) =^ moves0 nec (call nec ~[/g/talk] %plea our-comet %g /talk [%get %post])
=^ moves1 comet (call comet ~[//unix] %hear (snag-packet 0 moves0)) =^ moves1 comet (call comet ~[//unix] %hear (snag-packet 0 moves0))
@ -371,27 +375,34 @@
:^ comet /public-keys ~[//unix] :^ comet /public-keys ~[//unix]
^- sign:ames ^- sign:ames
[%jael %public-keys %full [n=[~nec point] ~ ~]] [%jael %public-keys %full [n=[~nec point] ~ ~]]
:: give comet's self-attestation to ~nec; at this point, we have established :: give comet's self-attestation to ~nec; at this point, we have
:: a channel, and can proceed as usual :: established a channel, and can proceed as usual
:: ::
=/ post [%post 'first1!!']
=^ moves3 nec (call nec ~[//unix] %hear (snag-packet 0 moves2)) =^ moves3 nec (call nec ~[//unix] %hear (snag-packet 0 moves2))
%+ weld
%- expect-fail |.
(call nec ~[//unix] %hear (snag-packet 1 moves2))
::
=^ moves4 comet (call comet ~[//unix] %hear (snag-packet 0 moves3)) =^ moves4 comet (call comet ~[//unix] %hear (snag-packet 0 moves3))
=^ moves5 comet (take comet /bone/~nec/0/1 ~[//unix] %g %done ~) =^ moves5 comet (take comet /bone/~nec/1/1 ~[//unix] %g %done ~)
=^ moves6 nec (call nec ~[//unix] %hear (snag-packet 0 moves5)) =^ moves6 nec (call nec ~[//unix] %hear (snag-packet 0 moves5))
=^ moves7 comet (take comet /bone/~nec/0/1 ~[//unix] %g %boon [%post 'first1!!']) =^ moves7 comet (take comet /bone/~nec/1/1 ~[//unix] %g %boon post)
=^ moves8 nec (call nec ~[//unix] %hear (snag-packet 0 moves7)) =^ moves8 nec (call nec ~[//unix] %hear (snag-packet 0 moves7))
:: ::
;: weld ;: weld
%+ expect-eq %+ expect-eq
!> [~[//unix] %pass /qos %d %flog %text "; ~nec is your neighbor"] !> =- [~[//unix] %pass /qos %d %flog %text -]
"; ~nec is your neighbor"
!> (snag 0 `(list move:ames)`moves4) !> (snag 0 `(list move:ames)`moves4)
:: ::
%+ expect-eq %+ expect-eq
!> [~[//unix] %pass /qos %d %flog %text "; {<our-comet>} is your neighbor"] !> =- [~[//unix] %pass /qos %d %flog %text -]
"; {<our-comet>} is your neighbor"
!> (snag 0 `(list move:ames)`moves6) !> (snag 0 `(list move:ames)`moves6)
:: ::
%+ expect-eq %+ expect-eq
!> [~[/g/talk] %give %boon [%post 'first1!!']] !> [~[/g/talk] %give %boon post]
!> (snag 0 `(list move:ames)`moves8) !> (snag 0 `(list move:ames)`moves8)
== ==
:: ::

View File

@ -0,0 +1,234 @@
/+ *test
/= behn-raw /sys/vane/behn
=/ behn-gate (behn-raw ~bus)
=/ scry *roof
=* move move:behn-gate
::
|%
++ test-wake-no
^- tang
=/ wen ~1111.1.1
=/ arg [~[/vere] [%wake ~]]
-:(call ~ wen arg ~)
::
++ test-wake-no-wait
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/vere] [%born ~]]
=/ a-out ~
=^ a behn-gate (call `%a wen a-arg a-out)
::
=/ b-arg [~[/vere] [%wake ~]]
=/ b-out ~
=^ b behn-gate (call `%b wen b-arg b-out)
::
(weld a b)
::
++ test-wake-no-born
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/foo] [%wait +(wen)]]
=/ a-out ~
=^ a behn-gate (call `%a wen a-arg a-out)
::
=/ b-arg [~[/vere] [%wake ~]]
=/ b-out ~
=^ b behn-gate (call `%b wen b-arg b-out)
::
(weld a b)
::
++ test-wake
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/vere] [%born ~]]
=/ a-out ~
=^ a behn-gate
(call ~ wen a-arg a-out)
::
=/ b-arg [~[/foo] [%wait +(wen)]]
=/ b-out=(list move) [~[/vere] [%give [%doze `+(wen)]]]~
=^ b behn-gate (call `%b wen b-arg b-out)
::
=/ c-arg [~[/vere] [%wake ~]]
=/ c-out=(list move) [~[/foo] [%give [%wake ~]]]~
=^ c behn-gate (call `%c +(wen) c-arg c-out)
::
:(weld a b c)
::
++ test-born
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/foo] [%wait +(wen)]]
=/ a-out ~
=^ a behn-gate (call `%a wen a-arg a-out)
::
=/ b-arg [~[/vere] [%born ~]]
=/ b-out=(list move) [~[/vere] [%give [%doze `+(wen)]]]~
=^ b behn-gate (call `%b wen b-arg b-out)
::
(weld a b)
::
++ test-many-ordered
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/vere] [%born ~]]
=/ a-out ~
=^ a behn-gate (call `%a wen a-arg a-out)
::
=/ b-arg [~[/foo] [%wait +(wen)]]
=/ b-out=(list move) [~[/vere] [%give [%doze `+(wen)]]]~
=^ b behn-gate (call `%b wen b-arg b-out)
::
=/ c-arg [~[/foo] [%wait (add 2 wen)]]
=/ c-out ~
=^ c behn-gate (call `%c wen c-arg c-out)
::
=/ d-arg [~[/foo] [%wait (add 3 wen)]]
=/ d-out ~
=^ d behn-gate (call `%d wen d-arg d-out)
::
=/ e-arg [~[/vere] [%wake ~]]
=/ e-out=(list move)
:~ [~[/vere] [%give [%doze `(add 2 wen)]]]
[~[/foo] [%give [%wake ~]]]
==
=^ e behn-gate (call `%e (add 4 wen) e-arg e-out)
::
:(weld a b c d e)
::
++ test-many-ordered-lag
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/vere] [%born ~]]
=/ a-out ~
=^ a behn-gate (call `%a wen a-arg a-out)
::
=/ b-arg [~[/foo] [%wait +(wen)]]
=/ b-out=(list move) [~[/vere] [%give [%doze `+(wen)]]]~
=^ b behn-gate (call `%b wen b-arg b-out)
::
=/ c-arg [~[/foo] [%wait (add 2 wen)]]
=/ c-out ~
=^ c behn-gate (call `%c wen c-arg c-out)
::
=/ d-arg [~[/foo] [%wait (add 3 wen)]]
=/ d-out ~
=^ d behn-gate (call `%d wen d-arg d-out)
::
=/ e-arg [~[/vere] [%wake ~]]
=/ e-out=(list move)
:~ [~[/vere] [%give [%doze `(add 2 wen)]]]
[~[/foo] [%give [%wake ~]]]
==
=^ e behn-gate (call `%e +(wen) e-arg e-out)
::
:(weld a b c d e)
::
++ test-many-unordered
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/vere] [%born ~]]
=/ a-out ~
=^ a behn-gate (call `%a wen a-arg a-out)
::
=/ b-arg [~[/foo] [%wait (add 2 wen)]]
=/ b-out=(list move) [~[/vere] [%give [%doze `(add 2 wen)]]]~
=^ b behn-gate (call `%b wen b-arg b-out)
::
=/ c-arg [~[/foo] [%wait (add 3 wen)]]
=/ c-out ~
=^ c behn-gate (call `%c wen c-arg c-out)
::
=/ d-arg [~[/foo] [%wait +(wen)]]
=/ d-out=(list move) [~[/vere] [%give [%doze `+(wen)]]]~
=^ d behn-gate (call `%d wen d-arg d-out)
::
=/ e-arg [~[/vere] [%wake ~]]
=/ e-out=(list move)
:~ [~[/vere] [%give [%doze `(add 2 wen)]]]
[~[/foo] [%give [%wake ~]]]
==
=^ e behn-gate (call `%e (add 4 wen) e-arg e-out)
::
:(weld a b c d e)
::
++ test-same-ordered-lag
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/vere] [%born ~]]
=/ a-out ~
=^ a behn-gate (call `%a wen a-arg a-out)
::
=/ b-arg [~[/foo] [%wait (add 2 wen)]]
=/ b-out=(list move) [~[/vere] [%give [%doze `(add 2 wen)]]]~
=^ b behn-gate (call `%b wen b-arg b-out)
::
=/ c-arg [~[/foo] [%wait (add 2 wen)]]
=/ c-out ~
=^ c behn-gate (call `%c wen c-arg c-out)
::
=/ d-arg [~[/foo] [%wait (add 2 wen)]]
=/ d-out ~
=^ d behn-gate (call `%d wen d-arg d-out)
::
=/ e-arg [~[/vere] [%wake ~]]
=/ e-out=(list move)
:~ [~[/vere] [%give [%doze `(add 2 wen)]]]
[~[/foo] [%give [%wake ~]]]
==
=^ e behn-gate (call `%e (add 3 wen) e-arg e-out)
::
:(weld a b c d e)
::
++ test-rest
^- tang
=/ wen ~1111.1.1
::
=/ a-arg [~[/vere] [%born ~]]
=/ a-out ~
=^ a behn-gate (call `%a wen a-arg a-out)
::
=/ b-arg [~[/foo] [%wait (add 2 wen)]]
=/ b-out=(list move) [~[/vere] [%give [%doze `(add 2 wen)]]]~
=^ b behn-gate (call `%b wen b-arg b-out)
::
=/ c-arg [~[/foo] [%wait (add 3 wen)]]
=/ c-out ~
=^ c behn-gate (call `%c wen c-arg c-out)
::
=/ d-arg [~[/foo] [%rest (add 2 wen)]]
=/ d-out=(list move) [~[/vere] [%give [%doze `(add 3 wen)]]]~
=^ d behn-gate (call `%d wen d-arg d-out)
::
=/ e-arg [~[/vere] [%wake ~]]
=/ e-out=(list move) [~[/foo] [%give [%wake ~]]]~
=^ e behn-gate (call `%e (add 4 wen) e-arg e-out)
::
:(weld a b c d e)
::
++ call
=| lac=?
|= $: label=(unit @tas)
now=@da
args=[=duct task=(hobo task:behn)]
expected-moves=(list move)
==
=/ behn-core (behn-gate now=now eny=`@`0xdead.beef scry=scry)
=^ moves behn-gate
(call:behn-core duct.args dud=~ task.args)
::
~? !lac moves
=/ output=tang
%+ expect-eq
!> expected-moves
!> moves
[?~(label output ?~(output ~ [u.label output])) behn-gate]
--

View File

@ -66,7 +66,7 @@
:: ::
++ rest ++ rest
|= p=@da |= p=@da
(arvo %b %wait p) (arvo %b %rest p)
:: ::
++ warp ++ warp
|= [wer=ship =riff:clay] |= [wer=ship =riff:clay]

View File

@ -11,7 +11,7 @@
|% |%
++ prefixes ++ prefixes
^- (map network tape) ^- (map network tape)
(my [[%main "bc"] [%testnet "tb"] ~]) (my [[%main "bc"] [%testnet "tb"] [%regtest "bcrt"] ~])
++ charset "qpzry9x8gf2tvdw0s3jn54khce6mua7l" ++ charset "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+$ raw-decoded [hrp=tape data=(list @) checksum=(list @)] +$ raw-decoded [hrp=tape data=(list @) checksum=(list @)]
:: below is a port of: https://github.com/bitcoinjs/bech32/blob/master/index.js :: below is a port of: https://github.com/bitcoinjs/bech32/blob/master/index.js

View File

@ -56,6 +56,8 @@
1^0x0 1^0x0
%testnet %testnet
1^0x1 1^0x1
%regtest
1^0x1
== ==
:- (cat:byt ~[1^typ pubkey.h]) :- (cat:byt ~[1^typ pubkey.h])
%- cat:byt %- cat:byt

View File

@ -433,7 +433,6 @@
%- pure:m %- pure:m
?~ full-file.client-response '' ?~ full-file.client-response ''
q.data.u.full-file.client-response q.data.u.full-file.client-response
:: ::
++ fetch-cord ++ fetch-cord
|= url=tape |= url=tape

View File

@ -38,7 +38,37 @@
=/ b (mule a) =/ b (mule a)
?- -.b ?- -.b
%| ~ %| ~
%& [leaf+"expected failure - succeeded" ~] %& ['expected failure - succeeded' ~]
==
:: +expect-runs: kicks a trap, expecting success; returns trace on failure
::
++ expect-success
|= a=(trap)
^- tang
=/ b (mule a)
?- -.b
%& ~
%| ['expected success - failed' p.b]
==
:: $test-chain: a sequence of tests to be run
::
+$ test-chain
$_
|?
?: =(0 0)
[%& p=*tang]
[%| p=[tang=*tang next=^?(..$)]]
:: +run-chain: run a sequence of tests, stopping at first failure
::
++ run-chain
|= seq=test-chain
^- tang
=/ res $:seq
?- -.res
%& p.res
%| ?. =(~ tang.p.res)
tang.p.res
$(seq next.p.res)
== ==
:: +category: prepends a name to an error result; passes successes unchanged :: +category: prepends a name to an error result; passes successes unchanged
:: ::

21
pkg/base-dev/mar/css.hoon Normal file
View File

@ -0,0 +1,21 @@
::
:::: /hoon/css/mar
::
/? 310
=, eyre
=, mimes:html
|_ mud=@t
++ grow :: convert to
|% ++ mime [/text/css (as-octs mud)] :: convert to %mime
++ elem ;style :: convert to %hymn
;- (trip mud)
==
++ hymn ;html:(head:"{elem}" body)
--
++ grab
|% :: convert from
++ mime |=([p=mite q=octs] (@t q.q))
++ noun @t :: clam from %noun
--
++ grad %mime
--

View File

@ -4,7 +4,7 @@
:: chyg: whether account is (non-)change. 0 or 1 :: chyg: whether account is (non-)change. 0 or 1
:: bytc: "btc-byts" with dat cast to @ux :: bytc: "btc-byts" with dat cast to @ux
|% |%
+$ network ?(%main %testnet) +$ network ?(%main %testnet %regtest)
+$ hexb [wid=@ dat=@ux] :: hex byts +$ hexb [wid=@ dat=@ux] :: hex byts
+$ bits [wid=@ dat=@ub] +$ bits [wid=@ dat=@ub]
+$ xpub @ta +$ xpub @ta

View File

@ -175,6 +175,11 @@
%broadcast-tx [%broadcast-tx rawtx.act] %broadcast-tx [%broadcast-tx rawtx.act]
%ping [%get-block-info ~] %ping [%get-block-info ~]
%block-info [%get-block-info block.act] %block-info [%get-block-info block.act]
%histogram [%get-histogram ~]
%block-headers [%get-block-headers start.act count.act cp.act]
%tx-from-pos [%get-tx-from-pos height.act pos.act merkle.act]
%fee [%get-fee block.act]
%psbt [%update-psbt psbt.act]
== ==
:: ::
++ req-card ++ req-card
@ -309,6 +314,31 @@
?> ?=([%get-block-info *] r) ?> ?=([%get-block-info *] r)
:_ state :_ state
~[(send-update:hc [%.y %block-info network.host-info +.r] ship)] ~[(send-update:hc [%.y %block-info network.host-info +.r] ship)]
::
%histogram
?> ?=([%get-histogram *] r)
:_ state
~[(send-update:hc [%.y %histogram +.r] ship)]
::
%block-headers
?> ?=([%get-block-headers *] r)
:_ state
~[(send-update:hc [%.y %block-headers +.r] ship)]
::
%tx-from-pos
?> ?=([%get-tx-from-pos *] r)
:_ state
~[(send-update:hc [%.y %tx-from-pos +.r] ship)]
::
%fee
?> ?=([%get-fee *] r)
:_ state
~[(send-update:hc [%.y %fee +.r] ship)]
::
%psbt
?> ?=([%update-psbt *] r)
:_ state
~[(send-update:hc [%.y %psbt +.r] ship)]
== ==
:: ::
++ connection-error ++ connection-error

View File

@ -900,7 +900,7 @@
?: =(~ prov) `state ?: =(~ prov) `state
?. =(host:(need prov) src.bowl) `state ?. =(host:(need prov) src.bowl) `state
?. ?=(%.y -.upd) `state ?. ?=(%.y -.upd) `state
?- -.p.upd ?+ -.p.upd `state
%address-info %address-info
:: located in the helper in Scan Logic to keep all of that unified :: located in the helper in Scan Logic to keep all of that unified
:: ::

View File

@ -5,7 +5,7 @@
glob-http+['https://bootstrap.urbit.org/glob-0v3.7b5q1.gn30e.cpfem.abmqg.qh77v.glob' 0v3.7b5q1.gn30e.cpfem.abmqg.qh77v] glob-http+['https://bootstrap.urbit.org/glob-0v3.7b5q1.gn30e.cpfem.abmqg.qh77v.glob' 0v3.7b5q1.gn30e.cpfem.abmqg.qh77v]
image+'https://urbit.ewr1.vultrobjects.com/hastuc-dibtux/2021.8.24..02.57.38-bitcoin.svg' image+'https://urbit.ewr1.vultrobjects.com/hastuc-dibtux/2021.8.24..02.57.38-bitcoin.svg'
base+'bitcoin' base+'bitcoin'
version+[0 0 1] version+[0 0 2]
license+'MIT' license+'MIT'
website+'https://tlon.io' website+'https://tlon.io'
== ==

View File

@ -74,6 +74,7 @@
:- ?- network :- ?- network
%main 1^0x0 %main 1^0x0
%testnet 1^0x6f %testnet 1^0x6f
%regtest 1^0x6f
== ==
~[(hash-160:bcu pubkey)] ~[(hash-160:bcu pubkey)]
:: ::
@ -84,6 +85,7 @@
:~ ?- network :~ ?- network
%main 1^0x5 %main 1^0x5
%testnet 1^0xc4 %testnet 1^0xc4
%regtest 1^0xc4
== ==
%- hash-160:bcu %- hash-160:bcu
(cat:byt:bcu ~[2^0x14 (hash-160:bcu pubkey)]) (cat:byt:bcu ~[2^0x14 (hash-160:bcu pubkey)])
@ -109,7 +111,8 @@
++ is-base58 ++ is-base58
|= at=tape |= at=tape
^- ? ^- ?
?| =("m" (scag 1 at)) ?| =("n" (scag 1 at))
=("m" (scag 1 at))
=("1" (scag 1 at)) =("1" (scag 1 at))
=("3" (scag 1 at)) =("3" (scag 1 at))
=("2" (scag 1 at)) =("2" (scag 1 at))
@ -120,6 +123,7 @@
^- ? ^- ?
?| =("bc1" (scag 3 at)) ?| =("bc1" (scag 3 at))
=("tb1" (scag 3 at)) =("tb1" (scag 3 at))
=("bcrt1" (scag 5 at))
== ==
-- --
:: ::

View File

@ -423,6 +423,21 @@
:: ::
%get-block-info %get-block-info
[id.res (block-info res.res)] [id.res (block-info res.res)]
::
%get-histogram
[id.res ((ar (ar ni)) res.res)]
::
%get-block-headers
[id.res (block-headers res.res)]
::
%get-tx-from-pos
[id.res (tx-from-pos res.res)]
::
%get-fee
[id.res (ne res.res)]
::
%update-psbt
[id.res (so res.res)]
== ==
:: ::
++ address-info ++ address-info
@ -474,11 +489,25 @@
[%blockhash (cu from-cord:hxb:bcu so)] [%blockhash (cu from-cord:hxb:bcu so)]
[%blockfilter (cu from-cord:hxb:bcu so)] [%blockfilter (cu from-cord:hxb:bcu so)]
== ==
++ block-headers
%- ot
:~ [%count ni]
[%hex (cu from-cord:hxb:bcu so)]
[%max ni]
[%root (cu:dejs-soft:format from-cord:hxb:bcu so:dejs-soft:format)]
[%branch (ar (cu from-cord:hxb:bcu so))]
==
++ tx-from-pos
%- ot
:~ [%tx-hash (cu from-cord:hxb:bcu so)]
[%merkle (ar (cu from-cord:hxb:bcu so))]
==
-- --
-- --
:: ::
++ rpc-action-to-http ++ rpc-action-to-http
|= [endpoint=@t ract=action:rpc-types:bp] |= [endpoint=@t ract=action:rpc-types:bp]
=, enjs:format
|^ ^- request:http |^ ^- request:http
?- -.ract ?- -.ract
%get-address-info %get-address-info
@ -510,6 +539,39 @@
?~(block.ract '' (rsh [3 2] (scot %ui u.block.ract))) ?~(block.ract '' (rsh [3 2] (scot %ui u.block.ract)))
%- get-request %- get-request
(mk-url '/getblockinfo/' param) (mk-url '/getblockinfo/' param)
::
%get-histogram
%- get-request
(mk-url '/feehistogram' '')
::
%get-block-headers
%+ post-request
%+ mk-url '/blockheaders' ''
%- pairs
:~ [%start (numb start.ract)]
[%count (numb count.ract)]
[%cp (numb (fall cp.ract 0))]
==
::
%get-tx-from-pos
%+ post-request
%+ mk-url '/txfrompos' ''
%- pairs
:~ [%height (numb height.ract)]
[%pos (numb pos.ract)]
[%merkle %b merkle.ract]
==
::
%get-fee
%- get-request
%+ mk-url '/estimatefee/'
%- crip
%+ scow %ud block.ract
::
%update-psbt
%- get-request
%+ mk-url '/updatepsbt/'
%- en:base64:mimes:html [(lent (trip psbt.ract)) psbt.ract]
== ==
++ mk-url ++ mk-url
|= [base=@t params=@t] |= [base=@t params=@t]

View File

@ -33,6 +33,11 @@
[%broadcast-tx rawtx=hexb] [%broadcast-tx rawtx=hexb]
[%ping ~] [%ping ~]
[%block-info block=(unit @ud)] [%block-info block=(unit @ud)]
[%histogram ~]
[%block-headers start=@ud count=@ud cp=(unit @ud)]
[%tx-from-pos height=@ud pos=@ud merkle=?]
[%fee block=@ud]
[%psbt psbt=@t]
== ==
:: ::
+$ result +$ result
@ -41,6 +46,11 @@
[%raw-tx txid=hexb rawtx=hexb] [%raw-tx txid=hexb rawtx=hexb]
[%broadcast-tx txid=hexb broadcast=? included=?] [%broadcast-tx txid=hexb broadcast=? included=?]
[%block-info =network block=@ud fee=(unit sats) blockhash=hexb blockfilter=hexb] [%block-info =network block=@ud fee=(unit sats) blockhash=hexb blockfilter=hexb]
[%histogram hist=(list (list @ud))]
[%block-headers count=@ud hex=hexb max=@ud root=(unit hexb) branch=(list hexb)]
[%tx-from-pos tx-hash=hexb merkle=(list hexb)]
[%fee fee=@rd]
[%psbt psbt=@t]
== ==
+$ error +$ error
$% [%not-connected status=@ud] $% [%not-connected status=@ud]
@ -64,6 +74,11 @@
[%broadcast-tx rawtx=hexb] [%broadcast-tx rawtx=hexb]
[%get-block-count ~] [%get-block-count ~]
[%get-block-info block=(unit @ud)] [%get-block-info block=(unit @ud)]
[%get-histogram ~]
[%get-block-headers start=@ud count=@ud cp=(unit @ud)]
[%get-tx-from-pos height=@ud pos=@ud merkle=?]
[%get-fee block=@ud]
[%update-psbt psbt=@t]
== ==
:: ::
+$ result +$ result
@ -74,7 +89,11 @@
[%broadcast-tx txid=hexb broadcast=? included=?] [%broadcast-tx txid=hexb broadcast=? included=?]
[%get-block-count block=@ud] [%get-block-count block=@ud]
[%get-block-info block=@ud fee=(unit sats) blockhash=hexb blockfilter=hexb] [%get-block-info block=@ud fee=(unit sats) blockhash=hexb blockfilter=hexb]
[%get-histogram hist=(list (list @ud))]
[%get-block-headers count=@ud hex=hexb max=@ud root=(unit hexb) branch=(list hexb)]
[%get-tx-from-pos tx-hash=hexb merkle=(list hexb)]
[%get-fee fee=@rd]
[%update-psbt psbt=@t]
== ==
-- --
-- --

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
:~ title+'System' :~ title+'System'
info+'An app launcher for Urbit.' info+'An app launcher for Urbit.'
color+0xee.5432 color+0xee.5432
glob-http+['https://bootstrap.urbit.org/glob-0v2.p3f6i.19q8d.lsgcb.mckg7.dtu8f.glob' 0v2.p3f6i.19q8d.lsgcb.mckg7.dtu8f] glob-http+['https://bootstrap.urbit.org/glob-0v5.kgrq2.gp725.bo5bk.dmr7d.h41qk.glob' 0v5.kgrq2.gp725.bo5bk.dmr7d.h41qk]
::glob-ames+~zod^0v0 ::glob-ames+~zod^0v0
base+'grid' base+'grid'
version+[1 1 3] version+[1 1 6]
website+'https://tlon.io' website+'https://tlon.io'
license+'MIT' license+'MIT'
== ==

1
pkg/garden/mar/css.hoon Symbolic link
View File

@ -0,0 +1 @@
../../base-dev/mar/css.hoon

View File

@ -18,7 +18,7 @@
"@radix-ui/react-toggle": "^0.0.10", "@radix-ui/react-toggle": "^0.0.10",
"@tlon/sigil-js": "^1.4.4", "@tlon/sigil-js": "^1.4.4",
"@types/lodash": "^4.14.172", "@types/lodash": "^4.14.172",
"@urbit/api": "^2.1.0", "@urbit/api": "^2.1.1",
"@urbit/http-api": "^2.1.0", "@urbit/http-api": "^2.1.0",
"big-integer": "^1.6.48", "big-integer": "^1.6.48",
"classnames": "^2.3.1", "classnames": "^2.3.1",
@ -1468,9 +1468,9 @@
} }
}, },
"node_modules/@urbit/api": { "node_modules/@urbit/api": {
"version": "2.1.0", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/@urbit/api/-/api-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@urbit/api/-/api-2.1.1.tgz",
"integrity": "sha512-2njwpvZ2s23gp5C4v9uDynU1wxrN33+vloqpvlErUhMR/4R6mXE4cMvsZzj/fCGOa0J3LRV/If7XmgG+kY69Tg==", "integrity": "sha512-QRlqhtJ73q+pgMdSwuOO62HlxA7/2c5ylCcOUT01LXkJ2LTVCl5u+QnejdDvUmqjOuN2PyZk7df30xJVg6rC2A==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.16.0", "@babel/runtime": "^7.16.0",
"big-integer": "^1.6.48", "big-integer": "^1.6.48",
@ -8257,9 +8257,9 @@
} }
}, },
"@urbit/api": { "@urbit/api": {
"version": "2.1.0", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/@urbit/api/-/api-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@urbit/api/-/api-2.1.1.tgz",
"integrity": "sha512-2njwpvZ2s23gp5C4v9uDynU1wxrN33+vloqpvlErUhMR/4R6mXE4cMvsZzj/fCGOa0J3LRV/If7XmgG+kY69Tg==", "integrity": "sha512-QRlqhtJ73q+pgMdSwuOO62HlxA7/2c5ylCcOUT01LXkJ2LTVCl5u+QnejdDvUmqjOuN2PyZk7df30xJVg6rC2A==",
"requires": { "requires": {
"@babel/runtime": "^7.16.0", "@babel/runtime": "^7.16.0",
"big-integer": "^1.6.48", "big-integer": "^1.6.48",

View File

@ -15,8 +15,8 @@
"tsc": "tsc --noEmit" "tsc": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-checkbox": "^0.1.5",
"@fingerprintjs/fingerprintjs": "^3.3.3", "@fingerprintjs/fingerprintjs": "^3.3.3",
"@radix-ui/react-checkbox": "^0.1.5",
"@radix-ui/react-dialog": "^0.0.20", "@radix-ui/react-dialog": "^0.0.20",
"@radix-ui/react-dropdown-menu": "^0.0.23", "@radix-ui/react-dropdown-menu": "^0.0.23",
"@radix-ui/react-icons": "^1.1.0", "@radix-ui/react-icons": "^1.1.0",
@ -25,7 +25,7 @@
"@radix-ui/react-toggle": "^0.0.10", "@radix-ui/react-toggle": "^0.0.10",
"@tlon/sigil-js": "^1.4.4", "@tlon/sigil-js": "^1.4.4",
"@types/lodash": "^4.14.172", "@types/lodash": "^4.14.172",
"@urbit/api": "^2.1.0", "@urbit/api": "^2.1.1",
"@urbit/http-api": "^2.1.0", "@urbit/http-api": "^2.1.0",
"big-integer": "^1.6.48", "big-integer": "^1.6.48",
"classnames": "^2.3.1", "classnames": "^2.3.1",

View File

@ -72,7 +72,6 @@ export const Leap = React.forwardRef(
useEffect(() => { useEffect(() => {
const newMatch = getMatch(rawInput); const newMatch = getMatch(rawInput);
if (newMatch && rawInput) { if (newMatch && rawInput) {
useLeapStore.setState({ selectedMatch: newMatch }); useLeapStore.setState({ selectedMatch: newMatch });
} }
@ -112,7 +111,10 @@ export const Leap = React.forwardRef(
const navigateByInput = useCallback( const navigateByInput = useCallback(
(input: string) => { (input: string) => {
const normalizedValue = input.trim().replace(/(~?[\w^_-]{3,13})\//, '$1/apps/'); const normalizedValue = input
.trim()
.replace('%', '')
.replace(/(~?[\w^_-]{3,13})\//, '$1/apps/$1/');
push(`/leap/${menu}/${normalizedValue}`); push(`/leap/${menu}/${normalizedValue}`);
}, },
[menu] [menu]

View File

@ -7,6 +7,7 @@ module.exports = {
// Because we use styled system, and use // Because we use styled system, and use
// the convention of each prop on a new line // the convention of each prop on a new line
// we probably shouldn't keep this on // we probably shouldn't keep this on
'max-lines-per-function': ['off', {}] 'max-lines-per-function': ['off', {}],
'max-lines': ['off', {}]
} }
}; };

View File

@ -1 +1 @@
16.14.0 14.19.0

View File

@ -0,0 +1 @@
nodejs 14.19.0

View File

@ -1,66 +1,71 @@
const path = require('path'); const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MomentLocalesPlugin = require('moment-locales-webpack-plugin'); const MomentLocalesPlugin = require("moment-locales-webpack-plugin");
const webpack = require('webpack'); const webpack = require("webpack");
const { execSync } = require('child_process'); const { execSync } = require("child_process");
const GIT_DESC = execSync('git describe --always', { encoding: 'utf8' }).trim(); const GIT_DESC = execSync("git describe --always", { encoding: "utf8" }).trim();
module.exports = { module.exports = {
mode: 'production', mode: "production",
entry: { entry: {
app: './src/index.tsx', app: "./src/index.tsx",
serviceworker: './src/serviceworker.js' serviceworker: "./src/serviceworker.js",
}, },
module: { module: {
rules: [ rules: [
{ {
test: /\.(j|t)sx?$/, test: /\.(j|t)sx?$/,
use: { use: {
loader: 'babel-loader', loader: "babel-loader",
options: { options: {
presets: ['@babel/preset-env', '@babel/typescript', '@babel/preset-react'], presets: [
"@babel/preset-env",
"@babel/typescript",
"@babel/preset-react",
],
plugins: [ plugins: [
'lodash', "lodash",
'@babel/transform-runtime', "@babel/transform-runtime",
'@babel/plugin-proposal-object-rest-spread', "@babel/plugin-proposal-object-rest-spread",
'@babel/plugin-proposal-optional-chaining', "@babel/plugin-proposal-optional-chaining",
'@babel/plugin-proposal-class-properties' "@babel/plugin-proposal-class-properties",
] ],
}
}, },
exclude: /node_modules\/(?!(@tlon\/indigo-dark|@tlon\/indigo-light|@tlon\/indigo-react|@urbit\/api)\/).*/ },
exclude:
/node_modules\/(?!(@tlon\/indigo-dark|@tlon\/indigo-light|@tlon\/indigo-react|@urbit\/api)\/).*/,
}, },
{ {
test: /\.css$/i, test: /\.css$/i,
use: [ use: [
// Creates `style` nodes from JS strings // Creates `style` nodes from JS strings
'style-loader', "style-loader",
// Translates CSS into CommonJS // Translates CSS into CommonJS
'css-loader', "css-loader",
// Compiles Sass to CSS // Compiles Sass to CSS
'sass-loader' "sass-loader",
] ],
}, },
{ {
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [ use: [
{ {
loader: 'file-loader', loader: "file-loader",
options: { options: {
name: '[name].[ext]', name: "[name].[ext]",
outputPath: 'fonts/' outputPath: "fonts/",
} },
} },
] ],
} },
] ],
}, },
resolve: { resolve: {
extensions: ['.js', '.ts', '.tsx'] extensions: [".js", ".ts", ".tsx"],
}, },
devtool: 'source-map', devtool: "source-map",
// devServer: { // devServer: {
// contentBase: path.join(__dirname, './'), // contentBase: path.join(__dirname, './'),
// hot: true, // hot: true,
@ -71,26 +76,30 @@ module.exports = {
new MomentLocalesPlugin(), new MomentLocalesPlugin(),
new CleanWebpackPlugin(), new CleanWebpackPlugin(),
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env.LANDSCAPE_STREAM': JSON.stringify(process.env.LANDSCAPE_STREAM), "process.env.LANDSCAPE_STREAM": JSON.stringify(
'process.env.LANDSCAPE_SHORTHASH': JSON.stringify(GIT_DESC), process.env.LANDSCAPE_STREAM
'process.env.LANDSCAPE_STORAGE_VERSION': Date.now().toString(), ),
'process.env.LANDSCAPE_LAST_WIPE': '2021-10-20', "process.env.LANDSCAPE_SHORTHASH": JSON.stringify(GIT_DESC),
"process.env.LANDSCAPE_STORAGE_VERSION": Date.now().toString(),
"process.env.LANDSCAPE_LAST_WIPE": "2021-10-20",
}), }),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
title: 'Groups', title: "Groups",
template: './public/index.html', template: "./public/index.html",
favicon: './src/assets/img/Favicon.png' favicon: "./src/assets/img/favicon.png",
}) }),
], ],
output: { output: {
filename: (pathData) => { filename: (pathData) => {
return pathData.chunk.name === 'app' ? 'index.[contenthash].js' : '[name].js'; return pathData.chunk.name === "app"
? "index.[contenthash].js"
: "[name].js";
}, },
path: path.resolve(__dirname, '../dist'), path: path.resolve(__dirname, "../dist"),
publicPath: '/apps/landscape/' publicPath: "/apps/landscape/",
}, },
optimization: { optimization: {
minimize: true, minimize: true,
usedExports: true usedExports: true,
} },
}; };

File diff suppressed because it is too large Load Diff

View File

@ -5,22 +5,19 @@
"main": "index.js", "main": "index.js",
"private": true, "private": true,
"engines": { "engines": {
"node": "16.14.0" "node": "14.19.0"
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"@fingerprintjs/fingerprintjs": "^3.3.3", "@fingerprintjs/fingerprintjs": "^3.3.3",
"@radix-ui/react-dialog": "^0.1.0", "@radix-ui/react-dialog": "^0.1.0",
"@reach/disclosure": "^0.10.5",
"@reach/menu-button": "^0.10.5",
"@reach/tabs": "^0.10.5",
"@react-spring/web": "^9.1.1", "@react-spring/web": "^9.1.1",
"@tlon/indigo-dark": "^1.0.6", "@tlon/indigo-dark": "^1.0.6",
"@tlon/indigo-light": "^1.0.7", "@tlon/indigo-light": "^1.0.7",
"@tlon/indigo-react": "^1.2.27", "@tlon/indigo-react": "^1.2.27",
"@tlon/sigil-js": "^1.4.3", "@tlon/sigil-js": "^1.4.5",
"@urbit/api": "^2.1.0", "@urbit/api": "^2.1.1",
"@urbit/http-api": "^2.1.0", "@urbit/http-api": "2.1.1",
"any-ascii": "^0.1.7", "any-ascii": "^0.1.7",
"aws-sdk": "^2.830.0", "aws-sdk": "^2.830.0",
"big-integer": "^1.6.48", "big-integer": "^1.6.48",
@ -36,15 +33,15 @@
"mousetrap": "^1.6.5", "mousetrap": "^1.6.5",
"mousetrap-global-bind": "^1.1.0", "mousetrap-global-bind": "^1.1.0",
"normalize-wheel": "1.0.1", "normalize-wheel": "1.0.1",
"oembed-parser": "^1.4.5", "oembed-parser": "^3.0.4",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"querystring": "^0.2.0", "querystring": "^0.2.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-codemirror2": "^6.0.1", "react-codemirror2-react-17": "^1.0.0",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-markdown": "^4.3.1", "react-markdown": "^5.0.3",
"react-oembed-container": "^1.0.0", "react-oembed-container": "^1.0.1",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-use-gesture": "^9.1.3", "react-use-gesture": "^9.1.3",
"react-virtuoso": "^0.20.3", "react-virtuoso": "^0.20.3",
@ -107,6 +104,7 @@
"lint-staged": "^11.0.0", "lint-staged": "^11.0.0",
"loki": "^0.28.1", "loki": "^0.28.1",
"moment-locales-webpack-plugin": "^1.2.0", "moment-locales-webpack-plugin": "^1.2.0",
"patch-package": "^6.4.7",
"react-refresh": "^0.11.0", "react-refresh": "^0.11.0",
"sass": "^1.32.5", "sass": "^1.32.5",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
@ -131,7 +129,8 @@
"storybook": "start-storybook -p 6006", "storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook", "build-storybook": "build-storybook",
"chromatic": "chromatic --exit-zero-on-changes", "chromatic": "chromatic --exit-zero-on-changes",
"hook-lint": "eslint --cache --fix" "hook-lint": "eslint --cache --fix",
"postinstall": "patch-package"
}, },
"author": "", "author": "",
"license": "MIT", "license": "MIT",

View File

@ -4,7 +4,7 @@ export interface Suspender<T> {
read: () => T; read: () => T;
} }
export function suspend<T>(awaiting: Promise<T>): Suspender<T> { export function suspend<T>(awaiting: Promise<T>, defaultValue?: any): Suspender<T> {
let state: SuspendState = 'pending'; let state: SuspendState = 'pending';
let result: T | null = null; let result: T | null = null;
@ -22,8 +22,10 @@ export function suspend<T>(awaiting: Promise<T>): Suspender<T> {
read: () => { read: () => {
if (state === 'result') { if (state === 'result') {
return result!; return result!;
} else if (state === 'error') { } else if (state === 'error' && typeof defaultValue === 'undefined') {
throw result; throw result;
} else if (state === 'error' && typeof defaultValue !== 'undefined') {
return defaultValue;
} else { } else {
throw promise; throw promise;
} }

View File

@ -34,7 +34,8 @@ const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
} }
client.current = new S3Client({ client.current = new S3Client({
credentials: s3.credentials, credentials: s3.credentials,
endpoint: s3.credentials.endpoint endpoint: s3.credentials.endpoint,
signatureVersion: 'v4'
}); });
} }
}, [gcp.token, s3.credentials]); }, [gcp.token, s3.credentials]);

View File

@ -11,8 +11,7 @@ export function getTitleFromWorkspace(
case 'messages': case 'messages':
return 'Messages'; return 'Messages';
case 'group': case 'group':
const association = associations.groups[workspace.group]; return associations.groups[workspace.group]?.metadata?.title || 'Groups';
return association?.metadata?.title || '';
} }
} }

View File

@ -1,6 +1,6 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import create from 'zustand'; import create from 'zustand';
import { suspend, Suspender , suspendWithResult } from '../lib/suspend'; import { suspend, Suspender } from '../lib/suspend';
import { jsonFetch } from '~/logic/lib/util'; import { jsonFetch } from '~/logic/lib/util';
export interface EmbedState { export interface EmbedState {
@ -23,17 +23,19 @@ const useEmbedState = create<EmbedState>((set, get) => ({
const search = new URLSearchParams({ const search = new URLSearchParams({
url url
}); });
const embed = await jsonFetch(`${OEMBED_PROVIDER}?${search.toString()}`); const embed = await jsonFetch(`${OEMBED_PROVIDER}?${search.toString()}`);
const { embeds: es } = get();
set({ embeds: { ...es, [url]: embed } });
return embed; return embed;
}, },
getEmbed: (url: string): Suspender<any> => { getEmbed: (url: string): Suspender<any> => {
const { fetch, embeds } = get(); const { fetch, embeds } = get();
if(url in embeds) { if(url in embeds) {
return suspendWithResult(embeds[url]); return embeds[url];
} }
return suspend(fetch(url)); const { embeds: es } = get();
const embed = suspend(fetch(url), {});
set({ embeds: { ...es, [url]: embed } });
return embed;
} }
})); }));

View File

@ -1,5 +1,6 @@
import { acceptDm, cite, Content, declineDm, deSig, Post } from '@urbit/api'; import { acceptDm, cite, Content, declineDm, deSig, Post } from '@urbit/api';
import React, { useCallback, useEffect } from 'react'; import React, { useCallback, useEffect } from 'react';
import Helmet from 'react-helmet';
import _ from 'lodash'; import _ from 'lodash';
import bigInt from 'big-integer'; import bigInt from 'big-integer';
import { Box, Row, Col, Text, Center } from '@tlon/indigo-react'; import { Box, Row, Col, Text, Center } from '@tlon/indigo-react';
@ -49,6 +50,21 @@ function quoteReply(post: Post) {
return `${reply}\n\n~${post.author}:`; return `${reply}\n\n~${post.author}:`;
} }
export function DmHelmet(props: DmHelmetProps) {
const { ship } = props;
const hark = useHarkDm(ship);
const unreadCount = hark.count;
const contact = useContact(ship);
const { hideNicknames } = useSettingsState(selectCalmState);
const showNickname = !hideNicknames && Boolean(contact);
const nickname = showNickname ? contact!.nickname : cite(ship) ?? ship;
return(
<Helmet defer={false}>
<title>{unreadCount ? `(${String(unreadCount)}) ` : ''}{ nickname }</title>
</Helmet>
);
}
export function DmResource(props: DmResourceProps) { export function DmResource(props: DmResourceProps) {
const { ship } = props; const { ship } = props;
const dm = useDM(ship); const dm = useDM(ship);

View File

@ -5,7 +5,7 @@ import 'codemirror/addon/hint/show-hint';
import 'codemirror/lib/codemirror.css'; import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/markdown/markdown'; import 'codemirror/mode/markdown/markdown';
import React, { useRef, ClipboardEvent, useEffect, useImperativeHandle } from 'react'; import React, { useRef, ClipboardEvent, useEffect, useImperativeHandle } from 'react';
import { Controlled as CodeEditor } from 'react-codemirror2'; import { Controlled as CodeEditor } from 'react-codemirror2-react-17';
import styled from 'styled-components'; import styled from 'styled-components';
import { MOBILE_BROWSER_REGEX } from '~/logic/lib/util'; import { MOBILE_BROWSER_REGEX } from '~/logic/lib/util';
import useSettingsState from '~/logic/state/settings'; import useSettingsState from '~/logic/state/settings';

View File

@ -1,18 +1,17 @@
import React from 'react'; import React from 'react';
import { import {
Icon, Icon,
Center,
Row, Row,
Text, Text,
Col, Col,
Box, Box,
CenterProps CenterProps
} from '@tlon/indigo-react'; } from '@tlon/indigo-react';
import { hasProvider } from 'oembed-parser'; import { AUDIO_REGEX, IMAGE_REGEX, validOembedCheck } from '~/views/components/RemoteContent';
import { AUDIO_REGEX, IMAGE_REGEX } from '~/views/components/RemoteContent';
import { AudioPlayer } from '~/views/components/AudioPlayer'; import { AudioPlayer } from '~/views/components/AudioPlayer';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
import { useHovering } from '~/logic/lib/util'; import { useHovering } from '~/logic/lib/util';
import { useEmbed } from '~/logic/state/embed';
import Author from '~/views/components/Author'; import Author from '~/views/components/Author';
import { import {
GraphNode, GraphNode,
@ -38,8 +37,32 @@ export interface LinkBlockItemProps {
summary?: boolean; summary?: boolean;
} }
export function LinkBlockItem(props: LinkBlockItemProps & CenterProps) { export const LinkBlockItem = (props: LinkBlockItemProps & CenterProps) => {
const { node, summary, size, m, border = 1, objectFit, ...rest } = props; const { node, ...rest } = props;
const { post } = node;
const { contents } = post;
const [{ text: title }, ...content] = contents as [
TextContent,
UrlContent | ReferenceContent
];
let url = '';
if ('url' in content?.[0]) {
url = content[0].url;
}
return(
<AsyncFallback fallback={<RemoteContentEmbedFallback url={url} />}>
<LinkBlockItemInner
node={node}
{...rest}
/>
</AsyncFallback>
);
}
function LinkBlockItemInner(props: LinkBlockItemProps & CenterProps) {
const { node, summary, m, border = 1, objectFit, ...rest } = props;
const { post, children } = node; const { post, children } = node;
const { contents, index, author } = post; const { contents, index, author } = post;
@ -56,8 +79,9 @@ export function LinkBlockItem(props: LinkBlockItemProps & CenterProps) {
const isImage = IMAGE_REGEX.test(url); const isImage = IMAGE_REGEX.test(url);
const isAudio = AUDIO_REGEX.test(url); const isAudio = AUDIO_REGEX.test(url);
const oembed = useEmbed(url);
const isOembed = validOembedCheck(oembed, url);
const isOembed = hasProvider(url);
const history = useHistory(); const history = useHistory();
const { hovering, bind } = useHovering(); const { hovering, bind } = useHovering();
const onClick = () => { const onClick = () => {
@ -65,20 +89,17 @@ export function LinkBlockItem(props: LinkBlockItemProps & CenterProps) {
history.push(`${pathname}/index${index}${search}`); history.push(`${pathname}/index${index}${search}`);
}; };
return ( return (
<Center <Box
onClick={onClick} onClick={onClick}
position="relative"
m={m}
border={border} border={border}
borderColor="lightGray" borderColor="lightGray"
position="relative"
borderRadius="1" borderRadius="1"
height={size}
width={size}
m={m}
maxHeight="100%"
{...rest} {...rest}
{...bind} {...bind}
> >
<AsyncFallback fallback={<RemoteContentEmbedFallback url={url} />}> <Col height="100%" justifyContent="center" alignItems="center">
{isReference ? ( {isReference ? (
summary ? ( summary ? (
<RemoteContentPermalinkEmbed <RemoteContentPermalinkEmbed
@ -100,11 +121,10 @@ export function LinkBlockItem(props: LinkBlockItemProps & CenterProps) {
) : isAudio ? ( ) : isAudio ? (
<AudioPlayer title={title} url={url} /> <AudioPlayer title={title} url={url} />
) : isOembed ? ( ) : isOembed ? (
<RemoteContentOembed tall={!summary} renderUrl={false} url={url} thumbnail={summary} /> <RemoteContentOembed tall={!summary} renderUrl={false} url={url} thumbnail={summary} oembed={oembed} />
) : ( ) : (
<RemoteContentEmbedFallback url={url} /> <RemoteContentEmbedFallback url={url} />
)} )}
</AsyncFallback>
<Box <Box
backgroundColor="white" backgroundColor="white"
display={summary && hovering ? 'block' : 'none'} display={summary && hovering ? 'block' : 'none'}
@ -129,6 +149,7 @@ export function LinkBlockItem(props: LinkBlockItemProps & CenterProps) {
</Row> </Row>
</Col> </Col>
</Box> </Box>
</Center> </Col>
</Box>
); );
} }

View File

@ -1,4 +1,4 @@
import { Col, Row, RowProps } from '@tlon/indigo-react'; import { Center, Col, Row, RowProps } from '@tlon/indigo-react';
import { Association, GraphNode, markEachAsRead, TextContent, UrlContent } from '@urbit/api'; import { Association, GraphNode, markEachAsRead, TextContent, UrlContent } from '@urbit/api';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useGroup } from '~/logic/state/group'; import { useGroup } from '~/logic/state/group';
@ -27,21 +27,13 @@ export function LinkDetail(props: LinkDetailProps) {
return ( return (
/* @ts-ignore indio props?? */ /* @ts-ignore indio props?? */
<Row height="100%" width="100%" flexDirection={['column', 'column', 'row']} {...rest}> <Row height="100%" width="100%" flexDirection={['column', 'column', 'row']} {...rest}>
<LinkBlockItem <Center flex="3 1 75%" overflowY="scroll" >
minWidth="0" <LinkBlockItem maxHeight="100%" border={0} node={node} objectFit="contain" />
minHeight="0" </Center>
height={["50%", "50%", "100%"]}
width={["100%", "100%", "calc(100% - 350px)"]}
flexGrow={0}
border={0}
node={node}
objectFit="contain"
/>
<Col <Col
minHeight="0" flex="1 25%"
flexShrink={1} maxWidth={['auto', 'auto', '45ch']}
width={['100%', '100%', '350px']} maxHeight={['50%', '50%', 'unset']}
flexGrow={0}
gapY={[2,4]} gapY={[2,4]}
borderLeft={[0, 0, 1]} borderLeft={[0, 0, 1]}
borderTop={[1, 1, 0]} borderTop={[1, 1, 0]}

View File

@ -90,12 +90,12 @@ export function EditProfile(props: any): ReactElement {
const onSubmit = async (values: any, actions: any) => { const onSubmit = async (values: any, actions: any) => {
try { try {
Object.keys(values).forEach((key) => { for (const key in values) {
const newValue = key !== 'color' ? values[key] : uxToHex(values[key]); const newValue = key !== 'color' ? values[key] : uxToHex(values[key]);
if (newValue !== contact[key]) { if (newValue === contact[key] || key === 'last-updated') {
if (key === 'isPublic') { continue;
airlock.poke(setPublic(newValue)); } else if (key === 'isPublic') {
return; await airlock.poke(setPublic(newValue));
} else if (key === 'groups') { } else if (key === 'groups') {
const toRemove: string[] = _.difference( const toRemove: string[] = _.difference(
contact?.groups || [], contact?.groups || [],
@ -105,18 +105,18 @@ export function EditProfile(props: any): ReactElement {
newValue, newValue,
contact?.groups || [] contact?.groups || []
); );
toRemove.forEach(e => for (const i in toRemove) {
airlock.poke(editContact(ship, { 'remove-group': resourceFromPath(e) })) const group = resourceFromPath(toRemove[i]);
); await airlock.poke(editContact(ship, { 'remove-group': group }));
toAdd.forEach(e => }
airlock.poke(editContact(ship, { 'add-group': resourceFromPath(e) })) for (const i in toAdd) {
); const group = resourceFromPath(toAdd[i]);
} else if (key !== 'last-updated' && key !== 'isPublic') { await airlock.poke(editContact(ship, { 'add-group': group }));
airlock.poke(editContact(ship, { [key]: newValue })); }
return; } else {
await airlock.poke(editContact(ship, { [key]: newValue }));
} }
} }
});
history.push(`/~profile/${ship}`); history.push(`/~profile/${ship}`);
} catch (e) { } catch (e) {
console.error(e); console.error(e);

View File

@ -6,7 +6,7 @@ import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/markdown/markdown'; import 'codemirror/mode/markdown/markdown';
import { useFormikContext } from 'formik'; import { useFormikContext } from 'formik';
import React, { useCallback, useRef } from 'react'; import React, { useCallback, useRef } from 'react';
import { UnControlled as CodeEditor } from 'react-codemirror2'; import { UnControlled as CodeEditor } from 'react-codemirror2-react-17';
import { Prompt } from 'react-router-dom'; import { Prompt } from 'react-router-dom';
import { useFileUpload } from '~/logic/lib/useFileUpload'; import { useFileUpload } from '~/logic/lib/useFileUpload';
import { IuseStorage } from '~/logic/lib/useStorage'; import { IuseStorage } from '~/logic/lib/useStorage';
@ -23,6 +23,7 @@ interface MarkdownEditorProps {
value: string; value: string;
onChange: (s: string) => void; onChange: (s: string) => void;
onBlur?: (e: any) => void; onBlur?: (e: any) => void;
disabled?: boolean;
} }
const PromptIfDirty = () => { const PromptIfDirty = () => {
@ -39,7 +40,7 @@ const PromptIfDirty = () => {
export function MarkdownEditor( export function MarkdownEditor(
props: MarkdownEditorProps & PropFunc<typeof Box> props: MarkdownEditorProps & PropFunc<typeof Box>
) { ) {
const { onBlur, placeholder, value, onChange, ...boxProps } = props; const { onBlur, placeholder, value, onChange, disabled, ...boxProps } = props;
const options = { const options = {
mode: MARKDOWN_CONFIG, mode: MARKDOWN_CONFIG,
@ -56,7 +57,9 @@ export function MarkdownEditor(
const handleChange = useCallback( const handleChange = useCallback(
(_e, _d, v: string) => { (_e, _d, v: string) => {
if (!disabled) {
onChange(v); onChange(v);
}
}, },
[onChange] [onChange]
); );
@ -93,6 +96,7 @@ export function MarkdownEditor(
p={1} p={1}
border={1} border={1}
borderColor="lightGray" borderColor="lightGray"
backgroundColor={disabled ? 'lightGray' : 'white'}
borderRadius={2} borderRadius={2}
height={['calc(100% - 22vh)', '100%']} height={['calc(100% - 22vh)', '100%']}
{...boxProps} {...boxProps}

View File

@ -6,14 +6,17 @@ import { MarkdownEditor } from './MarkdownEditor';
export const MarkdownField = ({ export const MarkdownField = ({
id, id,
disabled,
...rest ...rest
}: { id: string } & Parameters<typeof Box>[0]) => { }: { id: string; disabled?: boolean } & Parameters<typeof Box>[0]) => {
const [{ value, onBlur }, { error, touched }, { setValue }] = useField(id); const [{ value, onBlur }, { error, touched }, { setValue }] = useField(id);
const handleBlur = useCallback( const handleBlur = useCallback(
(e: any) => { (e: any) => {
if (!disabled) {
_.set(e, 'target.id', id); _.set(e, 'target.id', id);
onBlur && onBlur(e); onBlur && onBlur(e);
}
}, },
[onBlur, id] [onBlur, id]
); );
@ -23,7 +26,7 @@ export const MarkdownField = ({
return ( return (
<Box <Box
overflowY="hidden" overflowY="hidden"
height='100%' height="100%"
width="100%" width="100%"
display="flex" display="flex"
flexDirection="column" flexDirection="column"
@ -35,6 +38,7 @@ export const MarkdownField = ({
onBlur={handleBlur} onBlur={handleBlur}
value={value} value={value}
onChange={setValue} onChange={setValue}
disabled={disabled}
/> />
<ErrorLabel mt={2} hasError={Boolean(error && touched)}> <ErrorLabel mt={2} hasError={Boolean(error && touched)}>
{error} {error}

View File

@ -1,5 +1,7 @@
import { import {
Button, Col, ManagedTextInputField as Input, Button,
Col,
ManagedTextInputField as Input,
Row Row
} from '@tlon/indigo-react'; } from '@tlon/indigo-react';
import { Form, Formik, FormikHelpers } from 'formik'; import { Form, Formik, FormikHelpers } from 'formik';
@ -31,7 +33,8 @@ export interface PostFormSchema {
} }
export function PostForm(props: PostFormProps) { export function PostForm(props: PostFormProps) {
const { initial, onSubmit, submitLabel, loadingText, cancel, history } = props; const { initial, onSubmit, submitLabel, loadingText, cancel, history } =
props;
return ( return (
<Col width="100%" height="100%" p={[2, 4]}> <Col width="100%" height="100%" p={[2, 4]}>
@ -40,9 +43,23 @@ export function PostForm(props: PostFormProps) {
initialValues={initial} initialValues={initial}
onSubmit={onSubmit} onSubmit={onSubmit}
> >
{({ isSubmitting }) => (
<Form style={{ display: 'contents' }}> <Form style={{ display: 'contents' }}>
<Row flexShrink={0} flexDirection={['column-reverse', 'row']} mb={4} gapX={4} justifyContent='space-between'> <Row
<Input maxWidth='40rem' width='100%' flexShrink={[0, 1]} placeholder="Post Title" id="title" /> flexShrink={0}
flexDirection={['column-reverse', 'row']}
mb={4}
gapX={4}
justifyContent="space-between"
>
<Input
maxWidth="40rem"
width="100%"
flexShrink={[0, 1]}
placeholder="Post Title"
id="title"
disabled={isSubmitting}
/>
<Row flexDirection={['column', 'row']} mb={[4, 0]}> <Row flexDirection={['column', 'row']} mb={[4, 0]}>
<AsyncButton <AsyncButton
ml={[0, 2]} ml={[0, 2]}
@ -52,18 +69,23 @@ export function PostForm(props: PostFormProps) {
> >
{submitLabel} {submitLabel}
</AsyncButton> </AsyncButton>
{cancel && <Button {cancel && (
<Button
ml={[0, 2]} ml={[0, 2]}
mt={[2, 0]} mt={[2, 0]}
onClick={() => { onClick={() => {
history.goBack(); history.goBack();
}} }}
type="button" type="button"
>Cancel</Button>} >
Cancel
</Button>
)}
</Row> </Row>
</Row> </Row>
<MarkdownField flexGrow={1} id="body" /> <MarkdownField flexGrow={1} id="body" disabled={isSubmitting} />
</Form> </Form>
)}
</Formik> </Formik>
</Col> </Col>
); );

View File

@ -3,7 +3,7 @@ import moment from 'moment';
import React, { ReactElement, ReactNode } from 'react'; import React, { ReactElement, ReactNode } from 'react';
import { Sigil } from '~/logic/lib/sigil'; import { Sigil } from '~/logic/lib/sigil';
import { useCopy } from '~/logic/lib/useCopy'; import { useCopy } from '~/logic/lib/useCopy';
import { cite, uxToHex } from '~/logic/lib/util'; import { cite, deSig, uxToHex } from '~/logic/lib/util';
import { useContact } from '~/logic/state/contact'; import { useContact } from '~/logic/state/contact';
import { useDark } from '~/logic/state/join'; import { useDark } from '~/logic/state/join';
import useSettingsState, { selectCalmState, useShowNickname } from '~/logic/state/settings'; import useSettingsState, { selectCalmState, useShowNickname } from '~/logic/state/settings';
@ -52,7 +52,7 @@ function Author(props: AuthorProps & PropFunc<typeof Box>): ReactElement {
const { hideAvatars } = useSettingsState(selectCalmState); const { hideAvatars } = useSettingsState(selectCalmState);
const name = showNickname && contact ? contact.nickname : cite(ship); const name = showNickname && contact ? contact.nickname : cite(ship);
const stamp = moment(date); const stamp = moment(date);
const { copyDisplay, doCopy } = useCopy(`~${ship}`, name); const { copyDisplay, doCopy } = useCopy(`~${deSig(ship)}`, name);
const sigil = fullNotIcon ? ( const sigil = fullNotIcon ? (
<Sigil ship={ship} size={size} color={color} padding={sigilPadding} /> <Sigil ship={ship} size={size} color={color} padding={sigilPadding} />

View File

@ -28,7 +28,7 @@ import { Link } from 'react-router-dom';
import { AppPermalink, referenceToPermalink } from '~/logic/lib/permalinks'; import { AppPermalink, referenceToPermalink } from '~/logic/lib/permalinks';
import useMetadataState from '~/logic/state/metadata'; import useMetadataState from '~/logic/state/metadata';
import { RemoteContentWrapper } from './wrapper'; import { RemoteContentWrapper } from './wrapper';
import { useEmbed } from '~/logic/state/embed'; import { Suspender } from '~/logic/lib/suspend';
import { IS_SAFARI } from '~/logic/lib/platform'; import { IS_SAFARI } from '~/logic/lib/platform';
import useDocketState, { useTreaty } from '~/logic/state/docket'; import useDocketState, { useTreaty } from '~/logic/state/docket';
import { AppTile } from '~/views/apps/permalinks/embed'; import { AppTile } from '~/views/apps/permalinks/embed';
@ -97,6 +97,7 @@ export function RemoteContentImageEmbed(
objectFit="cover" objectFit="cover"
borderRadius={2} borderRadius={2}
onError={onError} onError={onError}
style={{ imageRendering: '-webkit-optimize-contrast' }}
{...props} {...props}
/> />
</Box> </Box>
@ -319,6 +320,7 @@ type RemoteContentOembedProps = {
renderUrl?: boolean; renderUrl?: boolean;
thumbnail?: boolean; thumbnail?: boolean;
tall?: boolean; tall?: boolean;
oembed: Suspender<any>;
} & RemoteContentEmbedProps & } & RemoteContentEmbedProps &
PropFunc<typeof Box>; PropFunc<typeof Box>;
@ -332,10 +334,9 @@ export const RemoteContentOembed = React.forwardRef<
HTMLDivElement, HTMLDivElement,
RemoteContentOembedProps RemoteContentOembedProps
>((props, ref) => { >((props, ref) => {
const { url, renderUrl = false, thumbnail = false, ...rest } = props; const { url, oembed, renderUrl = false, thumbnail = false, ...rest } = props;
const oembed = useEmbed(url);
const embed = oembed.read(); const embed = oembed.read();
const fallbackError = new Error('fallback');
const [aspect, width, height] = useMemo(() => { const [aspect, width, height] = useMemo(() => {
if(!('height' in embed && typeof embed.height === 'number' if(!('height' in embed && typeof embed.height === 'number'
@ -373,11 +374,9 @@ export const RemoteContentOembed = React.forwardRef<
dangerouslySetInnerHTML={{ __html: embed.html }} dangerouslySetInnerHTML={{ __html: embed.html }}
></EmbedBox> ></EmbedBox>
</EmbedContainer> </EmbedContainer>
) : renderUrl ? ( ) : (
<RemoteContentEmbedFallback url={url} /> <RemoteContentEmbedFallback url={url} />
) : (() => { )
throw fallbackError;
})()
} }
</Col> </Col>
); );

View File

@ -1,12 +1,17 @@
import { hasProvider } from 'oembed-parser'; import {
Box
} from '@tlon/indigo-react';
import React from 'react'; import React from 'react';
import useSettingsState from '~/logic/state/settings'; import useSettingsState from '~/logic/state/settings';
import { import {
RemoteContentAudioEmbed, RemoteContentAudioEmbed,
RemoteContentImageEmbed, RemoteContentImageEmbed,
RemoteContentOembed, RemoteContentOembed,
RemoteContentVideoEmbed RemoteContentVideoEmbed,
RemoteContentEmbedFallback
} from './embed'; } from './embed';
import { useEmbed } from '~/logic/state/embed';
import { Suspender } from '~/logic/lib/suspend';
import { TruncatedText } from '~/views/components/TruncatedText'; import { TruncatedText } from '~/views/components/TruncatedText';
import { RemoteContentWrapper } from './wrapper'; import { RemoteContentWrapper } from './wrapper';
import AsyncFallback from '../AsyncFallback'; import AsyncFallback from '../AsyncFallback';
@ -43,8 +48,34 @@ export const IMAGE_REGEX = new RegExp(
export const AUDIO_REGEX = new RegExp(/(\.mp3|\.wav|\.ogg|\.m4a)$/i); export const AUDIO_REGEX = new RegExp(/(\.mp3|\.wav|\.ogg|\.m4a)$/i);
export const VIDEO_REGEX = new RegExp(/(\.mov|\.mp4|\.ogv)$/i); export const VIDEO_REGEX = new RegExp(/(\.mov|\.mp4|\.ogv)$/i);
// This is used to prevent our oembed parser from
// trying to embed facebook/instagram links, which require an API key
const isFacebookGraphDependent = (url: string) => {
const caseDesensitizedURL = url.toLowerCase()
return (caseDesensitizedURL.includes('facebook.com') || caseDesensitizedURL.includes('instagram.com'))
}
export const validOembedCheck = (embed: Suspender<any>, url: string) => {
if (!isFacebookGraphDependent(url)) {
if (!embed.read().hasOwnProperty("error")) {
return true
}
}
return false
}
export const RemoteContent = (props: RemoteContentProps) => {
const {url, ...rest} = props
return(
<AsyncFallback fallback={<RemoteContentEmbedFallback url={url} />}>
<RemoteContentInner url={url} {...rest}/>
</AsyncFallback>
)
}
const emptyRef = () => {}; const emptyRef = () => {};
export function RemoteContent(props: RemoteContentProps) { function RemoteContentInner(props: RemoteContentProps) {
const { const {
url, url,
embedRef = emptyRef, embedRef = emptyRef,
@ -57,45 +88,51 @@ export function RemoteContent(props: RemoteContentProps) {
const isImage = IMAGE_REGEX.test(url); const isImage = IMAGE_REGEX.test(url);
const isAudio = AUDIO_REGEX.test(url); const isAudio = AUDIO_REGEX.test(url);
const isVideo = VIDEO_REGEX.test(url); const isVideo = VIDEO_REGEX.test(url);
const isOembed = hasProvider(url); const oembed = useEmbed(url);
const isOembed = validOembedCheck(oembed, url);
const wrapperProps = { const wrapperProps = {
url, url,
tall, tall,
embedOnly: !renderUrl || tall embedOnly: !renderUrl || tall
}; };
const fallback = !renderUrl ? null : ( const fallback = null;
<RemoteContentWrapper {...wrapperProps}>
<TruncatedText>{url}</TruncatedText>
</RemoteContentWrapper>
);
if (isImage && remoteContentPolicy.imageShown) { if (isImage && remoteContentPolicy.imageShown) {
return ( return (
<Box mt={1} mb={2} flexShrink={0}>
<RemoteContentWrapper {...wrapperProps} noOp={transcluded} replaced> <RemoteContentWrapper {...wrapperProps} noOp={transcluded} replaced>
<RemoteContentImageEmbed url={url} /> <RemoteContentImageEmbed url={url} stretch={tall} />
</RemoteContentWrapper> </RemoteContentWrapper>
</Box>
); );
} else if (isAudio && remoteContentPolicy.audioShown) { } else if (isAudio && remoteContentPolicy.audioShown) {
return ( return (
<Box mt={1} mb={2} flexShrink={0}>
<RemoteContentWrapper {...wrapperProps}> <RemoteContentWrapper {...wrapperProps}>
<RemoteContentAudioEmbed url={url} /> <RemoteContentAudioEmbed url={url} />
</RemoteContentWrapper> </RemoteContentWrapper>
</Box>
); );
} else if (isVideo && remoteContentPolicy.videoShown) { } else if (isVideo && remoteContentPolicy.videoShown) {
return ( return (
<Box mt={1} mb={2} flexShrink={0}>
<RemoteContentWrapper <RemoteContentWrapper
{...wrapperProps} {...wrapperProps}
detail={<RemoteContentVideoEmbed url={url} />} detail={<RemoteContentVideoEmbed url={url} />}
> >
<TruncatedText>{url}</TruncatedText> <TruncatedText>{url}</TruncatedText>
</RemoteContentWrapper> </RemoteContentWrapper>
</Box>
); );
} else if (isOembed && remoteContentPolicy.oembedShown) { } else if (isOembed && remoteContentPolicy.oembedShown) {
return ( return (
<Box mt={1} mb={2} flexShrink={0}>
<AsyncFallback fallback={fallback}> <AsyncFallback fallback={fallback}>
<RemoteContentOembed ref={embedRef} url={url} renderUrl={renderUrl} /> <RemoteContentOembed ref={embedRef} url={url} renderUrl={renderUrl} oembed={oembed} />
</AsyncFallback> </AsyncFallback>
</Box>
); );
} }
return fallback; return fallback;

View File

@ -2,26 +2,12 @@ import { Anchor, Text } from '@tlon/indigo-react';
import { Contact, Group } from '@urbit/api'; import { Contact, Group } from '@urbit/api';
import React from 'react'; import React from 'react';
import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown'; import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown';
import RemarkDisableTokenizers from 'remark-disable-tokenizers';
import { isValidPatp } from 'urbit-ob'; import { isValidPatp } from 'urbit-ob';
import { deSig } from '~/logic/lib/util'; import { deSig } from '~/logic/lib/util';
import { PermalinkEmbed } from '~/views/apps/permalinks/embed'; import { PermalinkEmbed } from '~/views/apps/permalinks/embed';
import { Mention } from '~/views/components/MentionText'; import { Mention } from '~/views/components/MentionText';
import RemoteContent from '~/views/components/RemoteContent'; import RemoteContent from '~/views/components/RemoteContent';
const DISABLED_BLOCK_TOKENS = [
'indentedCode',
'atxHeading',
'thematicBreak',
'list',
'setextHeading',
'html',
'definition',
'table'
];
const DISABLED_INLINE_TOKENS = [];
type RichTextProps = ReactMarkdownProps & { type RichTextProps = ReactMarkdownProps & {
disableRemoteContent?: boolean; disableRemoteContent?: boolean;
contact?: Contact; contact?: Contact;
@ -110,10 +96,6 @@ const RichText = React.memo(({ disableRemoteContent = false, ...props }: RichTex
return <Text display={props.inline ? 'inline' : 'block'} mb={2} {...props}>{paraProps.children}</Text>; return <Text display={props.inline ? 'inline' : 'block'} mb={2} {...props}>{paraProps.children}</Text>;
} }
}} }}
plugins={[[
RemarkDisableTokenizers,
{ block: DISABLED_BLOCK_TOKENS, inline: DISABLED_INLINE_TOKENS }
]]}
/> />
)); ));

View File

@ -74,7 +74,7 @@ export function GraphPermissions(props: GraphPermissionsProps) {
const writers = _.get( const writers = _.get(
group?.tags, group?.tags,
['graph', association.resource, 'writers'], ['graph', association.resource, 'writers'],
new Set() []
); );
let [, , hostShip] = association.resource.split('/'); let [, , hostShip] = association.resource.split('/');
@ -91,7 +91,7 @@ export function GraphPermissions(props: GraphPermissionsProps) {
const initialValues = { const initialValues = {
writePerms, writePerms,
writers: Array.from(writers) writers: [...writers]
.filter(x => x !== hostShip), .filter(x => x !== hostShip),
readerComments: association.metadata.vip === 'reader-comments' readerComments: association.metadata.vip === 'reader-comments'
}; };
@ -104,7 +104,7 @@ export function GraphPermissions(props: GraphPermissionsProps) {
resource: association.resource, resource: association.resource,
tag: 'writers' tag: 'writers'
}; };
const allWriters = Array.from(writers).map(w => `~${w}`); const allWriters = [...writers].map(w => `~${w}`);
if (values.readerComments !== readerComments) { if (values.readerComments !== readerComments) {
await airlock.poke(metadataEdit(association, { await airlock.poke(metadataEdit(association, {
vip: values.readerComments ? 'reader-comments' : '' vip: values.readerComments ? 'reader-comments' : ''
@ -170,7 +170,7 @@ export function GraphPermissions(props: GraphPermissionsProps) {
<Col> <Col>
<Label mb={2}>Permissions Summary</Label> <Label mb={2}>Permissions Summary</Label>
<PermissionsSummary <PermissionsSummary
writersSize={writers.size} writersSize={writers.length}
vip={association.metadata.vip} vip={association.metadata.vip}
/> />
</Col> </Col>

View File

@ -34,7 +34,11 @@ interface GraphMentionNode {
ship: string; ship: string;
} }
const addEmphasisToMention = (contents: Content[], content: Content, index: number) => { const addEmphasisToMention = (
contents: Content[],
content: Content,
index: number
) => {
const prevContent = contents[index - 1]; const prevContent = contents[index - 1];
const nextContent = contents[index + 1]; const nextContent = contents[index + 1];
@ -53,7 +57,7 @@ const addEmphasisToMention = (contents: Content[], content: Content, index: numb
nextContent !== undefined && nextContent !== undefined &&
'mention' in nextContent 'mention' in nextContent
) { ) {
if (content.text.charAt((content.text.length - 2)) === '*') { if (content.text.charAt(content.text.length - 2) === '*') {
return { text: content.text.slice(0, content.text.length - 2) }; return { text: content.text.slice(0, content.text.length - 2) };
} }
return { text: content.text.slice(0, content.text.length - 1) }; return { text: content.text.slice(0, content.text.length - 1) };
@ -116,9 +120,9 @@ const codeToMdAst = (content: CodeContent) => {
}; };
}; };
const contentToMdAst = (tall: boolean) => ( const contentToMdAst =
content: Content (tall: boolean) =>
): [StitchMode, any] => { (content: Content): [StitchMode, any] => {
if ('text' in content) { if ('text' in content) {
if (content.text.toString().trim().length === 0) { if (content.text.toString().trim().length === 0) {
return [ return [
@ -146,14 +150,23 @@ const contentToMdAst = (tall: boolean) => (
} }
]; ];
} else if ('url' in content) { } else if ('url' in content) {
const images = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];
return [ return [
'block', 'inline',
{ {
type: 'root', type: 'root',
children: [ children: [
{ {
type: 'graph-url', type: 'link',
url: content.url url: content.url,
children: [
{
type: 'text',
value: !images.some(i => content.url.includes(i))
? content.url
: ''
}
]
} }
] ]
} }
@ -186,8 +199,20 @@ function stitchInline(a: any, b: any) {
if (!a?.children) { if (!a?.children) {
throw new Error('Bad stitchInline call: missing root'); throw new Error('Bad stitchInline call: missing root');
} }
const lastParaIdx = a.children.length - 1; const lastParaIdx = a.children.length - 1;
const last = a.children[lastParaIdx]; const last = a.children[lastParaIdx];
// wrap bare link in list-item inside a p node
// for better typography consistency
if (last?.type === 'listItem') {
if (last?.children.length === 0) {
last.children.push({
type: 'paragraph',
children: []
});
}
}
if (last?.children) { if (last?.children) {
const ros = { const ros = {
...a, ...a,
@ -217,9 +242,14 @@ function getChildren<T extends unknown>(node: T): AstContent[] {
} }
export function asParent<T extends BlockContent>(node: T): Parent | undefined { export function asParent<T extends BlockContent>(node: T): Parent | undefined {
return ['paragraph', 'heading', 'list', 'listItem', 'table'].includes( return [
node.type 'paragraph',
) 'heading',
'list',
'listItem',
'table',
'blockquote'
].includes(node.type)
? (node as Parent) ? (node as Parent)
: undefined; : undefined;
} }
@ -241,6 +271,7 @@ function stitchMerge(a: Root, b: Root) {
children: [...aChildren.slice(0, -1), mergedPara, ...bChildren.slice(1)] children: [...aChildren.slice(0, -1), mergedPara, ...bChildren.slice(1)]
}; };
} }
return { ...a, children: [...aChildren, ...bChildren] }; return { ...a, children: [...aChildren, ...bChildren] };
} }
@ -256,10 +287,10 @@ function stitchInlineAfterBlock(a: Root, b: GraphMentionNode[]) {
} }
function stitchAsts(asts: [StitchMode, GraphAstNode][]) { function stitchAsts(asts: [StitchMode, GraphAstNode][]) {
return _.reduce( const t = _.reduce(
asts, asts,
([prevMode, ast], [mode, val]): [StitchMode, GraphAstNode] => { ([prevMode, ast], [mode, val]): [StitchMode, GraphAstNode] => {
if (prevMode === 'block') { if (prevMode === 'block' || prevMode === 'inline') {
if (mode === 'inline') { if (mode === 'inline') {
return [mode, stitchInlineAfterBlock(ast, val?.children ?? [])]; return [mode, stitchInlineAfterBlock(ast, val?.children ?? [])];
} }
@ -283,6 +314,46 @@ function stitchAsts(asts: [StitchMode, GraphAstNode][]) {
}, },
['block', { type: 'root', children: [] }] as [StitchMode, GraphAstNode] ['block', { type: 'root', children: [] }] as [StitchMode, GraphAstNode]
); );
t[1].children.map((c, idx) => {
const links = [];
function addRichEmbedURL(nodes) {
if (nodes?.children) {
nodes.children.filter(k => {
if (k.type === 'link') {
links.push({
type: 'root',
children: [
{
type: 'graph-url',
url: k.url
}
]
});
} else if (k?.children) {
k.children.filter(o => {
if (o.type === 'link') {
links.push({
type: 'root',
children: [
{
type: 'graph-url',
url: o.url
}
]
});
}
});
}
});
nodes.children.push(...links);
}
}
addRichEmbedURL(c);
});
return t;
} }
const header = ({ children, depth, ...rest }) => { const header = ({ children, depth, ...rest }) => {
const level = depth; const level = depth;
@ -392,7 +463,7 @@ const renderers = {
); );
return tall ? <Box mb={2}>{inner}</Box> : inner; return tall ? <Box mb={2}>{inner}</Box> : inner;
}, },
link: (props) => { link: props => {
return ( return (
<Anchor <Anchor
display="inline" display="inline"
@ -408,9 +479,13 @@ const renderers = {
); );
}, },
list: ({ depth, ordered, children }) => { list: ({ depth, ordered, children }) => {
return ordered ? <Ol>{children}</Ol> : <Ul>{children}</Ul>; return ordered ? (
<Ol fontSize="1">{children}</Ol>
) : (
<Ul fontSize="1">{children}</Ul>
);
}, },
'graph-mention': (obj) => { 'graph-mention': obj => {
return <Mention ship={obj.ship} emphasis={obj.emphasis} />; return <Mention ship={obj.ship} emphasis={obj.emphasis} />;
}, },
image: ({ url, tall }) => ( image: ({ url, tall }) => (
@ -419,19 +494,13 @@ const renderers = {
</Box> </Box>
), ),
'graph-url': ({ url, tall }) => ( 'graph-url': ({ url, tall }) => (
<Box mt={1} mb={2} flexShrink={0}>
<RemoteContent key={url} url={url} tall={tall} /> <RemoteContent key={url} url={url} tall={tall} />
</Box>
), ),
'graph-reference': ({ reference, transcluded }) => { 'graph-reference': ({ reference, transcluded }) => {
const { link } = referenceToPermalink({ reference }); const { link } = referenceToPermalink({ reference });
return ( return (
<Box my={2} flexShrink={0}> <Box my={2} flexShrink={0}>
<PermalinkEmbed <PermalinkEmbed link={link} transcluded={transcluded} showOurContact />
link={link}
transcluded={transcluded}
showOurContact
/>
</Box> </Box>
); );
}, },
@ -499,19 +568,13 @@ export type GraphContentProps = PropFunc<typeof Box> & {
showOurContact: boolean; showOurContact: boolean;
}; };
export const GraphContent = React.memo(( export const GraphContent = React.memo((props: GraphContentProps) => {
props: GraphContentProps const { contents, tall = false, transcluded = 0, ...rest } = props;
) => {
const {
contents,
tall = false,
transcluded = 0,
...rest
} = props;
const [, ast] = stitchAsts( const [, ast] = stitchAsts(
contents contents
.map((content, index) => addEmphasisToMention(contents, content, index)) .map((content, index) => addEmphasisToMention(contents, content, index))
.map(contentToMdAst(tall))); .map(contentToMdAst(tall))
);
return ( return (
<Box {...rest}> <Box {...rest}>
<Graphdown transcluded={transcluded} ast={ast} tall={tall} /> <Graphdown transcluded={transcluded} ast={ast} tall={tall} />

View File

@ -4,125 +4,123 @@
* critical change is that blockquotes require a newline to be continued, see * critical change is that blockquotes require a newline to be continued, see
* the `if(!prefixed) conditional * the `if(!prefixed) conditional
*/ */
'use strict' "use strict";
var trim = require('trim') var trim = require("trim");
var interrupt = require('remark-parse/lib/util/interrupt')
module.exports = blockquote module.exports = blockquote;
var lineFeed = '\n' var lineFeed = "\n";
var tab = '\t' var tab = "\t";
var space = ' ' var space = " ";
var greaterThan = '>' var greaterThan = ">";
function blockquote(eat, value, silent) { function blockquote(eat, value, silent) {
var self = this var self = this;
var offsets = self.offset var offsets = self.offset;
var tokenizers = self.blockTokenizers var tokenizers = self.blockTokenizers;
var interruptors = self.interruptBlockquote var interruptors = self.interruptBlockquote;
var now = eat.now() var now = eat.now();
var currentLine = now.line var currentLine = now.line;
var length = value.length var length = value.length;
var values = [] var values = [];
var contents = [] var contents = [];
var indents = [] var indents = [];
var add var add;
var index = 0 var index = 0;
var character var character;
var rest var rest;
var nextIndex var nextIndex;
var content var content;
var line var line;
var startIndex var startIndex;
var prefixed var prefixed;
var exit var exit;
while (index < length) { while (index < length) {
character = value.charAt(index) character = value.charAt(index);
if (character !== space && character !== tab) { if (character !== space && character !== tab) {
break break;
} }
index++ index++;
} }
if (value.charAt(index) !== greaterThan) { if (value.charAt(index) !== greaterThan) {
return return;
} }
if (silent) { if (silent) {
return true return true;
} }
index = 0 index = 0;
while (index < length) { while (index < length) {
nextIndex = value.indexOf(lineFeed, index) nextIndex = value.indexOf(lineFeed, index);
startIndex = index startIndex = index;
prefixed = false prefixed = false;
if (nextIndex === -1) { if (nextIndex === -1) {
nextIndex = length nextIndex = length;
} }
while (index < length) { while (index < length) {
character = value.charAt(index) character = value.charAt(index);
if (character !== space && character !== tab) { if (character !== space && character !== tab) {
break break;
} }
index++ index++;
} }
if (value.charAt(index) === greaterThan) { if (value.charAt(index) === greaterThan) {
index++ index++;
prefixed = true prefixed = true;
if (value.charAt(index) === space) { if (value.charAt(index) === space) {
index++ index++;
} }
} else { } else {
index = startIndex index = startIndex;
} }
content = value.slice(index, nextIndex) content = value.slice(index, nextIndex);
if (!prefixed && !trim(content)) { if (!prefixed && !trim(content)) {
index = startIndex index = startIndex;
break break;
} }
if (!prefixed) { if (!prefixed) {
break; break;
} }
line = startIndex === index ? content : value.slice(startIndex, nextIndex) line = startIndex === index ? content : value.slice(startIndex, nextIndex);
indents.push(index - startIndex) indents.push(index - startIndex);
values.push(line) values.push(line);
contents.push(content) contents.push(content);
index = nextIndex + 1 index = nextIndex + 1;
} }
const trailingNewline = value.charAt(nextIndex) === '\n'; const trailingNewline = value.charAt(nextIndex) === "\n";
index = -1 index = -1;
length = indents.length length = indents.length;
add = eat(values.join(lineFeed)) add = eat(values.join(lineFeed));
while (++index < length) { while (++index < length) {
offsets[currentLine] = (offsets[currentLine] || 0) + indents[index] offsets[currentLine] = (offsets[currentLine] || 0) + indents[index];
currentLine++ currentLine++;
} }
exit = self.enterBlock() exit = self.enterBlock();
contents = self.tokenizeBlock(contents.join(lineFeed), now) contents = self.tokenizeBlock(contents.join(lineFeed), now);
console.log(values); exit();
exit()
const added = add({type: 'blockquote', children: contents}) const added = add({ type: "blockquote", children: contents });
return trailingNewline ? add({ type: 'paragraph', children: [] }) : added; return trailingNewline ? add({ type: "paragraph", children: [] }) : added;
} }

View File

@ -8,7 +8,7 @@ import {
} from 'react-router-dom'; } from 'react-router-dom';
import { useShortcut } from '~/logic/state/settings'; import { useShortcut } from '~/logic/state/settings';
import { useLocalStorageState } from '~/logic/lib/useLocalStorageState'; import { useLocalStorageState } from '~/logic/lib/useLocalStorageState';
import { getGroupFromWorkspace } from '~/logic/lib/workspace'; import { getGroupFromWorkspace, getTitleFromWorkspace } from '~/logic/lib/workspace';
import useGroupState from '~/logic/state/group'; import useGroupState from '~/logic/state/group';
import useHarkState from '~/logic/state/hark'; import useHarkState from '~/logic/state/hark';
import useMetadataState from '~/logic/state/metadata'; import useMetadataState from '~/logic/state/metadata';
@ -22,7 +22,7 @@ import { Skeleton } from './Skeleton';
import { EmptyGroupHome } from './Home/EmptyGroupHome'; import { EmptyGroupHome } from './Home/EmptyGroupHome';
import { Join } from './Join/Join'; import { Join } from './Join/Join';
import { Resource } from './Resource'; import { Resource } from './Resource';
import { DmResource } from '~/views/apps/chat/DmResource'; import { DmResource, DmHelmet } from '~/views/apps/chat/DmResource';
import { UnjoinedResource } from '~/views/components/UnjoinedResource'; import { UnjoinedResource } from '~/views/components/UnjoinedResource';
import { NewChannel } from './NewChannel'; import { NewChannel } from './NewChannel';
import { GroupHome } from './Home/GroupHome'; import { GroupHome } from './Home/GroupHome';
@ -126,6 +126,8 @@ export function GroupsPane(props: GroupsPaneProps) {
const { ship } = match.params as Record<string, string>; const { ship } = match.params as Record<string, string>;
return ( return (
<>
<DmHelmet ship={ship} />
<Skeleton <Skeleton
mobileHide mobileHide
recentGroups={recentGroups} recentGroups={recentGroups}
@ -135,7 +137,7 @@ export function GroupsPane(props: GroupsPaneProps) {
> <DmResource ship={ship} /> > <DmResource ship={ship} />
</Skeleton> </Skeleton>
</>
); );
}} }}
/> />
@ -180,7 +182,7 @@ export function GroupsPane(props: GroupsPaneProps) {
const appPath = `/ship/${host}/${name}`; const appPath = `/ship/${host}/${name}`;
const association = associations.graph[appPath]; const association = associations.graph[appPath];
const resourceUrl = `${baseUrl}/join/${app}${appPath}`; const resourceUrl = `${baseUrl}/join/${app}${appPath}`;
let title = groupAssociation?.metadata?.title ?? 'Groups'; let title = getTitleFromWorkspace(associations, workspace);
if (!association) { if (!association) {
return <Loading />; return <Loading />;
@ -252,7 +254,7 @@ export function GroupsPane(props: GroupsPaneProps) {
render={(routeProps) => { render={(routeProps) => {
const shouldHideSidebar = const shouldHideSidebar =
routeProps.location.pathname.includes('/feed'); routeProps.location.pathname.includes('/feed');
const title = groupAssociation?.metadata?.title ?? 'Groups'; const title = getTitleFromWorkspace(associations, workspace);
return ( return (
<> <>
<Helmet defer={false}> <Helmet defer={false}>

View File

@ -352,7 +352,7 @@ function Participant(props: {
</Link> </Link>
</Action> </Action>
<Action bg="transparent"> <Action bg="transparent">
<Link to={`/~landscape/dm/${contact.patp}`}> <Link to={`/~landscape/messages/dm/~${contact.patp}`}>
<Text color="green">Send Message</Text> <Text color="green">Send Message</Text>
</Link> </Link>
</Action> </Action>

View File

@ -679,20 +679,19 @@
=/ update-log =/ update-log
(~(get by update-logs) [ship term]) (~(get by update-logs) [ship term])
:- ~ :- ~ :- %noun :- ~ :- ~ :- %noun
!>
?+ t.t.t.t.path (on-peek:def path) ?+ t.t.t.t.path (on-peek:def path)
~ ~
^- update-log:store !> ^- update-log:store
?~(update-log *update-log:store u.update-log) ?~(update-log *update-log:store u.update-log)
:: ::
[%latest ~] [%latest ~]
^- (unit time) !> ^- (unit time)
%+ biff update-log %+ biff update-log
|= =update-log:store |= =update-log:store
(bind (pry:orm-log:store update-log) head) (bind (pry:orm-log:store update-log) head)
:: ::
[%subset @ @ ~] [%subset @ @ ~]
^- update-log:store !> ^- update-log:store
?~ update-log *update-log:store ?~ update-log *update-log:store
=* start i.t.t.t.t.t.path =* start i.t.t.t.t.t.path
=* end i.t.t.t.t.t.t.path =* end i.t.t.t.t.t.t.path

View File

@ -190,6 +190,11 @@
|% |%
++ pull-action pull-hook-action+!>([%add ship rid]) ++ pull-action pull-hook-action+!>([%add ship rid])
:: ::
++ listen-hark
|= gr=resource
%+ poke-our:pass:io %hark-graph-hook
hark-graph-hook-action+!>([%listen gr /])
::
++ watch-md (watch-our:(jn-pass-io /md) %metadata-store /updates) ++ watch-md (watch-our:(jn-pass-io /md) %metadata-store /updates)
++ watch-groups (watch-our:(jn-pass-io /groups) %group-store /groups) ++ watch-groups (watch-our:(jn-pass-io /groups) %group-store /groups)
++ watch-md-nacks (watch-our:(jn-pass-io /md-nacks) %metadata-pull-hook /nack) ++ watch-md-nacks (watch-our:(jn-pass-io /md-nacks) %metadata-pull-hook /nack)
@ -436,6 +441,9 @@
=? jn-core |(hidden autojoin.request) =? jn-core |(hidden autojoin.request)
%- emit-many %- emit-many
(turn graphs pull-gra:pass) (turn graphs pull-gra:pass)
=? jn-core hidden
%- emit-many
(turn graphs listen-hark:pass)
jn-core jn-core
:: ::
++ feed-rid ++ feed-rid

View File

@ -1,10 +1,10 @@
:~ title+'Groups' :~ title+'Groups'
info+'A suite of applications to communicate on Urbit' info+'A suite of applications to communicate on Urbit'
color+0xee.5432 color+0xee.5432
glob-http+['https://bootstrap.urbit.org/glob-0v7.bmftr.90ktq.cma0h.da190.bs8b1.glob' 0v7.bmftr.90ktq.cma0h.da190.bs8b1] glob-http+['https://bootstrap.urbit.org/glob-0v7.2rpmd.966js.dt2sj.ggv4a.n15nq.glob' 0v7.2rpmd.966js.dt2sj.ggv4a.n15nq]
base+'landscape' base+'landscape'
version+[1 0 11] version+[1 1 0]
website+'https://tlon.io' website+'https://tlon.io'
license+'MIT' license+'MIT'
== ==

View File

@ -35,6 +35,8 @@
(poke-our %group-store group-update-0+!>([%add-members rid (sy our.bowl ~)])) (poke-our %group-store group-update-0+!>([%add-members rid (sy our.bowl ~)]))
;< ~ bind:m ;< ~ bind:m
(poke-our %group-push-hook push-hook-act) (poke-our %group-push-hook push-hook-act)
;< ~ bind:m
(poke-our %hark-graph-hook hark-graph-hook-action+!>([%listen rid /]))
(pure:m rid) (pure:m rid)
-- --
:: ::

View File

@ -38,4 +38,6 @@
(raw-poke-our %contact-pull-hook pull-hook-act) (raw-poke-our %contact-pull-hook pull-hook-act)
;< ~ bind:m ;< ~ bind:m
(raw-poke-our %group-store remove) (raw-poke-our %group-store remove)
;< ~ bind:m
(raw-poke-our %group-view group-view-action+!>([%done rid]))
(pure:m !>(~)) (pure:m !>(~))

View File

@ -22,3 +22,5 @@ export * as hood from './hood';
export * from './hood'; export * from './hood';
export * as docket from './docket'; export * as docket from './docket';
export * from './docket'; export * from './docket';
export * as term from './term';
export * from './term';

View File

@ -1,12 +1,12 @@
{ {
"name": "@urbit/api", "name": "@urbit/api",
"version": "2.1.0", "version": "2.1.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@urbit/api", "name": "@urbit/api",
"version": "2.1.0", "version": "2.1.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.16.0", "@babel/runtime": "^7.16.0",

View File

@ -8,8 +8,12 @@
"directory": "pkg/npm/api" "directory": "pkg/npm/api"
}, },
"type": "module", "type": "module",
"main": "dist/cjs/index.js", "main": "dist/cjs/index.cjs",
"module": "dist/esm/index.js", "module": "dist/esm/index.js",
"exports": {
"require": "./dist/cjs/index.cjs",
"import": "./dist/esm/index.js"
},
"jsdelivr": "dist/urbit-api.min.js", "jsdelivr": "dist/urbit-api.min.js",
"unpkg": "dist/urbit-api.min.js", "unpkg": "dist/urbit-api.min.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@ -60,13 +60,13 @@ export default [
], ],
output: [ output: [
{ {
dir: 'dist/esm', file: 'dist/esm/index.js',
format: 'esm', format: 'esm',
exports: 'named', exports: 'named',
sourcemap: true sourcemap: true,
}, },
{ {
dir: 'dist/cjs', file: 'dist/cjs/index.cjs',
format: 'cjs', format: 'cjs',
exports: 'named', exports: 'named',
sourcemap: true sourcemap: true

Some files were not shown because too many files have changed in this diff Show More