mavend: an unconfigured capability names the gap (V-479)
Netscan and the crawler both declined their own turn when the wiring was nil, and the question fell through to the search leg. "какие устройства в сети?" came back as a paragraph about routers in general, and a question about his own LAN went to an upstream engine — the personal boundary exists to stop exactly that. A URL he named came back answered as though he had not named it. Both now claim the turn once their own recogniser has matched, and say which capability is missing: net_off and page_off in the query family. TestQueryWebPassesWhenNotConfigured encoded the old decision, that announcing a configuration status is only for a capability that exists and failed. It is rewritten, not deleted: the gap is the answer now.
This commit is contained in:
@@ -367,9 +367,12 @@ func (h *reactiveHandler) queryNetwork(ctx context.Context, t *queryTurn) (strin
|
|||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
if h.netscan == nil {
|
if h.netscan == nil {
|
||||||
// Fall through, same as queryHome: an unconfigured scanner must not
|
// The recogniser already matched, so this is a question about HIS LAN
|
||||||
// swallow "сколько устройств в сети?" before recall has looked.
|
// and there is no scanner to answer it. Falling through sent it to the
|
||||||
return "", false
|
// search leg, which answered with a paragraph about routers in general
|
||||||
|
// and put his network question on an upstream engine (Vikunja #479).
|
||||||
|
// A missing capability names itself.
|
||||||
|
return phraser.Q(phraser.QueryNetOff, nil), true
|
||||||
}
|
}
|
||||||
return h.netscan.scanSummary(ctx)
|
return h.netscan.scanSummary(ctx)
|
||||||
}
|
}
|
||||||
@@ -524,12 +527,11 @@ func (h *reactiveHandler) queryWeb(ctx context.Context, t *queryTurn) (string, b
|
|||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
if h.crawler == nil {
|
if h.crawler == nil {
|
||||||
// Fall through. Reading pages is off unless configured, and on a daemon
|
// He named a URL, so the question is about that page and nothing else
|
||||||
// where it was never turned on the older behaviour is right: the model
|
// can answer it. The older comment here argued for falling through and
|
||||||
// answers the question as if the URL had not been said. Announcing a
|
// letting the model answer as if the URL had not been said; that is a
|
||||||
// configuration status is for a capability that exists and failed, not
|
// guess dressed as an answer (Vikunja #479).
|
||||||
// for one he never asked for.
|
return phraser.Q(phraser.QueryPageOff, nil), true
|
||||||
return "", false
|
|
||||||
}
|
}
|
||||||
ctxFetch, cancel := context.WithTimeout(ctx, 30*time.Second)
|
ctxFetch, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|||||||
@@ -125,13 +125,17 @@ func TestQueryWebPassesWithoutAURL(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A daemon where page reading was never turned on — the default — answers the
|
// A daemon where page reading was never turned on names the gap. He asked
|
||||||
// question the way it did before the capability existed. Claiming the turn to
|
// about one page, nothing else on the box can read it, and the old behaviour
|
||||||
// report a configuration status is for something that exists and failed.
|
// here was to answer as though the URL had not been said (Vikunja #479).
|
||||||
func TestQueryWebPassesWhenNotConfigured(t *testing.T) {
|
func TestQueryWebNamesTheGapWhenNotConfigured(t *testing.T) {
|
||||||
h := buildWebHandler(nil)
|
h := buildWebHandler(nil)
|
||||||
if reply, ok := askWeb(h, "посмотри https://example.org/page"); ok {
|
reply, ok := askWeb(h, "посмотри https://example.org/page")
|
||||||
t.Fatalf("an unconfigured crawler claimed the turn with %q", reply)
|
if !ok {
|
||||||
|
t.Fatal("an unconfigured crawler let the page question fall through")
|
||||||
|
}
|
||||||
|
if !phraser.IsQ(phraser.QueryPageOff, nil, reply) {
|
||||||
|
t.Errorf("got %q, want the gap named", reply)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
"github.com/kami/maven/internal/config"
|
"github.com/kami/maven/internal/config"
|
||||||
"github.com/kami/maven/internal/ipc"
|
"github.com/kami/maven/internal/ipc"
|
||||||
|
"github.com/kami/maven/internal/phraser"
|
||||||
|
"github.com/kami/maven/internal/router"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWireNetScanOffUnlessEnabled(t *testing.T) {
|
func TestWireNetScanOffUnlessEnabled(t *testing.T) {
|
||||||
@@ -169,3 +171,22 @@ func TestScanSummarySpeaksACountAndWritesTheAddresses(t *testing.T) {
|
|||||||
t.Errorf("a repeat question rescanned and rewrote the record (%d notes)", api.n)
|
t.Errorf("a repeat question rescanned and rewrote the record (%d notes)", api.n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An unconfigured scanner names the gap instead of declining the turn.
|
||||||
|
//
|
||||||
|
// Falling through sent "какие устройства в сети?" to the search leg, which
|
||||||
|
// answered with a paragraph about routers in general — and put a question about
|
||||||
|
// his own LAN on an upstream engine, which the personal boundary exists to
|
||||||
|
// prevent (Vikunja #479).
|
||||||
|
func TestQueryNetworkNamesTheGapWhenNotConfigured(t *testing.T) {
|
||||||
|
h := &reactiveHandler{}
|
||||||
|
reply, ok := h.queryNetwork(context.Background(), &queryTurn{
|
||||||
|
dec: router.Decision{Utterance: "какие устройства в сети?"},
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("an unconfigured scanner let the question fall through to search")
|
||||||
|
}
|
||||||
|
if !phraser.IsQ(phraser.QueryNetOff, nil, reply) {
|
||||||
|
t.Errorf("got %q, want the gap named", reply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ const (
|
|||||||
QueryWeatherOff = "weather_off"
|
QueryWeatherOff = "weather_off"
|
||||||
QueryWeatherWhere = "weather_nolocation"
|
QueryWeatherWhere = "weather_nolocation"
|
||||||
QueryNetEmpty = "net_empty"
|
QueryNetEmpty = "net_empty"
|
||||||
|
QueryNetOff = "net_off"
|
||||||
|
QueryPageOff = "page_off"
|
||||||
|
|
||||||
QueryFailPlan = "fail_plan"
|
QueryFailPlan = "fail_plan"
|
||||||
QueryFailNotes = "fail_notes"
|
QueryFailNotes = "fail_notes"
|
||||||
@@ -60,7 +62,7 @@ var queryKeys = []string{
|
|||||||
QueryUnknown, QueryOtherDay, QueryPersonalNone, QueryFactWhen, QueryFactValue,
|
QueryUnknown, QueryOtherDay, QueryPersonalNone, QueryFactWhen, QueryFactValue,
|
||||||
QueryFound, QueryPageText, QueryPageBlocked, QueryPageEmpty,
|
QueryFound, QueryPageText, QueryPageBlocked, QueryPageEmpty,
|
||||||
QueryFeedsOff, QueryFeedsNew, QueryFeedsEmpty, QueryFeedsTopic,
|
QueryFeedsOff, QueryFeedsNew, QueryFeedsEmpty, QueryFeedsTopic,
|
||||||
QueryWeatherNow, QueryWeatherOff, QueryWeatherWhere, QueryNetEmpty,
|
QueryWeatherNow, QueryWeatherOff, QueryWeatherWhere, QueryNetEmpty, QueryNetOff, QueryPageOff,
|
||||||
QueryFailPlan, QueryFailNotes, QueryFailFeeds, QueryFailCalendar,
|
QueryFailPlan, QueryFailNotes, QueryFailFeeds, QueryFailCalendar,
|
||||||
QueryFailWeather, QueryFailAnswer, QueryFailPage, QueryFailNetscan,
|
QueryFailWeather, QueryFailAnswer, QueryFailPage, QueryFailNetscan,
|
||||||
}
|
}
|
||||||
@@ -85,6 +87,8 @@ var queryFloor = say.RegisterFloor(map[string]string{
|
|||||||
QueryWeatherOff: "погода не настроена.",
|
QueryWeatherOff: "погода не настроена.",
|
||||||
QueryWeatherWhere: "не знаю, для какого города — задай voice.weather.default_location или назови город.",
|
QueryWeatherWhere: "не знаю, для какого города — задай voice.weather.default_location или назови город.",
|
||||||
QueryNetEmpty: "в сети никого не нашла{tail}.",
|
QueryNetEmpty: "в сети никого не нашла{tail}.",
|
||||||
|
QueryNetOff: "сканирование сети не настроено.",
|
||||||
|
QueryPageOff: "я не читаю страницы — это не настроено.",
|
||||||
|
|
||||||
QueryFailPlan: "не получилось собрать план.",
|
QueryFailPlan: "не получилось собрать план.",
|
||||||
QueryFailNotes: "не получилось посмотреть записи.",
|
QueryFailNotes: "не получилось посмотреть записи.",
|
||||||
|
|||||||
@@ -62,6 +62,14 @@
|
|||||||
"fixed": true,
|
"fixed": true,
|
||||||
"variants": ["не знаю, для какого города — задай voice.weather.default_location или назови город."]
|
"variants": ["не знаю, для какого города — задай voice.weather.default_location или назови город."]
|
||||||
},
|
},
|
||||||
|
"net_off": {
|
||||||
|
"fixed": true,
|
||||||
|
"variants": ["сканирование сети не настроено."]
|
||||||
|
},
|
||||||
|
"page_off": {
|
||||||
|
"fixed": true,
|
||||||
|
"variants": ["я не читаю страницы — это не настроено."]
|
||||||
|
},
|
||||||
"net_empty": {
|
"net_empty": {
|
||||||
"variants": ["в сети никого не нашла{tail}.", "никого в сети не видно{tail}."]
|
"variants": ["в сети никого не нашла{tail}.", "никого в сети не видно{tail}."]
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user